mirror of
https://git.tesses.org/tesses50/crosslang.git
synced 2026-10-01 17:14:13 +00:00
Fix bug with classes, use slim exclusively, add package private data and change rehaul cmake configs
This commit is contained in:
+145
-144
@@ -2,163 +2,164 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::Add(std::shared_ptr<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);
|
||||
bool InterperterThread::Add(std::shared_ptr<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));
|
||||
|
||||
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<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}));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
} 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());
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
cse.back()->Push(gc, Undefined());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+160
-196
@@ -2,235 +2,199 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right)
|
||||
{
|
||||
GCList ls(gc);
|
||||
if(std::holds_alternative<std::nullptr_t>(left) && std::holds_alternative<std::nullptr_t>(right))
|
||||
{
|
||||
bool Equals(std::shared_ptr<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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
else if(std::holds_alternative<Undefined>(left) && std::holds_alternative<Undefined>(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<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<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<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<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);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
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))
|
||||
{
|
||||
} 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}));
|
||||
}
|
||||
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 ToBool(obj->Call(ls, {right}));
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
|
||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+3460
-3754
File diff suppressed because it is too large
Load Diff
+656
-776
File diff suppressed because it is too large
Load Diff
+31
-38
@@ -2,53 +2,46 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
this->call_stack_entries.back()->Push(ls.GetGC(), Undefined());
|
||||
return false;
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+27
-33
@@ -2,46 +2,40 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#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});
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
} else {
|
||||
this->call_stack_entries[this->call_stack_entries.size() - 1]
|
||||
->Push(ls.GetGC(), obj->Call(ls, {right}));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+297
-335
@@ -2,371 +2,333 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
static void empty()
|
||||
{
|
||||
|
||||
}
|
||||
bool InterperterThread::SetField(std::shared_ptr<GC> gc)
|
||||
{
|
||||
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||
static void empty() {}
|
||||
bool InterperterThread::SetField(std::shared_ptr<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;
|
||||
}
|
||||
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);
|
||||
|
||||
std::string key = std::get<std::string>(_key);
|
||||
if(std::holds_alternative<std::shared_ptr<Tesses::Framework::TF_Timer_Handle>>(instance))
|
||||
{
|
||||
auto handle = std::get<std::shared_ptr<Tesses::Framework::TF_Timer_Handle>>(instance);
|
||||
if(handle)
|
||||
{
|
||||
int64_t ms;
|
||||
bool b;
|
||||
if(key == "Enabled" && GetObject(value,b))
|
||||
{
|
||||
if (!std::holds_alternative<std::string>(_key)) {
|
||||
stk->Push(gc, Undefined());
|
||||
return false;
|
||||
}
|
||||
|
||||
handle->SetEnabled(b);
|
||||
std::string key = std::get<std::string>(_key);
|
||||
if (std::holds_alternative<
|
||||
std::shared_ptr<Tesses::Framework::TF_Timer_Handle>>(
|
||||
instance)) {
|
||||
auto handle =
|
||||
std::get<std::shared_ptr<Tesses::Framework::TF_Timer_Handle>>(
|
||||
instance);
|
||||
if (handle) {
|
||||
int64_t ms;
|
||||
bool b;
|
||||
if (key == "Enabled" && GetObject(value, b)) {
|
||||
|
||||
cse.back()->Push(gc,b);
|
||||
return false;
|
||||
}
|
||||
handle->SetEnabled(b);
|
||||
|
||||
if(key == "Interval" && GetObject(value, ms))
|
||||
{
|
||||
handle->SetIntervalFromMilliseconds(ms);
|
||||
|
||||
cse.back()->Push(gc,ms);
|
||||
return false;
|
||||
}
|
||||
if(key == "Callback")
|
||||
{
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(value,callable))
|
||||
{
|
||||
|
||||
auto obj = CreateMarkedTObject(ls.GetGC(), callable);
|
||||
handle->SetCallback([obj]()->void {
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(obj->GetObject(), callable))
|
||||
{
|
||||
GCList ls(obj->GetGC());
|
||||
callable->Call(ls,{});
|
||||
}
|
||||
});
|
||||
cse.back()->Push(gc, callable);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle->SetCallback(empty);
|
||||
cse.back()->Push(gc, nullptr);
|
||||
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")
|
||||
{
|
||||
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);
|
||||
cse.back()->Push(gc, b);
|
||||
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 relative = std::dynamic_pointer_cast<Tesses::Framework::Filesystem::RelativeFilesystem>(vfs);
|
||||
|
||||
if(relative)
|
||||
{
|
||||
if(key == "Working")
|
||||
{
|
||||
Tesses::Framework::Filesystem::VFSPath path;
|
||||
if(GetObjectAsPath(value,path))
|
||||
{
|
||||
if(path.relative)
|
||||
{
|
||||
relative->SetWorking(path.MakeAbsolute(relative->GetWorking()));
|
||||
if (key == "Interval" && GetObject(value, ms)) {
|
||||
handle->SetIntervalFromMilliseconds(ms);
|
||||
|
||||
cse.back()->Push(gc, ms);
|
||||
return false;
|
||||
}
|
||||
if (key == "Callback") {
|
||||
TCallable *callable;
|
||||
if (GetObjectHeap(value, callable)) {
|
||||
|
||||
auto obj = CreateMarkedTObject(ls.GetGC(), callable);
|
||||
handle->SetCallback([obj]() -> void {
|
||||
TCallable *callable;
|
||||
if (GetObjectHeap(obj->GetObject(), callable)) {
|
||||
GCList ls(obj->GetGC());
|
||||
callable->Call(ls, {});
|
||||
}
|
||||
else {
|
||||
relative->SetWorking(path);
|
||||
});
|
||||
cse.back()->Push(gc, callable);
|
||||
return false;
|
||||
} else {
|
||||
handle->SetCallback(empty);
|
||||
cse.back()->Push(gc, nullptr);
|
||||
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") {
|
||||
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::Filesystem::VFS>>(
|
||||
instance)) {
|
||||
|
||||
auto vfs =
|
||||
std::get<std::shared_ptr<Tesses::Framework::Filesystem::VFS>>(
|
||||
instance);
|
||||
auto relative = std::dynamic_pointer_cast<
|
||||
Tesses::Framework::Filesystem::RelativeFilesystem>(vfs);
|
||||
|
||||
if (relative) {
|
||||
if (key == "Working") {
|
||||
Tesses::Framework::Filesystem::VFSPath path;
|
||||
if (GetObjectAsPath(value, path)) {
|
||||
if (path.relative) {
|
||||
relative->SetWorking(
|
||||
path.MakeAbsolute(relative->GetWorking()));
|
||||
} else {
|
||||
relative->SetWorking(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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(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);
|
||||
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 == "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 (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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int64_t n0;
|
||||
bool bc;
|
||||
if(key == "Broadcast" && GetObject(value,bc))
|
||||
netStrm->SetBroadcast(bc);
|
||||
if(key == "NoDelay" && GetObject(value,bc))
|
||||
netStrm->SetNoDelay(bc);
|
||||
if(key == "ReuseAddress" && GetObject(value,bc))
|
||||
netStrm->SetReuseAddress(bc);
|
||||
if(key == "ReusePort" && GetObject(value,bc))
|
||||
netStrm->SetReusePort(bc);
|
||||
if(key == "MulticastTTL" && GetObject(value,n0))
|
||||
netStrm->SetMulticastTTL((uint8_t)n0);
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
int64_t n0;
|
||||
bool bc;
|
||||
if (key == "Broadcast" && GetObject(value, bc))
|
||||
netStrm->SetBroadcast(bc);
|
||||
if (key == "NoDelay" && GetObject(value, bc))
|
||||
netStrm->SetNoDelay(bc);
|
||||
if (key == "ReuseAddress" && GetObject(value, bc))
|
||||
netStrm->SetReuseAddress(bc);
|
||||
if (key == "ReusePort" && GetObject(value, bc))
|
||||
netStrm->SetReusePort(bc);
|
||||
if (key == "MulticastTTL" && GetObject(value, n0))
|
||||
netStrm->SetMulticastTTL((uint8_t)n0);
|
||||
}
|
||||
stk->Push(gc, Undefined());
|
||||
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace Tesses::CrossLang
|
||||
+96
-104
@@ -2,120 +2,112 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
bool InterperterThread::Sub(std::shared_ptr<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);
|
||||
bool InterperterThread::Sub(std::shared_ptr<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);
|
||||
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));
|
||||
}
|
||||
|
||||
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}));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
} 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());
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
cse.back()->Push(gc, Undefined());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+73
-94
@@ -2,105 +2,84 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#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;
|
||||
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;
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+104
-122
@@ -2,132 +2,114 @@
|
||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||
#include "TessesFramework/Streams/ByteReader.hpp"
|
||||
#include "TessesFramework/Uuid.hpp"
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <variant>
|
||||
namespace Tesses::CrossLang {
|
||||
std::string ToString(std::shared_ptr<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 "";
|
||||
std::string ToString(std::shared_ptr<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 "";
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+85
-99
@@ -1,107 +1,93 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
TObject TCallable::CallWithFatalError(GCList& ls, std::vector<TObject> args)
|
||||
{
|
||||
try {
|
||||
return Call(ls,args);
|
||||
}
|
||||
catch(VMByteCodeException& ex)
|
||||
{
|
||||
ThrowFatalError(ex);
|
||||
}
|
||||
catch(VMException& ex)
|
||||
{
|
||||
ThrowFatalError(ex);
|
||||
}
|
||||
catch(SyntaxException& ex)
|
||||
{
|
||||
ThrowFatalError(ex);
|
||||
}
|
||||
catch(std::runtime_error& ex)
|
||||
{
|
||||
ThrowFatalError(ex);
|
||||
}
|
||||
catch(std::exception& ex)
|
||||
{
|
||||
ThrowFatalError(ex);
|
||||
}
|
||||
return (int64_t)1;
|
||||
TObject TCallable::CallWithFatalError(GCList &ls, std::vector<TObject> args) {
|
||||
try {
|
||||
return Call(ls, args);
|
||||
} catch (VMByteCodeException &ex) {
|
||||
ThrowFatalError(ex);
|
||||
} catch (VMException &ex) {
|
||||
ThrowFatalError(ex);
|
||||
} catch (SyntaxException &ex) {
|
||||
ThrowFatalError(ex);
|
||||
} catch (std::runtime_error &ex) {
|
||||
ThrowFatalError(ex);
|
||||
} catch (std::exception &ex) {
|
||||
ThrowFatalError(ex);
|
||||
}
|
||||
void ThrowFatalError(std::exception& ex)
|
||||
{
|
||||
using namespace Tesses::Framework::TextStreams;
|
||||
std::exception* ex2 = &ex;
|
||||
auto clexcept = dynamic_cast<VMByteCodeException*>(ex2);
|
||||
auto clrtexcept = dynamic_cast<VMException*>(ex2);
|
||||
auto compiler = dynamic_cast<SyntaxException*>(ex2);
|
||||
Tesses::Framework::TextStreams::ConsoleWriter error(true);
|
||||
|
||||
if(clexcept != nullptr)
|
||||
{
|
||||
error.WriteLine("CrossLang has encountered a fatal exception");
|
||||
error.WriteLine();
|
||||
|
||||
error.WriteLine(ToString(clexcept->GetGCList()->GetGC(),clexcept->exception));
|
||||
error.WriteLine();
|
||||
error.WriteLine("STACKTRACE:");
|
||||
|
||||
for(auto ittr = clexcept->stack_trace.crbegin(); ittr != clexcept->stack_trace.crend(); ittr++)
|
||||
{
|
||||
auto item = *ittr;
|
||||
std::string text = "\t";
|
||||
text += item->callable->closure->name.value_or((std::string)"<Closure>");
|
||||
text += "(";
|
||||
bool first=true;
|
||||
for(auto& arg : item->callable->closure->args)
|
||||
{
|
||||
if(!first) text += ", ";
|
||||
text += arg;
|
||||
first=false;
|
||||
}
|
||||
text += ")";
|
||||
if(item->srcline >= 1)
|
||||
{
|
||||
text += " at ";
|
||||
text += item->srcfile;
|
||||
text += ":";
|
||||
text += std::to_string(item->srcline);
|
||||
}
|
||||
error.WriteLine(text);
|
||||
}
|
||||
return (int64_t)1;
|
||||
}
|
||||
void ThrowFatalError(std::exception &ex) {
|
||||
using namespace Tesses::Framework::TextStreams;
|
||||
std::exception *ex2 = &ex;
|
||||
auto clexcept = dynamic_cast<VMByteCodeException *>(ex2);
|
||||
auto clrtexcept = dynamic_cast<VMException *>(ex2);
|
||||
auto compiler = dynamic_cast<SyntaxException *>(ex2);
|
||||
Tesses::Framework::TextStreams::ConsoleWriter error(true);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
if(clrtexcept != nullptr)
|
||||
{
|
||||
error.WriteLine("CrossLang has encountered a fatal runtime exception");
|
||||
error.WriteLine();
|
||||
error.WriteLine(clrtexcept->what());
|
||||
exit(1);
|
||||
}
|
||||
if(compiler != nullptr)
|
||||
{
|
||||
error.WriteLine("CrossLang has encountered a compiler error");
|
||||
error.WriteLine();
|
||||
error.WriteLine(compiler->Message());
|
||||
error.WriteLine();
|
||||
auto li = compiler->LineInfo();
|
||||
error.Write("in file: ");
|
||||
error.Write(li.filename);
|
||||
error.Write(":");
|
||||
error.Write((int64_t)li.line);
|
||||
error.Write(":");
|
||||
error.Write((int64_t)li.column);
|
||||
error.Write(":");
|
||||
error.WriteLine((int64_t)li.offset);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
error.WriteLine("CrossLang has encountered a fatal C++ exception");
|
||||
if (clexcept != nullptr) {
|
||||
error.WriteLine("CrossLang has encountered a fatal exception");
|
||||
error.WriteLine();
|
||||
error.Write("what(): ");
|
||||
error.WriteLine(ex2->what());
|
||||
|
||||
error.WriteLine(
|
||||
ToString(clexcept->GetGCList()->GetGC(), clexcept->exception));
|
||||
error.WriteLine();
|
||||
error.WriteLine("STACKTRACE:");
|
||||
|
||||
for (auto ittr = clexcept->stack_trace.crbegin();
|
||||
ittr != clexcept->stack_trace.crend(); ittr++) {
|
||||
auto item = *ittr;
|
||||
std::string text = "\t";
|
||||
text += item->callable->closure->name.value_or(
|
||||
(std::string) "<Closure>");
|
||||
text += "(";
|
||||
bool first = true;
|
||||
for (auto &arg : item->callable->closure->args) {
|
||||
if (!first)
|
||||
text += ", ";
|
||||
text += arg;
|
||||
first = false;
|
||||
}
|
||||
text += ")";
|
||||
if (item->srcline >= 1) {
|
||||
text += " at ";
|
||||
text += item->srcfile;
|
||||
text += ":";
|
||||
text += std::to_string(item->srcline);
|
||||
}
|
||||
error.WriteLine(text);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (clrtexcept != nullptr) {
|
||||
error.WriteLine("CrossLang has encountered a fatal runtime exception");
|
||||
error.WriteLine();
|
||||
error.WriteLine(clrtexcept->what());
|
||||
exit(1);
|
||||
}
|
||||
if (compiler != nullptr) {
|
||||
error.WriteLine("CrossLang has encountered a compiler error");
|
||||
error.WriteLine();
|
||||
error.WriteLine(compiler->Message());
|
||||
error.WriteLine();
|
||||
auto li = compiler->LineInfo();
|
||||
error.Write("in file: ");
|
||||
error.Write(li.filename);
|
||||
error.Write(":");
|
||||
error.Write((int64_t)li.line);
|
||||
error.Write(":");
|
||||
error.Write((int64_t)li.column);
|
||||
error.Write(":");
|
||||
error.WriteLine((int64_t)li.offset);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
error.WriteLine("CrossLang has encountered a fatal C++ exception");
|
||||
error.WriteLine();
|
||||
error.Write("what(): ");
|
||||
error.WriteLine(ex2->what());
|
||||
exit(1);
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+406
-446
@@ -1,453 +1,413 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
TFile* TFile::Create(GCList& ls)
|
||||
{
|
||||
TFile* f = new TFile();
|
||||
f->icon = -1;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(f);
|
||||
_gc->Watch(f);
|
||||
return f;
|
||||
}
|
||||
TFile* TFile::Create(GCList* ls)
|
||||
{
|
||||
TFile* f = new TFile();
|
||||
f->icon=-1;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(f);
|
||||
_gc->Watch(f);
|
||||
return f;
|
||||
}
|
||||
void TFileChunk::Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
this->file->Mark();
|
||||
}
|
||||
|
||||
TFileChunk* TFileChunk::Create(GCList& ls)
|
||||
{
|
||||
TFileChunk* chk = new TFileChunk();
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(chk);
|
||||
_gc->Watch(chk);
|
||||
return chk;
|
||||
}
|
||||
TFileChunk* TFileChunk::Create(GCList* ls)
|
||||
{
|
||||
TFileChunk* chk = new TFileChunk();
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(chk);
|
||||
_gc->Watch(chk);
|
||||
return chk;
|
||||
}
|
||||
void TFile::Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
|
||||
for(auto item : this->chunks)
|
||||
item->Mark();
|
||||
|
||||
}
|
||||
void TFile::Skip(std::shared_ptr<Tesses::Framework::Streams::Stream> stream,size_t len)
|
||||
{
|
||||
if(stream->CanSeek())
|
||||
{
|
||||
stream->Seek((int64_t)len,Tesses::Framework::Streams::SeekOrigin::Current);
|
||||
}
|
||||
else{
|
||||
uint8_t* buffer=new uint8_t[len];
|
||||
Ensure(stream,buffer,len);
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
void TFile::Ensure(std::shared_ptr<Tesses::Framework::Streams::Stream> stream, uint8_t* buffer,size_t len)
|
||||
{
|
||||
size_t read = stream->ReadBlock(buffer, len);
|
||||
if(read < len) throw VMException("End of file, could not read " + std::to_string((int64_t)len) + " byte(s)., offset=" + std::to_string(stream->GetLength()));
|
||||
}
|
||||
std::string TFile::EnsureString(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
auto len = EnsureInt(stream);
|
||||
if(len == 0) return {};
|
||||
std::string str={};
|
||||
str.resize((size_t)len);
|
||||
Ensure(stream,(uint8_t*)str.data(),str.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
uint32_t TFile::EnsureInt(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
uint8_t buffer[4];
|
||||
Ensure(stream,buffer,4);
|
||||
return BitConverter::ToUint32BE(buffer[0]);
|
||||
}
|
||||
std::string TFile::GetString(std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
uint32_t index=EnsureInt(stream);
|
||||
if(index >= this->strings.size()) throw VMException("String does not exist in TCrossVM file, expected string index: " + std::to_string(index) + ", total strings: " + std::to_string(this->strings.size()));
|
||||
return this->strings[index];
|
||||
}
|
||||
void TFile::EnsureCanRunInCrossLang()
|
||||
{
|
||||
if(this->vms.empty()) return;
|
||||
|
||||
for(auto item : this->vms)
|
||||
{
|
||||
if(item.first == VMName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string errorMessage="The virtual machines supported are:\n";
|
||||
|
||||
for(auto item : this->vms)
|
||||
{
|
||||
errorMessage += item.first + "\n\t" + item.second + "\n";
|
||||
}
|
||||
throw VMException(errorMessage);
|
||||
}
|
||||
|
||||
TDictionary* TFile::MetadataDecode(GCList& ls, size_t midx)
|
||||
{
|
||||
if(midx >= this->metadata.size()) return nullptr;
|
||||
if(this->metadata[midx].second.empty()) return nullptr;
|
||||
if(this->metadata[midx].second[0] != 8) return nullptr;
|
||||
size_t index = 0;
|
||||
auto& bytes = this->metadata[midx].second;
|
||||
|
||||
std::function<TObject()> parseEnt;
|
||||
parseEnt = [&]()->TObject {
|
||||
if(index >= bytes.size()) throw std::out_of_range("Abrupt end of metadata");
|
||||
switch(bytes[index++])
|
||||
{
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
return true;
|
||||
case 2:
|
||||
return nullptr;
|
||||
case 3:
|
||||
{
|
||||
if(index + 8 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint64BE(bytes[index]);
|
||||
index+=8;
|
||||
int64_t val2;
|
||||
memcpy(&val2,&val,sizeof(val));
|
||||
return val2;
|
||||
}
|
||||
else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
{
|
||||
if(index + 8 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToDoubleBE(bytes[index]);
|
||||
index+=8;
|
||||
return val;
|
||||
}
|
||||
else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
|
||||
if(index + 1 <= bytes.size())
|
||||
{
|
||||
return (char)bytes[index++];
|
||||
}
|
||||
else throw std::out_of_range("Abrupt end of metadata");
|
||||
break;
|
||||
case 6:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
return this->strings.at((size_t)val);
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
std::vector<TObject> items;
|
||||
for(uint32_t i = 0; i < val; i++)
|
||||
{
|
||||
items.push_back(parseEnt());
|
||||
}
|
||||
|
||||
return TList::Create(ls,items.begin(),items.end());
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
std::vector<TDItem> items;
|
||||
|
||||
for(uint32_t i = 0; i < val; i++)
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val2= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
std::string& text=this->strings.at((size_t)val2);
|
||||
items.emplace_back(text,parseEnt());
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
|
||||
}
|
||||
|
||||
return TDictionary::Create(ls, items.begin(),items.end());
|
||||
}else throw std::out_of_range("Abrupt end of metadata");
|
||||
break;
|
||||
case 9:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
auto ba = TByteArray::Create(ls);
|
||||
ba->data = this->resources.at((size_t)val);
|
||||
return ba;
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
return std::make_shared<EmbedStream>(ls.GetGC(),this,val);
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
{
|
||||
|
||||
auto data = parseEnt();
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(data,dict))
|
||||
{
|
||||
return std::make_shared<EmbedDirectory>(ls.GetGC(),dict);
|
||||
}
|
||||
else return Undefined();
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
{
|
||||
if(index + 4 <= bytes.size())
|
||||
{
|
||||
auto val= BitConverter::ToUint32BE(bytes[index]);
|
||||
index+=4;
|
||||
ls.GetGC()->BarrierBegin();
|
||||
auto em = TExternalMethod::Create(ls,"",{},[val,this](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
return std::make_shared<EmbedStream>(ls.GetGC(),this,val);
|
||||
});
|
||||
em->watch.push_back(this);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return em;
|
||||
} else throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid metadata opcode");
|
||||
}
|
||||
};
|
||||
|
||||
TDictionary* dict_res;
|
||||
TObject ent = parseEnt();
|
||||
if(GetObjectHeap(ent, dict_res)) return dict_res;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TFile::Load(std::shared_ptr<GC> gc, std::shared_ptr<Tesses::Framework::Streams::Stream> stream)
|
||||
{
|
||||
|
||||
uint8_t main_header[18];
|
||||
Ensure(stream,main_header,sizeof(main_header));
|
||||
if(strncmp((const char*)main_header,"TCROSSVM",8) != 0) throw VMException("Invalid TCrossVM image.");
|
||||
TVMVersion version(main_header+8);
|
||||
if(version.CompareToRuntime() == 1)
|
||||
{
|
||||
throw VMException("Runtime is too old.");
|
||||
}
|
||||
TVMVersion v2(main_header+13);
|
||||
this->version = v2;
|
||||
|
||||
size_t _len = (size_t)EnsureInt(stream);
|
||||
|
||||
char table_name[4];
|
||||
|
||||
for(size_t i = 0;i < _len; i++)
|
||||
{
|
||||
Ensure(stream,(uint8_t*)table_name,sizeof(table_name));
|
||||
size_t tableLen = (size_t)EnsureInt(stream);
|
||||
if(strncmp(table_name,"NAME",4) == 0)
|
||||
{
|
||||
this->name = GetString(stream);
|
||||
}
|
||||
else if(strncmp(table_name,"INFO",4) == 0)
|
||||
{
|
||||
this->info = GetString(stream);
|
||||
}
|
||||
else if(strncmp(table_name,"DEPS",4) == 0) //dependencies
|
||||
{
|
||||
std::string name = GetString(stream);
|
||||
uint8_t version_bytes[5];
|
||||
Ensure(stream,version_bytes,sizeof(version_bytes));
|
||||
TVMVersion depVersion(version_bytes);
|
||||
this->dependencies.push_back(std::pair<std::string,TVMVersion>(name, depVersion));
|
||||
}
|
||||
else if(strncmp(table_name,"TOOL",4) == 0) //compile tools (for package manager)
|
||||
{
|
||||
std::string name = GetString(stream);
|
||||
uint8_t version_bytes[5];
|
||||
Ensure(stream,version_bytes,sizeof(version_bytes));
|
||||
TVMVersion depVersion(version_bytes);
|
||||
this->tools.push_back(std::pair<std::string,TVMVersion>(name, depVersion));
|
||||
}
|
||||
else if(strncmp(table_name,"RESO",4) == 0) //resources (using embed)
|
||||
{
|
||||
auto& data = this->resources.emplace_back(tableLen);
|
||||
Ensure(stream,data.data(), data.size());
|
||||
}
|
||||
else if(strncmp(table_name,"CHKS",4) == 0 && gc != nullptr) //chunks
|
||||
{
|
||||
GCList ls(gc);
|
||||
size_t chunkCount = (size_t)EnsureInt(stream);
|
||||
for(size_t j = 0; j < chunkCount; j++)
|
||||
{
|
||||
|
||||
auto chunk = TFileChunk::Create(ls);
|
||||
chunk->file = this;
|
||||
size_t argCount = (size_t)EnsureInt(stream);
|
||||
for(size_t k = 0; k < argCount; k++)
|
||||
{
|
||||
chunk->args.push_back(GetString(stream));
|
||||
}
|
||||
size_t len = (size_t)EnsureInt(stream);
|
||||
chunk->code.resize(len);
|
||||
Ensure(stream,chunk->code.data(),len);
|
||||
//reader.ReadIntoBuffer(chunk->code);
|
||||
|
||||
this->chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
}
|
||||
else if(strncmp(table_name,"FUNS",4) == 0) //functions
|
||||
{
|
||||
size_t funLength = (size_t)EnsureInt(stream);
|
||||
|
||||
for(size_t j = 0; j < funLength;j++)
|
||||
{
|
||||
std::vector<std::string> fnParts;
|
||||
uint32_t fnPartsC = EnsureInt(stream);
|
||||
for(uint32_t k = 0; k < fnPartsC; k++)
|
||||
{
|
||||
fnParts.push_back(GetString(stream));
|
||||
}
|
||||
|
||||
uint32_t fnNumber = EnsureInt(stream);
|
||||
this->functions.push_back(std::pair<std::vector<std::string>,uint32_t>(fnParts,fnNumber));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else if(strncmp(table_name,"STRS",4) == 0) //strings
|
||||
{
|
||||
size_t strsLen = (size_t)EnsureInt(stream);
|
||||
for(size_t j = 0;j < strsLen;j++)
|
||||
{
|
||||
this->strings.push_back(EnsureString(stream));
|
||||
}
|
||||
}
|
||||
else if(strncmp(table_name,"ICON",4) == 0) //icon
|
||||
{
|
||||
this->icon = (int32_t)EnsureInt(stream);
|
||||
}
|
||||
else if(strncmp(table_name,"MACH",4) == 0) //machine
|
||||
{
|
||||
std::string name = GetString(stream);
|
||||
std::string howToGet = GetString(stream);
|
||||
this->vms.push_back(std::pair<std::string,std::string>(name,howToGet));
|
||||
}
|
||||
else if(strncmp(table_name,"CLSS",4) == 0) //classes
|
||||
{
|
||||
uint32_t clsCnt = EnsureInt(stream);
|
||||
for(uint32_t j = 0; j < clsCnt; j++)
|
||||
{
|
||||
TClass cls;
|
||||
cls.documentation= GetString(stream);
|
||||
uint32_t name_cnt = EnsureInt(stream);
|
||||
for(uint32_t k = 0; k < name_cnt; k++)
|
||||
{
|
||||
cls.name.push_back(GetString(stream));
|
||||
}
|
||||
name_cnt = EnsureInt(stream);
|
||||
for(uint32_t k = 0; k < name_cnt; k++)
|
||||
{
|
||||
cls.inherits.push_back(GetString(stream));
|
||||
}
|
||||
name_cnt = EnsureInt(stream);
|
||||
for(uint32_t k = 0; k < name_cnt; k++)
|
||||
{
|
||||
TClassEntry ent;
|
||||
Ensure(stream,main_header,1);
|
||||
uint8_t sig = main_header[0];
|
||||
ent.isAbstract = (sig & 0b00001000) != 0;
|
||||
ent.isFunction = (sig & 0b00000100) == 0;
|
||||
ent.modifier = (TClassModifier)(sig & 3);
|
||||
ent.documentation = GetString(stream);
|
||||
ent.name = GetString(stream);
|
||||
uint32_t arglen = EnsureInt(stream);
|
||||
for(uint32_t l = 0; l < arglen; l++)
|
||||
ent.args.push_back(GetString(stream));
|
||||
ent.chunkId = EnsureInt(stream);
|
||||
cls.entry.push_back(ent);
|
||||
}
|
||||
this->classes.push_back(cls);
|
||||
}
|
||||
}
|
||||
else if(strncmp(table_name,"META",4) == 0) //structured metadata
|
||||
{
|
||||
if(tableLen > 4)
|
||||
{
|
||||
auto name = this->GetString(stream);
|
||||
auto& data = this->metadata.emplace_back(name, std::vector<uint8_t>(tableLen-4));
|
||||
Ensure(stream,data.second.data(), tableLen-4);
|
||||
}
|
||||
else throw VMException("meta tag is not valid");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& data = this->sections.emplace_back(std::string(table_name, 4), std::vector<uint8_t>(tableLen));
|
||||
Ensure(stream,data.second.data(), tableLen);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
TFile *TFile::Create(GCList &ls) {
|
||||
TFile *f = new TFile();
|
||||
f->icon = -1;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(f);
|
||||
_gc->Watch(f);
|
||||
return f;
|
||||
}
|
||||
TFile *TFile::Create(GCList *ls) {
|
||||
TFile *f = new TFile();
|
||||
f->icon = -1;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(f);
|
||||
_gc->Watch(f);
|
||||
return f;
|
||||
}
|
||||
void TFileChunk::Mark() {
|
||||
if (this->marked)
|
||||
return;
|
||||
this->marked = true;
|
||||
this->file->Mark();
|
||||
}
|
||||
|
||||
TFileChunk *TFileChunk::Create(GCList &ls) {
|
||||
TFileChunk *chk = new TFileChunk();
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(chk);
|
||||
_gc->Watch(chk);
|
||||
return chk;
|
||||
}
|
||||
TFileChunk *TFileChunk::Create(GCList *ls) {
|
||||
TFileChunk *chk = new TFileChunk();
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(chk);
|
||||
_gc->Watch(chk);
|
||||
return chk;
|
||||
}
|
||||
void TFile::Mark() {
|
||||
if (this->marked)
|
||||
return;
|
||||
this->marked = true;
|
||||
|
||||
for (auto item : this->chunks)
|
||||
item->Mark();
|
||||
}
|
||||
void TFile::Skip(std::shared_ptr<Tesses::Framework::Streams::Stream> stream,
|
||||
size_t len) {
|
||||
if (stream->CanSeek()) {
|
||||
stream->Seek((int64_t)len,
|
||||
Tesses::Framework::Streams::SeekOrigin::Current);
|
||||
} else {
|
||||
uint8_t *buffer = new uint8_t[len];
|
||||
Ensure(stream, buffer, len);
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
void TFile::Ensure(std::shared_ptr<Tesses::Framework::Streams::Stream> stream,
|
||||
uint8_t *buffer, size_t len) {
|
||||
size_t read = stream->ReadBlock(buffer, len);
|
||||
if (read < len)
|
||||
throw VMException(
|
||||
"End of file, could not read " + std::to_string((int64_t)len) +
|
||||
" byte(s)., offset=" + std::to_string(stream->GetLength()));
|
||||
}
|
||||
std::string TFile::EnsureString(
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
||||
auto len = EnsureInt(stream);
|
||||
if (len == 0)
|
||||
return {};
|
||||
std::string str = {};
|
||||
str.resize((size_t)len);
|
||||
Ensure(stream, (uint8_t *)str.data(), str.size());
|
||||
return str;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
TFile::EnsureInt(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
||||
uint8_t buffer[4];
|
||||
Ensure(stream, buffer, 4);
|
||||
return BitConverter::ToUint32BE(buffer[0]);
|
||||
}
|
||||
std::string
|
||||
TFile::GetString(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
||||
uint32_t index = EnsureInt(stream);
|
||||
if (index >= this->strings.size())
|
||||
throw VMException(
|
||||
"String does not exist in TCrossVM file, expected string index: " +
|
||||
std::to_string(index) +
|
||||
", total strings: " + std::to_string(this->strings.size()));
|
||||
return this->strings[index];
|
||||
}
|
||||
void TFile::EnsureCanRunInCrossLang() {
|
||||
if (this->vms.empty())
|
||||
return;
|
||||
|
||||
for (auto item : this->vms) {
|
||||
if (item.first == VMName) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string errorMessage = "The virtual machines supported are:\n";
|
||||
|
||||
for (auto item : this->vms) {
|
||||
errorMessage += item.first + "\n\t" + item.second + "\n";
|
||||
}
|
||||
throw VMException(errorMessage);
|
||||
}
|
||||
|
||||
TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
|
||||
if (midx >= this->metadata.size())
|
||||
return nullptr;
|
||||
if (this->metadata[midx].second.empty())
|
||||
return nullptr;
|
||||
if (this->metadata[midx].second[0] != 8)
|
||||
return nullptr;
|
||||
size_t index = 0;
|
||||
auto &bytes = this->metadata[midx].second;
|
||||
|
||||
std::function<TObject()> parseEnt;
|
||||
parseEnt = [&]() -> TObject {
|
||||
if (index >= bytes.size())
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
switch (bytes[index++]) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
return true;
|
||||
case 2:
|
||||
return nullptr;
|
||||
case 3: {
|
||||
if (index + 8 <= bytes.size()) {
|
||||
auto val = BitConverter::ToUint64BE(bytes[index]);
|
||||
index += 8;
|
||||
int64_t val2;
|
||||
memcpy(&val2, &val, sizeof(val));
|
||||
return val2;
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
} break;
|
||||
case 4: {
|
||||
if (index + 8 <= bytes.size()) {
|
||||
auto val = BitConverter::ToDoubleBE(bytes[index]);
|
||||
index += 8;
|
||||
return val;
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
} break;
|
||||
case 5:
|
||||
|
||||
if (index + 1 <= bytes.size()) {
|
||||
return (char)bytes[index++];
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
break;
|
||||
case 6: {
|
||||
if (index + 4 <= bytes.size()) {
|
||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||
index += 4;
|
||||
return this->strings.at((size_t)val);
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
|
||||
} break;
|
||||
case 7: {
|
||||
if (index + 4 <= bytes.size()) {
|
||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||
index += 4;
|
||||
std::vector<TObject> items;
|
||||
for (uint32_t i = 0; i < val; i++) {
|
||||
items.push_back(parseEnt());
|
||||
}
|
||||
|
||||
return TList::Create(ls, items.begin(), items.end());
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
} break;
|
||||
case 8:
|
||||
if (index + 4 <= bytes.size()) {
|
||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||
index += 4;
|
||||
std::vector<TDItem> items;
|
||||
|
||||
for (uint32_t i = 0; i < val; i++) {
|
||||
if (index + 4 <= bytes.size()) {
|
||||
auto val2 = BitConverter::ToUint32BE(bytes[index]);
|
||||
index += 4;
|
||||
std::string &text = this->strings.at((size_t)val2);
|
||||
items.emplace_back(text, parseEnt());
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
}
|
||||
|
||||
return TDictionary::Create(ls, items.begin(), items.end());
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
break;
|
||||
case 9: {
|
||||
if (index + 4 <= bytes.size()) {
|
||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||
index += 4;
|
||||
auto ba = TByteArray::Create(ls);
|
||||
ba->data = this->resources.at((size_t)val);
|
||||
return ba;
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
} break;
|
||||
case 10: {
|
||||
if (index + 4 <= bytes.size()) {
|
||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||
index += 4;
|
||||
return std::make_shared<EmbedStream>(ls.GetGC(), this, val);
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
} break;
|
||||
case 11: {
|
||||
|
||||
auto data = parseEnt();
|
||||
TDictionary *dict;
|
||||
if (GetObjectHeap(data, dict)) {
|
||||
return std::make_shared<EmbedDirectory>(ls.GetGC(), dict);
|
||||
} else
|
||||
return Undefined();
|
||||
} break;
|
||||
case 12: {
|
||||
if (index + 4 <= bytes.size()) {
|
||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||
index += 4;
|
||||
ls.GetGC()->BarrierBegin();
|
||||
auto em = TExternalMethod::Create(
|
||||
ls, "", {},
|
||||
[val, this](GCList &ls,
|
||||
std::vector<TObject> args) -> TObject {
|
||||
return std::make_shared<EmbedStream>(ls.GetGC(), this,
|
||||
val);
|
||||
});
|
||||
em->watch.push_back(this);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return em;
|
||||
} else
|
||||
throw std::out_of_range("Abrupt end of metadata");
|
||||
} break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid metadata opcode");
|
||||
}
|
||||
};
|
||||
|
||||
TDictionary *dict_res;
|
||||
TObject ent = parseEnt();
|
||||
if (GetObjectHeap(ent, dict_res))
|
||||
return dict_res;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TFile::Load(std::shared_ptr<GC> gc,
|
||||
std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
||||
|
||||
uint8_t main_header[18];
|
||||
Ensure(stream, main_header, sizeof(main_header));
|
||||
if (strncmp((const char *)main_header, "TCROSSVM", 8) != 0)
|
||||
throw VMException("Invalid TCrossVM image.");
|
||||
TVMVersion version(main_header + 8);
|
||||
if (version.CompareToRuntime() == 1) {
|
||||
throw VMException("Runtime is too old.");
|
||||
}
|
||||
TVMVersion v2(main_header + 13);
|
||||
this->version = v2;
|
||||
|
||||
size_t _len = (size_t)EnsureInt(stream);
|
||||
|
||||
char table_name[4];
|
||||
|
||||
for (size_t i = 0; i < _len; i++) {
|
||||
Ensure(stream, (uint8_t *)table_name, sizeof(table_name));
|
||||
size_t tableLen = (size_t)EnsureInt(stream);
|
||||
if (strncmp(table_name, "NAME", 4) == 0) {
|
||||
this->name = GetString(stream);
|
||||
} else if (strncmp(table_name, "INFO", 4) == 0) {
|
||||
this->info = GetString(stream);
|
||||
} else if (strncmp(table_name, "DEPS", 4) == 0) // dependencies
|
||||
{
|
||||
std::string name = GetString(stream);
|
||||
uint8_t version_bytes[5];
|
||||
Ensure(stream, version_bytes, sizeof(version_bytes));
|
||||
TVMVersion depVersion(version_bytes);
|
||||
this->dependencies.push_back(
|
||||
std::pair<std::string, TVMVersion>(name, depVersion));
|
||||
} else if (strncmp(table_name, "TOOL", 4) ==
|
||||
0) // compile tools (for package manager)
|
||||
{
|
||||
std::string name = GetString(stream);
|
||||
uint8_t version_bytes[5];
|
||||
Ensure(stream, version_bytes, sizeof(version_bytes));
|
||||
TVMVersion depVersion(version_bytes);
|
||||
this->tools.push_back(
|
||||
std::pair<std::string, TVMVersion>(name, depVersion));
|
||||
} else if (strncmp(table_name, "RESO", 4) ==
|
||||
0) // resources (using embed)
|
||||
{
|
||||
auto &data = this->resources.emplace_back(tableLen);
|
||||
Ensure(stream, data.data(), data.size());
|
||||
} else if (strncmp(table_name, "CHKS", 4) == 0 &&
|
||||
gc != nullptr) // chunks
|
||||
{
|
||||
GCList ls(gc);
|
||||
size_t chunkCount = (size_t)EnsureInt(stream);
|
||||
for (size_t j = 0; j < chunkCount; j++) {
|
||||
|
||||
auto chunk = TFileChunk::Create(ls);
|
||||
chunk->file = this;
|
||||
size_t argCount = (size_t)EnsureInt(stream);
|
||||
for (size_t k = 0; k < argCount; k++) {
|
||||
chunk->args.push_back(GetString(stream));
|
||||
}
|
||||
size_t len = (size_t)EnsureInt(stream);
|
||||
chunk->code.resize(len);
|
||||
Ensure(stream, chunk->code.data(), len);
|
||||
// reader.ReadIntoBuffer(chunk->code);
|
||||
|
||||
this->chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
} else if (strncmp(table_name, "FUNS", 4) == 0) // functions
|
||||
{
|
||||
size_t funLength = (size_t)EnsureInt(stream);
|
||||
|
||||
for (size_t j = 0; j < funLength; j++) {
|
||||
std::vector<std::string> fnParts;
|
||||
uint32_t fnPartsC = EnsureInt(stream);
|
||||
for (uint32_t k = 0; k < fnPartsC; k++) {
|
||||
fnParts.push_back(GetString(stream));
|
||||
}
|
||||
|
||||
uint32_t fnNumber = EnsureInt(stream);
|
||||
this->functions.push_back(
|
||||
std::pair<std::vector<std::string>, uint32_t>(fnParts,
|
||||
fnNumber));
|
||||
}
|
||||
|
||||
} else if (strncmp(table_name, "STRS", 4) == 0) // strings
|
||||
{
|
||||
size_t strsLen = (size_t)EnsureInt(stream);
|
||||
for (size_t j = 0; j < strsLen; j++) {
|
||||
this->strings.push_back(EnsureString(stream));
|
||||
}
|
||||
} else if (strncmp(table_name, "ICON", 4) == 0) // icon
|
||||
{
|
||||
this->icon = (int32_t)EnsureInt(stream);
|
||||
} else if (strncmp(table_name, "MACH", 4) == 0) // machine
|
||||
{
|
||||
std::string name = GetString(stream);
|
||||
std::string howToGet = GetString(stream);
|
||||
this->vms.push_back(
|
||||
std::pair<std::string, std::string>(name, howToGet));
|
||||
} else if (strncmp(table_name, "CLSS", 4) == 0) // classes
|
||||
{
|
||||
uint32_t clsCnt = EnsureInt(stream);
|
||||
for (uint32_t j = 0; j < clsCnt; j++) {
|
||||
TClass cls;
|
||||
cls.documentation = GetString(stream);
|
||||
uint32_t name_cnt = EnsureInt(stream);
|
||||
for (uint32_t k = 0; k < name_cnt; k++) {
|
||||
cls.name.push_back(GetString(stream));
|
||||
}
|
||||
name_cnt = EnsureInt(stream);
|
||||
for (uint32_t k = 0; k < name_cnt; k++) {
|
||||
cls.inherits.push_back(GetString(stream));
|
||||
}
|
||||
name_cnt = EnsureInt(stream);
|
||||
for (uint32_t k = 0; k < name_cnt; k++) {
|
||||
TClassEntry ent;
|
||||
Ensure(stream, main_header, 1);
|
||||
uint8_t sig = main_header[0];
|
||||
ent.isAbstract = (sig & 0b00001000) != 0;
|
||||
ent.isFunction = (sig & 0b00000100) == 0;
|
||||
ent.modifier = (TClassModifier)(sig & 3);
|
||||
ent.documentation = GetString(stream);
|
||||
ent.name = GetString(stream);
|
||||
uint32_t arglen = EnsureInt(stream);
|
||||
for (uint32_t l = 0; l < arglen; l++)
|
||||
ent.args.push_back(GetString(stream));
|
||||
ent.chunkId = EnsureInt(stream);
|
||||
cls.entry.push_back(ent);
|
||||
}
|
||||
this->classes.push_back(cls);
|
||||
}
|
||||
} else if (strncmp(table_name, "META", 4) == 0) // structured metadata
|
||||
{
|
||||
if (tableLen > 4) {
|
||||
auto name = this->GetString(stream);
|
||||
auto &data = this->metadata.emplace_back(
|
||||
name, std::vector<uint8_t>(tableLen - 4));
|
||||
Ensure(stream, data.second.data(), tableLen - 4);
|
||||
} else
|
||||
throw VMException("meta tag is not valid");
|
||||
|
||||
} else {
|
||||
auto &data = this->sections.emplace_back(
|
||||
std::string(table_name, 4), std::vector<uint8_t>(tableLen));
|
||||
Ensure(stream, data.second.data(), tableLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Tesses::CrossLang
|
||||
|
||||
+181
-218
@@ -8,270 +8,233 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
|
||||
using namespace Tesses::Framework::Threading;
|
||||
using namespace std::chrono;
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
bool GC::IsRunning()
|
||||
{
|
||||
bool GC::IsRunning() {
|
||||
|
||||
bool run = this->running;
|
||||
bool run = this->running;
|
||||
|
||||
return run;
|
||||
}
|
||||
GC::GC()
|
||||
{
|
||||
return run;
|
||||
}
|
||||
GC::GC() {}
|
||||
TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached) {
|
||||
|
||||
}
|
||||
TDictionary* CreateThread(GCList& ls, TCallable* callable,bool detached)
|
||||
{
|
||||
TDictionary *dict = TDictionary::Create(ls);
|
||||
|
||||
TDictionary* dict = TDictionary::Create(ls);
|
||||
|
||||
ThreadHandle* th = new ThreadHandle();
|
||||
th->gc = ls.GetGC();
|
||||
th->callable = callable;
|
||||
th->hasInit=false;
|
||||
th->hasReturned = false;
|
||||
th->detached=detached;
|
||||
ls.Add(th);
|
||||
ls.GetGC()->Watch(th);
|
||||
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("_internal", th);
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"Join","Join thread",{},[th](GCList& _ls, std::vector<TObject> _args)-> TObject{
|
||||
ThreadHandle *th = new ThreadHandle();
|
||||
th->gc = ls.GetGC();
|
||||
th->callable = callable;
|
||||
th->hasInit = false;
|
||||
th->hasReturned = false;
|
||||
th->detached = detached;
|
||||
ls.Add(th);
|
||||
ls.GetGC()->Watch(th);
|
||||
|
||||
ls.GetGC()->BarrierBegin();
|
||||
dict->SetValue("_internal", th);
|
||||
|
||||
dict->DeclareFunction(
|
||||
ls.GetGC(), "Join", "Join thread", {},
|
||||
[th](GCList &_ls, std::vector<TObject> _args) -> TObject {
|
||||
th->thrd->Join();
|
||||
delete th->thrd;
|
||||
|
||||
if(th->hasReturned)
|
||||
{
|
||||
if (th->hasReturned) {
|
||||
_ls.GetGC()->BarrierBegin();
|
||||
auto v = th->returnValue;
|
||||
_ls.Add(v);
|
||||
_ls.GetGC()->BarrierEnd();
|
||||
return v;
|
||||
return v;
|
||||
}
|
||||
return Undefined();
|
||||
});
|
||||
dict->DeclareFunction(ls.GetGC(), "Detach","Detach thread",{},[th](GCList& _ls, std::vector<TObject> _args)-> TObject{
|
||||
dict->DeclareFunction(
|
||||
ls.GetGC(), "Detach", "Detach thread", {},
|
||||
[th](GCList &_ls, std::vector<TObject> _args) -> TObject {
|
||||
_ls.GetGC()->BarrierBegin();
|
||||
th->detached=true;
|
||||
th->detached = true;
|
||||
_ls.GetGC()->BarrierEnd();
|
||||
return Undefined();
|
||||
});
|
||||
|
||||
dict->DeclareFunction(ls.GetGC(),"getFinished","Get whether thread has finished",{},[th](GCList& _ls, std::vector<TObject> _args)-> TObject{
|
||||
return (bool)(th->hasReturned==true);
|
||||
dict->DeclareFunction(
|
||||
ls.GetGC(), "getFinished", "Get whether thread has finished", {},
|
||||
[th](GCList &_ls, std::vector<TObject> _args) -> TObject {
|
||||
return (bool)(th->hasReturned == true);
|
||||
});
|
||||
|
||||
ls.GetGC()->BarrierEnd();
|
||||
th->thrd =new Thread([th]()->void {
|
||||
std::shared_ptr<GC> gc=th->gc;
|
||||
GCList ls(gc);
|
||||
ls.Add(th);
|
||||
th->hasInit=true;
|
||||
TObject cb = th->callable->Call(ls,{});
|
||||
gc->BarrierBegin();
|
||||
th->returnValue=cb;
|
||||
gc->BarrierEnd();
|
||||
th->hasReturned=true;
|
||||
});
|
||||
while(!th->hasInit);
|
||||
return dict;
|
||||
}
|
||||
void GC::Start()
|
||||
{
|
||||
ls.GetGC()->BarrierEnd();
|
||||
th->thrd = new Thread([th]() -> void {
|
||||
std::shared_ptr<GC> gc = th->gc;
|
||||
GCList ls(gc);
|
||||
ls.Add(th);
|
||||
th->hasInit = true;
|
||||
TObject cb = th->callable->Call(ls, {});
|
||||
gc->BarrierBegin();
|
||||
th->returnValue = cb;
|
||||
gc->BarrierEnd();
|
||||
th->hasReturned = true;
|
||||
});
|
||||
while (!th->hasInit)
|
||||
;
|
||||
return dict;
|
||||
}
|
||||
void GC::Start() {
|
||||
|
||||
this->tpool=new Tesses::Framework::Lazy<Tesses::Framework::Threading::ThreadPool*>([]()->Tesses::Framework::Threading::ThreadPool*{
|
||||
auto threads = Tesses::Framework::Threading::ThreadPool::GetNumberOfCores();
|
||||
if(threads < 4) threads=4;
|
||||
this->tpool = new Tesses::Framework::Lazy<
|
||||
Tesses::Framework::Threading::ThreadPool *>(
|
||||
[]() -> Tesses::Framework::Threading::ThreadPool * {
|
||||
auto threads =
|
||||
Tesses::Framework::Threading::ThreadPool::GetNumberOfCores();
|
||||
if (threads < 4)
|
||||
threads = 4;
|
||||
return new Tesses::Framework::Threading::ThreadPool(threads);
|
||||
},[](Tesses::Framework::Threading::ThreadPool* p)->void{delete p;});
|
||||
this->mtx=new Mutex();
|
||||
this->running = true;
|
||||
this->thrd = new Thread([this]()->void {
|
||||
std::chrono::time_point<std::chrono::system_clock> last_frame, this_frame;
|
||||
},
|
||||
[](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; });
|
||||
this->mtx = new Mutex();
|
||||
this->running = true;
|
||||
this->thrd = new Thread([this]() -> void {
|
||||
std::chrono::time_point<std::chrono::system_clock> last_frame,
|
||||
this_frame;
|
||||
|
||||
this_frame = system_clock::now();
|
||||
last_frame = this_frame;
|
||||
|
||||
while(this->IsRunning())
|
||||
{
|
||||
while (this->IsRunning()) {
|
||||
this_frame = system_clock::now();
|
||||
if((this_frame - last_frame) > 10s)
|
||||
{
|
||||
|
||||
if ((this_frame - last_frame) > 10s) {
|
||||
|
||||
last_frame = this_frame;
|
||||
this->Collect();
|
||||
|
||||
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32)
|
||||
Sleep(100);
|
||||
#else
|
||||
#else
|
||||
usleep(100000);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
GC::Collect();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool GC::UsingNullThreads()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool GC::UsingNullThreads() { return false; }
|
||||
|
||||
void GC::BarrierBegin()
|
||||
{
|
||||
|
||||
this->mtx->Lock();
|
||||
}
|
||||
void GC::BarrierEnd()
|
||||
{
|
||||
|
||||
this->mtx->Unlock();
|
||||
|
||||
}
|
||||
void GC::Watch(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto _item=std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
|
||||
for(auto item : this->objects)
|
||||
{
|
||||
if(item == _item) {
|
||||
this->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->objects.push_back(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GC::Mark(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto _item=std::get<THeapObjectHolder>(obj).obj;
|
||||
_item->Mark();
|
||||
}
|
||||
}
|
||||
void GC::Unwatch(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto _item=std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
for(auto index = this->objects.begin();index<this->objects.end();index++)
|
||||
{
|
||||
if(*index == _item)
|
||||
{
|
||||
this->objects.erase(index);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GC::SetRoot(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto _item=std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
|
||||
for(auto item : this->roots)
|
||||
{
|
||||
if(item == _item) {
|
||||
this->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->roots.push_back(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
Tesses::Framework::Threading::ThreadPool* GC::GetPool()
|
||||
{
|
||||
return this->tpool->GetValue();
|
||||
}
|
||||
|
||||
void GC::UnsetRoot(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto _item=std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
for(auto index = this->roots.begin();index<this->roots.end();index++)
|
||||
{
|
||||
if(*index == _item)
|
||||
{
|
||||
this->roots.erase(index);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
|
||||
GC::~GC()
|
||||
{
|
||||
GC::BarrierBegin();
|
||||
|
||||
this->roots.clear();
|
||||
GC::BarrierEnd();
|
||||
|
||||
|
||||
|
||||
this->running=false;
|
||||
this->thrd->Join();
|
||||
delete this->thrd;
|
||||
for(auto item : objects) delete item;
|
||||
|
||||
delete this->tpool;
|
||||
delete this->mtx;
|
||||
}
|
||||
|
||||
void GC::RegisterEverythingCallback(std::function<void(std::shared_ptr<GC> gc, TRootEnvironment* env)> cb)
|
||||
{
|
||||
this->register_everything.push_back(cb);
|
||||
}
|
||||
void GC::RegisterEverything(TRootEnvironment* env)
|
||||
{
|
||||
for(auto item : this->register_everything)
|
||||
item(this->shared_from_this(),env);
|
||||
}
|
||||
void GC::Collect()
|
||||
{
|
||||
void GC::BarrierBegin() { this->mtx->Lock(); }
|
||||
void GC::BarrierEnd() { this->mtx->Unlock(); }
|
||||
void GC::Watch(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
for(auto item : this->objects)
|
||||
{
|
||||
item->marked=false;
|
||||
}
|
||||
for(auto item : this->roots)
|
||||
{
|
||||
item->Mark();
|
||||
}
|
||||
for(auto index = this->objects.begin();index < this->objects.end();index++)
|
||||
{
|
||||
THeapObject* o = *index;
|
||||
if(!o->marked)
|
||||
{
|
||||
delete o;
|
||||
this->objects.erase(index);
|
||||
index--;
|
||||
|
||||
for (auto item : this->objects) {
|
||||
if (item == _item) {
|
||||
this->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->objects.push_back(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GC::Mark(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
_item->Mark();
|
||||
}
|
||||
}
|
||||
void GC::Unwatch(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
for (auto index = this->objects.begin();
|
||||
index != this->objects.end();) {
|
||||
if (*index == _item) {
|
||||
index = this->objects.erase(index);
|
||||
continue;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
this->BarrierEnd();
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
void GC::SetRoot(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
|
||||
for (auto item : this->roots) {
|
||||
if (item == _item) {
|
||||
this->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->roots.push_back(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
Tesses::Framework::Threading::ThreadPool *GC::GetPool() {
|
||||
return this->tpool->GetValue();
|
||||
}
|
||||
|
||||
void GC::UnsetRoot(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
for (auto index = this->roots.begin(); index != this->roots.end();) {
|
||||
if (*index == _item) {
|
||||
index = this->roots.erase(index);
|
||||
continue;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
|
||||
GC::~GC() {
|
||||
GC::BarrierBegin();
|
||||
|
||||
this->roots.clear();
|
||||
GC::BarrierEnd();
|
||||
|
||||
this->running = false;
|
||||
this->thrd->Join();
|
||||
delete this->thrd;
|
||||
for (auto item : objects)
|
||||
delete item;
|
||||
|
||||
delete this->tpool;
|
||||
delete this->mtx;
|
||||
}
|
||||
|
||||
void GC::RegisterEverythingCallback(
|
||||
std::function<void(std::shared_ptr<GC> gc, TRootEnvironment *env)> cb) {
|
||||
this->register_everything.push_back(cb);
|
||||
}
|
||||
void GC::RegisterEverything(TRootEnvironment *env) {
|
||||
for (auto item : this->register_everything)
|
||||
item(this->shared_from_this(), env);
|
||||
}
|
||||
void GC::Collect() {
|
||||
this->BarrierBegin();
|
||||
for (auto item : this->objects) {
|
||||
item->marked = false;
|
||||
}
|
||||
for (auto item : this->roots) {
|
||||
item->Mark();
|
||||
}
|
||||
for (auto index = this->objects.begin(); index != this->objects.end();
|
||||
index++) {
|
||||
THeapObject *o = *index;
|
||||
if (!o->marked) {
|
||||
delete o;
|
||||
this->objects.erase(index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}; // namespace Tesses::CrossLang
|
||||
|
||||
+46
-60
@@ -1,67 +1,53 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
GCList::GCList(std::shared_ptr<GC> gc)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
this->gc = gc;
|
||||
gc->SetRoot(this);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
std::shared_ptr<GC> GCList::GetGC()
|
||||
{
|
||||
return this->gc;
|
||||
}
|
||||
void GCList::Remove(TObject obj)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto _item=std::get<THeapObjectHolder>(obj).obj;
|
||||
this->gc->BarrierBegin();
|
||||
for(auto index = this->items.begin();index<this->items.end();index++)
|
||||
{
|
||||
if(*index == _item)
|
||||
{
|
||||
this->items.erase(index);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
this->gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GCList::Add(TObject obj)
|
||||
{
|
||||
namespace Tesses::CrossLang {
|
||||
GCList::GCList(std::shared_ptr<GC> gc) {
|
||||
gc->BarrierBegin();
|
||||
this->gc = gc;
|
||||
gc->SetRoot(this);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
if(std::holds_alternative<THeapObjectHolder>(obj))
|
||||
{
|
||||
auto _item=std::get<THeapObjectHolder>(obj).obj;
|
||||
this->gc->BarrierBegin();
|
||||
|
||||
for(auto item : this->items)
|
||||
{
|
||||
if(item == _item) {
|
||||
this->gc->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
std::shared_ptr<GC> GCList::GetGC() { return this->gc; }
|
||||
void GCList::Remove(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->gc->BarrierBegin();
|
||||
for (auto index = this->items.begin(); index != this->items.end();
|
||||
index++) {
|
||||
if (*index == _item) {
|
||||
this->items.erase(index);
|
||||
continue;
|
||||
}
|
||||
this->items.push_back(_item);
|
||||
this->gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GCList::Mark()
|
||||
{
|
||||
this->marked=true;
|
||||
for(auto item : this->items)
|
||||
{
|
||||
item->Mark();
|
||||
}
|
||||
}
|
||||
GCList::~GCList()
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
this->gc->UnsetRoot(this);
|
||||
gc->BarrierEnd();
|
||||
this->gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GCList::Add(TObject obj) {
|
||||
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->gc->BarrierBegin();
|
||||
|
||||
for (auto item : this->items) {
|
||||
if (item == _item) {
|
||||
this->gc->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->items.push_back(_item);
|
||||
this->gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GCList::Mark() {
|
||||
this->marked = true;
|
||||
for (auto item : this->items) {
|
||||
item->Mark();
|
||||
}
|
||||
}
|
||||
GCList::~GCList() {
|
||||
gc->BarrierBegin();
|
||||
this->gc->UnsetRoot(this);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
|
||||
+2833
-3344
File diff suppressed because it is too large
Load Diff
+256
-258
@@ -1,260 +1,258 @@
|
||||
#if defined(VM_OPCODE_TABLE_INLINE)
|
||||
static opcode opcodes[256]={
|
||||
&InterperterThread::Add,
|
||||
&InterperterThread::Sub,
|
||||
&InterperterThread::Times,
|
||||
&InterperterThread::Divide,
|
||||
&InterperterThread::Mod,
|
||||
&InterperterThread::LShift,
|
||||
&InterperterThread::RShift,
|
||||
&InterperterThread::BOr,
|
||||
&InterperterThread::BAnd,
|
||||
&InterperterThread::BNot,
|
||||
&InterperterThread::Lt,
|
||||
&InterperterThread::Gt,
|
||||
&InterperterThread::Lte,
|
||||
&InterperterThread::Gte,
|
||||
&InterperterThread::Eq,
|
||||
&InterperterThread::NEq,
|
||||
&InterperterThread::LNot,
|
||||
&InterperterThread::Neg,
|
||||
&InterperterThread::XOr,
|
||||
&InterperterThread::Pop,
|
||||
&InterperterThread::Dup,
|
||||
&InterperterThread::Nop,
|
||||
&InterperterThread::PushClosure,
|
||||
&InterperterThread::CreateDictionary,
|
||||
&InterperterThread::CreateArray,
|
||||
&InterperterThread::AppendList,
|
||||
&InterperterThread::AppendDictionary,
|
||||
&InterperterThread::PushResource,
|
||||
&InterperterThread::PushLong,
|
||||
&InterperterThread::PushChar,
|
||||
&InterperterThread::PushDouble,
|
||||
&InterperterThread::PushString,
|
||||
&InterperterThread::PushNull,
|
||||
&InterperterThread::PushUndefined,
|
||||
&InterperterThread::ScopeBegin,
|
||||
&InterperterThread::ScopeEnd,
|
||||
&InterperterThread::ScopeEndTimes,
|
||||
&InterperterThread::PushFalse,
|
||||
&InterperterThread::PushTrue,
|
||||
&InterperterThread::SetVariable,
|
||||
&InterperterThread::GetVariable,
|
||||
&InterperterThread::DeclareVariable,
|
||||
&InterperterThread::SetField,
|
||||
&InterperterThread::GetField,
|
||||
&InterperterThread::ExecuteFunction,
|
||||
&InterperterThread::ExecuteMethod,
|
||||
&InterperterThread::Return,
|
||||
&InterperterThread::JumpConditional,
|
||||
&InterperterThread::Jump,
|
||||
&InterperterThread::JumpUndefined,
|
||||
&InterperterThread::Defer,
|
||||
&InterperterThread::TryCatch,
|
||||
&InterperterThread::Throw,
|
||||
&InterperterThread::PushScopelessClosure,
|
||||
&InterperterThread::Yield,
|
||||
&InterperterThread::PushRootPath,
|
||||
&InterperterThread::PushRelativePath,
|
||||
&InterperterThread::Breakpoint,
|
||||
&InterperterThread::PushBreak,
|
||||
&InterperterThread::PushContinue,
|
||||
&InterperterThread::JumpIfBreak,
|
||||
&InterperterThread::JumpIfContinue,
|
||||
&InterperterThread::JumpIfDefined,
|
||||
&InterperterThread::DeclareConstVariable,
|
||||
&InterperterThread::LineInfo,
|
||||
&InterperterThread::PushResourceStream,
|
||||
&InterperterThread::PushResourceDirectory,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal
|
||||
};
|
||||
static opcode opcodes[256] = {&InterperterThread::Add,
|
||||
&InterperterThread::Sub,
|
||||
&InterperterThread::Times,
|
||||
&InterperterThread::Divide,
|
||||
&InterperterThread::Mod,
|
||||
&InterperterThread::LShift,
|
||||
&InterperterThread::RShift,
|
||||
&InterperterThread::BOr,
|
||||
&InterperterThread::BAnd,
|
||||
&InterperterThread::BNot,
|
||||
&InterperterThread::Lt,
|
||||
&InterperterThread::Gt,
|
||||
&InterperterThread::Lte,
|
||||
&InterperterThread::Gte,
|
||||
&InterperterThread::Eq,
|
||||
&InterperterThread::NEq,
|
||||
&InterperterThread::LNot,
|
||||
&InterperterThread::Neg,
|
||||
&InterperterThread::XOr,
|
||||
&InterperterThread::Pop,
|
||||
&InterperterThread::Dup,
|
||||
&InterperterThread::Nop,
|
||||
&InterperterThread::PushClosure,
|
||||
&InterperterThread::CreateDictionary,
|
||||
&InterperterThread::CreateArray,
|
||||
&InterperterThread::AppendList,
|
||||
&InterperterThread::AppendDictionary,
|
||||
&InterperterThread::PushResource,
|
||||
&InterperterThread::PushLong,
|
||||
&InterperterThread::PushChar,
|
||||
&InterperterThread::PushDouble,
|
||||
&InterperterThread::PushString,
|
||||
&InterperterThread::PushNull,
|
||||
&InterperterThread::PushUndefined,
|
||||
&InterperterThread::ScopeBegin,
|
||||
&InterperterThread::ScopeEnd,
|
||||
&InterperterThread::ScopeEndTimes,
|
||||
&InterperterThread::PushFalse,
|
||||
&InterperterThread::PushTrue,
|
||||
&InterperterThread::SetVariable,
|
||||
&InterperterThread::GetVariable,
|
||||
&InterperterThread::DeclareVariable,
|
||||
&InterperterThread::SetField,
|
||||
&InterperterThread::GetField,
|
||||
&InterperterThread::ExecuteFunction,
|
||||
&InterperterThread::ExecuteMethod,
|
||||
&InterperterThread::Return,
|
||||
&InterperterThread::JumpConditional,
|
||||
&InterperterThread::Jump,
|
||||
&InterperterThread::JumpUndefined,
|
||||
&InterperterThread::Defer,
|
||||
&InterperterThread::TryCatch,
|
||||
&InterperterThread::Throw,
|
||||
&InterperterThread::PushScopelessClosure,
|
||||
&InterperterThread::Yield,
|
||||
&InterperterThread::PushRootPath,
|
||||
&InterperterThread::PushRelativePath,
|
||||
&InterperterThread::Breakpoint,
|
||||
&InterperterThread::PushBreak,
|
||||
&InterperterThread::PushContinue,
|
||||
&InterperterThread::JumpIfBreak,
|
||||
&InterperterThread::JumpIfContinue,
|
||||
&InterperterThread::JumpIfDefined,
|
||||
&InterperterThread::DeclareConstVariable,
|
||||
&InterperterThread::LineInfo,
|
||||
&InterperterThread::PushResourceStream,
|
||||
&InterperterThread::PushResourceDirectory,
|
||||
&InterperterThread::PushPrivateExpression,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal,
|
||||
&InterperterThread::Illegal};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user