From 0c1ead790d5c5617babf5fc788c04ec93ef8696d Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Thu, 8 May 2025 20:19:44 -0500 Subject: [PATCH] Add dvd builder script --- .clangd | 2 +- .vscode/settings.json | 3 +- CMakeLists.txt | 10 + README.md | 20 +- docs/CPP_LAYER.md | 2 +- include/CrossLang.hpp | 709 ++++++++++++++++++++++++++++++++-- src/compiler/codegen.cpp | 94 ++++- src/compiler/parser.cpp | 29 +- src/runtime_methods/env.cpp | 1 + src/runtime_methods/std.cpp | 22 ++ src/types/rootenvironment.cpp | 38 +- src/types/subenvironment.cpp | 6 +- src/vm/vm.cpp | 470 +++++++++++++++++++++- src/vm/vm_opcode_table.h | 4 +- 14 files changed, 1359 insertions(+), 51 deletions(-) diff --git a/.clangd b/.clangd index 2ed3fde..cd3da03 100644 --- a/.clangd +++ b/.clangd @@ -1,2 +1,2 @@ CompileFlags: # Tweak the parse settings, example directory given to show format - Add: ["-Iinclude"] \ No newline at end of file + Add: ["-Iinclude","-std=gnu++17"] diff --git a/.vscode/settings.json b/.vscode/settings.json index 598ce72..7ae39e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -74,7 +74,8 @@ "stop_token": "cpp", "thread": "cpp", "bitset": "cpp", - "regex": "cpp" + "regex": "cpp", + "cstdbool": "cpp" }, "clangd.fallbackFlags": [ "-Iinclude" diff --git a/CMakeLists.txt b/CMakeLists.txt index 56c0d74..0906bed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD 17) include(CMakePackageConfigHelpers) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +#option(CROSSLANG_ENABLE_DOXYGEN "Enable doxygen" ON) option(CROSSLANG_ENABLE_STATIC "Enable Tesses CrossLang static libraries" ON) option(CROSSLANG_ENABLE_SHARED "Enable Tesses CrossLang shared libraries" ON) @@ -25,6 +26,15 @@ option(CROSSLANG_ENABLE_CONFIG_ENVVAR "Allow setting config directory via the en option(CROSSLANG_CUSTOM_CONSOLE "Enable custom Console" OFF) +#if(CROSSLANG_ENABLE_DOXYGEN) +#find_package(Doxygen REQUIRED) +#doxygen_add_docs(doxygen-crosslang "${CMAKE_CURRENT_SOURCE_DIR}/include/CrossLang.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/docs" "${CMAKE_CURRENT_SOURCE_DIR}/README.md") +#add_custom_target(crosslang_doxygen ALL +# COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.doxygen-crosslang +# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +#) + +#endif() if(CROSSLANG_CUSTOM_CONSOLE) set(CROSSLANG_ENABLE_BINARIES OFF) diff --git a/README.md b/README.md index 2146abc..22ea9f0 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ Tesses Cross Language - CMake ## What libraries have I embeded from other people -- [HodwardHinnart's date]() (in folder src/HodwardHinnart_date, modified tz.cpp to point to correct header) -- [Sqlite]() (in folder src/sqlite also uses demo VFS (at least on Wii)) -- [Sago's platform_folders]() (in folder src/sago) +- [HodwardHinnart's date](https://github.com/HowardHinnant/date) (in folder src/HodwardHinnart_date, modified tz.cpp to point to correct header) +- [Sqlite](https://www.sqlite.org/) (in folder src/sqlite also uses demo VFS (at least on Wii)) +- [Sago's platform_folders](https://github.com/sago007/PlatformFolders) (in folder src/sago) - [subprocess](https://github.com/sheredom/subprocess.h) (as file src/runtime_methods/subprocess.h) ## Use in docker (use my container) ```bash @@ -30,7 +30,9 @@ Tesses Cross Language - Install [mbedtls](https://github.com/Mbed-TLS/mbedtls) (use sudo apt install libmbedtls-dev on debian) for TessesFramework - Follow the commands bellow -## Run these commands to install crosslang (or use binaries from [here](https://crosslang.tesseslanguage.com/download/)) +## Run these commands to install crosslang +Or use binaries from [here](https://crosslang.tesseslanguage.com/download/) + ```bash git clone https://onedev.site.tesses.net/CrossLang cd CrossLang @@ -41,6 +43,16 @@ make sudo make install ``` +## To Create the binaries and ISO (You need linux for this) +```bash +sudo apt install xorriso wget curl mingw-w64 nsis cmake tar zip +mkdir dvdwork +cp build-dvd.tcross dvdwork/ +cd dvdwork +crossint build-dvd.tcross +bash script.sh # the iso and tarballs will be in Working/Output +``` + ``` Ye are of God, little children, and have overcome them: because greater is he that is in you, than he that is in the world. (1 John 4:4) ``` diff --git a/docs/CPP_LAYER.md b/docs/CPP_LAYER.md index e0d2d83..eb43736 100644 --- a/docs/CPP_LAYER.md +++ b/docs/CPP_LAYER.md @@ -1 +1 @@ -# C++ Layer \ No newline at end of file +# C++ Layer diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index 01ea972..fd08089 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -17,23 +17,65 @@ #include #include #include + +/** + * @brief CrossLang Runtime Major version + * + */ #define TVM_MAJOR 1 +/** + * @brief CrossLang Runtime Minor version + * + */ #define TVM_MINOR 0 +/** + * @brief CrossLang Runtime Patch version + * + */ #define TVM_PATCH 0 +/** + * @brief CrossLang Runtime Build version + * + */ #define TVM_BUILD 0 +/** + * @brief CrossLang Runtime Stage version + * + */ #define TVM_VERSIONSTAGE DevVersion #if defined(_WIN32) #undef Yield #endif - +/** + * @namespace Tesses::CrossLang + * @brief The CrossLang namespace + * + */ namespace Tesses::CrossLang { - + /** + * @brief Escape a crosslang string (for generating source code) + * + * @param text text to escape + * @param quote whether to surround with double quotes + * @return std::string the escaped string + */ std::string EscapeString(std::string text,bool quote); Tesses::Framework::Filesystem::VFSPath GetRealExecutablePath(Tesses::Framework::Filesystem::VFSPath realPath); + /** + * @brief Get the config folder used by crosslang + * + * @return Tesses::Framework::Filesystem::VFSPath the config folder for crosslang + */ Tesses::Framework::Filesystem::VFSPath GetCrossLangConfigDir(); + + + /** + * @brief Version stage + * + */ enum TVMVersionStage : uint8_t { DevVersion=0, @@ -41,6 +83,10 @@ namespace Tesses::CrossLang { BetaVersion=2, ProductionVersion=3 }; + /** + * @brief CrossLang version + * + */ class TVMVersion { uint8_t major; @@ -48,50 +94,106 @@ namespace Tesses::CrossLang { uint8_t patch; uint16_t build; public: + /** + * @brief Major + * + * @return uint8_t The major + */ uint8_t Major() { return major; } + /** + * @brief Minor + * + * @return uint8_t The minor + */ uint8_t Minor() { return minor; } + /** + * @brief Patch + * + * @return uint8_t The patch + */ uint8_t Patch() { return patch; } + /** + * @brief Build + * + * @return uint16_t The build + */ uint16_t Build() { return build >> 2; } - + /** + * @brief Stage (dev, alpha, beta or prod) + * + * @return TVMVersionStage The stage + */ TVMVersionStage VersionStage() { return (TVMVersionStage)(build & 3); } - + /** + * @brief Set the Major + * + * @param major The major + */ void SetMajor(uint8_t major) { this->major=major; } + /** + * @brief Set the Minor + * + * @param minor The minor + */ void SetMinor(uint8_t minor) { this->minor=minor; } + /** + * @brief Set the Patch + * + * @param patch The patch + */ void SetPatch(uint8_t patch) { this->patch=patch; } + /** + * @brief Set the Build + * + * @param build The build << 2 | (stage & 3) + */ void SetBuild(uint16_t build) { this->build = build; } - + /** + * @brief Set the Build (and stage) + * + * @param build + * @param version + */ void SetBuild(uint16_t build,TVMVersionStage version) { this->build = (build << 2) | version; } - + /** + * @brief Set the Version + * + * @param major The major + * @param minor The minor + * @param patch The patch + * @param build The build + * @param ver The stage + */ void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, TVMVersionStage ver) { this->SetMajor(major); @@ -99,7 +201,14 @@ namespace Tesses::CrossLang { this->SetPatch(patch); this->SetBuild(build,ver); } - + /** + * @brief Set the Version + * + * @param major The major + * @param minor The minor + * @param patch The patch + * @param build The build << 2 | (stage & 3) + */ void SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build) { this->SetMajor(major); @@ -107,15 +216,33 @@ namespace Tesses::CrossLang { this->SetPatch(patch); this->SetBuild(build); } + /** + * @brief Set the Version + * + * @param major The major + * @param minor The minor + * @param patch The patch + * @param buildHigh The build (high 8 bits) + * @param buildLow The build (low 6 bits) << 2 | (stage & 3) + */ 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); } - + /** + * @brief Set the Version + * + * @param versionData same order as SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t buildHigh, uint8_t buildLow) but is a pointer to uint8_t version[5] + */ void SetVersion(uint8_t* versionData) { this->SetVersion(versionData[0],versionData[1],versionData[2],versionData[3],versionData[4]); } + /** + * @brief Set the version from long + * + * @param v version serialized as long + */ void SetFromLong(uint64_t v) { @@ -124,6 +251,11 @@ namespace Tesses::CrossLang { this->patch = (uint8_t)(v >> 16) & 0xFF; this->build = (uint16_t)(v & 0xFFFF); } + /** + * @brief Encodes the version to bytes to be decoded by SetVersion(uint8_t*) or the constructor + * + * @param versionData an array that is 5 bytes long + */ void ToArray(uint8_t* versionData) { versionData[0] = major; @@ -132,14 +264,32 @@ namespace Tesses::CrossLang { versionData[3] = build >> 8; versionData[4] = build & 0xFF; } + /** + * @brief Construct a new Version object + * + * @param major Major + * @param minor Minor + * @param patch Patch + * @param build Build + * @param version Stage (dev, alpha, beta, prod) see TVMVersionStage for actual names + */ TVMVersion(uint8_t major, uint8_t minor, uint8_t patch, uint16_t build, TVMVersionStage version) { this->SetVersion(major,minor,patch,build,version); } + /** + * @brief Construct a new Version object + * + * @param versionData same order as SetVersion(uint8_t major, uint8_t minor, uint8_t patch, uint8_t buildHigh, uint8_t buildLow) but is a pointer to uint8_t version[5] + */ TVMVersion(uint8_t* versionData) { this->SetVersion(versionData); } + /** + * @brief Construct a new 1.0.0.0-dev Version object + * + */ TVMVersion() { this->major=1; @@ -147,10 +297,21 @@ namespace Tesses::CrossLang { this->patch=0; this->SetBuild(0, TVMVersionStage::DevVersion); } + /** + * @brief Construct a new Version object from a long + * + * @param v version serialized as long + */ TVMVersion(uint64_t v) { this->SetFromLong(v); } + /** + * @brief Compares to another version + * + * @param version another version object + * @return int returns 1 if this is newer than other version, 0 if same, -1 if this is older than other version + */ int CompareTo(TVMVersion& version) { if(this->major > version.major) return 1; @@ -163,7 +324,11 @@ namespace Tesses::CrossLang { if(this->build < version.build) return -1; return 0; } - + /** + * @brief Serializes to a long + * + * @return uint64_t serialized as a long + */ uint64_t AsLong() { uint64_t v = (uint64_t)major << 32; @@ -172,11 +337,24 @@ namespace Tesses::CrossLang { v |= (uint64_t)build; return v; } + /** + * @brief Compares this to the runtime version + * + * @return int CompareTo(RuntimeVersion) where RuntimeVersion is the runtime version + */ int CompareToRuntime() { TVMVersion version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE); return CompareTo(version); } + /** + * @brief Try to parse the version from a string + * + * @param versionStr the version string like 1.0.0.0-prod (or dev, alpha, beta) + * @param version a reference to a version + * @return true the parsing succeeded + * @return false the parsing failed + */ static bool TryParse(std::string versionStr, TVMVersion& version) { if(versionStr.empty()) return false; @@ -264,7 +442,11 @@ namespace Tesses::CrossLang { return true; } - + /** + * @brief Converts version to string + * + * @return std::string the version string like 1.0.0.0-prod (or dev, alpha, beta) + */ std::string ToString() { std::string str={}; @@ -295,13 +477,32 @@ namespace Tesses::CrossLang { } }; - + /** + * @brief Create a crvm archive file + * + * @param vfs the filesystem used as root of the archive + * @param strm the output stream + * @param name the crvm name + * @param version the crvm version + * @param info the crvm info + * @param icon the crvm icon + */ void CrossArchiveCreate(Tesses::Framework::Filesystem::VFS* vfs,Tesses::Framework::Streams::Stream* strm,std::string name,TVMVersion version,std::string info, std::string icon=""); + /** + * @brief + * + * @param strm the input stream + * @param vfs vfs to extract to (as root) + * @return std::pair,std::string> ((name, version),info) + */ std::pair,std::string> CrossArchiveExtract(Tesses::Framework::Streams::Stream* strm,Tesses::Framework::Filesystem::VFS* vfs); - +/** + * @brief The token type for lexer + * + */ typedef enum { Identifier, Symbol, @@ -309,36 +510,97 @@ typedef enum { Char, Documentation } LexTokenType; - + /** + * @brief The line info for lextoken + * + */ class LexTokenLineInfo { public: + /** + * @brief line number + * + */ int line; + /** + * @brief column number + * + */ int column; + /** + * @brief byte offset in file + * + */ int offset; + /** + * @brief filename + * + */ std::string filename; + /** + * @brief Add a char + * + * @param c a char to add to line, column, offset + */ void Add(int c); + /** + * @brief Subtract from column and offset + * + * @param c the number of chars + */ void Subtract(size_t c); }; - + /** + * @brief The lextoken for lexer + * + */ class LexToken { public: + /** + * @brief line information + * + */ LexTokenLineInfo lineInfo; + /** + * @brief the token type + * + */ LexTokenType type; + /** + * @brief the token text + * + */ std::string text; + /** + * @brief any white space characters before this token + * + */ std::string whiteSpaceCharsBefore; }; + /** + * @brief Start lexing the file + * + * @param filename the filename used for exception purposes + * @param strm the character stream + * @param tokens the tokens + * @return int 0 on success, line number on failure + */ int Lex(std::string filename, std::istream& strm, std::vector& tokens); - +/** + * @brief Undefined type + * + */ class Undefined { }; - class AdvancedSyntaxNode; - +/** + * @brief Bytecode instruction enumeration + * + */ typedef enum { ADD, SUB, @@ -396,30 +658,94 @@ typedef enum { PUSHSCOPELESSCLOSURE, YIELD, PUSHROOTPATH, - PUSHRELATIVEPATH + PUSHRELATIVEPATH, + BREAKPOINT } Instruction; - +/** + * @brief Base type for bytecode instruction + * + */ class ByteCodeInstruction { public: + /** + * @brief Size of instruction + * + * @return size_t the length of the instruction + */ virtual size_t Size()=0; + /** + * @brief Write the instruction to vector + * + * @param data the vector of uint8_t + */ virtual void Write(std::vector& data)=0; virtual ~ByteCodeInstruction() {} }; - +/** + * @brief Basic bytecode instruction + * + */ class SimpleInstruction : public ByteCodeInstruction { public: + /** + * @brief The instruction + * + */ Instruction instruction; + /** + * @brief Construct a new Simple Instruction object + * + * @param instr the instruction + */ SimpleInstruction(Instruction instr); + /** + * @brief Size of instruction + * + * @return size_t 1, because simple instructions are just an instruction + */ size_t Size(); + /** + * @brief Write the opcode to the vector + * + * @param data the vector of uint8_t + */ void Write(std::vector& data); }; +/** + * @brief A bit converter + * + */ class BitConverter { public: + /** + * @brief Get the bits of a double from a int64_t + * + * @param v a int64_t with double's bits + * @return double the double + */ static double ToDoubleBits(uint64_t v); + /** + * @brief Get the bits of a int64_t from a double + * + * @param v a double with int64_t's bits + * @return uint64_t the int64_t + */ static uint64_t ToUintBits(double v); + /** + * @brief Get big endian double from uint8_t reference of first element of 8 byte array + * + * @param b a reference to the first byte of an array + * @return double the double + */ static double ToDoubleBE(uint8_t& b); + /** + * @brief Get big endian uint64_t from uint8_t reference of first element of 8 byte array + * + * @param b a reference to the first byte of an array + * @return uint64_t the uint64_t + */ static uint64_t ToUint64BE(uint8_t& b); static uint32_t ToUint32BE(uint8_t& b); static uint16_t ToUint16BE(uint8_t& b); @@ -528,6 +854,7 @@ class CodeGen { void GetFunctionArgs(std::vector& args,SyntaxNode n); void GetFunctionName(std::vector& name,SyntaxNode n); void GetFunctionArgs(std::vector& args,SyntaxNode n); + SyntaxNode StringifyListOfVars(SyntaxNode n); uint32_t GetString(std::string str); uint32_t GetResource(std::string res); @@ -537,6 +864,7 @@ class CodeGen { std::vector, std::vector>> chunks; std::vector,uint32_t>> funcs; std::vector objectEntries; + void GenNode(std::vector& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI); void GenPop(std::vector& instrs,SyntaxNode n); public: @@ -550,87 +878,381 @@ class CodeGen { void Save(Tesses::Framework::Filesystem::VFS* embedFS,Tesses::Framework::Streams::Stream* output); ~CodeGen(); }; - +/** + * @brief A html expression + * + */ constexpr std::string_view HtmlRootExpression = "htmlRootExpression"; +/** + * @brief an intrinsic function that embeads a resource from the filename based on the constant string argument + * + */ constexpr std::string_view EmbedExpression = "embedExpression"; +/** + * @brief Negative operator -EXPR + * + */ constexpr std::string_view NegativeExpression = "negativeExpression"; +/** + * @brief Not operator !EXPR + * + */ constexpr std::string_view NotExpression = "notExpression"; +/** + * @brief Bitwise not operator ~EXPR + * + */ constexpr std::string_view BitwiseNotExpression = "bitwiseNotExpression"; +/** + * @brief ++i + * + */ constexpr std::string_view PrefixIncrementExpression = "prefixIncrementExpression"; +/** + * @brief --i + * + */ constexpr std::string_view PrefixDecrementExpression = "prefixDecrementExpression"; +/** + * @brief i++ + * + */ constexpr std::string_view PostfixIncrementExpression = "postfixIncrementExpression"; +/** + * @brief i-- + * + */ constexpr std::string_view PostfixDecrementExpression = "postfixDecrementExpression"; +/** + * @brief Gets variable value + * + */ constexpr std::string_view GetVariableExpression = "getVariableExpression"; +/** + * @brief Get field or get property (EXPR.getNAME()) (unless it is wrapped in AssignExpression) which then it sets the field or calls EXPR.setNAME(VALUE) + * + */ constexpr std::string_view GetFieldExpression = "getFieldExpression"; +/** + * @brief Syntax sugar for EXPR.GetAt(index) (unless it is wrapped in AssignExpresion) which then it is EXPR.SetAt(index, VALUE) + * + */ constexpr std::string_view GetArrayExpression = "getArrayExpression"; +/** + * @brief Function Call myFn() or MyDict.Fn() + * + */ constexpr std::string_view FunctionCallExpression = "functionCallExpression"; +/** + * @brief Used for compound assignment like VAR += EXPR + * + */ constexpr std::string_view CompoundAssignExpression = "compoundAssignExpression"; +/** + * @brief Assign something using = + * + */ constexpr std::string_view AssignExpression = "assignExpression"; +/** + * @brief A char litteral + * + */ constexpr std::string_view CharExpression = "charExpression"; +/** + * @brief The undefined literal + * + */ constexpr std::string_view UndefinedExpression = "undefinedExpression"; +/** + * @brief A list of nodes that does create a new scope + * + */ constexpr std::string_view ScopeNode = "scopeNode"; +/** + * @brief A list of nodes that doesn't create a new scope + * + */ constexpr std::string_view NodeList = "nodeList"; - +/** + * @brief Array expresion [1,2,10] + * + */ constexpr std::string_view ArrayExpression = "arrayExpression"; +/** + * @brief Dictionary expression { a = 42, b = false} + * + */ constexpr std::string_view DictionaryExpression = "dictionaryExpression"; +/** + * @brief var v = 59; + * + */ constexpr std::string_view DeclareExpression = "declareExpression"; - +/** + * @brief Closure expression (a,b)=> a * b + * + */ constexpr std::string_view ClosureExpression = "closureExpression"; +/** + * @brief Just like normal closures but doesn't create its own scope + * + */ constexpr std::string_view ScopelessClosureExpression = "scopelessClosureExpression"; - +/** + * @brief Ternary operator COND ? EXPR : EXPR + * + */ constexpr std::string_view TernaryExpression = "ternaryExpression"; +/** + * @brief If statement if(COND) {} else if(COND) {} else {} + * + */ constexpr std::string_view IfStatement = "ifStatement"; +/** + * @brief For statement for(var i = 0; i < 42; i++) + * + */ constexpr std::string_view ForStatement = "forStatement"; +/** + * @brief While statement while(COND) + * + */ constexpr std::string_view WhileStatement = "whileStatement"; +/** + * @brief Do statement do(COND) + * + */ constexpr std::string_view DoStatement = "doStatement"; +/** + * @brief Each statement each(var item : EXPR) + * + */ constexpr std::string_view EachStatement = "eachStatement"; +/** + * @brief Return statement return EXPR; + * + */ constexpr std::string_view ReturnStatement = "returnStatement"; +/** + * @brief Break statement break; + * + */ constexpr std::string_view BreakStatement = "breakStatement"; +/** + * @brief Continue statement continue; + * + */ constexpr std::string_view ContinueStatement = "continueStatement"; +/** + * @brief Function statement func main(args) + * + */ constexpr std::string_view FunctionStatement = "functionStatement"; +/** + * @brief The documentation statement /^ Documentation ^/ func main(args) {} + * + */ constexpr std::string_view DocumentationStatement = "documentationStatement"; +/** + * @brief The comma expression EXPR, EXPR + * + */ constexpr std::string_view CommaExpression = "commaExpression"; - +/** + * @brief The addition operator EXPR + EXPR + * + */ constexpr std::string_view AddExpression = "addExpression"; +/** + * @brief The subtraction operator EXPR - EXPR + * + */ constexpr std::string_view SubExpression = "subtractExpression"; +/** + * @brief The times operator EXPR * EXPR + * + */ constexpr std::string_view TimesExpression = "timesExpression"; +/** + * @brief The divsion operator EXPR / EXPR + * + */ constexpr std::string_view DivideExpression = "divideExpression"; +/** + * @brief The modulo operator (get remainder) EXPR % EXPR + * + */ constexpr std::string_view ModExpression = "modExpression"; +/** + * @brief The left shift operator EXPR << EXPR + * + */ constexpr std::string_view LeftShiftExpression = "leftShiftExpression"; +/** + * @brief The right shift operator EXPR >> EXPR + * + */ constexpr std::string_view RightShiftExpression = "rightShiftExpression"; +/** + * @brief The bitwise or expression EXPR | EXPR + * + */ constexpr std::string_view BitwiseOrExpression = "bitwiseOrExpression"; +/** + * @brief The bitwise and expression EXPR & EXPR + * + */ constexpr std::string_view BitwiseAndExpression = "bitwiseAndExpression"; - +/** + * @brief The xor expression EXPR ^ EXPR + * + */ constexpr std::string_view XOrExpression = "xOrExpression"; +/** + * @brief The logical or expression EXPR || EXPR + * + */ constexpr std::string_view LogicalOrExpression = "logicalOrExpression"; +/** + * @brief The logical and expression EXPR && EXPR + * + */ constexpr std::string_view LogicalAndExpression = "logicalAndExpression"; - +/** + * @brief The equals expression EXPR == EXPR + * + */ constexpr std::string_view EqualsExpression = "equalsExpression"; +/** + * @brief The not equals expression EXPR != EXPR + * + */ constexpr std::string_view NotEqualsExpression = "notEqualsExpression"; +/** + * @brief The less than expression EXPR < EXPR + * + */ constexpr std::string_view LessThanExpression = "lessThanExpression"; +/** + * @brief The greater than expression EXPR > EXPR + * + */ constexpr std::string_view GreaterThanExpression = "greaterThanExpression"; +/** + * @brief The less than equals expression EXPR <= EXPR + * + */ constexpr std::string_view LessThanEqualsExpression = "lessThanEqualsExpression"; +/** + * @brief The greater than equals expression EXPR >= EXPR + * + */ constexpr std::string_view GreaterThanEqualsExpression = "greaterThanEqualsExpression"; +/** + * @brief The parentheses expression (expression) + * + */ constexpr std::string_view ParenthesesExpression = "parenthesesExpression"; +/** + * @brief The throw statement + * + */ constexpr std::string_view ThrowStatement = "throwStatement"; +/** + * @brief The breakpoint statement + */ +constexpr std::string_view BreakpointStatement = "breakpointStatement"; +/** + * @brief The try statement + * + */ constexpr std::string_view TryStatement = "tryStatement"; +/** + * @brief The defer statement + * + */ constexpr std::string_view DeferStatement = "deferStatement"; +/** + * @brief The defer statement + * + */ constexpr std::string_view YieldStatement = "yieldStatement"; +/** + * @brief The enumerable statement + * + */ constexpr std::string_view EnumerableStatement = "enumerableStatement"; +/** + * @brief The switch statement + * + */ constexpr std::string_view SwitchStatement = "switchStatement"; +/** + * @brief Case clause of switch statement + * + */ constexpr std::string_view CaseStatement = "caseStatement"; +/** + * @brief Default clause of switch statement + * + */ constexpr std::string_view DefaultStatement = "defaultStatement"; +/** + * @brief Object statement (like class but not having inheritence) (not implemented) + * + */ constexpr std::string_view ObjectStatement = "objectStatement"; +/** + * @brief Static statement (static methods in object statement) + * + */ constexpr std::string_view StaticStatement = "staticStatement"; -constexpr std::string_view MethodDeclaration = "methodDeclaration"; -constexpr std::string_view RootPathExpression = "rootPathExpression"; -constexpr std::string_view RelativePathExpression = "relativePathExpression"; +/** + * @brief Method declaration method fun() {} in object statement + * + */ + +constexpr std::string_view MethodDeclaration = "methodDeclaration"; +/** + * @brief Root path expression / "path" / "to" / "file" (fullfils the first /) + * + */ +constexpr std::string_view RootPathExpression = "rootPathExpression"; +/** + * @brief The relative path expression ./ "path" / "to" / "subdir" (fullfills the ./) + * + */ +constexpr std::string_view RelativePathExpression = "relativePathExpression"; +/** + * @brief Advanced AST node + * + */ class AdvancedSyntaxNode { public: + /** + * @brief The name of the advanced AST node + * + */ std::string nodeName; + /** + * @brief The advanced syntax node is an expression + * + */ bool isExpression; + /** + * @brief The subnodes of the abstract syntax node + * + */ std::vector nodes; + /** + * @brief Create abstract syntax node + * + * @param nodeName The name of the advanced AST node + * @param isExpression The advanced syntax node is an expression + * @param n The subnodes of the abstract syntax node + * @return AdvancedSyntaxNode The AST node + */ static AdvancedSyntaxNode Create(std::string_view nodeName,bool isExpression, std::vector n); }; @@ -639,7 +1261,10 @@ class AdvancedSyntaxNode { SyntaxNode Deserialize(std::string astData); std::string Serialize(SyntaxNode node); - +/** + * @brief Token Parser + * + */ class Parser { uint32_t id; uint32_t NewId(); @@ -671,7 +1296,17 @@ class Parser { SyntaxNode ParseUnary(); void ParseHtml(std::vector& nodes,std::string var); public: + /** + * @brief Construct a new Parser object + * + * @param tokens the tokens from lexer + */ Parser(std::vector tokens); + /** + * @brief Turn tokens into abstract syntax tree + * + * @return SyntaxNode the abstract syntax tree + */ SyntaxNode ParseRoot() { return ParseNode(true); @@ -713,6 +1348,10 @@ class Parser { class MethodInvoker { }; + /** + * @brief A script object + * + */ using TObject = std::variant; class TRootEnvironment; class GC; @@ -978,6 +1617,7 @@ class GC { class TRootEnvironment : public TEnvironment { TDictionary* dict; + TCallable* error=nullptr; void LoadDependency(GC* gc,Tesses::Framework::Filesystem::VFS* vfs, std::pair dep); public: @@ -999,6 +1639,9 @@ class GC { void DeclareVariable(std::string key, TObject value); TRootEnvironment* GetRootEnvironment(); TEnvironment* GetParentEnvironment(); + void RegisterOnError(TCallable* callable); + bool HandleException(GC* gc,TEnvironment* env, TObject err); + bool HandleBreakpoint(GC* gc,TEnvironment* env, TObject err); void Mark(); }; class TStd { @@ -1036,6 +1679,7 @@ class GC { void DeclareVariable(std::string key, TObject value); TRootEnvironment* GetRootEnvironment(); TEnvironment* GetParentEnvironment(); + TDictionary* GetDictionary(); void Mark(); }; @@ -1412,6 +2056,7 @@ class GC { bool Pop(GC* gc); bool Dup(GC* gc); bool Nop(GC* gc); + bool Breakpoint(GC* gc); public: static InterperterThread* Create(GCList* ls); static InterperterThread* Create(GCList& ls); @@ -1581,6 +2226,8 @@ class GC { } bool GetObjectAsPath(TObject& obj, Tesses::Framework::Filesystem::VFSPath& path, bool allowString=true); bool GetArgumentAsPath(std::vector& args, size_t index, Tesses::Framework::Filesystem::VFSPath& path,bool allowString=true); + bool ToBool(TObject obj); + bool Equals(GC* gc, TObject left, TObject right); typedef void (*PluginFunction)(GC* gc,TRootEnvironment* env); #if !defined(_WIN32) #define DLLEXPORT diff --git a/src/compiler/codegen.cpp b/src/compiler/codegen.cpp index 638ba48..669b7d5 100644 --- a/src/compiler/codegen.cpp +++ b/src/compiler/codegen.cpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace Tesses::CrossLang { void Write(Tesses::Framework::Streams::Stream* strm, uint8_t* buffer, size_t len) @@ -31,6 +32,7 @@ namespace Tesses::CrossLang } } + void CodeGen::Save(Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Streams::Stream* stream) { TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE); @@ -409,6 +411,32 @@ namespace Tesses::CrossLang } #define ONE_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 1) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));} #define TWO_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 2) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));} + + SyntaxNode CodeGen::StringifyListOfVars(SyntaxNode n) + { + if(std::holds_alternative(n)) + { + return n; + } + else if(std::holds_alternative(n)) + { + auto itemA=std::get(n); + if(itemA.nodeName == GetVariableExpression && itemA.nodes.size()==1 && std::holds_alternative(itemA.nodes[0])) + { + return std::get(itemA.nodes[0]); + } + else if(itemA.nodeName == CommaExpression && itemA.nodes.size()==2) + { + return AdvancedSyntaxNode::Create(CommaExpression,true,{StringifyListOfVars(itemA.nodes[0]),StringifyListOfVars(itemA.nodes[1])}); + } + + + + } + return nullptr; + } + + void CodeGen::GenNode(std::vector& instructions, SyntaxNode n,int32_t scope,int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI) { if(std::holds_alternative(n)) @@ -1018,18 +1046,48 @@ namespace Tesses::CrossLang else if(adv.nodeName == AssignExpression && adv.nodes.size() == 2 && std::holds_alternative(adv.nodes[0])) { auto varNode = std::get(adv.nodes[0]); + if(varNode.nodeName == GetVariableExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) { instructions.push_back(new StringInstruction(GetString(std::get(varNode.nodes[0])))); GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); instructions.push_back(new SimpleInstruction(SETVARIABLE)); } + else if(varNode.nodeName == ArrayExpression && varNode.nodes.size() >= 1) + { + + auto vars= StringifyListOfVars(varNode.nodes[0]); + + + auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars}); + + this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI); + GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); + instructions.push_back(new SimpleInstruction(SETVARIABLE)); + } else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) { instructions.push_back(new StringInstruction(GetString(std::get(varNode.nodes[0])))); GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); } + else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative(varNode.nodes[0])) + { + auto adv2 = std::get(varNode.nodes[0]); + + if(adv2.nodeName == ArrayExpression && adv2.nodes.size() == 1) + { + + auto vars= StringifyListOfVars(adv2.nodes[0]); + + auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars}); + + this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI); + GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); + instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); + + } + } else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2 && std::holds_alternative(varNode.nodes[1])) { GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI); @@ -1050,9 +1108,41 @@ namespace Tesses::CrossLang GenNode(instructions,n,scope,contscope,brkscope,contI,brkI); } } - else if(adv.nodeName == ThrowStatement && adv.nodes.size() == 1) + else if(adv.nodeName == BreakpointStatement && adv.nodes.size() == 5) + { + instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); + instructions.push_back(new StringInstruction(GetString("Data"))); + GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Filename"))); + GenNode(instructions,adv.nodes[1] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Line"))); + GenNode(instructions,adv.nodes[2] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Column"))); + GenNode(instructions,adv.nodes[3] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Offset"))); + GenNode(instructions,adv.nodes[4] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new SimpleInstruction(BREAKPOINT)); + } + else if(adv.nodeName == ThrowStatement && adv.nodes.size() == 5) { GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); + instructions.push_back(new StringInstruction(GetString("Filename"))); + GenNode(instructions,adv.nodes[1] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Line"))); + GenNode(instructions,adv.nodes[2] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Column"))); + GenNode(instructions,adv.nodes[3] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); + instructions.push_back(new StringInstruction(GetString("Offset"))); + GenNode(instructions,adv.nodes[4] ,scope,contscope ,brkscope ,contI ,brkI); + instructions.push_back(new SimpleInstruction(APPENDDICT)); instructions.push_back(new SimpleInstruction(THROW)); } else if(adv.nodeName == ReturnStatement && adv.nodes.size() == 1) @@ -1451,4 +1541,4 @@ namespace Tesses::CrossLang instrs.push_back(new SimpleInstruction(POP)); } } -} \ No newline at end of file +} diff --git a/src/compiler/parser.cpp b/src/compiler/parser.cpp index 6c0200c..c71ee48 100644 --- a/src/compiler/parser.cpp +++ b/src/compiler/parser.cpp @@ -588,9 +588,20 @@ namespace Tesses::CrossLang { if(i >= tokens.size()) throw std::out_of_range("End of file"); auto variable = tokens[i]; - i++; - if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); + + i++; + if(variable.type == LexTokenType::Symbol && variable.text == "[") + { + node = AdvancedSyntaxNode::Create(DeclareExpression,true,{ + AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()}) + }); + EnsureSymbol("]"); + } + else if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); + else + { node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text}); + } } else if(IsIdentifier("operator")) { @@ -1189,9 +1200,19 @@ namespace Tesses::CrossLang } if(IsIdentifier("throw")) { + auto tkn2 = tkn; + auto v = ParseExpression(); EnsureSymbol(";"); - return AdvancedSyntaxNode::Create(ThrowStatement,false,{v}); + return AdvancedSyntaxNode::Create(ThrowStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset}); + } + if(IsIdentifier("breakpoint")) + { + auto tkn2 = tkn; + + auto v = ParseExpression(); + EnsureSymbol(";"); + return AdvancedSyntaxNode::Create(BreakpointStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset}); } if(IsIdentifier("try")) { @@ -1355,4 +1376,4 @@ namespace Tesses::CrossLang } return expr; } -} \ No newline at end of file +} diff --git a/src/runtime_methods/env.cpp b/src/runtime_methods/env.cpp index 7eb81ca..69ae8cf 100644 --- a/src/runtime_methods/env.cpp +++ b/src/runtime_methods/env.cpp @@ -13,6 +13,7 @@ namespace Tesses::CrossLang #else static char EnvPathSeperator=':'; #endif + static std::string GetHomeFolder() { #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) diff --git a/src/runtime_methods/std.cpp b/src/runtime_methods/std.cpp index 0881a50..bb66d87 100644 --- a/src/runtime_methods/std.cpp +++ b/src/runtime_methods/std.cpp @@ -204,6 +204,14 @@ namespace Tesses::CrossLang auto strm = dynamic_cast(obj); auto svr = dynamic_cast(obj); auto cse = dynamic_cast(obj); + auto rootEnv = dynamic_cast(obj); + auto subEnv = dynamic_cast(obj); + auto env = dynamic_cast(obj); + + if(rootEnv != nullptr) return "RootEnvironment"; + if(subEnv != nullptr) return "SubEnvironment"; + if(env != nullptr) return "Environment"; + if(cse != nullptr) return "YieldedClosure"; if(dynDict != nullptr) return "DynamicDictionary"; if(dynList != nullptr) return "DynamicList"; @@ -568,6 +576,7 @@ namespace Tesses::CrossLang GCList ls(gc); TDictionary* dict = TDictionary::Create(ls); + TDictionary* gc_dict = TDictionary::Create(ls); dict->DeclareFunction(gc,"LoadNativePlugin","Load a native plugin, requires a dynamic linker and shared build of libcrosslang",{"path"},[gc,env](GCList& ls, std::vector args)->TObject { Tesses::Framework::Filesystem::VFSPath path; if(GetArgumentAsPath(args,0,path)) @@ -576,8 +585,21 @@ namespace Tesses::CrossLang } return nullptr; }); + gc_dict->DeclareFunction(gc,"Collect","Collect garbage",{},[](GCList& ls, std::vector args)->TObject{ + ls.GetGC()->Collect(); + return nullptr; + }); + gc_dict->DeclareFunction(gc,"BarrierBegin","Lock globally",{},[](GCList& ls,std::vector args)->TObject { + ls.GetGC()->BarrierBegin(); + return nullptr; + }); + gc_dict->DeclareFunction(gc, "BarrierEnd","Unlock globally",{},[](GCList& ls, std::vector args)->TObject { + ls.GetGC()->BarrierEnd(); + return nullptr; + }); gc->BarrierBegin(); env->SetVariable("Reflection",dict); + env->SetVariable("GC", gc_dict); gc->BarrierEnd(); env->permissions.locked=true; } diff --git a/src/types/rootenvironment.cpp b/src/types/rootenvironment.cpp index 2117a2e..9be8166 100644 --- a/src/types/rootenvironment.cpp +++ b/src/types/rootenvironment.cpp @@ -208,6 +208,7 @@ namespace Tesses::CrossLang { this->marked = true; this->dict->Mark(); for(auto defer : this->defers) defer->Mark(); + if(this->error != nullptr) this->error->Mark(); } TRootEnvironment* TRootEnvironment::Create(GCList* gc,TDictionary* dict) { @@ -225,4 +226,39 @@ namespace Tesses::CrossLang { _gc->Watch(env); return env; } -}; \ No newline at end of file + + bool TRootEnvironment::HandleException(GC* gc,TEnvironment* env, TObject err) + { + if(error != nullptr) + { + GCList ls(gc); + return ToBool(error->Call(ls, { + TDictionary::Create(ls,{ + TDItem("IsBreakpoint",false), + TDItem("Exception",err), + TDItem("Environment", env) + }) + })); + } + return false; + } + bool TRootEnvironment::HandleBreakpoint(GC* gc,TEnvironment* env, TObject err) + { + if(error != nullptr) + { + GCList ls(gc); + return ToBool(error->Call(ls, { + TDictionary::Create(ls,{ + TDItem("IsBreakpoint",true), + TDItem("Breakpoint",err), + TDItem("Environment", env) + }) + })); + } + return true; + } + void TRootEnvironment::RegisterOnError(TCallable* call) + { + this->error = call; + } +}; diff --git a/src/types/subenvironment.cpp b/src/types/subenvironment.cpp index 6534847..cc68bd4 100644 --- a/src/types/subenvironment.cpp +++ b/src/types/subenvironment.cpp @@ -1,6 +1,10 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { + TDictionary* TSubEnvironment::GetDictionary() + { + return this->dict; + } TObject TSubEnvironment::GetVariable(std::string key) { if(this->dict->HasValue(key)) @@ -144,4 +148,4 @@ namespace Tesses::CrossLang { this->DeclareVariable(key, TExternalMethod::Create(ls,documentation,argNames,cb,destroy)); gc.BarrierEnd(); } -}; \ No newline at end of file +}; diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 803cd7b..5bcc423 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -1,6 +1,7 @@ #include "CrossLang.hpp" #include #include +#include #include #include #include @@ -74,6 +75,170 @@ namespace Tesses::CrossLang { return false; } + + bool Equals(GC* gc, TObject left, TObject right) + { + GCList ls(gc); + if(std::holds_alternative(left) && std::holds_alternative(right)) + { + + return true; + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return true; + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + auto lver= std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + return r == 0; + } + else if(std::holds_alternative(left)) + { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto native = dynamic_cast(obj); + if(dict != nullptr) + { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator=="); + gc->BarrierEnd(); + if(!std::holds_alternative(fn)) + { + if(std::holds_alternative(fn)) + { + + auto obj = dynamic_cast(std::get(fn).obj); + if(obj != nullptr) + { + auto closure = dynamic_cast(obj); + if(closure != nullptr) + { + + if(!closure->closure->args.empty() && closure->closure->args[0] == "this") + { + return ToBool(obj->Call(ls,{left,right})); + } + else + { + return ToBool(obj->Call(ls,{right})); + } + + } + else + { + return ToBool(obj->Call(ls,{right})); + + } + } + + } + + } + return false; + + } + + else if(dynDict != nullptr) + { + auto res = dynDict->CallMethod(ls,"operator==",{right}); + if(!std::holds_alternative(res) && std::holds_alternative(res)) + { + return ToBool(res); + } + } + else if(native != nullptr && std::holds_alternative(right)) + { + return native->GetDestroyed(); + + } + + if(std::holds_alternative(right)) + { + return obj == std::get(right).obj; + + } + + else if(std::holds_alternative(right)) + { + return false; + } + else if(std::holds_alternative(right)) + { + + return false; + } + else + { + return false; + } + + } + + else if(std::holds_alternative(right)) + { + return false; + } + else if(std::holds_alternative(right)) + { + return false; + } + else + { + return false; + + } + + return false; + + } + TObject ExecuteFunction(GCList& ls,TCallable* callable, std::vector args) { return callable->Call(ls,args); @@ -172,6 +337,20 @@ namespace Tesses::CrossLang { this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); return false; } + bool InterperterThread::InterperterThread::Breakpoint(GC* gc) + { + std::vector& cse=this->call_stack_entries; + GCList ls(gc); + auto res = cse.back()->Pop(ls); + + auto env = cse.back()->env; + if(!env->GetRootEnvironment()->HandleBreakpoint(gc, env, res)) + { + throw std::exception(); + } + + return false; + } bool InterperterThread::Sub(GC* gc) { std::vector& cse=this->call_stack_entries; @@ -299,8 +478,11 @@ namespace Tesses::CrossLang { GCList ls(gc); auto right = cse.back()->Pop(ls); auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) + if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,Tesses::Framework::Filesystem::VFSPath(std::get(left)) / std::get(right)); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) { cse.back()->Push(gc,std::get(left) / std::get(right)); @@ -610,6 +792,10 @@ namespace Tesses::CrossLang { auto r = lver.CompareTo(rver); cse.back()->Push(gc, r < 0); } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, std::get(left) < std::get(right)); + } else if(std::holds_alternative(left)) { auto obj = std::get(left).obj; @@ -685,6 +871,10 @@ namespace Tesses::CrossLang { auto r = lver.CompareTo(rver); cse.back()->Push(gc, r > 0); } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, std::get(left) > std::get(right)); + } else if(std::holds_alternative(left)) { auto obj = std::get(left).obj; @@ -759,6 +949,10 @@ namespace Tesses::CrossLang { auto r = lver.CompareTo(rver); cse.back()->Push(gc, r <= 0); } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, std::get(left) <= std::get(right)); + } else if(std::holds_alternative(left)) { auto obj = std::get(left).obj; @@ -834,7 +1028,10 @@ namespace Tesses::CrossLang { auto r = lver.CompareTo(rver); cse.back()->Push(gc, r >= 0); } - + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, std::get(left) >= std::get(right)); + } else if(std::holds_alternative(left)) { auto obj = std::get(left).obj; @@ -2262,6 +2459,8 @@ namespace Tesses::CrossLang { auto strm = dynamic_cast(obj); auto vfs = dynamic_cast(obj); auto env = dynamic_cast(obj); + + auto subEnv = dynamic_cast(obj); auto rootEnv = dynamic_cast(obj); auto callable = dynamic_cast(obj); auto callstackEntry = dynamic_cast(obj); @@ -2369,6 +2568,17 @@ namespace Tesses::CrossLang { //TStd::RegisterSqlite //TStd::RegisterVM auto myEnv = cse.back()->env->GetRootEnvironment(); + + if(key == "RegisterOnError") + { + TCallable* callable; + if(!rootEnv->permissions.locked && GetArgumentHeap(args,0,callable)) + { + gc->BarrierBegin(); + rootEnv->RegisterOnError(callable); + gc->BarrierEnd(); + } + } if(key == "RegisterEverything") { if(myEnv->permissions.canRegisterEverything) @@ -2593,6 +2803,14 @@ namespace Tesses::CrossLang { return false; } } + if(subEnv != nullptr) + { + if(key == "GetDictionary") + { + cse.back()->Push(gc,subEnv->GetDictionary()); + return false; + } + } if(env != nullptr) { @@ -2614,6 +2832,7 @@ namespace Tesses::CrossLang { cse.back()->Push(gc,env->GetRootEnvironment()); return false; } + if(key == "GetSubEnvironment") { cse.back()->Push(gc,env->GetSubEnvironment(ls)); @@ -3573,6 +3792,48 @@ namespace Tesses::CrossLang { cse.back()->Push(gc, Undefined()); return false; } + if(key == "RemoveAllEqual") + { + if(args.size() != 1) + { + throw VMException("List.RemoveAllEqual must only accept one argument"); + } + + + gc->BarrierBegin(); + for(int64_t i = 0; i < list->Count(); i++) + { + if(Equals(gc,args[0],list->Get(i))) + { + list->RemoveAt(i); + i--; + } + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } + if(key == "Remove") + { + if(args.size() != 1) + { + throw VMException("List.Remove must only accept one argument"); + } + + + gc->BarrierBegin(); + for(int64_t i = 0; i < list->Count(); i++) + { + if(Equals(gc,args[0],list->Get(i))) + { + list->RemoveAt(i); + break; + } + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } if(key == "RemoveAt") { if(args.size() != 1) @@ -4290,6 +4551,7 @@ namespace Tesses::CrossLang { GCList ls(gc); auto value = stk->Pop(ls); auto key = stk->Pop(ls); + TList* mls; if(std::holds_alternative(key)) { gc->BarrierBegin(); @@ -4297,6 +4559,105 @@ namespace Tesses::CrossLang { stk->Push(gc, value); gc->BarrierEnd(); } + else if(GetObjectHeap(key,mls)) + { + gc->BarrierBegin(); + + TList* valueLs; + TDynamicList* valueDynList; + TDictionary* valueDict; + TDynamicDictionary* valueDynDict; + if(GetObjectHeap(value, valueLs)) + { + TDictionary* result = TDictionary::Create(ls); + int64_t len = std::min(valueLs->Count(), mls->Count()); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + auto val = valueLs->Get(i); + result->SetValue(mkey, val); + stk->env->SetVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else if(GetObjectHeap(value, valueDynList)) + { + TDictionary* result = TDictionary::Create(ls); + gc->BarrierEnd(); + int64_t len = std::min(valueDynList->Count(ls), mls->Count()); + gc->BarrierBegin(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + gc->BarrierEnd(); + auto val = valueDynList->GetAt(ls,i); + gc->BarrierBegin(); + result->SetValue(mkey, val); + stk->env->SetVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else if(GetObjectHeap(value, valueDict)) + { + + TDictionary* result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + auto val = valueDict->GetValue(mkey); + result->SetValue(mkey, val); + stk->env->SetVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else if(GetObjectHeap(value, valueDynDict)) + { + TDictionary* result = TDictionary::Create(ls); + int64_t len =mls->Count(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + gc->BarrierEnd(); + auto val = valueDynDict->GetField(ls,mkey); + gc->BarrierBegin(); + + result->SetValue(mkey, val); + stk->env->SetVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else { + int64_t len =mls->Count(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + stk->env->SetVariable(mkey, value); + } + } + stk->Push(gc, value); + } + gc->BarrierEnd(); + } else { throw VMException("[SETVARIABLE] Can't pop string."); @@ -4314,6 +4675,8 @@ namespace Tesses::CrossLang { auto value = stk->Pop(ls); auto key = stk->Pop(ls); + + TList* mls; if(std::holds_alternative(key)) { @@ -4322,6 +4685,105 @@ namespace Tesses::CrossLang { stk->Push(gc, value); gc->BarrierEnd(); } + else if(GetObjectHeap(key,mls)) + { + gc->BarrierBegin(); + + TList* valueLs; + TDynamicList* valueDynList; + TDictionary* valueDict; + TDynamicDictionary* valueDynDict; + if(GetObjectHeap(value, valueLs)) + { + TDictionary* result = TDictionary::Create(ls); + int64_t len = std::min(valueLs->Count(), mls->Count()); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + auto val = valueLs->Get(i); + result->SetValue(mkey, val); + stk->env->DeclareVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else if(GetObjectHeap(value, valueDynList)) + { + TDictionary* result = TDictionary::Create(ls); + gc->BarrierEnd(); + int64_t len = std::min(valueDynList->Count(ls), mls->Count()); + gc->BarrierBegin(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + gc->BarrierEnd(); + auto val = valueDynList->GetAt(ls,i); + gc->BarrierBegin(); + result->SetValue(mkey, val); + stk->env->DeclareVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else if(GetObjectHeap(value, valueDict)) + { + + TDictionary* result = TDictionary::Create(ls); + int64_t len = mls->Count(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + auto val = valueDict->GetValue(mkey); + result->SetValue(mkey, val); + stk->env->DeclareVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else if(GetObjectHeap(value, valueDynDict)) + { + TDictionary* result = TDictionary::Create(ls); + int64_t len =mls->Count(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + gc->BarrierEnd(); + auto val = valueDynDict->GetField(ls,mkey); + gc->BarrierBegin(); + + result->SetValue(mkey, val); + stk->env->DeclareVariable(mkey,val); + } + } + stk->Push(gc,result); + } + else { + int64_t len =mls->Count(); + for(int64_t i = 0; i < len; i++) + { + std::string mkey; + auto item = mls->Get(i); + if(GetObject(item,mkey)) + { + stk->env->DeclareVariable(mkey, value); + } + } + stk->Push(gc, value); + } + gc->BarrierEnd(); + } else { throw VMException("[DECLAREVARIABLE] Can't pop string."); @@ -4368,6 +4830,8 @@ namespace Tesses::CrossLang { if(!std::holds_alternative(_res2)) { + auto env = cse.back()->env; + if(!env->GetRootEnvironment()->HandleException(gc,env, _res2)) throw VMByteCodeException(gc,_res2); } return false; diff --git a/src/vm/vm_opcode_table.h b/src/vm/vm_opcode_table.h index 9f7b35e..3c90211 100644 --- a/src/vm/vm_opcode_table.h +++ b/src/vm/vm_opcode_table.h @@ -1,3 +1,3 @@ #if defined(VM_OPCODE_TABLE_INLINE) -static opcode opcodes[256]={&InterperterThread::Add, &InterperterThread::Sub, &InterperterThread::Times, &InterperterThread::Divide, &InterperterThread::Mod, &InterperterThread::LShift, &InterperterThread::RShift, &InterperterThread::BOr, &InterperterThread::BAnd, &InterperterThread::BNot, &InterperterThread::Lt, &InterperterThread::Gt, &InterperterThread::Lte, &InterperterThread::Gte, &InterperterThread::Eq, &InterperterThread::NEq, &InterperterThread::LNot, &InterperterThread::Neg, &InterperterThread::XOr, &InterperterThread::Pop, &InterperterThread::Dup,&InterperterThread::Nop, &InterperterThread::PushClosure, &InterperterThread::CreateDictionary, &InterperterThread::CreateArray, &InterperterThread::AppendList, &InterperterThread::AppendDictionary, &InterperterThread::PushResource, &InterperterThread::PushLong, &InterperterThread::PushChar, &InterperterThread::PushDouble, &InterperterThread::PushString, &InterperterThread::PushNull, &InterperterThread::PushUndefined, &InterperterThread::ScopeBegin, &InterperterThread::ScopeEnd, &InterperterThread::ScopeEndTimes, &InterperterThread::PushFalse, &InterperterThread::PushTrue, &InterperterThread::SetVariable, &InterperterThread::GetVariable, &InterperterThread::DeclareVariable, &InterperterThread::SetField, &InterperterThread::GetField, &InterperterThread::ExecuteFunction, &InterperterThread::ExecuteMethod, &InterperterThread::Return, &InterperterThread::JumpConditional, &InterperterThread::Jump, &InterperterThread::JumpUndefined, &InterperterThread::Defer, &InterperterThread::TryCatch, &InterperterThread::Throw, &InterperterThread::PushScopelessClosure, &InterperterThread::Yield, &InterperterThread::PushRootPath, &InterperterThread::PushRelativePath, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal}; -#endif \ No newline at end of file +static opcode opcodes[256]={&InterperterThread::Add, &InterperterThread::Sub, &InterperterThread::Times, &InterperterThread::Divide, &InterperterThread::Mod, &InterperterThread::LShift, &InterperterThread::RShift, &InterperterThread::BOr, &InterperterThread::BAnd, &InterperterThread::BNot, &InterperterThread::Lt, &InterperterThread::Gt, &InterperterThread::Lte, &InterperterThread::Gte, &InterperterThread::Eq, &InterperterThread::NEq, &InterperterThread::LNot, &InterperterThread::Neg, &InterperterThread::XOr, &InterperterThread::Pop, &InterperterThread::Dup,&InterperterThread::Nop, &InterperterThread::PushClosure, &InterperterThread::CreateDictionary, &InterperterThread::CreateArray, &InterperterThread::AppendList, &InterperterThread::AppendDictionary, &InterperterThread::PushResource, &InterperterThread::PushLong, &InterperterThread::PushChar, &InterperterThread::PushDouble, &InterperterThread::PushString, &InterperterThread::PushNull, &InterperterThread::PushUndefined, &InterperterThread::ScopeBegin, &InterperterThread::ScopeEnd, &InterperterThread::ScopeEndTimes, &InterperterThread::PushFalse, &InterperterThread::PushTrue, &InterperterThread::SetVariable, &InterperterThread::GetVariable, &InterperterThread::DeclareVariable, &InterperterThread::SetField, &InterperterThread::GetField, &InterperterThread::ExecuteFunction, &InterperterThread::ExecuteMethod, &InterperterThread::Return, &InterperterThread::JumpConditional, &InterperterThread::Jump, &InterperterThread::JumpUndefined, &InterperterThread::Defer, &InterperterThread::TryCatch, &InterperterThread::Throw, &InterperterThread::PushScopelessClosure, &InterperterThread::Yield, &InterperterThread::PushRootPath, &InterperterThread::PushRelativePath, &InterperterThread::Breakpoint, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal, &InterperterThread::Illegal}; +#endif