2024-12-28 20:38:00 +00:00
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
|
|
#include <vector>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <string>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <string>
|
|
|
|
#include <functional>
|
|
|
|
#include <variant>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <atomic>
|
|
|
|
#include <filesystem>
|
|
|
|
#include <memory>
|
|
|
|
#include <cstring>
|
|
|
|
#include <TessesFramework/TessesFramework.hpp>
|
|
|
|
#define TVM_MAJOR 1
|
|
|
|
#define TVM_MINOR 0
|
|
|
|
#define TVM_PATCH 0
|
|
|
|
#define TVM_BUILD 0
|
|
|
|
#define TVM_VERSIONSTAGE DevVersion
|
|
|
|
|
|
|
|
namespace Tesses::CrossLang {
|
|
|
|
|
|
|
|
std::string EscapeString(std::string text,bool quote);
|
|
|
|
|
|
|
|
enum TVMVersionStage : uint8_t
|
|
|
|
{
|
|
|
|
DevVersion=0,
|
|
|
|
AlphaVersion=1,
|
|
|
|
BetaVersion=2,
|
|
|
|
ProductionVersion=3
|
|
|
|
};
|
|
|
|
class TVMVersion
|
|
|
|
{
|
|
|
|
uint8_t major;
|
|
|
|
uint8_t minor;
|
|
|
|
uint8_t patch;
|
|
|
|
uint16_t build;
|
|
|
|
public:
|
|
|
|
uint8_t Major()
|
|
|
|
{
|
|
|
|
return major;
|
|
|
|
}
|
|
|
|
uint8_t Minor()
|
|
|
|
{
|
|
|
|
return minor;
|
|
|
|
}
|
|
|
|
uint8_t Patch()
|
|
|
|
{
|
|
|
|
return patch;
|
|
|
|
}
|
|
|
|
uint16_t Build()
|
|
|
|
{
|
|
|
|
return build >> 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
TVMVersionStage VersionStage()
|
|
|
|
{
|
|
|
|
return (TVMVersionStage)(build & 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetMajor(uint8_t major)
|
|
|
|
{
|
|
|
|
this->major=major;
|
|
|
|
}
|
|
|
|
void SetMinor(uint8_t minor)
|
|
|
|
{
|
|
|
|
this->minor=minor;
|
|
|
|
}
|
|
|
|
void SetPatch(uint8_t patch)
|
|
|
|
{
|
|
|
|
this->patch=patch;
|
|
|
|
}
|
|
|
|
void SetBuild(uint16_t build)
|
|
|
|
{
|
|
|
|
this->build = build;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetBuild(uint16_t build,TVMVersionStage version)
|
|
|
|
{
|
|
|
|
this->build = (build << 2) | version;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, TVMVersionStage ver)
|
|
|
|
{
|
|
|
|
this->SetMajor(major);
|
|
|
|
this->SetMinor(minor);
|
|
|
|
this->SetPatch(patch);
|
|
|
|
this->SetBuild(build,ver);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build)
|
|
|
|
{
|
|
|
|
this->SetMajor(major);
|
|
|
|
this->SetMinor(minor);
|
|
|
|
this->SetPatch(patch);
|
|
|
|
this->SetBuild(build);
|
|
|
|
}
|
|
|
|
void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t buildHigh, uint8_t buildLow)
|
|
|
|
{
|
|
|
|
this->SetVersion(major, minor, patch, buildHigh << 8 | buildLow);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetVersion(uint8_t* versionData)
|
|
|
|
{
|
|
|
|
this->SetVersion(versionData[0],versionData[1],versionData[2],versionData[3],versionData[4]);
|
|
|
|
}
|
|
|
|
void ToArray(uint8_t* versionData)
|
|
|
|
{
|
|
|
|
versionData[0] = major;
|
|
|
|
versionData[1] = minor;
|
|
|
|
versionData[2] = patch;
|
|
|
|
versionData[3] = build >> 8;
|
|
|
|
versionData[4] = build & 0xFF;
|
|
|
|
}
|
|
|
|
TVMVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, TVMVersionStage version)
|
|
|
|
{
|
|
|
|
this->SetVersion(major,minor,patch,build,version);
|
|
|
|
}
|
|
|
|
TVMVersion(uint8_t* versionData)
|
|
|
|
{
|
|
|
|
this->SetVersion(versionData);
|
|
|
|
}
|
|
|
|
TVMVersion()
|
|
|
|
{
|
|
|
|
this->major=1;
|
|
|
|
this->minor=0;
|
|
|
|
this->patch=0;
|
|
|
|
this->SetBuild(0, TVMVersionStage::DevVersion);
|
|
|
|
}
|
|
|
|
int CompareTo(TVMVersion& version)
|
|
|
|
{
|
|
|
|
if(this->major > version.major) return 1;
|
|
|
|
if(this->major < version.major) return -1;
|
|
|
|
if(this->minor > version.minor) return 1;
|
|
|
|
if(this->minor < version.minor) return -1;
|
|
|
|
if(this->patch > version.patch) return 1;
|
|
|
|
if(this->patch < version.patch) return -1;
|
|
|
|
if(this->build > version.build) return 1;
|
|
|
|
if(this->build < version.build) return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int CompareToRuntime()
|
|
|
|
{
|
|
|
|
TVMVersion version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
|
|
|
|
return CompareTo(version);
|
|
|
|
}
|
|
|
|
static bool TryParse(std::string versionStr, TVMVersion& version)
|
|
|
|
{
|
|
|
|
if(versionStr.empty()) return false;
|
|
|
|
size_t sep=versionStr.find_last_of('-');
|
|
|
|
|
|
|
|
std::string left = versionStr;
|
|
|
|
std::string right = "prod";
|
|
|
|
|
|
|
|
if(sep != std::string::npos)
|
|
|
|
{
|
|
|
|
left = versionStr.substr(0, sep);
|
|
|
|
right = versionStr.substr(sep+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(left.empty()) return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TVMVersionStage stage;
|
|
|
|
if(right == "dev")
|
|
|
|
stage = TVMVersionStage::DevVersion;
|
|
|
|
else if(right == "alpha")
|
|
|
|
stage = TVMVersionStage::AlphaVersion;
|
|
|
|
else if(right == "beta")
|
|
|
|
stage = TVMVersionStage::BetaVersion;
|
|
|
|
else if(right == "prod")
|
|
|
|
stage = TVMVersionStage::ProductionVersion;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
//1 0.0.0
|
|
|
|
sep=left.find_first_of('.');
|
|
|
|
|
|
|
|
if(sep != std::string::npos)
|
|
|
|
{
|
|
|
|
auto lStr = left.substr(0, sep);
|
|
|
|
|
|
|
|
right = left.substr(sep+1);
|
|
|
|
left = lStr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
version.SetMajor((uint8_t)std::stoul(left));
|
|
|
|
version.SetBuild(0,stage);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
version.SetMajor((uint8_t)std::stoul(left));
|
|
|
|
left = right;
|
|
|
|
sep=left.find_first_of('.');
|
|
|
|
|
|
|
|
if(sep != std::string::npos)
|
|
|
|
{
|
|
|
|
auto lStr = left.substr(0, sep);
|
|
|
|
|
|
|
|
right = left.substr(sep+1);
|
|
|
|
left = lStr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
version.SetMinor((uint8_t)std::stoul(left));
|
|
|
|
version.SetBuild(0,stage);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
version.SetMinor((uint8_t)std::stoul(left));
|
|
|
|
left = right;
|
|
|
|
sep=left.find_first_of('.');
|
|
|
|
|
|
|
|
if(sep != std::string::npos)
|
|
|
|
{
|
|
|
|
auto lStr = left.substr(0, sep);
|
|
|
|
|
|
|
|
right = left.substr(sep+1);
|
|
|
|
left = lStr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
version.SetPatch((uint8_t)std::stoul(left));
|
|
|
|
version.SetBuild(0,stage);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
version.SetPatch((uint8_t)std::stoul(left));
|
|
|
|
|
|
|
|
version.SetBuild((uint16_t)std::stoul(right),stage);
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
2025-01-03 11:54:27 +00:00
|
|
|
|
2024-12-28 20:38:00 +00:00
|
|
|
std::string ToString()
|
|
|
|
{
|
|
|
|
std::string str={};
|
|
|
|
str.append(std::to_string((int)this->Major()));
|
|
|
|
str.push_back('.');
|
|
|
|
str.append(std::to_string((int)this->Minor()));
|
|
|
|
str.push_back('.');
|
|
|
|
str.append(std::to_string((int)this->Patch()));
|
|
|
|
str.push_back('.');
|
|
|
|
str.append(std::to_string((int)this->Build()));
|
|
|
|
if(this->VersionStage() == TVMVersionStage::DevVersion)
|
|
|
|
{
|
|
|
|
str.append("-dev");
|
|
|
|
}
|
|
|
|
else if(this->VersionStage() == TVMVersionStage::AlphaVersion)
|
|
|
|
{
|
|
|
|
str.append("-alpha");
|
|
|
|
}
|
|
|
|
else if(this->VersionStage() == TVMVersionStage::BetaVersion)
|
|
|
|
{
|
|
|
|
str.append("-beta");
|
|
|
|
}
|
|
|
|
else if(this->VersionStage() == TVMVersionStage::ProductionVersion)
|
|
|
|
{
|
|
|
|
str.append("-prod");
|
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2025-01-03 11:54:27 +00:00
|
|
|
void CrossArchiveCreate(Tesses::Framework::Filesystem::VFS* vfs,Tesses::Framework::Streams::Stream* strm,std::string name,TVMVersion version,std::string info);
|
|
|
|
std::pair<std::pair<std::string,TVMVersion>,std::string> CrossArchiveExtract(Tesses::Framework::Streams::Stream* strm,Tesses::Framework::Filesystem::VFS* vfs);
|
|
|
|
|
2024-12-28 20:38:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
Identifier,
|
|
|
|
Symbol,
|
|
|
|
String,
|
|
|
|
Char,
|
|
|
|
Documentation
|
|
|
|
} LexTokenType;
|
|
|
|
|
|
|
|
class LexTokenLineInfo
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
int line;
|
|
|
|
int column;
|
|
|
|
int offset;
|
|
|
|
std::string filename;
|
|
|
|
void Add(int c);
|
|
|
|
void Subtract(size_t c);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class LexToken {
|
|
|
|
public:
|
|
|
|
LexTokenLineInfo lineInfo;
|
|
|
|
LexTokenType type;
|
|
|
|
std::string text;
|
|
|
|
};
|
|
|
|
int Lex(std::string filename, std::istream& strm, std::vector<LexToken>& tokens);
|
|
|
|
|
|
|
|
|
|
|
|
class Undefined
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class AdvancedSyntaxNode;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
ADD,
|
|
|
|
SUB,
|
|
|
|
TIMES,
|
|
|
|
DIVIDE,
|
|
|
|
MODULO,
|
|
|
|
LEFTSHIFT,
|
|
|
|
RIGHTSHIFT,
|
|
|
|
BITWISEOR,
|
|
|
|
BITWISEAND,
|
|
|
|
BITWISENOT,
|
|
|
|
LESSTHAN,
|
|
|
|
GREATERTHAN,
|
|
|
|
LESSTHANEQ,
|
|
|
|
GREATERTHANEQ,
|
|
|
|
EQ,
|
|
|
|
NEQ,
|
|
|
|
NOT,
|
|
|
|
NEGATIVE,
|
|
|
|
XOR,
|
|
|
|
POP,
|
|
|
|
DUP,
|
|
|
|
NOP,
|
|
|
|
PUSHCLOSURE,
|
|
|
|
CREATEDICTIONARY,
|
|
|
|
CREATEARRAY,
|
|
|
|
APPENDLIST,
|
|
|
|
APPENDDICT,
|
|
|
|
PUSHRESOURCE,
|
|
|
|
PUSHLONG,
|
|
|
|
PUSHCHAR,
|
|
|
|
PUSHDOUBLE,
|
|
|
|
PUSHSTRING,
|
|
|
|
PUSHNULL,
|
|
|
|
PUSHUNDEFINED,
|
|
|
|
SCOPEBEGIN,
|
|
|
|
SCOPEEND,
|
|
|
|
SCOPEENDTIMES,
|
|
|
|
PUSHFALSE,
|
|
|
|
PUSHTRUE,
|
|
|
|
SETVARIABLE,
|
|
|
|
GETVARIABLE,
|
|
|
|
DECLAREVARIABLE,
|
|
|
|
SETFIELD,
|
|
|
|
GETFIELD,
|
|
|
|
CALLFUNCTION,
|
|
|
|
CALLMETHOD,
|
|
|
|
RET,
|
|
|
|
JMPC,
|
|
|
|
JMP,
|
|
|
|
JMPUNDEFINED,
|
|
|
|
DEFER,
|
|
|
|
TRYCATCH,
|
|
|
|
THROW,
|
|
|
|
PUSHSCOPELESSCLOSURE
|
|
|
|
} Instruction;
|
|
|
|
|
|
|
|
class ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
virtual size_t Size()=0;
|
|
|
|
virtual void Write(std::vector<uint8_t>& data)=0;
|
|
|
|
virtual ~ByteCodeInstruction()
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SimpleInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
Instruction instruction;
|
|
|
|
SimpleInstruction(Instruction instr);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class BitConverter {
|
|
|
|
public:
|
|
|
|
static double ToDoubleBits(uint64_t v);
|
|
|
|
static uint64_t ToUintBits(double v);
|
|
|
|
static double ToDoubleBE(uint8_t& b);
|
|
|
|
static uint64_t ToUint64BE(uint8_t& b);
|
|
|
|
static uint32_t ToUint32BE(uint8_t& b);
|
|
|
|
static uint16_t ToUint16BE(uint8_t& b);
|
|
|
|
static void FromDoubleBE(uint8_t& b, double v);
|
|
|
|
static void FromUint64BE(uint8_t& b, uint64_t v);
|
|
|
|
static void FromUint32BE(uint8_t& b, uint32_t v);
|
|
|
|
static void FromUint16BE(uint8_t& b, uint16_t v);
|
|
|
|
};
|
|
|
|
|
|
|
|
class StringInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
uint32_t n;
|
|
|
|
StringInstruction(uint32_t n);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
class ScopeEndTimesInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
uint32_t n;
|
|
|
|
ScopeEndTimesInstruction(uint32_t n);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class LabelInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
std::string label;
|
|
|
|
LabelInstruction(std::string lbl);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
class LabelableInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
uint32_t n;
|
|
|
|
std::string label;
|
|
|
|
virtual size_t Size();
|
|
|
|
virtual void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class JumpStyleInstruction : public LabelableInstruction {
|
|
|
|
public:
|
|
|
|
Instruction type;
|
|
|
|
|
|
|
|
JumpStyleInstruction(Instruction conditional,std::string label);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class EmbedInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
uint32_t n;
|
|
|
|
EmbedInstruction(uint32_t n);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class ClosureInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
bool hasScope;
|
|
|
|
uint32_t n;
|
|
|
|
ClosureInstruction(uint32_t n,bool hasScope=true);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class DoubleInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
double n;
|
|
|
|
DoubleInstruction(double n);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class LongInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
int64_t n;
|
|
|
|
LongInstruction(int64_t n);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
class CharInstruction : public ByteCodeInstruction {
|
|
|
|
public:
|
|
|
|
char n;
|
|
|
|
CharInstruction(char n);
|
|
|
|
size_t Size();
|
|
|
|
void Write(std::vector<uint8_t>& data);
|
|
|
|
};
|
|
|
|
|
|
|
|
using SyntaxNode = std::variant<int64_t, double, std::string, char, bool, std::nullptr_t, Undefined, AdvancedSyntaxNode>;
|
|
|
|
|
|
|
|
class CodeGen {
|
|
|
|
uint32_t id;
|
|
|
|
uint32_t NewId();
|
|
|
|
|
|
|
|
void GetFunctionArgs(std::vector<uint32_t>& args,SyntaxNode n);
|
|
|
|
void GetFunctionName(std::vector<uint32_t>& name,SyntaxNode n);
|
|
|
|
void GetFunctionArgs(std::vector<SyntaxNode>& args,SyntaxNode n);
|
|
|
|
|
|
|
|
uint32_t GetString(std::string str);
|
|
|
|
uint32_t GetResource(std::string res);
|
|
|
|
std::vector<std::string> strs;
|
|
|
|
std::vector<std::string> res;
|
|
|
|
std::vector<std::pair<std::vector<uint32_t>, std::vector<ByteCodeInstruction*>>> chunks;
|
|
|
|
std::vector<std::pair<std::vector<uint32_t>,uint32_t>> funcs;
|
|
|
|
void GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI);
|
|
|
|
void GenPop(std::vector<ByteCodeInstruction*>& instrs,SyntaxNode n);
|
|
|
|
public:
|
|
|
|
std::vector<std::pair<std::string, TVMVersion>> dependencies;
|
|
|
|
TVMVersion version;
|
|
|
|
std::string name;
|
|
|
|
std::string info;
|
|
|
|
void GenRoot(SyntaxNode n);
|
|
|
|
void Save(Tesses::Framework::Filesystem::VFS* embedFS,Tesses::Framework::Streams::Stream* output);
|
|
|
|
~CodeGen();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
constexpr std::string_view EmbedExpression = "embedExpression";
|
|
|
|
constexpr std::string_view NegativeExpression = "negativeExpression";
|
|
|
|
constexpr std::string_view NotExpression = "notExpression";
|
|
|
|
constexpr std::string_view BitwiseNotExpression = "bitwiseNotExpression";
|
|
|
|
constexpr std::string_view PrefixIncrementExpression = "prefixIncrementExpression";
|
|
|
|
constexpr std::string_view PrefixDecrementExpression = "prefixDecrementExpression";
|
|
|
|
constexpr std::string_view PostfixIncrementExpression = "postfixIncrementExpression";
|
|
|
|
constexpr std::string_view PostfixDecrementExpression = "postfixDecrementExpression";
|
|
|
|
constexpr std::string_view GetVariableExpression = "getVariableExpression";
|
|
|
|
constexpr std::string_view GetFieldExpression = "getFieldExpression";
|
|
|
|
constexpr std::string_view GetArrayExpression = "getArrayExpression";
|
|
|
|
constexpr std::string_view FunctionCallExpression = "functionCallExpression";
|
|
|
|
constexpr std::string_view CompoundAssignExpression = "compoundAssignExpression";
|
|
|
|
constexpr std::string_view AssignExpression = "assignExpression";
|
|
|
|
constexpr std::string_view CharExpression = "charExpression";
|
|
|
|
constexpr std::string_view UndefinedExpression = "undefinedExpression";
|
|
|
|
constexpr std::string_view ScopeNode = "scopeNode";
|
|
|
|
constexpr std::string_view NodeList = "nodeList";
|
|
|
|
|
|
|
|
constexpr std::string_view ArrayExpression = "arrayExpression";
|
|
|
|
constexpr std::string_view DictionaryExpression = "dictionaryExpression";
|
|
|
|
constexpr std::string_view DeclareExpression = "declareExpression";
|
|
|
|
|
|
|
|
constexpr std::string_view ClosureExpression = "closureExpression";
|
|
|
|
constexpr std::string_view ScopelessClosureExpression = "scopelessClosureExpression";
|
|
|
|
|
|
|
|
constexpr std::string_view TernaryExpression = "ternaryExpression";
|
|
|
|
constexpr std::string_view IfStatement = "ifStatement";
|
|
|
|
constexpr std::string_view ForStatement = "forStatement";
|
|
|
|
constexpr std::string_view WhileStatement = "whileStatement";
|
|
|
|
constexpr std::string_view DoStatement = "doStatement";
|
|
|
|
constexpr std::string_view EachStatement = "eachStatement";
|
|
|
|
constexpr std::string_view ReturnStatement = "returnStatement";
|
|
|
|
constexpr std::string_view BreakStatement = "breakStatement";
|
|
|
|
constexpr std::string_view ContinueStatement = "continueStatement";
|
|
|
|
constexpr std::string_view FunctionStatement = "functionStatement";
|
|
|
|
constexpr std::string_view DocumentationStatement = "documentationStatement";
|
|
|
|
constexpr std::string_view CommaExpression = "commaExpression";
|
|
|
|
|
|
|
|
constexpr std::string_view AddExpression = "addExpression";
|
|
|
|
constexpr std::string_view SubExpression = "subtractExpression";
|
|
|
|
constexpr std::string_view TimesExpression = "timesExpression";
|
|
|
|
constexpr std::string_view DivideExpression = "divideExpression";
|
|
|
|
constexpr std::string_view ModExpression = "modExpression";
|
|
|
|
constexpr std::string_view LeftShiftExpression = "leftShiftExpression";
|
|
|
|
constexpr std::string_view RightShiftExpression = "rightShiftExpression";
|
|
|
|
constexpr std::string_view BitwiseOrExpression = "bitwiseOrExpression";
|
|
|
|
constexpr std::string_view BitwiseAndExpression = "bitwiseAndExpression";
|
|
|
|
|
|
|
|
constexpr std::string_view XOrExpression = "xOrExpression";
|
|
|
|
constexpr std::string_view LogicalOrExpression = "logicalOrExpression";
|
|
|
|
constexpr std::string_view LogicalAndExpression = "logicalAndExpression";
|
|
|
|
|
|
|
|
constexpr std::string_view EqualsExpression = "equalsExpression";
|
|
|
|
constexpr std::string_view NotEqualsExpression = "notEqualsExpression";
|
|
|
|
constexpr std::string_view LessThanExpression = "lessThanExpression";
|
|
|
|
constexpr std::string_view GreaterThanExpression = "greaterThanExpression";
|
|
|
|
constexpr std::string_view LessThanEqualsExpression = "lessThanEqualsExpression";
|
|
|
|
constexpr std::string_view GreaterThanEqualsExpression = "greaterThanEqualsExpression";
|
|
|
|
constexpr std::string_view ParenthesesExpression = "parenthesesExpression";
|
|
|
|
constexpr std::string_view ThrowStatement = "throwStatement";
|
|
|
|
constexpr std::string_view TryStatement = "tryStatement";
|
|
|
|
constexpr std::string_view DeferStatement = "deferStatement";
|
|
|
|
class AdvancedSyntaxNode {
|
|
|
|
public:
|
|
|
|
std::string nodeName;
|
|
|
|
bool isExpression;
|
|
|
|
std::vector<SyntaxNode> nodes;
|
|
|
|
static AdvancedSyntaxNode Create(std::string_view nodeName,bool isExpression, std::vector<SyntaxNode> n);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SyntaxNode Deserialize(std::string astData);
|
|
|
|
|
|
|
|
std::string Serialize(SyntaxNode node);
|
|
|
|
|
|
|
|
class Parser {
|
|
|
|
uint64_t i;
|
|
|
|
std::vector<LexToken> tokens;
|
|
|
|
|
|
|
|
LexToken tkn;
|
|
|
|
void EnsureSymbol(std::string txt);
|
|
|
|
bool IsIdentifier(std::string txt,bool pop=true);
|
|
|
|
bool IsAnyIdentifier(std::initializer_list<std::string> idents, bool pop=true);
|
|
|
|
bool IsSymbol(std::string txt,bool pop=true);
|
|
|
|
bool IsAnySymbol(std::initializer_list<std::string> idents, bool pop=true);
|
|
|
|
|
|
|
|
SyntaxNode ParseExpression();
|
|
|
|
SyntaxNode ParseTernary();
|
|
|
|
SyntaxNode ParseNode(bool isRoot=false);
|
|
|
|
SyntaxNode ParseAssignment();
|
|
|
|
SyntaxNode ParseXOr();
|
|
|
|
SyntaxNode ParseBOr();
|
|
|
|
SyntaxNode ParseLOr();
|
|
|
|
SyntaxNode ParseLAnd();
|
|
|
|
SyntaxNode ParseBAnd();
|
|
|
|
SyntaxNode ParseEq();
|
|
|
|
SyntaxNode ParseRel();
|
|
|
|
SyntaxNode ParseShift();
|
|
|
|
SyntaxNode ParseSum();
|
|
|
|
SyntaxNode ParseFactor();
|
|
|
|
SyntaxNode ParseValue();
|
|
|
|
SyntaxNode ParseUnary();
|
|
|
|
public:
|
|
|
|
Parser(std::vector<LexToken> tokens);
|
|
|
|
SyntaxNode ParseRoot()
|
|
|
|
{
|
|
|
|
return ParseNode(true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
class THeapObject;
|
|
|
|
class CallStackEntry;
|
|
|
|
class InterperterThread;
|
|
|
|
class THeapObject {
|
|
|
|
public:
|
|
|
|
bool marked;
|
|
|
|
virtual void Mark()
|
|
|
|
{
|
|
|
|
marked = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~THeapObject()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
class THeapObjectHolder
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
THeapObject* obj;
|
|
|
|
THeapObjectHolder(THeapObject* obj)
|
|
|
|
{
|
|
|
|
this->obj = obj;
|
|
|
|
}
|
|
|
|
THeapObjectHolder()
|
|
|
|
{
|
|
|
|
this->obj = obj;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
class MethodInvoker {
|
|
|
|
|
|
|
|
};
|
|
|
|
using TObject = std::variant<int64_t,double,char,bool,std::string,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder>;
|
|
|
|
class GC {
|
|
|
|
Tesses::Framework::Threading::Thread* thrd;
|
|
|
|
Tesses::Framework::Threading::Mutex* mtx;
|
|
|
|
volatile std::atomic<bool> running;
|
|
|
|
std::vector<THeapObject*> roots;
|
|
|
|
std::vector<THeapObject*> objects;
|
|
|
|
public:
|
|
|
|
bool UsingNullThreads();
|
|
|
|
GC();
|
|
|
|
void Start();
|
|
|
|
bool IsRunning();
|
|
|
|
void BarrierBegin();
|
|
|
|
void BarrierEnd();
|
|
|
|
void Collect();
|
|
|
|
void Watch(TObject obj);
|
|
|
|
void Unwatch(TObject obj);
|
|
|
|
void SetRoot(TObject obj);
|
|
|
|
void UnsetRoot(TObject obj);
|
|
|
|
static void Mark(TObject obj);
|
|
|
|
~GC();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
std::string ToString(GC* gc, TObject obj);
|
|
|
|
|
|
|
|
class GCList : public THeapObject
|
|
|
|
{
|
|
|
|
std::vector<THeapObject*> items;
|
|
|
|
|
|
|
|
GC* gc;
|
|
|
|
public:
|
|
|
|
GCList(GC* gc);
|
|
|
|
GCList(GC& gc);
|
|
|
|
GC* GetGC();
|
|
|
|
void Add(TObject v);
|
|
|
|
void Remove(TObject v);
|
|
|
|
void Mark();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
~GCList();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TFile;
|
|
|
|
|
|
|
|
class TFileChunk : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static TFileChunk* Create(GCList* gc);
|
|
|
|
static TFileChunk* Create(GCList& gc);
|
|
|
|
TFile* file;
|
|
|
|
std::vector<uint8_t> code;
|
|
|
|
std::vector<std::string> args;
|
|
|
|
std::string name;
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TByteArray : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
std::vector<uint8_t> data;
|
|
|
|
static TByteArray* Create(GCList* gc);
|
|
|
|
static TByteArray* Create(GCList& gc);
|
|
|
|
};
|
|
|
|
|
|
|
|
class TFile : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static TFile* Create(GCList* gc);
|
|
|
|
static TFile* Create(GCList& gc);
|
|
|
|
std::vector<TFileChunk*> chunks;
|
|
|
|
|
|
|
|
std::vector<std::string> strings;
|
|
|
|
std::vector<std::pair<std::vector<std::string>, uint32_t>> functions;
|
|
|
|
std::vector<std::pair<std::string,TVMVersion>> dependencies;
|
|
|
|
std::vector<std::vector<uint8_t>> resources;
|
|
|
|
std::string name;
|
|
|
|
TVMVersion version;
|
|
|
|
std::string info;
|
|
|
|
|
|
|
|
void Load(GC* gc, Tesses::Framework::Streams::Stream* strm);
|
|
|
|
void Skip(Tesses::Framework::Streams::Stream* strm,size_t len);
|
|
|
|
void Ensure(Tesses::Framework::Streams::Stream* strm,uint8_t* buffer, size_t len);
|
|
|
|
uint32_t EnsureInt(Tesses::Framework::Streams::Stream* strm);
|
|
|
|
std::string EnsureString(Tesses::Framework::Streams::Stream* strm);
|
|
|
|
|
|
|
|
std::string GetString(Tesses::Framework::Streams::Stream* strm);
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
|
|
|
|
class TList : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
std::vector<TObject> items;
|
|
|
|
static TList* Create(GCList* gc);
|
|
|
|
static TList* Create(GCList& gc);
|
|
|
|
virtual int64_t Count();
|
|
|
|
virtual TObject Get(int64_t index);
|
|
|
|
virtual void Set(int64_t index, TObject value);
|
|
|
|
virtual void Insert(int64_t index,TObject value);
|
|
|
|
virtual void Add(TObject value);
|
|
|
|
virtual void RemoveAt(int64_t index);
|
|
|
|
virtual void Clear();
|
|
|
|
virtual void Mark();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class TDictionary : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
std::unordered_map<std::string,TObject> items;
|
|
|
|
static TDictionary* Create(GCList* gc);
|
|
|
|
static TDictionary* Create(GCList& gc);
|
|
|
|
|
|
|
|
virtual bool HasValue(std::string key);
|
|
|
|
virtual TObject GetValue(std::string key);
|
|
|
|
virtual void SetValue(std::string key, TObject value);
|
|
|
|
virtual void Mark();
|
|
|
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb);
|
|
|
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb);
|
|
|
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
|
|
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
|
|
|
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TRootEnvironment;
|
|
|
|
class TSubEnvironment;
|
|
|
|
|
|
|
|
class TCallable : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
std::string documentation;
|
|
|
|
virtual TObject Call(GCList& ls,std::vector<TObject> args)=0;
|
|
|
|
};
|
|
|
|
|
|
|
|
class TEnvironment : public THeapObject {
|
|
|
|
|
|
|
|
public:
|
|
|
|
std::vector<TCallable*> defers;
|
|
|
|
TObject LoadFile(GC* gc, TFile* f);
|
|
|
|
TObject Eval(GCList& ls,std::string code);
|
|
|
|
virtual bool HasVariable(std::string key)=0;
|
|
|
|
virtual bool HasVariableRecurse(std::string key)=0;
|
|
|
|
virtual TObject GetVariable(std::string key)=0;
|
|
|
|
virtual void SetVariable(std::string key, TObject value)=0;
|
|
|
|
virtual void DeclareVariable(std::string key, TObject value)=0;
|
|
|
|
virtual TRootEnvironment* GetRootEnvironment()=0;
|
|
|
|
virtual TEnvironment* GetParentEnvironment()=0;
|
|
|
|
virtual TSubEnvironment* GetSubEnvironment(TDictionary* dict);
|
|
|
|
TSubEnvironment* GetSubEnvironment(GCList* gc);
|
|
|
|
TSubEnvironment* GetSubEnvironment(GCList& gc);
|
|
|
|
|
|
|
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb);
|
|
|
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb);
|
|
|
|
void DeclareFunction(GC* gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
|
|
|
void DeclareFunction(GC& gc,std::string key,std::string documentation, std::vector<std::string> argNames, std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
|
|
|
TObject CallFunction(GCList& ls, std::string key, std::vector<TObject> args);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class EnvironmentPermissions {
|
|
|
|
public:
|
|
|
|
EnvironmentPermissions();
|
|
|
|
Tesses::Framework::Filesystem::VFSPath sqliteOffsetPath;
|
|
|
|
bool canRegisterConsole;
|
|
|
|
bool canRegisterIO;
|
|
|
|
bool canRegisterLocalFS;
|
|
|
|
bool canRegisterNet;
|
|
|
|
bool canRegisterSqlite;
|
|
|
|
bool canRegisterVM;
|
|
|
|
bool canRegisterDictionary;
|
|
|
|
bool canRegisterJSON;
|
|
|
|
bool canRegisterCrypto;
|
|
|
|
bool canRegisterSDL2;
|
|
|
|
bool canRegisterRoot;
|
|
|
|
bool canRegisterPath;
|
|
|
|
bool canRegisterOGC;
|
|
|
|
bool canRegisterEnv;
|
|
|
|
bool sqlite3Scoped;
|
|
|
|
bool locked;
|
|
|
|
};
|
|
|
|
|
|
|
|
class TRootEnvironment : public TEnvironment
|
|
|
|
{
|
|
|
|
TDictionary* dict;
|
|
|
|
|
|
|
|
void LoadDependency(GC* gc,Tesses::Framework::Filesystem::VFS* vfs, std::pair<std::string,TVMVersion> dep);
|
|
|
|
public:
|
|
|
|
EnvironmentPermissions permissions;
|
|
|
|
|
|
|
|
std::vector<std::pair<std::string, TVMVersion>> dependencies;
|
|
|
|
|
|
|
|
void LoadFileWithDependencies(GC* gc,Tesses::Framework::Filesystem::VFS* vfs, TFile* f);
|
|
|
|
void LoadFileWithDependencies(GC* gc,Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
|
|
|
|
TDictionary* GetDictionary();
|
|
|
|
static TRootEnvironment* Create(GCList* gc,TDictionary* dict);
|
|
|
|
static TRootEnvironment* Create(GCList& gc,TDictionary* dict);
|
|
|
|
TRootEnvironment(TDictionary* dict);
|
|
|
|
bool HasVariable(std::string key);
|
|
|
|
bool HasVariableRecurse(std::string key);
|
|
|
|
TObject GetVariable(std::string key);
|
|
|
|
void SetVariable(std::string key, TObject value);
|
|
|
|
void DeclareVariable(std::string key, TObject value);
|
|
|
|
TRootEnvironment* GetRootEnvironment();
|
|
|
|
TEnvironment* GetParentEnvironment();
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
class TStd {
|
|
|
|
public:
|
|
|
|
static void RegisterStd(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterConsole(GC* gc,TRootEnvironment* env);
|
|
|
|
static void RegisterIO(GC* gc,TRootEnvironment* env, bool enableLocalFilesystem=true);
|
|
|
|
static void RegisterNet(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterSqlite(GC* gc,TRootEnvironment* env);
|
|
|
|
static void RegisterVM(GC* gc,TRootEnvironment* env);
|
|
|
|
static void RegisterDictionary(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterJson(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterCrypto(GC* gc,TRootEnvironment* env);
|
|
|
|
static void RegisterSDL2(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterRoot(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterPath(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterOGC(GC* gc, TRootEnvironment* env);
|
|
|
|
static void RegisterEnv(GC* gc, TRootEnvironment* env);
|
|
|
|
|
|
|
|
};
|
|
|
|
class TSubEnvironment : public TEnvironment
|
|
|
|
{
|
|
|
|
TEnvironment* env;
|
|
|
|
TDictionary* dict;
|
|
|
|
public:
|
|
|
|
static TSubEnvironment* Create(GCList* gc,TEnvironment* env,TDictionary* dict);
|
|
|
|
static TSubEnvironment* Create(GCList& gc,TEnvironment* env,TDictionary* dict);
|
|
|
|
TSubEnvironment(TEnvironment* env,TDictionary* dict);
|
|
|
|
bool HasVariable(std::string key);
|
|
|
|
bool HasVariableRecurse(std::string key);
|
|
|
|
TObject GetVariable(std::string key);
|
|
|
|
void SetVariable(std::string key, TObject value);
|
|
|
|
void DeclareVariable(std::string key, TObject value);
|
|
|
|
TRootEnvironment* GetRootEnvironment();
|
|
|
|
TEnvironment* GetParentEnvironment();
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TDictionary* CreateThread(GCList& ls, TCallable* callable,bool detached);
|
|
|
|
|
|
|
|
class TArgWrapper : public TCallable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TCallable* callable;
|
|
|
|
static TArgWrapper* Create(GCList& ls, TCallable* callable);
|
|
|
|
static TArgWrapper* Create(GCList* ls, TCallable* callable);
|
|
|
|
TObject Call(GCList& ls,std::vector<TObject> args);
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
|
|
|
|
class TExternalMethod : public TCallable
|
|
|
|
{
|
|
|
|
std::function<TObject(GCList& ls, std::vector<TObject> args)> cb;
|
|
|
|
std::function<void()> destroy;
|
|
|
|
|
|
|
|
public:
|
|
|
|
std::vector<std::string> args;
|
|
|
|
std::vector<TObject> watch;
|
|
|
|
TExternalMethod(std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::string documentation, std::vector<std::string> argNames,std::function<void()> destroy);
|
|
|
|
static TExternalMethod* Create(GCList& ls,std::string documentation, std::vector<std::string> argNames,std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
|
|
|
static TExternalMethod* Create(GCList* ls,std::string documentation, std::vector<std::string> argNames,std::function<TObject(GCList& ls, std::vector<TObject> args)> cb,std::function<void()> destroy);
|
|
|
|
|
|
|
|
static TExternalMethod* Create(GCList& ls,std::string documentation, std::vector<std::string> argNames,std::function<TObject(GCList& ls, std::vector<TObject> args)> cb);
|
|
|
|
static TExternalMethod* Create(GCList* ls,std::string documentation, std::vector<std::string> argNames,std::function<TObject(GCList& ls, std::vector<TObject> args)> cb);
|
|
|
|
TObject Call(GCList& ls, std::vector<TObject> args);
|
|
|
|
|
|
|
|
~TExternalMethod();
|
|
|
|
void Mark()
|
|
|
|
{
|
|
|
|
if(this->marked) return;
|
|
|
|
this->marked=true;
|
|
|
|
for(auto item : watch)
|
|
|
|
GC::Mark(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class TEnumerator : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual bool MoveNext(GC* ls)=0;
|
|
|
|
virtual TObject GetCurrent(GCList& ls)=0;
|
|
|
|
static TEnumerator* CreateFromObject(GCList& ls, TObject obj);
|
|
|
|
};
|
|
|
|
|
|
|
|
class TCustomEnumerator : public TEnumerator {
|
|
|
|
public:
|
|
|
|
TDictionary* dict;
|
|
|
|
bool MoveNext(GC* ls);
|
|
|
|
TObject GetCurrent(GCList& ls);
|
|
|
|
void Mark();
|
|
|
|
static TCustomEnumerator* Create(GCList& ls,TDictionary* dict);
|
|
|
|
static TCustomEnumerator* Create(GCList* ls,TDictionary* dict);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class TStringEnumerator : public TEnumerator
|
|
|
|
{
|
|
|
|
bool hasStarted;
|
|
|
|
size_t index;
|
|
|
|
std::string str;
|
|
|
|
public:
|
|
|
|
static TStringEnumerator* Create(GCList& ls,std::string str);
|
|
|
|
static TStringEnumerator* Create(GCList* ls,std::string str);
|
|
|
|
bool MoveNext(GC* ls);
|
|
|
|
TObject GetCurrent(GCList& ls);
|
|
|
|
};
|
|
|
|
class TListEnumerator : public TEnumerator
|
|
|
|
{
|
|
|
|
int64_t index;
|
|
|
|
TList* ls;
|
|
|
|
public:
|
|
|
|
static TListEnumerator* Create(GCList& ls, TList* list);
|
|
|
|
static TListEnumerator* Create(GCList* ls, TList* list);
|
|
|
|
bool MoveNext(GC* ls);
|
|
|
|
TObject GetCurrent(GCList& ls);
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
class TVFSPathEnumerator : public TEnumerator
|
|
|
|
{
|
|
|
|
Tesses::Framework::Filesystem::VFSPathEnumerator enumerator;
|
|
|
|
public:
|
|
|
|
static TVFSPathEnumerator* Create(GCList& ls, Tesses::Framework::Filesystem::VFSPathEnumerator list);
|
|
|
|
static TVFSPathEnumerator* Create(GCList* ls, Tesses::Framework::Filesystem::VFSPathEnumerator list);
|
|
|
|
bool MoveNext(GC* ls);
|
|
|
|
TObject GetCurrent(GCList& ls);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class TStreamHeapObject : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Tesses::Framework::Streams::Stream* stream;
|
|
|
|
|
|
|
|
static TStreamHeapObject* Create(GCList& ls, Tesses::Framework::Streams::Stream* strm);
|
|
|
|
static TStreamHeapObject* Create(GCList* ls, Tesses::Framework::Streams::Stream* strm);
|
|
|
|
~TStreamHeapObject();
|
|
|
|
void Close();
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class TVFSHeapObject : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Tesses::Framework::Filesystem::VFS* vfs;
|
|
|
|
static TVFSHeapObject* Create(GCList& ls, Tesses::Framework::Filesystem::VFS* vfs);
|
|
|
|
static TVFSHeapObject* Create(GCList* ls, Tesses::Framework::Filesystem::VFS* vfs);
|
|
|
|
~TVFSHeapObject();
|
|
|
|
void Close();
|
|
|
|
};
|
|
|
|
|
|
|
|
class TServerHeapObject : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Tesses::Framework::Http::IHttpServer* server;
|
|
|
|
static TServerHeapObject* Create(GCList& ls, Tesses::Framework::Http::IHttpServer* vfs);
|
|
|
|
static TServerHeapObject* Create(GCList* ls, Tesses::Framework::Http::IHttpServer* vfs);
|
|
|
|
~TServerHeapObject();
|
|
|
|
void Close();
|
|
|
|
};
|
|
|
|
class TObjectVFS : public Tesses::Framework::Filesystem::VFS
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TObject obj;
|
|
|
|
GCList* ls;
|
|
|
|
TObjectVFS(GC* gc, TObject obj);
|
|
|
|
Tesses::Framework::Streams::Stream* OpenFile(Tesses::Framework::Filesystem::VFSPath path, std::string mode);
|
|
|
|
void CreateDirectory(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
void DeleteDirectory(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool RegularFileExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool SymlinkExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool CharacterDeviceExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool BlockDeviceExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool SocketFileExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool FIFOFileExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool FileExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
bool SpecialFileExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
void CreateSymlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath symlinkFile);
|
|
|
|
void CreateHardlink(Tesses::Framework::Filesystem::VFSPath existingFile, Tesses::Framework::Filesystem::VFSPath newName);
|
|
|
|
bool DirectoryExists(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
void DeleteFile(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
void DeleteDirectoryRecurse(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
Tesses::Framework::Filesystem::VFSPathEnumerator EnumeratePaths(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
void MoveFile(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest);
|
|
|
|
void MoveDirectory(Tesses::Framework::Filesystem::VFSPath src, Tesses::Framework::Filesystem::VFSPath dest);
|
|
|
|
Tesses::Framework::Filesystem::VFSPath ReadLink(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
std::string VFSPathToSystem(Tesses::Framework::Filesystem::VFSPath path);
|
|
|
|
Tesses::Framework::Filesystem::VFSPath SystemToVFSPath(std::string path);
|
|
|
|
void GetDate(Tesses::Framework::Filesystem::VFSPath path, time_t& lastWrite, time_t& lastAccess);
|
|
|
|
void SetDate(Tesses::Framework::Filesystem::VFSPath path, time_t lastWrite, time_t lastAccess);
|
|
|
|
~TObjectVFS();
|
|
|
|
};
|
|
|
|
|
|
|
|
class TObjectStream : public Tesses::Framework::Streams::Stream
|
|
|
|
{
|
|
|
|
int64_t _GetPosInternal();
|
|
|
|
public:
|
|
|
|
TObject obj;
|
|
|
|
GCList* ls;
|
|
|
|
TObjectStream(GC* gc, TObject obj);
|
|
|
|
bool EndOfStream();
|
|
|
|
size_t Read(uint8_t* buff, size_t sz);
|
|
|
|
size_t Write(const uint8_t* buff, size_t sz);
|
|
|
|
bool CanRead();
|
|
|
|
bool CanWrite();
|
|
|
|
bool CanSeek();
|
|
|
|
int64_t GetPosition();
|
|
|
|
int64_t GetLength();
|
|
|
|
void Flush();
|
|
|
|
void Seek(int64_t pos, Tesses::Framework::Streams::SeekOrigin whence);
|
|
|
|
~TObjectStream();
|
|
|
|
};
|
|
|
|
|
|
|
|
class TObjectHttpServer : public Tesses::Framework::Http::IHttpServer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TObject obj;
|
|
|
|
GCList* ls;
|
|
|
|
TObjectHttpServer(GC* gc,TObject obj);
|
|
|
|
bool Handle(Tesses::Framework::Http::ServerContext& ctx);
|
|
|
|
~TObjectHttpServer();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class TDictionaryEnumerator : public TEnumerator
|
|
|
|
{
|
|
|
|
bool hasStarted;
|
|
|
|
std::unordered_map<std::string, Tesses::CrossLang::TObject>::iterator ittr;
|
|
|
|
TDictionary* dict;
|
|
|
|
public:
|
|
|
|
static TDictionaryEnumerator* Create(GCList& ls, TDictionary* dict);
|
|
|
|
static TDictionaryEnumerator* Create(GCList* ls, TDictionary* dict);
|
|
|
|
bool MoveNext(GC* ls);
|
|
|
|
TObject GetCurrent(GCList& ls);
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
|
|
|
|
class TClosure : public TCallable
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static TClosure* Create(GCList& ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope=true);
|
|
|
|
static TClosure* Create(GCList* ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope=true);
|
|
|
|
bool ownScope;
|
|
|
|
TFileChunk* closure;
|
|
|
|
TFile* file;
|
|
|
|
uint32_t chunkId;
|
|
|
|
TEnvironment* env;
|
|
|
|
TObject Call(GCList& ls,std::vector<TObject> args);
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CallStackEntry : public THeapObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static CallStackEntry* Create(GCList* ls);
|
|
|
|
static CallStackEntry* Create(GCList& ls);
|
|
|
|
std::vector<TObject> stack;
|
|
|
|
TEnvironment* env;
|
|
|
|
TClosure* callable;
|
|
|
|
uint32_t ip;
|
|
|
|
uint32_t scopes;
|
|
|
|
|
|
|
|
void Mark();
|
|
|
|
void Push(GC* gc,TObject v);
|
|
|
|
TObject Pop(GCList& gcl);
|
|
|
|
};
|
|
|
|
extern thread_local CallStackEntry* current_function;
|
|
|
|
|
|
|
|
class InterperterThread : public THeapObject
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
bool InvokeTwo(GCList& ls,TObject fn, TObject left, TObject right);
|
|
|
|
bool InvokeOne(GCList& ls,TObject fn, TObject arg);
|
|
|
|
bool InvokeMethod(GCList& ls, TObject fn, TObject instance, std::vector<TObject> args);
|
|
|
|
bool ExecuteMethod2(GC* gc, TObject instance, std::string key, std::vector<TObject> args);
|
|
|
|
protected:
|
|
|
|
static void* ThreadCallback(void* ptr);
|
|
|
|
bool Add(GC* gc);
|
|
|
|
bool Sub(GC* gc);
|
|
|
|
bool Times(GC* gc);
|
|
|
|
bool Divide(GC* gc);
|
|
|
|
bool Mod(GC* gc);
|
|
|
|
bool Neg(GC* gc);
|
|
|
|
bool Lt(GC* gc);
|
|
|
|
bool Gt(GC* gc);
|
|
|
|
bool Lte(GC* gc);
|
|
|
|
bool Gte(GC* gc);
|
|
|
|
bool Eq(GC* gc);
|
|
|
|
bool NEq(GC* gc);
|
|
|
|
bool LShift(GC* gc);
|
|
|
|
bool RShift(GC* gc);
|
|
|
|
bool BOr(GC* gc);
|
|
|
|
bool XOr(GC* gc);
|
|
|
|
bool LNot(GC* gc);
|
|
|
|
bool BNot(GC* gc);
|
|
|
|
bool BAnd(GC* gc);
|
|
|
|
bool ExecuteFunction(GC* gc);
|
|
|
|
bool ExecuteMethod(GC* gc);
|
2025-01-03 11:54:27 +00:00
|
|
|
bool GetVariable(GC* gc);
|
|
|
|
bool SetVariable(GC* gc);
|
2024-12-28 20:38:00 +00:00
|
|
|
bool GetField(GC* gc);
|
|
|
|
bool SetField(GC* gc);
|
|
|
|
bool GetArray(GC* gc);
|
|
|
|
bool SetArray(GC* gc);
|
2025-01-03 11:54:27 +00:00
|
|
|
bool DeclareVariable(GC* gc);
|
|
|
|
bool PushLong(GC* gc);
|
|
|
|
bool PushDouble(GC* gc);
|
|
|
|
bool PushChar(GC* gc);
|
|
|
|
bool PushString(GC* gc);
|
|
|
|
bool PushClosure(GC* gc);
|
|
|
|
bool PushScopelessClosure(GC* gc);
|
|
|
|
bool PushResource(GC* gc);
|
|
|
|
bool Illegal(GC* gc);
|
|
|
|
bool Throw(GC* gc);
|
|
|
|
bool Jump(GC* gc);
|
|
|
|
bool JumpConditional(GC* gc);
|
|
|
|
bool JumpUndefined(GC* gc);
|
|
|
|
bool Defer(GC* gc);
|
|
|
|
bool TryCatch(GC* gc);
|
|
|
|
bool Return(GC* gc);
|
|
|
|
bool ScopeBegin(GC* gc);
|
|
|
|
bool ScopeEnd(GC* gc);
|
|
|
|
bool ScopeEndTimes(GC* gc);
|
|
|
|
bool PushTrue(GC* gc);
|
|
|
|
bool PushFalse(GC* gc);
|
|
|
|
bool PushNull(GC* gc);
|
|
|
|
bool PushUndefined(GC* gc);
|
|
|
|
bool CreateDictionary(GC* gc);
|
|
|
|
bool CreateArray(GC* gc);
|
|
|
|
bool AppendList(GC* gc);
|
|
|
|
bool AppendDictionary(GC* gc);
|
|
|
|
bool Pop(GC* gc);
|
|
|
|
bool Dup(GC* gc);
|
|
|
|
bool Nop(GC* gc);
|
2024-12-28 20:38:00 +00:00
|
|
|
public:
|
|
|
|
static InterperterThread* Create(GCList* ls);
|
|
|
|
static InterperterThread* Create(GCList& ls);
|
|
|
|
std::vector<CallStackEntry*> call_stack_entries;
|
|
|
|
virtual void Execute(GC* gc);
|
|
|
|
void AddCallStackEntry(GCList& ls,TClosure* closure, std::vector<TObject> args);
|
|
|
|
void Mark();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class VMException : public std::exception {
|
|
|
|
|
|
|
|
std::string error_message;
|
|
|
|
public:
|
|
|
|
|
|
|
|
VMException(std::string ex)
|
|
|
|
{
|
|
|
|
error_message = "VMException: ";
|
|
|
|
error_message.append(ex);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char * what() const noexcept override
|
|
|
|
{
|
|
|
|
return error_message.c_str();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
class TNative : public THeapObject
|
|
|
|
{
|
|
|
|
std::atomic<bool> destroyed;
|
|
|
|
void* ptr;
|
|
|
|
std::function<void(void*)> destroy;
|
|
|
|
public:
|
|
|
|
TObject other;
|
|
|
|
TNative(void* ptr,std::function<void(void*)> destroy);
|
|
|
|
bool GetDestroyed();
|
|
|
|
void* GetPointer();
|
|
|
|
void Destroy();
|
|
|
|
void Mark();
|
|
|
|
static TNative* Create(GCList& ls, void* ptr,std::function<void(void*)> destroy);
|
|
|
|
static TNative* Create(GCList* ls, void* ptr,std::function<void(void*)> destroy);
|
|
|
|
~TNative();
|
|
|
|
};
|
|
|
|
|
|
|
|
class ThreadHandle : public THeapObject {
|
|
|
|
public:
|
|
|
|
Tesses::Framework::Threading::Thread* thrd;
|
|
|
|
std::atomic<bool> hasInit;
|
|
|
|
std::atomic<bool> hasReturned;
|
|
|
|
std::atomic<bool> detached;
|
|
|
|
TCallable* callable;
|
|
|
|
TObject returnValue;
|
|
|
|
GC* gc;
|
|
|
|
|
|
|
|
|
|
|
|
void Mark()
|
|
|
|
{
|
|
|
|
if(this->marked) return;
|
|
|
|
this->marked = true;
|
|
|
|
callable->Mark();
|
|
|
|
GC::Mark(returnValue);
|
|
|
|
}
|
|
|
|
~ThreadHandle()
|
|
|
|
{
|
|
|
|
if(this->detached)
|
|
|
|
{
|
|
|
|
this->thrd->Join();
|
|
|
|
delete this->thrd;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
TObject ExecuteFunction(GCList& ls,TCallable* callable,std::vector<TObject> args);
|
|
|
|
class VMByteCodeException : public std::exception
|
|
|
|
{
|
|
|
|
std::string lastErrorText;
|
|
|
|
std::shared_ptr<GCList> gcList;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
TObject exception;
|
|
|
|
|
|
|
|
VMByteCodeException()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
VMByteCodeException(GC* gc,TObject obj)
|
|
|
|
{
|
|
|
|
gcList = std::make_shared<GCList>(gc);
|
|
|
|
gcList.get()->Add(obj);
|
|
|
|
this->exception = obj;
|
|
|
|
UpdateError();
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateError()
|
|
|
|
{
|
|
|
|
lastErrorText = ToString(gcList.get()->GetGC(),exception);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const char * what() const noexcept override
|
|
|
|
{
|
|
|
|
return lastErrorText.c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
class SyntaxException : public std::exception
|
|
|
|
{
|
|
|
|
std::string msg={};
|
|
|
|
public:
|
|
|
|
SyntaxException(LexTokenLineInfo lineInfo, std::string message)
|
|
|
|
{
|
|
|
|
msg.append("in file: ");
|
|
|
|
msg.append(lineInfo.filename);
|
|
|
|
msg.append(":");
|
|
|
|
msg.append(std::to_string(lineInfo.line));
|
|
|
|
msg.append(":");
|
|
|
|
msg.append(std::to_string(lineInfo.column));
|
|
|
|
msg.append(":");
|
|
|
|
msg.append(std::to_string(lineInfo.offset));
|
|
|
|
msg.append(": ");
|
|
|
|
msg.append(message);
|
|
|
|
}
|
|
|
|
const char * what() const noexcept override
|
|
|
|
{
|
|
|
|
return msg.c_str();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool GetObject(TObject& obj, T& res)
|
|
|
|
{
|
|
|
|
if(!std::holds_alternative<T>(obj)) return false;
|
|
|
|
res = std::get<T>(obj);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
template<typename T>
|
|
|
|
bool GetArgument(std::vector<TObject>& args, size_t index, T& obj)
|
|
|
|
{
|
|
|
|
if( index >= args.size()) return false;
|
|
|
|
return GetObject(args[index], obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool GetObjectHeap(TObject& obj, T& res)
|
|
|
|
{
|
|
|
|
THeapObjectHolder h;
|
|
|
|
if(!GetObject<THeapObjectHolder>(obj,h)) return false;
|
|
|
|
auto v = dynamic_cast<T>(h.obj);
|
|
|
|
if(v == nullptr) return false;
|
|
|
|
res = v;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
bool GetArgumentHeap(std::vector<TObject>& args, size_t index, T& obj)
|
|
|
|
{
|
|
|
|
if( index >= args.size()) return false;
|
|
|
|
return GetObjectHeap(args[index], obj);
|
|
|
|
}
|
|
|
|
bool GetObjectAsPath(TObject& obj, Tesses::Framework::Filesystem::VFSPath& path, bool allowString=true);
|
|
|
|
bool GetArgumentAsPath(std::vector<TObject>& args, size_t index, Tesses::Framework::Filesystem::VFSPath& path,bool allowString=true);
|
|
|
|
|
|
|
|
|
|
|
|
};
|