mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-04-15 21:27:03 +00:00
Add uuid support
This commit is contained in:
2
.clangd
2
.clangd
@@ -1,2 +0,0 @@
|
||||
CompileFlags: # Tweak the parse settings, example directory given to show format
|
||||
Add: ["-Iinclude","-std=gnu++17"]
|
||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -84,7 +84,11 @@
|
||||
"stack": "cpp",
|
||||
"stdfloat": "cpp"
|
||||
},
|
||||
|
||||
"clangd.fallbackFlags": [
|
||||
"-Iinclude"
|
||||
"-I${workspaceFolder}/include",
|
||||
"-I/home/mike/tmp-crosslang/usr/local/include/"
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Maintainer: Mike Nolan <tesses@tesses.net>
|
||||
pkgname=crosslang # '-bzr', '-git', '-hg' or '-svn'
|
||||
pkgver=0.0.1
|
||||
pkgver=0.0.2
|
||||
pkgrel=1
|
||||
pkgdesc=""
|
||||
arch=('x86_64' 'powerpc')
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
|
||||
export DEB_VERSION=0.0.1
|
||||
export DEB_VERSION=0.0.2
|
||||
7
changelog.md
Normal file
7
changelog.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Changelog
|
||||
|
||||
## 0.0.2
|
||||
Add uuids and bytestreams
|
||||
|
||||
## 0.0.1
|
||||
Start versioning
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <any>
|
||||
|
||||
#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<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion,std::shared_ptr<Tesses::Framework::Date::DateTime>,std::shared_ptr<Tesses::Framework::Date::TimeSpan>,TBreak,TContinue,std::shared_ptr<Tesses::Framework::Streams::Stream>,std::shared_ptr<Tesses::Framework::Filesystem::VFS>,std::shared_ptr<Tesses::Framework::Http::IHttpServer>,std::shared_ptr<Tesses::Framework::Http::HttpRequestBody>,std::shared_ptr<Tesses::Framework::TextStreams::TextReader>,std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>;
|
||||
using TObject = std::variant<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion,std::shared_ptr<Tesses::Framework::Date::DateTime>,std::shared_ptr<Tesses::Framework::Date::TimeSpan>,TBreak,TContinue,std::shared_ptr<Tesses::Framework::Streams::Stream>,std::shared_ptr<Tesses::Framework::Filesystem::VFS>,std::shared_ptr<Tesses::Framework::Http::IHttpServer>,std::shared_ptr<Tesses::Framework::Http::HttpRequestBody>,std::shared_ptr<Tesses::Framework::TextStreams::TextReader>,std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>,std::shared_ptr<Tesses::Framework::Streams::ByteReader>,std::shared_ptr<Tesses::Framework::Streams::ByteWriter>, 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
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
@@ -131,6 +132,10 @@ namespace Tesses::CrossLang
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return list;
|
||||
}
|
||||
static TObject Env_getLittleEndian(GCList& ls, std::vector<TObject> 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);
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Streams/Stream.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <memory>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#if defined(CROSSLANG_ENABLE_SHARED)
|
||||
#if defined(CROSSLANG_ENABLE_FFI)
|
||||
#include <ffi.h>
|
||||
@@ -568,6 +574,23 @@ namespace Tesses::CrossLang
|
||||
std::shared_ptr<Tesses::Framework::TextStreams::TextWriter> strm;
|
||||
return GetArgument(args,0,strm);
|
||||
}
|
||||
static TObject TypeIsByteReader(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
std::shared_ptr<Tesses::Framework::Streams::ByteReader> strm;
|
||||
return GetArgument(args,0,strm);
|
||||
}
|
||||
static TObject TypeIsByteWriter(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
std::shared_ptr<Tesses::Framework::Streams::ByteWriter> strm;
|
||||
return GetArgument(args,0,strm);
|
||||
}
|
||||
static TObject TypeIsUuid(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
return std::holds_alternative<Tesses::Framework::Uuid>(args[0]);
|
||||
}
|
||||
static TObject TypeIsVFS(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
if(args.empty()) return nullptr;
|
||||
@@ -741,6 +764,11 @@ namespace Tesses::CrossLang
|
||||
if(std::holds_alternative<TVMVersion>(_obj)) return "Version";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(_obj)) return "DateTime";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(_obj)) return "TimeSpan";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::ByteReader>>(_obj)) return "ByteReader";
|
||||
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::ByteWriter>>(_obj)) return "ByteWriter";
|
||||
|
||||
if(std::holds_alternative<Tesses::Framework::Uuid>(_obj)) return "Uuid";
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::Stream>>(_obj))
|
||||
{
|
||||
auto strm = std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(_obj);
|
||||
@@ -1222,6 +1250,21 @@ namespace Tesses::CrossLang
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
static TObject New_ByteReader(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||
if(GetArgument(args, 0, strm))
|
||||
return std::make_shared<Tesses::Framework::Streams::ByteReader>(strm);
|
||||
return nullptr;
|
||||
}
|
||||
static TObject New_ByteWriter(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> strm;
|
||||
if(GetArgument(args, 0, strm))
|
||||
return std::make_shared<Tesses::Framework::Streams::ByteWriter>(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<TObject> args)->TObject {
|
||||
|
||||
40
src/runtime_methods/uuid.cpp
Normal file
40
src/runtime_methods/uuid.cpp
Normal file
@@ -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<TObject> args)
|
||||
{
|
||||
return Tesses::Framework::Uuid::Generate();
|
||||
}
|
||||
static TObject Uuid_TryParse(GCList& ls, std::vector<TObject> 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<TObject> 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();
|
||||
}
|
||||
}
|
||||
164
src/vm/bc/add.cpp
Normal file
164
src/vm/bc/add.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::Add(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||
GCList ls(gc);
|
||||
auto right = cse.back()->Pop(ls);
|
||||
auto left = cse.back()->Pop(ls);
|
||||
|
||||
|
||||
|
||||
if(std::holds_alternative<std::string>(left) && std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<std::string>(left) + std::get<Tesses::Framework::Filesystem::VFSPath>(right));
|
||||
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc,(char)(std::get<char>(left) + std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (char)(std::get<int64_t>(left) + std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (char)(std::get<char>(left) + std::get<int64_t>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<Tesses::Framework::Filesystem::VFSPath>(left) + std::get<std::string>(right));
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(left) && std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<Tesses::Framework::Filesystem::VFSPath>(left) + std::get<Tesses::Framework::Filesystem::VFSPath>(right));
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) + std::get<int64_t>(right));
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) + std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) + std::get<int64_t>(right));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) + std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::TimeSpan>((*l) + (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::DateTime>((*l) + (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::DateTime>((*l) + (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
std::string str={};
|
||||
str.append(std::get<std::string>(left));
|
||||
str.append(std::get<std::string>(right));
|
||||
cse.back()->Push(gc,str);
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
std::string str={};
|
||||
str.push_back(std::get<char>(left));
|
||||
str.append(std::get<std::string>(right));
|
||||
cse.back()->Push(gc,str);
|
||||
}
|
||||
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
std::string str={};
|
||||
str.append(std::get<std::string>(left));
|
||||
str.push_back(std::get<char>(right));
|
||||
cse.back()->Push(gc,str);
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(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;
|
||||
}
|
||||
}
|
||||
236
src/vm/bc/equals.cpp
Normal file
236
src/vm/bc/equals.cpp
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool Equals(GC* gc, TObject left, TObject right)
|
||||
{
|
||||
GCList ls(gc);
|
||||
if(std::holds_alternative<std::nullptr_t>(left) && std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<Undefined>(left) && std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
return std::get<int64_t>(left) == std::get<int64_t>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
return std::get<double>(left) == std::get<double>(right);
|
||||
}
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
return std::get<double>(left) == std::get<int64_t>(right);
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
return std::get<int64_t>(left) == std::get<double>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
|
||||
{
|
||||
return std::get<std::string>(left) == std::get<std::string>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<bool>(left) && std::holds_alternative<bool>(right))
|
||||
{
|
||||
return std::get<bool>(left) == std::get<bool>(right);
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
return std::get<char>(left) == std::get<char>(right);
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
return std::get<char>(left) == std::get<int64_t>(right);
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
return std::get<int64_t>(left) == std::get<char>(right);
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left)->ToEpoch() == std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right)->ToEpoch();
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(left)->TotalSeconds() == std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right)->TotalSeconds();
|
||||
}
|
||||
else if(std::holds_alternative<TVMVersion>(left) && std::holds_alternative<TVMVersion>(right))
|
||||
{
|
||||
auto lver= std::get<TVMVersion>(left);
|
||||
auto rver = std::get<TVMVersion>(right);
|
||||
auto r = lver.CompareTo(rver);
|
||||
return r == 0;
|
||||
}
|
||||
else if(std::holds_alternative<Tesses::Framework::Uuid>(left) && std::holds_alternative<Tesses::Framework::Uuid>(right))
|
||||
{
|
||||
auto l= std::get<Tesses::Framework::Uuid>(left);
|
||||
auto r = std::get<Tesses::Framework::Uuid>(right);
|
||||
|
||||
return l == r;
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto native = dynamic_cast<TNative*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(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<std::nullptr_t>(right)) {
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(right))
|
||||
{
|
||||
return cls == std::get<THeapObjectHolder>(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<Undefined>(fn))
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(fn))
|
||||
{
|
||||
|
||||
auto obj = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(fn).obj);
|
||||
if(obj != nullptr)
|
||||
{
|
||||
auto closure = dynamic_cast<TClosure*>(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<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
else if(dynDict != nullptr)
|
||||
{
|
||||
auto res = dynDict->CallMethod(ls,"operator==",{right});
|
||||
if(!std::holds_alternative<std::nullptr_t>(res) && std::holds_alternative<Undefined>(res))
|
||||
{
|
||||
return ToBool(res);
|
||||
}
|
||||
}
|
||||
else if(native != nullptr && std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
return native->GetDestroyed();
|
||||
|
||||
}
|
||||
|
||||
if(std::holds_alternative<THeapObjectHolder>(right))
|
||||
{
|
||||
return obj == std::get<THeapObjectHolder>(right).obj;
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if(std::holds_alternative<Undefined>(right))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
3715
src/vm/bc/executemethod2.cpp
Normal file
3715
src/vm/bc/executemethod2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
769
src/vm/bc/getfield.cpp
Normal file
769
src/vm/bc/getfield.cpp
Normal file
@@ -0,0 +1,769 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::GetField(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& 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<std::string>(_key))
|
||||
{
|
||||
stk->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string key = std::get<std::string>(_key);
|
||||
|
||||
|
||||
if(std::holds_alternative<std::string>(instance))
|
||||
{
|
||||
std::string str = std::get<std::string>(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<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(instance))
|
||||
{
|
||||
auto vfs = std::get<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(instance);
|
||||
auto tmpFS=std::dynamic_pointer_cast<Tesses::Framework::Filesystem::TempFS>(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<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
|
||||
{
|
||||
auto writer = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance);
|
||||
auto stringWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringWriter>(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<std::shared_ptr<Tesses::Framework::Streams::ByteReader>>(instance))
|
||||
{
|
||||
auto br = std::get<std::shared_ptr<Tesses::Framework::Streams::ByteReader>>(instance);
|
||||
if(key == "Stream")
|
||||
{
|
||||
cse.back()->Push(gc,br->GetStream());
|
||||
return false;
|
||||
}
|
||||
cse.back()->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::ByteWriter>>(instance))
|
||||
{
|
||||
auto bw = std::get<std::shared_ptr<Tesses::Framework::Streams::ByteWriter>>(instance);
|
||||
if(key == "Stream")
|
||||
{
|
||||
|
||||
cse.back()->Push(gc,bw->GetStream());
|
||||
return false;
|
||||
}
|
||||
cse.back()->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance))
|
||||
{
|
||||
auto strm = std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance);
|
||||
if(strm != nullptr)
|
||||
{
|
||||
auto netStrm = std::dynamic_pointer_cast<Tesses::Framework::Streams::NetworkStream>(strm);
|
||||
|
||||
if(key == "CanRead")
|
||||
{
|
||||
|
||||
|
||||
cse.back()->Push(gc, strm->CanRead());
|
||||
return false;
|
||||
}
|
||||
if(key == "CanWrite")
|
||||
{
|
||||
|
||||
cse.back()->Push(gc, strm->CanWrite());
|
||||
return false;
|
||||
}
|
||||
if(key == "CanSeek")
|
||||
{
|
||||
|
||||
|
||||
cse.back()->Push(gc, strm->CanSeek());
|
||||
return false;
|
||||
}
|
||||
if(key == "EndOfStream")
|
||||
{
|
||||
|
||||
cse.back()->Push(gc, strm->EndOfStream());
|
||||
return false;
|
||||
}
|
||||
if(key == "Length")
|
||||
{
|
||||
|
||||
cse.back()->Push(gc, strm->GetLength());
|
||||
return false;
|
||||
}
|
||||
if(key == "Position")
|
||||
{
|
||||
|
||||
cse.back()->Push(gc, strm->GetPosition());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(netStrm != nullptr)
|
||||
{
|
||||
if(key == "Port")
|
||||
{
|
||||
cse.back()->Push(gc, netStrm->GetPort());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cse.back()->Push(gc, Undefined());
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
if(std::holds_alternative<TVMVersion>(instance))
|
||||
{
|
||||
TVMVersion& version = std::get<TVMVersion>(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<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(instance))
|
||||
{
|
||||
auto time = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(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<std::shared_ptr<Tesses::Framework::Date::DateTime>>(instance))
|
||||
{
|
||||
auto& date = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(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<THeapObjectHolder>(instance))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
||||
auto bA = dynamic_cast<TByteArray*>(obj);
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto dynList = dynamic_cast<TDynamicList*>(obj);
|
||||
auto tcallable = dynamic_cast<TCallable*>(obj);
|
||||
auto closure = dynamic_cast<TClosure*>(obj);
|
||||
auto externalMethod = dynamic_cast<TExternalMethod*>(obj);
|
||||
auto ittr = dynamic_cast<TEnumerator*>(obj);
|
||||
|
||||
auto callstackEntry = dynamic_cast<CallStackEntry*>(obj);
|
||||
auto file = dynamic_cast<TFile*>(obj);
|
||||
auto chunk = dynamic_cast<TFileChunk*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||
auto aarray = dynamic_cast<TAssociativeArray*>(obj);
|
||||
auto task = dynamic_cast<TTask*>(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<THeapObjectHolder>(fn) && dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(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;
|
||||
}
|
||||
}
|
||||
54
src/vm/bc/invokemethod.cpp
Normal file
54
src/vm/bc/invokemethod.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool InterperterThread::InvokeMethod(GCList& ls, TObject fn, TObject instance, std::vector<TObject> args)
|
||||
{
|
||||
|
||||
if(std::holds_alternative<THeapObjectHolder>(fn))
|
||||
{
|
||||
|
||||
auto obj = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(fn).obj);
|
||||
if(obj != nullptr)
|
||||
{
|
||||
auto closure = dynamic_cast<TClosure*>(obj);
|
||||
if(closure != nullptr)
|
||||
{
|
||||
|
||||
if(!closure->closure->args.empty() && closure->closure->args[0] == "this")
|
||||
{
|
||||
std::vector<TObject> 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;
|
||||
}
|
||||
}
|
||||
47
src/vm/bc/invoketwo.cpp
Normal file
47
src/vm/bc/invoketwo.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::InvokeTwo(GCList& ls, TObject fn, TObject left, TObject right)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(fn))
|
||||
{
|
||||
|
||||
auto obj = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(fn).obj);
|
||||
if(obj != nullptr)
|
||||
{
|
||||
auto closure = dynamic_cast<TClosure*>(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;
|
||||
}
|
||||
}
|
||||
278
src/vm/bc/setfield.cpp
Normal file
278
src/vm/bc/setfield.cpp
Normal file
@@ -0,0 +1,278 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool InterperterThread::SetField(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& 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<std::string>(_key))
|
||||
{
|
||||
stk->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string key = std::get<std::string>(_key);
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance))
|
||||
{
|
||||
auto writer = std::get<std::shared_ptr<Tesses::Framework::TextStreams::TextWriter>>(instance);
|
||||
auto stringWriter = std::dynamic_pointer_cast<Tesses::Framework::TextStreams::StringWriter>(writer);
|
||||
if(stringWriter != nullptr)
|
||||
{
|
||||
if(key == "Text")
|
||||
{
|
||||
if(std::holds_alternative<std::string>(value))
|
||||
{
|
||||
stringWriter->GetString() = std::get<std::string>(value);
|
||||
}
|
||||
cse.back()->Push(gc, stringWriter->GetString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(key == "NewLine")
|
||||
{
|
||||
if(std::holds_alternative<std::string>(value))
|
||||
{
|
||||
writer->newline = std::get<std::string>(value);
|
||||
}
|
||||
cse.back()->Push(gc,writer->newline);
|
||||
return false;
|
||||
}
|
||||
cse.back()->Push(gc,Undefined());
|
||||
return false;
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Http::IHttpServer>>(instance))
|
||||
{
|
||||
auto svr = std::get<std::shared_ptr<Tesses::Framework::Http::IHttpServer>>(instance);
|
||||
auto bas = std::dynamic_pointer_cast<Tesses::Framework::Http::BasicAuthServer>(svr);
|
||||
auto cgi = std::dynamic_pointer_cast<Tesses::Framework::Http::CGIServer>(svr);
|
||||
auto changable = std::dynamic_pointer_cast<Tesses::Framework::Http::ChangeableServer>(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<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance))
|
||||
{
|
||||
auto strm = std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(instance);
|
||||
|
||||
auto netStrm = std::dynamic_pointer_cast<Tesses::Framework::Streams::NetworkStream>(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<THeapObjectHolder>(instance))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
||||
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(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<TCallable*>(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<THeapObjectHolder>(fn) && dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(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;
|
||||
}
|
||||
|
||||
}
|
||||
121
src/vm/bc/sub.cpp
Normal file
121
src/vm/bc/sub.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::Sub(GC* gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||
GCList ls(gc);
|
||||
auto right = cse.back()->Pop(ls);
|
||||
auto left = cse.back()->Pop(ls);
|
||||
|
||||
if(std::holds_alternative<int64_t>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) - std::get<int64_t>(right));
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) - std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<double>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<double>(left) - std::get<int64_t>(right));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<double>(right))
|
||||
{
|
||||
cse.back()->Push(gc,std::get<int64_t>(left) - std::get<double>(right));
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (int64_t)(std::get<char>(left) - std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<char>(left) && std::holds_alternative<int64_t>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (int64_t)(std::get<char>(left) - std::get<int64_t>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
|
||||
{
|
||||
cse.back()->Push(gc, (int64_t)(std::get<int64_t>(left) - std::get<char>(right)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::TimeSpan>((*l) - (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left) && std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right))
|
||||
{
|
||||
auto& l = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(left);
|
||||
auto& r = std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||
cse.back()->Push(gc,std::make_shared<Tesses::Framework::Date::DateTime>((*l) - (*r)));
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(left))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
|
||||
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
|
||||
|
||||
auto cls = dynamic_cast<TClassObject*>(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;
|
||||
}
|
||||
}
|
||||
106
src/vm/bc/tobool.cpp
Normal file
106
src/vm/bc/tobool.cpp
Normal file
@@ -0,0 +1,106 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
bool ToBool(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(obj))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(std::holds_alternative<TVMVersion>(obj))
|
||||
{
|
||||
auto v = std::get<TVMVersion>(obj);
|
||||
return v.AsLong() != 0;
|
||||
}
|
||||
if(std::holds_alternative<std::string>(obj))
|
||||
{
|
||||
return !std::get<std::string>(obj).empty();
|
||||
}
|
||||
else if(std::holds_alternative<int64_t>(obj))
|
||||
{
|
||||
return std::get<int64_t>(obj) != 0;
|
||||
}
|
||||
else if(std::holds_alternative<double>(obj))
|
||||
{
|
||||
return std::get<double>(obj);
|
||||
}
|
||||
else if(std::holds_alternative<bool>(obj))
|
||||
{
|
||||
return std::get<bool>(obj);
|
||||
}
|
||||
else if(std::holds_alternative<char>(obj))
|
||||
{
|
||||
return std::get<char>(obj) != 0;
|
||||
}
|
||||
else if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(obj))
|
||||
{
|
||||
auto& dt = std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(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<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(obj))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(obj)->TotalSeconds() != 0;
|
||||
}
|
||||
else if(std::holds_alternative<Tesses::Framework::Uuid>(obj))
|
||||
{
|
||||
auto& uuid = std::get<Tesses::Framework::Uuid>(obj);
|
||||
return !uuid.IsEmpty();
|
||||
}
|
||||
else if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto o = std::get<THeapObjectHolder>(obj).obj;
|
||||
auto ls = dynamic_cast<TList*>(o);
|
||||
auto aarray = dynamic_cast<TAssociativeArray*>(o);
|
||||
auto dict = dynamic_cast<TDictionary*>(o);
|
||||
auto ba = dynamic_cast<TByteArray*>(o);
|
||||
auto nat = dynamic_cast<TNative*>(o);
|
||||
auto thrd = dynamic_cast<ThreadHandle*>(o);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(o);
|
||||
|
||||
auto any = dynamic_cast<TAny*>(o);
|
||||
auto cls = dynamic_cast<TClassObject*>(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;
|
||||
}
|
||||
}
|
||||
133
src/vm/bc/tostring.cpp
Normal file
133
src/vm/bc/tostring.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "CrossLang.hpp"
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
std::string ToString(GC* gc, TObject o)
|
||||
{
|
||||
if(std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(o))
|
||||
{
|
||||
return std::get<Tesses::Framework::Filesystem::VFSPath>(o).ToString();
|
||||
}
|
||||
if(std::holds_alternative<std::string>(o))
|
||||
{
|
||||
return std::get<std::string>(o);
|
||||
}
|
||||
if(std::holds_alternative<TVMVersion>(o))
|
||||
{
|
||||
return std::get<TVMVersion>(o).ToString();
|
||||
}
|
||||
if(std::holds_alternative<int64_t>(o))
|
||||
{
|
||||
return std::to_string(std::get<int64_t>(o));
|
||||
}
|
||||
|
||||
if(std::holds_alternative<double>(o))
|
||||
{
|
||||
return std::to_string(std::get<double>(o));
|
||||
}
|
||||
|
||||
if(std::holds_alternative<char>(o))
|
||||
{
|
||||
return std::string{std::get<char>(o)};
|
||||
}
|
||||
if(std::holds_alternative<std::nullptr_t>(o))
|
||||
{
|
||||
return "null";
|
||||
}
|
||||
if(std::holds_alternative<Undefined>(o))
|
||||
{
|
||||
return "undefined";
|
||||
}
|
||||
if(std::holds_alternative<bool>(o))
|
||||
{
|
||||
return std::get<bool>(o) ? "true" : "false";
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::DateTime>>(o))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::DateTime>>(o)->ToString();
|
||||
}
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(o))
|
||||
{
|
||||
return std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(o)->ToString(false);
|
||||
}
|
||||
if(std::holds_alternative<Tesses::Framework::Uuid>(o))
|
||||
{
|
||||
return std::get<Tesses::Framework::Uuid>(o).ToString(Framework::UuidStringifyConfig::LowercaseNoCurly);
|
||||
}
|
||||
if(std::holds_alternative<THeapObjectHolder>(o))
|
||||
{
|
||||
auto obj = std::get<THeapObjectHolder>(o).obj;
|
||||
auto dict = dynamic_cast<TDictionary*>(obj);
|
||||
auto list = dynamic_cast<TList*>(obj);
|
||||
auto bArray = dynamic_cast<TByteArray*>(obj);
|
||||
auto natObj = dynamic_cast<TNativeObject*>(obj);
|
||||
auto cls = dynamic_cast<TClassObject*>(obj);
|
||||
auto aArray = dynamic_cast<TAssociativeArray*>(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 "";
|
||||
}
|
||||
}
|
||||
4854
src/vm/vm.cpp
4854
src/vm/vm.cpp
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user