#include "CrossLang.hpp" namespace Tesses::CrossLang { TDynamicDictionary::TDynamicDictionary(TCallable *callable) : cb(callable) {} TDynamicDictionary *TDynamicDictionary::Create(GCList &ls, TCallable *callable) { return ls.Create(callable); } TDynamicDictionary *TDynamicDictionary::Create(GCList *ls, TCallable *callable) { return ls->Create(callable); } 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 this->cb->Call(ls, {dict}); } TObject 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(); return this->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 this->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, this->cb->Call(ls, {dict})); } bool TDictionary::MethodExists(GCList &ls, std::string method) { ls.GetGC()->BarrierBegin(); auto r = this->GetValue(method); TCallable *callable; bool res = GetObjectHeap(r, callable); ls.GetGC()->BarrierEnd(); return res; } 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 = this->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(); auto res = this->GetValue(key); ls.GetGC()->BarrierEnd(); TCallable *callable; if (GetObjectHeap(res, callable)) { auto closure = dynamic_cast(callable); if (closure != nullptr && !closure->closure->args.empty() && closure->closure->args.front() == "this") { std::vector args2; args2.push_back(this); args2.insert(args2.end(), args.begin(), args.end()); return closure->Call(ls, args2); } else { return callable->Call(ls, args); } } return Undefined(); } TObject TDictionary::CallMethodWithFatalError(GCList &ls, std::string key, std::vector args) { ls.GetGC()->BarrierBegin(); auto res = this->GetValue(key); ls.GetGC()->BarrierEnd(); TCallable *callable; if (GetObjectHeap(res, callable)) { auto closure = dynamic_cast(callable); if (closure != nullptr && !closure->closure->args.empty() && closure->closure->args.front() == "this") { std::vector args2; args2.push_back(this); args2.insert(args2.end(), args.begin(), args.end()); return closure->CallWithFatalError(ls, args2); } else { return callable->CallWithFatalError(ls, args); } } return Undefined(); } void TDictionary::DeclareFunction( std::shared_ptr gc, std::string key, std::string documentation, std::vector argNames, std::function args)> cb) { gc->BarrierBegin(); GCList ls(gc); this->SetValue(key, TExternalMethod::Create(ls, documentation, argNames, cb)); gc->BarrierEnd(); } void TDictionary::DeclareFunction( std::shared_ptr gc, std::string key, std::string documentation, std::vector argNames, std::function args)> cb, std::function destroy) { gc->BarrierBegin(); GCList ls(gc); this->SetValue( key, TExternalMethod::Create(ls, documentation, argNames, cb, destroy)); gc->BarrierEnd(); } TObject TDictionary::GetValue(std::string key) { if (this->items.empty()) return Undefined(); auto item = this->items.find(key); if (item != this->items.end()) return item->second; return Undefined(); } void TDictionary::SetValue(std::string key, TObject value) { if (std::holds_alternative(value)) { if (this->items.count(key) > 0) this->items.erase(key); } else { this->items[key] = value; } } bool TDictionary::HasValue(std::string key) { return this->items.count(key) > 0; } void TDictionary::Mark() { if (this->marked) return; this->marked = true; for (auto item : this->items) { GC::Mark(item.second); } } TDictionary *TDictionary::Create(GCList *gc) { return gc->Create(); } TDictionary *TDictionary::Create(GCList &gc) { return gc.Create(); } }; // namespace Tesses::CrossLang