From 5c8dc0fd9b869ef59cc8f255653376da72c7ae65 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Tue, 14 Jan 2025 22:03:27 -0600 Subject: [PATCH] Fix docker --- .onedev-buildspec.yml | 21 +++-- Dockerfile.run | 2 + include/CrossLang.hpp | 53 +++++++++++ src/runtime_methods/dictionary.cpp | 112 ++++++++++++++++++---- src/runtime_methods/std.cpp | 125 +++++++++++++++++-------- src/types/dictionary.cpp | 90 ++++++++++++++++++ src/types/ittr.cpp | 52 +++++++++++ src/types/list.cpp | 67 ++++++++++++++ src/vm/vm.cpp | 143 ++++++++++++++++++++++++++++- 9 files changed, 600 insertions(+), 65 deletions(-) create mode 100644 Dockerfile.run diff --git a/.onedev-buildspec.yml b/.onedev-buildspec.yml index 3b78693..272bfb1 100644 --- a/.onedev-buildspec.yml +++ b/.onedev-buildspec.yml @@ -8,8 +8,22 @@ jobs: withLfs: true withSubmodules: false condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL + - !CommandStep + name: Execute build + runInContainer: true + image: onedev.site.tesses.net/tesses-framework/tesses-framework:latest + interpreter: !DefaultInterpreter + commands: | + mkdir build + cd build + cmake -S .. -B . + make -j12 + make install DESTDIR=out + useTTY: true + condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL - !BuildImageStep name: Build Docker Image + dockerfile: Dockerfile.run output: !RegistryOutput tags: onedev.site.tesses.net/crosslang/crosslang:latest registryLogins: @@ -20,14 +34,7 @@ jobs: condition: ALL_PREVIOUS_STEPS_WERE_SUCCESSFUL triggers: - !BranchUpdateTrigger - projects: crosslang - - !DependencyFinishedTrigger projects: tesses-framework - projectDependencies: - - projectPath: tesses-framework - buildProvider: !LastFinishedBuild - jobName: Build for x86_64 - artifacts: -** retryCondition: never maxRetries: 3 retryDelay: 30 diff --git a/Dockerfile.run b/Dockerfile.run new file mode 100644 index 0000000..ad936a9 --- /dev/null +++ b/Dockerfile.run @@ -0,0 +1,2 @@ +FROM onedev.site.tesses.net/tesses-framework/tesses-framework:latest +COPY build/out / \ No newline at end of file diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index 556a975..6e24e66 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -646,6 +646,7 @@ class Parser { } }; + //this is a dummy type with class MethodInvoker { }; @@ -800,6 +801,8 @@ class GC { virtual TObject Call(GCList& ls,std::vector args)=0; }; + + class TEnvironment : public THeapObject { public: @@ -993,6 +996,17 @@ class GC { TObject GetCurrent(GCList& ls); void Mark(); }; + class TDynamicListEnumerator : public TEnumerator + { + int64_t index; + TDynamicList* ls; + public: + static TDynamicListEnumerator* Create(GCList& ls, TDynamicList* list); + static TDynamicListEnumerator* Create(GCList* ls, TDynamicList* list); + bool MoveNext(GC* ls); + TObject GetCurrent(GCList& ls); + void Mark(); + }; class TVFSPathEnumerator : public TEnumerator { Tesses::Framework::Filesystem::VFSPathEnumerator enumerator; @@ -1126,7 +1140,46 @@ class GC { TObject Call(GCList& ls,std::vector args); void Mark(); }; + class TDynamicList : public THeapObject + { + public: + TCallable* cb; + static TDynamicList* Create(GCList& ls,TCallable* callable); + static TDynamicList* Create(GCList* ls,TCallable* callable); + void Mark(); + + int64_t Count(GCList& ls); + + TObject GetAt(GCList& ls, int64_t index); + + void SetAt(GCList& ls, int64_t index, TObject val); + + ~TDynamicList(); + }; + class TDynamicDictionary : public THeapObject + { + public: + TCallable* cb; + + static TDynamicDictionary* Create(GCList& ls,TCallable* callable); + static TDynamicDictionary* Create(GCList* ls,TCallable* callable); + + void Mark(); + + TObject GetField(GCList& ls, std::string key); + + void SetField(GCList& ls, std::string key, TObject value); + + TObject CallMethod(GCList& ls, std::string name, std::vector args); + + bool MethodExists(GCList& ls, std::string name); + + TEnumerator* GetEnumerator(GCList& ls); + + + ~TDynamicDictionary(); + }; class CallStackEntry : public THeapObject diff --git a/src/runtime_methods/dictionary.cpp b/src/runtime_methods/dictionary.cpp index a16947e..6e564db 100644 --- a/src/runtime_methods/dictionary.cpp +++ b/src/runtime_methods/dictionary.cpp @@ -2,36 +2,112 @@ namespace Tesses::CrossLang { - TObject Dictionary_Items(GCList& ls, std::vector args) { TDictionary* dict; - - if(args.size() == 1 && std::holds_alternative(args[0])) + TDynamicDictionary* dynDict; + if(GetArgumentHeap(args,0,dynDict)) { - auto item = dynamic_cast(std::get(args[0]).obj); - if(item != nullptr) - { - TDictionary* enumerableItem = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); + TDictionary* enumerableItem = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); - auto fn = TExternalMethod::Create(ls,"Get Enumerator for Dictionary",{"dict"},[item](GCList& ls2, std::vector args)->TObject { - return TDictionaryEnumerator::Create(ls2,item); - }); - fn->watch.push_back(item); + auto fn = TExternalMethod::Create(ls,"Get Enumerator for Dictionary",{"dict"},[dynDict](GCList& ls2, std::vector args)->TObject { + return dynDict->GetEnumerator(ls2); + }); + fn->watch.push_back(dynDict); - enumerableItem->SetValue("GetEnumerator", fn); + enumerableItem->SetValue("GetEnumerator", fn); - ls.GetGC()->BarrierEnd(); + ls.GetGC()->BarrierEnd(); - return enumerableItem; - } + return enumerableItem; + + } + if(GetArgumentHeap(args,0,dict)) + { + TDictionary* enumerableItem = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + + auto fn = TExternalMethod::Create(ls,"Get Enumerator for Dictionary",{"dict"},[dict](GCList& ls2, std::vector args)->TObject { + return TDictionaryEnumerator::Create(ls2,dict); + }); + fn->watch.push_back(dict); + + enumerableItem->SetValue("GetEnumerator", fn); + + ls.GetGC()->BarrierEnd(); + + return enumerableItem; + } return Undefined(); } - + TObject Dictionary_GetField(GCList& ls, std::vector args) + { + TDictionary* dict; + TDynamicDictionary* dynDict; + std::string key; + if(GetArgument(args,1,key)) + { + if(GetArgumentHeap(args,0,dict)) + { + ls.GetGC()->BarrierBegin(); + auto res = dict->GetValue(key); + ls.GetGC()->BarrierEnd(); + return res; + } + else if(GetArgumentHeap(args,0,dynDict)) + { + return dynDict->GetField(ls,key); + } + } + return nullptr; + } + TObject Dictionary_SetField(GCList& ls, std::vector args) + { + TDictionary* dict; + TDynamicDictionary* dynDict; + std::string key; + if(args.size() == 3 && GetArgument(args,1,key)) + { + if(GetArgumentHeap(args,0,dict)) + { + ls.GetGC()->BarrierBegin(); + dict->SetValue(key,args[2]); + ls.GetGC()->BarrierEnd(); + } + else if(GetArgumentHeap(args,0,dynDict)) + { + dynDict->SetField(ls,key,args[2]); + } + } + return nullptr; + } + + + TObject Dictionary_GetField(GCList& ls, std::vector args) + { + TDictionary* dict; + TDynamicDictionary* dynDict; + std::string key; + if(GetArgument(args,1,key)) + { + if(GetArgumentHeap(args,0,dict)) + { + ls.GetGC()->BarrierBegin(); + auto res = dict->GetValue(key); + ls.GetGC()->BarrierEnd(); + return res; + } + else if(GetArgumentHeap(args,0,dynDict)) + { + return dynDict->GetField(ls,key); + } + } + return nullptr; + } void TStd::RegisterDictionary(GC* gc,TRootEnvironment* env) { @@ -43,6 +119,8 @@ namespace Tesses::CrossLang gc->BarrierBegin(); dict->DeclareFunction(gc, "Items","Get Dictionary Item Enumerable, for the each(item : Dictionary.Items(myDict)){item.Key; item.Value;}",{"dictionary"},Dictionary_Items); + dict->DeclareFunction(gc, "SetField","Set a field in dictionary",{"dict","key","value"},Dictionary_SetField); + dict->DeclareFunction(gc, "GetField","Get a field in dictionary",{"dict","key"},Dictionary_GetField); env->DeclareVariable("Dictionary", dict); gc->BarrierEnd(); diff --git a/src/runtime_methods/std.cpp b/src/runtime_methods/std.cpp index 9ee56c7..518666d 100644 --- a/src/runtime_methods/std.cpp +++ b/src/runtime_methods/std.cpp @@ -2,7 +2,69 @@ namespace Tesses::CrossLang { - TObject TypeOf(GCList& ls, std::vector args) + static TObject TypeIsDefined(GCList& ls,std::vector args) + { + if(args.empty()) return nullptr; + return (!std::holds_alternative(args[0]) && !std::holds_alternative(args[0])); + } + static TObject TypeIsHeap(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + return std::holds_alternative(args[0]); + } + static TObject TypeIsNumber(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + return std::holds_alternative(args[0]) || std::holds_alternative(args[0]); + } + static TObject TypeIsLong(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + return std::holds_alternative(args[0]); + } + static TObject TypeIsDouble(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + return std::holds_alternative(args[0]); + } + static TObject TypeIsString(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + return std::holds_alternative(args[0]); + } + static TObject TypeIsCallable(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + TCallable* call; + return GetArgumentHeap(args,0,call); + } + static TObject TypeIsDictionary(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + TDictionary* dict; + TDynamicDictionary* dynDict; + return GetArgumentHeap(args,0,dict) || GetArgumentHeap(args,0,dynDict); + } + static TObject TypeIsList(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + TList* list; + TDynamicList* dynList; + return GetArgumentHeap(args,0,list) || GetArgumentHeap(args,0, dynList); + } + static TObject TypeIsStream(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + TStreamHeapObject* strm; + return GetArgumentHeap(args,0,strm); + } + static TObject TypeIsVFS(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + TVFSHeapObject* vfs; + return GetArgumentHeap(args,0,vfs); + } + static TObject TypeOf(GCList& ls, std::vector args) { if(args.size() < 1) return "Undefined"; if(std::holds_alternative(args[0])) return "Undefined"; @@ -18,7 +80,10 @@ namespace Tesses::CrossLang { auto obj = std::get(args[0]).obj; auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto list = dynamic_cast(obj); + auto dynList = dynamic_cast(obj); auto argWrapper = dynamic_cast(obj); auto closure = dynamic_cast(obj); auto externalMethod = dynamic_cast(obj); @@ -26,6 +91,8 @@ namespace Tesses::CrossLang auto native = dynamic_cast(obj); auto vfs = dynamic_cast(obj); auto strm = dynamic_cast(obj); + if(dynDict != nullptr) return "DynamicDictionary"; + if(dynList != nullptr) return "DynamicList"; if(strm != nullptr) { auto netStrm = dynamic_cast(strm->stream); @@ -141,41 +208,6 @@ namespace Tesses::CrossLang - static TObject Throw(GCList& ls, std::vector args) - { - if(!args.empty()) - { - VMByteCodeException bce(ls.GetGC(),args[0]); - throw bce; - } - return nullptr; - } - static TObject Try(GCList& ls, std::vector args) - { - TCallable* tryPart; - TCallable* catchPart; - if(GetArgumentHeap(args,0,tryPart) && GetArgumentHeap(args,1,catchPart)) - { - try { - tryPart->Call(ls,{}); - } - catch(VMByteCodeException& ex) - { - catchPart->Call(ls,{ex.exception}); - } - catch(std::exception& ex) - { - TDictionary* dict = TDictionary::Create(ls); - auto gc = ls.GetGC(); - gc->BarrierBegin(); - dict->SetValue("Type","NativeException"); - dict->SetValue("Text",ex.what()); - gc->BarrierEnd(); - catchPart->Call(ls,{dict}); - } - } - return nullptr; - } EnvironmentPermissions::EnvironmentPermissions() { this->canRegisterConsole=false; @@ -203,11 +235,22 @@ namespace Tesses::CrossLang env->permissions.canRegisterRoot=true; env->DeclareFunction(gc, "ParseLong","Parse Long from String",{"arg","$base"},ParseLong); - env->DeclareFunction(gc, "ParseDouble","Parse Double from String",{"arg"},ParseDouble); env->DeclareFunction(gc, "TypeOf","Get type of object",{"object"},TypeOf); - env->DeclareFunction(gc, "Throw", "Throw an exception",{"object"},Throw); - env->DeclareFunction(gc, "Try", "Handle exceptions",{"callbackToTry","callbackToCatch"},Try); + env->DeclareFunction(gc, "TypeIsDefined","Get whether object is not null or undefined",{"object"},TypeIsDefined); + env->DeclareFunction(gc, "TypeIsHeap","Get whether object is susceptible to garbage collection",{"object"},TypeIsHeap); + env->DeclareFunction(gc, "TypeIsNumber","Get whether object is a number",{"object"},TypeIsNumber); + env->DeclareFunction(gc, "TypeIsLong","Get whether object is a long (not a double)",{"object"},TypeIsLong); + env->DeclareFunction(gc, "TypeIsDouble","Get whether object is a double (not a long)",{"object"},TypeIsDouble); + env->DeclareFunction(gc, "TypeIsString","Get whether object is a string",{"object"},TypeIsString); + env->DeclareFunction(gc, "TypeIsCallable","Get whether object is callable",{"object"},TypeIsCallable); + env->DeclareFunction(gc, "TypeIsDictionary","Get whether object is a dictionary or dynamic dictionary",{"object"},TypeIsDictionary); + env->DeclareFunction(gc, "TypeIsList","Get whether object is a list or dynamic list",{"object"},TypeIsList); + env->DeclareFunction(gc, "TypeIsStream","Get whether object is a stream",{"object"},TypeIsStream); + env->DeclareFunction(gc, "TypeIsVFS","Get whether object is a virtual filesystem",{"object"},TypeIsVFS); + + + env->DeclareFunction(gc, "Thread","Create thread",{"callback"},[](GCList& ls, std::vector args)-> TObject { if(args.size() == 1 && std::holds_alternative(args[0])) @@ -221,7 +264,9 @@ namespace Tesses::CrossLang return Undefined(); }); env->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray); - + gc->BarrierBegin(); + env->DeclareVariable("InvokeMethod",MethodInvoker()); + gc->BarrierEnd(); } void TStd::RegisterStd(GC* gc, TRootEnvironment* env) { diff --git a/src/types/dictionary.cpp b/src/types/dictionary.cpp index 1ea7a53..e4c599d 100644 --- a/src/types/dictionary.cpp +++ b/src/types/dictionary.cpp @@ -1,6 +1,96 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { + TDynamicDictionary* TDynamicDictionary::Create(GCList& ls,TCallable* callable) + { + + TDynamicDictionary* dict=new TDynamicDictionary(); + dict->cb = callable; + GC* _gc = ls.GetGC(); + ls.Add(dict); + _gc->Watch(dict); + return dict; + } + TDynamicDictionary* TDynamicDictionary::Create(GCList* ls,TCallable* callable) + { + TDynamicDictionary* dict=new TDynamicDictionary(); + dict->cb = callable; + GC* _gc = ls->GetGC(); + ls->Add(dict); + _gc->Watch(dict); + return dict; + } + + void TDynamicDictionary::Mark() + { + if(this->marked) return; + this->marked=true; + this->cb->Mark(); + } + + TObject TDynamicDictionary::GetField(GCList& ls, std::string key) + { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "GetField"); + dict->SetValue("Key", key); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls,{dict}); + } + + void TDynamicDictionary::SetField(GCList& ls, std::string key, TObject value) + { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "SetField"); + dict->SetValue("Key", key); + dict->SetValue("Value", value); + ls.GetGC()->BarrierEnd(); + cb->Call(ls,{dict}); + } + + TObject TDynamicDictionary::CallMethod(GCList& ls, std::string name, std::vector args) + { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "CallMethod"); + dict->SetValue("Name", name); + auto argVal = TList::Create(ls); + argVal->items = args; + dict->SetValue("Arguments", argVal); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls,{dict}); + } + + TEnumerator* TDynamicDictionary::GetEnumerator(GCList& ls) + { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "GetEnumerator"); + + ls.GetGC()->BarrierEnd(); + + return TEnumerator::CreateFromObject(ls,cb->Call(ls,{dict})); + } + bool TDynamicDictionary::MethodExists(GCList& ls,std::string name) + { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "MethodExists"); + dict->SetValue("Name", name); + + ls.GetGC()->BarrierEnd(); + + auto res = cb->Call(ls,{dict}); + bool r2; + if(GetObject(res,r2)) return r2; + return false; + } + + TDynamicDictionary::~TDynamicDictionary() + { + + } TObject TDictionary::CallMethod(GCList& ls, std::string key, std::vector args) { ls.GetGC()->BarrierBegin(); diff --git a/src/types/ittr.cpp b/src/types/ittr.cpp index 204ae1d..4efb8f0 100644 --- a/src/types/ittr.cpp +++ b/src/types/ittr.cpp @@ -56,6 +56,8 @@ namespace Tesses::CrossLang { std::string str; TList* mls; + TDynamicList* dynList; + TDynamicDictionary* dynDict; TDictionary* dict; TEnumerator* enumerator; if(GetObject(obj,str)) @@ -66,6 +68,10 @@ namespace Tesses::CrossLang { return TListEnumerator::Create(ls,mls); } + else if(GetObjectHeap(obj,dynList)) + { + return TDynamicListEnumerator::Create(ls,dynList); + } else if(GetObjectHeap(obj,dict)) { auto res=dict->CallMethod(ls,"GetEnumerator",{}); @@ -208,6 +214,52 @@ namespace Tesses::CrossLang this->ls->Mark(); } + TDynamicListEnumerator* TDynamicListEnumerator::Create(GCList& ls, TDynamicList* list) + { + TDynamicListEnumerator* liste=new TDynamicListEnumerator(); + liste->ls = list; + liste->index = -1; + GC* _gc = ls.GetGC(); + ls.Add(liste); + _gc->Watch(liste); + return liste; + } + TDynamicListEnumerator* TDynamicListEnumerator::Create(GCList* ls, TDynamicList* list) + { + TDynamicListEnumerator* liste=new TDynamicListEnumerator(); + liste->ls = list; + liste->index = -1; + GC* _gc = ls->GetGC(); + ls->Add(liste); + _gc->Watch(liste); + return liste; + } + bool TDynamicListEnumerator::MoveNext(GC* ls) + { + this->index++; + GCList ls2(ls); + return this->index >= 0 && this->index < this->ls->Count(ls2); + } + TObject TDynamicListEnumerator::GetCurrent(GCList& ls) + { + + if(this->index < -1) return nullptr; + auto r = this->ls->Count(ls); + if(r == 0) return nullptr; + if(this->index >= r) return nullptr; + ls.GetGC()->BarrierBegin(); + TObject o = this->ls->GetAt(ls,index); + ls.GetGC()->BarrierEnd(); + return o; + } + void TDynamicListEnumerator::Mark() + { + if(this->marked) return; + this->marked = true; + this->ls->Mark(); + } + + TStringEnumerator* TStringEnumerator::Create(GCList& ls,std::string str) { TStringEnumerator* stre=new TStringEnumerator(); diff --git a/src/types/list.cpp b/src/types/list.cpp index e6430cc..1aa6d9c 100644 --- a/src/types/list.cpp +++ b/src/types/list.cpp @@ -1,5 +1,72 @@ #include "CrossLang.hpp" namespace Tesses::CrossLang { + TDynamicList* TDynamicList::Create(GCList& ls,TCallable* callable) + { + TDynamicList* list=new TDynamicList(); + list->cb = callable; + GC* _gc = ls.GetGC(); + ls.Add(list); + _gc->Watch(list); + return list; + } + TDynamicList* TDynamicList::Create(GCList* ls,TCallable* callable) + { + TDynamicList* list=new TDynamicList(); + list->cb = callable; + GC* _gc = ls->GetGC(); + ls->Add(list); + _gc->Watch(list); + return list; + } + + void TDynamicList::Mark() + { + if(this->marked) return; + this->marked=true; + this->cb->Mark(); + } + + int64_t TDynamicList::Count(GCList& ls) + { + + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "Count"); + ls.GetGC()->BarrierEnd(); + auto res = cb->Call(ls,{dict}); + int64_t n; + if(GetObject(res,n)) return n; + return 0; + } + + TObject TDynamicList::GetAt(GCList& ls, int64_t index) + { + + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "GetAt"); + dict->SetValue("Index",index); + ls.GetGC()->BarrierEnd(); + return cb->Call(ls,{dict}); + } + + void TDynamicList::SetAt(GCList& ls, int64_t index, TObject val) + { + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + dict->SetValue("Type", "SetAt"); + dict->SetValue("Index",index); + dict->SetValue("Value",val); + ls.GetGC()->BarrierEnd(); + cb->Call(ls,{dict}); + } + + TDynamicList::~TDynamicList() + { + + } + + TByteArray* TByteArray::Create(GCList& ls) { TByteArray* arr=new TByteArray(); diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 3e154e7..b995c3e 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -191,6 +191,7 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -198,6 +199,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator-",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -238,6 +244,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -245,6 +253,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator*",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -306,6 +319,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -313,6 +328,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator/",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -354,6 +374,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -361,6 +383,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator%",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -393,6 +420,7 @@ namespace Tesses::CrossLang { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -400,6 +428,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeOne(ls,negfn,left); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator-",{})); + return false; + } else { cse.back()->Push(gc,nullptr); @@ -442,6 +475,7 @@ namespace Tesses::CrossLang { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -449,6 +483,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeOne(ls,negfn,left); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator!",{})); + return false; + } else { cse.back()->Push(gc, !ToBool(left)); @@ -479,6 +518,7 @@ namespace Tesses::CrossLang { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -486,6 +526,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeOne(ls,negfn,left); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator~",{})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -528,6 +573,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -535,6 +582,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator<",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -577,6 +629,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -584,6 +638,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator>",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -626,6 +685,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -633,6 +694,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator<=",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -675,6 +741,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -682,6 +750,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator>=",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -748,6 +821,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -757,7 +832,16 @@ namespace Tesses::CrossLang { return InvokeTwo(ls,fn,left,right); } - + + else if(dynDict != nullptr) + { + auto res = dynDict->CallMethod(ls,"operator==",{right}); + if(!std::holds_alternative(res) && std::holds_alternative(res)) + { + cse.back()->Push(gc,res); + return false; + } + } if(std::holds_alternative(right)) { cse.back()->Push(gc,obj == std::get(right).obj); @@ -824,6 +908,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -833,6 +919,16 @@ namespace Tesses::CrossLang { return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + + auto res = dynDict->CallMethod(ls,"operator!=",{right}); + if(!std::holds_alternative(res) && std::holds_alternative(res)) + { + cse.back()->Push(gc,res); + return false; + } + } if(std::holds_alternative(right)) { cse.back()->Push(gc,obj != std::get(right).obj); @@ -866,6 +962,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -873,6 +971,12 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator<<",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -901,6 +1005,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -908,6 +1014,12 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator>>",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -936,6 +1048,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -943,6 +1057,12 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator|",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -971,6 +1091,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -978,6 +1100,12 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator^",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -1006,6 +1134,8 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -1013,6 +1143,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator&",{right})); + return false; + } else { cse.back()->Push(gc,Undefined()); @@ -1130,6 +1265,7 @@ namespace Tesses::CrossLang { { auto obj = std::get(left).obj; auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); if(dict != nullptr) { gc->BarrierBegin(); @@ -1137,6 +1273,11 @@ namespace Tesses::CrossLang { gc->BarrierEnd(); return InvokeTwo(ls,fn,left,right); } + else if(dynDict != nullptr) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"operator+",{right})); + return false; + } else { cse.back()->Push(gc, Undefined());