diff --git a/cpp/core/core_includes.h b/cpp/core/core_includes.h index 9cd0202..d52b3d6 100644 --- a/cpp/core/core_includes.h +++ b/cpp/core/core_includes.h @@ -27,11 +27,13 @@ namespace std { // This module is part of Layer 2B (Host C# Compatibility Layer) #define CORE_LAYER_2B +#ifdef __GNUC__ // Disable the "unused parameter" warning. Some of our transpiled classes // (particularly the ASTNode and Parselet hierarchies) make extensive use // of virtual methods, and in many cases, don't need all the parameters, // but C# does not allow us to leave such parameters unnamed. #pragma GCC diagnostic ignored "-Wunused-parameter" +#endif /* defined(__GNUC__) */ // Data types which, in C#, are all defined in System. // C# code should use these instead of the shortcuts (int, byte, long, etc.) diff --git a/cs/App.cs b/cs/App.cs index 5b7e5b7..f315ba0 100644 --- a/cs/App.cs +++ b/cs/App.cs @@ -31,6 +31,13 @@ #ifndef _WIN32 #include #endif +#ifdef _WIN32 +#include +// POSIX setenv stub +// Contract: we always ignore the return value and always want to overwrite a previous value +// ^^^^^^^^^ if either of these things change in the below code, this will need rewritten +void setenv(const char *name, const char *value, int overwrite) { SetEnvironmentVariableA(name, value); } +#endif using namespace MiniScript; *** END CPP_ONLY ***/ diff --git a/cs/Assembler.cs b/cs/Assembler.cs index 0c4c2e9..1e74211 100644 --- a/cs/Assembler.cs +++ b/cs/Assembler.cs @@ -589,7 +589,7 @@ public UInt32 AddLine(String line, Int32 lineNumber) { Byte reserveRegs = (Byte)ParseInt16(parts[1]); // ToDo: check range before typecast constantValue = ParseAsConstant(parts[2]); if (!is_string(constantValue)) { - Error(StringUtils.Format("Function name must be a string")); + Error("Function name must be a string"); return 0; } Int32 constIdx = AddConstant(constantValue); diff --git a/cs/GCManager.cs b/cs/GCManager.cs index 34f4508..16f3537 100644 --- a/cs/GCManager.cs +++ b/cs/GCManager.cs @@ -280,6 +280,7 @@ public static GCHandle GetHandle(Value v) { return Handles.Get(value_item_index(v)); } + //*** BEGIN CS_ONLY *** // ── Static helper for content-based string access ───────────────────────── // Used by GCMap for content-based key hashing and equality. // (Or is it? ToDo: see if this is still needed.) @@ -300,6 +301,7 @@ public static String GetStringContent(Value v) { } return ""; } + //*** END CS_ONLY *** } } diff --git a/cs/IOHelper.cs b/cs/IOHelper.cs index 5914930..7cd3989 100644 --- a/cs/IOHelper.cs +++ b/cs/IOHelper.cs @@ -9,6 +9,49 @@ // CPP: #include // CPP: #include +/*** BEGIN CPP_ONLY *** +#ifdef _WIN32 // define POSIX getline if on Windows +#include +#include + +int getline(char** lineptr, size_t* n, FILE* stream) { + if (!lineptr || !n || !stream) return -1; + + size_t pos = 0; + + // Allocate if needed + if (*lineptr == nullptr || *n == 0) { + *n = 128; + *lineptr = (char*)malloc(*n); + if (!*lineptr) return -1; + } + + int c; + while ((c = fgetc(stream)) != EOF) { + // Grow buffer if needed + if (pos + 1 >= *n) { + size_t new_size = *n * 2; + char* new_ptr = (char*)realloc(*lineptr, new_size); + if (!new_ptr) return -1; + *lineptr = new_ptr; + *n = new_size; + } + + (*lineptr)[pos++] = (char)c; + + if (c == '\n') break; + } + + if (pos == 0 && c == EOF) { + return -1; // EOF with no data + } + + (*lineptr)[pos] = '\0'; + return (int)pos; +} +#endif // defined(_WIN32) +*** END CPP_ONLY ***/ + namespace MiniScript { public enum TextStyle : Int32 { diff --git a/cs/IntrinsicAPI.cs b/cs/IntrinsicAPI.cs index a954e73..a1bdd65 100644 --- a/cs/IntrinsicAPI.cs +++ b/cs/IntrinsicAPI.cs @@ -57,7 +57,7 @@ public Value GetVar(String variableName) { return vm.LookupParamByName(variableName); } - public Interpreter Interpreter() { + public Interpreter GetInterpreter() { return vm.GetInterpreter(); } } diff --git a/cs/ShellIntrinsics.cs b/cs/ShellIntrinsics.cs index f1fc9e3..284d080 100644 --- a/cs/ShellIntrinsics.cs +++ b/cs/ShellIntrinsics.cs @@ -52,12 +52,12 @@ #include #endif #define PATHSEP "/" + extern "C" { + extern char **environ; + } #endif #include #include -extern "C" { - extern char **environ; -} *** END CPP_ONLY ***/ namespace MiniScript { @@ -1088,7 +1088,7 @@ struct tm t; localtime_r(&stats.st_mtime, &t); #endif #endif - char dateBuf[32]; + char dateBuf[72]; snprintf(dateBuf, sizeof(dateBuf), "%04d-%02d-%02d %02d:%02d:%02d", 1900 + t.tm_year, 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); Value result = make_map(4); diff --git a/cs/VM.cs b/cs/VM.cs index ded456b..a87db32 100644 --- a/cs/VM.cs +++ b/cs/VM.cs @@ -9,6 +9,7 @@ // H: #include "ErrorTypes.g.h" // H: #include "value_map.h" // H: #include +// H: #include // H: #include "GCManager.g.h" // CPP: #include "value_list.h" // CPP: #include "value_string.h" diff --git a/cs/VMVis.cs b/cs/VMVis.cs index 69d6301..78d37e6 100644 --- a/cs/VMVis.cs +++ b/cs/VMVis.cs @@ -61,8 +61,15 @@ public void UpdateScreenSize() { //*** END CS_ONLY *** /*** BEGIN CPP_ONLY *** #ifdef _WIN32 - _screenWidth = csbi.srWindow.Right - csbi.srWindow.Left + 1; - _screenHeight = rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + HANDLE hStdout; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if ((hStdout = GetStdHandle(STD_OUTPUT_HANDLE))!=INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbi)) { + _screenWidth = csbi.srWindow.Right - csbi.srWindow.Left + 1; + _screenHeight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + } else { + _screenWidth = 80; + _screenHeight = 24; + } #else struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); diff --git a/generated/App.g.cpp b/generated/App.g.cpp index c84118f..cc1dc2d 100644 --- a/generated/App.g.cpp +++ b/generated/App.g.cpp @@ -27,6 +27,13 @@ #ifndef _WIN32 #include #endif +#ifdef _WIN32 +#include +// POSIX setenv stub +// Contract: we always ignore the return value and always want to overwrite a previous value +// ^^^^^^^^^ if either of these things change in the below code, this will need rewritten +void setenv(const char *name, const char *value, int overwrite) { SetEnvironmentVariableA(name, value); } +#endif using namespace MiniScript; int main(int argc, const char* argv[]) { diff --git a/generated/Assembler.g.cpp b/generated/Assembler.g.cpp index 173db85..61ba46a 100644 --- a/generated/Assembler.g.cpp +++ b/generated/Assembler.g.cpp @@ -555,7 +555,7 @@ UInt32 AssemblerStorage::AddLine(String line,Int32 lineNumber) { Byte reserveRegs = (Byte)ParseInt16(parts[1]); // ToDo: check range before typecast constantValue = ParseAsConstant(parts[2]); if (!is_string(constantValue)) { - Error(StringUtils::Format("Function name must be a string")); + Error("Function name must be a string"); return 0; } Int32 constIdx = AddConstant(constantValue); @@ -771,6 +771,7 @@ String AssemblerStorage::ParseLabel(String token) { return token.Substring(0, token.Length()-1); } bool AssemblerStorage::AddFunction(String functionName) { + if (HasFunction(functionName)) { IOHelper::Print(StringUtils::Format("ERROR: Function {0} is defined multiple times", functionName)); return Boolean(false); diff --git a/generated/Bytecode.g.cpp b/generated/Bytecode.g.cpp index d6f5b03..d1c177c 100644 --- a/generated/Bytecode.g.cpp +++ b/generated/Bytecode.g.cpp @@ -18,6 +18,7 @@ EmitPattern BytecodeUtil::GetEmitPattern(Opcode opcode) { // _rA_rB_rC, _rA_rB_iC, _rA_iB_rC, _iA_rB_iC, _rA_rB_kC, _rA_rB (two registers) if (mnemonic.Contains("_rA_rB_rC") || mnemonic.Contains("_rA_rB_iC") || mnemonic.Contains("_rA_iB_rC") || mnemonic.Contains("_iA_rB_iC") || + mnemonic.Contains("_rA_rB_kC") || mnemonic.EndsWith("_rA_rB")) { return EmitPattern::ABC; } diff --git a/generated/CodeGenerator.g.cpp b/generated/CodeGenerator.g.cpp index a5bff1a..2a292cf 100644 --- a/generated/CodeGenerator.g.cpp +++ b/generated/CodeGenerator.g.cpp @@ -22,6 +22,7 @@ CodeGeneratorStorage::CodeGeneratorStorage(CodeEmitterBase emitter) { } List CodeGeneratorStorage::GetFunctions() { return _functions; + } Int32 CodeGeneratorStorage::AllocReg() { // Scan from _firstAvailable to find first free register @@ -407,6 +408,7 @@ Int32 CodeGeneratorStorage::Visit(BinaryOpNode node) { } Int32 resultReg = GetTargetOrAlloc(); // Capture target before any recursive calls + Int32 leftReg = node.Left().Accept(_this); Int32 rightReg = node.Right().Accept(_this); diff --git a/generated/GCItems.g.cpp b/generated/GCItems.g.cpp index c2892fc..7652164 100644 --- a/generated/GCItems.g.cpp +++ b/generated/GCItems.g.cpp @@ -42,6 +42,7 @@ Int32 GCList::IndexOf(Value item,Int32 afterIdx) { void GCList::MarkChildren() { if (IsNull(Items)) return; for (Int32 i = 0; i < Items.Count(); i++) GCManager::Mark(Items[i]); + } Int32 GCMap::Count() { diff --git a/generated/GCManager.g.h b/generated/GCManager.g.h index 90a4bef..a5ee3f2 100644 --- a/generated/GCManager.g.h +++ b/generated/GCManager.g.h @@ -120,11 +120,6 @@ class GCManager { public: static GCFunction GetFuncRef(Value v); public: static GCHandle GetHandle(Value v); - // ── Static helper for content-based string access ───────────────────────── - // Used by GCMap for content-based key hashing and equality. - // (Or is it? ToDo: see if this is still needed.) - - public: static String GetStringContent(Value v); }; // end of struct GCManager // INLINE METHODS @@ -133,20 +128,5 @@ inline void GCManager::Mark(Value v) { if (!is_gc_object(v)) return; DispatchMark(value_gc_set_index(v), value_item_index(v)); } -inline String GCManager::GetStringContent(Value v) { - if (is_tiny_string(v)) { - Int32 len = value_tiny_len(v); - char chars[len]; - for (Int32 i = 0; i < len; i++) chars[i] = (char)((value_bits(v) >> (8 * (i + 1))) & 0xFF); - return String::New(chars); - } - if (is_heap_string(v)) { - GCStringSet set; - set = (value_gc_set_index(v) == InternedStringSet) ? InternedStrings : BigStrings; - String data = set.Get(value_item_index(v)).Data; - return !IsNull(data) ? data : ""; - } - return ""; -} } // end of namespace MiniScript diff --git a/generated/GCSet.g.h b/generated/GCSet.g.h index 7dc0e7a..ae814f3 100644 --- a/generated/GCSet.g.h +++ b/generated/GCSet.g.h @@ -173,6 +173,7 @@ class GCErrorSetStorage : public GCSetBaseStorage { public: GCErrorSetStorage(Int32 initialCapacity = 64); protected: void CallMarkChildren(Int32 idx); + protected: void CallOnSweep(Int32 idx); protected: void AppendItem(); @@ -309,6 +310,7 @@ struct GCErrorSet : public GCSetBase { } protected: void CallMarkChildren(Int32 idx) { return get()->CallMarkChildren(idx); } + protected: void CallOnSweep(Int32 idx) { return get()->CallOnSweep(idx); } protected: void AppendItem() { return get()->AppendItem(); } diff --git a/generated/IOHelper.g.cpp b/generated/IOHelper.g.cpp index 04426ba..0c48d02 100644 --- a/generated/IOHelper.g.cpp +++ b/generated/IOHelper.g.cpp @@ -7,6 +7,46 @@ #include #include #include +#ifdef _WIN32 // define POSIX getline if on Windows +#include +#include + +int getline(char** lineptr, size_t* n, FILE* stream) { + if (!lineptr || !n || !stream) return -1; + + size_t pos = 0; + + // Allocate if needed + if (*lineptr == nullptr || *n == 0) { + *n = 128; + *lineptr = (char*)malloc(*n); + if (!*lineptr) return -1; + } + + int c; + while ((c = fgetc(stream)) != EOF) { + // Grow buffer if needed + if (pos + 1 >= *n) { + size_t new_size = *n * 2; + char* new_ptr = (char*)realloc(*lineptr, new_size); + if (!new_ptr) return -1; + *lineptr = new_ptr; + *n = new_size; + } + + (*lineptr)[pos++] = (char)c; + + if (c == '\n') break; + } + + if (pos == 0 && c == EOF) { + return -1; // EOF with no data + } + + (*lineptr)[pos] = '\0'; + return (int)pos; +} +#endif // defined(_WIN32) namespace MiniScript { diff --git a/generated/Interpreter.g.cpp b/generated/Interpreter.g.cpp index ac183ce..21f3eeb 100644 --- a/generated/Interpreter.g.cpp +++ b/generated/Interpreter.g.cpp @@ -140,6 +140,7 @@ void InterpreterStorage::REPL(String sourceLine,double timeLimit) { Error = val_null; if (IsNull(parser)) parser = Parser::New(); parser.Init(_pendingSource); + List statements = parser.ParseProgram(); // If parser needs more input, return and wait for next line diff --git a/generated/Interpreter.g.h b/generated/Interpreter.g.h index bcc5256..2f6f632 100644 --- a/generated/Interpreter.g.h +++ b/generated/Interpreter.g.h @@ -41,6 +41,7 @@ class InterpreterStorage : public std::enable_shared_from_thisshared_from_this() : nullptr) {} // + // standardOutput: receives the output of the "print" intrinsic. // diff --git a/generated/IntrinsicAPI.g.cpp b/generated/IntrinsicAPI.g.cpp index b6e481d..5197426 100644 --- a/generated/IntrinsicAPI.g.cpp +++ b/generated/IntrinsicAPI.g.cpp @@ -10,7 +10,7 @@ namespace MiniScript { Value Context::GetVar(String variableName) { return vm.LookupParamByName(variableName); } -Interpreter Context::Interpreter() { +Interpreter Context::GetInterpreter() { return vm.GetInterpreter(); } diff --git a/generated/IntrinsicAPI.g.h b/generated/IntrinsicAPI.g.h index f26b13c..abd2041 100644 --- a/generated/IntrinsicAPI.g.h +++ b/generated/IntrinsicAPI.g.h @@ -38,7 +38,7 @@ struct Context { // argument values, which are far more efficiently found via GetArg (above). public: Value GetVar(String variableName); - public: Interpreter Interpreter(); + public: Interpreter GetInterpreter(); }; // end of struct Context // IntrinsicResult: represents the result of calling an intrinsic function diff --git a/generated/LangConstants.g.h b/generated/LangConstants.g.h index 8e93cc4..a7d5bcc 100644 --- a/generated/LangConstants.g.h +++ b/generated/LangConstants.g.h @@ -66,6 +66,7 @@ enum class TokenType : Int32 { COLON, DOT, NOT, + AND, OR, WHILE, diff --git a/generated/Parser.g.cpp b/generated/Parser.g.cpp index 6935aa9..f145ee1 100644 --- a/generated/Parser.g.cpp +++ b/generated/Parser.g.cpp @@ -171,6 +171,7 @@ Precedence ParserStorage::GetPrecedence() { InfixParselet parselet = nullptr; if (_infixParselets.TryGetValue(_current.Type, &parselet)) { return parselet.Prec(); + } return Precedence::NONE; } diff --git a/generated/ShellIntrinsics.g.cpp b/generated/ShellIntrinsics.g.cpp index bcd83db..20025a1 100644 --- a/generated/ShellIntrinsics.g.cpp +++ b/generated/ShellIntrinsics.g.cpp @@ -45,12 +45,12 @@ #include #endif #define PATHSEP "/" +extern "C" { + extern char **environ; +} #endif #include #include -extern "C" { -extern char **environ; -} namespace MiniScript { @@ -577,7 +577,7 @@ Value ShellIntrinsics::FsInfo(String path) { localtime_r(&stats.st_mtime, &t); #endif #endif - char dateBuf[32]; + char dateBuf[72]; snprintf(dateBuf, sizeof(dateBuf), "%04d-%02d-%02d %02d:%02d:%02d", 1900 + t.tm_year, 1 + t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec); Value result = make_map(4); @@ -881,6 +881,7 @@ void ShellIntrinsics::InitFileIntrinsics() { f.set_Code([](Context ctx, IntrinsicResult partialResult) -> IntrinsicResult { Value self = ctx.GetArg(0); Value hv = val_null; map_try_get(self, make_string("_handle"), &hv); + Int32 len = GetRawBufLen(hv); if (len < 0) return IntrinsicResult(ErrorType::FileError("RawData has no buffer")); Int32 off = (Int32)as_double(ctx.GetArg(1)); if (off < 0) off += len; if (off < 0 || off + 4 > len) return IntrinsicResult(ErrorType::FileError("index out of bounds")); diff --git a/generated/VM.g.h b/generated/VM.g.h index 6d30179..da9b01b 100644 --- a/generated/VM.g.h +++ b/generated/VM.g.h @@ -10,6 +10,7 @@ #include "ErrorTypes.g.h" #include "value_map.h" #include +#include #include "GCManager.g.h" namespace MiniScript { diff --git a/generated/VMVis.g.cpp b/generated/VMVis.g.cpp index d474629..de956e1 100644 --- a/generated/VMVis.g.cpp +++ b/generated/VMVis.g.cpp @@ -40,8 +40,15 @@ VMVis::VMVis(VM vm) { } void VMVis::UpdateScreenSize() { #ifdef _WIN32 - _screenWidth = csbi.srWindow.Right - csbi.srWindow.Left + 1; - _screenHeight = rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + HANDLE hStdout; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if ((hStdout = GetStdHandle(STD_OUTPUT_HANDLE))!=INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbi)) { + _screenWidth = csbi.srWindow.Right - csbi.srWindow.Left + 1; + _screenHeight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + } else { + _screenWidth = 80; + _screenHeight = 24; + } #else struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); diff --git a/generated/VarMap.g.cpp b/generated/VarMap.g.cpp index e1b7db9..b43ed3b 100644 --- a/generated/VarMap.g.cpp +++ b/generated/VarMap.g.cpp @@ -124,6 +124,7 @@ void VarMapBackingStorage::Rebind(Int32 mapIdx,List registers,List _names = names; _regOrder.Clear(); _regIndices.Clear(); + GCManager::Maps.SetVmb(mapIdx, _this); } void VarMapBackingStorage::MapToRegister(Int32 mapIdx,Value varName,List registers,Int32 regIndex) { diff --git a/generated/forward_decs.g.h b/generated/forward_decs.g.h index ffb0f04..6362632 100644 --- a/generated/forward_decs.g.h +++ b/generated/forward_decs.g.h @@ -1,89 +1,9 @@ // FORWARD DECLARATIONS namespace MiniScript { -struct CodeGenerator; -class CodeGeneratorStorage; -struct CallInfo; -struct VM; -class VMStorage; -struct Context; -struct IntrinsicResult; -struct VMVis; -struct CodeEmitterBase; -class CodeEmitterBaseStorage; -struct LabelReference; -struct BytecodeEmitter; -class BytecodeEmitterStorage; -struct AssemblyEmitter; -class AssemblyEmitterStorage; +struct App; struct Assembler; class AssemblerStorage; -struct Parselet; -class ParseletStorage; -struct PrefixParselet; -class PrefixParseletStorage; -struct InfixParselet; -class InfixParseletStorage; -struct NumberParselet; -class NumberParseletStorage; -struct SelfParselet; -class SelfParseletStorage; -struct SuperParselet; -class SuperParseletStorage; -struct ScopeParselet; -class ScopeParseletStorage; -struct StringParselet; -class StringParseletStorage; -struct IdentifierParselet; -class IdentifierParseletStorage; -struct UnaryOpParselet; -class UnaryOpParseletStorage; -struct AddressOfParselet; -class AddressOfParseletStorage; -struct GroupParselet; -class GroupParseletStorage; -struct ListParselet; -class ListParseletStorage; -struct MapParselet; -class MapParseletStorage; -struct BinaryOpParselet; -class BinaryOpParseletStorage; -struct ComparisonParselet; -class ComparisonParseletStorage; -struct CallParselet; -class CallParseletStorage; -struct IndexParselet; -class IndexParseletStorage; -struct MemberParselet; -class MemberParseletStorage; -struct Intrinsic; -class IntrinsicStorage; -struct GCSetBase; -class GCSetBaseStorage; -struct GCStringSet; -class GCStringSetStorage; -struct GCListSet; -class GCListSetStorage; -struct GCMapSet; -class GCMapSetStorage; -struct GCErrorSet; -class GCErrorSetStorage; -struct GCHandleSet; -class GCHandleSetStorage; -struct GCFuncRefSet; -class GCFuncRefSetStorage; -struct Parser; -class ParserStorage; -struct GCString; -struct GCList; -struct GCMap; -struct GCError; -struct GCFunction; -struct GCHandle; -struct Interpreter; -class InterpreterStorage; -struct FuncDef; -class FuncDefStorage; struct ASTNode; class ASTNodeStorage; struct NumberNode; @@ -140,9 +60,89 @@ struct ScopeNode; class ScopeNodeStorage; struct ReturnNode; class ReturnNodeStorage; -struct App; -struct VarMapBacking; -class VarMapBackingStorage; +struct CodeEmitterBase; +class CodeEmitterBaseStorage; +struct LabelReference; +struct BytecodeEmitter; +class BytecodeEmitterStorage; +struct AssemblyEmitter; +class AssemblyEmitterStorage; +struct CodeGenerator; +class CodeGeneratorStorage; +struct FuncDef; +class FuncDefStorage; +struct GCString; +struct GCList; +struct GCMap; +struct GCError; +struct GCFunction; +struct GCHandle; +struct GCSetBase; +class GCSetBaseStorage; +struct GCStringSet; +class GCStringSetStorage; +struct GCListSet; +class GCListSetStorage; +struct GCMapSet; +class GCMapSetStorage; +struct GCErrorSet; +class GCErrorSetStorage; +struct GCHandleSet; +class GCHandleSetStorage; +struct GCFuncRefSet; +class GCFuncRefSetStorage; +struct Interpreter; +class InterpreterStorage; +struct Intrinsic; +class IntrinsicStorage; +struct Context; +struct IntrinsicResult; struct Token; struct Lexer; +struct Parselet; +class ParseletStorage; +struct PrefixParselet; +class PrefixParseletStorage; +struct InfixParselet; +class InfixParseletStorage; +struct NumberParselet; +class NumberParseletStorage; +struct SelfParselet; +class SelfParseletStorage; +struct SuperParselet; +class SuperParseletStorage; +struct ScopeParselet; +class ScopeParseletStorage; +struct StringParselet; +class StringParseletStorage; +struct IdentifierParselet; +class IdentifierParseletStorage; +struct UnaryOpParselet; +class UnaryOpParseletStorage; +struct AddressOfParselet; +class AddressOfParseletStorage; +struct GroupParselet; +class GroupParseletStorage; +struct ListParselet; +class ListParseletStorage; +struct MapParselet; +class MapParseletStorage; +struct BinaryOpParselet; +class BinaryOpParseletStorage; +struct ComparisonParselet; +class ComparisonParseletStorage; +struct CallParselet; +class CallParseletStorage; +struct IndexParselet; +class IndexParseletStorage; +struct MemberParselet; +class MemberParseletStorage; +struct Parser; +class ParserStorage; +struct VarMapBacking; +class VarMapBackingStorage; +struct CallInfo; +struct VM; +class VMStorage; +struct VMVis; }