From 2430b62232e61ae991a455cbb9ca81c7b5dcb39a Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Tue, 1 Sep 2026 05:15:43 -0500 Subject: [PATCH] Replace time-based GC with allocation-count trigger, migrate all Create factories to GCList::Create(), fix VFSPath root path, reorder TObject variant --- .gitea/workflows/tag.yaml | 2 +- changelog.md | 3 + cmake/findtf.cmake | 2 +- cmake/sources.cmake | 1 + cmake/version.cmake | 2 +- include/CrossLang.hpp | 278 +++++++++++++----- src/archive.cpp | 2 +- src/compiler/codegen.cpp | 152 +++++++--- src/compiler/lexer.cpp | 2 +- src/compiler/parser.cpp | 167 +---------- src/program_lib/crossarchivecreate.cpp | 4 +- src/program_lib/crosslangcompiler.cpp | 12 +- src/runtime_methods/console.cpp | 4 +- src/runtime_methods/json.cpp | 4 +- src/runtime_methods/net.cpp | 77 +++-- src/runtime_methods/process.cpp | 6 +- src/runtime_methods/std.cpp | 8 +- src/runtime_methods/vm.cpp | 5 + src/types/any.cpp | 18 +- src/types/associativearray.cpp | 12 +- src/types/classenvironment.cpp | 21 +- src/types/closure.cpp | 68 ++--- src/types/dictionary.cpp | 32 +- src/types/exception.cpp | 168 +++++++++++ src/types/externalmethod.cpp | 31 +- src/types/ittr.cpp | 149 +++------- src/types/list.cpp | 49 +-- src/types/native.cpp | 13 +- src/types/queryable.cpp | 12 +- src/types/rootenvironment.cpp | 25 +- src/types/subenvironment.cpp | 26 +- src/vm/bc/executemethod2.cpp | 4 +- src/vm/exception.cpp | 8 +- src/vm/filereader.cpp | 34 +-- src/vm/gc.cpp | 168 ++++++----- src/vm/gclist.cpp | 3 +- src/vm/vm.cpp | 124 ++++---- ...{vm_opcode_table.h => vm_opcode_table.def} | 0 38 files changed, 889 insertions(+), 807 deletions(-) create mode 100644 src/types/exception.cpp rename src/vm/{vm_opcode_table.h => vm_opcode_table.def} (100%) diff --git a/.gitea/workflows/tag.yaml b/.gitea/workflows/tag.yaml index a2e22fa..b30e6d6 100644 --- a/.gitea/workflows/tag.yaml +++ b/.gitea/workflows/tag.yaml @@ -5,7 +5,7 @@ on: - 'v*' env: - TF_VERSION: 0.0.6 + TF_VERSION: 0.0.7 PACKAGE_AND_BREW: ${{ secrets.PACKAGE_AND_BREW }} VERSION: ${{ gitea.ref_name }} RESULT_IMAGE_NAME: tesses50/crosslang diff --git a/changelog.md b/changelog.md index 8bce7dd..087d5ad 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,8 @@ # Changelog +## 0.0.10 +Replace time-based GC with allocation-count trigger, migrate all Create factories to GCList::Create(), fix VFSPath root path, reorder TObject variant + ## 0.0.9 Fixed Process.ShellFileOrUrl was broken New.ShellFileOrUrl diff --git a/cmake/findtf.cmake b/cmake/findtf.cmake index 57a338b..4ed866c 100644 --- a/cmake/findtf.cmake +++ b/cmake/findtf.cmake @@ -5,7 +5,7 @@ set(CROSSLANG_STATIC ${TESSESFRAMEWORK_STATIC} CACHE INTERNAL "For CrossLang" FO FetchContent_Declare( TessesFramework GIT_REPOSITORY https://git.tesses.org/tesses50/tessesframework.git - GIT_TAG bd0587779e68832cf382fe49b6b2e99474bcf81f + GIT_TAG 5b54af1728907559999e446e56497055297a3696 ) set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF) FetchContent_MakeAvailable(TessesFramework) diff --git a/cmake/sources.cmake b/cmake/sources.cmake index 7dc8216..879a04d 100644 --- a/cmake/sources.cmake +++ b/cmake/sources.cmake @@ -47,6 +47,7 @@ src/types/class.cpp src/types/classenvironment.cpp src/types/random.cpp src/types/queryable.cpp +src/types/exception.cpp src/vm/filereader.cpp src/vm/gc.cpp src/vm/gclist.cpp diff --git a/cmake/version.cmake b/cmake/version.cmake index 1eb439f..4c94a6c 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -1,3 +1,3 @@ set(CROSSLANG_MAJOR_VERSION 0) set(CROSSLANG_MINOR_VERSION 0) -set(CROSSLANG_PATCH_VERSION 9) +set(CROSSLANG_PATCH_VERSION 10) diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index 722e04f..69fc3be 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,7 @@ * */ namespace Tesses::CrossLang { +constexpr uint32_t ALLOC_THRESHOLD = 10000; using BitConverter = Tesses::Framework::Serialization::BitConverter; constexpr std::string_view VMName = "CrossLangVM"; constexpr std::string_view VMHowToGet = "https://crosslang.tesseslanguage.com/"; @@ -794,14 +796,16 @@ class ResourceByteArray : public ResourceBase { GetLength(std::shared_ptr embedFS); void Write(std::shared_ptr output); }; - class CodeGen { uint32_t id; uint32_t NewId(); - void GetFunctionArgs(std::vector &args, SyntaxNode n); + void GetFunctionArgs(std::vector &args, + std::vector &instructions, + SyntaxNode n); + void FlattenCommas(std::vector &args, SyntaxNode n); void GetFunctionName(std::vector &name, SyntaxNode n); - void GetFunctionArgs(std::vector &args, SyntaxNode n); + void FlattenCommas(std::vector &args, SyntaxNode n); SyntaxNode StringifyListOfVars(SyntaxNode n); uint32_t GetString(std::string str); @@ -1347,8 +1351,10 @@ class THeapObject { public: bool marked; virtual void Mark() { marked = true; } - - virtual ~THeapObject() {} + THeapObject() = default; + THeapObject(const THeapObject &) = delete; + THeapObject &operator=(const THeapObject &) = delete; + virtual ~THeapObject() = default; }; class THeapObjectHolder { @@ -1369,9 +1375,9 @@ class TContinue {}; */ using TObject = - std::variant, std::shared_ptr, TBreak, TContinue, std::shared_ptr, @@ -1387,50 +1393,72 @@ using TObject = Tesses::Framework::Uuid>; class TRootEnvironment; +class GCList; class GC : public std::enable_shared_from_this { Tesses::Framework::Threading::Thread *thrd; - Tesses::Framework::Threading::Mutex *mtx; + Tesses::Framework::Threading::Mutex mtx; + Tesses::Framework::Threading::Cond cond; + uint32_t allocs = 0; volatile std::atomic running; - std::vector roots; - std::vector objects; + std::unordered_set roots; + std::unordered_set objects; Tesses::Framework::Lazy *tpool; std::vector< std::function gc, TRootEnvironment *env)>> register_everything; + void SetRoot(GCList *obj); + void UnsetRoot(GCList *obj); + public: Tesses::Framework::Threading::ThreadPool *GetPool(); bool UsingNullThreads(); GC(); + GC(const GC &) = delete; + GC &operator=(const GC &) = delete; void Start(); bool IsRunning(); void BarrierBegin(); void BarrierEnd(); - void Collect(); + void Collect(std::vector &to_delete); void Watch(TObject obj); void Unwatch(TObject obj); - void SetRoot(TObject obj); - void UnsetRoot(TObject obj); static void Mark(TObject obj); void RegisterEverythingCallback( std::function gc, TRootEnvironment *env)> cb); void RegisterEverything(TRootEnvironment *env); ~GC(); + + // uses thread_local or std::map + static void SetCurrentFunction(CallStackEntry *fn); + // uses thread local or std::map + static CallStackEntry *GetCurrentFunction(); + friend class GCList; }; std::string GetObjectTypeString(TObject obj); std::string ToString(std::shared_ptr gc, TObject obj); -class GCList : public THeapObject { +class GCList { std::vector items; std::shared_ptr gc; public: GCList(std::shared_ptr gc); - std::shared_ptr GetGC(); + GCList(const GCList &) = delete; + GCList &operator=(const GCList &) = delete; + std::shared_ptr GetGC() const; + + template T *Create(TArgs &&...args) { + T *obj = new T(std::forward(args)...); + Add(obj); + gc->Watch(obj); + return obj; + } + void Add(TObject v); void Remove(TObject v); void Mark(); @@ -1443,7 +1471,9 @@ class TFile; class TFileChunk : public THeapObject { public: + [[deprecated("Use GCList::Create() instead")]] static TFileChunk *Create(GCList *gc); + [[deprecated("Use GCList::Create() instead")]] static TFileChunk *Create(GCList &gc); TFile *file; std::vector code; @@ -1455,7 +1485,9 @@ class TFileChunk : public THeapObject { 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 }; @@ -1488,7 +1520,9 @@ class TClassObjectEntry { class TDictionary; class TFile : public THeapObject { public: + [[deprecated("Use GCList::Create() instead")]] static TFile *Create(GCList *gc); + [[deprecated("Use GCList::Create() instead")]] static TFile *Create(GCList &gc); std::vector chunks; @@ -1504,7 +1538,7 @@ class TFile : public THeapObject { std::string name; TVMVersion version; std::string info; - int32_t icon; + int32_t icon = -1; void Load(std::shared_ptr gc, std::shared_ptr strm); @@ -1528,7 +1562,9 @@ class TFile : public THeapObject { class TAssociativeArray : public THeapObject { public: std::vector> items; + [[deprecated("Use GCList::Create() instead")]] static TAssociativeArray *Create(GCList &ls); + [[deprecated("Use GCList::Create() instead")]] static TAssociativeArray *Create(GCList *ls); void Set(std::shared_ptr gc, TObject key, TObject value); TObject Get(std::shared_ptr gc, TObject key); @@ -1542,29 +1578,33 @@ class TAssociativeArray : public THeapObject { class TList : public THeapObject { public: + TList() = default; + template + TList(Itterator begin, Itterator end) : items(begin, end) {} + 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) { - auto list = Create(gc); - gc->GetGC()->BarrierBegin(); - for (Itterator i = begin; i != end; ++i) { - TObject item = *i; - list->Add(item); - } - gc->GetGC()->BarrierEnd(); - return list; + return gc->Create(begin, end); } template + [[deprecated("Use GCList::Create() instead")]] static TList *Create(GCList &gc, Itterator begin, Itterator end) { - return Create(&gc, begin, end); + return gc.Create(begin, end); } + [[deprecated("Use GCList::Create() instead")]] static TList *Create(GCList *gc, std::initializer_list il) { - return Create(gc, il.begin(), il.end()); + return gc->Create(il); } + [[deprecated("Use GCList::Create() instead")]] static TList *Create(GCList &gc, std::initializer_list il) { - return Create(gc, il.begin(), il.end()); + return gc.Create(il); } virtual int64_t Count(); virtual TObject Get(int64_t index); @@ -1578,30 +1618,37 @@ class TList : public THeapObject { using TDItem = std::pair; class TDictionary : public THeapObject { public: + TDictionary() = default; + template TDictionary(Itterator begin, Itterator end) { + for (Itterator i = begin; i != end; ++i) { + TDItem &item = *i; + SetValue(item.first, item.second); + } + } + TDictionary(std::initializer_list il) { + for (auto &item : il) { + SetValue(item.first, item.second); + } + } std::map items; + [[deprecated("Use GCList::Create() instead")]] static TDictionary *Create(GCList *gc); + [[deprecated("Use GCList::Create() instead")]] static TDictionary *Create(GCList &gc); template static TDictionary *Create(GCList *gc, Itterator begin, Itterator end) { - auto dict = Create(gc); - gc->GetGC()->BarrierBegin(); - for (Itterator i = begin; i != end; ++i) { - TDItem item = *i; - dict->SetValue(item.first, item.second); - } - gc->GetGC()->BarrierEnd(); - return dict; + return gc->Create(begin, end); } template static TDictionary *Create(GCList &gc, Itterator begin, Itterator end) { - return Create(&gc, begin, end); + return gc.Create(begin, end); } static TDictionary *Create(GCList *gc, std::initializer_list il) { - return Create(gc, il.begin(), il.end()); + return gc->Create(il); } static TDictionary *Create(GCList &gc, std::initializer_list il) { - return Create(gc, il.begin(), il.end()); + return gc.Create(il); } virtual bool HasValue(std::string key); @@ -1641,9 +1688,11 @@ class TCallable : public THeapObject { void ThrowFatalError(std::exception &ex); void ThrowConstError(std::string key); +enum class TEnvironmentDeclType { TEDT_VAR, TEDT_CONST }; class TEnvironment : public THeapObject { - std::vector consts; + protected: + std::unordered_map decls; public: std::vector defers; @@ -1700,8 +1749,10 @@ class TClassObject : public THeapObject { std::vector inherit_tree; std::vector entries; + // This is the only place where the old way is static TClassObject *Create(GCList &ls, TFile *f, uint32_t classIndex, TEnvironment *env, std::vector args); + // this too static TClassObject *Create(GCList *ls, TFile *f, uint32_t classIndex, TEnvironment *env, std::vector args); @@ -1720,8 +1771,10 @@ class TClassEnvironment : public TEnvironment { TClassObject *clsObj; public: + [[deprecated("Use GCList::Create() instead")]] static TClassEnvironment *Create(GCList *gc, TEnvironment *env, TClassObject *obj); + [[deprecated("Use GCList::Create() instead")]] static TClassEnvironment *Create(GCList &gc, TEnvironment *env, TClassObject *obj); TClassEnvironment(TEnvironment *env, TClassObject *obj); @@ -1796,7 +1849,9 @@ class TRootEnvironment : public TEnvironment { Tesses::Framework::Filesystem::VFSPath path); TDictionary *GetDictionary(); + [[deprecated("Use GCList::Create() instead")]] static TRootEnvironment *Create(GCList *gc, TDictionary *dict); + [[deprecated("Use GCList::Create() instead")]] static TRootEnvironment *Create(GCList &gc, TDictionary *dict); TRootEnvironment(TDictionary *dict); bool HasVariable(std::string key); @@ -1856,8 +1911,10 @@ class TSubEnvironment : public TEnvironment { TDictionary *dict; public: + [[deprecated("Use GCList::Create() instead")]] static TSubEnvironment *Create(GCList *gc, TEnvironment *env, TDictionary *dict); + [[deprecated("Use GCList::Create() instead")]] static TSubEnvironment *Create(GCList &gc, TEnvironment *env, TDictionary *dict); TSubEnvironment(TEnvironment *env, TDictionary *dict); @@ -1883,7 +1940,10 @@ TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached); class TArgWrapper : public TCallable { public: TCallable *callable; + TArgWrapper(TCallable *callable); + [[deprecated("Use GCList::Create() instead")]] static TArgWrapper *Create(GCList &ls, TCallable *callable); + [[deprecated("Use GCList::Create() instead")]] static TArgWrapper *Create(GCList *ls, TCallable *callable); TObject Call(GCList &ls, std::vector args); void Mark(); @@ -1897,24 +1957,28 @@ class TExternalMethod : public TCallable { std::vector args; std::vector watch; TExternalMethod( - std::function args)> cb, std::string documentation, std::vector argNames, - std::function destroy); + std::function args)> cb, + std::function destroy = nullptr); + + [[deprecated("Use GCList::Create() instead")]] static TExternalMethod * Create(GCList &ls, std::string documentation, std::vector argNames, std::function args)> cb, std::function destroy); + [[deprecated("Use GCList::Create() instead")]] static TExternalMethod * Create(GCList *ls, std::string documentation, std::vector argNames, std::function args)> cb, std::function destroy); - + [[deprecated("Use GCList::Create() instead")]] static TExternalMethod * Create(GCList &ls, std::string documentation, std::vector argNames, std::function args)> cb); + [[deprecated("Use GCList::Create() instead")]] static TExternalMethod * Create(GCList *ls, std::string documentation, std::vector argNames, @@ -1943,8 +2007,11 @@ class TAssociativeArrayEnumerator : public TEnumerator { TAssociativeArray *ls; public: + TAssociativeArrayEnumerator(TAssociativeArray *list); + [[deprecated("Use GCList::Create() instead")]] static TAssociativeArrayEnumerator *Create(GCList &ls, TAssociativeArray *list); + [[deprecated("Use GCList::Create() instead")]] static TAssociativeArrayEnumerator *Create(GCList *ls, TAssociativeArray *list); bool MoveNext(std::shared_ptr ls); @@ -1955,10 +2022,13 @@ class TAssociativeArrayEnumerator : public TEnumerator { class TCustomEnumerator : public TEnumerator { public: TDictionary *dict; + TCustomEnumerator(TDictionary *dict); bool MoveNext(std::shared_ptr ls); TObject GetCurrent(GCList &ls); void Mark(); + [[deprecated("Use GCList::Create() instead")]] static TCustomEnumerator *Create(GCList &ls, TDictionary *dict); + [[deprecated("Use GCList::Create() instead")]] static TCustomEnumerator *Create(GCList *ls, TDictionary *dict); }; @@ -1968,10 +2038,13 @@ class TYieldEnumerator : public TEnumerator { TObject current; public: + TYieldEnumerator(TObject v); bool MoveNext(std::shared_ptr ls); TObject GetCurrent(GCList &ls); void Mark(); + [[deprecated("Use GCList::Create() instead")]] static TYieldEnumerator *Create(GCList &ls, TObject v); + [[deprecated("Use GCList::Create() instead")]] static TYieldEnumerator *Create(GCList *ls, TObject v); }; @@ -1981,7 +2054,10 @@ class TStringEnumerator : public TEnumerator { std::string str; public: + TStringEnumerator(std::string str); + [[deprecated("Use GCList::Create() instead")]] static TStringEnumerator *Create(GCList &ls, std::string str); + [[deprecated("Use GCList::Create() instead")]] static TStringEnumerator *Create(GCList *ls, std::string str); bool MoveNext(std::shared_ptr ls); TObject GetCurrent(GCList &ls); @@ -1992,7 +2068,10 @@ class TListEnumerator : public TEnumerator { TList *ls; public: + TListEnumerator(TList *list); + [[deprecated("Use GCList::Create() instead")]] static TListEnumerator *Create(GCList &ls, TList *list); + [[deprecated("Use GCList::Create() instead")]] static TListEnumerator *Create(GCList *ls, TList *list); bool MoveNext(std::shared_ptr ls); TObject GetCurrent(GCList &ls); @@ -2005,7 +2084,10 @@ class TDynamicListEnumerator : public TEnumerator { TDynamicList *ls; public: + TDynamicListEnumerator(TDynamicList *list); + [[deprecated("Use GCList::Create() instead")]] static TDynamicListEnumerator *Create(GCList &ls, TDynamicList *list); + [[deprecated("Use GCList::Create() instead")]] static TDynamicListEnumerator *Create(GCList *ls, TDynamicList *list); bool MoveNext(std::shared_ptr ls); TObject GetCurrent(GCList &ls); @@ -2015,8 +2097,11 @@ class TVFSPathEnumerator : public TEnumerator { Tesses::Framework::Filesystem::VFSPathEnumerator enumerator; public: + TVFSPathEnumerator(Tesses::Framework::Filesystem::VFSPathEnumerator list); + [[deprecated("Use GCList::Create() instead")]] static TVFSPathEnumerator * Create(GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator list); + [[deprecated("Use GCList::Create() instead")]] static TVFSPathEnumerator * Create(GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator list); bool MoveNext(std::shared_ptr ls); @@ -2105,7 +2190,10 @@ class TDictionaryEnumerator : public TEnumerator { TDictionary *dict; public: + TDictionaryEnumerator(TDictionary *dict); + [[deprecated("Use GCList::Create() instead")]] static TDictionaryEnumerator *Create(GCList &ls, TDictionary *dict); + [[deprecated("Use GCList::Create() instead")]] static TDictionaryEnumerator *Create(GCList *ls, TDictionary *dict); bool MoveNext(std::shared_ptr ls); TObject GetCurrent(GCList &ls); @@ -2114,8 +2202,12 @@ class TDictionaryEnumerator : public TEnumerator { class TClosure : public TCallable { public: + TClosure(TEnvironment *env, TFile *file, uint32_t chunkId, + bool ownScope = true); + [[deprecated("Use GCList::Create() instead")]] static TClosure *Create(GCList &ls, TEnvironment *env, TFile *file, uint32_t chunkId, bool ownScope = true); + [[deprecated("Use GCList::Create() instead")]] static TClosure *Create(GCList *ls, TEnvironment *env, TFile *file, uint32_t chunkId, bool ownScope = true); bool ownScope; @@ -2130,7 +2222,10 @@ class TClosure : public TCallable { class TDynamicList : public THeapObject { public: TCallable *cb; + TDynamicList(TCallable *callable); + [[deprecated("Use GCList::Create() instead")]] static TDynamicList *Create(GCList &ls, TCallable *callable); + [[deprecated("Use GCList::Create() instead")]] static TDynamicList *Create(GCList *ls, TCallable *callable); void Mark(); @@ -2154,8 +2249,10 @@ class TDynamicList : public THeapObject { class TDynamicDictionary : public THeapObject { public: TCallable *cb; - + TDynamicDictionary(TCallable *callable); + [[deprecated("Use GCList::Create() instead")]] static TDynamicDictionary *Create(GCList &ls, TCallable *callable); + [[deprecated("Use GCList::Create() instead")]] static TDynamicDictionary *Create(GCList *ls, TCallable *callable); void Mark(); @@ -2176,17 +2273,19 @@ class InterperterThread; class CallStackEntry : public THeapObject { public: + [[deprecated("Use GCList::Create() instead")]] static CallStackEntry *Create(GCList *ls); + [[deprecated("Use GCList::Create() instead")]] static CallStackEntry *Create(GCList &ls); - InterperterThread *thread; + InterperterThread *thread = nullptr; std::vector stack; - TEnvironment *env; - TClosure *callable; + TEnvironment *env = nullptr; + TClosure *callable = nullptr; uint32_t ip; uint32_t scopes; - int64_t srcline; - std::string srcfile; - bool mustReturn; + int64_t srcline = -1; + std::string srcfile = ""; + bool mustReturn = false; void Mark(); void Push(std::shared_ptr gc, TObject v); @@ -2203,6 +2302,7 @@ class TTask : public THeapObject { TTask(std::shared_ptr gc); public: + // this still is needed static TTask *Create(GCList &ls); bool IsCompleted(); @@ -2223,7 +2323,6 @@ class TTask : public THeapObject { static TTask *FromResult(GCList &ls, TObject v); }; -extern thread_local CallStackEntry *current_function; class InterperterThread : public THeapObject { private: @@ -2309,7 +2408,9 @@ class InterperterThread : public THeapObject { bool PushPrivateExpression(std::shared_ptr gc); public: + [[deprecated("Use GCList::Create() instead")]] static InterperterThread *Create(GCList *ls); + [[deprecated("Use GCList::Create() instead")]] static InterperterThread *Create(GCList &ls); std::vector call_stack_entries; virtual void Execute(std::shared_ptr gc); @@ -2328,34 +2429,31 @@ class VMException : public std::exception { error_message.append(ex); } + const std::string &GetMessage() { return error_message; } + const char *what() const noexcept override { return error_message.c_str(); } }; class TAny : public THeapObject { public: std::any any; TObject other; - + [[deprecated("Use GCList::Create() instead")]] static TAny *Create(GCList &ls); + [[deprecated("Use GCList::Create() instead")]] static TAny *Create(GCList *ls); void Mark(); }; class TNativeObject : public THeapObject { public: template - static T *Create(GCList &ls, TArgs... args) { - T *obj = new T(args...); - std::shared_ptr gc = ls.GetGC(); - ls.Add(obj); - gc->Watch(obj); - return obj; + [[deprecated("Use GCList::Create() instead")]] + static T *Create(GCList &ls, TArgs &&...args) { + return ls.Create(std::forward(args)...); } template - static T *Create(GCList *ls, TArgs... args) { - T *obj = new T(args...); - std::shared_ptr gc = ls->GetGC(); - ls->Add(obj); - gc->Watch(obj); - return obj; + [[deprecated("Use GCList::Create() instead")]] + static T *Create(GCList *ls, TArgs &&...args) { + return ls->Create(std::forward(args)...); } virtual TObject CallMethod(GCList &ls, std::string name, @@ -2363,7 +2461,6 @@ class TNativeObject : public THeapObject { virtual std::string TypeName() = 0; virtual bool ToBool(); virtual bool Equals(std::shared_ptr gc, TObject right); - virtual ~TNativeObject(); }; class TRandom : public TNativeObject { public: @@ -2380,13 +2477,15 @@ class TNative : public THeapObject { public: TObject other; - TNative(void *ptr, std::function destroy); + TNative(void *ptr, std::function destroy = nullptr); bool GetDestroyed(); void *GetPointer(); void Destroy(); void Mark(); + [[deprecated("Use GCList::Create() instead")]] static TNative *Create(GCList &ls, void *ptr, std::function destroy); + [[deprecated("Use GCList::Create() instead")]] static TNative *Create(GCList *ls, void *ptr, std::function destroy); ~TNative(); @@ -2525,9 +2624,9 @@ typedef void (*PluginFunction)(std::shared_ptr gc, TRootEnvironment *env); void LoadPlugin(std::shared_ptr gc, TRootEnvironment *env, Tesses::Framework::Filesystem::VFSPath sharedObjectPath); std::string Json_Encode(TObject o, bool indent = false); -TObject Json_Decode(GCList ls, std::string str); +TObject Json_Decode(GCList &ls, std::string str); std::string Json_DocEncode(TObject o, bool indent); -TObject Json_DocDecode(GCList ls, std::string str); +TObject Json_DocDecode(GCList &ls, std::string str); // DO NOT USE DIRECTLY class SharedPtrTObject { GCList *ls; @@ -2586,6 +2685,44 @@ class EmbedDirectory : public Tesses::Framework::Filesystem::VFS { Tesses::Framework::Filesystem::StatData &data); }; +class TNativeException : public TNativeObject { + std::string what; + std::exception_ptr ptr; + + public: + TNativeException() = delete; + TNativeException(const char *what, std::exception_ptr ptr); + TObject CallMethod(GCList &ls, std::string key, std::vector args); + std::string TypeName(); + std::string What(); + std::exception_ptr GetPointer(); + void ThrowIt(); +}; + +class TException : public TNativeObject { + private: + TDictionary *extraFields; + TObject innerException; + + std::string message; + std::string type; + std::optional filename; + std::optional line; + std::optional column; + std::optional offset; + + public: + TException() = delete; + TException(std::string message, std::string type = "Exception", + TDictionary *extraFields = nullptr, + TObject innerException = Undefined()); + TObject CallMethod(GCList &ls, std::string key, std::vector args); + std::string TypeName(); + bool ToBool(); + void Mark(); + ~TException() = default; +}; + namespace Programs { int64_t CrossArchiveCreate(std::vector &argv); int64_t CrossArchiveExtract(std::vector &argv); @@ -2615,11 +2752,14 @@ class TQueryable : public THeapObject { TObject parent; TQueryableMode mode; std::vector args; + + public: TQueryable(TObject parent); TQueryable(TObject parent, TQueryableMode mode, std::vector args); - public: + [[deprecated("Use GCList::Create() instead")]] static TQueryable *Create(GCList &ls, TObject parent); + [[deprecated("Use GCList::Create() instead")]] static TQueryable *Create(GCList &ls, TObject parent, TQueryableMode mode, std::vector args); diff --git a/src/archive.cpp b/src/archive.cpp index 97e6e4c..88a62d0 100644 --- a/src/archive.cpp +++ b/src/archive.cpp @@ -44,7 +44,7 @@ void CrossArchiveCreate( strs.push_back("Console"); strs.push_back("WriteLine"); strs.push_back("You are trying to run a crvm archive, stop it you won't " - "get anywhere!\nUse crossarchiveextract instead."); + "get anywhere!\nUse crosslang archiveextract instead."); std::vector resources; diff --git a/src/compiler/codegen.cpp b/src/compiler/codegen.cpp index f9d3d6f..fad8cca 100644 --- a/src/compiler/codegen.cpp +++ b/src/compiler/codegen.cpp @@ -175,7 +175,7 @@ void CodeGen::WriteMetadataObject(std::vector &bytes, SyntaxNode n) { std::vector itms; if (asn.nodes.size() > 0) - GetFunctionArgs(itms, asn.nodes[0]); + FlattenCommas(itms, asn.nodes[0]); bytes.push_back(7); size_t offset = bytes.size(); bytes.resize(offset + 4); @@ -189,7 +189,7 @@ void CodeGen::WriteMetadataObject(std::vector &bytes, SyntaxNode n) { std::vector itms; if (asn.nodes.size() > 0) - GetFunctionArgs(itms, asn.nodes[0]); + FlattenCommas(itms, asn.nodes[0]); bytes.push_back(8); size_t offset = bytes.size(); bytes.resize(offset + 4); @@ -827,6 +827,8 @@ void CodeGen::GenNode(std::vector &instructions, size_t fnindex = this->chunks.size(); ent.closure = (uint32_t)fnindex; this->chunks.resize(fnindex + 1); + + std::vector fnInstructions; auto &nameAndArgs = std::get(adv2.nodes[2]); if (nameAndArgs.nodeName == FunctionCallExpression && @@ -844,14 +846,13 @@ void CodeGen::GenNode(std::vector &instructions, std::get(getvar.nodes[0])); if (nameAndArgs.nodes.size() > 1) { GetFunctionArgs(ent.arguments, + fnInstructions, nameAndArgs.nodes[1]); } } else continue; } - std::vector fnInstructions; - GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1, -1); @@ -881,8 +882,8 @@ void CodeGen::GenNode(std::vector &instructions, ent.name = GetString( std::get(getvar.nodes[0])); if (nameAndArgs.nodes.size() > 1) { - GetFunctionArgs(ent.arguments, - nameAndArgs.nodes[1]); + FlattenCommas(ent.arguments, + nameAndArgs.nodes[1]); } } else continue; @@ -1041,13 +1042,13 @@ void CodeGen::GenNode(std::vector &instructions, } if (item.first.second.nodeName == DefaultStatement) { if (!defaultJmp.empty()) - std::cout << "ERROR: multiple default in " - "switch statement will cause " - "undefined behaviour, this is not " - "an exception due to not allowing " - "exceptions in codegen stage (the " - "compilation shouldn't fail)" - << std::endl; + Tesses::Framework::Console::WriteLine( + "ERROR: multiple default in " + "switch statement will cause " + "undefined behaviour, this is not " + "an exception due to not allowing " + "exceptions in codegen stage (the " + "compilation shouldn't fail)"); defaultJmp = item.first.first; } } @@ -1223,7 +1224,7 @@ void CodeGen::GenNode(std::vector &instructions, std::vector itms; if (adv.nodes.size() > 0) - GetFunctionArgs(itms, adv.nodes[0]); + FlattenCommas(itms, adv.nodes[0]); for (auto item : itms) { GenNode(instructions, item, scope, contscope, brkscope, contI, brkI); @@ -1233,7 +1234,7 @@ void CodeGen::GenNode(std::vector &instructions, instructions.push_back(new SimpleInstruction(CREATEDICTIONARY)); std::vector itms; if (adv.nodes.size() > 0) - GetFunctionArgs(itms, adv.nodes[0]); + FlattenCommas(itms, adv.nodes[0]); for (auto item : itms) { if (std::holds_alternative(item)) { auto tkn = std::get(item); @@ -1273,7 +1274,7 @@ void CodeGen::GenNode(std::vector &instructions, contI, brkI); if (adv.nodes.size() == 2) { std::vector nodes; - GetFunctionArgs(nodes, adv.nodes[1]); + FlattenCommas(nodes, adv.nodes[1]); for (auto item : nodes) GenNode(instructions, item, scope, contscope, brkscope, contI, brkI); @@ -1288,7 +1289,7 @@ void CodeGen::GenNode(std::vector &instructions, contI, brkI); if (adv.nodes.size() == 2) { std::vector nodes; - GetFunctionArgs(nodes, adv.nodes[1]); + FlattenCommas(nodes, adv.nodes[1]); for (auto item : nodes) GenNode(instructions, item, scope, contscope, brkscope, contI, brkI); @@ -1555,7 +1556,8 @@ void CodeGen::GenNode(std::vector &instructions, } else if (adv.nodeName == ContinueStatement) { if (contscope == -1) { - std::cout << "WARN: continue does nothing here\n"; + Tesses::Framework::Console::WriteLine( + "WARN: continue does nothing here"); } else if (contscope == -2) { instructions.push_back(new SimpleInstruction(PUSHCONTINUE)); instructions.push_back(new SimpleInstruction(RET)); @@ -1572,7 +1574,8 @@ void CodeGen::GenNode(std::vector &instructions, } } else if (adv.nodeName == BreakStatement) { if (brkscope == -1) { - std::cout << "WARN: break does nothing here\n"; + Tesses::Framework::Console::WriteLine( + "WARN: break does nothing here"); } else if (brkscope == -2) { instructions.push_back(new SimpleInstruction(PUSHBREAK)); instructions.push_back(new SimpleInstruction(RET)); @@ -1978,7 +1981,7 @@ void CodeGen::GenNode(std::vector &instructions, //(a,b) => {} // it has two args std::vector args; - GetFunctionArgs(args, adv.nodes[0]); + FlattenCommas(args, adv.nodes[0]); std::vector fnInstructions; size_t fnindex = this->chunks.size(); @@ -2008,12 +2011,11 @@ void CodeGen::GenNode(std::vector &instructions, // Name => {} //(a,b) => {} // it has two args - std::vector args; - GetFunctionArgs(args, adv.nodes[0]); - std::vector fnInstructions; size_t fnindex = this->chunks.size(); this->chunks.resize(fnindex + 1); + std::vector args; + GetFunctionArgs(args, fnInstructions, adv.nodes[0]); auto body = adv.nodes[1]; @@ -2060,18 +2062,20 @@ void CodeGen::GenNode(std::vector &instructions, } } } -void CodeGen::GetFunctionArgs(std::vector &args, SyntaxNode n) { +void CodeGen::FlattenCommas(std::vector &args, SyntaxNode n) { AdvancedSyntaxNode sn; if (std::holds_alternative(n) && (sn = std::get(n)).nodeName == CommaExpression && sn.nodes.size() == 2) { - GetFunctionArgs(args, sn.nodes[0]); - GetFunctionArgs(args, sn.nodes[1]); + FlattenCommas(args, sn.nodes[0]); + FlattenCommas(args, sn.nodes[1]); } else { args.push_back(n); } } -void CodeGen::GetFunctionArgs(std::vector &name, SyntaxNode n) { +void CodeGen::GetFunctionArgs(std::vector &name, + std::vector &instrs, + SyntaxNode n) { if (std::holds_alternative(n)) return; @@ -2079,10 +2083,90 @@ void CodeGen::GetFunctionArgs(std::vector &name, SyntaxNode n) { auto res = std::get(n); if (res.nodeName == ParenthesesExpression) { for (auto n : res.nodes) - GetFunctionArgs(name, n); + GetFunctionArgs(name, instrs, n); + } else if (res.nodeName == AssignExpression && res.nodes.size() == 2) { + // ennsure the left argument is a getVariableExpression + if (std::holds_alternative(res.nodes[0])) { + auto left = std::get(res.nodes[0]); + + if (left.nodeName == GetVariableExpression && + !left.nodes.empty() && + std::holds_alternative(left.nodes[0])) { + std::string key = std::get(left.nodes[0]); + if (key.size() >= 2 && key[0] == '$' && key[1] == '$') { + Tesses::Framework::Console::WriteLine( + "WARN: you can't assign variadic functions to a " + "default value, this will be an " + "error on future release."); + return; + } + + if (key.size() > 0 && key[0] == '$') { + key.erase(key.cbegin()); + } + + name.push_back(GetString('$' + key)); + + uint32_t ifId = NewId(); + std::string compGenSetVar = "__compGenSetVar"; + compGenSetVar.append(std::to_string(ifId)); + + std::string compGenSetVarEnd = "__compGenSetVarEnd"; + compGenSetVarEnd.append(std::to_string(ifId)); + GenNode(instrs, + AdvancedSyntaxNode::Create(GetVariableExpression, + true, {key}), + 0, -1, -1, -1, -1); + instrs.push_back(new JumpStyleInstruction( + Tesses::CrossLang::Instruction::JMPUNDEFINED, + compGenSetVar)); + instrs.push_back(new SimpleInstruction(POP)); + instrs.push_back(new JumpStyleInstruction( + Tesses::CrossLang::Instruction::JMP, compGenSetVarEnd)); + instrs.push_back(new LabelInstruction(compGenSetVar)); + GenNode(instrs, + AdvancedSyntaxNode::Create( + AssignExpression, true, + {AdvancedSyntaxNode::Create(DeclareExpression, + true, {key}), + res.nodes[1]}), + + 0, -1, -1, -1, -1); + instrs.push_back(new SimpleInstruction(POP)); + instrs.push_back(new LabelInstruction(compGenSetVarEnd)); + } else { + Tesses::Framework::Console::WriteLine( + "WARN: assignment does not assign arg, this will be an " + "error on future release."); + } + } else { + Tesses::Framework::Console::WriteLine( + "WARN: assignment does not assign arg, this will be an " + "error on future release."); + } } else if (res.nodeName == CommaExpression && res.nodes.size() == 2) { - GetFunctionArgs(name, res.nodes[0]); - GetFunctionArgs(name, res.nodes[1]); + GetFunctionArgs(name, instrs, res.nodes[0]); + GetFunctionArgs(name, instrs, res.nodes[1]); + } else if (res.nodeName == GetVariableExpression && + res.nodes.size() == 1) { + if (std::holds_alternative(res.nodes[0])) { + name.push_back(GetString(std::get(res.nodes[0]))); + } + } + } +} +void CodeGen::FlattenCommas(std::vector &name, SyntaxNode n) { + if (std::holds_alternative(n)) + return; + + if (std::holds_alternative(n)) { + auto res = std::get(n); + if (res.nodeName == ParenthesesExpression) { + for (auto n : res.nodes) + FlattenCommas(name, n); + } else if (res.nodeName == CommaExpression && res.nodes.size() == 2) { + FlattenCommas(name, res.nodes[0]); + FlattenCommas(name, res.nodes[1]); } else if (res.nodeName == GetVariableExpression && res.nodes.size() == 1) { if (std::holds_alternative(res.nodes[0])) { @@ -2175,14 +2259,14 @@ void CodeGen::GenRoot(SyntaxNode n) { functionName.insert( functionName.begin(), {GetString(documentation)}); - if (fcalli.nodes.size() == 2) - GetFunctionArgs(args, - fcalli.nodes[1]); - std::vector fnInstructions; size_t fnindex = this->chunks.size(); this->chunks.resize(fnindex + 1); + if (fcalli.nodes.size() == 2) + GetFunctionArgs(args, + fnInstructions, + fcalli.nodes[1]); GenNode(fnInstructions, res2.nodes[1], 0, -1, -1, -1, -1); diff --git a/src/compiler/lexer.cpp b/src/compiler/lexer.cpp index 1ae66e8..37db6ca 100644 --- a/src/compiler/lexer.cpp +++ b/src/compiler/lexer.cpp @@ -482,6 +482,7 @@ int Lex(std::string filename, std::istream &strm, } break; case '<': + case '>': case '?': if (peek == read) { Flush(); @@ -532,7 +533,6 @@ int Lex(std::string filename, std::istream &strm, case '^': case '~': case '!': - case '>': case '*': case '%': //* diff --git a/src/compiler/parser.cpp b/src/compiler/parser.cpp index f0a0853..3c8f770 100644 --- a/src/compiler/parser.cpp +++ b/src/compiler/parser.cpp @@ -115,58 +115,16 @@ bool Parser::IsIdentifier(std::string txt, bool pop) { } return false; } - bool Parser::IsAnySymbol(std::initializer_list idents, bool pop) { - if (i < tokens.size()) { if (tokens[i].type != LexTokenType::Symbol) return false; for (auto item : idents) { - if (item == ">") { - if (i + 1 < tokens.size()) { - if ((tokens[i + 1].text == ">" || - tokens[i + 1].text == ">=") && - tokens[i + 1].type == LexTokenType::Symbol) - continue; - } - if (item == tokens[i].text) { - tkn = tokens[i]; - if (pop) - i++; - return true; - } - } else if (item == ">>=") { - if (i + 1 < tokens.size()) { - if (tokens[i].text == ">" && tokens[i + 1].text == ">=" && - tokens[i].type == LexTokenType::Symbol && - tokens[i + 1].type == LexTokenType::Symbol) { - tkn = tokens[i]; - tkn.text = ">>="; - if (pop) - i += 2; - return true; - } - } - } else if (item == ">>") { - if (i + 1 < tokens.size()) { - if (tokens[i].text == ">" && tokens[i + 1].text == ">" && - tokens[i].type == LexTokenType::Symbol && - tokens[i + 1].type == LexTokenType::Symbol) { - tkn = tokens[i]; - tkn.text = ">>"; - if (pop) - i += 2; - return true; - } - } - - } else { - if (item == tokens[i].text) { - tkn = tokens[i]; - if (pop) - i++; - return true; - } + if (item == tokens[i].text) { + tkn = tokens[i]; + if (pop) + i++; + return true; } } } @@ -176,45 +134,7 @@ bool Parser::IsSymbol(std::string txt, bool pop) { if (i < tokens.size()) { if (tokens[i].type != LexTokenType::Symbol) return false; - if (txt == ">") { - if (i + 1 < tokens.size()) { - if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") && - tokens[i + 1].type == LexTokenType::Symbol) - return false; - } - if (txt == tokens[i].text) { - tkn = tokens[i]; - if (pop) - i++; - return true; - } - } else if (txt == ">>=") { - if (i + 1 < tokens.size()) { - - if (tokens[i].text == ">" && tokens[i + 1].text == ">=" && - tokens[i].type == LexTokenType::Symbol && - tokens[i + 1].type == LexTokenType::Symbol) { - tkn = tokens[i]; - tkn.text = ">>="; - if (pop) - i += 2; - return true; - } - } - } else if (txt == ">>") { - if (i + 1 < tokens.size()) { - if (tokens[i].text == ">" && tokens[i + 1].text == ">" && - tokens[i].type == LexTokenType::Symbol && - tokens[i + 1].type == LexTokenType::Symbol) { - tkn = tokens[i]; - tkn.text = ">>"; - if (pop) - i += 2; - return true; - } - } - - } else if (tokens[i].text == txt) { + if (tokens[i].text == txt) { tkn = tokens[i]; if (pop) i++; @@ -233,7 +153,6 @@ static std::string EnsureSafeVariable(LexToken token) { } void Parser::EnsureSymbol(std::string txt) { if (i < tokens.size()) { - if (tokens[i].type != LexTokenType::Symbol) { throw SyntaxException( tokens[i].lineInfo, @@ -241,69 +160,7 @@ void Parser::EnsureSymbol(std::string txt) { LexTokenType_ToString(tokens[i].type) + " \"" + tokens[i].text + "\" which is not a symbol at all."); } - if (txt == ">") { - if (i + 1 < tokens.size()) { - if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") && - tokens[i + 1].type == LexTokenType::Symbol) - throw SyntaxException(tokens[i].lineInfo, - "expected the symbol \"" + txt + - "\" but got the symbol \"" + - tokens[i].text + - tokens[i + 1].text + "\""); - ; - } - if (txt == tokens[i].text) { - - tkn = tokens[i]; - i++; - return; - } - } - if (txt == ">>=") { - if (i + 1 < tokens.size()) { - if (tokens[i].text == ">" && tokens[i + 1].text == ">=" && - tokens[i].type == LexTokenType::Symbol && - tokens[i + 1].type == LexTokenType::Symbol) { - - tkn = tokens[i]; - i += 2; - return; - } - - throw SyntaxException(tokens[i].lineInfo, - "expected the symbol \"" + txt + - "\" but got the symbol \"" + - tokens[i].text + tokens[i + 1].text + - "\""); - } - - throw SyntaxException(tokens[i].lineInfo, - "expected the symbol \"" + txt + - "\" but got the symbol \"" + - tokens[i].text + "\""); - } else if (txt == ">>") { - if (i + 1 < tokens.size()) { - if (tokens[i].text == ">" && tokens[i + 1].text == ">" && - tokens[i].type == LexTokenType::Symbol && - tokens[i + 1].type == LexTokenType::Symbol) { - - tkn = tokens[i]; - i += 2; - return; - } - - throw SyntaxException(tokens[i].lineInfo, - "expected the symbol \"" + txt + - "\" but got the symbol \"" + - tokens[i].text + tokens[i + 1].text + - "\""); - } - - throw SyntaxException(tokens[i].lineInfo, - "expected the symbol \"" + txt + - "\" but got the symbol \"" + - tokens[i].text + "\""); - } else if (tokens[i].text != txt) { + if (tokens[i].text != txt) { throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + @@ -633,6 +490,11 @@ void Parser::ParseHtml(std::vector &nodes, std::string var) { EnsureSymbol(")"); EnsureSymbol(">"); + if (std::holds_alternative(item)) + item = AdvancedSyntaxNode::Create( + DeclareExpression, true, + {"item"}); + std::vector _nodes; parseFn(_nodes, "each"); body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes); @@ -1411,7 +1273,7 @@ SyntaxNode Parser::ParseNode(bool isRoot) { } if (!isRoot) - i++; + EnsureSymbol("}"); return aSN; } @@ -1519,8 +1381,7 @@ SyntaxNode Parser::ParseNode(bool isRoot) { if (std::holds_alternative(item)) item = AdvancedSyntaxNode::Create( DeclareExpression, true, - {AdvancedSyntaxNode::Create(GetVariableExpression, true, - {"item"})}); + {"item"}); return AdvancedSyntaxNode::Create(EachStatement, false, {item, list, body}); diff --git a/src/program_lib/crossarchivecreate.cpp b/src/program_lib/crossarchivecreate.cpp index a3d9bb3..45b9744 100644 --- a/src/program_lib/crossarchivecreate.cpp +++ b/src/program_lib/crossarchivecreate.cpp @@ -16,7 +16,7 @@ static void Help(std::string &filename) { printf(" -n: Set name (MyAppOrLibName defaults to out)\n"); printf(" -h, --help: Prints help\n"); printf("Options except for help have flag with arg like this: -F ARG\n"); - exit(1); + std::exit(1); } int64_t CrossArchiveCreate(std::vector &argv) { @@ -53,7 +53,7 @@ int64_t CrossArchiveCreate(std::vector &argv) { printf("Expected " "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]" "]]]\n"); - exit(1); + std::exit(1); } } } else { diff --git a/src/program_lib/crosslangcompiler.cpp b/src/program_lib/crosslangcompiler.cpp index 143b572..49a055d 100644 --- a/src/program_lib/crosslangcompiler.cpp +++ b/src/program_lib/crosslangcompiler.cpp @@ -27,7 +27,7 @@ static void Help(std::string filename) { "for sane with file access to current directory and sub " "directories, \"full\" has full runtime.\n"); printf("Options except for help have flag with arg like this: -F ARG\n"); - exit(1); + std::exit(1); } void CrossLangCompiler(std::vector &argv) { /*std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary); @@ -107,14 +107,14 @@ void CrossLangCompiler(std::vector &argv) { printf("Expected " "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-" "prod]]]]\n"); - exit(1); + std::exit(1); } dependencies.push_back( std::pair(str1, v2)); } else { printf("ERROR: Dependency must have version\n"); - exit(1); + std::exit(1); } } } else if (argv[i] == "-t") { @@ -137,14 +137,14 @@ void CrossLangCompiler(std::vector &argv) { printf("Expected " "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-" "prod]]]]\n"); - exit(1); + std::exit(1); } tools.push_back( std::pair(str1, v2)); } else { printf("ERROR: Tool must have version\n"); - exit(1); + std::exit(1); } } } else if (argv[i] == "-n") { @@ -161,7 +161,7 @@ void CrossLangCompiler(std::vector &argv) { printf("Expected " "MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]" "]]]\n"); - exit(1); + std::exit(1); } } } else if (argv[i] == "-D" || argv[i] == "--debug") { diff --git a/src/runtime_methods/console.cpp b/src/runtime_methods/console.cpp index 04f3349..11c7971 100644 --- a/src/runtime_methods/console.cpp +++ b/src/runtime_methods/console.cpp @@ -72,11 +72,11 @@ TObject Console_Write(GCList &ls, std::vector args) { TObject Console_Fatal(GCList &ls, std::vector args) { if (args.size() < 1) { Tesses::Framework::Console::ErrorLine("FATAL: "); - exit(1); + std::exit(1); } Tesses::Framework::Console::ErrorLine("FATAL: " + ToString(ls.GetGC(), args[0])); - exit(1); + std::exit(1); } TObject Console_WriteLine(GCList &ls, std::vector args) { diff --git a/src/runtime_methods/json.cpp b/src/runtime_methods/json.cpp index dc4bfb0..9aa7bf0 100644 --- a/src/runtime_methods/json.cpp +++ b/src/runtime_methods/json.cpp @@ -159,7 +159,7 @@ static TObject JsonDocDecode(GCList &ls2, std::vector args) { std::string Json_Encode(TObject o, bool indent) { return Json::Encode(JsonSerialize(o), indent); } -TObject Json_Decode(GCList ls, std::string str) { +TObject Json_Decode(GCList &ls, std::string str) { return JsonDeserialize(ls, Json::Decode(str)); } std::string Json_DocEncode(TObject o, bool indent) { @@ -169,7 +169,7 @@ std::string Json_DocEncode(TObject o, bool indent) { return Json::DocEncode(ls, indent); return ""; } -TObject Json_DocDecode(GCList ls, std::string str) { +TObject Json_DocDecode(GCList &ls, std::string str) { return JsonDeserialize(ls, Json::DocDecode(str)); } void TStd::RegisterJson(std::shared_ptr gc, TRootEnvironment *env) { diff --git a/src/runtime_methods/net.cpp b/src/runtime_methods/net.cpp index 73f7804..8cc831e 100644 --- a/src/runtime_methods/net.cpp +++ b/src/runtime_methods/net.cpp @@ -150,6 +150,46 @@ class THttpDictionary : public TNativeObject { value); } return nullptr; + } else if (key == "TryGetOnlyOne") { + std::string key; + std::string value; + if (GetArgument(args, 0, key) && dict->TryGetOnlyOne(key, value)) { + return value; + } + return nullptr; + } else if (key == "TryGetOnlyOneBoolean") { + std::string key; + bool value; + if (GetArgument(args, 0, key) && + dict->TryGetOnlyOneBoolean(key, value)) { + return value; + } + return nullptr; + } else if (key == "TryGetOnlyOneDouble") { + std::string key; + double value; + if (GetArgument(args, 0, key) && + dict->TryGetOnlyOneDouble(key, value)) { + return value; + } + return nullptr; + } else if (key == "TryGetOnlyOneInt") { + std::string key; + int64_t value; + if (GetArgument(args, 0, key) && + dict->TryGetOnlyOneInt(key, value)) { + return value; + } + return nullptr; + } else if (key == "TryGetOnlyOneDate") { + std::string key; + Tesses::Framework::Date::DateTime value; + if (GetArgument(args, 0, key) && + dict->TryGetOnlyOneDate(key, value)) { + return std::make_shared( + value); + } + return nullptr; } else if (key == "ToList") { TList *_ls = TList::Create(ls); for (auto item : dict->kvp) { @@ -239,6 +279,9 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary { else if (key == "getQueryParams") return TNativeObject::Create(ls, &ctx->queryParams, this); + else if (key == "getBodyParams") + return TNativeObject::Create(ls, &ctx->bodyParams, + this); else if (key == "getRequestHeaders") return TNativeObject::Create( ls, &ctx->requestHeaders, this); @@ -781,17 +824,19 @@ static TObject Net_Http_MimeType(GCList &ls, std::vector args) { Tesses::Framework::Filesystem::VFSPath p; if (GetArgumentAsPath(args, 0, p)) { std::filesystem::path p2 = p.GetFileName(); - return HttpUtils::MimeType(p2); + return HttpUtils::GetMimeType(p2); } return std::string("application/octet-stream"); } class THttpRequestBody : public TNativeObject { - HttpRequestBody *body; + std::shared_ptr body; public: - THttpRequestBody(HttpRequestBody *body) { this->body = body; } + THttpRequestBody(std::shared_ptr body) { + this->body = body; + } bool IsClosed() { return body == nullptr; } - HttpRequestBody *GetBody() { return this->body; } + std::shared_ptr GetBody() { return this->body; } std::string TypeName() { return "Net.Http.HttpRequestBody"; } @@ -799,10 +844,7 @@ class THttpRequestBody : public TNativeObject { return Undefined(); } - void Close() { - delete this->body; - this->body = nullptr; - } + void Close() { this->body = nullptr; } }; class THttpResponse : public TNativeObjectThatReturnsHttpDictionary { @@ -907,7 +949,8 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector args, _obj = options->GetValue("Body"); if (GetObjectHeap(_obj, body1)) { - req.body = new TDictionaryHttpRequestBody(gc, body1); + req.body = + std::make_shared(gc, body1); } else if (GetObjectHeap(_obj, body2) && !body2->IsClosed()) { req.body = body2->GetBody(); } @@ -920,8 +963,6 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector args, if (req.body != nullptr) { if (body2 != nullptr) { body2->Close(); - } else if (body1 != nullptr) { - delete req.body; } } @@ -1073,7 +1114,7 @@ static TObject Net_Http_WebSocketClient(GCList &ls, std::vector args) { if (GetArgument(args, 0, url) && GetArgumentHeap(args, 1, headers) && GetArgumentHeap(args, 2, dict)) { GetArgumentHeap(args, 3, callable); - HttpDictionary hdict; + HttpDictionary hdict(false); for (int64_t index = 0; index < headers->Count(); index++) { _obj = headers->Get(index); TDictionary *dict; @@ -1171,7 +1212,7 @@ static TObject Net_Http_WebSocketClient(GCList &ls, std::vector args) { if (!GetObjectHeap(hobj, headers)) return Undefined(); - HttpDictionary hdict; + HttpDictionary hdict(false); for (int64_t index = 0; index < headers->Count(); index++) { _obj = headers->Get(index); TDictionary *dict; @@ -1381,7 +1422,7 @@ static TObject New_StreamHttpRequestBody(GCList &ls, if (GetArgument(args, 0, strm) && GetArgument(args, 1, mimeType)) { return TNativeObject::Create( - ls, new StreamHttpRequestBody(strm, mimeType)); + ls, std::make_shared(strm, mimeType)); } return nullptr; } @@ -1390,7 +1431,7 @@ static TObject New_TextHttpRequestBody(GCList &ls, std::vector args) { std::string mimeType; if (GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) { return TNativeObject::Create( - ls, new TextHttpRequestBody(text, mimeType)); + ls, std::make_shared(text, mimeType)); } return nullptr; } @@ -1398,8 +1439,8 @@ static TObject New_JsonHttpRequestBody(GCList &ls, std::vector args) { if (!args.empty()) { return TNativeObject::Create( - ls, - new TextHttpRequestBody(Json_Encode(args[0]), "application/json")); + ls, std::make_shared(Json_Encode(args[0]), + "application/json")); } return nullptr; } @@ -1423,7 +1464,7 @@ void TStd::RegisterNet(std::shared_ptr gc, TRootEnvironment *env) { "Create a text request body", {"text", "mimeType"}, New_TextHttpRequestBody); _new->DeclareFunction(gc, "JsonHttpRequestBody", - "Create a text request body", {"json"}, + "Create a json request body", {"json"}, New_JsonHttpRequestBody); _new->DeclareFunction( gc, "HttpServer", "Create a http server (allows multiple)", diff --git a/src/runtime_methods/process.cpp b/src/runtime_methods/process.cpp index 5c502b4..b19fd06 100644 --- a/src/runtime_methods/process.cpp +++ b/src/runtime_methods/process.cpp @@ -3,10 +3,6 @@ namespace Tesses::CrossLang { class ProcessObject : public TNativeObject { public: - ProcessObject() { - arguments = nullptr; - environment = nullptr; - } ProcessObject(GCList &ls) { arguments = TList::Create(ls); environment = TList::Create(ls); @@ -167,7 +163,7 @@ static TObject Process_Start(GCList &ls, std::vector args, TDictionary *dict; if (GetArgumentHeap(args, 0, dict)) { - auto process = TNativeObject::Create(ls); + auto process = TNativeObject::Create(ls, ls); auto name = dict->GetValue("FileName"); auto inh = dict->GetValue("InheritParentEnvironment"); auto rStdIn = dict->GetValue("RedirectStandardInput"); diff --git a/src/runtime_methods/std.cpp b/src/runtime_methods/std.cpp index fe5ae5d..67d2444 100644 --- a/src/runtime_methods/std.cpp +++ b/src/runtime_methods/std.cpp @@ -1613,7 +1613,13 @@ void TStd::RegisterStd( gc_dict->DeclareFunction( gc, "Collect", "Collect garbage", {}, [](GCList &ls, std::vector args) -> TObject { - ls.GetGC()->Collect(); + std::vector to_delete; + ls.GetGC()->BarrierBegin(); + ls.GetGC()->Collect(to_delete); + ls.GetGC()->BarrierEnd(); + + for (auto item : to_delete) + delete item; return nullptr; }); gc_dict->DeclareFunction( diff --git a/src/runtime_methods/vm.cpp b/src/runtime_methods/vm.cpp index 3f2d353..518f2f3 100644 --- a/src/runtime_methods/vm.cpp +++ b/src/runtime_methods/vm.cpp @@ -67,6 +67,8 @@ static TObject VM_SourceToAst(GCList &ls, std::vector args) { static TObject VM_Eval(GCList &ls, std::vector args) { std::string str; if (GetArgument(args, 0, str)) { + + auto current_function = GC::GetCurrentFunction(); if (current_function != nullptr) { return current_function->env->Eval(ls, str); } @@ -90,6 +92,8 @@ static TObject Success(GCList &ls) { } static TObject VM_getCurrentEnvironment(GCList &ls2, std::vector args) { + + auto current_function = GC::GetCurrentFunction(); if (current_function != nullptr) return current_function->env; return Undefined(); @@ -261,6 +265,7 @@ static TObject VM_Compile(GCList &ls, std::vector args) { } } 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); diff --git a/src/types/any.cpp b/src/types/any.cpp index a98f01e..0442b5e 100644 --- a/src/types/any.cpp +++ b/src/types/any.cpp @@ -1,22 +1,8 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { -TAny *TAny::Create(GCList &ls) { - TAny *anyObj = new TAny(); - - std::shared_ptr gc = ls.GetGC(); - ls.Add(anyObj); - gc->Watch(anyObj); - return anyObj; -} -TAny *TAny::Create(GCList *ls) { - TAny *anyObj = new TAny(); - - std::shared_ptr gc = ls->GetGC(); - ls->Add(anyObj); - gc->Watch(anyObj); - return anyObj; -} +TAny *TAny::Create(GCList &ls) { return ls.Create(); } +TAny *TAny::Create(GCList *ls) { return ls->Create(); } void TAny::Mark() { if (this->marked) return; diff --git a/src/types/associativearray.cpp b/src/types/associativearray.cpp index b3cf6ab..57923a5 100644 --- a/src/types/associativearray.cpp +++ b/src/types/associativearray.cpp @@ -3,18 +3,10 @@ namespace Tesses::CrossLang { TAssociativeArray *TAssociativeArray::Create(GCList &ls) { - TAssociativeArray *list = new TAssociativeArray(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(list); - _gc->Watch(list); - return list; + return ls.Create(); } TAssociativeArray *TAssociativeArray::Create(GCList *ls) { - TAssociativeArray *list = new TAssociativeArray(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(list); - _gc->Watch(list); - return list; + return ls->Create(); } void TAssociativeArray::Set(std::shared_ptr gc, TObject key, TObject value) { diff --git a/src/types/classenvironment.cpp b/src/types/classenvironment.cpp index e5af5e5..287da2e 100644 --- a/src/types/classenvironment.cpp +++ b/src/types/classenvironment.cpp @@ -9,22 +9,12 @@ bool TClassEnvironment::HasConstForSet(std::string key) { TClassEnvironment *TClassEnvironment::Create(GCList *gc, TEnvironment *env, TClassObject *obj) { - TClassEnvironment *env2 = new TClassEnvironment(env, obj); - - std::shared_ptr _gc = gc->GetGC(); - gc->Add(env2); - _gc->Watch(env2); - return env2; + return gc->Create(env, obj); } TClassEnvironment *TClassEnvironment::Create(GCList &gc, TEnvironment *env, TClassObject *obj) { - TClassEnvironment *env2 = new TClassEnvironment(env, obj); - - std::shared_ptr _gc = gc.GetGC(); - gc.Add(env2); - _gc->Watch(env2); - return env2; + return gc.Create(env, obj); } TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) { this->env = env; @@ -33,6 +23,7 @@ TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) { bool TClassEnvironment::HasVariable(std::string key) { if (key == "this") return true; + auto current_function = GC::GetCurrentFunction(); if (this->clsObj->HasValue(current_function == nullptr ? "" : current_function->callable->className, @@ -49,6 +40,8 @@ bool TClassEnvironment::HasVariableOrFieldRecurse(std::string key, bool setting) { if (key == "this") return true; + + auto current_function = GC::GetCurrentFunction(); std::string clsName = current_function == nullptr ? "" : current_function->callable->className; @@ -63,6 +56,7 @@ TObject TClassEnvironment::GetVariable(std::string key) { if (key == "this") return this->clsObj; + auto current_function = GC::GetCurrentFunction(); std::string clsName = current_function == nullptr ? "" : current_function->callable->className; @@ -75,6 +69,7 @@ void TClassEnvironment::SetVariable(std::string key, TObject value) { if (key == "this") return; + auto current_function = GC::GetCurrentFunction(); std::string clsName = current_function == nullptr ? "" : current_function->callable->className; @@ -90,6 +85,7 @@ TObject TClassEnvironment::GetVariable(GCList &ls, std::string key) { if (key == "this") return this->clsObj; + auto current_function = GC::GetCurrentFunction(); std::string clsName = current_function == nullptr ? "" : current_function->callable->className; @@ -107,6 +103,7 @@ TObject TClassEnvironment::SetVariable(GCList &ls, std::string key, TObject v) { if (key == "this") return this->clsObj; + auto current_function = GC::GetCurrentFunction(); std::string clsName = current_function == nullptr ? "" : current_function->callable->className; diff --git a/src/types/closure.cpp b/src/types/closure.cpp index 055cfb3..b675373 100644 --- a/src/types/closure.cpp +++ b/src/types/closure.cpp @@ -1,27 +1,18 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { +TArgWrapper::TArgWrapper(TCallable *callable) : callable(callable) {} TArgWrapper *TArgWrapper::Create(GCList &ls, TCallable *callable) { - TArgWrapper *argWrapper = new TArgWrapper(); - argWrapper->callable = callable; - std::shared_ptr gc = ls.GetGC(); - ls.Add(argWrapper); - gc->Watch(argWrapper); - return argWrapper; + return ls.Create(callable); } TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) { - TArgWrapper *argWrapper = new TArgWrapper(); - argWrapper->callable = callable; - std::shared_ptr gc = ls->GetGC(); - ls->Add(argWrapper); - gc->Watch(argWrapper); - return argWrapper; + return ls->Create(callable); } TObject TArgWrapper::Call(GCList &ls, std::vector args) { - auto cse = current_function; + auto cse = GC::GetCurrentFunction(); TList *argList = TList::Create(ls); argList->items = args; TObject v = this->callable->Call(ls, {argList}); - current_function = cse; + GC::SetCurrentFunction(cse); return v; } void TArgWrapper::Mark() { @@ -46,52 +37,39 @@ void TClosure::Mark() { this->closure->Mark(); GC::Mark(this->tag); } -TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file, - uint32_t chunkId, bool ownScope) { - TClosure *closure = new TClosure(); - closure->className = ""; - closure->ownScope = ownScope; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(closure); - _gc->Watch(closure); - closure->chunkId = chunkId; +TClosure::TClosure(TEnvironment *env, TFile *file, uint32_t chunkId, + bool ownScope) { + this->className = ""; + this->ownScope = ownScope; + + this->chunkId = chunkId; + if (chunkId < file->chunks.size()) - closure->closure = file->chunks[chunkId]; + this->closure = file->chunks[chunkId]; else throw VMException("ChunkId out of bounds."); - closure->env = env; - closure->file = file; - - return closure; + this->env = env; + this->file = file; +} +TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file, + uint32_t chunkId, bool ownScope) { + return ls.Create(env, file, chunkId, ownScope); } TClosure *TClosure::Create(GCList *ls, TEnvironment *env, TFile *file, uint32_t chunkId, bool ownScope) { - TClosure *closure = new TClosure(); - closure->className = ""; - closure->ownScope = ownScope; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(closure); - _gc->Watch(closure); - closure->chunkId = chunkId; - if (chunkId < file->chunks.size()) - closure->closure = file->chunks[chunkId]; - else - throw VMException("ChunkId out of bounds."); - closure->env = env; - closure->file = file; - - return closure; + return ls->Create(env, file, chunkId, ownScope); } TObject TClosure::Call(GCList &ls, std::vector args) { - auto cse = current_function; + auto cse = GC::GetCurrentFunction(); InterperterThread *thrd = InterperterThread::Create(ls); thrd->AddCallStackEntry(ls, this, args); thrd->Execute(ls.GetGC()); TObject v = thrd->call_stack_entries[0]->Pop(ls); - current_function = cse; + GC::SetCurrentFunction(cse); + // current_function = cse; return v; } } // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/dictionary.cpp b/src/types/dictionary.cpp index 34edcd9..e773453 100644 --- a/src/types/dictionary.cpp +++ b/src/types/dictionary.cpp @@ -1,24 +1,15 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { +TDynamicDictionary::TDynamicDictionary(TCallable *callable) : cb(callable) {} TDynamicDictionary *TDynamicDictionary::Create(GCList &ls, TCallable *callable) { - TDynamicDictionary *dict = new TDynamicDictionary(); - dict->cb = callable; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(dict); - _gc->Watch(dict); - return dict; + return ls.Create(callable); } TDynamicDictionary *TDynamicDictionary::Create(GCList *ls, TCallable *callable) { - TDynamicDictionary *dict = new TDynamicDictionary(); - dict->cb = callable; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(dict); - _gc->Watch(dict); - return dict; + return ls->Create(callable); } void TDynamicDictionary::Mark() { @@ -165,8 +156,9 @@ void TDictionary::DeclareFunction( TObject TDictionary::GetValue(std::string key) { if (this->items.empty()) return Undefined(); - if (this->items.count(key) > 0) - return this->items[key]; + auto item = this->items.find(key); + if (item != this->items.end()) + return item->second; return Undefined(); } void TDictionary::SetValue(std::string key, TObject value) { @@ -189,18 +181,10 @@ void TDictionary::Mark() { } } TDictionary *TDictionary::Create(GCList *gc) { - TDictionary *dict = new TDictionary(); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(dict); - _gc->Watch(dict); - return dict; + return gc->Create(); } TDictionary *TDictionary::Create(GCList &gc) { - TDictionary *dict = new TDictionary(); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(dict); - _gc->Watch(dict); - return dict; + return gc.Create(); } }; // namespace Tesses::CrossLang diff --git a/src/types/exception.cpp b/src/types/exception.cpp new file mode 100644 index 0000000..4ce35ab --- /dev/null +++ b/src/types/exception.cpp @@ -0,0 +1,168 @@ +#include "CrossLang.hpp" + +namespace Tesses::CrossLang { + +TException::TException(std::string message, std::string type, + TDictionary *extraFields, TObject innerException) + : message(message), type(type), extraFields(extraFields), + innerException(innerException) {} +TObject TException::CallMethod(GCList &ls, std::string key, + std::vector args) { + + if (key == "getMessage" || + key == "getText") // Text is for compatibility reasons + return this->message; + if (key == "getInnerException") + return this->innerException; + if (key == "getType") + return this->type; + if (key == "getLine") + return static_cast(this->line.value_or(0)); + if (key == "getOffset") + return static_cast(this->offset.value_or(0)); + if (key == "getColumn") + return static_cast(this->column.value_or(0)); + if (key == "getFileName") + return this->filename.value_or(""); + + if (key == "setLine") { + int64_t v; + if (!this->line && GetArgument(args, 0, v)) + this->line = static_cast(v); + + return Undefined(); + } + if (key == "setColumn") { + int64_t v; + if (!this->column && GetArgument(args, 0, v)) + this->column = static_cast(v); + + return Undefined(); + } + if (key == "setOffset") { + int64_t v; + if (!this->offset && GetArgument(args, 0, v)) + this->offset = static_cast(v); + + return Undefined(); + } + if (key == "setFileName") { + std::string v; + if (!this->filename && GetArgument(args, 0, v)) + this->filename = v; + + return Undefined(); + } + + if (key == "ToString") { + std::string text; + text.reserve(this->type.size() + this->message.size() + 3); + text.append(this->type); + text.append(": "); + text.append(this->message); + text.push_back('\n'); + if (this->filename) { + auto &filename = *this->filename; + text.reserve(text.size() + filename.size() + 4); + text.append("At: "); + text.append(filename); + + if (this->line) { + text.push_back(':'); + text.append(std::to_string(*this->line)); + if (this->column) { + + text.push_back(':'); + text.append(std::to_string(*this->column)); + } + } + text.push_back('\n'); + + if (!this->line && this->column) { + text.append("Column: "); + text.append(std::to_string(*this->column)); + text.push_back('\n'); + } + } else { + if (this->line) { + text.append("Line: "); + text.append(std::to_string(*this->line)); + text.push_back('\n'); + } + if (this->column) { + text.append("Column: "); + text.append(std::to_string(*this->column)); + text.push_back('\n'); + } + } + + if (this->offset) { + text.append("Offset: "); + text.append(std::to_string(*this->offset)); + text.push_back('\n'); + } + if (!std::holds_alternative(this->innerException)) { + text.append("InnerException:"); + + std::string textInner = ToString(ls.GetGC(), this->innerException); + + for (auto item : Tesses::Framework::Http::HttpUtils::SplitString( + textInner, "\n")) { + if (item.empty()) { + text.push_back('\n'); + continue; + } + text.append("\n\t"); + text.append(item); + } + } + return text; + } + if (extraFields != nullptr) { + GCList ls2(ls.GetGC()); + if (extraFields->MethodExists(ls2, key)) { + return extraFields->CallMethod(ls, key, args); + } + + if (key.size() > 3 && key[0] == 'g' && key[1] == 'e' && key[2] == 't') { + ls.GetGC()->BarrierBegin(); + auto val = extraFields->GetValue(key.substr(3)); + ls.GetGC()->BarrierEnd(); + return val; + } + } + + return Undefined(); +} +std::string TException::TypeName() { return this->type; } +bool TException::ToBool() { return true; } +void TException::Mark() { + if (marked) + return; + marked = true; + + if (this->extraFields) + this->extraFields->Mark(); + + GC::Mark(this->innerException); +} + +TNativeException::TNativeException(const char *what, std::exception_ptr ptr) + : what(what != nullptr ? what : ""), ptr(ptr) {} +TObject TNativeException::CallMethod(GCList &ls, std::string key, + std::vector args) { + if (key == "getMessage" || key == "getText") + return this->what; + if (key == "getType") + return "NativeException"; + + if (key == "ToString") { + return "NativeException: " + this->what; + } + return Undefined(); +} +std::string TNativeException::TypeName() { return "NativeException"; } +std::string TNativeException::What() { return this->what; } +std::exception_ptr TNativeException::GetPointer() { return this->ptr; } +void TNativeException::ThrowIt() { std::rethrow_exception(this->ptr); } +} // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/types/externalmethod.cpp b/src/types/externalmethod.cpp index c97dd12..e9ea82e 100644 --- a/src/types/externalmethod.cpp +++ b/src/types/externalmethod.cpp @@ -1,8 +1,8 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { TExternalMethod::TExternalMethod( - std::function args)> cb, std::string documentation, std::vector argNames, + std::function args)> cb, std::function destroy) { this->cb = cb; @@ -14,43 +14,24 @@ TExternalMethod *TExternalMethod::Create( GCList &ls, std::string documentation, std::vector argNames, std::function args)> cb, std::function destroy) { - auto gc = ls.GetGC(); - TExternalMethod *method = - new TExternalMethod(cb, documentation, argNames, destroy); - ls.Add(method); - gc->Watch(method); - return method; + return ls.Create(documentation, argNames, cb, destroy); } TExternalMethod *TExternalMethod::Create( GCList *ls, std::string documentation, std::vector argNames, std::function args)> cb, std::function destroy) { - auto gc = ls->GetGC(); - TExternalMethod *method = - new TExternalMethod(cb, documentation, argNames, destroy); - ls->Add(method); - gc->Watch(method); - return method; + return ls->Create(documentation, argNames, cb, destroy); } TExternalMethod *TExternalMethod::Create( GCList &ls, std::string documentation, std::vector argNames, std::function args)> cb) { - auto gc = ls.GetGC(); - TExternalMethod *method = - new TExternalMethod(cb, documentation, argNames, []() -> void {}); - ls.Add(method); - gc->Watch(method); - return method; + return ls.Create(documentation, argNames, cb); } TExternalMethod *TExternalMethod::Create( GCList *ls, std::string documentation, std::vector argNames, std::function args)> cb) { - auto gc = ls->GetGC(); - TExternalMethod *method = - new TExternalMethod(cb, documentation, argNames, []() -> void {}); - ls->Add(method); - gc->Watch(method); - return method; + + return ls->Create(documentation, argNames, cb); } TObject TExternalMethod::Call(GCList &ls, std::vector args) { if (cb == nullptr) diff --git a/src/types/ittr.cpp b/src/types/ittr.cpp index d471258..a9b3381 100644 --- a/src/types/ittr.cpp +++ b/src/types/ittr.cpp @@ -44,28 +44,15 @@ void TYieldEnumerator::Mark() { GC::Mark(this->current); GC::Mark(this->enumerator); } -TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) { - TYieldEnumerator *yieldEnum = new TYieldEnumerator(); - yieldEnum->current = nullptr; - yieldEnum->hasStarted = false; - yieldEnum->enumerator = v; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(yieldEnum); - _gc->Watch(yieldEnum); - return yieldEnum; +TYieldEnumerator::TYieldEnumerator(TObject v) + : current(nullptr), hasStarted(false), enumerator(v) {} + +TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) { + return ls.Create(v); } TYieldEnumerator *TYieldEnumerator::Create(GCList *ls, TObject v) { - - TYieldEnumerator *yieldEnum = new TYieldEnumerator(); - yieldEnum->current = nullptr; - yieldEnum->hasStarted = false; - yieldEnum->enumerator = v; - - std::shared_ptr _gc = ls->GetGC(); - ls->Add(yieldEnum); - _gc->Watch(yieldEnum); - return yieldEnum; + return ls->Create(v); } bool TCustomEnumerator::MoveNext(std::shared_ptr ls) { @@ -97,21 +84,12 @@ void TCustomEnumerator::Mark() { return; this->dict->Mark(); } +TCustomEnumerator::TCustomEnumerator(TDictionary *dict) : dict(dict) {} TCustomEnumerator *TCustomEnumerator::Create(GCList *ls, TDictionary *dict) { - TCustomEnumerator *customEnum = new TCustomEnumerator(); - customEnum->dict = dict; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(customEnum); - _gc->Watch(customEnum); - return customEnum; + return ls->Create(dict); } TCustomEnumerator *TCustomEnumerator::Create(GCList &ls, TDictionary *dict) { - TCustomEnumerator *customEnum = new TCustomEnumerator(); - customEnum->dict = dict; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(customEnum); - _gc->Watch(customEnum); - return customEnum; + return ls.Create(dict); } TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) { std::string str; @@ -141,23 +119,16 @@ TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) { } return nullptr; } +TVFSPathEnumerator::TVFSPathEnumerator( + Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) + : enumerator(enumerator) {} TVFSPathEnumerator *TVFSPathEnumerator::Create( GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) { - TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator(); - vfspathe->enumerator = enumerator; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(vfspathe); - _gc->Watch(vfspathe); - return vfspathe; + return ls.Create(enumerator); } TVFSPathEnumerator *TVFSPathEnumerator::Create( GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) { - TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator(); - vfspathe->enumerator = enumerator; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(vfspathe); - _gc->Watch(vfspathe); - return vfspathe; + return ls->Create(enumerator); } bool TVFSPathEnumerator::MoveNext(std::shared_ptr ls) { return enumerator.MoveNext(); @@ -165,25 +136,15 @@ bool TVFSPathEnumerator::MoveNext(std::shared_ptr ls) { TObject TVFSPathEnumerator::GetCurrent(GCList &ls) { return enumerator.Current; } +TDictionaryEnumerator::TDictionaryEnumerator(TDictionary *dict) + : dict(dict), hasStarted(false) {} TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList &ls, TDictionary *dict) { - TDictionaryEnumerator *dicte = new TDictionaryEnumerator(); - dicte->dict = dict; - dicte->hasStarted = false; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(dicte); - _gc->Watch(dicte); - return dicte; + return ls.Create(dict); } TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList *ls, TDictionary *dict) { - TDictionaryEnumerator *dicte = new TDictionaryEnumerator(); - dicte->dict = dict; - dicte->hasStarted = false; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(dicte); - _gc->Watch(dicte); - return dicte; + return ls->Create(dict); } bool TDictionaryEnumerator::MoveNext(std::shared_ptr ls) { @@ -217,24 +178,13 @@ void TDictionaryEnumerator::Mark() { this->marked = true; this->dict->Mark(); } +TListEnumerator::TListEnumerator(TList *list) : ls(list), index(-1) {} TListEnumerator *TListEnumerator::Create(GCList &ls, TList *list) { - TListEnumerator *liste = new TListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(liste); - _gc->Watch(liste); - return liste; + return ls.Create(list); } TListEnumerator *TListEnumerator::Create(GCList *ls, TList *list) { - TListEnumerator *liste = new TListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(liste); - _gc->Watch(liste); - return liste; + return ls->Create(list); } bool TListEnumerator::MoveNext(std::shared_ptr ls) { this->index++; @@ -260,25 +210,17 @@ void TListEnumerator::Mark() { this->ls->Mark(); } +TAssociativeArrayEnumerator::TAssociativeArrayEnumerator( + TAssociativeArray *list) + : ls(list), index(-1) {} + TAssociativeArrayEnumerator * TAssociativeArrayEnumerator::Create(GCList &ls, TAssociativeArray *list) { - TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(liste); - _gc->Watch(liste); - return liste; + return ls.Create(list); } TAssociativeArrayEnumerator * TAssociativeArrayEnumerator::Create(GCList *ls, TAssociativeArray *list) { - TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(liste); - _gc->Watch(liste); - return liste; + return ls->Create(list); } bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr ls) { this->index++; @@ -305,26 +247,16 @@ void TAssociativeArrayEnumerator::Mark() { this->marked = true; this->ls->Mark(); } +TDynamicListEnumerator::TDynamicListEnumerator(TDynamicList *list) + : ls(list), index(-1) {} TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList &ls, TDynamicList *list) { - TDynamicListEnumerator *liste = new TDynamicListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(liste); - _gc->Watch(liste); - return liste; + return ls.Create(list); } TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList *ls, TDynamicList *list) { - TDynamicListEnumerator *liste = new TDynamicListEnumerator(); - liste->ls = list; - liste->index = -1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(liste); - _gc->Watch(liste); - return liste; + return ls->Create(list); } bool TDynamicListEnumerator::MoveNext(std::shared_ptr ls) { this->index++; @@ -351,24 +283,13 @@ void TDynamicListEnumerator::Mark() { this->marked = true; this->ls->Mark(); } - +TStringEnumerator::TStringEnumerator(std::string str) + : str(str), hasStarted(false) {} TStringEnumerator *TStringEnumerator::Create(GCList &ls, std::string str) { - TStringEnumerator *stre = new TStringEnumerator(); - stre->str = str; - stre->hasStarted = false; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(stre); - _gc->Watch(stre); - return stre; + return ls.Create(str); } TStringEnumerator *TStringEnumerator::Create(GCList *ls, std::string str) { - TStringEnumerator *stre = new TStringEnumerator(); - stre->str = str; - stre->hasStarted = false; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(stre); - _gc->Watch(stre); - return stre; + return ls->Create(str); } bool TStringEnumerator::MoveNext(std::shared_ptr ls) { if (!this->hasStarted) { diff --git a/src/types/list.cpp b/src/types/list.cpp index 37615c2..fb6eb2b 100644 --- a/src/types/list.cpp +++ b/src/types/list.cpp @@ -1,20 +1,11 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { +TDynamicList::TDynamicList(TCallable *callable) : cb(callable) {} TDynamicList *TDynamicList::Create(GCList &ls, TCallable *callable) { - TDynamicList *list = new TDynamicList(); - list->cb = callable; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(list); - _gc->Watch(list); - return list; + return ls.Create(callable); } TDynamicList *TDynamicList::Create(GCList *ls, TCallable *callable) { - TDynamicList *list = new TDynamicList(); - list->cb = callable; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(list); - _gc->Watch(list); - return list; + return ls->Create(callable); } void TDynamicList::Mark() { @@ -120,35 +111,11 @@ TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) { TDynamicList::~TDynamicList() {} -TByteArray *TByteArray::Create(GCList &ls) { - TByteArray *arr = new TByteArray(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(arr); - _gc->Watch(arr); - return arr; -} +TByteArray *TByteArray::Create(GCList &ls) { return ls.Create(); } -TByteArray *TByteArray::Create(GCList *ls) { - TByteArray *arr = new TByteArray(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(arr); - _gc->Watch(arr); - return arr; -} -TList *TList::Create(GCList *gc) { - TList *list = new TList(); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(list); - _gc->Watch(list); - return list; -} -TList *TList::Create(GCList &gc) { - TList *list = new TList(); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(list); - _gc->Watch(list); - return list; -} +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()) { @@ -161,7 +128,7 @@ TObject TList::Get(int64_t index) { } return Undefined(); } -int64_t TList::Count() { return (int64_t)this->items.size(); } +int64_t TList::Count() { return this->items.size(); } void TList::Insert(int64_t index, TObject value) { if (index >= 0 && index <= this->Count()) { this->items.insert(this->items.begin() + index, value); diff --git a/src/types/native.cpp b/src/types/native.cpp index 18a5f61..17f9c37 100644 --- a/src/types/native.cpp +++ b/src/types/native.cpp @@ -1,7 +1,6 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { -TNativeObject::~TNativeObject() {} TNative::TNative(void *ptr, std::function destroy) { this->ptr = ptr; @@ -34,19 +33,11 @@ bool TNativeObject::Equals(std::shared_ptr gc, TObject right) { } TNative *TNative::Create(GCList &ls, void *ptr, std::function destroy) { - TNative *native = new TNative(ptr, destroy); - std::shared_ptr gc = ls.GetGC(); - ls.Add(native); - gc->Watch(native); - return native; + return ls.Create(ptr, destroy); } TNative *TNative::Create(GCList *ls, void *ptr, std::function destroy) { - TNative *native = new TNative(ptr, destroy); - std::shared_ptr gc = ls->GetGC(); - ls->Add(native); - gc->Watch(native); - return native; + return ls->Create(ptr, destroy); } TNative::~TNative() { this->Destroy(); } diff --git a/src/types/queryable.cpp b/src/types/queryable.cpp index f2f64b6..4a43a81 100644 --- a/src/types/queryable.cpp +++ b/src/types/queryable.cpp @@ -41,19 +41,11 @@ TList *TQueryable::ToList(GCList &ls) { return list; } TQueryable *TQueryable::Create(GCList &ls, TObject parent) { - TQueryable *queryable = new TQueryable(parent); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; + return ls.Create(parent); } TQueryable *TQueryable::Create(GCList &ls, TObject parent, TQueryableMode mode, std::vector args) { - TQueryable *queryable = new TQueryable(parent, mode, args); - std::shared_ptr gc = ls.GetGC(); - ls.Add(queryable); - gc->Watch(queryable); - return queryable; + return ls.Create(parent, mode, args); } void TQueryable::Mark() { diff --git a/src/types/rootenvironment.cpp b/src/types/rootenvironment.cpp index ea3dbf9..7b74b5e 100644 --- a/src/types/rootenvironment.cpp +++ b/src/types/rootenvironment.cpp @@ -9,12 +9,11 @@ void ThrowConstError(std::string key) { void TEnvironment::DeclareConstVariable(std::string key, TObject value) { this->DeclareVariable(key, value); - this->consts.push_back(key); + this->decls[key] = TEnvironmentDeclType::TEDT_CONST; } bool TEnvironment::HasConstForDeclare(std::string key) { - for (auto item : this->consts) - if (item == key) - return true; + if (this->decls.count(key) > 0) + return this->decls[key] == TEnvironmentDeclType::TEDT_CONST; return false; } bool TEnvironment::HasConstForSet(std::string key) { @@ -308,13 +307,15 @@ void TRootEnvironment::SetVariable(std::string key, TObject value) { this->dict->SetValue(key, value); } void TRootEnvironment::DeclareVariable(std::string key, TObject value) { + if (this->decls.count(key) == 0) + this->decls[key] = TEnvironmentDeclType::TEDT_VAR; return this->dict->SetValue(key, value); } bool TRootEnvironment::HasVariable(std::string key) { - return this->dict->HasValue(key); + return this->dict->HasValue(key) || this->decls.count(key) > 0; } bool TRootEnvironment::HasVariableRecurse(std::string key) { - return this->dict->HasValue(key); + return this->dict->HasValue(key) || this->decls.count(key) > 0; } TEnvironment *TRootEnvironment::GetParentEnvironment() { return this; } TRootEnvironment *TRootEnvironment::GetRootEnvironment() { return this; } @@ -338,18 +339,10 @@ void TRootEnvironment::Mark() { cls.first->Mark(); } TRootEnvironment *TRootEnvironment::Create(GCList *gc, TDictionary *dict) { - TRootEnvironment *env = new TRootEnvironment(dict); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(env); - _gc->Watch(env); - return env; + return gc->Create(dict); } TRootEnvironment *TRootEnvironment::Create(GCList &gc, TDictionary *dict) { - TRootEnvironment *env = new TRootEnvironment(dict); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(env); - _gc->Watch(env); - return env; + return gc.Create(dict); } bool TRootEnvironment::HandleException(std::shared_ptr gc, diff --git a/src/types/subenvironment.cpp b/src/types/subenvironment.cpp index 4064ce7..0ca9332 100644 --- a/src/types/subenvironment.cpp +++ b/src/types/subenvironment.cpp @@ -82,16 +82,24 @@ TObject TSubEnvironment::GetVariable(std::string key) { if (this->dict->HasValue(key)) { return this->dict->GetValue(key); } + if (this->decls.count(key) > 0 && + this->decls[key] == TEnvironmentDeclType::TEDT_VAR) { + return Undefined(); + } if (this->env->HasVariableRecurse(key)) { return this->env->GetVariable(key); } return Undefined(); } void TSubEnvironment::DeclareVariable(std::string key, TObject value) { + if (this->decls.count(key) == 0) + this->decls[key] = TEnvironmentDeclType::TEDT_VAR; + this->dict->SetValue(key, value); } void TSubEnvironment::SetVariable(std::string key, TObject value) { - if (this->dict->HasValue(key)) { + + if (this->dict->HasValue(key) || this->decls.count(key) > 0) { this->dict->SetValue(key, value); return; } @@ -102,10 +110,10 @@ void TSubEnvironment::SetVariable(std::string key, TObject value) { } } bool TSubEnvironment::HasVariable(std::string key) { - return this->dict->HasValue(key); + return this->dict->HasValue(key) || this->decls.count(key) > 0; } bool TSubEnvironment::HasVariableRecurse(std::string key) { - if (this->dict->HasValue(key)) + if (this->dict->HasValue(key) || this->decls.count(key) > 0) return true; return this->env->HasVariableRecurse(key); } @@ -159,19 +167,11 @@ TSubEnvironment *TEnvironment::GetSubEnvironment(GCList &gc) { } TSubEnvironment *TSubEnvironment::Create(GCList *gc, TEnvironment *env, TDictionary *dict) { - TSubEnvironment *senv = new TSubEnvironment(env, dict); - std::shared_ptr _gc = gc->GetGC(); - gc->Add(senv); - _gc->Watch(senv); - return senv; + return gc->Create(env, dict); } TSubEnvironment *TSubEnvironment::Create(GCList &gc, TEnvironment *env, TDictionary *dict) { - TSubEnvironment *senv = new TSubEnvironment(env, dict); - std::shared_ptr _gc = gc.GetGC(); - gc.Add(senv); - _gc->Watch(senv); - return senv; + return gc.Create(env, dict); } TEnvironment *TSubEnvironment::GetParentEnvironment() { return this->env; } TRootEnvironment *TSubEnvironment::GetRootEnvironment() { diff --git a/src/vm/bc/executemethod2.cpp b/src/vm/bc/executemethod2.cpp index 612997b..4f7ab9b 100644 --- a/src/vm/bc/executemethod2.cpp +++ b/src/vm/bc/executemethod2.cpp @@ -1490,12 +1490,12 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr gc, TObject instance, pattern, callable->ToRouteServerRequestHandler(gc)); } - } else if (key == "Trace") { + } else if (key == "Query") { std::string pattern; TCallable *callable; if (GetArgument(args, 0, pattern) && GetArgumentHeap(args, 1, callable)) { - routable->Trace( + routable->Query( pattern, callable->ToRouteServerRequestHandler(gc)); } diff --git a/src/vm/exception.cpp b/src/vm/exception.cpp index 48ad2bc..ab2a73d 100644 --- a/src/vm/exception.cpp +++ b/src/vm/exception.cpp @@ -58,13 +58,13 @@ void ThrowFatalError(std::exception &ex) { error.WriteLine(text); } - exit(1); + std::exit(1); } if (clrtexcept != nullptr) { error.WriteLine("CrossLang has encountered a fatal runtime exception"); error.WriteLine(); error.WriteLine(clrtexcept->what()); - exit(1); + std::exit(1); } if (compiler != nullptr) { error.WriteLine("CrossLang has encountered a compiler error"); @@ -81,13 +81,13 @@ void ThrowFatalError(std::exception &ex) { error.Write(":"); error.WriteLine((int64_t)li.offset); - exit(1); + std::exit(1); } error.WriteLine("CrossLang has encountered a fatal C++ exception"); error.WriteLine(); error.Write("what(): "); error.WriteLine(ex2->what()); - exit(1); + std::exit(1); } } // namespace Tesses::CrossLang \ No newline at end of file diff --git a/src/vm/filereader.cpp b/src/vm/filereader.cpp index 1d224e0..509634d 100644 --- a/src/vm/filereader.cpp +++ b/src/vm/filereader.cpp @@ -5,22 +5,8 @@ #include namespace Tesses::CrossLang { -TFile *TFile::Create(GCList &ls) { - TFile *f = new TFile(); - f->icon = -1; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(f); - _gc->Watch(f); - return f; -} -TFile *TFile::Create(GCList *ls) { - TFile *f = new TFile(); - f->icon = -1; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(f); - _gc->Watch(f); - return f; -} +TFile *TFile::Create(GCList &ls) { return ls.Create(); } +TFile *TFile::Create(GCList *ls) { return ls->Create(); } void TFileChunk::Mark() { if (this->marked) return; @@ -28,20 +14,8 @@ void TFileChunk::Mark() { this->file->Mark(); } -TFileChunk *TFileChunk::Create(GCList &ls) { - TFileChunk *chk = new TFileChunk(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(chk); - _gc->Watch(chk); - return chk; -} -TFileChunk *TFileChunk::Create(GCList *ls) { - TFileChunk *chk = new TFileChunk(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(chk); - _gc->Watch(chk); - return chk; -} +TFileChunk *TFileChunk::Create(GCList &ls) { return ls.Create(); } +TFileChunk *TFileChunk::Create(GCList *ls) { return ls->Create(); } void TFile::Mark() { if (this->marked) return; diff --git a/src/vm/gc.cpp b/src/vm/gc.cpp index 6767cf5..8fcdd05 100644 --- a/src/vm/gc.cpp +++ b/src/vm/gc.cpp @@ -11,7 +11,18 @@ using namespace Tesses::Framework::Threading; using namespace std::chrono; namespace Tesses::CrossLang { +#if defined(GEKKO) || defined(_EE) +struct PthreadCmp { + bool operator()(const pthread_t &a, const pthread_t &b) const { + return pthread_equal(a, b) != 0; + } +}; +static std::map current_funcs; +static Tesses::Framework::Threading::Mutex current_funcs_mtx; +#else +thread_local CallStackEntry *current_function; +#endif bool GC::IsRunning() { bool run = this->running; @@ -74,7 +85,14 @@ TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached) { TObject cb = th->callable->Call(ls, {}); gc->BarrierBegin(); th->returnValue = cb; + std::map mt; +#if defined(GEKKO) || defined(_EE) + current_funcs_mtx.Lock(); + current_funcs.erase(pthread_self()); + current_funcs_mtx.Unlock(); +#endif gc->BarrierEnd(); + th->hasReturned = true; }); while (!th->hasInit) @@ -93,50 +111,47 @@ void GC::Start() { return new Tesses::Framework::Threading::ThreadPool(threads); }, [](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; }); - this->mtx = new Mutex(); + this->running = true; this->thrd = new Thread([this]() -> void { - std::chrono::time_point last_frame, - this_frame; - - this_frame = system_clock::now(); - last_frame = this_frame; - while (this->IsRunning()) { - this_frame = system_clock::now(); - if ((this_frame - last_frame) > 10s) { + this->BarrierBegin(); + while (this->allocs < ALLOC_THRESHOLD) + this->cond.Wait( + &this->mtx); // your wrapper around pthread_cond_wait + this->allocs = 0; + std::vector to_delete; + this->Collect(to_delete); + this->BarrierEnd(); - last_frame = this_frame; - this->Collect(); - } - -#if defined(_WIN32) - Sleep(100); -#else - usleep(100000); -#endif + for (auto o : to_delete) + delete o; + } + { + std::vector to_delete; + this->BarrierBegin(); + this->Collect(to_delete); + this->BarrierEnd(); + + for (auto item : to_delete) + delete item; } - GC::Collect(); }); } bool GC::UsingNullThreads() { return false; } -void GC::BarrierBegin() { this->mtx->Lock(); } -void GC::BarrierEnd() { this->mtx->Unlock(); } +void GC::BarrierBegin() { this->mtx.Lock(); } +void GC::BarrierEnd() { this->mtx.Unlock(); } void GC::Watch(TObject obj) { if (std::holds_alternative(obj)) { auto _item = std::get(obj).obj; this->BarrierBegin(); - - for (auto item : this->objects) { - if (item == _item) { - this->BarrierEnd(); - return; - } - } - this->objects.push_back(_item); + this->objects.insert(_item); + auto nowAllocs = ++this->allocs; this->BarrierEnd(); + if (nowAllocs >= ALLOC_THRESHOLD) + this->cond.Signal(); } } void GC::Mark(TObject obj) { @@ -149,65 +164,36 @@ void GC::Unwatch(TObject obj) { if (std::holds_alternative(obj)) { auto _item = std::get(obj).obj; this->BarrierBegin(); - for (auto index = this->objects.begin(); - index != this->objects.end();) { - if (*index == _item) { - index = this->objects.erase(index); - continue; - } - index++; - } + this->objects.erase(_item); this->BarrierEnd(); } } -void GC::SetRoot(TObject obj) { - if (std::holds_alternative(obj)) { - auto _item = std::get(obj).obj; - this->BarrierBegin(); +void GC::SetRoot(GCList *_item) { + if (_item == nullptr) + return; + this->BarrierBegin(); - for (auto item : this->roots) { - if (item == _item) { - this->BarrierEnd(); - return; - } - } - this->roots.push_back(_item); - this->BarrierEnd(); - } + this->roots.insert(_item); + this->BarrierEnd(); } Tesses::Framework::Threading::ThreadPool *GC::GetPool() { return this->tpool->GetValue(); } -void GC::UnsetRoot(TObject obj) { - if (std::holds_alternative(obj)) { - auto _item = std::get(obj).obj; - this->BarrierBegin(); - for (auto index = this->roots.begin(); index != this->roots.end();) { - if (*index == _item) { - index = this->roots.erase(index); - continue; - } - index++; - } - this->BarrierEnd(); - } +void GC::UnsetRoot(GCList *_item) { + if (_item == nullptr) + return; + this->BarrierBegin(); + this->roots.erase(_item); + this->BarrierEnd(); } GC::~GC() { - GC::BarrierBegin(); - - this->roots.clear(); - GC::BarrierEnd(); - this->running = false; + this->cond.Signal(); this->thrd->Join(); delete this->thrd; - for (auto item : objects) - delete item; - delete this->tpool; - delete this->mtx; } void GC::RegisterEverythingCallback( @@ -218,23 +204,45 @@ void GC::RegisterEverything(TRootEnvironment *env) { for (auto item : this->register_everything) item(this->shared_from_this(), env); } -void GC::Collect() { - this->BarrierBegin(); + +CallStackEntry *GC::GetCurrentFunction() { +#if defined(GEKKO) || defined(_EE) + current_funcs_mtx.Lock(); + auto val = current_funcs[pthread_self()]; + current_funcs_mtx.Unlock(); + + return val; + +#else + return current_function; +#endif +} +void GC::SetCurrentFunction(CallStackEntry *cse) { +#if defined(GEKKO) || defined(_EE) + current_funcs_mtx.Lock(); + current_funcs[pthread_self()] = cse; + current_funcs_mtx.Unlock(); +#else + current_function = cse; +#endif +} + +void GC::Collect(std::vector &to_delete) { + for (auto item : this->objects) { item->marked = false; } for (auto item : this->roots) { item->Mark(); } - for (auto index = this->objects.begin(); index != this->objects.end(); - index++) { + for (auto index = this->objects.begin(); index != this->objects.end();) { THeapObject *o = *index; if (!o->marked) { - delete o; - this->objects.erase(index); - index--; + to_delete.push_back(o); + index = this->objects.erase(index); + } else { + ++index; } } - this->BarrierEnd(); } }; // namespace Tesses::CrossLang diff --git a/src/vm/gclist.cpp b/src/vm/gclist.cpp index b087cbd..a05adfe 100644 --- a/src/vm/gclist.cpp +++ b/src/vm/gclist.cpp @@ -8,7 +8,7 @@ GCList::GCList(std::shared_ptr gc) { gc->BarrierEnd(); } -std::shared_ptr GCList::GetGC() { return this->gc; } +std::shared_ptr GCList::GetGC() const { return this->gc; } void GCList::Remove(TObject obj) { if (std::holds_alternative(obj)) { auto _item = std::get(obj).obj; @@ -40,7 +40,6 @@ void GCList::Add(TObject obj) { } } void GCList::Mark() { - this->marked = true; for (auto item : this->items) { item->Mark(); } diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index f3ed6db..d8a251d 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -12,8 +12,6 @@ namespace Tesses::CrossLang { -thread_local CallStackEntry *current_function = nullptr; - TObject ExecuteFunction(GCList &ls, TCallable *callable, std::vector args) { return callable->Call(ls, args); @@ -2113,8 +2111,14 @@ bool InterperterThread::Throw(std::shared_ptr gc) { if (!std::holds_alternative(_res2)) { auto env = cse.back()->env; - if (!env->GetRootEnvironment()->HandleException(gc, env, _res2)) + if (!env->GetRootEnvironment()->HandleException(gc, env, _res2)) { + TNativeException *nex; + if (GetObjectHeap(_res2, nex)) { + nex->ThrowIt(); + } + throw VMByteCodeException(gc, _res2, cse.back()); + } } return false; } @@ -2223,6 +2227,7 @@ bool InterperterThread::JumpUndefined(std::shared_ptr gc) { bool InterperterThread::Jump(std::shared_ptr gc) { std::vector &cse = this->call_stack_entries; + auto stk = cse.back(); if (stk->ip + 4 <= stk->callable->closure->code.size()) { @@ -2409,23 +2414,39 @@ bool InterperterThread::TryCatch(std::shared_ptr gc) { if (GetObjectHeap(tryFn, tryC) && GetObjectHeap(catchFn, catchC)) { try { stk->Push(gc, tryC->Call(ls, {})); - } - catch (std::exception &ex) { - TDictionary *dict = TDictionary::Create(ls); - auto gc = ls.GetGC(); - auto myEx = dynamic_cast(&ex); - if (myEx != nullptr) { - stk->Push(gc, catchC->Call(ls, {myEx->exception})); - } else { - gc->BarrierBegin(); + } catch (std::bad_alloc &ex) { + std::cerr + << "CrossLang has failed to allocate, sorry for termination." + << std::endl; + std::exit(1); + } catch (const std::string &ex) { + stk->Push(gc, catchC->Call(ls, {ex})); + } catch (const char *ex) { - dict->SetValue("Type", "NativeException"); - dict->SetValue("Text", ex.what()); - gc->BarrierEnd(); + stk->Push(gc, + catchC->Call(ls, {std::string{ex != nullptr ? ex : ""}})); + } catch (std::runtime_error &ex) { - stk->Push(gc, catchC->Call(ls, {dict})); - } + stk->Push( + gc, catchC->Call(ls, {TNativeObject::Create( + ls, ex.what(), "RuntimeException")})); + } catch (VMException &ex) { + stk->Push( + gc, catchC->Call(ls, {TNativeObject::Create( + ls, ex.GetMessage(), "VMException")})); + } catch (VMByteCodeException &ex) { + stk->Push(gc, catchC->Call(ls, {ex.exception})); + } catch (std::exception &ex) { + stk->Push(gc, + catchC->Call( + ls, {TNativeObject::Create( + ls, ex.what(), std::current_exception())})); + } catch (...) { + stk->Push(gc, + catchC->Call(ls, {TNativeObject::Create( + ls, "", + std::current_exception())})); } } return false; @@ -2693,14 +2714,14 @@ void InterperterThread::Execute(std::shared_ptr gc) { std::vector &cse = this->call_stack_entries; #define VM_OPCODE_TABLE_INLINE -#include "vm_opcode_table.h" +#include "vm_opcode_table.def" #undef VM_OPCODE_TABLE_INLINE execute: if (!cse.empty()) { auto stk = cse.back(); - current_function = stk; + GC::SetCurrentFunction(stk); try { while (stk->ip < 0xFFFFFFFF && @@ -2721,7 +2742,7 @@ execute: cse[cse.size() - 2]->Push(gc, o); cse.erase(cse.end() - 1); - current_function = cse.back(); + GC::SetCurrentFunction(cse.back()); gc->BarrierEnd(); goto execute; } else { @@ -2729,8 +2750,13 @@ execute: } } - if (gc->UsingNullThreads()) - gc->Collect(); + if (gc->UsingNullThreads()) { + std::vector objs; + gc->Collect(objs); + for (auto &item : objs) { + delete item; + } + } } stk->mustReturn = false; @@ -2764,7 +2790,7 @@ execute: } if (cse.size() == 1) { - current_function = nullptr; + GC::SetCurrentFunction(nullptr); { gc->BarrierBegin(); @@ -2817,7 +2843,7 @@ execute: cse[cse.size() - 2]->Push(gc, o); cse.erase(cse.end() - 1); - current_function = cse.back(); + GC::SetCurrentFunction(cse.back()); gc->BarrierEnd(); for (auto item : callable) { @@ -2846,7 +2872,7 @@ void CallStackEntry::Push(std::shared_ptr gc, TObject o) { gc->BarrierEnd(); } TObject CallStackEntry::Resume(GCList &ls) { - auto cse = current_function; + auto cse = GC::GetCurrentFunction(); InterperterThread *thrd = InterperterThread::Create(ls); ls.GetGC()->BarrierBegin(); thrd->call_stack_entries.push_back(this); @@ -2855,7 +2881,7 @@ TObject CallStackEntry::Resume(GCList &ls) { thrd->Execute(ls.GetGC()); TObject v = thrd->call_stack_entries[0]->Pop(ls); - current_function = cse; + GC::SetCurrentFunction(cse); return v; } TObject CallStackEntry::Pop(GCList &gc) { @@ -2870,41 +2896,17 @@ TObject CallStackEntry::Pop(GCList &gc) { } InterperterThread *InterperterThread::Create(GCList &ls) { - InterperterThread *it = new InterperterThread(); - std::shared_ptr _gc = ls.GetGC(); - ls.Add(it); - _gc->Watch(it); - return it; + return ls.Create(); } InterperterThread *InterperterThread::Create(GCList *ls) { - InterperterThread *it = new InterperterThread(); - std::shared_ptr _gc = ls->GetGC(); - ls->Add(it); - _gc->Watch(it); - return it; + return ls->Create(); } CallStackEntry *CallStackEntry::Create(GCList &ls) { - CallStackEntry *cse = new CallStackEntry(); - cse->mustReturn = false; - cse->srcline = -1; - cse->srcfile = ""; - cse->thread = nullptr; - std::shared_ptr _gc = ls.GetGC(); - ls.Add(cse); - _gc->Watch(cse); - return cse; + return ls.Create(); } CallStackEntry *CallStackEntry::Create(GCList *ls) { - CallStackEntry *cse = new CallStackEntry(); - cse->mustReturn = false; - cse->srcline = -1; - cse->srcfile = ""; - cse->thread = nullptr; - std::shared_ptr _gc = ls->GetGC(); - ls->Add(cse); - _gc->Watch(cse); - return cse; + return ls->Create(); } void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure, std::vector args) { @@ -2963,6 +2965,18 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure, cse->env->DeclareVariable(trimStart(closure->closure->args[i]), args[i]); } + + for (; i < closure->closure->args.size(); i++) { + auto &a = closure->closure->args[i]; + if (a.size() > 1 && a[0] == '$') { + if (a[1] == '$') { + break; + } + cse->env->DeclareVariable(trimStart(a), Undefined()); + } else { + break; + } + } std::string back = closure->closure->args.empty() ? std::string() : closure->closure->args.back(); @@ -2979,7 +2993,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure, throw VMException("Too many arguments"); } - current_function = cse; + GC::SetCurrentFunction(cse); this->call_stack_entries.push_back(cse); ls.GetGC()->BarrierEnd(); diff --git a/src/vm/vm_opcode_table.h b/src/vm/vm_opcode_table.def similarity index 100% rename from src/vm/vm_opcode_table.h rename to src/vm/vm_opcode_table.def