From 1f3bc13e8def3ede933c665ce79a3852966ce0f2 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Sun, 13 Sep 2026 01:00:33 -0500 Subject: [PATCH] First commit to big refactor --- include/CrossLang.hpp | 401 +++++++++++++++++++---- src/compiler/parser.cpp | 2 + src/program_lib/crosslang.cpp | 2 +- src/program_lib/crosslanginterperter.cpp | 2 +- src/program_lib/crosslangvm.cpp | 4 +- src/runtime_methods/class.cpp | 8 +- src/runtime_methods/dictionary.cpp | 2 +- src/runtime_methods/env.cpp | 2 +- src/runtime_methods/io.cpp | 2 +- src/runtime_methods/json.cpp | 2 +- src/runtime_methods/net.cpp | 10 +- src/runtime_methods/process.cpp | 4 +- src/runtime_methods/sqlite.cpp | 2 +- src/runtime_methods/vm.cpp | 4 +- src/types/byteviews/byteview.cpp | 83 +++++ src/types/byteviews/mutbyteview.cpp | 0 src/types/byteviews/resource.cpp | 10 + src/types/byteviews/string.cpp | 123 +++++++ src/types/closure.cpp | 2 +- src/types/dictionary.cpp | 2 +- src/types/list.cpp | 220 ++++++++++++- src/types/queryable.cpp | 2 +- src/types/streams/memorystream.cpp | 30 ++ src/types/streams/networkstream.cpp | 165 ++++++++++ src/types/streams/stream.cpp | 251 ++++++++++++++ src/types/streams/streamwrapper.cpp | 56 ++++ src/vm/bc/add.cpp | 10 + src/vm/bc/executemethod2.cpp | 324 +----------------- src/vm/bc/getfield.cpp | 88 +---- src/vm/bc/invokemethod.cpp | 2 +- src/vm/bc/setfield.cpp | 25 -- src/vm/bc/sub.cpp | 12 +- src/vm/filereader.cpp | 95 ++++-- src/vm/vm.cpp | 21 +- 34 files changed, 1398 insertions(+), 570 deletions(-) create mode 100644 src/types/byteviews/byteview.cpp create mode 100644 src/types/byteviews/mutbyteview.cpp create mode 100644 src/types/byteviews/resource.cpp create mode 100644 src/types/byteviews/string.cpp create mode 100644 src/types/streams/memorystream.cpp create mode 100644 src/types/streams/networkstream.cpp create mode 100644 src/types/streams/stream.cpp create mode 100644 src/types/streams/streamwrapper.cpp diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index 60d3f86..06c76fd 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -84,31 +84,33 @@ class TVMVersion { * * @return uint8_t The major */ - uint8_t Major() { return major; } + uint8_t Major() const { return major; } /** * @brief Minor * * @return uint8_t The minor */ - uint8_t Minor() { return minor; } + uint8_t Minor() const { return minor; } /** * @brief Patch * * @return uint8_t The patch */ - uint8_t Patch() { return patch; } + uint8_t Patch() const { return patch; } /** * @brief Build * * @return uint16_t The build */ - uint16_t Build() { return build >> 2; } + uint16_t Build() const { return build >> 2; } /** * @brief Stage (dev, alpha, beta or prod) * * @return TVMVersionStage The stage */ - TVMVersionStage VersionStage() { return (TVMVersionStage)(build & 3); } + TVMVersionStage VersionStage() const { + return static_cast(build & 3); + } /** * @brief Set the Major * @@ -215,7 +217,7 @@ class TVMVersion { * * @param versionData an array that is 5 bytes long */ - void ToArray(uint8_t *versionData) { + void ToArray(uint8_t *versionData) const { versionData[0] = major; versionData[1] = minor; versionData[2] = patch; @@ -267,7 +269,7 @@ class TVMVersion { * @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) { + int CompareTo(const TVMVersion &version) const { if (this->major > version.major) return 1; if (this->major < version.major) @@ -291,7 +293,7 @@ class TVMVersion { * * @return uint64_t serialized as a long */ - uint64_t AsLong() { + uint64_t AsLong() const { uint64_t v = (uint64_t)major << 32; v |= (uint64_t)minor << 24; v |= (uint64_t)patch << 16; @@ -304,7 +306,7 @@ class TVMVersion { * @return int CompareTo(RuntimeVersion) where RuntimeVersion is the runtime * version */ - int CompareToRuntime() { + int CompareToRuntime() const { TVMVersion version(CROSSLANG_BYTECODE_MAJOR, CROSSLANG_BYTECODE_MINOR, CROSSLANG_BYTECODE_PATCH, CROSSLANG_BYTECODE_BUILD, CROSSLANG_BYTECODE_VERSIONSTAGE); @@ -319,9 +321,10 @@ class TVMVersion { * @return true the parsing succeeded * @return false the parsing failed */ - static bool TryParse(std::string versionStr, TVMVersion &version) { + static bool TryParse(const std::string &versionStr, TVMVersion &version) { if (versionStr.empty()) return false; + size_t sep = versionStr.find_last_of('-'); std::string left = versionStr; @@ -399,7 +402,7 @@ class TVMVersion { * @return std::string the version string like 1.0.0.0-prod (or dev, alpha, * beta) */ - std::string ToString() { + std::string ToString() const { std::string str = {}; str.append(std::to_string((int)this->Major())); str.push_back('.'); @@ -408,14 +411,20 @@ class TVMVersion { str.append(std::to_string((int)this->Patch())); str.push_back('.'); str.append(std::to_string((int)this->Build())); - if (this->VersionStage() == TVMVersionStage::DevVersion) { + + switch (this->VersionStage()) { + case TVMVersionStage::DevVersion: str.append("-dev"); - } else if (this->VersionStage() == TVMVersionStage::AlphaVersion) { + break; + case TVMVersionStage::AlphaVersion: str.append("-alpha"); - } else if (this->VersionStage() == TVMVersionStage::BetaVersion) { + break; + case TVMVersionStage::BetaVersion: str.append("-beta"); - } else if (this->VersionStage() == TVMVersionStage::ProductionVersion) { + break; + case TVMVersionStage::ProductionVersion: str.append("-prod"); + break; } return str; } @@ -1347,14 +1356,67 @@ class Parser { class THeapObject; class CallStackEntry; class InterperterThread; +class TString; class THeapObject { + protected: + virtual bool opAdd(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opSub(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opTimes(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opDiv(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opMod(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opLessThan(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opGreaterThan(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opLessThanEqual(InterperterThread *thrd, + std::shared_ptr gc, TObject rhs); + virtual bool opGreaterThanEqual(InterperterThread *thrd, + std::shared_ptr gc, TObject rhs); + virtual bool opLeftShift(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opRightShift(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opBitwiseOr(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opBitwiseAnd(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opXor(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + virtual bool opNeg(InterperterThread *thrd, std::shared_ptr gc); + virtual bool opBitwiseNot(InterperterThread *thrd, std::shared_ptr gc); + virtual bool opLogicalNot(InterperterThread *thrd, std::shared_ptr gc); + virtual bool opExecuteMethod(InterperterThread *thrd, + std::shared_ptr gc, + const std::string &name, + const std::vector &args); + virtual bool opSetField(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name, TObject value); + virtual bool opGetField(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name); + public: bool marked; virtual void Mark() { marked = true; } THeapObject() = default; THeapObject(const THeapObject &) = delete; THeapObject &operator=(const THeapObject &) = delete; + virtual ~THeapObject() = default; + + virtual std::string TypeName() = 0; + + virtual TString *ToString(GCList &ls); + virtual bool ToBool(); + + virtual bool IsEqualTo(std::shared_ptr gc, TObject rhs); + virtual bool IsNotEqualTo(std::shared_ptr gc, TObject rhs); + + friend class InterperterThread; }; // this is a dummy type with @@ -1368,13 +1430,12 @@ class TContinue {}; */ using TObject = - std::variant, std::shared_ptr, TBreak, - TContinue, std::shared_ptr, - std::shared_ptr, + TContinue, std::shared_ptr, std::shared_ptr, std::shared_ptr, std::shared_ptr, @@ -1432,7 +1493,7 @@ class GC : public std::enable_shared_from_this { }; std::string GetObjectTypeString(TObject obj); -std::string ToString(std::shared_ptr gc, TObject obj); +std::string ObjectToString(std::shared_ptr gc, TObject obj); class GCList { std::vector items; @@ -1452,6 +1513,8 @@ class GCList { return obj; } + TString *FromString(std::string_view str); + void Add(TObject v); void Remove(TObject v); void Mark(); @@ -1470,36 +1533,164 @@ class TFileChunk : public THeapObject { static TFileChunk *Create(GCList &gc); TFile *file; std::vector code; - std::vector args; - std::optional name; + std::vector args; + std::optional name; + void Mark(); +}; +class TMutByteView; +class TByteView : public THeapObject { + public: + virtual std::pair GetBounds() const = 0; + TString *ToString(GCList &ls); + void CopyTo(TMutByteView *view); + void CopyTo(TMutByteView *view, size_t srcOffset, size_t destOffset, + size_t length); + std::pair + GetBoundsConstrained(size_t offset = 0, size_t length = (size_t)-1) { + auto bounds = GetBounds(); + + if (bounds.first == nullptr || offset >= bounds.second || length == 0) + return std::pair(nullptr, 0); + + length = std::min(length, bounds.second - offset); + + return std::pair(bounds.first + offset, + length); + } + std::string TypeName(); + bool opExecuteMethod(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name, + const std::vector &args); + bool opGetField(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name); + + int64_t GetAt(size_t index) { + auto res = GetBoundsConstrained(index, 1); + if (res.first == nullptr || res.second != 1) + return -1; + return *res.first; + } +}; + +class TMutByteView : public TByteView { + public: + std::pair GetBounds() const; + virtual std::pair GetMutableBounds() = 0; + std::pair + GetMutableBoundsConstrained(size_t offset = 0, size_t length = (size_t)-1) { + auto bounds = GetMutableBounds(); + if (bounds.first == nullptr || offset >= bounds.second || length == 0) + return std::pair(nullptr, 0); + + length = std::min(length, bounds.second - offset); + + return std::pair(bounds.first + offset, length); + } +}; + +class TMemoryStreamMutByteView : public TMutByteView { + std::shared_ptr strm; + + public: + TMemoryStreamMutByteView( + std::shared_ptr strm); + std::pair GetMutableBounds(); +}; + +class TString : public TByteView { + private: + std::string text; + + protected: + bool opAdd(InterperterThread *thrd, std::shared_ptr gc, TObject rhs); + bool opLessThan(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + bool opGreaterThan(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + bool opLessThanEqual(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + bool opGreaterThanEqual(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs); + + public: + TString(); + explicit TString(std::string_view str); + TString(std::string_view lhs, std::string_view rhs); + TString(const char *text, size_t len); + template + TString(Itterator begin, Itterator end) : text(begin, end) {} + TString(std::string &&str); + + const std::string &GetString() const; + + std::pair GetBounds() const; + + TString *ToString(GCList &ls); + + std::string TypeName(); + + bool IsEqualTo(std::shared_ptr gc, TObject rhs); + bool IsNotEqualTo(std::shared_ptr gc, TObject rhs); +}; +class TResource : public TByteView { + std::vector bytes; + + public: + TResource(std::vector &&bytes); + + std::pair GetBounds() const; + std::string TypeName(); +}; +class TByteArray : public TMutByteView { + std::vector data; + + public: + TByteArray(size_t length); + TByteArray(TByteView *view); + void Resize(size_t length); + std::pair GetMutableBounds(); + std::string TypeName(); +}; +class TMutSpan : public TMutByteView { + TMutByteView *view; + int64_t offset; + int64_t length; + + public: + TMutSpan(TMutByteView *view, int64_t offset, int64_t length); + std::pair GetMutableBounds(); + std::string TypeName(); + void Mark(); +}; +class TSpan : public TByteView { + TByteView *view; + int64_t offset; + int64_t length; + + public: + TSpan(TByteView *view, int64_t offset, int64_t length); + std::pair GetBounds() const; + std::string TypeName(); void Mark(); }; -class TByteArray : public THeapObject { - public: - std::vector data; - [[deprecated("Use GCList::Create() instead")]] - static TByteArray *Create(GCList *gc); - [[deprecated("Use GCList::Create() instead")]] - static TByteArray *Create(GCList &gc); -}; enum class TClassModifier { Private, Protected, Public, Static }; class TClassEntry { public: TClassModifier modifier; bool isFunction; bool isAbstract; - std::vector args; - std::string documentation; - std::string name; + std::vector args; + TString *documentation; + TString *name; uint32_t chunkId; }; class TClass { public: - std::string documentation; - std::vector name; - std::vector inherits; + TString *documentation; + std::vector name; + std::vector inherits; std::vector entry; }; class TClassObjectEntry { @@ -1519,19 +1710,19 @@ class TFile : public THeapObject { static TFile *Create(GCList &gc); std::vector chunks; - std::vector strings; - std::vector> vms; - std::vector, uint32_t>> functions; - std::vector> dependencies; - std::vector> tools; + std::vector strings; + std::vector> vms; + std::vector, uint32_t>> functions; + std::vector> dependencies; + std::vector> tools; std::vector>> sections; - std::vector>> metadata; - std::vector> resources; + std::vector>> metadata; + std::vector resources; std::vector classes; - std::string name; + TString *name; TVMVersion version; - std::string info; - int32_t icon = -1; + TString *info; + TResource *icon = nullptr; void Load(std::shared_ptr gc, std::shared_ptr strm); @@ -1541,10 +1732,10 @@ class TFile : public THeapObject { uint8_t *buffer, size_t len); uint32_t EnsureInt(std::shared_ptr strm); - std::string - EnsureString(std::shared_ptr strm); + void EnsureString(GCList &ls, + std::shared_ptr strm); - std::string + TString * GetString(std::shared_ptr strm); void Mark(); @@ -1570,6 +1761,13 @@ class TAssociativeArray : public THeapObject { }; class TList : public THeapObject { + protected: + bool opExecuteMethod(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name, + const std::vector &args); + bool opGetField(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name); + public: TList() = default; template @@ -1577,10 +1775,7 @@ class TList : public THeapObject { TList(std::initializer_list il) : items(il) {} TList(int64_t capacity) { items.reserve(capacity); } std::vector items; - [[deprecated("Use GCList::Create() instead")]] - static TList *Create(GCList *gc); - [[deprecated("Use GCList::Create() instead")]] - static TList *Create(GCList &gc); + template [[deprecated("Use GCList::Create() instead")]] static TList *Create(GCList *gc, Itterator begin, Itterator end) { @@ -1599,6 +1794,7 @@ class TList : public THeapObject { static TList *Create(GCList &gc, std::initializer_list il) { return gc.Create(il); } + std::string TypeName(); virtual int64_t Count(); virtual TObject Get(int64_t index); virtual void Set(int64_t index, TObject value); @@ -2235,7 +2431,7 @@ class TDynamicList : public THeapObject { TObject Remove(GCList &ls, TObject v); TObject RemoveAt(GCList &ls, int64_t v); TObject Clear(GCList &ls); - TObject ToString(GCList &ls); + TString *ToString(GCList &ls); ~TDynamicList(); }; @@ -2449,12 +2645,64 @@ class TNativeObject : public THeapObject { return ls->Create(std::forward(args)...); } - virtual TObject CallMethod(GCList &ls, std::string name, - std::vector args) = 0; - virtual std::string TypeName() = 0; - virtual bool ToBool(); - virtual bool Equals(std::shared_ptr gc, TObject right); + virtual TObject CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args) = 0; }; +class ITStream : public TNativeObject { + protected: + bool Exists(std::string_view str); + + public: + TObject CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args); + std::string TypeName(); + virtual std::shared_ptr GetStream() = 0; +}; +class TObjectStreamWrapper : public ITStream { + std::shared_ptr strm; + + public: + TObjectStreamWrapper(std::shared_ptr strm); + TObject CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args); + std::string TypeName(); + std::shared_ptr GetStream(); +}; +class TStream : public ITStream { + std::shared_ptr strm; + + public: + TStream(std::shared_ptr strm); + std::shared_ptr GetStream(); +}; + +class TMemoryStream : public ITStream { + std::shared_ptr strm; + + public: + TMemoryStream( + std::shared_ptr strm); + std::shared_ptr GetStream(); + TObject CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args); + std::string TypeName(); +}; + +class TNetworkStream : public ITStream { + std::shared_ptr strm; + TNetworkStream( + std::shared_ptr strm); + std::shared_ptr GetStream(); + TObject CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args); + std::string TypeName(); +}; + class TRandom : public TNativeObject { public: Tesses::Framework::Random random; @@ -2565,7 +2813,7 @@ class SyntaxException : public std::exception { LexTokenLineInfo LineInfo() { return line; } }; -template bool GetObject(TObject &obj, T &res) { +template bool GetObject(const TObject &obj, T &res) { if (!std::holds_alternative(obj)) return false; res = std::get(obj); @@ -2580,20 +2828,34 @@ inline bool IsNull(const TObject &obj) { } [[deprecated("Use GetObjectHeap() with TString instead")]] -inline bool GetObject(TObject &obj, std::string &str) { +inline bool GetObject(const TObject &obj, std::string &str) { if (!std::holds_alternative(obj)) return false; str = std::get(obj); return true; } +template < + typename T, + std::enable_if_t, + int> = 0> +bool GetObject(const TObject &obj, std::shared_ptr &ptr) { + ITStream *strm; + if (!GetObjectHeap(obj, strm)) + return false; + auto res = std::dynamic_pointer_cast(strm->GetStream()); + if (!res) + return false; + ptr = res; + return true; +} + template -bool GetArgument(std::vector &args, size_t index, T &obj) { +bool GetArgument(const std::vector &args, size_t index, T &obj) { if (index >= args.size()) return false; return GetObject(args[index], obj); } - template bool GetObjectHeap(TObject &obj, T &res) { THeapObject *h; if (!GetObject(obj, h)) @@ -2606,7 +2868,7 @@ template bool GetObjectHeap(TObject &obj, T &res) { } template -bool GetArgumentHeap(std::vector &args, size_t index, T &obj) { +bool GetArgumentHeap(const std::vector &args, size_t index, T &obj) { if (index >= args.size()) return false; return GetObjectHeap(args[index], obj); @@ -2616,8 +2878,8 @@ bool GetObjectAsPath(TObject &obj, Tesses::Framework::Filesystem::VFSPath &path, bool GetArgumentAsPath(std::vector &args, size_t index, Tesses::Framework::Filesystem::VFSPath &path, bool allowString = true); -bool ToBool(TObject obj); -bool Equals(std::shared_ptr gc, TObject left, TObject right); +bool ObjectToBool(TObject obj); +bool ObjectEquals(std::shared_ptr gc, TObject left, TObject right); typedef void (*PluginFunction)(std::shared_ptr gc, TRootEnvironment *env); #if !defined(_WIN32) #define DLLEXPORT @@ -2662,11 +2924,10 @@ ToHttpServer(std::shared_ptr gc, TObject obj); class EmbedStream : public Tesses::Framework::Streams::Stream { size_t offset; - MarkedTObject file; - uint32_t resource; + MarkedTObject resource; public: - EmbedStream(std::shared_ptr gc, TFile *file, uint32_t resource); + EmbedStream(std::shared_ptr gc, TResource *res); bool CanRead(); bool CanSeek(); bool EndOfStream(); diff --git a/src/compiler/parser.cpp b/src/compiler/parser.cpp index 7a21e13..d0916fa 100644 --- a/src/compiler/parser.cpp +++ b/src/compiler/parser.cpp @@ -1865,6 +1865,8 @@ SyntaxNode Parser::ParseBAnd() { SyntaxNode Parser::ParseExpression() { SyntaxNode expr = ParseAssignment(); while (IsSymbol(",")) { + if (IsAnySymbol({"]", "}"}, false)) + break; expr = AdvancedSyntaxNode::Create(CommaExpression, true, {expr, ParseAssignment()}); } diff --git a/src/program_lib/crosslang.cpp b/src/program_lib/crosslang.cpp index f7800dc..3bd7474 100644 --- a/src/program_lib/crosslang.cpp +++ b/src/program_lib/crosslang.cpp @@ -142,7 +142,7 @@ TObject CrossLangShell(GCList &ls, std::vector &argv) { env->LoadFileWithDependencies( ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, filename); - TList *args = TList::Create(ls); + TList *args = ls.Create(); args->Add(filename.ToString()); diff --git a/src/program_lib/crosslanginterperter.cpp b/src/program_lib/crosslanginterperter.cpp index d956975..672db26 100644 --- a/src/program_lib/crosslanginterperter.cpp +++ b/src/program_lib/crosslanginterperter.cpp @@ -39,7 +39,7 @@ TObject CrossLangInterperter(GCList &ls, TRootEnvironment *env, } } - TList *args = TList::Create(ls); + TList *args = ls.Create(); for (int arg = 1; arg < argv.size(); arg++) args->Add(std::string(argv[arg])); diff --git a/src/program_lib/crosslangvm.cpp b/src/program_lib/crosslangvm.cpp index 61ae555..a7639c1 100644 --- a/src/program_lib/crosslangvm.cpp +++ b/src/program_lib/crosslangvm.cpp @@ -25,7 +25,7 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env, env->EnsureDictionary(ls.GetGC(), "Net") ->SetValue("WebServerPort", (int64_t)port); - TList *args2 = TList::Create(ls); + TList *args2 = ls.Create(); for (auto &item : args.positional) { args2->Add(item); } @@ -48,7 +48,7 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env, TF_Quit(); return (int64_t)0; } else { - TList *args = TList::Create(ls); + TList *args = ls.Create(); for (size_t arg = 1; arg < argv.size(); arg++) args->Add(std::string(argv[arg])); diff --git a/src/runtime_methods/class.cpp b/src/runtime_methods/class.cpp index f72950a..abdf5b4 100644 --- a/src/runtime_methods/class.cpp +++ b/src/runtime_methods/class.cpp @@ -2,7 +2,7 @@ namespace Tesses::CrossLang { static TList *VectorOfStringToList(GCList &ls, std::vector &strs) { - TList *list = TList::Create(ls); + TList *list = ls.Create(); ls.GetGC()->BarrierBegin(); for (auto &item : strs) list->Add(item); @@ -10,7 +10,7 @@ static TList *VectorOfStringToList(GCList &ls, std::vector &strs) { return list; } static TList *EntriesToList(GCList &ls, std::vector &ents) { - TList *list = TList::Create(ls); + TList *list = ls.Create(); ls.GetGC()->BarrierBegin(); for (auto &item : ents) { std::string modifier = "public"; @@ -42,7 +42,7 @@ static TList *EntriesToList(GCList &ls, std::vector &ents) { return list; } static TList *ClassInstanceToList(GCList &ls, TClassObject *co) { - TList *list = TList::Create(ls); + TList *list = ls.Create(); ls.GetGC()->BarrierBegin(); for (auto &item : co->entries) { if (item.modifier == TClassModifier::Public) { @@ -126,7 +126,7 @@ static TObject Class_CreateInstance(TRootEnvironment *env, GCList &ls, } static TObject Class_GetClassNames(TRootEnvironment *env, GCList &ls, std::vector args) { - TList *list = TList::Create(ls); + TList *list = ls.Create(); ls.GetGC()->BarrierBegin(); for (auto &item : env->classes) { list->Add(JoinPeriod(item.first->classes.at(item.second).name)); diff --git a/src/runtime_methods/dictionary.cpp b/src/runtime_methods/dictionary.cpp index da206b0..2369a8b 100644 --- a/src/runtime_methods/dictionary.cpp +++ b/src/runtime_methods/dictionary.cpp @@ -2,7 +2,7 @@ namespace Tesses::CrossLang { TObject Dictionary_FindByKey(GCList &ls, std::vector args) { - TList *dest = TList::Create(ls); + TList *dest = ls.Create(); ls.GetGC()->BarrierBegin(); std::string key; if (GetArgument(args, 1, key)) { diff --git a/src/runtime_methods/env.cpp b/src/runtime_methods/env.cpp index 9e64c1c..b167eab 100644 --- a/src/runtime_methods/env.cpp +++ b/src/runtime_methods/env.cpp @@ -91,7 +91,7 @@ static TObject Env_GetRealExecutablePath(GCList &ls, } static TObject Env_GetAll(GCList &ls, std::vector args) { ls.GetGC()->BarrierBegin(); - TList *list = TList::Create(ls); + TList *list = ls.Create(); std::vector> env; Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env); for (auto &item : env) { diff --git a/src/runtime_methods/io.cpp b/src/runtime_methods/io.cpp index f5972aa..cc92194 100644 --- a/src/runtime_methods/io.cpp +++ b/src/runtime_methods/io.cpp @@ -63,7 +63,7 @@ static TObject FS_ReadAllLines(GCList &ls, std::vector args) { Tesses::Framework::Filesystem::Helpers::ReadAllLines(vfs, path, lines); ls.GetGC()->BarrierBegin(); - auto items = TList::Create(ls); + auto items = ls.Create(); for (auto &l : lines) { items->Add(l); } diff --git a/src/runtime_methods/json.cpp b/src/runtime_methods/json.cpp index 709e65a..bacb14f 100644 --- a/src/runtime_methods/json.cpp +++ b/src/runtime_methods/json.cpp @@ -114,7 +114,7 @@ static TObject JsonDeserialize(GCList &ls2, JToken json) { if (TryGetJToken(json, str)) return str; if (TryGetJToken(json, arr)) { - TList *ls = TList::Create(ls2); + TList *ls = ls2.Create(); for (auto &item : arr) { auto itemRes = JsonDeserialize(ls2, item); diff --git a/src/runtime_methods/net.cpp b/src/runtime_methods/net.cpp index 316b6bf..5612e16 100644 --- a/src/runtime_methods/net.cpp +++ b/src/runtime_methods/net.cpp @@ -17,13 +17,13 @@ static std::shared_ptr TObjectToSMTPBody(GCList &ls, std::string mimeType, TObject obj) { std::shared_ptr body; std::string text; - TByteArray *ba; + TByteView *ba; std::shared_ptr sho; if (GetObject(obj, text)) { body = std::make_shared(text, mimeType); } else if (GetObjectHeap(obj, ba)) { std::shared_ptr ms = std::make_shared(true); - ms->WriteBlock(ba->data.data(), ba->data.size()); + ms->WriteBlock(ba->GetData(), ba->GetSize()); ms->Seek(0L, SeekOrigin::Begin); body = std::make_shared(mimeType, ms); @@ -191,7 +191,7 @@ class THttpDictionary : public TNativeObject { } return nullptr; } else if (key == "ToList") { - TList *_ls = TList::Create(ls); + TList *_ls = ls.Create(); for (auto item : dict->kvp) { for (auto i : item.second) { auto d = TDictionary::Create(ls); @@ -334,7 +334,7 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary { return strm; }); - return TList::Create(ls, response.begin(), response.end()); + return ls.Create(response.begin(), response.end()); } } else if (key == "getNeedToParseFormData") return ctx->NeedToParseFormData(); @@ -1581,7 +1581,7 @@ void TStd::RegisterNet(std::shared_ptr gc, TRootEnvironment *env) { dict->DeclareFunction( gc, "getIPAddresses", "Get the ip addresses of this machine", {"$ipv6"}, [](GCList &ls, std::vector args) -> TObject { - TList *a = TList::Create(ls); + TList *a = ls.Create(); bool ipv6 = false; GetArgument(args, 0, ipv6); ls.GetGC()->BarrierBegin(); diff --git a/src/runtime_methods/process.cpp b/src/runtime_methods/process.cpp index b19fd06..851349a 100644 --- a/src/runtime_methods/process.cpp +++ b/src/runtime_methods/process.cpp @@ -4,8 +4,8 @@ namespace Tesses::CrossLang { class ProcessObject : public TNativeObject { public: ProcessObject(GCList &ls) { - arguments = TList::Create(ls); - environment = TList::Create(ls); + arguments = ls.Create(); + environment = ls.Create(); process.includeThisEnv = true; process.redirectStdIn = false; diff --git a/src/runtime_methods/sqlite.cpp b/src/runtime_methods/sqlite.cpp index 0fde954..1b67e0e 100644 --- a/src/runtime_methods/sqlite.cpp +++ b/src/runtime_methods/sqlite.cpp @@ -100,7 +100,7 @@ class SQLiteObject : public TNativeObject { this->db->Exec(arg, res); - TList *list = TList::Create(ls); + TList *list = ls.Create(); for (auto &item : res) { TDictionary *dict = TDictionary::Create(ls); diff --git a/src/runtime_methods/vm.cpp b/src/runtime_methods/vm.cpp index 518f2f3..f896c1b 100644 --- a/src/runtime_methods/vm.cpp +++ b/src/runtime_methods/vm.cpp @@ -39,7 +39,7 @@ static TObject AstToTObject(GCList &ls, SyntaxNode node) { ls.GetGC()->BarrierBegin(); r->SetValue("Type", asn.nodeName); r->SetValue("IsExpression", asn.isExpression); - TList *ls2 = TList::Create(ls); + TList *ls2 = ls.Create(); for (auto item : asn.nodes) { ls2->Add(AstToTObject(ls, item)); } @@ -268,7 +268,7 @@ static TObject VM_GetStacktrace(GCList &ls, std::vector args) { auto current_function = GC::GetCurrentFunction(); if (current_function != nullptr) { if (current_function->thread != nullptr) { - TList *list = TList::Create(ls); + TList *list = ls.Create(); ls.GetGC()->BarrierBegin(); for (auto item : current_function->thread->call_stack_entries) { auto dict = TDictionary::Create(ls); diff --git a/src/types/byteviews/byteview.cpp b/src/types/byteviews/byteview.cpp new file mode 100644 index 0000000..65f81cc --- /dev/null +++ b/src/types/byteviews/byteview.cpp @@ -0,0 +1,83 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { +std::string TByteView::TypeName() { return "ByteView"; } +TString *TByteView::ToString(GCList &ls) { + auto bounds = GetBounds(); + if (bounds.first == nullptr || bounds.second == 0) + return ls.FromString(""); + + return ls.Create(reinterpret_cast(bounds.first), + bounds.second); +} +bool TByteView::opExecuteMethod(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name, + const std::vector &args) { + if (name == "Slice") { + int64_t offset = 0; + int64_t length = -1; + + GetArgument(args, 0, offset); + GetArgument(args, 1, length); + + GCList ls(gc); + + thrd->call_stack_entries.back()->Push( + gc, ls.Create(this, offset, length)); + return false; + } + if (name == "Count" || name == "Length") { + thrd->call_stack_entries.back()->Push( + gc, static_cast(this->GetBounds().second)); + return false; + } + if (name == "GetAt") { + int64_t i64; + if (GetArgument(args, 0, i64)) { + auto res = this->GetAt(static_cast(i64)); + + thrd->call_stack_entries.back()->Push( + gc, res == -1 ? static_cast(nullptr) + : static_cast(res)); + return false; + } + } + + thrd->call_stack_entries.back()->Push(gc, Undefined()); + return false; +} +bool TByteView::opGetField(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name) { + if (name == "Count" || name == "Length") { + thrd->call_stack_entries.back()->Push( + gc, static_cast(this->GetBounds().second)); + return false; + } + thrd->call_stack_entries.back()->Push(gc, Undefined()); + return false; +} +void TByteView::CopyTo(TMutByteView *view) { + auto myBounds = this->GetBounds(); + if (myBounds.first == nullptr || myBounds.second == 0) + return; + auto theirBounds = view->GetMutableBoundsConstrained(0, myBounds.second); + + if (theirBounds.first == nullptr || theirBounds.second == 0) + return; + + memcpy(theirBounds.first, myBounds.first, theirBounds.second); +} +void TByteView::CopyTo(TMutByteView *view, size_t srcOffset, size_t destOffset, + size_t length) { + auto myBounds = this->GetBoundsConstrained(srcOffset, length); + if (myBounds.first == nullptr || myBounds.second == 0) + return; + auto theirBounds = + view->GetMutableBoundsConstrained(destOffset, myBounds.second); + + if (theirBounds.first == nullptr || theirBounds.second == 0) + return; + + memcpy(theirBounds.first, myBounds.first, theirBounds.second); +} +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/byteviews/mutbyteview.cpp b/src/types/byteviews/mutbyteview.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/types/byteviews/resource.cpp b/src/types/byteviews/resource.cpp new file mode 100644 index 0000000..bb68b5f --- /dev/null +++ b/src/types/byteviews/resource.cpp @@ -0,0 +1,10 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { +TResource::TResource(std::vector &&bytes) : bytes(std::move(bytes)) {} +std::pair TResource::GetBounds() const { + return std::pair(bytes.data(), bytes.size()); +} + +std::string TResource::TypeName() { return "Resource"; } +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/byteviews/string.cpp b/src/types/byteviews/string.cpp new file mode 100644 index 0000000..689257c --- /dev/null +++ b/src/types/byteviews/string.cpp @@ -0,0 +1,123 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { + +TString::TString() {} +TString::TString(std::string_view str) : text(str) {} +TString::TString(const char *text, size_t len) : text(text, len) {} +TString::TString(std::string_view left, std::string_view right) { + text.reserve(left.size() + right.size()); + text.append(left.begin(), left.end()); + text.append(right.begin(), right.end()); +} +TString::TString(std::string &&str) : text(std::move(str)) {} + +const std::string &TString::GetString() const { return this->text; } + +std::pair TString::GetBounds() const { + return std::pair( + reinterpret_cast(text.data()), text.size()); +} + +std::string TString::TypeName() { return "String"; } + +TString *TString::ToString(GCList &ls) { + ls.Add(this); + return this; +} + +bool TString::opAdd(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs) { + TString *rStr; + char rChr; + if (GetObjectHeap(rhs, rStr)) { + GCList ls(gc); + thrd->call_stack_entries.back()->Push( + gc, ls.Create(this->GetString(), rStr->GetString())); + return false; + } + if (GetObject(rhs, rChr)) { + GCList ls(gc); + thrd->call_stack_entries.back()->Push( + gc, + ls.Create(this->GetString(), std::string_view(&rChr, 1))); + return false; + } + + thrd->call_stack_entries.back()->Push(gc, Undefined()); + return false; +} +bool TString::opLessThan(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs) { + + TString *rStr; + if (GetObjectHeap(rhs, rStr)) { + thrd->call_stack_entries.back()->Push(gc, this->GetString() < + rStr->GetString()); + return false; + } + + thrd->call_stack_entries.back()->Push(gc, Undefined()); + return false; +} +bool TString::opGreaterThan(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs) { + + TString *rStr; + if (GetObjectHeap(rhs, rStr)) { + thrd->call_stack_entries.back()->Push(gc, this->GetString() > + rStr->GetString()); + return false; + } + + thrd->call_stack_entries.back()->Push(gc, Undefined()); + return false; +} +bool TString::opLessThanEqual(InterperterThread *thrd, std::shared_ptr gc, + TObject rhs) { + + TString *rStr; + if (GetObjectHeap(rhs, rStr)) { + + thrd->call_stack_entries.back()->Push(gc, this->GetString() <= + rStr->GetString()); + return false; + } + + thrd->call_stack_entries.back()->Push(gc, Undefined()); + return false; +} +bool TString::opGreaterThanEqual(InterperterThread *thrd, + std::shared_ptr gc, TObject rhs) { + + TString *rStr; + if (GetObjectHeap(rhs, rStr)) { + + thrd->call_stack_entries.back()->Push(gc, this->GetString() >= + rStr->GetString()); + return false; + } + + thrd->call_stack_entries.back()->Push(gc, Undefined()); + return false; +} +bool TString::IsEqualTo(std::shared_ptr gc, TObject rhs) { + TString *rStr; + if (GetObjectHeap(rhs, rStr)) { + if (this == rStr) + return true; + return this->GetString() == rStr->GetString(); + } + return false; +} +bool TString::IsNotEqualTo(std::shared_ptr gc, TObject rhs) { + TString *rStr; + if (GetObjectHeap(rhs, rStr)) { + if (this == rStr) + return false; + return this->GetString() != rStr->GetString(); + } + return true; +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/closure.cpp b/src/types/closure.cpp index b675373..4a8e7df 100644 --- a/src/types/closure.cpp +++ b/src/types/closure.cpp @@ -9,7 +9,7 @@ TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) { } TObject TArgWrapper::Call(GCList &ls, std::vector args) { auto cse = GC::GetCurrentFunction(); - TList *argList = TList::Create(ls); + TList *argList = ls.Create(); argList->items = args; TObject v = this->callable->Call(ls, {argList}); GC::SetCurrentFunction(cse); diff --git a/src/types/dictionary.cpp b/src/types/dictionary.cpp index e773453..9d1a382 100644 --- a/src/types/dictionary.cpp +++ b/src/types/dictionary.cpp @@ -45,7 +45,7 @@ TObject TDynamicDictionary::CallMethod(GCList &ls, std::string name, ls.GetGC()->BarrierBegin(); dict->SetValue("Type", "CallMethod"); dict->SetValue("Name", name); - auto argVal = TList::Create(ls); + auto argVal = ls.Create(); argVal->items = args; dict->SetValue("Arguments", argVal); ls.GetGC()->BarrierEnd(); diff --git a/src/types/list.cpp b/src/types/list.cpp index fb6eb2b..3988e8d 100644 --- a/src/types/list.cpp +++ b/src/types/list.cpp @@ -19,7 +19,7 @@ int64_t TDynamicList::Count(GCList &ls) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Count"); + dict->SetValue("Type", ls.FromString("Count")); ls.GetGC()->BarrierEnd(); auto res = cb->Call(ls, {dict}); int64_t n; @@ -31,7 +31,7 @@ TObject TDynamicList::Add(GCList &ls, TObject v) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Add"); + dict->SetValue("Type", ls.FromString("Add")); dict->SetValue("Value", v); ls.GetGC()->BarrierEnd(); return cb->Call(ls, {dict}); @@ -40,7 +40,7 @@ TObject TDynamicList::Insert(GCList &ls, int64_t index, TObject v) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Insert"); + dict->SetValue("Type", ls.FromString("Insert")); dict->SetValue("Index", index); dict->SetValue("Value", v); ls.GetGC()->BarrierEnd(); @@ -49,14 +49,14 @@ TObject TDynamicList::Insert(GCList &ls, int64_t index, TObject v) { TObject TDynamicList::Clear(GCList &ls) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Clear"); + dict->SetValue("Type", ls.FromString("Clear")); ls.GetGC()->BarrierEnd(); return cb->Call(ls, {dict}); } TObject TDynamicList::Remove(GCList &ls, TObject obj) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "Remove"); + dict->SetValue("Type", ls.FromString("Remove")); dict->SetValue("Value", obj); ls.GetGC()->BarrierEnd(); @@ -65,7 +65,7 @@ TObject TDynamicList::Remove(GCList &ls, TObject obj) { TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "RemoveAllEqual"); + dict->SetValue("Type", ls.FromString("RemoveAllEqual")); dict->SetValue("Value", obj); ls.GetGC()->BarrierEnd(); @@ -74,7 +74,7 @@ TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) { TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "RemoveAt"); + dict->SetValue("Type", ls.FromString("RemoveAt")); dict->SetValue("Index", index); ls.GetGC()->BarrierEnd(); @@ -83,7 +83,7 @@ TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) { TObject TDynamicList::ToString(GCList &ls) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "ToString"); + dict->SetValue("Type", ls.FromString("ToString")); ls.GetGC()->BarrierEnd(); return cb->Call(ls, {dict}); @@ -93,7 +93,7 @@ TObject TDynamicList::GetAt(GCList &ls, int64_t index) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "GetAt"); + dict->SetValue("Type", ls.FromString("GetAt")); dict->SetValue("Index", index); ls.GetGC()->BarrierEnd(); return cb->Call(ls, {dict}); @@ -102,7 +102,7 @@ TObject TDynamicList::GetAt(GCList &ls, int64_t index) { TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) { auto dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); - dict->SetValue("Type", "SetAt"); + dict->SetValue("Type", ls.FromString("SetAt")); dict->SetValue("Index", index); dict->SetValue("Value", val); ls.GetGC()->BarrierEnd(); @@ -114,8 +114,7 @@ TDynamicList::~TDynamicList() {} TByteArray *TByteArray::Create(GCList &ls) { return ls.Create(); } TByteArray *TByteArray::Create(GCList *ls) { return ls->Create(); } -TList *TList::Create(GCList *gc) { return gc->Create(); } -TList *TList::Create(GCList &gc) { return gc.Create(); } + void TList::Add(TObject value) { this->items.push_back(value); } void TList::Set(int64_t index, TObject value) { if (index >= 0 && index < this->Count()) { @@ -148,4 +147,201 @@ void TList::Mark() { GC::Mark(item); } } +std::string TList::TypeName() { return "List"; } +bool TList::opGetField(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name) { + auto &cse = thrd->call_stack_entries; + if (name == "Count" || name == "Length") { + int64_t len = this->Count(); + if (len < 0) + len = 0; + + cse.back()->Push(gc, len); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; +} +bool TList::opExecuteMethod(InterperterThread *thrd, std::shared_ptr gc, + const std::string &name, + const std::vector &args) { + + auto &cse = thrd->call_stack_entries; + GCList ls(gc); + + if (name == "GetEnumerator") { + cse.back()->Push(gc, ls.Create(this)); + return false; + } else if (name == "ToString") { + + cse.back()->Push(gc, Json_Encode(this)); + return false; + + } else if (name == "Insert") { + if (args.size() != 2) { + throw VMException("List.Insert must only accept two arguments"); + } + int64_t index; + + if (!GetArgument(args, 0, index)) { + throw VMException("List.Insert first argument must be Long"); + } + + gc->BarrierBegin(); + this->Insert(index, args[1]); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (name == "Add") { + if (args.size() != 1) { + throw VMException("List.Add must only accept one argument"); + } + gc->BarrierBegin(); + this->Add(args[0]); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (name == "Contains") { + if (args.size() != 1) { + throw VMException("List.Contains must only accept one argument"); + } + gc->BarrierBegin(); + for (int64_t i = 0; i < this->Count(); i++) { + auto item = this->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + cse.back()->Push(gc, true); + return false; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, false); + return false; + } else if (name == "IndexOf") { + // IndexOf(obj, $idx) + if (args.size() < 1 || args.size() > 2) { + throw VMException("List.IndexOf must either have one " + "or two arguments"); + } + + int64_t i = 0; + + GetArgument(args, 1, i); + gc->BarrierBegin(); + for (; i < this->Count(); i++) { + auto item = this->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + + cse.back()->Push(gc, i); + return false; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, (int64_t)-1); + return false; + } else if (name == "RemoveAllEqual") { + if (args.size() != 1) { + throw VMException("List.RemoveAllEqual must only " + "accept one argument"); + } + + gc->BarrierBegin(); + for (int64_t i = 0; i < this->Count(); i++) { + auto item = this->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + gc->BarrierBegin(); + this->RemoveAt(i); + i--; + } else + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (name == "Remove") { + if (args.size() != 1) { + throw VMException("List.Remove must only accept one argument"); + } + + gc->BarrierBegin(); + for (int64_t i = 0; i < this->Count(); i++) { + auto item = this->Get(i); + gc->BarrierEnd(); + if (Equals(gc, args[0], item)) { + gc->BarrierBegin(); + this->RemoveAt(i); + gc->BarrierEnd(); + break; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (name == "RemoveAt") { + if (args.size() != 1) { + throw VMException("List.RemoveAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("List.RemoveAt must only accept a long"); + } + gc->BarrierBegin(); + this->RemoveAt(std::get(args[0])); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (name == "Clear") { + gc->BarrierBegin(); + this->Clear(); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } else if (name == "GetAt") { + if (args.size() != 1) { + throw VMException("List.GetAt must only accept one argument"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("List.GetAt must only accept a long"); + } + + int64_t index = std::get(args[0]); + if (index >= 0 && index < this->Count()) { + cse.back()->Push(gc, this->Get(index)); + return false; + } + + } else if (name == "SetAt") { + if (args.size() != 2) { + throw VMException("List.SetAt must only accept two arguments"); + } + + if (!std::holds_alternative(args[0])) { + throw VMException("List.SetAt first argument must only " + "accept a long"); + } + + int64_t index = std::get(args[0]); + if (index >= 0 && index < this->Count()) { + this->Set(index, args[1]); + return false; + } + + } + + else if (name == "Count" || name == "Length") { + gc->BarrierBegin(); + cse.back()->Push(gc, this->Count()); + gc->BarrierEnd(); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; +} + }; // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/queryable.cpp b/src/types/queryable.cpp index 4a43a81..e638bb9 100644 --- a/src/types/queryable.cpp +++ b/src/types/queryable.cpp @@ -32,7 +32,7 @@ TList *TQueryable::ToList(GCList &ls) { auto enumerator = this->GetEnumerator(ls); if (enumerator == nullptr) return nullptr; - auto list = TList::Create(ls); + auto list = ls.Create(); while (enumerator->MoveNext(gc)) { gc->BarrierBegin(); list->Add(enumerator->GetCurrent(ls)); diff --git a/src/types/streams/memorystream.cpp b/src/types/streams/memorystream.cpp new file mode 100644 index 0000000..6d4c5bf --- /dev/null +++ b/src/types/streams/memorystream.cpp @@ -0,0 +1,30 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { +TMemoryStream::TMemoryStream( + std::shared_ptr strm) + : strm(strm) {} +std::shared_ptr TMemoryStream::GetStream() { + return this->strm; +} +TObject TMemoryStream::CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args) { + if (name == "GetBytes") { + return ls.Create(strm); + } + return ITStream::CallMethod(thrd, ls, name, args); +} +TMemoryStreamMutByteView::TMemoryStreamMutByteView( + std::shared_ptr strm) + : strm(strm) {} +std::pair TMemoryStreamMutByteView::GetMutableBounds() { + if (!strm) + return std::pair(nullptr, 0); + auto &buff = strm->GetBuffer(); + return std::pair(buff.data(), buff.size()); +} + +std::string TMemoryStream::TypeName() { return "MemoryStream"; } + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/streams/networkstream.cpp b/src/types/streams/networkstream.cpp new file mode 100644 index 0000000..01c2bb6 --- /dev/null +++ b/src/types/streams/networkstream.cpp @@ -0,0 +1,165 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { +TNetworkStream::TNetworkStream( + std::shared_ptr strm) + : strm(strm) {} +std::shared_ptr +TNetworkStream::GetStream() { + return this->strm; +} +TObject TNetworkStream::CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args) { + int64_t n0; + bool bc; + if (name == "setBroadcast" && GetArgument(args, 0, bc)) + strm->SetBroadcast(bc); + if (name == "setNoDelay" && GetArgument(args, 0, bc)) + strm->SetNoDelay(bc); + if (name == "setReuseAddress" && GetArgument(args, 0, bc)) + strm->SetReuseAddress(bc); + if (name == "setReusePort" && GetArgument(args, 0, bc)) + strm->SetReusePort(bc); + if (name == "MulticastTTL" && GetArgument(args, 0, n0)) + strm->SetMulticastTTL((uint8_t)n0); + if (name == "getPort" || name == "GetPort") { + return (int64_t)strm->GetPort(); + } + + if (name == "SetMulticastMembership") { + std::string ma; + std::string ifaceIP = "0.0.0.0"; + if (GetArgument(args, 0, ma)) { + GetArgument(args, 1, ifaceIP); + strm->SetMulticastMembership(ma, ifaceIP); + } + return Undefined(); + } + if (name == "Bind") { + std::string ip; + int64_t port; + if (GetArgument(args, 0, ip) && GetArgument(args, 1, port)) + strm->Bind(ip, (uint16_t)port); + + return Undefined(); + } + + if (name == "Accept") { + std::string ip; + uint16_t port; + auto strm2 = strm->Accept(ip, port); + + if (strm2 == + nullptr) // just in case, so we don't get a bugged TNetworkStream + return nullptr; + + std::array list = { + TDItem("IP", ls.FromString(ip)), + TDItem("Port", (int64_t)port), + TDItem("Stream", ls.Create(strm2)), + }; + + return ls.Create(list.begin(), list.end()); + } + if (name == "Listen") { + int64_t backlog; + if (GetArgument(args, 0, backlog)) { + strm->Listen((int32_t)backlog); + } else { + strm->Listen(10); + } + + return Undefined(); + } + if (name == "ReadFrom") { + TByteArray *data; + int64_t offset; + int64_t length; + + if (name == "Read") { + TMutByteView *bytes; + if (GetArgumentHeap(args, 0, bytes)) { + int64_t offset; + int64_t length; + if (GetArgument(args, 1, offset) && + GetArgument(args, 2, length)) { + auto safe = bytes->GetMutableBoundsConstrained( + (size_t)offset, (size_t)length); + if (safe.first != nullptr) { + std::string ip = {}; + uint16_t port = 0; + auto read = + strm->ReadFrom(safe.first, safe.second, ip, port); + std::array list = { + TDItem("IP", ls.FromString(ip)), + TDItem("Port", (int64_t)port), + TDItem("Read", (int64_t)read), + }; + return ls.Create(list.begin(), list.end()); + } else { + return nullptr; + } + } + + auto bounds = bytes->GetMutableBounds(); + + if (bounds.first) { + std::string ip = {}; + uint16_t port = 0; + auto read = + strm->ReadFrom(bounds.first, bounds.second, ip, port); + std::array list = { + TDItem("IP", ls.FromString(ip)), + TDItem("Port", (int64_t)port), + TDItem("Read", (int64_t)read), + }; + return ls.Create(list.begin(), list.end()); + } + } + + return Undefined(); + } + } + if (name == "WriteTo") { + + // strm->WriteTo(buff, ip, port) + // strm->WriteTo(buff, off, len, ip, port) + + TByteView *bytes; + if (GetArgumentHeap(args, 0, bytes)) { + int64_t offset; + int64_t length; + TString *ip; + int64_t port; + if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) { + if (!(GetArgumentHeap(args, 3, ip) && + GetArgument(args, 4, port))) + return Undefined(); + auto safe = + bytes->GetBoundsConstrained((size_t)offset, (size_t)length); + if (safe.first != nullptr) { + return strm->WriteTo(safe.first, safe.second, + ip->GetString(), (uint16_t)port); + } else + return nullptr; + } + if (!(GetArgumentHeap(args, 1, ip) && GetArgument(args, 2, port))) + return Undefined(); + auto bounds = bytes->GetBounds(); + + if (bounds.first) { + + return (int64_t)strm->WriteTo(bounds.first, bounds.second, + ip->GetString(), (uint16_t)port); + } + } + + return Undefined(); + } + + return ITStream::CallMethod(thrd, ls, name, args); +} + +std::string TNetworkStream::TypeName() { return "NetworkStream"; } +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/streams/stream.cpp b/src/types/streams/stream.cpp new file mode 100644 index 0000000..2f4aefe --- /dev/null +++ b/src/types/streams/stream.cpp @@ -0,0 +1,251 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { + +#define CROSSLANG_TSTREAM_NAMES \ + CROSSLANG_TSTREAM_NAME_ENT(getCanRead) \ + CROSSLANG_TSTREAM_NAME_ENT(getCanSeek) \ + CROSSLANG_TSTREAM_NAME_ENT(getCanWrite) \ + CROSSLANG_TSTREAM_NAME_ENT(getEndOfStream) \ + CROSSLANG_TSTREAM_NAME_ENT(getLength) \ + CROSSLANG_TSTREAM_NAME_ENT(getPosition) \ + CROSSLANG_TSTREAM_NAME_ENT(setPosition) \ + CROSSLANG_TSTREAM_NAME_ENT(Close) \ + CROSSLANG_TSTREAM_NAME_ENT(Dispose) \ + CROSSLANG_TSTREAM_NAME_ENT(CopyTo) \ + CROSSLANG_TSTREAM_NAME_ENT(CopyToLimit) \ + CROSSLANG_TSTREAM_NAME_ENT(Flush) \ + CROSSLANG_TSTREAM_NAME_ENT(Read) \ + CROSSLANG_TSTREAM_NAME_ENT(ReadBlock) \ + CROSSLANG_TSTREAM_NAME_ENT(ReadByte) \ + CROSSLANG_TSTREAM_NAME_ENT(Seek) \ + CROSSLANG_TSTREAM_NAME_ENT(SetRecvTimeout) \ + CROSSLANG_TSTREAM_NAME_ENT(SetSendTimeout) \ + CROSSLANG_TSTREAM_NAME_ENT(Write) \ + CROSSLANG_TSTREAM_NAME_ENT(WriteText) \ + CROSSLANG_TSTREAM_NAME_ENT(WriteBlock) \ + CROSSLANG_TSTREAM_NAME_ENT(WriteByte) + +enum TStreamFuncNameEnum { +#define CROSSLANG_TSTREAM_NAME_ENT(name) TSF_##name, + CROSSLANG_TSTREAM_NAMES +#undef CROSSLANG_TSTREAM_NAME_ENT +}; // namespace Tesses::CrossLang + +static std::unordered_map + stream_func_names = { +#define CROSSLANG_TSTREAM_NAME_ENT(name) {#name, TSF_##name}, + CROSSLANG_TSTREAM_NAMES +#undef CROSSLANG_TSTREAM_NAME_ENT +}; + +bool ITStream::Exists(std::string_view str) { + return stream_func_names.count(str) != 0; +} + +TObject ITStream::CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args) { + + auto strm = GetStream(); + if (strm == nullptr) + return Undefined(); + + auto result = stream_func_names.find(name); + + if (result == stream_func_names.end()) + return Undefined(); + + switch (result->second) { + case TSF_getCanRead: + return strm->CanRead(); + case TSF_getCanSeek: + return strm->CanSeek(); + case TSF_getCanWrite: + return strm->CanWrite(); + case TSF_getEndOfStream: + return strm->EndOfStream(); + case TSF_getLength: + return strm->GetLength(); + case TSF_getPosition: + return strm->GetPosition(); + case TSF_setPosition: { + int64_t n; + if (GetArgument(args, 0, n)) { + strm->Seek(n, Tesses::Framework::Streams::SeekOrigin::Begin); + return n; + } + return Undefined(); + } + case TSF_Close: + case TSF_Dispose: + strm->Close(); + return Undefined(); + case TSF_CopyTo: { + ITStream *strmDest; + if (GetArgumentHeap(args, 0, strmDest)) { + int64_t n = 1024; + GetArgument(args, 1, n); + strm->CopyTo(strmDest->GetStream(), (size_t)n); + } + return Undefined(); + } + case TSF_CopyToLimit: { + ITStream *strmDest; + int64_t len; + if (GetArgumentHeap(args, 0, strmDest) && GetArgument(args, 1, len)) { + int64_t n = 1024; + GetArgument(args, 2, n); + strm->CopyToLimit(strmDest->GetStream(), (uint64_t)len, (size_t)n); + } + return Undefined(); + } + case TSF_Flush: + strm->Flush(); + return Undefined(); + case TSF_Read: { + TMutByteView *bytes; + if (GetArgumentHeap(args, 0, bytes)) { + int64_t offset; + int64_t length; + if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) { + auto safe = bytes->GetMutableBoundsConstrained((size_t)offset, + (size_t)length); + if (safe.first != nullptr) + return strm->Read(safe.first, safe.second); + else + return 0; + } + + auto bounds = bytes->GetMutableBounds(); + + if (bounds.first) { + return (int64_t)strm->Read(bounds.first, bounds.second); + } + } + + return Undefined(); + } + case TSF_ReadBlock: { + TMutByteView *bytes; + if (GetArgumentHeap(args, 0, bytes)) { + int64_t offset; + int64_t length; + if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) { + auto safe = bytes->GetMutableBoundsConstrained((size_t)offset, + (size_t)length); + if (safe.first != nullptr) + return strm->ReadBlock(safe.first, safe.second); + else + return 0; + } + + auto bounds = bytes->GetMutableBounds(); + + if (bounds.first) { + return (int64_t)strm->ReadBlock(bounds.first, bounds.second); + } + } + + return Undefined(); + } + case TSF_ReadByte: { + return (int64_t)strm->ReadByte(); + } + case TSF_Seek: { + int64_t offset; + int64_t whence; + if (GetArgument(args, 0, offset) && GetArgument(args, 1, whence)) { + strm->Seek(offset, (Tesses::Framework::Streams::SeekOrigin)whence); + } + return Undefined(); + } + case TSF_SetRecvTimeout: { + int64_t to; + if (GetArgument(args, 0, to)) { + strm->SetRecvTimeout((uint64_t)to); + } + return Undefined(); + } + case TSF_SetSendTimeout: { + int64_t to; + if (GetArgument(args, 0, to)) { + strm->SetSendTimeout((uint64_t)to); + } + return Undefined(); + } + case TSF_Write: { + TByteView *bytes; + if (GetArgumentHeap(args, 0, bytes)) { + int64_t offset; + int64_t length; + if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) { + auto safe = + bytes->GetBoundsConstrained((size_t)offset, (size_t)length); + if (safe.first != nullptr) + return strm->Write(safe.first, safe.second); + else + return 0; + } + + auto bounds = bytes->GetBounds(); + + if (bounds.first) { + return (int64_t)strm->Write(bounds.first, bounds.second); + } + } + + return Undefined(); + } + case TSF_WriteText: { // for compat + TByteView *bytes; + if (GetArgumentHeap(args, 0, bytes)) { + auto bounds = bytes->GetBounds(); + if (bounds.first) + strm->WriteBlock(bounds.first, bounds.second); + } + return Undefined(); + } + case TSF_WriteBlock: { + TByteView *bytes; + if (GetArgumentHeap(args, 0, bytes)) { + int64_t offset; + int64_t length; + if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) { + auto safe = + bytes->GetBoundsConstrained((size_t)offset, (size_t)length); + if (safe.first != nullptr) + strm->WriteBlock(safe.first, safe.second); + + return Undefined(); + } + + auto bounds = bytes->GetBounds(); + + if (bounds.first) { + strm->WriteBlock(bounds.first, bounds.second); + } + } + + return Undefined(); + } + case TSF_WriteByte: { + int64_t b0; + if (GetArgument(args, 0, b0)) { + strm->WriteByte((uint8_t)b0); + } + return Undefined(); + } + } + + return Undefined(); +} +std::string ITStream::TypeName() { return "Stream"; } + +TStream::TStream(std::shared_ptr strm) + : strm(strm) {} +std::shared_ptr TStream::GetStream() { + return this->strm; +} + +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/streams/streamwrapper.cpp b/src/types/streams/streamwrapper.cpp new file mode 100644 index 0000000..ccf522c --- /dev/null +++ b/src/types/streams/streamwrapper.cpp @@ -0,0 +1,56 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { +TObjectStreamWrapper::TObjectStreamWrapper(std::shared_ptr strm) + : strm(strm) {} +TObject TObjectStreamWrapper::CallMethod(InterperterThread *thrd, GCList &ls, + const std::string &name, + const std::vector &args) { + if (Exists(name)) { + return ITStream::CallMethod(thrd, ls, name, args); + } + + TDictionary *dict; + + if (GetObjectHeap(strm->obj, dict)) { + auto val = dict->GetValue(name); + + TCallable *call; + if (GetObjectHeap(val, call)) { + + auto closure = dynamic_cast(call); + + if (closure && !closure->closure->args.empty() && + closure->closure->args[0]->GetString() == "this") { + std::vector args_new; + args_new.reserve(args.size() + 1); + args_new.push_back(dict); + args_new.insert(args_new.cend(), args.begin(), args.end()); + + return closure->Call(ls, args_new); + } else { + return call->Call(ls, args); + } + } + if (name.size() > 3 && name[1] == 'e' && name[2] == 't') { + char c = name[0]; + if (c == 'g') { + auto fieldName = name.substr(3); + return dict->GetValue(fieldName); + } else if (c == 's' && !args.empty()) { + auto fieldName = name.substr(3); + dict->SetValue(fieldName, args[0]); + ls.Add(args[0]); + return args[0]; + } + } + } + + return Undefined(); +} +std::shared_ptr +TObjectStreamWrapper::GetStream() { + return this->strm; +} +std::string TObjectStreamWrapper::TypeName() { return "CustomStream"; } +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/bc/add.cpp b/src/vm/bc/add.cpp index 39807c7..056d21a 100644 --- a/src/vm/bc/add.cpp +++ b/src/vm/bc/add.cpp @@ -121,6 +121,15 @@ bool InterperterThread::Add(std::shared_ptr gc) { cse.back()->Push(gc, str); } else if (std::holds_alternative(left)) { auto obj = std::get(left); + + if (obj == nullptr) { + cse.back()->Push(gc, Undefined()); + return false; + } + + return obj->opAdd(this, gc, right); + + /* auto dict = dynamic_cast(obj); auto dynDict = dynamic_cast(obj); auto natObj = dynamic_cast(obj); @@ -156,6 +165,7 @@ bool InterperterThread::Add(std::shared_ptr gc) { } else { cse.back()->Push(gc, Undefined()); } + */ } else { cse.back()->Push(gc, Undefined()); diff --git a/src/vm/bc/executemethod2.cpp b/src/vm/bc/executemethod2.cpp index 36b604f..6a0fdfb 100644 --- a/src/vm/bc/executemethod2.cpp +++ b/src/vm/bc/executemethod2.cpp @@ -58,7 +58,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, if (GetArgument(args, 0, str)) { std::smatch m; if (std::regex_search(str, m, regex)) { - auto myLs = TList::Create(ls); + auto myLs = ls.Create(); gc->BarrierBegin(); for (auto item : m) { auto itm = TDictionary::Create(ls); @@ -288,7 +288,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, std::get(instance); if (key == "GetEnumerator") { - TList *_ls = TList::Create(ls); + TList *_ls = ls.Create(); for (auto item : path.path) { _ls->Add(item); } @@ -683,7 +683,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, auto res = Tesses::Framework::Http::HttpUtils::SplitString( str, delimiter, count); - TList *mls = TList::Create(ls); + TList *mls = ls.Create(); for (auto item : res) { if (!removeEmpty || !item.empty()) mls->Add(item); @@ -825,7 +825,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, std::vector lines; textReader->ReadAllLines(lines); gc->BarrierBegin(); - TList *list = TList::Create(ls); + TList *list = ls.Create(); for (auto &item : lines) list->Add(item); gc->BarrierEnd(); @@ -1072,8 +1072,6 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, std::get>( instance); if (strm != nullptr) { - auto memStrm = std::dynamic_pointer_cast< - Tesses::Framework::Streams::MemoryStream>(strm); auto netStrm = std::dynamic_pointer_cast< Tesses::Framework::Streams::NetworkStream>(strm); @@ -1090,134 +1088,8 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, return InvokeMethod(ls, o, dict2, args); } } - if (memStrm != nullptr) { - if (key == "GetBytes") { - auto res = TByteArray::Create(ls); - res->data = memStrm->GetBuffer(); - cse.back()->Push(gc, res); - return false; - } - } + if (netStrm != nullptr) { - if (key == "SetMulticastMembership") { - std::string ma; - std::string ifaceIP = "0.0.0.0"; - if (GetArgument(args, 0, ma)) { - GetArgument(args, 1, ifaceIP); - netStrm->SetMulticastMembership(ma, ifaceIP); - } - cse.back()->Push(gc, Undefined()); - return false; - } - if (key == "GetPort") { - cse.back()->Push(gc, (int64_t)netStrm->GetPort()); - return false; - } - if (key == "Bind") { - std::string ip; - int64_t port; - if (GetArgument(args, 0, ip) && - GetArgument(args, 1, port)) - netStrm->Bind(ip, (uint16_t)port); - - cse.back()->Push(gc, nullptr); - return false; - } - if (key == "Accept") { - std::string ip; - uint16_t port; - auto strm = netStrm->Accept(ip, port); - TDictionary *dict = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->SetValue("IP", ip); - dict->SetValue("Port", (int64_t)port); - dict->SetValue("Stream", strm); - - gc->BarrierEnd(); - cse.back()->Push(gc, dict); - return false; - } - if (key == "Listen") { - int64_t backlog; - if (GetArgument(args, 0, backlog)) { - netStrm->Listen((int32_t)backlog); - } else { - netStrm->Listen(10); - } - - cse.back()->Push(gc, nullptr); - return false; - } - if (key == "ReadFrom") { - TByteArray *data; - int64_t offset; - int64_t length; - if (GetArgumentHeap(args, 0, data) && - GetArgument(args, 1, offset) && - GetArgument(args, 2, length)) { - size_t off = (size_t)offset; - size_t len = (size_t)length; - std::string ip = {}; - uint16_t port = 0; - - if (off < len) - - len = netStrm->ReadFrom( - data->data.data() + off, - std::min(len, - std::min(data->data.size() - off, - data->data.size())), - ip, port); - - else - len = 0; - - TDictionary *dict = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->SetValue("IP", ip); - dict->SetValue("Port", (int64_t)port); - dict->SetValue("Read", (int64_t)len); - - gc->BarrierEnd(); - cse.back()->Push(gc, dict); - - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if (key == "WriteTo") { - TByteArray *data; - int64_t offset; - int64_t length; - std::string ip; - int64_t port; - if (GetArgumentHeap(args, 0, data) && - GetArgument(args, 1, offset) && - GetArgument(args, 2, length) && - GetArgument(args, 3, ip) && - GetArgument(args, 4, port)) { - size_t off = (size_t)offset; - size_t len = (size_t)length; - - if (off < len) - - len = netStrm->WriteTo( - data->data.data() + off, - std::min(len, - std::min(data->data.size() - off, - data->data.size())), - ip, (int64_t)port); - - else - len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } } if (key == "Read") { @@ -1966,7 +1838,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, return false; } else if (std::holds_alternative(instance)) { auto obj = std::get(instance); - auto list = dynamic_cast(obj); + auto dynList = dynamic_cast(obj); auto bArray = dynamic_cast(obj); auto dict = dynamic_cast(obj); @@ -3336,190 +3208,6 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, } cse.back()->Push(gc, Undefined()); return false; - } else if (list != nullptr) { - - if (key == "GetEnumerator") { - cse.back()->Push(gc, TListEnumerator::Create(ls, list)); - return false; - } else if (key == "ToString") { - - cse.back()->Push(gc, Json_Encode(list)); - return false; - - } else if (key == "Insert") { - if (args.size() != 2) { - throw VMException( - "List.Insert must only accept two arguments"); - } - int64_t index; - - if (!GetArgument(args, 0, index)) { - throw VMException( - "List.Insert first argument must be Long"); - } - - gc->BarrierBegin(); - list->Insert(index, args[1]); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } else if (key == "Add") { - if (args.size() != 1) { - throw VMException( - "List.Add must only accept one argument"); - } - gc->BarrierBegin(); - list->Add(args[0]); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } else if (key == "Contains") { - if (args.size() != 1) { - throw VMException( - "List.Contains must only accept one argument"); - } - gc->BarrierBegin(); - for (int64_t i = 0; i < list->Count(); i++) { - auto item = list->Get(i); - gc->BarrierEnd(); - if (Equals(gc, args[0], item)) { - cse.back()->Push(gc, true); - return false; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, false); - return false; - } else if (key == "IndexOf") { - // IndexOf(obj, $idx) - if (args.size() < 1 || args.size() > 2) { - throw VMException("List.IndexOf must either have one " - "or two arguments"); - } - - int64_t i = 0; - - GetArgument(args, 1, i); - gc->BarrierBegin(); - for (; i < list->Count(); i++) { - auto item = list->Get(i); - gc->BarrierEnd(); - if (Equals(gc, args[0], item)) { - - cse.back()->Push(gc, i); - return false; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, (int64_t)-1); - return false; - } else 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++) { - auto item = list->Get(i); - gc->BarrierEnd(); - if (Equals(gc, args[0], item)) { - gc->BarrierBegin(); - list->RemoveAt(i); - i--; - } else - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } else 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++) { - auto item = list->Get(i); - gc->BarrierEnd(); - if (Equals(gc, args[0], item)) { - gc->BarrierBegin(); - list->RemoveAt(i); - gc->BarrierEnd(); - break; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } else if (key == "RemoveAt") { - if (args.size() != 1) { - throw VMException( - "List.RemoveAt must only accept one argument"); - } - - if (!std::holds_alternative(args[0])) { - throw VMException( - "List.RemoveAt must only accept a long"); - } - gc->BarrierBegin(); - list->RemoveAt(std::get(args[0])); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } else if (key == "Clear") { - gc->BarrierBegin(); - list->Clear(); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } else if (key == "GetAt") { - if (args.size() != 1) { - throw VMException( - "List.GetAt must only accept one argument"); - } - - if (!std::holds_alternative(args[0])) { - throw VMException("List.GetAt must only accept a long"); - } - - int64_t index = std::get(args[0]); - if (index >= 0 && index < list->Count()) { - cse.back()->Push(gc, list->Get(index)); - return false; - } - - } else if (key == "SetAt") { - if (args.size() != 2) { - throw VMException( - "List.SetAt must only accept two arguments"); - } - - if (!std::holds_alternative(args[0])) { - throw VMException("List.SetAt first argument must only " - "accept a long"); - } - - int64_t index = std::get(args[0]); - if (index >= 0 && index < list->Count()) { - list->Set(index, args[1]); - return false; - } - - } - - else if (key == "Count" || key == "Length") { - gc->BarrierBegin(); - cse.back()->Push(gc, list->Count()); - gc->BarrierEnd(); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; } else if (dynList != nullptr) { if (key == "GetEnumerator") { diff --git a/src/vm/bc/getfield.cpp b/src/vm/bc/getfield.cpp index e967a24..379d8cd 100644 --- a/src/vm/bc/getfield.cpp +++ b/src/vm/bc/getfield.cpp @@ -145,59 +145,6 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, Undefined()); return false; } - if (std::holds_alternative< - std::shared_ptr>( - instance)) { - auto strm = - std::get>( - instance); - if (strm != nullptr) { - auto netStrm = std::dynamic_pointer_cast< - Tesses::Framework::Streams::NetworkStream>(strm); - - if (key == "CanRead") { - - cse.back()->Push(gc, strm->CanRead()); - return false; - } - if (key == "CanWrite") { - - cse.back()->Push(gc, strm->CanWrite()); - return false; - } - if (key == "CanSeek") { - - cse.back()->Push(gc, strm->CanSeek()); - return false; - } - if (key == "EndOfStream") { - - cse.back()->Push(gc, strm->EndOfStream()); - return false; - } - if (key == "Length") { - - cse.back()->Push(gc, strm->GetLength()); - return false; - } - if (key == "Position") { - - cse.back()->Push(gc, strm->GetPosition()); - return false; - } - - if (netStrm != nullptr) { - if (key == "Port") { - cse.back()->Push(gc, (int64_t)netStrm->GetPort()); - return false; - } - } - - cse.back()->Push(gc, Undefined()); - - return false; - } - } if (std::holds_alternative(instance)) { TVMVersion &version = std::get(instance); if (key == "Major") { @@ -391,7 +338,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, file->info); return false; } else if (key == "Dependencies") { - auto list = TList::Create(ls); + auto list = ls.Create(); gc->BarrierBegin(); for (auto item : file->dependencies) { auto res = TDictionary::Create(ls); @@ -403,7 +350,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, list); return false; } else if (key == "Tools") { - auto list = TList::Create(ls); + auto list = ls.Create(); gc->BarrierBegin(); for (auto item : file->tools) { auto res = TDictionary::Create(ls); @@ -415,7 +362,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, list); return false; } else if (key == "Strings") { - auto list = TList::Create(ls); + auto list = ls.Create(); gc->BarrierBegin(); for (auto item : file->name) { list->Add(item); @@ -429,7 +376,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, (int64_t)file->metadata.size()); return false; } else if (key == "Metadata") { - TList *meta = TList::Create(ls); + TList *meta = ls.Create(); gc->BarrierBegin(); for (size_t i = 0; i < file->metadata.size(); i++) { meta->Add(TDictionary::Create( @@ -441,7 +388,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, meta); return false; } else if (key == "Sections") { - TList *sections = TList::Create(ls); + TList *sections = ls.Create(); gc->BarrierBegin(); for (auto &item : file->sections) { TByteArray *ba = TByteArray::Create(ls); @@ -455,7 +402,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, sections); return false; } else if (key == "SupportedVMs") { - TList *supported = TList::Create(ls); + TList *supported = ls.Create(); gc->BarrierBegin(); if (file->vms.empty()) { supported->Add(TDictionary::Create( @@ -471,7 +418,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, supported); return false; } else if (key == "Chunks") { - auto list = TList::Create(ls); + auto list = ls.Create(); gc->BarrierBegin(); for (auto item : file->chunks) { list->Add(item); @@ -482,7 +429,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { cse.back()->Push(gc, list); return false; } else if (key == "Classes") { - auto list = TList::Create(ls); + auto list = ls.Create(); gc->BarrierBegin(); for (uint32_t i = 0; i < (uint32_t)file->classes.size(); @@ -494,13 +441,13 @@ bool InterperterThread::GetField(std::shared_ptr gc) { gc->BarrierEnd(); return false; } else if (key == "Functions") { - auto list = TList::Create(ls); + auto list = ls.Create(); gc->BarrierBegin(); for (auto &item : file->functions) { TDictionary *dict = TDictionary::Create(ls); if (!item.first.empty()) dict->SetValue("Documentation", item.first[0]); - TList *nameParts = TList::Create(ls); + TList *nameParts = ls.Create(); for (size_t i = 1; i < item.first.size(); i++) { nameParts->Add(item.first[i]); } @@ -530,7 +477,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { } if (chunk != nullptr) { if (key == "Arguments") { - auto myargs = TList::Create(ls); + auto myargs = ls.Create(); gc->BarrierBegin(); for (auto item : chunk->args) { myargs->Add(item); @@ -586,7 +533,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { if (closure != nullptr) { if (key == "Arguments") { GCList ls2(gc); - TList *ls = TList::Create(ls2); + TList *ls = ls2.Create(); for (auto arg : closure->closure->args) { ls->Add(arg); } @@ -601,7 +548,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { if (externalMethod != nullptr) { if (key == "Arguments") { GCList ls2(gc); - TList *ls = TList::Create(ls2); + TList *ls = ls2.Create(); for (auto arg : externalMethod->args) { ls->Add(arg); } @@ -635,16 +582,7 @@ bool InterperterThread::GetField(std::shared_ptr gc) { return false; } } - if (list != nullptr) { - if (key == "Count" || key == "Length") { - int64_t len = list->Count(); - if (len < 0) - len = 0; - stk->Push(gc, len); - return false; - } - } if (dynList != nullptr) { if (key == "Count" || key == "Length") { int64_t len = dynList->Count(ls); diff --git a/src/vm/bc/invokemethod.cpp b/src/vm/bc/invokemethod.cpp index e5287b4..af07b5c 100644 --- a/src/vm/bc/invokemethod.cpp +++ b/src/vm/bc/invokemethod.cpp @@ -23,7 +23,7 @@ bool InterperterThread::InvokeMethod(GCList &ls, TObject fn, TObject instance, if (closure != nullptr) { if (!closure->closure->args.empty() && - closure->closure->args[0] == "this") { + closure->closure->args[0].GetString() == "this") { std::vector args2; args2.push_back(instance); args2.insert(args2.end(), args.begin(), args.end()); diff --git a/src/vm/bc/setfield.cpp b/src/vm/bc/setfield.cpp index 0d1295e..4e5092d 100644 --- a/src/vm/bc/setfield.cpp +++ b/src/vm/bc/setfield.cpp @@ -231,32 +231,7 @@ bool InterperterThread::SetField(std::shared_ptr gc) { stk->Push(gc, Undefined()); return false; } - if (std::holds_alternative< - std::shared_ptr>( - instance)) { - auto strm = - std::get>( - instance); - auto netStrm = std::dynamic_pointer_cast< - Tesses::Framework::Streams::NetworkStream>(strm); - if (netStrm != nullptr) { - int64_t n0; - bool bc; - if (key == "Broadcast" && GetObject(value, bc)) - netStrm->SetBroadcast(bc); - if (key == "NoDelay" && GetObject(value, bc)) - netStrm->SetNoDelay(bc); - if (key == "ReuseAddress" && GetObject(value, bc)) - netStrm->SetReuseAddress(bc); - if (key == "ReusePort" && GetObject(value, bc)) - netStrm->SetReusePort(bc); - if (key == "MulticastTTL" && GetObject(value, n0)) - netStrm->SetMulticastTTL((uint8_t)n0); - } - stk->Push(gc, Undefined()); - return false; - } if (std::holds_alternative(instance)) { auto obj = std::get(instance); diff --git a/src/vm/bc/sub.cpp b/src/vm/bc/sub.cpp index e1db190..8d9ad81 100644 --- a/src/vm/bc/sub.cpp +++ b/src/vm/bc/sub.cpp @@ -67,7 +67,15 @@ bool InterperterThread::Sub(std::shared_ptr gc) { std::make_shared((*l) - (*r))); } else if (std::holds_alternative(left)) { auto obj = std::get(left); - auto dict = dynamic_cast(obj); + + if (obj == nullptr) { + cse.back()->Push(gc, Undefined()); + return false; + } + + return obj->opSub(this, gc, right); + + /*auto dict = dynamic_cast(obj); auto dynDict = dynamic_cast(obj); auto natObj = dynamic_cast(obj); @@ -104,7 +112,7 @@ bool InterperterThread::Sub(std::shared_ptr gc) { } else { cse.back()->Push(gc, Undefined()); } - + */ } else { cse.back()->Push(gc, Undefined()); } diff --git a/src/vm/filereader.cpp b/src/vm/filereader.cpp index 509634d..22205f0 100644 --- a/src/vm/filereader.cpp +++ b/src/vm/filereader.cpp @@ -43,15 +43,18 @@ void TFile::Ensure(std::shared_ptr stream, "End of file, could not read " + std::to_string((int64_t)len) + " byte(s)., offset=" + std::to_string(stream->GetLength())); } -std::string TFile::EnsureString( - std::shared_ptr stream) { +void TFile::EnsureString( + GCList &ls, std::shared_ptr stream) { auto len = EnsureInt(stream); - if (len == 0) - return {}; + if (len == 0) { + this->strings.push_back(ls.FromString("")); + return; + } std::string str = {}; str.resize((size_t)len); Ensure(stream, (uint8_t *)str.data(), str.size()); - return str; + + this->strings.push_back(ls.Create(std::move(str))); } uint32_t @@ -60,7 +63,7 @@ TFile::EnsureInt(std::shared_ptr stream) { Ensure(stream, buffer, 4); return BitConverter::ToUint32BE(buffer[0]); } -std::string +TString * TFile::GetString(std::shared_ptr stream) { uint32_t index = EnsureInt(stream); if (index >= this->strings.size()) @@ -75,7 +78,7 @@ void TFile::EnsureCanRunInCrossLang() { return; for (auto item : this->vms) { - if (item.first == VMName) { + if (item.first->GetString() == VMName) { return; } } @@ -83,7 +86,8 @@ void TFile::EnsureCanRunInCrossLang() { std::string errorMessage = "The virtual machines supported are:\n"; for (auto item : this->vms) { - errorMessage += item.first + "\n\t" + item.second + "\n"; + errorMessage += + item.first->GetString() + "\n\t" + item.second->GetString() + "\n"; } throw VMException(errorMessage); } @@ -152,7 +156,7 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) { items.push_back(parseEnt()); } - return TList::Create(ls, items.begin(), items.end()); + return ls.Create(items.begin(), items.end()); } else throw std::out_of_range("Abrupt end of metadata"); } break; @@ -166,8 +170,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) { if (index + 4 <= bytes.size()) { auto val2 = BitConverter::ToUint32BE(bytes[index]); index += 4; - std::string &text = this->strings.at((size_t)val2); - items.emplace_back(text, parseEnt()); + TString *text = this->strings.at((size_t)val2); + items.emplace_back(text->GetString(), parseEnt()); } else throw std::out_of_range("Abrupt end of metadata"); } @@ -180,9 +184,7 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) { if (index + 4 <= bytes.size()) { auto val = BitConverter::ToUint32BE(bytes[index]); index += 4; - auto ba = TByteArray::Create(ls); - ba->data = this->resources.at((size_t)val); - return ba; + return ls.Create(this->resources.at((size_t)val)); } else throw std::out_of_range("Abrupt end of metadata"); } break; @@ -190,7 +192,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) { if (index + 4 <= bytes.size()) { auto val = BitConverter::ToUint32BE(bytes[index]); index += 4; - return std::make_shared(ls.GetGC(), this, val); + return ls.Create( + std::make_shared(ls.GetGC(), this, val)); } else throw std::out_of_range("Abrupt end of metadata"); } break; @@ -212,8 +215,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) { ls, "", {}, [val, this](GCList &ls, std::vector args) -> TObject { - return std::make_shared(ls.GetGC(), this, - val); + return ls.Create(std::make_shared( + ls.GetGC(), this, val)); }); em->watch.push_back(this); ls.GetGC()->BarrierEnd(); @@ -261,26 +264,36 @@ void TFile::Load(std::shared_ptr gc, this->info = GetString(stream); } else if (strncmp(table_name, "DEPS", 4) == 0) // dependencies { - std::string name = GetString(stream); + TString *name = GetString(stream); uint8_t version_bytes[5]; Ensure(stream, version_bytes, sizeof(version_bytes)); TVMVersion depVersion(version_bytes); + gc->BarrierBegin(); this->dependencies.push_back( - std::pair(name, depVersion)); + std::pair(name, depVersion)); + gc->BarrierEnd(); } else if (strncmp(table_name, "TOOL", 4) == 0) // compile tools (for package manager) { - std::string name = GetString(stream); + TString *name = GetString(stream); uint8_t version_bytes[5]; Ensure(stream, version_bytes, sizeof(version_bytes)); TVMVersion depVersion(version_bytes); + gc->BarrierBegin(); this->tools.push_back( - std::pair(name, depVersion)); + std::pair(name, depVersion)); + gc->BarrierEnd(); } else if (strncmp(table_name, "RESO", 4) == 0) // resources (using embed) { - auto &data = this->resources.emplace_back(tableLen); + std::vector data; + data.resize(tableLen); Ensure(stream, data.data(), data.size()); + GCList ls(gc); + gc->BarrierBegin(); + this->resources.push_back(ls.Create(std::move(data))); + gc->BarrierEnd(); + } else if (strncmp(table_name, "CHKS", 4) == 0 && gc != nullptr) // chunks { @@ -288,11 +301,13 @@ void TFile::Load(std::shared_ptr gc, size_t chunkCount = (size_t)EnsureInt(stream); for (size_t j = 0; j < chunkCount; j++) { - auto chunk = TFileChunk::Create(ls); + auto chunk = ls.Create(); chunk->file = this; size_t argCount = (size_t)EnsureInt(stream); for (size_t k = 0; k < argCount; k++) { + gc->BarrierBegin(); chunk->args.push_back(GetString(stream)); + gc->BarrierEnd(); } size_t len = (size_t)EnsureInt(stream); chunk->code.resize(len); @@ -307,33 +322,45 @@ void TFile::Load(std::shared_ptr gc, size_t funLength = (size_t)EnsureInt(stream); for (size_t j = 0; j < funLength; j++) { - std::vector fnParts; + std::vector fnParts; uint32_t fnPartsC = EnsureInt(stream); for (uint32_t k = 0; k < fnPartsC; k++) { fnParts.push_back(GetString(stream)); } uint32_t fnNumber = EnsureInt(stream); + gc->BarrierBegin(); this->functions.push_back( - std::pair, uint32_t>(fnParts, - fnNumber)); + std::pair, uint32_t>(fnParts, + fnNumber)); + gc->BarrierEnd(); } } else if (strncmp(table_name, "STRS", 4) == 0) // strings { size_t strsLen = (size_t)EnsureInt(stream); + + gc->BarrierBegin(); + this->strings.reserve(strsLen); + gc->BarrierEnd(); + + GCList ls(gc); for (size_t j = 0; j < strsLen; j++) { - this->strings.push_back(EnsureString(stream)); + gc->BarrierBegin(); + EnsureString(ls, stream); + gc->BarrierEnd(); } } else if (strncmp(table_name, "ICON", 4) == 0) // icon { - this->icon = (int32_t)EnsureInt(stream); + this->icon = this->resources.at(EnsureInt(stream)); } else if (strncmp(table_name, "MACH", 4) == 0) // machine { - std::string name = GetString(stream); - std::string howToGet = GetString(stream); + TString *name = GetString(stream); + TString *howToGet = GetString(stream); + gc->BarrierBegin(); this->vms.push_back( - std::pair(name, howToGet)); + std::pair(name, howToGet)); + gc->BarrierEnd(); } else if (strncmp(table_name, "CLSS", 4) == 0) // classes { uint32_t clsCnt = EnsureInt(stream); @@ -341,14 +368,17 @@ void TFile::Load(std::shared_ptr gc, TClass cls; cls.documentation = GetString(stream); uint32_t name_cnt = EnsureInt(stream); + cls.name.reserve((size_t)name_cnt); for (uint32_t k = 0; k < name_cnt; k++) { cls.name.push_back(GetString(stream)); } name_cnt = EnsureInt(stream); + cls.inherits.reserve((size_t)name_cnt); for (uint32_t k = 0; k < name_cnt; k++) { cls.inherits.push_back(GetString(stream)); } name_cnt = EnsureInt(stream); + cls.entry.reserve((size_t)name_cnt); for (uint32_t k = 0; k < name_cnt; k++) { TClassEntry ent; Ensure(stream, main_header, 1); @@ -359,12 +389,15 @@ void TFile::Load(std::shared_ptr gc, ent.documentation = GetString(stream); ent.name = GetString(stream); uint32_t arglen = EnsureInt(stream); + ent.args.reserve((size_t)arglen); for (uint32_t l = 0; l < arglen; l++) ent.args.push_back(GetString(stream)); ent.chunkId = EnsureInt(stream); cls.entry.push_back(ent); } + gc->BarrierBegin(); this->classes.push_back(cls); + gc->BarrierEnd(); } } else if (strncmp(table_name, "META", 4) == 0) // structured metadata { diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 9adf8bf..62beeaf 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -2042,7 +2042,8 @@ bool InterperterThread::DeclareConstVariable(std::shared_ptr gc) { throw VMException( "[DECLARECONSTVARIABLE] Can't pop string, got type " + - GetObjectTypeString(key) + " = " + ToString(gc, key) + "."); + GetObjectTypeString(key) + " = " + ObjectToString(gc, key) + + "."); } } return false; @@ -2060,10 +2061,8 @@ bool InterperterThread::PushResourceStream(std::shared_ptr gc) { gc->BarrierBegin(); GCList ls(gc); - // TByteArray* arr = TByteArray::Create(ls); - // arr->data = stk->callable->file->resources[n]; - stk->Push( - gc, std::make_shared(gc, stk->callable->file, n)); + stk->Push(gc, ls.Create(std::make_shared( + gc, stk->callable->file->resources[n]))); gc->BarrierEnd(); } else { @@ -2086,9 +2085,9 @@ bool InterperterThread::PushResource(std::shared_ptr gc) { gc->BarrierBegin(); GCList ls(gc); - TByteArray *arr = TByteArray::Create(ls); - arr->data = stk->callable->file->resources[n]; - stk->Push(gc, arr); + + stk->Push(gc, + ls.Create(stk->callable->file->resources[n])); gc->BarrierEnd(); } else { @@ -2379,7 +2378,7 @@ bool InterperterThread::CreateArray(std::shared_ptr gc) { std::vector &cse = this->call_stack_entries; auto stk = cse.back(); GCList ls(gc); - TList *dict = TList::Create(ls); + TList *dict = ls.Create(); stk->Push(gc, dict); return false; } @@ -2910,7 +2909,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure, : closure->env; cse->ip = 0; if (closure->closure->args.empty() && closure->chunkId != 0) { - TList *list = TList::Create(ls); + TList *list = ls.Create(); list->items = args; cse->env->DeclareVariable("arguments", list); @@ -2974,7 +2973,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure, if (i == closure->closure->args.size() - 1 && back.size() > 2 && back[0] == '$' && back[1] == '$') { auto argName = closure->closure->args[i]; - auto lsArgs = TList::Create(ls); + auto lsArgs = ls.Create(); for (; i < args.size(); i++) lsArgs->Add(args[i]); cse->env->DeclareVariable(trimStart(argName), lsArgs);