From 5be9d96b541a57ca545413cf35432fbe8cf0d997 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Mon, 16 Feb 2026 17:42:01 -0600 Subject: [PATCH] Add uuid support --- .clangd | 2 - .vscode/settings.json | 6 +- CMakeLists.txt | 13 +- Packaging/Linux/PKGBUILD | 2 +- Packaging/Linux/version.sh | 2 +- changelog.md | 7 + include/CrossLang.hpp | 5 +- src/runtime_methods/env.cpp | 6 + src/runtime_methods/std.cpp | 52 + src/runtime_methods/uuid.cpp | 40 + src/vm/bc/add.cpp | 164 ++ src/vm/bc/equals.cpp | 236 ++ src/vm/bc/executemethod2.cpp | 3715 ++++++++++++++++++++++++++ src/vm/bc/getfield.cpp | 769 ++++++ src/vm/bc/invokemethod.cpp | 54 + src/vm/bc/invoketwo.cpp | 47 + src/vm/bc/setfield.cpp | 278 ++ src/vm/bc/sub.cpp | 121 + src/vm/bc/tobool.cpp | 106 + src/vm/bc/tostring.cpp | 133 + src/vm/vm.cpp | 4854 +--------------------------------- 21 files changed, 5774 insertions(+), 4838 deletions(-) delete mode 100644 .clangd create mode 100644 changelog.md create mode 100644 src/runtime_methods/uuid.cpp create mode 100644 src/vm/bc/add.cpp create mode 100644 src/vm/bc/equals.cpp create mode 100644 src/vm/bc/executemethod2.cpp create mode 100644 src/vm/bc/getfield.cpp create mode 100644 src/vm/bc/invokemethod.cpp create mode 100644 src/vm/bc/invoketwo.cpp create mode 100644 src/vm/bc/setfield.cpp create mode 100644 src/vm/bc/sub.cpp create mode 100644 src/vm/bc/tobool.cpp create mode 100644 src/vm/bc/tostring.cpp diff --git a/.clangd b/.clangd deleted file mode 100644 index cd3da03..0000000 --- a/.clangd +++ /dev/null @@ -1,2 +0,0 @@ -CompileFlags: # Tweak the parse settings, example directory given to show format - Add: ["-Iinclude","-std=gnu++17"] diff --git a/.vscode/settings.json b/.vscode/settings.json index d2113a3..471378b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -84,7 +84,11 @@ "stack": "cpp", "stdfloat": "cpp" }, + "clangd.fallbackFlags": [ - "-Iinclude" + "-I${workspaceFolder}/include", + "-I/home/mike/tmp-crosslang/usr/local/include/" ] + + } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c13e32..550d3c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) set(CROSSLANG_MAJOR_VERSION 0) set(CROSSLANG_MINOR_VERSION 0) -set(CROSSLANG_PATCH_VERSION 1) +set(CROSSLANG_PATCH_VERSION 2) project(TessesCrossLang VERSION ${CROSSLANG_MAJOR_VERSION}.${CROSSLANG_MINOR_VERSION}.${CROSSLANG_PATCH_VERSION}) @@ -141,6 +141,16 @@ target_include_directories(${CROSSLANG_TARGET_NAME} endfunction() list(APPEND CROSSLANG_SOURCE +src/vm/bc/add.cpp +src/vm/bc/sub.cpp +src/vm/bc/getfield.cpp +src/vm/bc/setfield.cpp +src/vm/bc/tostring.cpp +src/vm/bc/equals.cpp +src/vm/bc/invokemethod.cpp +src/vm/bc/executemethod2.cpp +src/vm/bc/invoketwo.cpp +src/vm/bc/tobool.cpp src/assembler/asm.cpp src/assembler/disasm.cpp src/assembler/merge.cpp @@ -148,6 +158,7 @@ src/compiler/codegen.cpp src/compiler/lexer.cpp src/compiler/parser.cpp src/compiler/ast.cpp +src/runtime_methods/uuid.cpp src/runtime_methods/class.cpp src/runtime_methods/console.cpp src/runtime_methods/io.cpp diff --git a/Packaging/Linux/PKGBUILD b/Packaging/Linux/PKGBUILD index 4518870..5a3c798 100644 --- a/Packaging/Linux/PKGBUILD +++ b/Packaging/Linux/PKGBUILD @@ -1,6 +1,6 @@ # Maintainer: Mike Nolan pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn' -pkgver=0.0.1 +pkgver=0.0.2 pkgrel=1 pkgdesc="" arch=('x86_64' 'powerpc') diff --git a/Packaging/Linux/version.sh b/Packaging/Linux/version.sh index 8c1e404..b58f59d 100644 --- a/Packaging/Linux/version.sh +++ b/Packaging/Linux/version.sh @@ -1,2 +1,2 @@ -export DEB_VERSION=0.0.1 \ No newline at end of file +export DEB_VERSION=0.0.2 \ No newline at end of file diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..ebd8e31 --- /dev/null +++ b/changelog.md @@ -0,0 +1,7 @@ +# Changelog + +## 0.0.2 +Add uuids and bytestreams + +## 0.0.1 +Start versioning \ No newline at end of file diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index f71684c..6029cb3 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -20,6 +20,7 @@ #include #include "CrossLangVersion.h" +#include "TessesFramework/Streams/ByteReader.hpp" #define CROSSLANG_BYTECODE_MAJOR 1 #define CROSSLANG_BYTECODE_MINOR 0 @@ -1404,7 +1405,7 @@ class TContinue { * */ -using TObject = std::variant,std::shared_ptr,TBreak,TContinue,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr>; +using TObject = std::variant,std::shared_ptr,TBreak,TContinue,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr,std::shared_ptr, Tesses::Framework::Uuid>; class TRootEnvironment; class GC; @@ -1841,6 +1842,7 @@ class GC { class TStd { private: static void RegisterHelpers(GC* gc, TRootEnvironment* env); + static void RegisterUuid(GC* gc, TRootEnvironment* env); public: static void RegisterStd(GC* gc, TRootEnvironment* env); static void RegisterConsole(GC* gc,TRootEnvironment* env); @@ -1857,6 +1859,7 @@ class GC { static void RegisterEnv(GC* gc, TRootEnvironment* env); static void RegisterProcess(GC* gc, TRootEnvironment* env); static void RegisterClass(GC* gc, TRootEnvironment* env); + }; class TSubEnvironment : public TEnvironment diff --git a/src/runtime_methods/env.cpp b/src/runtime_methods/env.cpp index 72d4045..9ac4bec 100644 --- a/src/runtime_methods/env.cpp +++ b/src/runtime_methods/env.cpp @@ -1,4 +1,5 @@ #include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" #if defined(_WIN32) #include @@ -131,6 +132,10 @@ namespace Tesses::CrossLang ls.GetGC()->BarrierEnd(); return list; } + static TObject Env_getLittleEndian(GCList& ls, std::vector args) + { + return Tesses::Framework::Serialization::BitConverter::IsLittleEndian(); + } void TStd::RegisterEnv(GC* gc, TRootEnvironment* env) { @@ -155,6 +160,7 @@ namespace Tesses::CrossLang dict->DeclareFunction(gc,"getUser","Get user folder",{},Env_getUser); dict->DeclareFunction(gc,"getPlatform","Get platform name",{},Env_getPlatform); dict->DeclareFunction(gc,"GetRealExecutablePath", "Get the absolute path for executable", {"path"},Env_GetRealExecutablePath); + dict->DeclareFunction(gc, "getLittleEndian", "Is the platform little endian", {},Env_getLittleEndian); gc->BarrierBegin(); dict->SetValue("EnvPathSeperator",EnvPathSeperator); env->SetVariable("Env", dict); diff --git a/src/runtime_methods/std.cpp b/src/runtime_methods/std.cpp index 2defcf8..08951e3 100644 --- a/src/runtime_methods/std.cpp +++ b/src/runtime_methods/std.cpp @@ -1,5 +1,11 @@ #include "CrossLang.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Streams/Stream.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include #if defined(CROSSLANG_ENABLE_SHARED) #if defined(CROSSLANG_ENABLE_FFI) #include @@ -568,6 +574,23 @@ namespace Tesses::CrossLang std::shared_ptr strm; return GetArgument(args,0,strm); } + static TObject TypeIsByteReader(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + std::shared_ptr strm; + return GetArgument(args,0,strm); + } + static TObject TypeIsByteWriter(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + std::shared_ptr strm; + return GetArgument(args,0,strm); + } + static TObject TypeIsUuid(GCList& ls, std::vector args) + { + if(args.empty()) return nullptr; + return std::holds_alternative(args[0]); + } static TObject TypeIsVFS(GCList& ls, std::vector args) { if(args.empty()) return nullptr; @@ -741,6 +764,11 @@ namespace Tesses::CrossLang if(std::holds_alternative(_obj)) return "Version"; if(std::holds_alternative>(_obj)) return "DateTime"; if(std::holds_alternative>(_obj)) return "TimeSpan"; + if(std::holds_alternative>(_obj)) return "ByteReader"; + + if(std::holds_alternative>(_obj)) return "ByteWriter"; + + if(std::holds_alternative(_obj)) return "Uuid"; if(std::holds_alternative>(_obj)) { auto strm = std::get>(_obj); @@ -1222,6 +1250,21 @@ namespace Tesses::CrossLang } return nullptr; } + static TObject New_ByteReader(GCList& ls, std::vector args) + { + std::shared_ptr strm; + if(GetArgument(args, 0, strm)) + return std::make_shared(strm); + return nullptr; + } + static TObject New_ByteWriter(GCList& ls, std::vector args) + { + std::shared_ptr strm; + if(GetArgument(args, 0, strm)) + return std::make_shared(strm); + return nullptr; + } + void TStd::RegisterRoot(GC* gc, TRootEnvironment* env) { GCList ls(gc); @@ -1230,6 +1273,8 @@ namespace Tesses::CrossLang env->permissions.canRegisterRoot=true; RegisterHelpers(gc,env); + RegisterUuid(gc, env); + auto date =env->EnsureDictionary(gc,"DateTime"); date->DeclareFunction(gc, "Sleep","Sleep for a specified amount of milliseconds (multiply seconds by 1000 to get milliseconds)", {"ms"},DateTime_Sleep); @@ -1269,6 +1314,10 @@ namespace Tesses::CrossLang task->DeclareFunction(gc, "FromResult", "async from result", {"result"}, Task_FromResult); TDictionary* newTypes = env->EnsureDictionary(gc, "New"); + + newTypes->DeclareFunction(gc, "ByteReader","Read binary data from stream",{"stream"},New_ByteReader); + + newTypes->DeclareFunction(gc, "ByteWriter","Write binary data to stream",{"stream"},New_ByteWriter); //newTypes->DeclareFunction(gc,) newTypes->DeclareFunction(gc, "Promise", "Create an async object",{"resolve","reject"},New_Promise); newTypes->DeclareFunction(gc, "DateTime","Create a DateTime object, if only one arg is provided year is epoch, isLocal defaults to true unless epoch",{"year","$month","$day","$hour","$minute","$second","$isLocal"},New_DateTime); @@ -1339,6 +1388,9 @@ namespace Tesses::CrossLang env->DeclareFunction(gc, "TypeIsTimeSpan","Get whether object is a TimeSpan",{"object"},TypeIsTimeSpan); env->DeclareFunction(gc, "TypeIsTextReader","Get whether object is a TextReader",{"object"},TypeIsTextReader); env->DeclareFunction(gc, "TypeIsTextWriter","Get whether object is a TextWriter",{"object"},TypeIsTextWriter); + env->DeclareFunction(gc, "TypeIsByteReader","Get whether object is a ByteReader",{"object"},TypeIsByteReader); + env->DeclareFunction(gc, "TypeIsByteWriter","Get whether object is a ByteWriter",{"object"},TypeIsByteWriter); + env->DeclareFunction(gc, "TypeIsUuid","Get whether object is a Uuid",{"object"},TypeIsUuid); newTypes->DeclareFunction(gc, "Regex", "Create regex object",{"regex"},[](GCList& ls,std::vector args)->TObject { diff --git a/src/runtime_methods/uuid.cpp b/src/runtime_methods/uuid.cpp new file mode 100644 index 0000000..9325dd2 --- /dev/null +++ b/src/runtime_methods/uuid.cpp @@ -0,0 +1,40 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Uuid.hpp" + +namespace Tesses::CrossLang { + static TObject Uuid_NewUuid(GCList& ls, std::vector args) + { + return Tesses::Framework::Uuid::Generate(); + } + static TObject Uuid_TryParse(GCList& ls, std::vector args) + { + std::string str; + Tesses::Framework::Uuid uuid; + if(GetArgument(args, 0, str) && Tesses::Framework::Uuid::TryParse(str,uuid)) + return uuid; + return nullptr; + } + static TObject Uuid_FromBytes(GCList& ls, std::vector args) + { + TByteArray* ba; + int64_t index; + if(GetArgumentHeap(args,0,ba) && GetArgument(args, 1, index) && (size_t)index < ba->data.size() && (size_t)index + 16 <= ba->data.size()) + { + return Tesses::Framework::Serialization::BitConverter::ToUuid(ba->data[(size_t)index]); + } + + return nullptr; + } + + void TStd::RegisterUuid(GC* gc, TRootEnvironment* env) + { + gc->BarrierBegin(); + TDictionary* guid = env->EnsureDictionary(gc, "Uuid"); + guid->DeclareFunction(gc,"NewUuid","Create random uuid",{},Uuid_NewUuid); + guid->DeclareFunction(gc, "TryParse","Try to parse",{"str"}, Uuid_TryParse); + guid->DeclareFunction(gc, "FromBytes", "From bytes (big endian)",{"byteArray","offset"}, Uuid_FromBytes); + + gc->BarrierEnd(); + } +} \ No newline at end of file diff --git a/src/vm/bc/add.cpp b/src/vm/bc/add.cpp new file mode 100644 index 0000000..044cdfc --- /dev/null +++ b/src/vm/bc/add.cpp @@ -0,0 +1,164 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include +namespace Tesses::CrossLang { + bool InterperterThread::Add(GC* gc) + { + std::vector& cse=this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + + + if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) + std::get(right)); + + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,(char)(std::get(left) + std::get(right))); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, (char)(std::get(left) + std::get(right))); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, (char)(std::get(left) + std::get(right))); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) + std::get(right)); + + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) + std::get(right)); + + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) + std::get(right)); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) + std::get(right)); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) + std::get(right)); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) + std::get(right)); + } + else if(std::holds_alternative>(left) && std::holds_alternative>(right)) + { + auto& l = std::get>(left); + auto& r = std::get>(right); + cse.back()->Push(gc,std::make_shared((*l) + (*r))); + } + else if(std::holds_alternative>(left) && std::holds_alternative>(right)) + { + auto& l = std::get>(left); + auto& r = std::get>(right); + cse.back()->Push(gc,std::make_shared((*l) + (*r))); + } + else if(std::holds_alternative>(left) && std::holds_alternative>(right)) + { + auto& l = std::get>(left); + auto& r = std::get>(right); + cse.back()->Push(gc,std::make_shared((*l) + (*r))); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + std::string str={}; + str.append(std::get(left)); + str.append(std::get(right)); + cse.back()->Push(gc,str); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + std::string str={}; + str.push_back(std::get(left)); + str.append(std::get(right)); + cse.back()->Push(gc,str); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + std::string str={}; + str.append(std::get(left)); + str.push_back(std::get(right)); + cse.back()->Push(gc,str); + } + else if(std::holds_alternative(left)) + { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if(cls != nullptr) + { + gc->BarrierBegin(); + auto obj=cls->GetValue(cse.back()->callable->className,"operator+"); + gc->BarrierEnd(); + TClosure* clos; + TCallable* callable; + if(GetObjectHeap(obj,clos)) + { + this->AddCallStackEntry(ls,clos,{right}); + return true; + } + else if(GetObjectHeap(obj,callable)) + { + cse.back()->Push(gc,callable->Call(ls,{right})); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + + } + else if(natObj != nullptr) + { + cse.back()->Push(gc, natObj->CallMethod(ls,"operator+",{right})); + return false; + } + else if(dict != nullptr) + { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator+"); + 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()); + } + + } + else + { + cse.back()->Push(gc, Undefined()); + } + return false; + } +} \ No newline at end of file diff --git a/src/vm/bc/equals.cpp b/src/vm/bc/equals.cpp new file mode 100644 index 0000000..43bbe99 --- /dev/null +++ b/src/vm/bc/equals.cpp @@ -0,0 +1,236 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include + + +namespace Tesses::CrossLang { + + bool Equals(GC* gc, TObject left, TObject right) + { + GCList ls(gc); + if(std::holds_alternative(left) && std::holds_alternative(right)) + { + + return true; + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return true; + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + return std::get(left) == std::get(right); + } + else if(std::holds_alternative>(left) && std::holds_alternative>(right)) + { + return std::get>(left)->ToEpoch() == std::get>(right)->ToEpoch(); + } + else if(std::holds_alternative>(left) && std::holds_alternative>(right)) + { + return std::get>(left)->TotalSeconds() == std::get>(right)->TotalSeconds(); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + auto lver= std::get(left); + auto rver = std::get(right); + auto r = lver.CompareTo(rver); + return r == 0; + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + auto l= std::get(left); + auto r = std::get(right); + + return l == r; + } + else if(std::holds_alternative(left)) + { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + + auto dynDict = dynamic_cast(obj); + auto native = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if(cls != nullptr) + { + gc->BarrierBegin(); + auto obj=cls->GetValue("","operator=="); + gc->BarrierEnd(); + TCallable* callable; + + if(GetObjectHeap(obj,callable)) + { + return ToBool(callable->Call(ls,{right})); + + } + else if(std::holds_alternative(right)) { + return false; + } + else if(std::holds_alternative(right)) + { + return false; + } + else if(std::holds_alternative(right)) + { + return cls == std::get(right).obj; + } + } + else + if(natObj != nullptr) + { + return natObj->Equals(gc, right); + } + if(dict != nullptr) + { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator=="); + gc->BarrierEnd(); + if(!std::holds_alternative(fn)) + { + if(std::holds_alternative(fn)) + { + + auto obj = dynamic_cast(std::get(fn).obj); + if(obj != nullptr) + { + auto closure = dynamic_cast(obj); + if(closure != nullptr) + { + + if(!closure->closure->args.empty() && closure->closure->args[0] == "this") + { + return ToBool(obj->Call(ls,{left,right})); + } + else + { + return ToBool(obj->Call(ls,{right})); + } + + } + else + { + return ToBool(obj->Call(ls,{right})); + + } + } + else { + + + return dict == std::get(right).obj; + } + + } else { + + return dict == std::get(right).obj; + } + + } + else { + + return dict == std::get(right).obj; + } + return false; + + } + + else if(dynDict != nullptr) + { + auto res = dynDict->CallMethod(ls,"operator==",{right}); + if(!std::holds_alternative(res) && std::holds_alternative(res)) + { + return ToBool(res); + } + } + else if(native != nullptr && std::holds_alternative(right)) + { + return native->GetDestroyed(); + + } + + if(std::holds_alternative(right)) + { + return obj == std::get(right).obj; + + } + + else if(std::holds_alternative(right)) + { + return false; + } + else if(std::holds_alternative(right)) + { + + return false; + } + else + { + return false; + } + + } + + else if(std::holds_alternative(right)) + { + return false; + } + else if(std::holds_alternative(right)) + { + return false; + } + else + { + return false; + + } + + return false; + + } +} \ No newline at end of file diff --git a/src/vm/bc/executemethod2.cpp b/src/vm/bc/executemethod2.cpp new file mode 100644 index 0000000..6826dab --- /dev/null +++ b/src/vm/bc/executemethod2.cpp @@ -0,0 +1,3715 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Streams/ByteWriter.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +namespace Tesses::CrossLang { + extern bool IHttpServer_Handle(std::shared_ptr svr,std::vector& args); + + bool InterperterThread::ExecuteMethod2(GC* gc, TObject instance, std::string key, std::vector args) + { + std::vector& cse=this->call_stack_entries; + if(!cse.empty()) + { + GCList ls(gc); + std::regex regex; + TVMVersion version; + if(std::holds_alternative(instance)) + { + if(key == "ToString") + { + cse.back()->Push(gc,"null"); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + }else if(std::holds_alternative(instance)) + { + if(key == "ToString") + { + cse.back()->Push(gc,"undefined"); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + else + if(GetObject(instance, version)) + { + if(key == "ToString") + { + cse.back()->Push(gc, version.ToString()); + return false; + } + if(key == "ToByteArray") + { + TByteArray* ba = TByteArray::Create(ls); + ba->data.resize(5); + version.ToArray(ba->data.data()); + cse.back()->Push(gc,ba); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(GetObject(instance,regex)) + { + if(key == "Search") + { + std::string str; + if(GetArgument(args,0,str)) + { + std::smatch m; + if(std::regex_search(str,m,regex)) + { + auto myLs = TList::Create(ls); + gc->BarrierBegin(); + for(auto item : m) + { + auto itm = TDictionary::Create(ls); + itm->SetValue("Offset", (int64_t)(item.first-str.begin())); + itm->SetValue("Length",(int64_t)item.length()); + itm->SetValue("Matched",item.matched); + itm->SetValue("Text",item.str()); + myLs->Add(itm); + } + + + cse.back()->Push(gc, myLs); + gc->BarrierEnd(); + return false; + } + + } + } + + cse.back()->Push(gc, nullptr); + return false; + } + else if(std::holds_alternative(instance)) + { + bool flag = std::get(instance); + if(key == "ToString") + { + cse.back()->Push(gc, flag ? "true" : "false"); + return false; + } + else if(key == "ToLong") + { + cse.back()->Push(gc, flag ? (int64_t)1 : (int64_t)0); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative(instance)) + { + char c = std::get(instance); + if(key == "ToString") + { + cse.back()->Push(gc, std::string{c}); + return false; + } + else if(key == "ToLong") + { + uint8_t uc = (uint8_t)c; + cse.back()->Push(gc, (int64_t)uc); + return false; + } + else if(key == "IsAscii") + { + bool isAscii = c >= 0; + cse.back()->Push(gc, isAscii); + return false; + } + if(key == "IsLetter") + { + bool isLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); + cse.back()->Push(gc, isLetter); + return false; + } + if(key == "IsDigit") + { + bool isDigit = (c >= '0' && c <= '9'); + cse.back()->Push(gc, isDigit); + return false; + } + if(key == "IsLetterOrDigit") + { + bool isDigit = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); + cse.back()->Push(gc, isDigit); + return false; + } + if(key == "ToLower") + { + if(c >= 'A' && c <= 'Z') + cse.back()->Push(gc, (char)tolower(c)); + else + cse.back()->Push(gc, c); + + return false; + } + if(key == "ToUpper") + { + if(c >= 'a' && c <= 'z') + cse.back()->Push(gc, (char)toupper(c)); + else + cse.back()->Push(gc, c); + + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative(instance)) + { + double number = std::get(instance); + if(key == "ToString") + { + cse.back()->Push(gc, std::to_string(number)); + return false; + } + if(key == "ToLong") + { + cse.back()->Push(gc, (int64_t)number); + return false; + } + if(key == "ToLongBits") + { + cse.back()->Push(gc, *(int64_t*)&number); + return false; + } + if(key == "Floor") + { + cse.back()->Push(gc,floor(number)); + return false; + } + if(key == "Ceiling") + { + cse.back()->Push(gc,ceil(number)); + return false; + } + if(key == "Abs") + { + cse.back()->Push(gc,fabs(number)); + return false; + } + if(key == "Pow") + { + if(args.size() != 1) + { + throw VMException("Double.Pow must only accept one argument"); + } + if(!std::holds_alternative(args[0])) + { + throw VMException("Double.Pow must only accept a double"); + } + cse.back()->Push(gc,pow(number, std::get(args[0]))); + return false; + } + if(key == "Atan2") + { + if(args.size() != 1) + { + throw VMException("Double.Atan2 must only accept one argument"); + } + if(!std::holds_alternative(args[0])) + { + throw VMException("Double.Atan2 must only accept a double"); + } + cse.back()->Push(gc,atan2(number, std::get(args[0]))); + return false; + } + if(key == "Atan") + { + cse.back()->Push(gc,tan(number)); + return false; + } + if(key == "Tan") + { + cse.back()->Push(gc,tan(number)); + return false; + } + if(key == "Tanh") + { + cse.back()->Push(gc,tanh(number)); + return false; + } + if(key == "Asin") + { + cse.back()->Push(gc,asin(number)); + return false; + } + if(key == "Sin") + { + cse.back()->Push(gc,sin(number)); + return false; + } + if(key == "Sinh") + { + cse.back()->Push(gc,sinh(number)); + return false; + } + if(key == "Acos") + { + cse.back()->Push(gc,acos(number)); + return false; + } + if(key == "Cos") + { + cse.back()->Push(gc,cos(number)); + return false; + } + if(key == "Cosh") + { + cse.back()->Push(gc,cosh(number)); + return false; + } + if(key == "Log") + { + cse.back()->Push(gc,log(number)); + return false; + } + if(key == "Log10") + { + cse.back()->Push(gc,log10(number)); + return false; + } + if(key == "Sqrt") + { + cse.back()->Push(gc,sqrt(number)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative(instance)) + { + int64_t number = std::get(instance); + if(key == "ToHexString") + { + int64_t width = 1; + + if(!GetArgument(args,0,width)) width=1; + size_t _width = (size_t)width; + + std::stringstream strm; + if(_width > 1) + strm << std::setfill('0') << std::setw((int)_width) << std::hex << number; + else + strm << std::hex << number; + cse.back()->Push(gc,strm.str()); + return false; + } + if(key == "ToString") + { + cse.back()->Push(gc, std::to_string(number)); + return false; + } + if(key == "ToChar") + { + uint8_t c = (uint8_t)number; + cse.back()->Push(gc, (char)c); + return false; + } + if(key == "Abs") + { + if(number < 0) + cse.back()->Push(gc, -number); + else + cse.back()->Push(gc, number); + return false; + } + if(key == "ToDouble") + { + cse.back()->Push(gc,(double)number); + return false; + } + if(key == "ToDoubleBits") + { + cse.back()->Push(gc,*(double*)&number); + return false; + } + + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative(instance)) + { + auto path = std::get(instance); + if(key == "GetEnumerator") + { + + TList* _ls = TList::Create(ls); + for(auto item : path.path) + { + _ls->Add(item); + } + + cse.back()->Push(gc, TListEnumerator::Create(ls,_ls)); + return false; + } + if(key == "ToString") + { + cse.back()->Push(gc, path.ToString()); + return false; + } + if(key == "GetAt") + { + int64_t index; + if(GetArgument(args,0,index)) + { + size_t idx = (size_t)idx; + if(idx < path.path.size()) + cse.back()->Push(gc, path.path[idx]); + else + cse.back()->Push(gc, nullptr); + return false; + } + } + if(key == "Count" || key == "Length") + { + cse.back()->Push(gc, (int64_t)path.path.size()); + return false; + } + if(key == "GetParent") + { + cse.back()->Push(gc, path.GetParent()); + return false; + } + if(key == "GetFileName") + { + cse.back()->Push(gc, path.GetFileName()); + return false; + } + if(key == "GetExtension") + { + cse.back()->Push(gc, path.GetExtension()); + return false; + } + if(cse.back()->env->GetRootEnvironment()->permissions.canRegisterLocalFS && key == "MakeAbsolute") + { + Tesses::Framework::Filesystem::VFSPath p; + if(GetArgumentAsPath(args,0,p)) + { + cse.back()->Push(gc,path.MakeAbsolute(p)); + return false; + } + else + { + cse.back()->Push(gc,path.MakeAbsolute()); + return false; + } + } + if(cse.back()->env->GetRootEnvironment()->permissions.canRegisterLocalFS && key == "MakeRelative") + { + Tesses::Framework::Filesystem::VFSPath p; + if(GetArgumentAsPath(args,0,p)) + { + cse.back()->Push(gc,path.MakeRelative(p)); + return false; + } + else + { + cse.back()->Push(gc,path.MakeRelative()); + return false; + } + } + if(key == "ChangeExtension") + { + Tesses::Framework::Filesystem::VFSPath newPath = path; + std::string ext; + if(GetArgument(args,0, ext)) + { + newPath.ChangeExtension(ext); + } + else + { + newPath.RemoveExtension(); + } + cse.back()->Push(gc, newPath); + return false; + } + if(key == "CollapseRelativeParents") + { + cse.back()->Push(gc, path.CollapseRelativeParents()); + return false; + } + if(key == "IsRelative") + { + cse.back()->Push(gc, path.relative); + return false; + //Path.FromString(); + } + } + else if(std::holds_alternative(instance)) + { + std::string str = std::get(instance); + if(key == "ToLower") + { + for(size_t i = 0; i < str.size(); i++) + { + if(str[i] >= 'A' && str[i] <= 'Z') + { + str[i] = 'a' + (str[i] - 'A'); + } + } + cse.back()->Push(gc, str); + return false; + } + if(key == "ToUpper") + { + + for(size_t i = 0; i < str.size(); i++) + { + if(str[i] >= 'a' && str[i] <= 'z') + { + str[i] = 'A' + (str[i] - 'a'); + } + } + cse.back()->Push(gc, str); + return false; + } + if(key == "PadLeft") + { + int64_t pad; + char padChar=' '; + + if(args.size() == 0 || args.size() > 2) + { + throw VMException("String.PadLeft must only accept 1 or 2 arguments"); + + } + + if(GetArgument(args,0, pad)) + { + if((size_t)pad < str.size()) { + cse.back()->Push(gc, str); + return false; + } + GetArgument(args,1, padChar); + size_t diff = (size_t)pad - str.size(); + str.insert(str.begin(),diff, padChar); + cse.back()->Push(gc, str); + return false; + } + else throw VMException("String.PadLeft must have a long for width"); + } + if(key == "PadRight") + { + int64_t pad; + char padChar=' '; + + if(args.size() == 0 || args.size() > 2) + { + throw VMException("String.PadRight must only accept 1 or 2 arguments"); + + } + + if(GetArgument(args,0, pad)) + { + if((size_t)pad < str.size()) { + cse.back()->Push(gc, str); + return false; + } + GetArgument(args,1, padChar); + size_t diff = (size_t)pad - str.size(); + str.insert(str.end(),diff, padChar); + cse.back()->Push(gc, str); + return false; + } + else throw VMException("String.PadRight must have a long for width"); + } + if(key == "Contains") + { + std::string str2; + char c; + if(GetArgument(args,0,str2)) + { + + int64_t index = 0; + GetArgument(args,1,index); + + auto res = str.find(str2,(std::size_t)index); + + cse.back()->Push(gc, res != std::string::npos); + return false; + } + + else if(GetArgument(args,0,c)) + { + int64_t index = 0; + GetArgument(args,1,index); + + auto res = str.find_first_of(c,(std::size_t)index); + + cse.back()->Push(gc, res != std::string::npos); + return false; + } + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "IndexOf") + { + std::string str2; + char c; + if(GetArgument(args,0,str2)) + { + + int64_t index = 0; + GetArgument(args,1,index); + + auto res = str.find(str2,(std::size_t)index); + if(res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); + return false; + } + + else if(GetArgument(args,0,c)) + { + int64_t index = 0; + GetArgument(args,1,index); + + auto res = str.find_first_of(c,(std::size_t)index); + if(res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); + return false; + } + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "LastIndexOf") + { + std::string str2; + char c; + if(GetArgument(args,0,str2)) + { + + int64_t index = str.size(); + GetArgument(args,1,index); + + auto res = str.rfind(str2,(std::size_t)index); + if(res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); + return false; + } + else if(GetArgument(args,0,c)) + { + int64_t index = str.size(); + GetArgument(args,1,index); + + auto res = str.find_last_of(c,(std::size_t)index); + if(res == std::string::npos) + cse.back()->Push(gc, (int64_t)-1); + else + cse.back()->Push(gc, (int64_t)res); + return false; + } + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "GetEnumerator") + { + cse.back()->Push(gc, TStringEnumerator::Create(ls,str)); + return false; + } + if(key == "Substring") + { + if(args.size() >=1 && std::holds_alternative(args[0])) + { + size_t offset = (size_t)std::get(args[0]); + size_t count = std::string::npos; + if(args.size() == 2 && std::holds_alternative(args[1])) + { + count = (size_t)std::get(args[1]); + } + cse.back()->Push(gc, str.substr(offset,count)); + return false; + } + + } + if(key == "Remove") + { + if(args.size() >=1 && std::holds_alternative(args[0])) + { + size_t offset = (size_t)std::get(args[0]); + size_t count = std::string::npos; + if(args.size() == 2 && std::holds_alternative(args[1])) + { + count = (size_t)std::get(args[1]); + } + cse.back()->Push(gc, str.erase(offset,count)); + return false; + } + + } + if(key == "TrimStart") + { + if(args.size() >= 0) + { + char c = (args.size() == 1 && std::holds_alternative(args[0])) ? std::get(args[0]) : ' '; + + size_t i = 0; + for(; i < str.size();i++) + { + if(str[i] != c) break; + } + cse.back()->Push(gc,str.substr(i)); + return false; + } + } + if(key == "TrimEnd") + { + if(args.size() >= 0) + { + char c = (args.size() == 1 && std::holds_alternative(args[0])) ? std::get(args[0]) : ' '; + size_t i = str.size()-1; + for(; i >= 0;i--) + { + if(str[i] != c) break; + } + cse.back()->Push(gc,str.substr(0,i+1)); + return false; + } + } + if(key == "EndsWith") + { + std::string v; + if(GetArgument(args,0,v)) + { + if(str.size() < v.size()) { + cse.back()->Push(gc,false); + return false; + } + + size_t _end = str.size()-v.size(); + for(size_t i = 0; i < v.size(); i++) + { + if(v[i] != str[i+_end]) + { + cse.back()->Push(gc,false); + return false; + } + } + cse.back()->Push(gc,true); + return false; + } + cse.back()->Push(gc,false); + return false; + } + if(key == "StartsWith") + { + std::string v; + if(GetArgument(args,0,v)) + { + if(str.size() < v.size()) { + cse.back()->Push(gc,false); + return false; + } + for(size_t i = 0; i < v.size(); i++) + { + if(v[i] != str[i]) + { + cse.back()->Push(gc,false); + return false; + } + } + cse.back()->Push(gc,true); + return false; + } + cse.back()->Push(gc,false); + return false; + } + if(key == "Escape") + { + bool quote; + if(!GetArgument(args,0,quote)) quote=false; + cse.back()->Push(gc, EscapeString(str, quote)); + return false; + } + if(key == "Replace") + { + std::string oldStr; + std::string newStr; + + std::string _str={}; + if(GetArgument(args,0,oldStr) && GetArgument(args,1,newStr)) + { + _str = Tesses::Framework::Http::HttpUtils::Replace(str, oldStr,newStr); + + + } + cse.back()->Push(gc,_str); + + return false; + } + if(key == "Split") + { + std::string delimiter; + bool removeEmpty=false; + size_t count=std::string::npos; + + if(args.size() < 1 || args.size() > 3) throw VMException("String.Split must only accept 1-3 arguments"); + if(!std::holds_alternative(args[0])) throw VMException("String.Split first arg must be a string"); + else + delimiter = std::get(args[0]); + + if(args.size() > 1 && !std::holds_alternative(args[1])) throw VMException("String.Split second arg must be a bool"); + else if(args.size() > 1) + removeEmpty = std::get(args[1]); + if(args.size() > 2 && !std::holds_alternative(args[2])) throw VMException("String.Split third arg must be a int64_t"); + else if(args.size() > 2) + count = (size_t)std::get(args[2]); + + auto res = Tesses::Framework::Http::HttpUtils::SplitString(str, delimiter,count); + TList* mls = TList::Create(ls); + for(auto item : res) + { + if(!removeEmpty || !item.empty()) mls->Add(item); + } + cse.back()->Push(gc,mls); + return false; + // SplitString() + } + if(key == "GetAt") + { + if(args.size() != 1) + { + throw VMException("String.GetAt must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("String.GetAt must only accept a long"); + } + + size_t index = (size_t)std::get(args[0]); + size_t sz = str.size(); + if(index >= 0 && index < sz) + { + cse.back()->Push(gc, str[index]); + return false; + } + + } + if(key == "Count" || key == "Length") + { + int64_t len = (int64_t)str.size(); + if(len < 0) len = 0; + + cse.back()->Push(gc, len); + return false; + } + if(key == "ToString") + { + cse.back()->Push(gc, str); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative>(instance)) + { + auto& time = std::get>(instance); + if(key == "ToString") + { + bool slim = false; + GetArgument(args,0,slim); + + cse.back()->Push(gc, time->ToString(slim)); + + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative>(instance)) + { + auto& date = std::get>(instance); + + + if(key == "ToString") + { + std::string fmt; + if(GetArgument(args,0,fmt)) + { + cse.back()->Push(gc, date->ToString(fmt)); + } + else + { + cse.back()->Push(gc, date->ToString()); + } + return false; + } + if(key == "ToHttpDate") + { + cse.back()->Push(gc, date->ToHttpDate()); + return false; + } + if(key == "ToEpoch") + { + cse.back()->Push(gc, date->ToEpoch()); + return false; + } + if(key == "ToLocal") + { + cse.back()->Push(gc, std::make_shared(date->ToLocal())); + return false; + } + if(key == "ToUTC") + { + cse.back()->Push(gc, std::make_shared(date->ToUTC())); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + + } + else if(std::holds_alternative>(instance)) + { + auto textReader = std::get>(instance); + if(key == "Rewind") + { + cse.back()->Push(gc,textReader->Rewind()); + return false; + } + if(key == "ReadBlock") + { + int64_t sz; + if(GetArgument(args,0,sz)) + { + std::string block; + if(textReader->ReadBlock(block,(size_t)sz)) + { + cse.back()->Push(gc, block); + return false; + } + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "ReadChar") + { + cse.back()->Push(gc,(int64_t)textReader->ReadChar()); + return false; + } + if(key == "ReadLine") + { + std::string line; + if(textReader->ReadLine(line)) + { + cse.back()->Push(gc, line); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "ReadLineHttp") + { + std::string line; + if(textReader->ReadLineHttp(line)) + { + cse.back()->Push(gc, line); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "ReadAllLines") + { + std::vector lines; + textReader->ReadAllLines(lines); + gc->BarrierBegin(); + TList* list = TList::Create(ls); + for(auto& item : lines) list->Add(item); + gc->BarrierEnd(); + return list; + } + if(key == "ReadToEnd") + { + std::string text; + textReader->ReadToEnd(text); + cse.back()->Push(gc,text); + return false; + } + if(key == "CopyTo") + { + std::shared_ptr writer; + if(GetArgument(args,0,writer)) + { + textReader->CopyTo(*writer); + } + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative>(instance)) + { + auto textWriter=std::get>(instance); + if(key == "Write") + { + if(args.size()>0) + textWriter->Write(ToString(gc,args[0])); + } + if(key == "WriteLine") + { + if(args.size()>0) + textWriter->WriteLine(ToString(gc,args[0])); + } + if(key == "WriteData") + { + if(args.size()>0) + { + auto s=ToString(gc,args[0]); + textWriter->WriteData(s.c_str(),s.size()); + } + } + cse.back()->Push(gc, nullptr); + return false; + } + else if(std::holds_alternative>(instance)) + { + auto& br = std::get>(instance); + if(key == "ReadS8") + { + cse.back()->Push(gc,(int64_t)br->ReadI8()); + return false; + } + if(key == "ReadU8") + { + cse.back()->Push(gc,(int64_t)br->ReadU8()); + return false; + } + if(key == "ReadS16BE") + { + cse.back()->Push(gc,(int64_t)br->ReadI16BE()); + return false; + } + if(key == "ReadS16LE") + { + cse.back()->Push(gc,(int64_t)br->ReadI16LE()); + return false; + } + if(key == "ReadU16BE") + { + cse.back()->Push(gc,(int64_t)br->ReadU16BE()); + return false; + } + if(key == "ReadU16LE") + { + cse.back()->Push(gc,(int64_t)br->ReadU16LE()); + return false; + } + if(key == "ReadS32BE") + { + cse.back()->Push(gc,(int64_t)br->ReadI32BE()); + return false; + } + if(key == "ReadS32LE") + { + cse.back()->Push(gc,(int64_t)br->ReadI32LE()); + return false; + } + if(key == "ReadU32BE") + { + cse.back()->Push(gc,(int64_t)br->ReadU32BE()); + return false; + } + if(key == "ReadU32LE") + { + cse.back()->Push(gc,(int64_t)br->ReadU32LE()); + return false; + } + if(key == "ReadS64BE") + { + cse.back()->Push(gc,br->ReadI64BE()); + return false; + } + if(key == "ReadS64LE") + { + cse.back()->Push(gc,br->ReadI64LE()); + return false; + } + if(key == "ReadU16BE") + { + uint64_t value = br->ReadU64BE(); + int64_t value2 = 0; + memcpy(&value2,&value,sizeof(uint64_t)); + cse.back()->Push(gc,value2); + return false; + } + if(key == "ReadU64LE") + { + uint64_t value = br->ReadU64LE(); + int64_t value2 = 0; + memcpy(&value2,&value,sizeof(uint64_t)); + cse.back()->Push(gc,value2); + return false; + } + + if(key == "ReadF32BE") + { + cse.back()->Push(gc,(double)br->ReadF32BE()); + return false; + } + if(key == "ReadF32LE") + { + cse.back()->Push(gc,(double)br->ReadF32LE()); + return false; + } + + if(key == "ReadF64BE") + { + cse.back()->Push(gc,br->ReadF64BE()); + return false; + } + if(key == "ReadF64LE") + { + cse.back()->Push(gc,br->ReadF64LE()); + return false; + } + + if(key == "ReadUuid") + { + cse.back()->Push(gc, br->ReadUuid()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative>(instance)) + { + auto& bw = std::get>(instance); + int64_t number; + + double numberDbl; + + Tesses::Framework::Uuid uuid; + if(GetArgument(args,0,number)) + { + if(key == "WriteS8") + { + bw->WriteI8((int8_t)number); + } + else if(key == "WriteU8") + { + bw->WriteI8((uint8_t)number); + } + + + else if(key == "WriteS16BE") + { + bw->WriteI16BE((int16_t)number); + } + else if(key == "WriteS16LE") + { + bw->WriteI16LE((int16_t)number); + } + else if(key == "WriteU16BE") + { + bw->WriteU16BE((uint16_t)number); + } + else if(key == "WriteU16LE") + { + bw->WriteU16LE((uint16_t)number); + } + + + else if(key == "WriteS32BE") + { + bw->WriteI32BE((int32_t)number); + } + else if(key == "WriteS32LE") + { + bw->WriteI32LE((int32_t)number); + } + else if(key == "WriteU32BE") + { + bw->WriteU32BE((uint32_t)number); + } + else if(key == "WriteU32LE") + { + bw->WriteU32LE((uint32_t)number); + } + + else if(key == "WriteS64BE") + { + bw->WriteI64BE(number); + } + else if(key == "WriteS64LE") + { + bw->WriteI64LE(number); + } + else if(key == "WriteU64BE") + { + uint64_t number2 = 0; + memcpy(&number2,&number, sizeof(uint64_t)); + bw->WriteU64BE(number2); + } + else if(key == "WriteU64LE") + { + + uint64_t number2 = 0; + memcpy(&number2,&number, sizeof(uint64_t)); + bw->WriteU64LE(number2); + } + + + } + else if(GetArgument(args,0,numberDbl)) + { + if(key == "WriteF32BE") + { + bw->WriteF32BE((float)numberDbl); + } + else if(key == "WriteF32LE") + { + bw->WriteF32LE((float)numberDbl); + } + else if(key == "WriteF64BE") + { + bw->WriteF64BE(numberDbl); + } + else if(key == "WriteF64LE") + { + bw->WriteF64LE(numberDbl); + } + } + else if(GetArgument(args,0,uuid)) + { + if(key == "WriteUuid") + { + bw->WriteUuid(uuid); + } + } + cse.back()->Push(gc,Undefined()); + return false; + } + else if(std::holds_alternative>(instance)) + { + auto& strm = std::get>(instance); + if(strm != nullptr) + { + auto memStrm = std::dynamic_pointer_cast(strm); + auto netStrm = std::dynamic_pointer_cast(strm); + + auto mystrm = std::dynamic_pointer_cast(strm); + + if(mystrm != nullptr) + { + TDictionary* dict2; + if(GetObjectHeap(mystrm->obj, dict2)) + { + + gc->BarrierBegin(); + auto o = dict2->GetValue(key); + gc->BarrierEnd(); + + return InvokeMethod(ls,o,dict2,args); + } + } + if(memStrm != nullptr) + { + if(key == "GetBytes") + { + auto res = TByteArray::Create(ls); + res->data = memStrm->GetBuffer(); + cse.back()->Push(gc, res); + return false; + } + } + if(netStrm != nullptr) + { + if(key == "GetPort") + { + cse.back()->Push(gc, (int64_t)netStrm->GetPort()); + return false; + } + if(key == "Bind") + { + std::string ip; + int64_t port; + if(GetArgument(args,0,ip) && GetArgument(args,1,port)) + netStrm->Bind(ip,(uint16_t)port); + + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Accept") + { + std::string ip; + uint16_t port; + auto strm = netStrm->Accept(ip,port); + TDictionary* dict = TDictionary::Create(ls); + gc->BarrierBegin(); + dict->SetValue("IP",ip); + dict->SetValue("Port",(int64_t)port); + dict->SetValue("Stream", strm); + + gc->BarrierEnd(); + cse.back()->Push(gc, dict); + return false; + } + if(key == "Listen") + { + int64_t backlog; + if(GetArgument(args,0,backlog)) + { + netStrm->Listen((int32_t)backlog); + } + else + { + netStrm->Listen(10); + } + + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "ReadFrom") + { + TByteArray* data; + int64_t offset; + int64_t length; + if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) + { + size_t off = (size_t)offset; + size_t len = (size_t)length; + std::string ip={}; + uint16_t port=0; + + if(off < len) + + len = netStrm->ReadFrom(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size())),ip,port); + + else + len = 0; + + TDictionary* dict = TDictionary::Create(ls); + gc->BarrierBegin(); + dict->SetValue("IP",ip); + dict->SetValue("Port",(int64_t)port); + dict->SetValue("Read", (int64_t)len); + + gc->BarrierEnd(); + cse.back()->Push(gc, dict); + + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "WriteTo") + { + TByteArray* data; + int64_t offset; + int64_t length; + std::string ip; + int64_t port; + if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length) && GetArgument(args,3,ip) && GetArgument(args,4,port)) + { + size_t off = (size_t)offset; + size_t len = (size_t)length; + + if(off < len) + + len = netStrm->WriteTo(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size())), ip, (int64_t)port); + + else + len = 0; + + cse.back()->Push(gc, (int64_t)len); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + } + + if(key == "Read") + { + TByteArray* data; + int64_t offset; + int64_t length; + if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) + { + size_t off = (size_t)offset; + size_t len = (size_t)length; + + if(off < len) + + len = strm->Read(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size()))); + + else + len = 0; + + cse.back()->Push(gc, (int64_t)len); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Write") + { + TByteArray* data; + int64_t offset; + int64_t length; + if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) + { + size_t off = (size_t)offset; + size_t len = (size_t)length; + + if(off < len) + + len = strm->Write(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size()))); + + else + len = 0; + + cse.back()->Push(gc, (int64_t)len); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "ReadBlock") + { + TByteArray* data; + int64_t offset; + int64_t length; + if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) + { + size_t off = (size_t)offset; + size_t len = (size_t)length; + + if(off < len) + + len = strm->ReadBlock(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size()))); + + else + len = 0; + + cse.back()->Push(gc, (int64_t)len); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "WriteText") + { + std::string text; + + if(GetArgument(args,0,text)) + { + strm->WriteBlock((const uint8_t*)text.data(), text.size()); + } + + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "WriteBlock") + { + TByteArray* data; + int64_t offset; + int64_t length; + if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) + { + size_t off = (size_t)offset; + size_t len = (size_t)length; + + if(off < len) + + strm->WriteBlock(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size()))); + + + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "CopyTo") + { + std::shared_ptr data; + int64_t buffSize; + if(GetArgument(args,0,data)) + { + if(!GetArgument(args,1,buffSize)) buffSize=1024; + strm->CopyTo(data,(size_t)buffSize); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "CopyToLimit") + { + std::shared_ptr data; + int64_t cnt; + int64_t buffSize; + if(GetArgument(args,0,data) && GetArgument(args,1,cnt)) + { + if(!GetArgument(args,2,buffSize)) buffSize=1024; + strm->CopyToLimit(data,(uint64_t)cnt,(size_t)buffSize); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Flush") + { + strm->Flush(); + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Close") + { + strm->Close(); + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Seek") + { + int64_t pos,whence; + if(!GetArgument(args,0,pos)) pos=0; + + if(!GetArgument(args,1,whence)) whence=0; + + + strm->Seek(pos, whence == 0 ? Tesses::Framework::Streams::SeekOrigin::Begin : whence == 1 ? Tesses::Framework::Streams::SeekOrigin::Current : Tesses::Framework::Streams::SeekOrigin::End); + + cse.back()->Push(gc, nullptr); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + } + else if(std::holds_alternative>(instance)) + { + auto svr = std::get>(instance); + if(svr != nullptr) + { + auto mountable = std::dynamic_pointer_cast(svr); + auto routable = std::dynamic_pointer_cast(svr); + + if(mountable != nullptr) + { + if(key == "Mount") + { + Tesses::Framework::Filesystem::VFSPath p; + + if(args.size() > 1 && GetArgumentAsPath(args,0,p)) + { + std::shared_ptr svr2=ToHttpServer(gc,args[1]); + + if(svr2) + mountable->Mount(p.ToString(), svr2); + + cse.back()->Push(gc,nullptr); + return false; + } + } + if(key == "Unmount") + { + Tesses::Framework::Filesystem::VFSPath p; + + if(GetArgumentAsPath(args,0,p)) + { + mountable->Unmount(p.ToString()); + cse.back()->Push(gc,nullptr); + return false; + } + } + } + if(routable != nullptr) + { + if(key == "Add") + { + std::string method; + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,method) && GetArgument(args,1,pattern) && GetArgumentHeap(args,2,callable)) + { + routable->Add(method,pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + else if(key == "Delete") + { + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) + { + routable->Delete(pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + else if(key == "Get") + { + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) + { + routable->Get(pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + else if(key == "Options") + { + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) + { + routable->Options(pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + else if(key == "Patch") + { + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) + { + routable->Patch(pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + else if(key == "Post") + { + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) + { + routable->Post(pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + else if(key == "Put") + { + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) + { + routable->Put(pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + else if(key == "Trace") + { + std::string pattern; + TCallable* callable; + if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) + { + routable->Trace(pattern, callable->ToRouteServerRequestHandler(gc)); + } + } + } + if(key == "Handle") + { + cse.back()->Push(gc,IHttpServer_Handle(svr,args)); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + } + else if(std::holds_alternative>(instance)) + { + auto vfs = std::get>(instance); + if(vfs != nullptr) + { + auto myvfs = std::dynamic_pointer_cast(vfs); + + auto mountable = std::dynamic_pointer_cast(vfs); + if(myvfs != nullptr) + { + TDictionary* dict2; + if(GetObjectHeap(myvfs->obj, dict2)) + { + + gc->BarrierBegin(); + auto o = dict2->GetValue(key); + gc->BarrierEnd(); + + return InvokeMethod(ls,o,dict2,args); + } + } + if(mountable != nullptr) + { + if(key == "Unmount") + { + Tesses::Framework::Filesystem::VFSPath path; + + if(GetArgumentAsPath(args,0,path)) + { + mountable->Unmount(path); + } + + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Mount") + { + Tesses::Framework::Filesystem::VFSPath path; + std::shared_ptr vfs2; + if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,vfs2)) + { + + //mountable->Mount(path, , true); + mountable->Mount(path, vfs2); + } + + cse.back()->Push(gc, nullptr); + return false; + } + } + if(key == "Close") + { + vfs->Close(); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "EnumeratePaths") + { + Tesses::Framework::Filesystem::VFSPath dir; + if(GetArgumentAsPath(args,0,dir)) + { + auto tem = TExternalMethod::Create(ls,"Get the enumerator",{},[vfs,dir](GCList& ls, std::vector args)->TObject{ + return TVFSPathEnumerator::Create(ls,vfs->EnumeratePaths(dir)); + }); + auto d1=TDictionary::Create(ls); + gc->BarrierBegin(); + tem->watch.push_back(vfs); + d1->SetValue("GetEnumerator", tem); + gc->BarrierEnd(); + + cse.back()->Push(gc,d1); + return false; + } + + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "MoveDirectory") + { + Tesses::Framework::Filesystem::VFSPath existingFile; + + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) + { + vfs->MoveDirectory(existingFile,symlinkFile); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "SetDate") + { + Tesses::Framework::Filesystem::VFSPath path; + std::shared_ptr lastWrite; + std::shared_ptr lastAccess; + if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,lastWrite) && GetArgument(args,2,lastAccess)) + { + vfs->SetDate(path,*lastWrite, *lastAccess); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "GetDate") + { + Tesses::Framework::Filesystem::VFSPath path; + if(GetArgumentAsPath(args,0,path)) + { + Tesses::Framework::Date::DateTime lastWrite; + Tesses::Framework::Date::DateTime lastAccess; + vfs->GetDate(path,lastWrite,lastAccess); + + auto dict = TDictionary::Create(ls); + ls.GetGC()->BarrierBegin(); + + dict->SetValue("LastWrite", std::make_shared(lastWrite)); + dict->SetValue("LastAccess", std::make_shared(lastAccess)); + ls.GetGC()->BarrierEnd(); + + cse.back()->Push(gc, dict); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "MoveFile") + { + Tesses::Framework::Filesystem::VFSPath existingFile; + + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) + { + vfs->MoveFile(existingFile,symlinkFile); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "CreateHardlink") + { + Tesses::Framework::Filesystem::VFSPath existingFile; + + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) + { + vfs->CreateHardlink(existingFile,symlinkFile); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "CreateSymlink") + { + Tesses::Framework::Filesystem::VFSPath existingFile; + + Tesses::Framework::Filesystem::VFSPath symlinkFile; + if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) + { + vfs->CreateSymlink(existingFile,symlinkFile); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "RegularFileExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->RegularFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "SpecialFileExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->SpecialFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "FIFOFileExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->FIFOFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "SocketFileExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->SocketFileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "BlockDeviceExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->BlockDeviceExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "CharacterDeviceExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->CharacterDeviceExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "SymlinkExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->SymlinkExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "DirectoryExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->DirectoryExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "FileExists") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->FileExists(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "ReadLink") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->ReadLink(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "VFSPathToSystem") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + cse.back()->Push(gc,vfs->VFSPathToSystem(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "SystemToVFSPath") + { + std::string filename; + if(GetArgument(args,0,filename)) + { + cse.back()->Push(gc,vfs->SystemToVFSPath(filename)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "DeleteFile") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + vfs->DeleteFile(filename); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Lock") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + vfs->Lock(filename); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Unlock") + { + Tesses::Framework::Filesystem::VFSPath filename; + if(GetArgumentAsPath(args,0,filename)) + { + vfs->Unlock(filename); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "DeleteDirectoryRecurse") + { + Tesses::Framework::Filesystem::VFSPath dirname; + if(GetArgumentAsPath(args,0,dirname)) + { + vfs->DeleteDirectoryRecurse(dirname); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "DeleteDirectory") + { + Tesses::Framework::Filesystem::VFSPath dirname; + if(GetArgumentAsPath(args,0,dirname)) + { + vfs->DeleteDirectory(dirname); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "CreateDirectory") + { + + Tesses::Framework::Filesystem::VFSPath dirname; + if(GetArgumentAsPath(args,0,dirname)) + { + vfs->CreateDirectory(dirname); + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "OpenFile") + { + + Tesses::Framework::Filesystem::VFSPath path; + std::string mode; + if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode)) + { + auto res = vfs->OpenFile(path,mode); + cse.back()->Push(gc, res); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "Chmod") + { + Tesses::Framework::Filesystem::VFSPath path; + int64_t mode; + if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode)) + { + vfs->Chmod(path,(uint32_t)mode); + } + + cse.back()->Push(gc, nullptr); + return false; + } + if(key == "StatVFS") + { + Tesses::Framework::Filesystem::VFSPath path; + + if(GetArgumentAsPath(args,0,path)) + { + Tesses::Framework::Filesystem::StatVFSData data; + if(vfs->StatVFS(path,data)) + { + cse.back()->Push(gc, TDictionary::Create(ls,{ + TDItem("BlockSize", (int64_t)data.BlockSize), + TDItem("FragmentSize",(int64_t)data.FragmentSize), + TDItem("Blocks",(int64_t)data.Blocks), + TDItem("BlocksFree",(int64_t)data.BlocksFree), + TDItem("BlocksAvailable", (int64_t)data.BlocksAvailable), + TDItem("TotalInodes", (int64_t)data.TotalInodes), + TDItem("FreeInodes",(int64_t)data.FreeInodes), + TDItem("AvailableInodes",(int64_t)data.AvailableInodes), + TDItem("Id",(int64_t)data.Id), + TDItem("Flags",(int64_t)data.Flags), + TDItem("MaxNameLength",(int64_t)data.MaxNameLength) + })); + return false; + } + } + + cse.back()->Push(gc, nullptr); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + + } + else if(std::holds_alternative(instance)) + { + auto& obj = std::get(instance); + if(key == "ToBytes") + { + TByteArray* ba = TByteArray::Create(ls); + ba->data.resize(16); + Tesses::Framework::Serialization::BitConverter::FromUuid(ba->data[0], obj); + cse.back()->Push(gc, ba); + return false; + } + if(key == "ToString") + { + int64_t arg; + if(GetArgument(args,0,arg)) + { + cse.back()->Push(gc, obj.ToString((Framework::UuidStringifyConfig)arg)); + return false; + } + cse.back()->Push(gc, obj.ToString(Framework::UuidStringifyConfig::LowercaseNoCurly)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(std::holds_alternative(instance)) + { + auto obj = std::get(instance).obj; + auto list = dynamic_cast(obj); + auto dynList = dynamic_cast(obj); + auto bArray = dynamic_cast(obj); + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto ittr = dynamic_cast(obj); + + auto env = dynamic_cast(obj); + + auto subEnv = dynamic_cast(obj); + auto rootEnv = dynamic_cast(obj); + auto callable = dynamic_cast(obj); + auto callstackEntry = dynamic_cast(obj); + + + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + auto aArray=dynamic_cast(obj); + auto ttask = dynamic_cast(obj); + auto file = dynamic_cast(obj); + + if(file != nullptr) + { + if(key == "MetadataDecode") + { + int64_t index; + if(GetArgument(args,0, index) && (size_t)index < file->metadata.size()) + { + cse.back()->Push(gc,file->MetadataDecode(ls,(size_t)index)); + return false; + } + } + if(key == "MetadataName") + { + int64_t index; + if(GetArgument(args,0, index) && (size_t)index < file->metadata.size()) + { + cse.back()->Push(gc,file->metadata.at((size_t)index).first); + return false; + } + } + cse.back()->Push(gc,Undefined()); + return false; + } + if(ttask != nullptr) + { + if(key == "ContinueWith") + { + TCallable* callable2; + if(GetArgumentHeap(args,0,callable2)) + { + cse.back()->Push(gc,ttask->ContinueWith(ls,callable2)); + return false; + } + } + if(key == "Wait") + { + + cse.back()->Push(gc,ttask->Wait()); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + + if(natObj != nullptr) + { + cse.back()->Push(gc, natObj->CallMethod(ls,key,args)); + return false; + } + + if(callstackEntry != nullptr) + { + if(key == "Resume") + { + gc->BarrierBegin(); + cse.push_back(callstackEntry); + gc->BarrierEnd(); + return true; + } + if(key == "Push") + { + if(!args.empty()) + callstackEntry->Push(gc, args[0]); + else + callstackEntry->Push(gc,Undefined()); + return false; + } + if(key == "Pop") + { + cse.back()->Push(gc, callstackEntry->Pop(ls)); + return false; + } + } + + + if(rootEnv != nullptr) + { + //TStd::RegisterCrypto + //TStd::RegisterDictionary + //TStd::RegisterEnv + //TStd::RegisterIO + //TStd::RegisterJson + //TStd::RegisterNet + //TStd::RegisterOGC + //TStd::RegisterPath + //TStd::RegisterRoot + //TStd::RegisterSqlite + //TStd::RegisterVM + auto myEnv = cse.back()->env->GetRootEnvironment(); + + if(key == "RegisterOnError") + { + TCallable* callable; + if(!rootEnv->permissions.locked && GetArgumentHeap(args,0,callable)) + { + gc->BarrierBegin(); + rootEnv->RegisterOnError(callable); + gc->BarrierEnd(); + } + } + if(key == "SetCustomConsole") + { + TDictionary* dict; + if(!rootEnv->permissions.locked && GetArgumentHeap(args,0, dict)) + { + gc->BarrierBegin(); + rootEnv->permissions.customConsole = dict; + gc->BarrierEnd(); + } + else if(!rootEnv->permissions.locked && myEnv->permissions.customConsole == nullptr) + { + gc->BarrierBegin(); + rootEnv->permissions.customConsole=nullptr; + gc->BarrierEnd(); + } + } + if(key == "RegisterEverything") + { + if(myEnv->permissions.canRegisterEverything) + { + TStd::RegisterStd(gc, rootEnv); + } + else + { + if(myEnv->permissions.canRegisterConsole && !rootEnv->permissions.locked) + TStd::RegisterConsole(gc, rootEnv); + + if(myEnv->permissions.canRegisterCrypto && !rootEnv->permissions.locked) + TStd::RegisterCrypto(gc, rootEnv); + + if(myEnv->permissions.canRegisterDictionary && !rootEnv->permissions.locked) + TStd::RegisterDictionary(gc, rootEnv); + + if(myEnv->permissions.canRegisterEnv && !rootEnv->permissions.locked) + TStd::RegisterEnv(gc, rootEnv); + + + if(myEnv->permissions.canRegisterIO && !rootEnv->permissions.locked) + TStd::RegisterIO(gc, rootEnv, myEnv->permissions.canRegisterLocalFS); + + if(myEnv->permissions.canRegisterJSON && !rootEnv->permissions.locked) + TStd::RegisterJson(gc, rootEnv); + + if(myEnv->permissions.canRegisterNet && !rootEnv->permissions.locked) + TStd::RegisterNet(gc, rootEnv); + + if(myEnv->permissions.canRegisterOGC && !rootEnv->permissions.locked) + TStd::RegisterOGC(gc, rootEnv); + + if(myEnv->permissions.canRegisterPath && !rootEnv->permissions.locked) + TStd::RegisterPath(gc, rootEnv); + + if(myEnv->permissions.canRegisterRoot && !rootEnv->permissions.locked) + TStd::RegisterRoot(gc, rootEnv); + + + if(myEnv->permissions.canRegisterSqlite && !rootEnv->permissions.locked) + TStd::RegisterSqlite(gc, rootEnv); + + if(myEnv->permissions.canRegisterVM && !rootEnv->permissions.locked) + TStd::RegisterVM(gc, rootEnv); + if(myEnv->permissions.canRegisterProcess && !rootEnv->permissions.locked) + TStd::RegisterProcess(gc, rootEnv); + } + + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterClass") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterClass) && !rootEnv->permissions.locked) + TStd::RegisterClass(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + + if(key == "RegisterConsole") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked) + TStd::RegisterConsole(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterProcess") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterProcess) && !rootEnv->permissions.locked) + TStd::RegisterProcess(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterCrypto") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterCrypto) && !rootEnv->permissions.locked) + TStd::RegisterCrypto(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterDictionary") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterDictionary) && !rootEnv->permissions.locked) + TStd::RegisterDictionary(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterEnv") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterEnv) && !rootEnv->permissions.locked) + TStd::RegisterDictionary(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterIO") + { + bool r; + if(GetArgument(args,0,r)) + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterIO) && !rootEnv->permissions.locked) + TStd::RegisterIO(gc, rootEnv, myEnv->permissions.canRegisterLocalFS ? r : false); + } + cse.back()->Push(gc,nullptr); + return false; + + } + if(key == "RegisterJson") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterJSON) && !rootEnv->permissions.locked) + TStd::RegisterJson(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterNet") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterNet) && !rootEnv->permissions.locked) + TStd::RegisterNet(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterOGC") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterOGC) && !rootEnv->permissions.locked) + TStd::RegisterOGC(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterPath") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterPath) && !rootEnv->permissions.locked) + TStd::RegisterPath(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterRoot") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterRoot) && !rootEnv->permissions.locked) + TStd::RegisterRoot(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + + if(key == "RegisterSqlite") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterSqlite) && !rootEnv->permissions.locked) + TStd::RegisterSqlite(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + + if(key == "SetSqliteRoot") + { + Tesses::Framework::Filesystem::VFSPath p; + if(!rootEnv->permissions.locked) + { + if(GetArgumentAsPath(args,0,p)) + { + if(myEnv->permissions.sqlite3Scoped) + { + rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath / p.CollapseRelativeParents(); + rootEnv->permissions.sqlite3Scoped = true; + } + else + { + rootEnv->permissions.sqliteOffsetPath = p; + rootEnv->permissions.sqlite3Scoped = true; + } + } + else { + if(myEnv->permissions.sqlite3Scoped) + { + rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath; + rootEnv->permissions.sqlite3Scoped = true; + } + else + { + rootEnv->permissions.sqlite3Scoped = false; + } + } + } + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "RegisterVM") + { + if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterVM) && !rootEnv->permissions.locked) + TStd::RegisterVM(gc, rootEnv); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "LockRegister") + { + if(!rootEnv->permissions.locked) + { + rootEnv->permissions.locked=true; + } + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "GetDictionary") + { + + cse.back()->Push(gc,rootEnv->GetDictionary()); + return false; + } + if(key == "LoadFileWithDependencies") + { + std::shared_ptr vfs0; + TFile* f; + Tesses::Framework::Filesystem::VFSPath p; + if(GetArgument(args,0,vfs0) ) + { + if(GetArgumentHeap(args,1,f)) + { + rootEnv->LoadFileWithDependencies(gc,vfs0,f); + } + else if(GetArgumentAsPath(args,1,p)) + { + rootEnv->LoadFileWithDependencies(gc,vfs0,p); + } + } + cse.back()->Push(gc,nullptr); + return false; + } + } + if(subEnv != nullptr) + { + if(key == "GetDictionary") + { + cse.back()->Push(gc,subEnv->GetDictionary()); + return false; + } + } + + if(env != nullptr) + { + if(key == "Eval") + { + std::string str; + if(GetArgument(args,0,str)) + { + + + cse.back()->Push(gc,env->Eval(ls,str)); + return false; + } + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "GetRootEnvironment") + { + cse.back()->Push(gc,env->GetRootEnvironment()); + return false; + } + + if(key == "GetSubEnvironment") + { + cse.back()->Push(gc,env->GetSubEnvironment(ls)); + return false; + } + if(key == "GetParentEnvironment") + { + cse.back()->Push(gc,env->GetParentEnvironment()); + return false; + } + if(key == "GetVariable") + { + std::string key; + gc->BarrierBegin(); + if(GetArgument(args,0,key)) + cse.back()->Push(gc,env->GetVariable(key)); + gc->BarrierEnd(); + return false; + } + if(key == "SetVariable") + { + std::string key; + + gc->BarrierBegin(); + if(args.size() > 1 && GetArgument(args,0,key)) + { + if(env->HasConstForSet(key)) + { + gc->BarrierEnd(); + ThrowConstError(key); + } + + env->SetVariable(key,args[1]); + + } + gc->BarrierEnd(); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "DeclareVariable") + { + std::string key; + + gc->BarrierBegin(); + if(args.size() > 1 && GetArgument(args,0,key)) + { + if(env->HasConstForDeclare(key)) + { + gc->BarrierEnd(); + ThrowConstError(key); + } + env->DeclareVariable(key,args[1]); + + } + gc->BarrierEnd(); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "DeclareConstVariable") + { + std::string key; + + gc->BarrierBegin(); + if(args.size() > 1 && GetArgument(args,0,key)) + { + if(env->HasConstForDeclare(key)) + { + gc->BarrierEnd(); + ThrowConstError(key); + } + env->DeclareConstVariable(key,args[1]); + } + gc->BarrierEnd(); + cse.back()->Push(gc,nullptr); + return false; + } + if(key == "LoadFile") + { + TFile* f; + if(GetArgumentHeap(args,0,f)) + { + env->LoadFile(gc,f); + } + cse.back()->Push(gc,nullptr); + return false; + } + + cse.back()->Push(gc,nullptr); + return false; + } + + + + if(ittr != nullptr) + { + if(key == "MoveNext") + { + cse.back()->Push(gc, ittr->MoveNext(gc)); + return false; + } + cse.back()->Push(gc, nullptr); + return false; + } + + else if(bArray != nullptr) + { + if(key == "Count" || key == "Length") + { + int64_t len = (int64_t)bArray->data.size(); + if(len < 0) len = 0; + + cse.back()->Push(gc, len); + return false; + + } + if(key == "ToString") + { + cse.back()->Push(gc,std::string(bArray->data.begin(),bArray->data.end())); + return false; + } + if(key == "GetAt") + { + if(args.size() != 1) + { + throw VMException("ByteArray.GetAt must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("ByteArray.GetAt must only accept a long"); + } + + size_t index = (size_t)std::get(args[0]); + size_t sz = bArray->data.size(); + if(index >= 0 && index < sz) + { + cse.back()->Push(gc, (int64_t)bArray->data[index]); + return false; + } + + } + + if(key == "SetAt") + { + if(args.size() != 2) + { + throw VMException("ByteArray.SetAt must only accept two arguments"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("ByteArray.SetAt first argument must only accept a long"); + } + + uint8_t v = 0; + + if(std::holds_alternative(args[1])) + { + v = (uint8_t)(std::get(args[1]) & 0xFF); + } + + size_t index = (size_t)std::get(args[0]); + size_t sz = bArray->data.size(); + if(index >= 0 && index < sz) + { + bArray->data[index]=v; + return false; + } + + } + if(key == "ToCHeaderFile") + { + std::string name = "NONAME"; + GetArgument(args,0,name); + + cse.back()->Push(gc, Tesses::Framework::Text::GenerateCHeaderFile(bArray->data,name)); + return false; + } + if(key == "CopyTo") + { + //CopyTo(destBuff, offsetSrc, offsetDest, length) + + if(args.size() != 4) + { + throw VMException("ByteArray.CopyTo must only accept 4 arguments"); + } + + TByteArray* bArray2; + int64_t offsetSrc; + int64_t offsetDest; + int64_t count; + if(!GetArgumentHeap(args,0,bArray2)) + { + throw VMException("ByteArray.CopyTo first argument must be a ByteArray"); + } + if(!GetArgument(args,1, offsetSrc)) + { + throw VMException("ByteArray.CopyTo second argument must be a Long (offsetSrc)"); + } + if(!GetArgument(args,2, offsetDest)) + { + throw VMException("ByteArray.CopyTo third argument must be a Long (offsetDest)"); + } + if(!GetArgument(args,3,count)) + { + throw VMException("ByteArray.CopyTo fourth argument must be a Long (length)"); + } + size_t offsrc = (size_t)offsetSrc; + size_t offdest = (size_t)offsetDest; + size_t len = (size_t)count; + + if(offsrc > bArray->data.size()) + { + offsrc = bArray->data.size(); + } + + if(offdest > bArray2->data.size()) + { + offdest = bArray2->data.size(); + } + + len = std::min(std::min(bArray->data.size()-offsrc,bArray2->data.size()-offdest),len); + + if(len > 0) + memcpy(bArray2->data.data()+offdest,bArray->data.data()+offsrc,len); + cse.back()->Push(gc,bArray2); + return false; + } + if(key == "Insert") + { + if(args.size() != 4) + { + throw VMException("ByteArray.Insert must only accept 4 arguments"); + } + //Insert(offsetDest, buffer, offsetSrc, length) + TByteArray* bArray2; + int64_t offsetSrc; + int64_t offsetDest; + int64_t count; + if(!GetArgumentHeap(args,1,bArray2)) + { + throw VMException("ByteArray.Insert second argument must be a ByteArray"); + } + if(!GetArgument(args,0, offsetSrc)) + { + throw VMException("ByteArray.Insert first argument must be a Long (offsetSrc)"); + } + if(!GetArgument(args,2, offsetDest)) + { + throw VMException("ByteArray.Insert third argument must be a Long (offsetDest)"); + } + if(!GetArgument(args,3,count)) + { + throw VMException("ByteArray.Insert fourth argument must be a Long (length)"); + } + + size_t offsrc = (size_t)offsetSrc; + size_t offdest = (size_t)offsetDest; + size_t len = (size_t)count; + + if(offsrc > bArray->data.size()) + { + offsrc = bArray->data.size(); + } + if(offdest > bArray->data.size()) + { + offdest = bArray->data.size(); + } + + len = std::min(len,bArray2->data.size()-offsrc); + + + bArray->data.insert(bArray->data.begin()+offdest,bArray2->data.begin()+offsrc,bArray2->data.begin()+offsrc+len); + cse.back()->Push(gc, bArray); + return false; + } + if(key == "Append") + { + if(args.size() != 3) + { + throw VMException("ByteArray.Append must only accept 3 arguments"); + } + TByteArray* bArray2; + int64_t offset; + int64_t count; + if(!GetArgumentHeap(args,0,bArray2)) + { + throw VMException("ByteArray.Append first argument must be a ByteArray"); + } + if(!GetArgument(args,1, offset)) + { + throw VMException("ByteArray.Append second argument must be a Long (offset)"); + } + if(!GetArgument(args,2,count)) + { + throw VMException("ByteArray.Append third argument must be a Long (length)"); + } + size_t off = (size_t)offset; + size_t len = (size_t)count; + + if(off > bArray->data.size()) + { + off = bArray->data.size(); + } + + len = std::min(bArray->data.size() - off,len); + bArray->data.insert(bArray->data.end(),bArray2->data.begin()+off,bArray2->data.begin()+off+len); + cse.back()->Push(gc,bArray); + return false; + } + + if(key == "Resize") + { + if(args.size() != 1) + { + throw VMException("ByteArray.Resize must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("ByteArray.Resize must only accept a long"); + } + + size_t len = (size_t)std::get(args[0]); + if(len >= 0) + { + bArray->data.resize(len); + } + cse.back()->Push(gc, bArray); + return false; + } + if(key == "SetU16BE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + uint16_t number = (uint16_t)value; + BitConverter::FromUint16BE(bArray->data[(size_t)index],number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if(key == "SetU32BE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + uint32_t number = (uint32_t)value; + BitConverter::FromUint32BE(bArray->data[(size_t)index],number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if(key == "SetU64BE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + uint64_t number=0; + memcpy(&number, &value,sizeof(int64_t)); + BitConverter::FromUint64BE(bArray->data[(size_t)index],number); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "SetU16LE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + uint16_t number = (uint16_t)value; + BitConverter::FromUint16LE(bArray->data[(size_t)index],number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if(key == "SetU32LE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + uint32_t number = (uint32_t)value; + BitConverter::FromUint32LE(bArray->data[(size_t)index],number); + cse.back()->Push(gc, (int64_t)value); + return false; + } + } + if(key == "SetU64LE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + uint64_t number=0; + memcpy(&number, &value,sizeof(int64_t)); + BitConverter::FromUint64LE(bArray->data[(size_t)index],number); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "SetU16BE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + BitConverter::FromSint16BE(bArray->data[(size_t)index],(int16_t)value); + cse.back()->Push(gc, (int64_t)(int16_t)value); + return false; + } + } + if(key == "SetS32BE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + BitConverter::FromSint32BE(bArray->data[(size_t)index],(int32_t)value); + cse.back()->Push(gc,(int64_t)(int32_t) value); + return false; + } + } + if(key == "SetS64BE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + BitConverter::FromSint64BE(bArray->data[(size_t)index],value); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "SetS16LE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + BitConverter::FromSint16LE(bArray->data[(size_t)index],(int16_t)value); + cse.back()->Push(gc,(int64_t)(int16_t) value); + return false; + } + } + if(key == "SetS32LE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + BitConverter::FromSint32LE(bArray->data[(size_t)index],(int32_t)value); + cse.back()->Push(gc, (int64_t)(int32_t)value); + return false; + } + } + if(key == "SetS64LE") + { + int64_t index; + int64_t value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + BitConverter::FromSint64LE(bArray->data[(size_t)index],value); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "SetF32LE") + { + int64_t index; + double value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + BitConverter::FromFloatLE(bArray->data[(size_t)index],(float)value); + cse.back()->Push(gc, (double)(float)value); + return false; + } + } + if(key == "SetF64LE") + { + int64_t index; + double value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + BitConverter::FromDoubleLE(bArray->data[(size_t)index],value); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "SetF32BE") + { + int64_t index; + double value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + BitConverter::FromFloatBE(bArray->data[(size_t)index],(float)value); + cse.back()->Push(gc, (double)(float)value); + return false; + } + } + if(key == "SetF64BE") + { + int64_t index; + double value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + BitConverter::FromDoubleBE(bArray->data[(size_t)index],value); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "SetUuid") + { + int64_t index; + Tesses::Framework::Uuid value; + if(GetArgument(args,0,index) && GetArgument(args,1, value) && (size_t)index < bArray->data.size() && (size_t)index + 16 <= bArray->data.size()) + { + BitConverter::FromUuid(bArray->data[(size_t)index],value); + cse.back()->Push(gc, value); + return false; + } + } + + if(key == "GetU16BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToUint16BE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetU32BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToUint32BE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetU64BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + uint64_t value = BitConverter::ToUint64BE(bArray->data[(size_t)index]); + int64_t value2 = 0; + memcpy(&value2, &value, sizeof(uint64_t)); + cse.back()->Push(gc, value2); + return false; + } + } + if(key == "GetU16LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToUint16LE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetU32LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToUint32LE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetU64LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + uint64_t value = BitConverter::ToUint64LE(bArray->data[(size_t)index]); + int64_t value2 = 0; + memcpy(&value2, &value, sizeof(uint64_t)); + cse.back()->Push(gc, value2); + return false; + } + } + + if(key == "GetS16BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToSint16BE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetS32BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToSint32BE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetS64BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + int64_t value = BitConverter::ToSint64BE(bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetS16LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 2 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToSint16LE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetS32LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + int64_t value = (int64_t)BitConverter::ToSint32LE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetS64LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + int64_t value = BitConverter::ToSint64LE(bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + + if(key == "GetF32LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + double value = (double)BitConverter::ToFloatLE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetF64LE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + uint64_t value = BitConverter::ToDoubleLE(bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetF32BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 4 <= bArray->data.size()) + { + double value = (double)BitConverter::ToFloatBE(bArray->data[(size_t)index]); + cse.back()->Push(gc, value); + return false; + } + } + if(key == "GetF64BE") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 8 <= bArray->data.size()) + { + uint64_t value = BitConverter::ToDoubleBE(bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + + if(key == "GetUuid") + { + int64_t index; + if(GetArgument(args,0,index) && (size_t)index < bArray->data.size() && (size_t)index + 16 <= bArray->data.size()) + { + auto value = BitConverter::ToUuid(bArray->data[(size_t)index]); + + cse.back()->Push(gc, value); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(aArray != nullptr) + { + if(key == "ToString") + { + cse.back()->Push(gc,ToString(gc,aArray)); + return false; + } + else if(key == "GetAt") + { + if(args.size() != 1) + { + throw VMException("AArray.GetAt must only accept one argument"); + } + cse.back()->Push(gc, aArray->Get(gc,args[0])); + return false; + } + else if(key == "SetAt") + { + if(args.size() != 2) + { + throw VMException("AArray.SetAt must only accept two arguments"); + } + aArray->Set(gc,args[0],args[1]); + cse.back()->Push(gc, args[1]); + return false; + } + else if(key == "GetKey") + { + if(args.size() != 1) + { + throw VMException("AArray.GetKey must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("AArray.GetKey must only accept a long"); + } + + gc->BarrierBegin(); + auto res = aArray->GetKey(std::get(args[0])); + gc->BarrierEnd(); + cse.back()->Push(gc, res); + return false; + } + else if(key == "GetValue") + { + if(args.size() != 1) + { + throw VMException("AArray.GetValue must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("AArray.GetValue must only accept a long"); + } + + gc->BarrierBegin(); + auto res = aArray->GetValue(std::get(args[0])); + gc->BarrierEnd(); + cse.back()->Push(gc, res); + return false; + } + else if(key == "SetKey") + { + if(args.size() != 2) + { + throw VMException("AArray.SetKey must only accept two arguments"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("AArray.SetKey first argument must only accept a long"); + } + + gc->BarrierBegin(); + aArray->SetKey(std::get(args[0]),args[1]); + gc->BarrierEnd(); + cse.back()->Push(gc, args[1]); + return false; + } + else if(key == "SetValue") + { + if(args.size() != 2) + { + throw VMException("AArray.SetValue must only accept two arguments"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("AArray.SetValue first argument must only accept a long"); + } + + gc->BarrierBegin(); + aArray->SetValue(std::get(args[0]),args[1]); + gc->BarrierEnd(); + cse.back()->Push(gc, args[1]); + return false; + } + else if(key == "Count" || key == "Length") + { + gc->BarrierBegin(); + cse.back()->Push(gc, aArray->Count()); + gc->BarrierEnd(); + return false; + } + else if(key == "GetEnumerator") + { + + cse.back()->Push(gc,TAssociativeArrayEnumerator::Create(ls,aArray)); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + else if(list != nullptr) + { + + if(key == "GetEnumerator") + { + cse.back()->Push(gc, TListEnumerator::Create(ls,list)); + return false; + } + else if(key == "ToString") + { + + cse.back()->Push(gc,Json_Encode(list)); + return false; + + } + else if(key == "Insert") + { + if(args.size() != 2) + { + throw VMException("List.Insert must only accept two arguments"); + } + int64_t index; + + if(!GetArgument(args,0,index)) + { + throw VMException("List.Insert first argument must be Long"); + } + + gc->BarrierBegin(); + list->Insert(index,args[1]); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } + else if(key == "Add") + { + if(args.size() != 1) + { + throw VMException("List.Add must only accept one argument"); + } + gc->BarrierBegin(); + list->Add(args[0]); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } + else if(key == "Contains") + { + if(args.size() != 1) + { + throw VMException("List.Contains must only accept one argument"); + } + gc->BarrierBegin(); + for(int64_t i = 0; i < list->Count(); i++) + { + auto item = list->Get(i); + gc->BarrierEnd(); + if(Equals(gc,args[0],item)) + { + cse.back()->Push(gc, true); + return false; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, false); + return false; + } + else if(key == "IndexOf") + { + //IndexOf(obj, $idx) + if(args.size() < 1 || args.size() > 2) + { + throw VMException("List.IndexOf must either have one or two arguments"); + } + + int64_t i=0; + + GetArgument(args,1,i); + gc->BarrierBegin(); + for(; i < list->Count(); i++) + { + auto item = list->Get(i); + gc->BarrierEnd(); + if(Equals(gc,args[0],item)) + { + + cse.back()->Push(gc,i); + return false; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc,(int64_t)-1); + return false; + } + else if(key == "RemoveAllEqual") + { + if(args.size() != 1) + { + throw VMException("List.RemoveAllEqual must only accept one argument"); + } + + + gc->BarrierBegin(); + for(int64_t i = 0; i < list->Count(); i++) + { + auto item = list->Get(i); + gc->BarrierEnd(); + if(Equals(gc,args[0],item)) + { + gc->BarrierBegin(); + list->RemoveAt(i); + i--; + }else gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } + else if(key == "Remove") + { + if(args.size() != 1) + { + throw VMException("List.Remove must only accept one argument"); + } + + + gc->BarrierBegin(); + for(int64_t i = 0; i < list->Count(); i++) + { + auto item = list->Get(i); + gc->BarrierEnd(); + if(Equals(gc,args[0],item)) + { + gc->BarrierBegin(); + list->RemoveAt(i); + gc->BarrierEnd(); + break; + } + gc->BarrierBegin(); + } + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } + else if(key == "RemoveAt") + { + if(args.size() != 1) + { + throw VMException("List.RemoveAt must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("List.RemoveAt must only accept a long"); + } + gc->BarrierBegin(); + list->RemoveAt(std::get(args[0])); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } + else if(key == "Clear") + { + gc->BarrierBegin(); + list->Clear(); + gc->BarrierEnd(); + cse.back()->Push(gc, Undefined()); + return false; + } + else if(key == "GetAt") + { + if(args.size() != 1) + { + throw VMException("List.GetAt must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("List.GetAt must only accept a long"); + } + + int64_t index = std::get(args[0]); + if(index >= 0 && index < list->Count()) + { + cse.back()->Push(gc, list->Get(index)); + return false; + } + + } + else if(key == "SetAt") + { + if(args.size() != 2) + { + throw VMException("List.SetAt must only accept two arguments"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("List.SetAt first argument must only accept a long"); + } + + int64_t index = std::get(args[0]); + if(index >= 0 && index < list->Count()) + { + list->Set(index,args[1]); + return false; + } + + } + + else if(key == "Count" || key == "Length") + { + gc->BarrierBegin(); + cse.back()->Push(gc, list->Count()); + gc->BarrierEnd(); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(dynList != nullptr) + { + + if(key == "GetEnumerator") + { + cse.back()->Push(gc, TDynamicListEnumerator::Create(ls, dynList)); + return false; + } + else if(key == "ToString") + { + cse.back()->Push(gc, dynList->ToString(ls)); + return false; + } + else if(key == "Insert") + { + if(args.size() != 2) + { + throw VMException("List.Insert must only accept two arguments"); + } + int64_t index; + + if(!GetArgument(args,0,index)) + { + throw VMException("List.Insert first argument must be Long"); + } + + cse.back()->Push(gc, dynList->Insert(ls,index,args[0])); + return false; + } + if(key == "Add") + { + if(args.size() != 1) + { + throw VMException("List.Add must only accept one argument"); + } + + cse.back()->Push(gc,dynList->Add(ls,args[0])); + return false; + } + if(key == "RemoveAllEqual") + { + if(args.size() != 1) + { + throw VMException("List.RemoveAllEqual must only accept one argument"); + } + + cse.back()->Push(gc,dynList->RemoveAllEqual(ls, args[0])); + return false; + } + if(key == "Remove") + { + if(args.size() != 1) + { + throw VMException("List.Remove must only accept one argument"); + } + + + + cse.back()->Push(gc,dynList->Remove(ls, args[0])); + return false; + } + if(key == "RemoveAt") + { + if(args.size() != 1) + { + throw VMException("List.RemoveAt must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("List.RemoveAt must only accept a long"); + } + cse.back()->Push(gc,dynList->RemoveAt(ls,std::get(args[0]))); + + return false; + } + if(key == "Clear") + { + + + cse.back()->Push(gc, dynList->Clear(ls)); + return false; + } + if(key == "GetAt") + { + if(args.size() != 1) + { + throw VMException("List.GetAt must only accept one argument"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("List.GetAt must only accept a long"); + } + + int64_t index = std::get(args[0]); + if(index >= 0) + { + cse.back()->Push(gc, dynList->GetAt(ls,index)); + return false; + } + + } + if(key == "SetAt") + { + if(args.size() != 2) + { + throw VMException("List.SetAt must only accept two arguments"); + } + + if(!std::holds_alternative(args[0])) + { + throw VMException("List.SetAt first argument must only accept a long"); + } + + int64_t index = std::get(args[0]); + if(index >= 0) + { + cse.back()->Push(gc,dynList->SetAt(ls,index,args[1])); + return false; + } + + } + + if(key == "Count" || key == "Length") + { + cse.back()->Push(gc, dynList->Count(ls)); + + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(cls != nullptr) + { + gc->BarrierBegin(); + auto obj=cls->GetValue(cse.back()->callable->className,key); + gc->BarrierEnd(); + TClosure* clos; + TCallable* callable; + if(GetObjectHeap(obj,clos)) + { + this->AddCallStackEntry(ls,clos,args); + return true; + } + else if(GetObjectHeap(obj,callable)) + { + cse.back()->Push(gc,callable->Call(ls,args)); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + else if(dict != nullptr) + { + if(key == "ToString" && !dict->MethodExists(ls, key) && args.empty()) + { + cse.back()->Push(gc,Json_Encode(dict)); + return false; + } + gc->BarrierBegin(); + auto o = dict->GetValue(key); + gc->BarrierEnd(); + + + return InvokeMethod(ls,o,dict,args); + } + else if(dynDict != nullptr) + { + + + cse.back()->Push(gc,dynDict->CallMethod(ls, key, args)); + + return false; + } + else if(callable != nullptr) + { + if(key == "Call") + { + TList* argls; + if(GetArgumentHeap(args,0,argls)) + { + TClosure* clo = dynamic_cast(callable); + if(clo != nullptr) + { + AddCallStackEntry(ls,clo,argls->items); + return true; + } + else + { + cse.back()->Push(gc,callable->Call(ls, argls->items)); + return false; + } + } + } + cse.back()->Push(gc,nullptr); + return false; + } + else + { + cse.back()->Push(gc, Undefined()); + } + } + else + { + cse.back()->Push(gc,Undefined()); + } + } + + + return false; + } +} \ No newline at end of file diff --git a/src/vm/bc/getfield.cpp b/src/vm/bc/getfield.cpp new file mode 100644 index 0000000..8e17940 --- /dev/null +++ b/src/vm/bc/getfield.cpp @@ -0,0 +1,769 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include +namespace Tesses::CrossLang { + bool InterperterThread::GetField(GC* gc) + { + std::vector& cse=this->call_stack_entries; + + if(!cse.empty()) + { + auto stk = cse.back(); + GCList ls(gc); + TObject _key = stk->Pop(ls); + + + TObject instance = stk->Pop(ls); + + if(!std::holds_alternative(_key)) + { + stk->Push(gc,Undefined()); + return false; + } + + std::string key = std::get(_key); + + + if(std::holds_alternative(instance)) + { + std::string str = std::get(instance); + + if(key == "Count" || key == "Length") + { + int64_t len = (int64_t)str.size(); + if(len < 0) len = 0; + + cse.back()->Push(gc, len); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto vfs = std::get>(instance); + auto tmpFS=std::dynamic_pointer_cast(vfs); + if(tmpFS) + { + if(key == "TempDirectoryName") + { + + cse.back()->Push(gc,tmpFS->TempDirectoryName()); + return false; + } + } + cse.back()->Push(gc,Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto writer = std::get>(instance); + auto stringWriter = std::dynamic_pointer_cast(writer); + if(stringWriter != nullptr) + { + if(key == "Text") + { + cse.back()->Push(gc, stringWriter->GetString()); + return false; + } + } + if(key == "NewLine") + { + cse.back()->Push(gc,writer->newline); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto br = std::get>(instance); + if(key == "Stream") + { + cse.back()->Push(gc,br->GetStream()); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto bw = std::get>(instance); + if(key == "Stream") + { + + cse.back()->Push(gc,bw->GetStream()); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto strm = std::get>(instance); + if(strm != nullptr) + { + auto netStrm = std::dynamic_pointer_cast(strm); + + if(key == "CanRead") + { + + + cse.back()->Push(gc, strm->CanRead()); + return false; + } + if(key == "CanWrite") + { + + cse.back()->Push(gc, strm->CanWrite()); + return false; + } + if(key == "CanSeek") + { + + + cse.back()->Push(gc, strm->CanSeek()); + return false; + } + if(key == "EndOfStream") + { + + cse.back()->Push(gc, strm->EndOfStream()); + return false; + } + if(key == "Length") + { + + cse.back()->Push(gc, strm->GetLength()); + return false; + } + if(key == "Position") + { + + cse.back()->Push(gc, strm->GetPosition()); + return false; + } + + if(netStrm != nullptr) + { + if(key == "Port") + { + cse.back()->Push(gc, netStrm->GetPort()); + return false; + } + } + + cse.back()->Push(gc, Undefined()); + + return false; + + } + } + if(std::holds_alternative(instance)) + { + TVMVersion& version = std::get(instance); + if(key == "Major") + { + stk->Push(gc, (int64_t)version.Major()); + return false; + } + if(key == "Minor") + { + stk->Push(gc, (int64_t)version.Minor()); + return false; + } + if(key == "Patch") + { + stk->Push(gc, (int64_t)version.Patch()); + return false; + } + if(key == "Build") + { + stk->Push(gc, (int64_t)version.Build()); + return false; + } + if(key == "VersionInt") + { + stk->Push(gc,(int64_t)version.AsLong()); + return false; + } + if(key == "Stage") + { + switch(version.VersionStage()) + { + case TVMVersionStage::DevVersion: + stk->Push(gc,"dev"); + break; + case TVMVersionStage::AlphaVersion: + stk->Push(gc,"alpha"); + break; + case TVMVersionStage::BetaVersion: + stk->Push(gc,"beta"); + break; + case TVMVersionStage::ProductionVersion: + stk->Push(gc,"prod"); + break; + } + return false; + } + + stk->Push(gc, Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto time = std::get>(instance); + if(key == "Days") + { + stk->Push(gc, (int64_t)time->Days()); + return false; + } + if(key == "Hours") + { + stk->Push(gc, (int64_t)time->Hours()); + return false; + } + + if(key == "Minutes") + { + stk->Push(gc, (int64_t)time->Minutes()); + return false; + } + if(key == "Seconds") + { + stk->Push(gc, (int64_t)time->Seconds()); + return false; + } + + if(key == "TotalHours") + { + stk->Push(gc, time->TotalHours()); + return false; + } + + if(key == "TotalMinutes") + { + stk->Push(gc, time->TotalMinutes()); + return false; + } + + if(key == "TotalSeconds") + { + stk->Push(gc, time->TotalSeconds()); + return false; + } + + stk->Push(gc, Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto& date = std::get>(instance); + if(key == "IsLocal") + { + stk->Push(gc, date->IsLocal()); + return false; + } + if(key == "Year") + { + stk->Push(gc, (int64_t)date->Year()); + return false; + } + if(key == "Month") + { + stk->Push(gc, (int64_t)date->Month()); + return false; + } + if(key == "Day") + { + stk->Push(gc, (int64_t)date->Day()); + return false; + } + if(key == "Hour") + { + stk->Push(gc, (int64_t)date->Hour()); + return false; + } + if(key == "Minute") + { + stk->Push(gc, (int64_t)date->Minute()); + return false; + } + if(key == "Second") + { + stk->Push(gc, (int64_t)date->Second()); + return false; + } + if(key == "DayOfWeek") + { + stk->Push(gc, (int64_t)date->DayOfWeek()); + return false; + } + + stk->Push(gc, Undefined()); + return false; + } + if(std::holds_alternative(instance)) + { + auto obj = std::get(instance).obj; + auto bA = dynamic_cast(obj); + auto list = dynamic_cast(obj); + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto dynList = dynamic_cast(obj); + auto tcallable = dynamic_cast(obj); + auto closure = dynamic_cast(obj); + auto externalMethod = dynamic_cast(obj); + auto ittr = dynamic_cast(obj); + + auto callstackEntry = dynamic_cast(obj); + auto file = dynamic_cast(obj); + auto chunk = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + auto aarray = dynamic_cast(obj); + auto task = dynamic_cast(obj); + if(task != nullptr) + { + if(key == "IsCompleted") + { + cse.back()->Push(gc,task->IsCompleted()); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + if(aarray != nullptr) + { + if(key == "Count" || key == "Length") + { + cse.back()->Push(gc,aarray->Count()); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + else if(cls != nullptr) + { + gc->BarrierBegin(); + auto obj=cls->GetValue(cse.back()->callable->className,"get"+key); + gc->BarrierEnd(); + TClosure* clos; + TCallable* callable; + if(GetObjectHeap(obj,clos)) + { + this->AddCallStackEntry(ls,clos,{}); + return true; + } + else if(GetObjectHeap(obj,callable)) + { + cse.back()->Push(gc,callable->Call(ls,{})); + return false; + } + cse.back()->Push(gc,cls->GetValue(cse.back()->callable->className,key)); + return false; + + } + else + if(natObj != nullptr) + { + cse.back()->Push(gc,natObj->CallMethod(ls,"get"+key,{})); + return false; + } + + if(file != nullptr) + { + if(key == "Version") + { + cse.back()->Push(gc,file->version); + return false; + } + else if(key == "Name") + { + cse.back()->Push(gc,file->name); + return false; + } + else if(key == "Info") + { + cse.back()->Push(gc, file->info); + return false; + } + else if(key == "Dependencies") + { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for(auto item : file->dependencies) + { + auto res = TDictionary::Create(ls); + res->SetValue("Name", item.first); + res->SetValue("Version", item.second); + list->Add(res); + } + gc->BarrierEnd(); + cse.back()->Push(gc, list); + return false; + } + else if(key == "Tools") + { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for(auto item : file->tools) + { + auto res = TDictionary::Create(ls); + res->SetValue("Name", item.first); + res->SetValue("Version", item.second); + list->Add(res); + } + gc->BarrierEnd(); + cse.back()->Push(gc, list); + return false; + } + else if(key == "Strings") + { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for(auto item : file->name) + { + list->Add(item); + } + gc->BarrierEnd(); + + cse.back()->Push(gc, list); + return false; + } + else if(key == "MetadataCount") + { + + cse.back()->Push(gc, (int64_t)file->metadata.size()); + return false; + } + else if(key == "Metadata") + { + TList* meta = TList::Create(ls); + gc->BarrierBegin(); + for(size_t i = 0; i < file->metadata.size(); i++) + { + meta->Add( + TDictionary::Create(ls, + { + TDItem("Name", file->metadata[i].first), + TDItem("Index",(int64_t)i) + } + ) + ); + } + gc->BarrierEnd(); + + cse.back()->Push(gc, meta); + return false; + } + else if(key == "Sections") + { + TList* sections = TList::Create(ls); + gc->BarrierBegin(); + for(auto& item : file->sections) + { + TByteArray* ba = TByteArray::Create(ls); + ba->data = item.second; + sections->Add(TDictionary::Create(ls,{ + TDItem("Name", item.first), + TDItem("Data", ba) + })); + } + gc->BarrierEnd(); + + cse.back()->Push(gc, sections); + return false; + } + else if(key == "SupportedVMs") + { + TList* supported = TList::Create(ls); + gc->BarrierBegin(); + if(file->vms.empty()) + { + supported->Add(TDictionary::Create(ls,{ + TDItem("Name",std::string(VMName)), + TDItem("HowToGet",std::string(VMHowToGet)) + })); + } + else { + for(auto item : file->vms) + supported->Add(TDictionary::Create(ls,{ + TDItem("Name",item.first), + TDItem("HowToGet",item.second) + })); + } + gc->BarrierEnd(); + cse.back()->Push(gc, supported); + return false; + } + else if(key == "Chunks") + { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for(auto item : file->chunks) + { + list->Add(item); + } + + gc->BarrierEnd(); + + cse.back()->Push(gc, list); + return false; + } + else if(key == "Classes") + { + auto list = TList::Create(ls); + gc->BarrierBegin(); + + for(uint32_t i = 0; i < (uint32_t)file->classes.size(); i++) + { + list->Add(GetClassInfo(ls,file,i)); + } + + cse.back()->Push(gc, list); + gc->BarrierEnd(); + return false; + } + else if(key == "Functions") + { + auto list = TList::Create(ls); + gc->BarrierBegin(); + for(auto& item : file->functions) + { + TDictionary* dict = TDictionary::Create(ls); + if(!item.first.empty()) + dict->SetValue("Documentation", item.first[0]); + TList* nameParts = TList::Create(ls); + for(size_t i = 1; i < item.first.size(); i++) + { + nameParts->Add(item.first[i]); + } + dict->SetValue("NameParts", nameParts); + dict->SetValue("ChunkId", (int64_t)item.second); + + list->Add(dict); + } + + cse.back()->Push(gc, list); + gc->BarrierEnd(); + return false; + } + else if(key == "Icon") + { + if(file->icon >= 0 && file->icon < file->resources.size()) + { + TByteArray* ba = TByteArray::Create(ls); + ba->data = file->resources[file->icon]; + cse.back()->Push(gc, ba); + return false; + } + else { + cse.back()->Push(gc, nullptr); + return false; + } + } + cse.back()->Push(gc, Undefined()); + return false; + } + if(chunk != nullptr) + { + if(key == "Arguments") + { + auto myargs = TList::Create(ls); + gc->BarrierBegin(); + for(auto item : chunk->args) + { + myargs->Add(item); + } + gc->BarrierEnd(); + cse.back()->Push(gc, myargs); + return false; + } + if(key == "Code") + { + auto ba = TByteArray::Create(ls); + ba->data = chunk->code; + cse.back()->Push(gc, ba); + return false; + } + if(key == "File") + { + cse.back()->Push(gc, chunk->file); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if(callstackEntry != nullptr) + { + if(key == "IP") + { + cse.back()->Push(gc, (int64_t)callstackEntry->ip); + return false; + } + if(key == "IsDone") + { + cse.back()->Push(gc, callstackEntry->ip >= callstackEntry->callable->closure->code.size()); + return false; + } + if(key == "Closure") + { + cse.back()->Push(gc, callstackEntry->callable); + return false; + } + if(key == "StackEmpty") + { + cse.back()->Push(gc, callstackEntry->stack.empty()); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + + + + + if(ittr != nullptr) + { + if(key == "Current") + { + cse.back()->Push(gc, ittr->GetCurrent(ls)); + return false; + } + cse.back()->Push(gc, Undefined()); + return false; + } + if(closure != nullptr) + { + if(key == "Arguments") + { + GCList ls2(gc); + TList* ls = TList::Create(ls2); + for(auto arg : closure->closure->args) + { + ls->Add(arg); + } + cse.back()->Push(gc,ls); + return false; + } + if(key == "File") + { + cse.back()->Push(gc,closure->file); + return false; + } + } + if(externalMethod != nullptr) + { + if(key == "Arguments") + { + GCList ls2(gc); + TList* ls = TList::Create(ls2); + for(auto arg : externalMethod->args) + { + ls->Add(arg); + } + cse.back()->Push(gc,ls); + return false; + } + } + + if(tcallable != nullptr) + { + if(key == "Documentation") + { + cse.back()->Push(gc, tcallable->documentation); + return false; + } + if(key == "Tag") + { + gc->BarrierBegin(); + cse.back()->Push(gc, tcallable->tag); + gc->BarrierEnd(); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + + if(bA != nullptr) + { + if(key == "Count" || key == "Length") + { + int64_t len = (int64_t)bA->data.size(); + if(len < 0) len = 0; + + stk->Push(gc, len); + return false; + } + } + if(list != nullptr) + { + if(key == "Count" || key == "Length") + { + int64_t len = list->Count(); + if(len < 0) len = 0; + + stk->Push(gc, len); + return false; + } + } + if(dynList != nullptr) + { + if(key == "Count" || key == "Length") + { + int64_t len = dynList->Count(ls); + if(len < 0) len = 0; + + stk->Push(gc, len); + return false; + } + } + if(dynDict != nullptr) + { + if(dynDict->MethodExists(ls,"get" + key)) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"get" + key, {})); + } + else + { + cse.back()->Push(gc, dynDict->GetField(ls,key)); + } + return false; + } + + if(dict != nullptr) + { + gc->BarrierBegin(); + TObject fn = dict->GetValue("get" + key); + gc->BarrierEnd(); + if(std::holds_alternative(fn) && dynamic_cast(std::get(fn).obj) != nullptr) + { + return InvokeOne(ls,fn, dict); + } + else + { + gc->BarrierBegin(); + fn = dict->GetValue(key); + stk->Push(gc, fn); + gc->BarrierEnd(); + return false; + } + } + + } + + stk->Push(gc, Undefined()); + } + + return false; + } +} \ No newline at end of file diff --git a/src/vm/bc/invokemethod.cpp b/src/vm/bc/invokemethod.cpp new file mode 100644 index 0000000..46b726f --- /dev/null +++ b/src/vm/bc/invokemethod.cpp @@ -0,0 +1,54 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace Tesses::CrossLang { + + bool InterperterThread::InvokeMethod(GCList& ls, TObject fn, TObject instance, std::vector args) + { + + if(std::holds_alternative(fn)) + { + + auto obj = dynamic_cast(std::get(fn).obj); + if(obj != nullptr) + { + auto closure = dynamic_cast(obj); + if(closure != nullptr) + { + + if(!closure->closure->args.empty() && closure->closure->args[0] == "this") + { + std::vector args2; + args2.push_back(instance); + args2.insert(args2.end(), args.begin(),args.end()); + this->AddCallStackEntry(ls,closure,args2); + } + else + { + this->AddCallStackEntry(ls,closure,args); + } + + } + else + { + auto val = obj->Call(ls,args); + this->call_stack_entries.back()->Push(ls.GetGC(), val); + return false; + } + return true; + } + + } + this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); + return false; + } +} \ No newline at end of file diff --git a/src/vm/bc/invoketwo.cpp b/src/vm/bc/invoketwo.cpp new file mode 100644 index 0000000..8f97d5b --- /dev/null +++ b/src/vm/bc/invoketwo.cpp @@ -0,0 +1,47 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include +namespace Tesses::CrossLang { + bool InterperterThread::InvokeTwo(GCList& ls, TObject fn, TObject left, TObject right) + { + if(std::holds_alternative(fn)) + { + + auto obj = dynamic_cast(std::get(fn).obj); + if(obj != nullptr) + { + auto closure = dynamic_cast(obj); + if(closure != nullptr) + { + + if(!closure->closure->args.empty() && closure->closure->args[0] == "this") + { + this->AddCallStackEntry(ls,closure,{left,right}); + } + else + { + this->AddCallStackEntry(ls,closure,{right}); + } + + } + else + { + this->call_stack_entries[this->call_stack_entries.size()-1]->Push(ls.GetGC(), obj->Call(ls,{right})); + + return false; + } + return true; + } + + } + return false; + } +} \ No newline at end of file diff --git a/src/vm/bc/setfield.cpp b/src/vm/bc/setfield.cpp new file mode 100644 index 0000000..1e4cf68 --- /dev/null +++ b/src/vm/bc/setfield.cpp @@ -0,0 +1,278 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include +namespace Tesses::CrossLang { + + bool InterperterThread::SetField(GC* gc) + { + std::vector& cse=this->call_stack_entries; + + if(!cse.empty()) + { + auto stk = cse.back(); + GCList ls(gc); + TObject value = stk->Pop(ls); + TObject _key = stk->Pop(ls); + TObject instance = stk->Pop(ls); + + if(!std::holds_alternative(_key)) + { + stk->Push(gc,Undefined()); + return false; + } + + std::string key = std::get(_key); + if(std::holds_alternative>(instance)) + { + auto writer = std::get>(instance); + auto stringWriter = std::dynamic_pointer_cast(writer); + if(stringWriter != nullptr) + { + if(key == "Text") + { + if(std::holds_alternative(value)) + { + stringWriter->GetString() = std::get(value); + } + cse.back()->Push(gc, stringWriter->GetString()); + return false; + } + } + if(key == "NewLine") + { + if(std::holds_alternative(value)) + { + writer->newline = std::get(value); + } + cse.back()->Push(gc,writer->newline); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto svr = std::get>(instance); + auto bas = std::dynamic_pointer_cast(svr); + auto cgi = std::dynamic_pointer_cast(svr); + auto changable = std::dynamic_pointer_cast(svr); + if(changable != nullptr) + { + if(key == "Server") + { + bas->server = ToHttpServer(gc,value); + stk->Push(gc,value); + return false; + } + } + + if(bas != nullptr) + { + if(key == "Realm") + { + bool val; + if(GetObject(value,val)) + { + bas->realm = val; + stk->Push(gc,val ); + + return false; + } + } + if(key == "Server") + { + bas->server = ToHttpServer(gc,value); + stk->Push(gc,value); + return false; + } + if(key == "Authorization") + { + TCallable* val; + if(GetObjectHeap(value,val)) + { + auto marked= CreateMarkedTObject(ls, val); + bas->authorization = [marked](std::string user,std::string password)->bool { + GCList ls(marked->GetGC()); + TCallable* callable; + if(GetObjectHeap(marked->GetObject(), callable)) + { + return ToBool(callable->Call(ls,{user,password})); + } + return false; + }; + stk->Push(gc,val); + + return false; + } + } + } + + if(cgi != nullptr) + { + if(key == "WorkingDirectory") + { + Tesses::Framework::Filesystem::VFSPath path; + if(GetObjectAsPath(value,path)) + { + cgi->workingDirectory = path; + stk->Push(gc,path); + return false; + } + else { + cgi->workingDirectory = std::nullopt; + stk->Push(gc,nullptr); + return false; + } + + } + if(key == "DocumentRoot") + { + Tesses::Framework::Filesystem::VFSPath path; + if(GetObjectAsPath(value,path)) + { + cgi->document_root= path; + stk->Push(gc,path); + return false; + } + else { + cgi->document_root= std::nullopt; + stk->Push(gc,nullptr); + return false; + } + + } + if(key == "AdminEmail") + { + std::string str; + if(GetObject(value,str)) + { + cgi->adminEmail = str; + stk->Push(gc,str); + return false; + } + else { + cgi->adminEmail= std::nullopt; + stk->Push(gc,nullptr); + return false; + } + + } + } + + stk->Push(gc, Undefined()); + return false; + } + if(std::holds_alternative>(instance)) + { + auto strm = std::get>(instance); + + auto netStrm = std::dynamic_pointer_cast(strm); + if(netStrm != nullptr) + { + bool bc; + if(key == "Broadcast" && GetObject(value,bc)) + netStrm->SetBroadcast(bc); + if(key == "NoDelay" && GetObject(value,bc)) + netStrm->SetNoDelay(bc); + } + stk->Push(gc, Undefined()); + return false; + } + if(std::holds_alternative(instance)) + { + auto obj = std::get(instance).obj; + + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + if(cls != nullptr) + { + gc->BarrierBegin(); + auto obj=cls->GetValue(cse.back()->callable->className,"set"+key); + gc->BarrierEnd(); + TClosure* clos; + TCallable* callable; + if(GetObjectHeap(obj,clos)) + { + this->AddCallStackEntry(ls,clos,{value}); + return true; + } + else if(GetObjectHeap(obj,callable)) + { + cse.back()->Push(gc,callable->Call(ls,{value})); + return false; + } + gc->BarrierBegin(); + cls->SetValue(cse.back()->callable->className,key,value); + gc->BarrierEnd(); + cse.back()->Push(gc,value); + return false; + + } + else + if(natObj != nullptr) + { + cse.back()->Push(gc,natObj->CallMethod(ls,"set"+key,{value})); + return false; + } + auto tcallable = dynamic_cast(obj); + if(tcallable != nullptr) + { + if(key == "Tag") + { + gc->BarrierBegin(); + tcallable->tag = value; + gc->BarrierEnd(); + cse.back()->Push(gc,nullptr); + return false; + } + } + if(dynDict != nullptr) + { + if(dynDict->MethodExists(ls,"set" + key)) + { + cse.back()->Push(gc,dynDict->CallMethod(ls,"set" + key, {value})); + } + else + { + dynDict->SetField(ls,key,value); + cse.back()->Push(gc,value); + } + return false; + } + if(dict != nullptr) + { + gc->BarrierBegin(); + TObject fn = dict->GetValue("set" + key); + gc->BarrierEnd(); + if(std::holds_alternative(fn) && dynamic_cast(std::get(fn).obj) != nullptr) + { + return InvokeTwo(ls,fn, dict, value); + } + else + { + gc->BarrierBegin(); + dict->SetValue(key, value); + stk->Push(gc, value); + gc->BarrierEnd(); + return false; + } + } + + } + stk->Push(gc, Undefined()); + + } + return false; + } + +} \ No newline at end of file diff --git a/src/vm/bc/sub.cpp b/src/vm/bc/sub.cpp new file mode 100644 index 0000000..4d59677 --- /dev/null +++ b/src/vm/bc/sub.cpp @@ -0,0 +1,121 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include +namespace Tesses::CrossLang { + bool InterperterThread::Sub(GC* gc) + { + std::vector& cse=this->call_stack_entries; + GCList ls(gc); + auto right = cse.back()->Pop(ls); + auto left = cse.back()->Pop(ls); + + if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) - std::get(right)); + } + + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) - std::get(right)); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) - std::get(right)); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc,std::get(left) - std::get(right)); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); + } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); + } + else if(std::holds_alternative>(left) && std::holds_alternative>(right)) + { + auto& l = std::get>(left); + auto& r = std::get>(right); + cse.back()->Push(gc,std::make_shared((*l) - (*r))); + } + else if(std::holds_alternative>(left) && std::holds_alternative>(right)) + { + auto& l = std::get>(left); + auto& r = std::get>(right); + cse.back()->Push(gc,std::make_shared((*l) - (*r))); + } + else if(std::holds_alternative(left)) + { + auto obj = std::get(left).obj; + auto dict = dynamic_cast(obj); + auto dynDict = dynamic_cast(obj); + + auto natObj = dynamic_cast(obj); + + + auto cls = dynamic_cast(obj); + if(cls != nullptr) + { + gc->BarrierBegin(); + auto obj=cls->GetValue(cse.back()->callable->className,"operator-"); + gc->BarrierEnd(); + TClosure* clos; + TCallable* callable; + if(GetObjectHeap(obj,clos)) + { + this->AddCallStackEntry(ls,clos,{right}); + return true; + } + else if(GetObjectHeap(obj,callable)) + { + cse.back()->Push(gc,callable->Call(ls,{right})); + return false; + } + cse.back()->Push(gc,Undefined()); + return false; + + } + else if(natObj != nullptr) + { + cse.back()->Push(gc, natObj->CallMethod(ls,"operator-",{right})); + return false; + } + else if(dict != nullptr) + { + gc->BarrierBegin(); + TObject fn = dict->GetValue("operator-"); + 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()); + } + + } + else + { + cse.back()->Push(gc, Undefined()); + } + return false; + } +} \ No newline at end of file diff --git a/src/vm/bc/tobool.cpp b/src/vm/bc/tobool.cpp new file mode 100644 index 0000000..574f83c --- /dev/null +++ b/src/vm/bc/tobool.cpp @@ -0,0 +1,106 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace Tesses::CrossLang { + bool ToBool(TObject obj) + { + if(std::holds_alternative(obj)) + { + return true; + } + if(std::holds_alternative(obj)) + { + auto v = std::get(obj); + return v.AsLong() != 0; + } + if(std::holds_alternative(obj)) + { + return !std::get(obj).empty(); + } + else if(std::holds_alternative(obj)) + { + return std::get(obj) != 0; + } + else if(std::holds_alternative(obj)) + { + return std::get(obj); + } + else if(std::holds_alternative(obj)) + { + return std::get(obj); + } + else if(std::holds_alternative(obj)) + { + return std::get(obj) != 0; + } + else if(std::holds_alternative>(obj)) + { + auto& dt = std::get>(obj); + return !(dt->Year() == 1970 && dt->Month() == 1 && dt->Day() == 1 && dt->Hour() == 0 && dt->Minute() == 0 && dt->Second() == 0 && !dt->IsLocal()); + + } + else if(std::holds_alternative>(obj)) + { + return std::get>(obj)->TotalSeconds() != 0; + } + else if(std::holds_alternative(obj)) + { + auto& uuid = std::get(obj); + return !uuid.IsEmpty(); + } + else if(std::holds_alternative(obj)) + { + auto o = std::get(obj).obj; + auto ls = dynamic_cast(o); + auto aarray = dynamic_cast(o); + auto dict = dynamic_cast(o); + auto ba = dynamic_cast(o); + auto nat = dynamic_cast(o); + auto thrd = dynamic_cast(o); + auto natObj = dynamic_cast(o); + + auto any = dynamic_cast(o); + auto cls = dynamic_cast(o); + if(cls!=nullptr) return true; + if(natObj != nullptr) return natObj->ToBool(); + if(any != nullptr) return any->any.has_value(); + + if(ls != nullptr) + { + return ls->Count() != 0; + } + if(aarray != nullptr) + { + return aarray->Count() != 0; + } + else if(dict != nullptr) + { + return !dict->items.empty(); + } + else if(ba != nullptr) + { + return !ba->data.empty(); + } + else if(nat != nullptr) + { + return !nat->GetDestroyed(); + } + else if(thrd != nullptr) + { + return !thrd->hasReturned; + } + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/src/vm/bc/tostring.cpp b/src/vm/bc/tostring.cpp new file mode 100644 index 0000000..31641ae --- /dev/null +++ b/src/vm/bc/tostring.cpp @@ -0,0 +1,133 @@ +#include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" +#include +#include +#include +#include +#include +#include +#include +namespace Tesses::CrossLang { + std::string ToString(GC* gc, TObject o) + { + if(std::holds_alternative(o)) + { + return std::get(o).ToString(); + } + if(std::holds_alternative(o)) + { + return std::get(o); + } + if(std::holds_alternative(o)) + { + return std::get(o).ToString(); + } + if(std::holds_alternative(o)) + { + return std::to_string(std::get(o)); + } + + if(std::holds_alternative(o)) + { + return std::to_string(std::get(o)); + } + + if(std::holds_alternative(o)) + { + return std::string{std::get(o)}; + } + if(std::holds_alternative(o)) + { + return "null"; + } + if(std::holds_alternative(o)) + { + return "undefined"; + } + if(std::holds_alternative(o)) + { + return std::get(o) ? "true" : "false"; + } + if(std::holds_alternative>(o)) + { + return std::get>(o)->ToString(); + } + if(std::holds_alternative>(o)) + { + return std::get>(o)->ToString(false); + } + if(std::holds_alternative(o)) + { + return std::get(o).ToString(Framework::UuidStringifyConfig::LowercaseNoCurly); + } + if(std::holds_alternative(o)) + { + auto obj = std::get(o).obj; + auto dict = dynamic_cast(obj); + auto list = dynamic_cast(obj); + auto bArray = dynamic_cast(obj); + auto natObj = dynamic_cast(obj); + auto cls = dynamic_cast(obj); + auto aArray = dynamic_cast(obj); + if(aArray != nullptr) + { + + std::string str={}; + + gc->BarrierBegin(); + bool first=true; + for(auto item : aArray->items) + { + if(!first) str.push_back('\n'); + first=false; + str.push_back('['); + str.append(Json_Encode(item.first)); + str.append("] = "); + str.append(Json_Encode(item.second)); + str.append(";"); + } + gc->BarrierEnd(); + return str; + } + if(cls != nullptr) + { + auto res = cls->GetValue("","ToString"); + TCallable* call; + GCList ls(gc); + if(GetObjectHeap(res,call)) return ToString(gc, call->Call(ls,{})); + return cls->TypeName(); + } + if(natObj != nullptr) + { + GCList ls(gc); + TObject o=natObj->CallMethod(ls,"ToString",{}); + + + return ToString(gc, o); + } + + if(dict != nullptr) + { + GCList ls(gc); + if(dict->MethodExists(ls,"ToString")) + return ToString(gc,dict->CallMethod(ls,"ToString",{})); + else + { + return Json_Encode(dict); + } + } + else if(bArray != nullptr) + { + return std::string(bArray->data.begin(),bArray->data.end()); + } + else if(list != nullptr) + { + return Json_Encode(list); + } + } + + return ""; + } +} \ No newline at end of file diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 60553a9..d22545c 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -1,4 +1,7 @@ #include "CrossLang.hpp" +#include "TessesFramework/Serialization/BitConverter.hpp" +#include "TessesFramework/Streams/ByteReader.hpp" +#include "TessesFramework/Uuid.hpp" #include #include #include @@ -10,311 +13,11 @@ namespace Tesses::CrossLang { - extern bool IHttpServer_Handle(std::shared_ptr svr,std::vector& args); thread_local CallStackEntry* current_function=nullptr; - bool ToBool(TObject obj) - { - if(std::holds_alternative(obj)) - { - return true; - } - if(std::holds_alternative(obj)) - { - auto v = std::get(obj); - return v.AsLong() != 0; - } - if(std::holds_alternative(obj)) - { - return !std::get(obj).empty(); - } - else if(std::holds_alternative(obj)) - { - return std::get(obj) != 0; - } - else if(std::holds_alternative(obj)) - { - return std::get(obj); - } - else if(std::holds_alternative(obj)) - { - return std::get(obj); - } - else if(std::holds_alternative(obj)) - { - return std::get(obj) != 0; - } - else if(std::holds_alternative>(obj)) - { - auto& dt = std::get>(obj); - return !(dt->Year() == 1970 && dt->Month() == 1 && dt->Day() == 1 && dt->Hour() == 0 && dt->Minute() == 0 && dt->Second() == 0 && !dt->IsLocal()); - - } - else if(std::holds_alternative>(obj)) - { - return std::get>(obj)->TotalSeconds() != 0; - } - else if(std::holds_alternative(obj)) - { - auto o = std::get(obj).obj; - auto ls = dynamic_cast(o); - auto aarray = dynamic_cast(o); - auto dict = dynamic_cast(o); - auto ba = dynamic_cast(o); - auto nat = dynamic_cast(o); - auto thrd = dynamic_cast(o); - auto natObj = dynamic_cast(o); + - auto any = dynamic_cast(o); - auto cls = dynamic_cast(o); - if(cls!=nullptr) return true; - if(natObj != nullptr) return natObj->ToBool(); - if(any != nullptr) return any->any.has_value(); - - if(ls != nullptr) - { - return ls->Count() != 0; - } - if(aarray != nullptr) - { - return aarray->Count() != 0; - } - else if(dict != nullptr) - { - return !dict->items.empty(); - } - else if(ba != nullptr) - { - return !ba->data.empty(); - } - else if(nat != nullptr) - { - return !nat->GetDestroyed(); - } - else if(thrd != nullptr) - { - return !thrd->hasReturned; - } - return true; - } - - return false; - } - - bool Equals(GC* gc, TObject left, TObject right) - { - GCList ls(gc); - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - - return true; - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return true; - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - return std::get(left) == std::get(right); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - return std::get>(left)->ToEpoch() == std::get>(right)->ToEpoch(); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - return std::get>(left)->TotalSeconds() == std::get>(right)->TotalSeconds(); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - auto lver= std::get(left); - auto rver = std::get(right); - auto r = lver.CompareTo(rver); - return r == 0; - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - - auto dynDict = dynamic_cast(obj); - auto native = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue("","operator=="); - gc->BarrierEnd(); - TCallable* callable; - - if(GetObjectHeap(obj,callable)) - { - return ToBool(callable->Call(ls,{right})); - - } - else if(std::holds_alternative(right)) { - return false; - } - else if(std::holds_alternative(right)) - { - return false; - } - else if(std::holds_alternative(right)) - { - return cls == std::get(right).obj; - } - } - else - if(natObj != nullptr) - { - return natObj->Equals(gc, right); - } - if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator=="); - gc->BarrierEnd(); - if(!std::holds_alternative(fn)) - { - if(std::holds_alternative(fn)) - { - - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - if(!closure->closure->args.empty() && closure->closure->args[0] == "this") - { - return ToBool(obj->Call(ls,{left,right})); - } - else - { - return ToBool(obj->Call(ls,{right})); - } - - } - else - { - return ToBool(obj->Call(ls,{right})); - - } - } - else { - - - return dict == std::get(right).obj; - } - - } else { - - return dict == std::get(right).obj; - } - - } - else { - - return dict == std::get(right).obj; - } - return false; - - } - - else if(dynDict != nullptr) - { - auto res = dynDict->CallMethod(ls,"operator==",{right}); - if(!std::holds_alternative(res) && std::holds_alternative(res)) - { - return ToBool(res); - } - } - else if(native != nullptr && std::holds_alternative(right)) - { - return native->GetDestroyed(); - - } - - if(std::holds_alternative(right)) - { - return obj == std::get(right).obj; - - } - - else if(std::holds_alternative(right)) - { - return false; - } - else if(std::holds_alternative(right)) - { - - return false; - } - else - { - return false; - } - - } - - else if(std::holds_alternative(right)) - { - return false; - } - else if(std::holds_alternative(right)) - { - return false; - } - else - { - return false; - - } - - return false; - - } TObject ExecuteFunction(GCList& ls,TCallable* callable, std::vector args) { @@ -335,85 +38,6 @@ namespace Tesses::CrossLang { typedef bool (InterperterThread::*opcode)(GC* gc); - - - - - - - bool InterperterThread::InvokeTwo(GCList& ls, TObject fn, TObject left, TObject right) - { - if(std::holds_alternative(fn)) - { - - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - if(!closure->closure->args.empty() && closure->closure->args[0] == "this") - { - this->AddCallStackEntry(ls,closure,{left,right}); - } - else - { - this->AddCallStackEntry(ls,closure,{right}); - } - - } - else - { - this->call_stack_entries[this->call_stack_entries.size()-1]->Push(ls.GetGC(), obj->Call(ls,{right})); - - return false; - } - return true; - } - - } - return false; - } - bool InterperterThread::InvokeMethod(GCList& ls, TObject fn, TObject instance, std::vector args) - { - - if(std::holds_alternative(fn)) - { - - auto obj = dynamic_cast(std::get(fn).obj); - if(obj != nullptr) - { - auto closure = dynamic_cast(obj); - if(closure != nullptr) - { - - if(!closure->closure->args.empty() && closure->closure->args[0] == "this") - { - std::vector args2; - args2.push_back(instance); - args2.insert(args2.end(), args.begin(),args.end()); - this->AddCallStackEntry(ls,closure,args2); - } - else - { - this->AddCallStackEntry(ls,closure,args); - } - - } - else - { - auto val = obj->Call(ls,args); - this->call_stack_entries.back()->Push(ls.GetGC(), val); - return false; - } - return true; - } - - } - this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); - return false; - } bool InterperterThread::InterperterThread::Breakpoint(GC* gc) { std::vector& cse=this->call_stack_entries; @@ -428,114 +52,7 @@ namespace Tesses::CrossLang { return false; } - bool InterperterThread::Sub(GC* gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) - std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (int64_t)(std::get(left) - std::get(right))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) - (*r))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) - (*r))); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - - auto natObj = dynamic_cast(obj); - - - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator-"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator-",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator-"); - 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()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - return false; - } + bool InterperterThread::Times(GC* gc) { std::vector& cse=this->call_stack_entries; @@ -1604,6 +1121,13 @@ namespace Tesses::CrossLang { auto r = lver.CompareTo(rver); cse.back()->Push(gc, r == 0); } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + auto l= std::get(left); + auto r = std::get(right); + + return l == r; + } else if(std::holds_alternative>(left) && std::holds_alternative>(right)) { @@ -1778,6 +1302,13 @@ namespace Tesses::CrossLang { auto r = lver.CompareTo(rver); cse.back()->Push(gc, r != 0); } + else if(std::holds_alternative(left) && std::holds_alternative(right)) + { + auto l= std::get(left); + auto r = std::get(right); + + return l != r; + } else if(std::holds_alternative>(left) && std::holds_alternative>(right)) { @@ -2280,157 +1811,7 @@ namespace Tesses::CrossLang { } return false; } - bool InterperterThread::Add(GC* gc) - { - std::vector& cse=this->call_stack_entries; - GCList ls(gc); - auto right = cse.back()->Pop(ls); - auto left = cse.back()->Pop(ls); - - - - if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,(char)(std::get(left) + std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (char)(std::get(left) + std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc, (char)(std::get(left) + std::get(right))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - cse.back()->Push(gc,std::get(left) + std::get(right)); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) + (*r))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) + (*r))); - } - else if(std::holds_alternative>(left) && std::holds_alternative>(right)) - { - auto& l = std::get>(left); - auto& r = std::get>(right); - cse.back()->Push(gc,std::make_shared((*l) + (*r))); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - std::string str={}; - str.append(std::get(left)); - str.append(std::get(right)); - cse.back()->Push(gc,str); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - std::string str={}; - str.push_back(std::get(left)); - str.append(std::get(right)); - cse.back()->Push(gc,str); - } - else if(std::holds_alternative(left) && std::holds_alternative(right)) - { - std::string str={}; - str.append(std::get(left)); - str.push_back(std::get(right)); - cse.back()->Push(gc,str); - } - else if(std::holds_alternative(left)) - { - auto obj = std::get(left).obj; - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"operator+"); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{right}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{right})); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - - } - else if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,"operator+",{right})); - return false; - } - else if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("operator+"); - 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()); - } - - } - else - { - cse.back()->Push(gc, Undefined()); - } - return false; - } + bool InterperterThread::ExecuteFunction(GC* gc) { std::vector& cse=this->call_stack_entries; @@ -2507,3085 +1888,7 @@ namespace Tesses::CrossLang { } return false; } - bool InterperterThread::ExecuteMethod2(GC* gc, TObject instance, std::string key, std::vector args) - { - std::vector& cse=this->call_stack_entries; - if(!cse.empty()) - { - GCList ls(gc); - std::regex regex; - TVMVersion version; - if(std::holds_alternative(instance)) - { - if(key == "ToString") - { - cse.back()->Push(gc,"null"); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - }else if(std::holds_alternative(instance)) - { - if(key == "ToString") - { - cse.back()->Push(gc,"undefined"); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - else - if(GetObject(instance, version)) - { - if(key == "ToString") - { - cse.back()->Push(gc, version.ToString()); - return false; - } - if(key == "ToByteArray") - { - TByteArray* ba = TByteArray::Create(ls); - ba->data.resize(5); - version.ToArray(ba->data.data()); - cse.back()->Push(gc,ba); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(GetObject(instance,regex)) - { - if(key == "Search") - { - std::string str; - if(GetArgument(args,0,str)) - { - std::smatch m; - if(std::regex_search(str,m,regex)) - { - auto myLs = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : m) - { - auto itm = TDictionary::Create(ls); - itm->SetValue("Offset", (int64_t)(item.first-str.begin())); - itm->SetValue("Length",(int64_t)item.length()); - itm->SetValue("Matched",item.matched); - itm->SetValue("Text",item.str()); - myLs->Add(itm); - } - - - cse.back()->Push(gc, myLs); - gc->BarrierEnd(); - return false; - } - - } - } - - cse.back()->Push(gc, nullptr); - return false; - } - else if(std::holds_alternative(instance)) - { - bool flag = std::get(instance); - if(key == "ToString") - { - cse.back()->Push(gc, flag ? "true" : "false"); - return false; - } - else if(key == "ToLong") - { - cse.back()->Push(gc, flag ? (int64_t)1 : (int64_t)0); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative(instance)) - { - char c = std::get(instance); - if(key == "ToString") - { - cse.back()->Push(gc, std::string{c}); - return false; - } - else if(key == "ToLong") - { - uint8_t uc = (uint8_t)c; - cse.back()->Push(gc, (int64_t)uc); - return false; - } - else if(key == "IsAscii") - { - bool isAscii = c >= 0; - cse.back()->Push(gc, isAscii); - return false; - } - if(key == "IsLetter") - { - bool isLetter = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); - cse.back()->Push(gc, isLetter); - return false; - } - if(key == "IsDigit") - { - bool isDigit = (c >= '0' && c <= '9'); - cse.back()->Push(gc, isDigit); - return false; - } - if(key == "IsLetterOrDigit") - { - bool isDigit = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); - cse.back()->Push(gc, isDigit); - return false; - } - if(key == "ToLower") - { - if(c >= 'A' && c <= 'Z') - cse.back()->Push(gc, (char)tolower(c)); - else - cse.back()->Push(gc, c); - - return false; - } - if(key == "ToUpper") - { - if(c >= 'a' && c <= 'z') - cse.back()->Push(gc, (char)toupper(c)); - else - cse.back()->Push(gc, c); - - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative(instance)) - { - double number = std::get(instance); - if(key == "ToString") - { - cse.back()->Push(gc, std::to_string(number)); - return false; - } - if(key == "ToLong") - { - cse.back()->Push(gc, (int64_t)number); - return false; - } - if(key == "ToLongBits") - { - cse.back()->Push(gc, *(int64_t*)&number); - return false; - } - if(key == "Floor") - { - cse.back()->Push(gc,floor(number)); - return false; - } - if(key == "Ceiling") - { - cse.back()->Push(gc,ceil(number)); - return false; - } - if(key == "Abs") - { - cse.back()->Push(gc,fabs(number)); - return false; - } - if(key == "Pow") - { - if(args.size() != 1) - { - throw VMException("Double.Pow must only accept one argument"); - } - if(!std::holds_alternative(args[0])) - { - throw VMException("Double.Pow must only accept a double"); - } - cse.back()->Push(gc,pow(number, std::get(args[0]))); - return false; - } - if(key == "Atan2") - { - if(args.size() != 1) - { - throw VMException("Double.Atan2 must only accept one argument"); - } - if(!std::holds_alternative(args[0])) - { - throw VMException("Double.Atan2 must only accept a double"); - } - cse.back()->Push(gc,atan2(number, std::get(args[0]))); - return false; - } - if(key == "Atan") - { - cse.back()->Push(gc,tan(number)); - return false; - } - if(key == "Tan") - { - cse.back()->Push(gc,tan(number)); - return false; - } - if(key == "Tanh") - { - cse.back()->Push(gc,tanh(number)); - return false; - } - if(key == "Asin") - { - cse.back()->Push(gc,asin(number)); - return false; - } - if(key == "Sin") - { - cse.back()->Push(gc,sin(number)); - return false; - } - if(key == "Sinh") - { - cse.back()->Push(gc,sinh(number)); - return false; - } - if(key == "Acos") - { - cse.back()->Push(gc,acos(number)); - return false; - } - if(key == "Cos") - { - cse.back()->Push(gc,cos(number)); - return false; - } - if(key == "Cosh") - { - cse.back()->Push(gc,cosh(number)); - return false; - } - if(key == "Log") - { - cse.back()->Push(gc,log(number)); - return false; - } - if(key == "Log10") - { - cse.back()->Push(gc,log10(number)); - return false; - } - if(key == "Sqrt") - { - cse.back()->Push(gc,sqrt(number)); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative(instance)) - { - int64_t number = std::get(instance); - if(key == "ToHexString") - { - int64_t width = 1; - - if(!GetArgument(args,0,width)) width=1; - size_t _width = (size_t)width; - - std::stringstream strm; - if(_width > 1) - strm << std::setfill('0') << std::setw((int)_width) << std::hex << number; - else - strm << std::hex << number; - cse.back()->Push(gc,strm.str()); - return false; - } - if(key == "ToString") - { - cse.back()->Push(gc, std::to_string(number)); - return false; - } - if(key == "ToChar") - { - uint8_t c = (uint8_t)number; - cse.back()->Push(gc, (char)c); - return false; - } - if(key == "Abs") - { - if(number < 0) - cse.back()->Push(gc, -number); - else - cse.back()->Push(gc, number); - return false; - } - if(key == "ToDouble") - { - cse.back()->Push(gc,(double)number); - return false; - } - if(key == "ToDoubleBits") - { - cse.back()->Push(gc,*(double*)&number); - return false; - } - - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative(instance)) - { - auto path = std::get(instance); - if(key == "GetEnumerator") - { - - TList* _ls = TList::Create(ls); - for(auto item : path.path) - { - _ls->Add(item); - } - - cse.back()->Push(gc, TListEnumerator::Create(ls,_ls)); - return false; - } - if(key == "ToString") - { - cse.back()->Push(gc, path.ToString()); - return false; - } - if(key == "GetAt") - { - int64_t index; - if(GetArgument(args,0,index)) - { - size_t idx = (size_t)idx; - if(idx < path.path.size()) - cse.back()->Push(gc, path.path[idx]); - else - cse.back()->Push(gc, nullptr); - return false; - } - } - if(key == "Count" || key == "Length") - { - cse.back()->Push(gc, (int64_t)path.path.size()); - return false; - } - if(key == "GetParent") - { - cse.back()->Push(gc, path.GetParent()); - return false; - } - if(key == "GetFileName") - { - cse.back()->Push(gc, path.GetFileName()); - return false; - } - if(key == "GetExtension") - { - cse.back()->Push(gc, path.GetExtension()); - return false; - } - if(cse.back()->env->GetRootEnvironment()->permissions.canRegisterLocalFS && key == "MakeAbsolute") - { - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgumentAsPath(args,0,p)) - { - cse.back()->Push(gc,path.MakeAbsolute(p)); - return false; - } - else - { - cse.back()->Push(gc,path.MakeAbsolute()); - return false; - } - } - if(cse.back()->env->GetRootEnvironment()->permissions.canRegisterLocalFS && key == "MakeRelative") - { - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgumentAsPath(args,0,p)) - { - cse.back()->Push(gc,path.MakeRelative(p)); - return false; - } - else - { - cse.back()->Push(gc,path.MakeRelative()); - return false; - } - } - if(key == "ChangeExtension") - { - Tesses::Framework::Filesystem::VFSPath newPath = path; - std::string ext; - if(GetArgument(args,0, ext)) - { - newPath.ChangeExtension(ext); - } - else - { - newPath.RemoveExtension(); - } - cse.back()->Push(gc, newPath); - return false; - } - if(key == "CollapseRelativeParents") - { - cse.back()->Push(gc, path.CollapseRelativeParents()); - return false; - } - if(key == "IsRelative") - { - cse.back()->Push(gc, path.relative); - return false; - //Path.FromString(); - } - } - else if(std::holds_alternative(instance)) - { - std::string str = std::get(instance); - if(key == "ToLower") - { - for(size_t i = 0; i < str.size(); i++) - { - if(str[i] >= 'A' && str[i] <= 'Z') - { - str[i] = 'a' + (str[i] - 'A'); - } - } - cse.back()->Push(gc, str); - return false; - } - if(key == "ToUpper") - { - - for(size_t i = 0; i < str.size(); i++) - { - if(str[i] >= 'a' && str[i] <= 'z') - { - str[i] = 'A' + (str[i] - 'a'); - } - } - cse.back()->Push(gc, str); - return false; - } - if(key == "PadLeft") - { - int64_t pad; - char padChar=' '; - - if(args.size() == 0 || args.size() > 2) - { - throw VMException("String.PadLeft must only accept 1 or 2 arguments"); - - } - - if(GetArgument(args,0, pad)) - { - if((size_t)pad < str.size()) { - cse.back()->Push(gc, str); - return false; - } - GetArgument(args,1, padChar); - size_t diff = (size_t)pad - str.size(); - str.insert(str.begin(),diff, padChar); - cse.back()->Push(gc, str); - return false; - } - else throw VMException("String.PadLeft must have a long for width"); - } - if(key == "PadRight") - { - int64_t pad; - char padChar=' '; - - if(args.size() == 0 || args.size() > 2) - { - throw VMException("String.PadRight must only accept 1 or 2 arguments"); - - } - - if(GetArgument(args,0, pad)) - { - if((size_t)pad < str.size()) { - cse.back()->Push(gc, str); - return false; - } - GetArgument(args,1, padChar); - size_t diff = (size_t)pad - str.size(); - str.insert(str.end(),diff, padChar); - cse.back()->Push(gc, str); - return false; - } - else throw VMException("String.PadRight must have a long for width"); - } - if(key == "Contains") - { - std::string str2; - char c; - if(GetArgument(args,0,str2)) - { - - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find(str2,(std::size_t)index); - - cse.back()->Push(gc, res != std::string::npos); - return false; - } - - else if(GetArgument(args,0,c)) - { - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find_first_of(c,(std::size_t)index); - - cse.back()->Push(gc, res != std::string::npos); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "IndexOf") - { - std::string str2; - char c; - if(GetArgument(args,0,str2)) - { - - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find(str2,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - - else if(GetArgument(args,0,c)) - { - int64_t index = 0; - GetArgument(args,1,index); - - auto res = str.find_first_of(c,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "LastIndexOf") - { - std::string str2; - char c; - if(GetArgument(args,0,str2)) - { - - int64_t index = str.size(); - GetArgument(args,1,index); - - auto res = str.rfind(str2,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - else if(GetArgument(args,0,c)) - { - int64_t index = str.size(); - GetArgument(args,1,index); - - auto res = str.find_last_of(c,(std::size_t)index); - if(res == std::string::npos) - cse.back()->Push(gc, (int64_t)-1); - else - cse.back()->Push(gc, (int64_t)res); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "GetEnumerator") - { - cse.back()->Push(gc, TStringEnumerator::Create(ls,str)); - return false; - } - if(key == "Substring") - { - if(args.size() >=1 && std::holds_alternative(args[0])) - { - size_t offset = (size_t)std::get(args[0]); - size_t count = std::string::npos; - if(args.size() == 2 && std::holds_alternative(args[1])) - { - count = (size_t)std::get(args[1]); - } - cse.back()->Push(gc, str.substr(offset,count)); - return false; - } - - } - if(key == "Remove") - { - if(args.size() >=1 && std::holds_alternative(args[0])) - { - size_t offset = (size_t)std::get(args[0]); - size_t count = std::string::npos; - if(args.size() == 2 && std::holds_alternative(args[1])) - { - count = (size_t)std::get(args[1]); - } - cse.back()->Push(gc, str.erase(offset,count)); - return false; - } - - } - if(key == "TrimStart") - { - if(args.size() >= 0) - { - char c = (args.size() == 1 && std::holds_alternative(args[0])) ? std::get(args[0]) : ' '; - - size_t i = 0; - for(; i < str.size();i++) - { - if(str[i] != c) break; - } - cse.back()->Push(gc,str.substr(i)); - return false; - } - } - if(key == "TrimEnd") - { - if(args.size() >= 0) - { - char c = (args.size() == 1 && std::holds_alternative(args[0])) ? std::get(args[0]) : ' '; - size_t i = str.size()-1; - for(; i >= 0;i--) - { - if(str[i] != c) break; - } - cse.back()->Push(gc,str.substr(0,i+1)); - return false; - } - } - if(key == "EndsWith") - { - std::string v; - if(GetArgument(args,0,v)) - { - if(str.size() < v.size()) { - cse.back()->Push(gc,false); - return false; - } - - size_t _end = str.size()-v.size(); - for(size_t i = 0; i < v.size(); i++) - { - if(v[i] != str[i+_end]) - { - cse.back()->Push(gc,false); - return false; - } - } - cse.back()->Push(gc,true); - return false; - } - cse.back()->Push(gc,false); - return false; - } - if(key == "StartsWith") - { - std::string v; - if(GetArgument(args,0,v)) - { - if(str.size() < v.size()) { - cse.back()->Push(gc,false); - return false; - } - for(size_t i = 0; i < v.size(); i++) - { - if(v[i] != str[i]) - { - cse.back()->Push(gc,false); - return false; - } - } - cse.back()->Push(gc,true); - return false; - } - cse.back()->Push(gc,false); - return false; - } - if(key == "Escape") - { - bool quote; - if(!GetArgument(args,0,quote)) quote=false; - cse.back()->Push(gc, EscapeString(str, quote)); - return false; - } - if(key == "Replace") - { - std::string oldStr; - std::string newStr; - - std::string _str={}; - if(GetArgument(args,0,oldStr) && GetArgument(args,1,newStr)) - { - _str = Tesses::Framework::Http::HttpUtils::Replace(str, oldStr,newStr); - - - } - cse.back()->Push(gc,_str); - - return false; - } - if(key == "Split") - { - std::string delimiter; - bool removeEmpty=false; - size_t count=std::string::npos; - - if(args.size() < 1 || args.size() > 3) throw VMException("String.Split must only accept 1-3 arguments"); - if(!std::holds_alternative(args[0])) throw VMException("String.Split first arg must be a string"); - else - delimiter = std::get(args[0]); - - if(args.size() > 1 && !std::holds_alternative(args[1])) throw VMException("String.Split second arg must be a bool"); - else if(args.size() > 1) - removeEmpty = std::get(args[1]); - if(args.size() > 2 && !std::holds_alternative(args[2])) throw VMException("String.Split third arg must be a int64_t"); - else if(args.size() > 2) - count = (size_t)std::get(args[2]); - - auto res = Tesses::Framework::Http::HttpUtils::SplitString(str, delimiter,count); - TList* mls = TList::Create(ls); - for(auto item : res) - { - if(!removeEmpty || !item.empty()) mls->Add(item); - } - cse.back()->Push(gc,mls); - return false; - // SplitString() - } - if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("String.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("String.GetAt must only accept a long"); - } - - size_t index = (size_t)std::get(args[0]); - size_t sz = str.size(); - if(index >= 0 && index < sz) - { - cse.back()->Push(gc, str[index]); - return false; - } - - } - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)str.size(); - if(len < 0) len = 0; - - cse.back()->Push(gc, len); - return false; - } - if(key == "ToString") - { - cse.back()->Push(gc, str); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative>(instance)) - { - auto& time = std::get>(instance); - if(key == "ToString") - { - bool slim = false; - GetArgument(args,0,slim); - - cse.back()->Push(gc, time->ToString(slim)); - - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative>(instance)) - { - auto& date = std::get>(instance); - - - if(key == "ToString") - { - std::string fmt; - if(GetArgument(args,0,fmt)) - { - cse.back()->Push(gc, date->ToString(fmt)); - } - else - { - cse.back()->Push(gc, date->ToString()); - } - return false; - } - if(key == "ToHttpDate") - { - cse.back()->Push(gc, date->ToHttpDate()); - return false; - } - if(key == "ToEpoch") - { - cse.back()->Push(gc, date->ToEpoch()); - return false; - } - if(key == "ToLocal") - { - cse.back()->Push(gc, std::make_shared(date->ToLocal())); - return false; - } - if(key == "ToUTC") - { - cse.back()->Push(gc, std::make_shared(date->ToUTC())); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - - } - else if(std::holds_alternative>(instance)) - { - auto textReader = std::get>(instance); - if(key == "Rewind") - { - cse.back()->Push(gc,textReader->Rewind()); - return false; - } - if(key == "ReadBlock") - { - int64_t sz; - if(GetArgument(args,0,sz)) - { - std::string block; - if(textReader->ReadBlock(block,(size_t)sz)) - { - cse.back()->Push(gc, block); - return false; - } - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadChar") - { - cse.back()->Push(gc,(int64_t)textReader->ReadChar()); - return false; - } - if(key == "ReadLine") - { - std::string line; - if(textReader->ReadLine(line)) - { - cse.back()->Push(gc, line); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadLineHttp") - { - std::string line; - if(textReader->ReadLineHttp(line)) - { - cse.back()->Push(gc, line); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadAllLines") - { - std::vector lines; - textReader->ReadAllLines(lines); - gc->BarrierBegin(); - TList* list = TList::Create(ls); - for(auto& item : lines) list->Add(item); - gc->BarrierEnd(); - return list; - } - if(key == "ReadToEnd") - { - std::string text; - textReader->ReadToEnd(text); - cse.back()->Push(gc,text); - return false; - } - if(key == "CopyTo") - { - std::shared_ptr writer; - if(GetArgument(args,0,writer)) - { - textReader->CopyTo(*writer); - } - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(std::holds_alternative>(instance)) - { - auto textWriter=std::get>(instance); - if(key == "Write") - { - if(args.size()>0) - textWriter->Write(ToString(gc,args[0])); - } - if(key == "WriteLine") - { - if(args.size()>0) - textWriter->WriteLine(ToString(gc,args[0])); - } - if(key == "WriteData") - { - if(args.size()>0) - { - auto s=ToString(gc,args[0]); - textWriter->WriteData(s.c_str(),s.size()); - } - } - cse.back()->Push(gc, nullptr); - return false; - } - else if(std::holds_alternative>(instance)) - { - auto strm = std::get>(instance); - if(strm != nullptr) - { - auto memStrm = std::dynamic_pointer_cast(strm); - auto netStrm = std::dynamic_pointer_cast(strm); - - auto mystrm = std::dynamic_pointer_cast(strm); - - if(mystrm != nullptr) - { - TDictionary* dict2; - if(GetObjectHeap(mystrm->obj, dict2)) - { - - gc->BarrierBegin(); - auto o = dict2->GetValue(key); - gc->BarrierEnd(); - - return InvokeMethod(ls,o,dict2,args); - } - } - if(memStrm != nullptr) - { - if(key == "GetBytes") - { - auto res = TByteArray::Create(ls); - res->data = memStrm->GetBuffer(); - cse.back()->Push(gc, res); - return false; - } - } - if(netStrm != nullptr) - { - if(key == "GetPort") - { - cse.back()->Push(gc, (int64_t)netStrm->GetPort()); - return false; - } - if(key == "Bind") - { - std::string ip; - int64_t port; - if(GetArgument(args,0,ip) && GetArgument(args,1,port)) - netStrm->Bind(ip,(uint16_t)port); - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Accept") - { - std::string ip; - uint16_t port; - auto strm = netStrm->Accept(ip,port); - TDictionary* dict = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->SetValue("IP",ip); - dict->SetValue("Port",(int64_t)port); - dict->SetValue("Stream", strm); - - gc->BarrierEnd(); - cse.back()->Push(gc, dict); - return false; - } - if(key == "Listen") - { - int64_t backlog; - if(GetArgument(args,0,backlog)) - { - netStrm->Listen((int32_t)backlog); - } - else - { - netStrm->Listen(10); - } - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadFrom") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; - std::string ip={}; - uint16_t port=0; - - if(off < len) - - len = netStrm->ReadFrom(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size())),ip,port); - - else - len = 0; - - TDictionary* dict = TDictionary::Create(ls); - gc->BarrierBegin(); - dict->SetValue("IP",ip); - dict->SetValue("Port",(int64_t)port); - dict->SetValue("Read", (int64_t)len); - - gc->BarrierEnd(); - cse.back()->Push(gc, dict); - - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "WriteTo") - { - TByteArray* data; - int64_t offset; - int64_t length; - std::string ip; - int64_t port; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length) && GetArgument(args,3,ip) && GetArgument(args,4,port)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; - - if(off < len) - - len = netStrm->WriteTo(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size())), ip, (int64_t)port); - - else - len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - } - - if(key == "Read") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; - - if(off < len) - - len = strm->Read(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size()))); - - else - len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Write") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; - - if(off < len) - - len = strm->Write(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size()))); - - else - len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadBlock") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; - - if(off < len) - - len = strm->ReadBlock(data->data.data()+off,std::min(len, std::min(data->data.size() - off, data->data.size()))); - - else - len = 0; - - cse.back()->Push(gc, (int64_t)len); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "WriteText") - { - std::string text; - - if(GetArgument(args,0,text)) - { - strm->WriteBlock((const uint8_t*)text.data(), text.size()); - } - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "WriteBlock") - { - TByteArray* data; - int64_t offset; - int64_t length; - if(GetArgumentHeap(args, 0, data) && GetArgument(args, 1, offset) && GetArgument(args,2,length)) - { - size_t off = (size_t)offset; - size_t len = (size_t)length; - - if(off < len) - - strm->WriteBlock(data->data.data()+off,std::min(len,std::min(data->data.size() - off, data->data.size()))); - - - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CopyTo") - { - std::shared_ptr data; - int64_t buffSize; - if(GetArgument(args,0,data)) - { - if(!GetArgument(args,1,buffSize)) buffSize=1024; - strm->CopyTo(data,(size_t)buffSize); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CopyToLimit") - { - std::shared_ptr data; - int64_t cnt; - int64_t buffSize; - if(GetArgument(args,0,data) && GetArgument(args,1,cnt)) - { - if(!GetArgument(args,2,buffSize)) buffSize=1024; - strm->CopyToLimit(data,(uint64_t)cnt,(size_t)buffSize); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Flush") - { - strm->Flush(); - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Close") - { - strm->Close(); - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Seek") - { - int64_t pos,whence; - if(!GetArgument(args,0,pos)) pos=0; - - if(!GetArgument(args,1,whence)) whence=0; - - - strm->Seek(pos, whence == 0 ? Tesses::Framework::Streams::SeekOrigin::Begin : whence == 1 ? Tesses::Framework::Streams::SeekOrigin::Current : Tesses::Framework::Streams::SeekOrigin::End); - - cse.back()->Push(gc, nullptr); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - } - else if(std::holds_alternative>(instance)) - { - auto svr = std::get>(instance); - if(svr != nullptr) - { - auto mountable = std::dynamic_pointer_cast(svr); - auto routable = std::dynamic_pointer_cast(svr); - - if(mountable != nullptr) - { - if(key == "Mount") - { - Tesses::Framework::Filesystem::VFSPath p; - - if(args.size() > 1 && GetArgumentAsPath(args,0,p)) - { - std::shared_ptr svr2=ToHttpServer(gc,args[1]); - - if(svr2) - mountable->Mount(p.ToString(), svr2); - - cse.back()->Push(gc,nullptr); - return false; - } - } - if(key == "Unmount") - { - Tesses::Framework::Filesystem::VFSPath p; - - if(GetArgumentAsPath(args,0,p)) - { - mountable->Unmount(p.ToString()); - cse.back()->Push(gc,nullptr); - return false; - } - } - } - if(routable != nullptr) - { - if(key == "Add") - { - std::string method; - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,method) && GetArgument(args,1,pattern) && GetArgumentHeap(args,2,callable)) - { - routable->Add(method,pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Delete") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Delete(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Get") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Get(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Options") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Options(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Patch") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Patch(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Post") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Post(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Put") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Put(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - else if(key == "Trace") - { - std::string pattern; - TCallable* callable; - if(GetArgument(args,0,pattern) && GetArgumentHeap(args,1,callable)) - { - routable->Trace(pattern, callable->ToRouteServerRequestHandler(gc)); - } - } - } - if(key == "Handle") - { - cse.back()->Push(gc,IHttpServer_Handle(svr,args)); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - } - else if(std::holds_alternative>(instance)) - { - auto vfs = std::get>(instance); - if(vfs != nullptr) - { - auto myvfs = std::dynamic_pointer_cast(vfs); - - auto mountable = std::dynamic_pointer_cast(vfs); - if(myvfs != nullptr) - { - TDictionary* dict2; - if(GetObjectHeap(myvfs->obj, dict2)) - { - - gc->BarrierBegin(); - auto o = dict2->GetValue(key); - gc->BarrierEnd(); - - return InvokeMethod(ls,o,dict2,args); - } - } - if(mountable != nullptr) - { - if(key == "Unmount") - { - Tesses::Framework::Filesystem::VFSPath path; - - if(GetArgumentAsPath(args,0,path)) - { - mountable->Unmount(path); - } - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Mount") - { - Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr vfs2; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,vfs2)) - { - - //mountable->Mount(path, , true); - mountable->Mount(path, vfs2); - } - - cse.back()->Push(gc, nullptr); - return false; - } - } - if(key == "Close") - { - vfs->Close(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "EnumeratePaths") - { - Tesses::Framework::Filesystem::VFSPath dir; - if(GetArgumentAsPath(args,0,dir)) - { - auto tem = TExternalMethod::Create(ls,"Get the enumerator",{},[vfs,dir](GCList& ls, std::vector args)->TObject{ - return TVFSPathEnumerator::Create(ls,vfs->EnumeratePaths(dir)); - }); - auto d1=TDictionary::Create(ls); - gc->BarrierBegin(); - tem->watch.push_back(vfs); - d1->SetValue("GetEnumerator", tem); - gc->BarrierEnd(); - - cse.back()->Push(gc,d1); - return false; - } - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "MoveDirectory") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->MoveDirectory(existingFile,symlinkFile); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SetDate") - { - Tesses::Framework::Filesystem::VFSPath path; - std::shared_ptr lastWrite; - std::shared_ptr lastAccess; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,lastWrite) && GetArgument(args,2,lastAccess)) - { - vfs->SetDate(path,*lastWrite, *lastAccess); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "GetDate") - { - Tesses::Framework::Filesystem::VFSPath path; - if(GetArgumentAsPath(args,0,path)) - { - Tesses::Framework::Date::DateTime lastWrite; - Tesses::Framework::Date::DateTime lastAccess; - vfs->GetDate(path,lastWrite,lastAccess); - - auto dict = TDictionary::Create(ls); - ls.GetGC()->BarrierBegin(); - - dict->SetValue("LastWrite", std::make_shared(lastWrite)); - dict->SetValue("LastAccess", std::make_shared(lastAccess)); - ls.GetGC()->BarrierEnd(); - - cse.back()->Push(gc, dict); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "MoveFile") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->MoveFile(existingFile,symlinkFile); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CreateHardlink") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->CreateHardlink(existingFile,symlinkFile); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CreateSymlink") - { - Tesses::Framework::Filesystem::VFSPath existingFile; - - Tesses::Framework::Filesystem::VFSPath symlinkFile; - if(GetArgumentAsPath(args,0,existingFile) && GetArgumentAsPath(args,1,symlinkFile)) - { - vfs->CreateSymlink(existingFile,symlinkFile); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "RegularFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->RegularFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SpecialFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->SpecialFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "FIFOFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->FIFOFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SocketFileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->SocketFileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "BlockDeviceExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->BlockDeviceExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CharacterDeviceExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->CharacterDeviceExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SymlinkExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->SymlinkExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DirectoryExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->DirectoryExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "FileExists") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->FileExists(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "ReadLink") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->ReadLink(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "VFSPathToSystem") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - cse.back()->Push(gc,vfs->VFSPathToSystem(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "SystemToVFSPath") - { - std::string filename; - if(GetArgument(args,0,filename)) - { - cse.back()->Push(gc,vfs->SystemToVFSPath(filename)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DeleteFile") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - vfs->DeleteFile(filename); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Lock") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - vfs->Lock(filename); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Unlock") - { - Tesses::Framework::Filesystem::VFSPath filename; - if(GetArgumentAsPath(args,0,filename)) - { - vfs->Unlock(filename); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DeleteDirectoryRecurse") - { - Tesses::Framework::Filesystem::VFSPath dirname; - if(GetArgumentAsPath(args,0,dirname)) - { - vfs->DeleteDirectoryRecurse(dirname); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "DeleteDirectory") - { - Tesses::Framework::Filesystem::VFSPath dirname; - if(GetArgumentAsPath(args,0,dirname)) - { - vfs->DeleteDirectory(dirname); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "CreateDirectory") - { - - Tesses::Framework::Filesystem::VFSPath dirname; - if(GetArgumentAsPath(args,0,dirname)) - { - vfs->CreateDirectory(dirname); - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "OpenFile") - { - - Tesses::Framework::Filesystem::VFSPath path; - std::string mode; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode)) - { - auto res = vfs->OpenFile(path,mode); - cse.back()->Push(gc, res); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "Chmod") - { - Tesses::Framework::Filesystem::VFSPath path; - int64_t mode; - if(GetArgumentAsPath(args,0,path) && GetArgument(args,1,mode)) - { - vfs->Chmod(path,(uint32_t)mode); - } - - cse.back()->Push(gc, nullptr); - return false; - } - if(key == "StatVFS") - { - Tesses::Framework::Filesystem::VFSPath path; - - if(GetArgumentAsPath(args,0,path)) - { - Tesses::Framework::Filesystem::StatVFSData data; - if(vfs->StatVFS(path,data)) - { - cse.back()->Push(gc, TDictionary::Create(ls,{ - TDItem("BlockSize", (int64_t)data.BlockSize), - TDItem("FragmentSize",(int64_t)data.FragmentSize), - TDItem("Blocks",(int64_t)data.Blocks), - TDItem("BlocksFree",(int64_t)data.BlocksFree), - TDItem("BlocksAvailable", (int64_t)data.BlocksAvailable), - TDItem("TotalInodes", (int64_t)data.TotalInodes), - TDItem("FreeInodes",(int64_t)data.FreeInodes), - TDItem("AvailableInodes",(int64_t)data.AvailableInodes), - TDItem("Id",(int64_t)data.Id), - TDItem("Flags",(int64_t)data.Flags), - TDItem("MaxNameLength",(int64_t)data.MaxNameLength) - })); - return false; - } - } - - cse.back()->Push(gc, nullptr); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - - } - else if(std::holds_alternative(instance)) - { - auto obj = std::get(instance).obj; - auto list = dynamic_cast(obj); - auto dynList = dynamic_cast(obj); - auto bArray = dynamic_cast(obj); - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto ittr = dynamic_cast(obj); - - auto env = dynamic_cast(obj); - - auto subEnv = dynamic_cast(obj); - auto rootEnv = dynamic_cast(obj); - auto callable = dynamic_cast(obj); - auto callstackEntry = dynamic_cast(obj); - - - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - auto aArray=dynamic_cast(obj); - auto ttask = dynamic_cast(obj); - auto file = dynamic_cast(obj); - - if(file != nullptr) - { - if(key == "MetadataDecode") - { - int64_t index; - if(GetArgument(args,0, index) && (size_t)index < file->metadata.size()) - { - cse.back()->Push(gc,file->MetadataDecode(ls,(size_t)index)); - return false; - } - } - if(key == "MetadataName") - { - int64_t index; - if(GetArgument(args,0, index) && (size_t)index < file->metadata.size()) - { - cse.back()->Push(gc,file->metadata.at((size_t)index).first); - return false; - } - } - cse.back()->Push(gc,Undefined()); - return false; - } - if(ttask != nullptr) - { - if(key == "ContinueWith") - { - TCallable* callable2; - if(GetArgumentHeap(args,0,callable2)) - { - cse.back()->Push(gc,ttask->ContinueWith(ls,callable2)); - return false; - } - } - if(key == "Wait") - { - - cse.back()->Push(gc,ttask->Wait()); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - - if(natObj != nullptr) - { - cse.back()->Push(gc, natObj->CallMethod(ls,key,args)); - return false; - } - - if(callstackEntry != nullptr) - { - if(key == "Resume") - { - gc->BarrierBegin(); - cse.push_back(callstackEntry); - gc->BarrierEnd(); - return true; - } - if(key == "Push") - { - if(!args.empty()) - callstackEntry->Push(gc, args[0]); - else - callstackEntry->Push(gc,Undefined()); - return false; - } - if(key == "Pop") - { - cse.back()->Push(gc, callstackEntry->Pop(ls)); - return false; - } - } - - - if(rootEnv != nullptr) - { - //TStd::RegisterCrypto - //TStd::RegisterDictionary - //TStd::RegisterEnv - //TStd::RegisterIO - //TStd::RegisterJson - //TStd::RegisterNet - //TStd::RegisterOGC - //TStd::RegisterPath - //TStd::RegisterRoot - //TStd::RegisterSqlite - //TStd::RegisterVM - auto myEnv = cse.back()->env->GetRootEnvironment(); - - if(key == "RegisterOnError") - { - TCallable* callable; - if(!rootEnv->permissions.locked && GetArgumentHeap(args,0,callable)) - { - gc->BarrierBegin(); - rootEnv->RegisterOnError(callable); - gc->BarrierEnd(); - } - } - if(key == "SetCustomConsole") - { - TDictionary* dict; - if(!rootEnv->permissions.locked && GetArgumentHeap(args,0, dict)) - { - gc->BarrierBegin(); - rootEnv->permissions.customConsole = dict; - gc->BarrierEnd(); - } - else if(!rootEnv->permissions.locked && myEnv->permissions.customConsole == nullptr) - { - gc->BarrierBegin(); - rootEnv->permissions.customConsole=nullptr; - gc->BarrierEnd(); - } - } - if(key == "RegisterEverything") - { - if(myEnv->permissions.canRegisterEverything) - { - TStd::RegisterStd(gc, rootEnv); - } - else - { - if(myEnv->permissions.canRegisterConsole && !rootEnv->permissions.locked) - TStd::RegisterConsole(gc, rootEnv); - - if(myEnv->permissions.canRegisterCrypto && !rootEnv->permissions.locked) - TStd::RegisterCrypto(gc, rootEnv); - - if(myEnv->permissions.canRegisterDictionary && !rootEnv->permissions.locked) - TStd::RegisterDictionary(gc, rootEnv); - - if(myEnv->permissions.canRegisterEnv && !rootEnv->permissions.locked) - TStd::RegisterEnv(gc, rootEnv); - - - if(myEnv->permissions.canRegisterIO && !rootEnv->permissions.locked) - TStd::RegisterIO(gc, rootEnv, myEnv->permissions.canRegisterLocalFS); - - if(myEnv->permissions.canRegisterJSON && !rootEnv->permissions.locked) - TStd::RegisterJson(gc, rootEnv); - - if(myEnv->permissions.canRegisterNet && !rootEnv->permissions.locked) - TStd::RegisterNet(gc, rootEnv); - - if(myEnv->permissions.canRegisterOGC && !rootEnv->permissions.locked) - TStd::RegisterOGC(gc, rootEnv); - - if(myEnv->permissions.canRegisterPath && !rootEnv->permissions.locked) - TStd::RegisterPath(gc, rootEnv); - - if(myEnv->permissions.canRegisterRoot && !rootEnv->permissions.locked) - TStd::RegisterRoot(gc, rootEnv); - - - if(myEnv->permissions.canRegisterSqlite && !rootEnv->permissions.locked) - TStd::RegisterSqlite(gc, rootEnv); - - if(myEnv->permissions.canRegisterVM && !rootEnv->permissions.locked) - TStd::RegisterVM(gc, rootEnv); - if(myEnv->permissions.canRegisterProcess && !rootEnv->permissions.locked) - TStd::RegisterProcess(gc, rootEnv); - } - - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterClass") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterClass) && !rootEnv->permissions.locked) - TStd::RegisterClass(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - - if(key == "RegisterConsole") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterConsole) && !rootEnv->permissions.locked) - TStd::RegisterConsole(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterProcess") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterProcess) && !rootEnv->permissions.locked) - TStd::RegisterProcess(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterCrypto") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterCrypto) && !rootEnv->permissions.locked) - TStd::RegisterCrypto(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterDictionary") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterDictionary) && !rootEnv->permissions.locked) - TStd::RegisterDictionary(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterEnv") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterEnv) && !rootEnv->permissions.locked) - TStd::RegisterDictionary(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterIO") - { - bool r; - if(GetArgument(args,0,r)) - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterIO) && !rootEnv->permissions.locked) - TStd::RegisterIO(gc, rootEnv, myEnv->permissions.canRegisterLocalFS ? r : false); - } - cse.back()->Push(gc,nullptr); - return false; - - } - if(key == "RegisterJson") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterJSON) && !rootEnv->permissions.locked) - TStd::RegisterJson(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterNet") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterNet) && !rootEnv->permissions.locked) - TStd::RegisterNet(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterOGC") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterOGC) && !rootEnv->permissions.locked) - TStd::RegisterOGC(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterPath") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterPath) && !rootEnv->permissions.locked) - TStd::RegisterPath(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterRoot") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterRoot) && !rootEnv->permissions.locked) - TStd::RegisterRoot(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - - if(key == "RegisterSqlite") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterSqlite) && !rootEnv->permissions.locked) - TStd::RegisterSqlite(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - - if(key == "SetSqliteRoot") - { - Tesses::Framework::Filesystem::VFSPath p; - if(!rootEnv->permissions.locked) - { - if(GetArgumentAsPath(args,0,p)) - { - if(myEnv->permissions.sqlite3Scoped) - { - rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath / p.CollapseRelativeParents(); - rootEnv->permissions.sqlite3Scoped = true; - } - else - { - rootEnv->permissions.sqliteOffsetPath = p; - rootEnv->permissions.sqlite3Scoped = true; - } - } - else { - if(myEnv->permissions.sqlite3Scoped) - { - rootEnv->permissions.sqliteOffsetPath = myEnv->permissions.sqliteOffsetPath; - rootEnv->permissions.sqlite3Scoped = true; - } - else - { - rootEnv->permissions.sqlite3Scoped = false; - } - } - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "RegisterVM") - { - if((myEnv->permissions.canRegisterEverything || myEnv->permissions.canRegisterVM) && !rootEnv->permissions.locked) - TStd::RegisterVM(gc, rootEnv); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "LockRegister") - { - if(!rootEnv->permissions.locked) - { - rootEnv->permissions.locked=true; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "GetDictionary") - { - - cse.back()->Push(gc,rootEnv->GetDictionary()); - return false; - } - if(key == "LoadFileWithDependencies") - { - std::shared_ptr vfs0; - TFile* f; - Tesses::Framework::Filesystem::VFSPath p; - if(GetArgument(args,0,vfs0) ) - { - if(GetArgumentHeap(args,1,f)) - { - rootEnv->LoadFileWithDependencies(gc,vfs0,f); - } - else if(GetArgumentAsPath(args,1,p)) - { - rootEnv->LoadFileWithDependencies(gc,vfs0,p); - } - } - cse.back()->Push(gc,nullptr); - return false; - } - } - if(subEnv != nullptr) - { - if(key == "GetDictionary") - { - cse.back()->Push(gc,subEnv->GetDictionary()); - return false; - } - } - - if(env != nullptr) - { - if(key == "Eval") - { - std::string str; - if(GetArgument(args,0,str)) - { - - - cse.back()->Push(gc,env->Eval(ls,str)); - return false; - } - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "GetRootEnvironment") - { - cse.back()->Push(gc,env->GetRootEnvironment()); - return false; - } - - if(key == "GetSubEnvironment") - { - cse.back()->Push(gc,env->GetSubEnvironment(ls)); - return false; - } - if(key == "GetParentEnvironment") - { - cse.back()->Push(gc,env->GetParentEnvironment()); - return false; - } - if(key == "GetVariable") - { - std::string key; - gc->BarrierBegin(); - if(GetArgument(args,0,key)) - cse.back()->Push(gc,env->GetVariable(key)); - gc->BarrierEnd(); - return false; - } - if(key == "SetVariable") - { - std::string key; - - gc->BarrierBegin(); - if(args.size() > 1 && GetArgument(args,0,key)) - { - if(env->HasConstForSet(key)) - { - gc->BarrierEnd(); - ThrowConstError(key); - } - - env->SetVariable(key,args[1]); - - } - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "DeclareVariable") - { - std::string key; - - gc->BarrierBegin(); - if(args.size() > 1 && GetArgument(args,0,key)) - { - if(env->HasConstForDeclare(key)) - { - gc->BarrierEnd(); - ThrowConstError(key); - } - env->DeclareVariable(key,args[1]); - - } - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "DeclareConstVariable") - { - std::string key; - - gc->BarrierBegin(); - if(args.size() > 1 && GetArgument(args,0,key)) - { - if(env->HasConstForDeclare(key)) - { - gc->BarrierEnd(); - ThrowConstError(key); - } - env->DeclareConstVariable(key,args[1]); - } - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - if(key == "LoadFile") - { - TFile* f; - if(GetArgumentHeap(args,0,f)) - { - env->LoadFile(gc,f); - } - cse.back()->Push(gc,nullptr); - return false; - } - - cse.back()->Push(gc,nullptr); - return false; - } - - - - if(ittr != nullptr) - { - if(key == "MoveNext") - { - cse.back()->Push(gc, ittr->MoveNext(gc)); - return false; - } - cse.back()->Push(gc, nullptr); - return false; - } - - else if(bArray != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)bArray->data.size(); - if(len < 0) len = 0; - - cse.back()->Push(gc, len); - return false; - - } - if(key == "ToString") - { - cse.back()->Push(gc,std::string(bArray->data.begin(),bArray->data.end())); - return false; - } - if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("ByteArray.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("ByteArray.GetAt must only accept a long"); - } - - size_t index = (size_t)std::get(args[0]); - size_t sz = bArray->data.size(); - if(index >= 0 && index < sz) - { - cse.back()->Push(gc, (int64_t)bArray->data[index]); - return false; - } - - } - - if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("ByteArray.SetAt must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("ByteArray.SetAt first argument must only accept a long"); - } - - uint8_t v = 0; - - if(std::holds_alternative(args[1])) - { - v = (uint8_t)(std::get(args[1]) & 0xFF); - } - - size_t index = (size_t)std::get(args[0]); - size_t sz = bArray->data.size(); - if(index >= 0 && index < sz) - { - bArray->data[index]=v; - return false; - } - - } - if(key == "ToCHeaderFile") - { - std::string name = "NONAME"; - GetArgument(args,0,name); - - cse.back()->Push(gc, Tesses::Framework::Text::GenerateCHeaderFile(bArray->data,name)); - return false; - } - if(key == "CopyTo") - { - //CopyTo(destBuff, offsetSrc, offsetDest, length) - - if(args.size() != 4) - { - throw VMException("ByteArray.CopyTo must only accept 4 arguments"); - } - - TByteArray* bArray2; - int64_t offsetSrc; - int64_t offsetDest; - int64_t count; - if(!GetArgumentHeap(args,0,bArray2)) - { - throw VMException("ByteArray.CopyTo first argument must be a ByteArray"); - } - if(!GetArgument(args,1, offsetSrc)) - { - throw VMException("ByteArray.CopyTo second argument must be a Long (offsetSrc)"); - } - if(!GetArgument(args,2, offsetDest)) - { - throw VMException("ByteArray.CopyTo third argument must be a Long (offsetDest)"); - } - if(!GetArgument(args,3,count)) - { - throw VMException("ByteArray.CopyTo fourth argument must be a Long (length)"); - } - size_t offsrc = (size_t)offsetSrc; - size_t offdest = (size_t)offsetDest; - size_t len = (size_t)count; - - if(offsrc > bArray->data.size()) - { - offsrc = bArray->data.size(); - } - - if(offdest > bArray2->data.size()) - { - offdest = bArray2->data.size(); - } - - len = std::min(std::min(bArray->data.size()-offsrc,bArray2->data.size()-offdest),len); - - if(len > 0) - memcpy(bArray2->data.data()+offdest,bArray->data.data()+offsrc,len); - cse.back()->Push(gc,bArray2); - return false; - } - if(key == "Insert") - { - if(args.size() != 4) - { - throw VMException("ByteArray.Insert must only accept 4 arguments"); - } - //Insert(offsetDest, buffer, offsetSrc, length) - TByteArray* bArray2; - int64_t offsetSrc; - int64_t offsetDest; - int64_t count; - if(!GetArgumentHeap(args,1,bArray2)) - { - throw VMException("ByteArray.Insert second argument must be a ByteArray"); - } - if(!GetArgument(args,0, offsetSrc)) - { - throw VMException("ByteArray.Insert first argument must be a Long (offsetSrc)"); - } - if(!GetArgument(args,2, offsetDest)) - { - throw VMException("ByteArray.Insert third argument must be a Long (offsetDest)"); - } - if(!GetArgument(args,3,count)) - { - throw VMException("ByteArray.Insert fourth argument must be a Long (length)"); - } - - size_t offsrc = (size_t)offsetSrc; - size_t offdest = (size_t)offsetDest; - size_t len = (size_t)count; - - if(offsrc > bArray->data.size()) - { - offsrc = bArray->data.size(); - } - if(offdest > bArray->data.size()) - { - offdest = bArray->data.size(); - } - - len = std::min(len,bArray2->data.size()-offsrc); - - - bArray->data.insert(bArray->data.begin()+offdest,bArray2->data.begin()+offsrc,bArray2->data.begin()+offsrc+len); - cse.back()->Push(gc, bArray); - return false; - } - if(key == "Append") - { - if(args.size() != 3) - { - throw VMException("ByteArray.Append must only accept 3 arguments"); - } - TByteArray* bArray2; - int64_t offset; - int64_t count; - if(!GetArgumentHeap(args,0,bArray2)) - { - throw VMException("ByteArray.Append first argument must be a ByteArray"); - } - if(!GetArgument(args,1, offset)) - { - throw VMException("ByteArray.Append second argument must be a Long (offset)"); - } - if(!GetArgument(args,2,count)) - { - throw VMException("ByteArray.Append third argument must be a Long (length)"); - } - size_t off = (size_t)offset; - size_t len = (size_t)count; - - if(off > bArray->data.size()) - { - off = bArray->data.size(); - } - - len = std::min(bArray->data.size() - off,len); - bArray->data.insert(bArray->data.end(),bArray2->data.begin()+off,bArray2->data.begin()+off+len); - cse.back()->Push(gc,bArray); - return false; - } - - if(key == "Resize") - { - if(args.size() != 1) - { - throw VMException("ByteArray.Resize must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("ByteArray.Resize must only accept a long"); - } - - size_t len = (size_t)std::get(args[0]); - if(len >= 0) - { - bArray->data.resize(len); - } - cse.back()->Push(gc, bArray); - return false; - } - - - cse.back()->Push(gc, Undefined()); - return false; - } - else if(aArray != nullptr) - { - if(key == "ToString") - { - cse.back()->Push(gc,ToString(gc,aArray)); - return false; - } - else if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("AArray.GetAt must only accept one argument"); - } - cse.back()->Push(gc, aArray->Get(gc,args[0])); - return false; - } - else if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("AArray.SetAt must only accept two arguments"); - } - aArray->Set(gc,args[0],args[1]); - cse.back()->Push(gc, args[1]); - return false; - } - else if(key == "GetKey") - { - if(args.size() != 1) - { - throw VMException("AArray.GetKey must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.GetKey must only accept a long"); - } - - gc->BarrierBegin(); - auto res = aArray->GetKey(std::get(args[0])); - gc->BarrierEnd(); - cse.back()->Push(gc, res); - return false; - } - else if(key == "GetValue") - { - if(args.size() != 1) - { - throw VMException("AArray.GetValue must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.GetValue must only accept a long"); - } - - gc->BarrierBegin(); - auto res = aArray->GetValue(std::get(args[0])); - gc->BarrierEnd(); - cse.back()->Push(gc, res); - return false; - } - else if(key == "SetKey") - { - if(args.size() != 2) - { - throw VMException("AArray.SetKey must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.SetKey first argument must only accept a long"); - } - - gc->BarrierBegin(); - aArray->SetKey(std::get(args[0]),args[1]); - gc->BarrierEnd(); - cse.back()->Push(gc, args[1]); - return false; - } - else if(key == "SetValue") - { - if(args.size() != 2) - { - throw VMException("AArray.SetValue must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("AArray.SetValue first argument must only accept a long"); - } - - gc->BarrierBegin(); - aArray->SetValue(std::get(args[0]),args[1]); - gc->BarrierEnd(); - cse.back()->Push(gc, args[1]); - return false; - } - else if(key == "Count" || key == "Length") - { - gc->BarrierBegin(); - cse.back()->Push(gc, aArray->Count()); - gc->BarrierEnd(); - return false; - } - else if(key == "GetEnumerator") - { - - cse.back()->Push(gc,TAssociativeArrayEnumerator::Create(ls,aArray)); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - else if(list != nullptr) - { - - if(key == "GetEnumerator") - { - cse.back()->Push(gc, TListEnumerator::Create(ls,list)); - return false; - } - else if(key == "ToString") - { - - cse.back()->Push(gc,Json_Encode(list)); - return false; - - } - else if(key == "Insert") - { - if(args.size() != 2) - { - throw VMException("List.Insert must only accept two arguments"); - } - int64_t index; - - if(!GetArgument(args,0,index)) - { - throw VMException("List.Insert first argument must be Long"); - } - - gc->BarrierBegin(); - list->Insert(index,args[1]); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Add") - { - if(args.size() != 1) - { - throw VMException("List.Add must only accept one argument"); - } - gc->BarrierBegin(); - list->Add(args[0]); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Contains") - { - if(args.size() != 1) - { - throw VMException("List.Contains must only accept one argument"); - } - gc->BarrierBegin(); - for(int64_t i = 0; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - cse.back()->Push(gc, true); - return false; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, false); - return false; - } - else if(key == "IndexOf") - { - //IndexOf(obj, $idx) - if(args.size() < 1 || args.size() > 2) - { - throw VMException("List.IndexOf must either have one or two arguments"); - } - - int64_t i=0; - - GetArgument(args,1,i); - gc->BarrierBegin(); - for(; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - - cse.back()->Push(gc,i); - return false; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc,(int64_t)-1); - return false; - } - else if(key == "RemoveAllEqual") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAllEqual must only accept one argument"); - } - - - gc->BarrierBegin(); - for(int64_t i = 0; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - gc->BarrierBegin(); - list->RemoveAt(i); - i--; - }else gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Remove") - { - if(args.size() != 1) - { - throw VMException("List.Remove must only accept one argument"); - } - - - gc->BarrierBegin(); - for(int64_t i = 0; i < list->Count(); i++) - { - auto item = list->Get(i); - gc->BarrierEnd(); - if(Equals(gc,args[0],item)) - { - gc->BarrierBegin(); - list->RemoveAt(i); - gc->BarrierEnd(); - break; - } - gc->BarrierBegin(); - } - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "RemoveAt") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.RemoveAt must only accept a long"); - } - gc->BarrierBegin(); - list->RemoveAt(std::get(args[0])); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "Clear") - { - gc->BarrierBegin(); - list->Clear(); - gc->BarrierEnd(); - cse.back()->Push(gc, Undefined()); - return false; - } - else if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("List.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.GetAt must only accept a long"); - } - - int64_t index = std::get(args[0]); - if(index >= 0 && index < list->Count()) - { - cse.back()->Push(gc, list->Get(index)); - return false; - } - - } - else if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("List.SetAt must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.SetAt first argument must only accept a long"); - } - - int64_t index = std::get(args[0]); - if(index >= 0 && index < list->Count()) - { - list->Set(index,args[1]); - return false; - } - - } - - else if(key == "Count" || key == "Length") - { - gc->BarrierBegin(); - cse.back()->Push(gc, list->Count()); - gc->BarrierEnd(); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(dynList != nullptr) - { - - if(key == "GetEnumerator") - { - cse.back()->Push(gc, TDynamicListEnumerator::Create(ls, dynList)); - return false; - } - else if(key == "ToString") - { - cse.back()->Push(gc, dynList->ToString(ls)); - return false; - } - else if(key == "Insert") - { - if(args.size() != 2) - { - throw VMException("List.Insert must only accept two arguments"); - } - int64_t index; - - if(!GetArgument(args,0,index)) - { - throw VMException("List.Insert first argument must be Long"); - } - - cse.back()->Push(gc, dynList->Insert(ls,index,args[0])); - return false; - } - if(key == "Add") - { - if(args.size() != 1) - { - throw VMException("List.Add must only accept one argument"); - } - - cse.back()->Push(gc,dynList->Add(ls,args[0])); - return false; - } - if(key == "RemoveAllEqual") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAllEqual must only accept one argument"); - } - - cse.back()->Push(gc,dynList->RemoveAllEqual(ls, args[0])); - return false; - } - if(key == "Remove") - { - if(args.size() != 1) - { - throw VMException("List.Remove must only accept one argument"); - } - - - - cse.back()->Push(gc,dynList->Remove(ls, args[0])); - return false; - } - if(key == "RemoveAt") - { - if(args.size() != 1) - { - throw VMException("List.RemoveAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.RemoveAt must only accept a long"); - } - cse.back()->Push(gc,dynList->RemoveAt(ls,std::get(args[0]))); - - return false; - } - if(key == "Clear") - { - - - cse.back()->Push(gc, dynList->Clear(ls)); - return false; - } - if(key == "GetAt") - { - if(args.size() != 1) - { - throw VMException("List.GetAt must only accept one argument"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.GetAt must only accept a long"); - } - - int64_t index = std::get(args[0]); - if(index >= 0) - { - cse.back()->Push(gc, dynList->GetAt(ls,index)); - return false; - } - - } - if(key == "SetAt") - { - if(args.size() != 2) - { - throw VMException("List.SetAt must only accept two arguments"); - } - - if(!std::holds_alternative(args[0])) - { - throw VMException("List.SetAt first argument must only accept a long"); - } - - int64_t index = std::get(args[0]); - if(index >= 0) - { - cse.back()->Push(gc,dynList->SetAt(ls,index,args[1])); - return false; - } - - } - - if(key == "Count" || key == "Length") - { - cse.back()->Push(gc, dynList->Count(ls)); - - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,key); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,args); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,args)); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - else if(dict != nullptr) - { - if(key == "ToString" && !dict->MethodExists(ls, key) && args.empty()) - { - cse.back()->Push(gc,Json_Encode(dict)); - return false; - } - gc->BarrierBegin(); - auto o = dict->GetValue(key); - gc->BarrierEnd(); - - - return InvokeMethod(ls,o,dict,args); - } - else if(dynDict != nullptr) - { - - - cse.back()->Push(gc,dynDict->CallMethod(ls, key, args)); - - return false; - } - else if(callable != nullptr) - { - if(key == "Call") - { - TList* argls; - if(GetArgumentHeap(args,0,argls)) - { - TClosure* clo = dynamic_cast(callable); - if(clo != nullptr) - { - AddCallStackEntry(ls,clo,argls->items); - return true; - } - else - { - cse.back()->Push(gc,callable->Call(ls, argls->items)); - return false; - } - } - } - cse.back()->Push(gc,nullptr); - return false; - } - else - { - cse.back()->Push(gc, Undefined()); - } - } - else - { - cse.back()->Push(gc,Undefined()); - } - } - - - return false; - } + bool InterperterThread::Yield(GC* gc) { GCList ls(gc); @@ -5635,1003 +1938,7 @@ namespace Tesses::CrossLang { } return false; } - bool InterperterThread::GetField(GC* gc) - { - std::vector& cse=this->call_stack_entries; - - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - TObject _key = stk->Pop(ls); - - - TObject instance = stk->Pop(ls); - - if(!std::holds_alternative(_key)) - { - stk->Push(gc,Undefined()); - return false; - } - - std::string key = std::get(_key); - - - if(std::holds_alternative(instance)) - { - std::string str = std::get(instance); - - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)str.size(); - if(len < 0) len = 0; - - cse.back()->Push(gc, len); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto vfs = std::get>(instance); - auto tmpFS=std::dynamic_pointer_cast(vfs); - if(tmpFS) - { - if(key == "TempDirectoryName") - { - - cse.back()->Push(gc,tmpFS->TempDirectoryName()); - return false; - } - } - cse.back()->Push(gc,Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto writer = std::get>(instance); - auto stringWriter = std::dynamic_pointer_cast(writer); - if(stringWriter != nullptr) - { - if(key == "Text") - { - cse.back()->Push(gc, stringWriter->GetString()); - return false; - } - } - if(key == "NewLine") - { - cse.back()->Push(gc,writer->newline); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto strm = std::get>(instance); - if(strm != nullptr) - { - auto netStrm = std::dynamic_pointer_cast(strm); - - if(key == "CanRead") - { - - - cse.back()->Push(gc, strm->CanRead()); - return false; - } - if(key == "CanWrite") - { - - cse.back()->Push(gc, strm->CanWrite()); - return false; - } - if(key == "CanSeek") - { - - - cse.back()->Push(gc, strm->CanSeek()); - return false; - } - if(key == "EndOfStream") - { - - cse.back()->Push(gc, strm->EndOfStream()); - return false; - } - if(key == "Length") - { - - cse.back()->Push(gc, strm->GetLength()); - return false; - } - if(key == "Position") - { - - cse.back()->Push(gc, strm->GetPosition()); - return false; - } - - if(netStrm != nullptr) - { - if(key == "Port") - { - cse.back()->Push(gc, netStrm->GetPort()); - return false; - } - } - - cse.back()->Push(gc, Undefined()); - - return false; - - } - } - if(std::holds_alternative(instance)) - { - TVMVersion& version = std::get(instance); - if(key == "Major") - { - stk->Push(gc, (int64_t)version.Major()); - return false; - } - if(key == "Minor") - { - stk->Push(gc, (int64_t)version.Minor()); - return false; - } - if(key == "Patch") - { - stk->Push(gc, (int64_t)version.Patch()); - return false; - } - if(key == "Build") - { - stk->Push(gc, (int64_t)version.Build()); - return false; - } - if(key == "VersionInt") - { - stk->Push(gc,(int64_t)version.AsLong()); - return false; - } - if(key == "Stage") - { - switch(version.VersionStage()) - { - case TVMVersionStage::DevVersion: - stk->Push(gc,"dev"); - break; - case TVMVersionStage::AlphaVersion: - stk->Push(gc,"alpha"); - break; - case TVMVersionStage::BetaVersion: - stk->Push(gc,"beta"); - break; - case TVMVersionStage::ProductionVersion: - stk->Push(gc,"prod"); - break; - } - return false; - } - - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto time = std::get>(instance); - if(key == "Days") - { - stk->Push(gc, (int64_t)time->Days()); - return false; - } - if(key == "Hours") - { - stk->Push(gc, (int64_t)time->Hours()); - return false; - } - - if(key == "Minutes") - { - stk->Push(gc, (int64_t)time->Minutes()); - return false; - } - if(key == "Seconds") - { - stk->Push(gc, (int64_t)time->Seconds()); - return false; - } - - if(key == "TotalHours") - { - stk->Push(gc, time->TotalHours()); - return false; - } - - if(key == "TotalMinutes") - { - stk->Push(gc, time->TotalMinutes()); - return false; - } - - if(key == "TotalSeconds") - { - stk->Push(gc, time->TotalSeconds()); - return false; - } - - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto& date = std::get>(instance); - if(key == "IsLocal") - { - stk->Push(gc, date->IsLocal()); - return false; - } - if(key == "Year") - { - stk->Push(gc, (int64_t)date->Year()); - return false; - } - if(key == "Month") - { - stk->Push(gc, (int64_t)date->Month()); - return false; - } - if(key == "Day") - { - stk->Push(gc, (int64_t)date->Day()); - return false; - } - if(key == "Hour") - { - stk->Push(gc, (int64_t)date->Hour()); - return false; - } - if(key == "Minute") - { - stk->Push(gc, (int64_t)date->Minute()); - return false; - } - if(key == "Second") - { - stk->Push(gc, (int64_t)date->Second()); - return false; - } - if(key == "DayOfWeek") - { - stk->Push(gc, (int64_t)date->DayOfWeek()); - return false; - } - - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative(instance)) - { - auto obj = std::get(instance).obj; - auto bA = dynamic_cast(obj); - auto list = dynamic_cast(obj); - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto dynList = dynamic_cast(obj); - auto tcallable = dynamic_cast(obj); - auto closure = dynamic_cast(obj); - auto externalMethod = dynamic_cast(obj); - auto ittr = dynamic_cast(obj); - - auto callstackEntry = dynamic_cast(obj); - auto file = dynamic_cast(obj); - auto chunk = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - auto aarray = dynamic_cast(obj); - auto task = dynamic_cast(obj); - if(task != nullptr) - { - if(key == "IsCompleted") - { - cse.back()->Push(gc,task->IsCompleted()); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - if(aarray != nullptr) - { - if(key == "Count" || key == "Length") - { - cse.back()->Push(gc,aarray->Count()); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - else if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"get"+key); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{})); - return false; - } - cse.back()->Push(gc,cls->GetValue(cse.back()->callable->className,key)); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc,natObj->CallMethod(ls,"get"+key,{})); - return false; - } - - if(file != nullptr) - { - if(key == "Version") - { - cse.back()->Push(gc,file->version); - return false; - } - else if(key == "Name") - { - cse.back()->Push(gc,file->name); - return false; - } - else if(key == "Info") - { - cse.back()->Push(gc, file->info); - return false; - } - else if(key == "Dependencies") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->dependencies) - { - auto res = TDictionary::Create(ls); - res->SetValue("Name", item.first); - res->SetValue("Version", item.second); - list->Add(res); - } - gc->BarrierEnd(); - cse.back()->Push(gc, list); - return false; - } - else if(key == "Tools") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->tools) - { - auto res = TDictionary::Create(ls); - res->SetValue("Name", item.first); - res->SetValue("Version", item.second); - list->Add(res); - } - gc->BarrierEnd(); - cse.back()->Push(gc, list); - return false; - } - else if(key == "Strings") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->name) - { - list->Add(item); - } - gc->BarrierEnd(); - - cse.back()->Push(gc, list); - return false; - } - else if(key == "MetadataCount") - { - - cse.back()->Push(gc, (int64_t)file->metadata.size()); - return false; - } - else if(key == "Metadata") - { - TList* meta = TList::Create(ls); - gc->BarrierBegin(); - for(size_t i = 0; i < file->metadata.size(); i++) - { - meta->Add( - TDictionary::Create(ls, - { - TDItem("Name", file->metadata[i].first), - TDItem("Index",(int64_t)i) - } - ) - ); - } - gc->BarrierEnd(); - - cse.back()->Push(gc, meta); - return false; - } - else if(key == "Sections") - { - TList* sections = TList::Create(ls); - gc->BarrierBegin(); - for(auto& item : file->sections) - { - TByteArray* ba = TByteArray::Create(ls); - ba->data = item.second; - sections->Add(TDictionary::Create(ls,{ - TDItem("Name", item.first), - TDItem("Data", ba) - })); - } - gc->BarrierEnd(); - - cse.back()->Push(gc, sections); - return false; - } - else if(key == "SupportedVMs") - { - TList* supported = TList::Create(ls); - gc->BarrierBegin(); - if(file->vms.empty()) - { - supported->Add(TDictionary::Create(ls,{ - TDItem("Name",std::string(VMName)), - TDItem("HowToGet",std::string(VMHowToGet)) - })); - } - else { - for(auto item : file->vms) - supported->Add(TDictionary::Create(ls,{ - TDItem("Name",item.first), - TDItem("HowToGet",item.second) - })); - } - gc->BarrierEnd(); - cse.back()->Push(gc, supported); - return false; - } - else if(key == "Chunks") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : file->chunks) - { - list->Add(item); - } - - gc->BarrierEnd(); - - cse.back()->Push(gc, list); - return false; - } - else if(key == "Classes") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - - for(uint32_t i = 0; i < (uint32_t)file->classes.size(); i++) - { - list->Add(GetClassInfo(ls,file,i)); - } - - cse.back()->Push(gc, list); - gc->BarrierEnd(); - return false; - } - else if(key == "Functions") - { - auto list = TList::Create(ls); - gc->BarrierBegin(); - for(auto& item : file->functions) - { - TDictionary* dict = TDictionary::Create(ls); - if(!item.first.empty()) - dict->SetValue("Documentation", item.first[0]); - TList* nameParts = TList::Create(ls); - for(size_t i = 1; i < item.first.size(); i++) - { - nameParts->Add(item.first[i]); - } - dict->SetValue("NameParts", nameParts); - dict->SetValue("ChunkId", (int64_t)item.second); - - list->Add(dict); - } - - cse.back()->Push(gc, list); - gc->BarrierEnd(); - return false; - } - else if(key == "Icon") - { - if(file->icon >= 0 && file->icon < file->resources.size()) - { - TByteArray* ba = TByteArray::Create(ls); - ba->data = file->resources[file->icon]; - cse.back()->Push(gc, ba); - return false; - } - else { - cse.back()->Push(gc, nullptr); - return false; - } - } - cse.back()->Push(gc, Undefined()); - return false; - } - if(chunk != nullptr) - { - if(key == "Arguments") - { - auto myargs = TList::Create(ls); - gc->BarrierBegin(); - for(auto item : chunk->args) - { - myargs->Add(item); - } - gc->BarrierEnd(); - cse.back()->Push(gc, myargs); - return false; - } - if(key == "Code") - { - auto ba = TByteArray::Create(ls); - ba->data = chunk->code; - cse.back()->Push(gc, ba); - return false; - } - if(key == "File") - { - cse.back()->Push(gc, chunk->file); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - if(callstackEntry != nullptr) - { - if(key == "IP") - { - cse.back()->Push(gc, (int64_t)callstackEntry->ip); - return false; - } - if(key == "IsDone") - { - cse.back()->Push(gc, callstackEntry->ip >= callstackEntry->callable->closure->code.size()); - return false; - } - if(key == "Closure") - { - cse.back()->Push(gc, callstackEntry->callable); - return false; - } - if(key == "StackEmpty") - { - cse.back()->Push(gc, callstackEntry->stack.empty()); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - - - - - if(ittr != nullptr) - { - if(key == "Current") - { - cse.back()->Push(gc, ittr->GetCurrent(ls)); - return false; - } - cse.back()->Push(gc, Undefined()); - return false; - } - if(closure != nullptr) - { - if(key == "Arguments") - { - GCList ls2(gc); - TList* ls = TList::Create(ls2); - for(auto arg : closure->closure->args) - { - ls->Add(arg); - } - cse.back()->Push(gc,ls); - return false; - } - if(key == "File") - { - cse.back()->Push(gc,closure->file); - return false; - } - } - if(externalMethod != nullptr) - { - if(key == "Arguments") - { - GCList ls2(gc); - TList* ls = TList::Create(ls2); - for(auto arg : externalMethod->args) - { - ls->Add(arg); - } - cse.back()->Push(gc,ls); - return false; - } - } - - if(tcallable != nullptr) - { - if(key == "Documentation") - { - cse.back()->Push(gc, tcallable->documentation); - return false; - } - if(key == "Tag") - { - gc->BarrierBegin(); - cse.back()->Push(gc, tcallable->tag); - gc->BarrierEnd(); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - - if(bA != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = (int64_t)bA->data.size(); - if(len < 0) len = 0; - - stk->Push(gc, len); - return false; - } - } - if(list != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = list->Count(); - if(len < 0) len = 0; - - stk->Push(gc, len); - return false; - } - } - if(dynList != nullptr) - { - if(key == "Count" || key == "Length") - { - int64_t len = dynList->Count(ls); - if(len < 0) len = 0; - - stk->Push(gc, len); - return false; - } - } - if(dynDict != nullptr) - { - if(dynDict->MethodExists(ls,"get" + key)) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"get" + key, {})); - } - else - { - cse.back()->Push(gc, dynDict->GetField(ls,key)); - } - return false; - } - - if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("get" + key); - gc->BarrierEnd(); - if(std::holds_alternative(fn) && dynamic_cast(std::get(fn).obj) != nullptr) - { - return InvokeOne(ls,fn, dict); - } - else - { - gc->BarrierBegin(); - fn = dict->GetValue(key); - stk->Push(gc, fn); - gc->BarrierEnd(); - return false; - } - } - - } - - stk->Push(gc, Undefined()); - } - - return false; - } - bool InterperterThread::SetField(GC* gc) - { - std::vector& cse=this->call_stack_entries; - - if(!cse.empty()) - { - auto stk = cse.back(); - GCList ls(gc); - TObject value = stk->Pop(ls); - TObject _key = stk->Pop(ls); - TObject instance = stk->Pop(ls); - - if(!std::holds_alternative(_key)) - { - stk->Push(gc,Undefined()); - return false; - } - - std::string key = std::get(_key); - if(std::holds_alternative>(instance)) - { - auto writer = std::get>(instance); - auto stringWriter = std::dynamic_pointer_cast(writer); - if(stringWriter != nullptr) - { - if(key == "Text") - { - if(std::holds_alternative(value)) - { - stringWriter->GetString() = std::get(value); - } - cse.back()->Push(gc, stringWriter->GetString()); - return false; - } - } - if(key == "NewLine") - { - if(std::holds_alternative(value)) - { - writer->newline = std::get(value); - } - cse.back()->Push(gc,writer->newline); - return false; - } - cse.back()->Push(gc,Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto svr = std::get>(instance); - auto bas = std::dynamic_pointer_cast(svr); - auto cgi = std::dynamic_pointer_cast(svr); - auto changable = std::dynamic_pointer_cast(svr); - if(changable != nullptr) - { - if(key == "Server") - { - bas->server = ToHttpServer(gc,value); - stk->Push(gc,value); - return false; - } - } - - if(bas != nullptr) - { - if(key == "Realm") - { - bool val; - if(GetObject(value,val)) - { - bas->realm = val; - stk->Push(gc,val ); - - return false; - } - } - if(key == "Server") - { - bas->server = ToHttpServer(gc,value); - stk->Push(gc,value); - return false; - } - if(key == "Authorization") - { - TCallable* val; - if(GetObjectHeap(value,val)) - { - auto marked= CreateMarkedTObject(ls, val); - bas->authorization = [marked](std::string user,std::string password)->bool { - GCList ls(marked->GetGC()); - TCallable* callable; - if(GetObjectHeap(marked->GetObject(), callable)) - { - return ToBool(callable->Call(ls,{user,password})); - } - return false; - }; - stk->Push(gc,val); - - return false; - } - } - } - - if(cgi != nullptr) - { - if(key == "WorkingDirectory") - { - Tesses::Framework::Filesystem::VFSPath path; - if(GetObjectAsPath(value,path)) - { - cgi->workingDirectory = path; - stk->Push(gc,path); - return false; - } - else { - cgi->workingDirectory = std::nullopt; - stk->Push(gc,nullptr); - return false; - } - - } - if(key == "DocumentRoot") - { - Tesses::Framework::Filesystem::VFSPath path; - if(GetObjectAsPath(value,path)) - { - cgi->document_root= path; - stk->Push(gc,path); - return false; - } - else { - cgi->document_root= std::nullopt; - stk->Push(gc,nullptr); - return false; - } - - } - if(key == "AdminEmail") - { - std::string str; - if(GetObject(value,str)) - { - cgi->adminEmail = str; - stk->Push(gc,str); - return false; - } - else { - cgi->adminEmail= std::nullopt; - stk->Push(gc,nullptr); - return false; - } - - } - } - - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative>(instance)) - { - auto strm = std::get>(instance); - - auto netStrm = std::dynamic_pointer_cast(strm); - if(netStrm != nullptr) - { - bool bc; - if(key == "Broadcast" && GetObject(value,bc)) - netStrm->SetBroadcast(bc); - if(key == "NoDelay" && GetObject(value,bc)) - netStrm->SetNoDelay(bc); - } - stk->Push(gc, Undefined()); - return false; - } - if(std::holds_alternative(instance)) - { - auto obj = std::get(instance).obj; - - auto dict = dynamic_cast(obj); - auto dynDict = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - if(cls != nullptr) - { - gc->BarrierBegin(); - auto obj=cls->GetValue(cse.back()->callable->className,"set"+key); - gc->BarrierEnd(); - TClosure* clos; - TCallable* callable; - if(GetObjectHeap(obj,clos)) - { - this->AddCallStackEntry(ls,clos,{value}); - return true; - } - else if(GetObjectHeap(obj,callable)) - { - cse.back()->Push(gc,callable->Call(ls,{value})); - return false; - } - gc->BarrierBegin(); - cls->SetValue(cse.back()->callable->className,key,value); - gc->BarrierEnd(); - cse.back()->Push(gc,value); - return false; - - } - else - if(natObj != nullptr) - { - cse.back()->Push(gc,natObj->CallMethod(ls,"set"+key,{value})); - return false; - } - auto tcallable = dynamic_cast(obj); - if(tcallable != nullptr) - { - if(key == "Tag") - { - gc->BarrierBegin(); - tcallable->tag = value; - gc->BarrierEnd(); - cse.back()->Push(gc,nullptr); - return false; - } - } - if(dynDict != nullptr) - { - if(dynDict->MethodExists(ls,"set" + key)) - { - cse.back()->Push(gc,dynDict->CallMethod(ls,"set" + key, {value})); - } - else - { - dynDict->SetField(ls,key,value); - cse.back()->Push(gc,value); - } - return false; - } - if(dict != nullptr) - { - gc->BarrierBegin(); - TObject fn = dict->GetValue("set" + key); - gc->BarrierEnd(); - if(std::holds_alternative(fn) && dynamic_cast(std::get(fn).obj) != nullptr) - { - return InvokeTwo(ls,fn, dict, value); - } - else - { - gc->BarrierBegin(); - dict->SetValue(key, value); - stk->Push(gc, value); - gc->BarrierEnd(); - return false; - } - } - - } - stk->Push(gc, Undefined()); - - } - return false; - } - + bool InterperterThread::GetVariable(GC* gc) { std::vector& cse=this->call_stack_entries; @@ -8188,120 +3495,5 @@ namespace Tesses::CrossLang { ls.GetGC()->BarrierEnd(); } - std::string ToString(GC* gc, TObject o) - { - if(std::holds_alternative(o)) - { - return std::get(o).ToString(); - } - if(std::holds_alternative(o)) - { - return std::get(o); - } - if(std::holds_alternative(o)) - { - return std::get(o).ToString(); - } - if(std::holds_alternative(o)) - { - return std::to_string(std::get(o)); - } - - if(std::holds_alternative(o)) - { - return std::to_string(std::get(o)); - } - - if(std::holds_alternative(o)) - { - return std::string{std::get(o)}; - } - if(std::holds_alternative(o)) - { - return "null"; - } - if(std::holds_alternative(o)) - { - return "undefined"; - } - if(std::holds_alternative(o)) - { - return std::get(o) ? "true" : "false"; - } - if(std::holds_alternative>(o)) - { - return std::get>(o)->ToString(); - } - if(std::holds_alternative>(o)) - { - return std::get>(o)->ToString(false); - } - if(std::holds_alternative(o)) - { - auto obj = std::get(o).obj; - auto dict = dynamic_cast(obj); - auto list = dynamic_cast(obj); - auto bArray = dynamic_cast(obj); - auto natObj = dynamic_cast(obj); - auto cls = dynamic_cast(obj); - auto aArray = dynamic_cast(obj); - if(aArray != nullptr) - { - - std::string str={}; - - gc->BarrierBegin(); - bool first=true; - for(auto item : aArray->items) - { - if(!first) str.push_back('\n'); - first=false; - str.push_back('['); - str.append(Json_Encode(item.first)); - str.append("] = "); - str.append(Json_Encode(item.second)); - str.append(";"); - } - gc->BarrierEnd(); - return str; - } - if(cls != nullptr) - { - auto res = cls->GetValue("","ToString"); - TCallable* call; - GCList ls(gc); - if(GetObjectHeap(res,call)) return ToString(gc, call->Call(ls,{})); - return cls->TypeName(); - } - if(natObj != nullptr) - { - GCList ls(gc); - TObject o=natObj->CallMethod(ls,"ToString",{}); - - - return ToString(gc, o); - } - - if(dict != nullptr) - { - GCList ls(gc); - if(dict->MethodExists(ls,"ToString")) - return ToString(gc,dict->CallMethod(ls,"ToString",{})); - else - { - return Json_Encode(dict); - } - } - else if(bArray != nullptr) - { - return std::string(bArray->data.begin(),bArray->data.end()); - } - else if(list != nullptr) - { - return Json_Encode(list); - } - } - - return ""; - } + }