mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-02-09 01:25:45 +00:00
Add classes
This commit is contained in:
28
src/types/any.cpp
Normal file
28
src/types/any.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
TAny* TAny::Create(GCList& ls)
|
||||
{
|
||||
TAny* anyObj = new TAny();
|
||||
|
||||
GC* gc = ls.GetGC();
|
||||
ls.Add(anyObj);
|
||||
gc->Watch(anyObj);
|
||||
return anyObj;
|
||||
}
|
||||
TAny* TAny::Create(GCList* ls)
|
||||
{
|
||||
TAny* anyObj = new TAny();
|
||||
|
||||
GC* gc = ls->GetGC();
|
||||
ls->Add(anyObj);
|
||||
gc->Watch(anyObj);
|
||||
return anyObj;
|
||||
}
|
||||
void TAny::Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
GC::Mark(this->other);
|
||||
}
|
||||
}
|
||||
232
src/types/class.cpp
Normal file
232
src/types/class.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
#include "CrossLang.hpp"
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
std::string TClassObject::TypeName()
|
||||
{
|
||||
std::string type = "class ";
|
||||
type += this->name;
|
||||
for(auto& item : this->inherit_tree) type += " : " + item;
|
||||
return type;
|
||||
}
|
||||
TClassObjectEntry* TClassObject::GetEntry(std::string classN, std::string key)
|
||||
{
|
||||
for(auto& item : this->entries)
|
||||
{
|
||||
if(item.name == key)
|
||||
{
|
||||
switch(item.modifier)
|
||||
{
|
||||
case TClassModifier::Private:
|
||||
if(classN != item.owner) return nullptr;
|
||||
break;
|
||||
case TClassModifier::Protected:
|
||||
if(classN.empty()) return nullptr;
|
||||
if(classN != item.owner)
|
||||
{
|
||||
for(auto inh : this->inherit_tree)
|
||||
{
|
||||
if(inh == classN) {
|
||||
|
||||
return &item;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return &item;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
TClassObject* TClassObject::Create(GCList& ls, TFile* f, uint32_t classIndex, TEnvironment* env, std::vector<TObject> args)
|
||||
{
|
||||
return Create(&ls,f,classIndex,env,args);
|
||||
}
|
||||
std::string JoinPeriod(std::vector<std::string>& p)
|
||||
{
|
||||
std::string newStr = "";
|
||||
for(size_t i = 0; i < p.size(); i++)
|
||||
{
|
||||
if(i > 0) newStr.push_back('.');
|
||||
newStr += p[i];
|
||||
}
|
||||
return newStr;
|
||||
}
|
||||
TClassObject* TClassObject::Create(GCList* ls, TFile* f, uint32_t classIndex, TEnvironment* env, std::vector<TObject> args)
|
||||
{
|
||||
if(ls == nullptr) return nullptr;
|
||||
TClassObject* obj = new TClassObject();
|
||||
obj->file = f;
|
||||
obj->classIndex = classIndex;
|
||||
obj->ogEnv=env;
|
||||
obj->env = TClassEnvironment::Create(ls,env,obj);
|
||||
obj->name = JoinPeriod(f->classes[classIndex].name);
|
||||
bool hasToString=false;
|
||||
|
||||
for(auto entry : f->classes[classIndex].entry)
|
||||
{
|
||||
if(entry.modifier == TClassModifier::Static) continue;
|
||||
TClassObjectEntry ent;
|
||||
ent.name = entry.name;
|
||||
ent.modifier = entry.modifier;
|
||||
ent.canSet = !entry.isFunction;
|
||||
ent.owner = obj->name;
|
||||
|
||||
if(entry.isFunction)
|
||||
{
|
||||
if(ent.name == "ToString") hasToString=true;
|
||||
if(entry.isAbstract)
|
||||
{
|
||||
delete obj;
|
||||
throw VMException("Method " + ent.name + " in " + ent.owner + " is abstract.");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto clos = TClosure::Create(ls,obj->env,obj->file,entry.chunkId);
|
||||
clos->documentation = entry.documentation;
|
||||
clos->className = ent.owner;
|
||||
ent.value = clos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(entry.isAbstract) ent.value = Undefined();
|
||||
else {
|
||||
auto clos = TClosure::Create(ls,obj->env,obj->file,entry.chunkId);
|
||||
|
||||
clos->className=ent.owner;
|
||||
ent.value = clos->Call(*ls,{});
|
||||
}
|
||||
}
|
||||
|
||||
obj->entries.push_back(ent);
|
||||
}
|
||||
|
||||
TClass* clsCur = &f->classes[classIndex];
|
||||
TRootEnvironment* rEnv = env->GetRootEnvironment();
|
||||
while(!clsCur->inherits.empty() && !(clsCur->inherits.size() == 1 && clsCur->inherits[0] == "ClassObject"))
|
||||
{
|
||||
obj->inherit_tree.push_back(JoinPeriod(clsCur->inherits));
|
||||
size_t idx;
|
||||
if(rEnv->TryFindClass(clsCur->name,idx))
|
||||
{
|
||||
auto file = rEnv->classes[idx].first;
|
||||
clsCur = &rEnv->classes[idx].first->classes.at(rEnv->classes[idx].second);
|
||||
auto ownerNow = JoinPeriod(clsCur->name);
|
||||
for(auto entry : clsCur->entry)
|
||||
{
|
||||
if(entry.modifier == TClassModifier::Static) continue;
|
||||
bool cont=false;
|
||||
for(auto e : obj->entries)
|
||||
if(e.name == entry.name)
|
||||
{
|
||||
cont=true;
|
||||
break;
|
||||
}
|
||||
if(cont) continue;
|
||||
|
||||
TClassObjectEntry ent;
|
||||
ent.name = entry.name;
|
||||
ent.modifier = entry.modifier;
|
||||
ent.canSet = !entry.isFunction;
|
||||
ent.owner = ownerNow;
|
||||
|
||||
if(entry.isFunction)
|
||||
{
|
||||
|
||||
if(ent.name == "ToString") hasToString=true;
|
||||
if(entry.isAbstract)
|
||||
{
|
||||
delete obj;
|
||||
throw VMException("Method " + ent.name + " in " + ownerNow + " is abstract.");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||
clos->className = ownerNow;
|
||||
clos->documentation = entry.documentation;
|
||||
ent.value = clos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(entry.isAbstract) ent.value = Undefined();
|
||||
else {
|
||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||
clos->className = ownerNow;
|
||||
ent.value = clos->Call(*ls,{});
|
||||
}
|
||||
}
|
||||
|
||||
obj->entries.push_back(ent);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if(!hasToString)
|
||||
{
|
||||
TClassObjectEntry ent;
|
||||
ent.canSet=false;
|
||||
ent.modifier = TClassModifier::Public;
|
||||
ent.name = "ToString";
|
||||
ent.owner = obj->name;
|
||||
ent.value = TExternalMethod::Create(ls,"The ToString",{},[obj](GCList& ls,std::vector<TObject> args)->TObject { return obj->TypeName();});
|
||||
obj->entries.push_back(ent);
|
||||
}
|
||||
TCallable* call=nullptr;
|
||||
std::string fnName = f->classes[classIndex].name[f->classes[classIndex].name.size()-1];
|
||||
for(auto& item : obj->entries)
|
||||
if(item.name == fnName)
|
||||
{
|
||||
GetObjectHeap(item.value,call);
|
||||
break;
|
||||
}
|
||||
ls->Add(obj);
|
||||
ls->GetGC()->Watch(obj);
|
||||
|
||||
if(call != nullptr) call->Call(*ls,args);
|
||||
return obj;
|
||||
}
|
||||
|
||||
TObject TClassObject::GetValue(std::string className, std::string key)
|
||||
{
|
||||
auto ent = GetEntry(className,key);
|
||||
if(ent == nullptr) return Undefined();
|
||||
return ent->value;
|
||||
}
|
||||
void TClassObject::SetValue(std::string className, std::string key,TObject value)
|
||||
{
|
||||
auto ent = GetEntry(className,key);
|
||||
if(ent == nullptr) return;
|
||||
if(ent->canSet) ent->value = value;
|
||||
}
|
||||
bool TClassObject::HasValue(std::string className,std::string key)
|
||||
{
|
||||
auto ent = GetEntry(className,key);
|
||||
return ent != nullptr;
|
||||
|
||||
}
|
||||
bool TClassObject::HasField(std::string className,std::string key)
|
||||
{
|
||||
auto ent = GetEntry(className,key);
|
||||
if(ent == nullptr) return false;
|
||||
return ent->canSet;
|
||||
}
|
||||
bool TClassObject::HasMethod(std::string className,std::string key)
|
||||
{
|
||||
auto ent = GetEntry(className,key);
|
||||
if(ent == nullptr) return false;
|
||||
TCallable* call;
|
||||
return GetObjectHeap(ent->value,call);
|
||||
}
|
||||
void TClassObject::Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
this->env->Mark();
|
||||
this->file->Mark();
|
||||
this->ogEnv->Mark();
|
||||
for(auto& item : this->entries) GC::Mark(item.value);
|
||||
|
||||
}
|
||||
}
|
||||
122
src/types/classenvironment.cpp
Normal file
122
src/types/classenvironment.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "CrossLang.hpp"
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
TClassEnvironment* TClassEnvironment::Create(GCList* gc,TEnvironment* env,TClassObject* obj)
|
||||
{
|
||||
|
||||
TClassEnvironment* env2=new TClassEnvironment(env,obj);
|
||||
|
||||
GC* _gc = gc->GetGC();
|
||||
gc->Add(env2);
|
||||
_gc->Watch(env2);
|
||||
return env2;
|
||||
}
|
||||
TClassEnvironment* TClassEnvironment::Create(GCList& gc,TEnvironment* env,TClassObject* obj)
|
||||
{
|
||||
|
||||
TClassEnvironment* env2=new TClassEnvironment(env,obj);
|
||||
|
||||
GC* _gc = gc.GetGC();
|
||||
gc.Add(env2);
|
||||
_gc->Watch(env2);
|
||||
return env2;
|
||||
}
|
||||
TClassEnvironment::TClassEnvironment(TEnvironment* env,TClassObject* obj)
|
||||
{
|
||||
this->env = env;
|
||||
this->clsObj=obj;
|
||||
}
|
||||
bool TClassEnvironment::HasVariable(std::string key)
|
||||
{
|
||||
if(key == "this") return true;
|
||||
if(this->clsObj->HasValue(current_function == nullptr ? "" : current_function->callable->className,key)) return true;
|
||||
return false;
|
||||
}
|
||||
bool TClassEnvironment::HasVariableRecurse(std::string key)
|
||||
{
|
||||
if(HasVariable(key)) return true;
|
||||
return this->env->HasVariableRecurse(key);
|
||||
}
|
||||
bool TClassEnvironment::HasVariableOrFieldRecurse(std::string key, bool setting)
|
||||
{
|
||||
if(key == "this") return true;
|
||||
std::string clsName = current_function == nullptr ? "" : current_function->callable->className;
|
||||
if(clsObj->HasMethod(clsName,(setting ? "set" : "get")+key)) return true;
|
||||
if(clsObj->HasValue(clsName,key)) return true;
|
||||
return env->HasVariableOrFieldRecurse(key,setting);
|
||||
}
|
||||
|
||||
TObject TClassEnvironment::GetVariable(std::string key)
|
||||
{
|
||||
if(key == "this") return this->clsObj;
|
||||
|
||||
std::string clsName = current_function == nullptr ? "" : current_function->callable->className;
|
||||
|
||||
if(clsObj->HasValue(clsName,key)) return this->clsObj->GetValue(clsName,key);
|
||||
return env->GetVariable(key);
|
||||
}
|
||||
void TClassEnvironment::SetVariable(std::string key, TObject value)
|
||||
{
|
||||
if(key == "this") return;
|
||||
|
||||
std::string clsName = current_function == nullptr ? "" : current_function->callable->className;
|
||||
|
||||
if(clsObj->HasValue(clsName,key))
|
||||
{
|
||||
this->clsObj->SetValue(clsName,key,value);
|
||||
return;
|
||||
}
|
||||
this->env->SetVariable(key,value);
|
||||
return;
|
||||
}
|
||||
TObject TClassEnvironment::GetVariable(GCList& ls, std::string key)
|
||||
{
|
||||
if(key == "this") return this->clsObj;
|
||||
|
||||
std::string clsName = current_function == nullptr ? "" : current_function->callable->className;
|
||||
if(this->clsObj->HasMethod(clsName,"get"+key))
|
||||
{
|
||||
auto res=this->clsObj->GetValue(clsName,"get"+key);
|
||||
TCallable* call;
|
||||
if(GetObjectHeap(res,call)) return call->Call(ls,{});
|
||||
}
|
||||
if(this->clsObj->HasValue(clsName,key)) return this->clsObj->GetValue(clsName,key);
|
||||
return this->env->GetVariable(ls,key);
|
||||
}
|
||||
TObject TClassEnvironment::SetVariable(GCList& ls, std::string key, TObject v)
|
||||
{
|
||||
if(key == "this") return this->clsObj;
|
||||
|
||||
std::string clsName = current_function == nullptr ? "" : current_function->callable->className;
|
||||
if(this->clsObj->HasMethod(clsName,"set"+key))
|
||||
{
|
||||
auto res=this->clsObj->GetValue(clsName,"set"+key);
|
||||
TCallable* call;
|
||||
if(GetObjectHeap(res,call)) return call->Call(ls,{v});
|
||||
}
|
||||
if(this->clsObj->HasValue(clsName,key)) { this->clsObj->SetValue(clsName,key,v); return v;}
|
||||
return this->env->SetVariable(ls,key,v);
|
||||
}
|
||||
|
||||
void TClassEnvironment::DeclareVariable(std::string key, TObject value)
|
||||
{
|
||||
|
||||
}
|
||||
TRootEnvironment* TClassEnvironment::GetRootEnvironment()
|
||||
{
|
||||
return this->env->GetRootEnvironment();
|
||||
}
|
||||
TEnvironment* TClassEnvironment::GetParentEnvironment()
|
||||
{
|
||||
return this->env;
|
||||
}
|
||||
|
||||
void TClassEnvironment::Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
this->clsObj->Mark();
|
||||
this->env->Mark();
|
||||
for(auto item : this->defers) item->Mark();
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ namespace Tesses::CrossLang {
|
||||
TClosure* TClosure::Create(GCList& ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope)
|
||||
{
|
||||
TClosure* closure = new TClosure();
|
||||
closure->className="";
|
||||
closure->ownScope=ownScope;
|
||||
GC* _gc = ls.GetGC();
|
||||
ls.Add(closure);
|
||||
@@ -68,6 +69,7 @@ namespace Tesses::CrossLang {
|
||||
TClosure* TClosure::Create(GCList* ls,TEnvironment* env,TFile* file,uint32_t chunkId,bool ownScope)
|
||||
{
|
||||
TClosure* closure = new TClosure();
|
||||
closure->className="";
|
||||
closure->ownScope=ownScope;
|
||||
GC* _gc = ls->GetGC();
|
||||
ls->Add(closure);
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
TNativeObject::~TNativeObject()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TNative::TNative(void* ptr,std::function<void(void*)> destroy)
|
||||
{
|
||||
this->ptr = ptr;
|
||||
@@ -34,6 +39,18 @@ namespace Tesses::CrossLang
|
||||
this->destroy(this->ptr);
|
||||
}
|
||||
}
|
||||
bool TNativeObject::ToBool()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool TNativeObject::Equals(GC* gc, TObject right)
|
||||
{
|
||||
if(std::holds_alternative<THeapObjectHolder>(right))
|
||||
{
|
||||
return this == std::get<THeapObjectHolder>(right).obj;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
TNative* TNative::Create(GCList& ls, void* ptr,std::function<void(void*)> destroy)
|
||||
{
|
||||
TNative* native = new TNative(ptr,destroy);
|
||||
|
||||
@@ -2,6 +2,69 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
namespace Tesses::CrossLang {
|
||||
bool TRootEnvironment::TryFindClass(std::vector<std::string>& name, size_t& index)
|
||||
{
|
||||
for(size_t i = 0; i < this->classes.size(); i++)
|
||||
{
|
||||
if(classes[i].first->classes.at(classes[i].second).name.size() != name.size()) continue;
|
||||
for(size_t j = 0; j < name.size(); j++)
|
||||
if(classes[i].first->classes.at(classes[i].second).name[j] != name[j]) continue;
|
||||
index=i;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool TRootEnvironment::HasVariableOrFieldRecurse(std::string key,bool setting)
|
||||
{
|
||||
std::string property=(setting? "set":"get") + key;
|
||||
if(this->HasVariable(property))
|
||||
{
|
||||
auto res = this->GetVariable(property);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(res,callable)) return true;
|
||||
}
|
||||
|
||||
return this->HasVariable(key);
|
||||
}
|
||||
TObject TRootEnvironment::GetVariable(GCList& ls, std::string key)
|
||||
{
|
||||
ls.GetGC()->BarrierBegin();
|
||||
if(this->HasVariable("get" + key))
|
||||
{
|
||||
auto item = this->GetVariable("get"+key);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(item,callable))
|
||||
{
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return callable->Call(ls,{});
|
||||
}
|
||||
}
|
||||
|
||||
auto item = this->GetVariable(key);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return item;
|
||||
}
|
||||
TObject TRootEnvironment::SetVariable(GCList& ls, std::string key, TObject value)
|
||||
{
|
||||
ls.GetGC()->BarrierBegin();
|
||||
if(this->HasVariable("set" + key))
|
||||
{
|
||||
auto item = this->GetVariable("set"+key);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(item,callable))
|
||||
{
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return callable->Call(ls,{value});
|
||||
}
|
||||
}
|
||||
|
||||
this->SetVariable(key,value);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void TRootEnvironment::LoadDependency(GC* gc,Tesses::Framework::Filesystem::VFS* vfs, std::pair<std::string,TVMVersion> dep)
|
||||
{
|
||||
for(auto item : this->dependencies)
|
||||
@@ -45,9 +108,115 @@ namespace Tesses::CrossLang {
|
||||
f->Load(ls.GetGC(),&ms);
|
||||
return this->LoadFile(ls.GetGC(), f);
|
||||
}
|
||||
TDictionary* TEnvironment::EnsureDictionary(GC* gc, std::string key)
|
||||
{
|
||||
TObject item = this->GetVariable(key);
|
||||
TDictionary* dict;
|
||||
if(GetObjectHeap(item,dict)) return dict;
|
||||
GCList ls(gc);
|
||||
dict = TDictionary::Create(ls);
|
||||
this->DeclareVariable(key, dict);
|
||||
return dict;
|
||||
}
|
||||
void TEnvironment::DeclareVariable(GC* gc, std::vector<std::string> name, TObject o)
|
||||
{
|
||||
if(name.size() == 0)
|
||||
throw VMException("name can't be empty.");
|
||||
|
||||
else if(name.size() == 1)
|
||||
{
|
||||
GCList ls(gc);
|
||||
|
||||
gc->BarrierBegin();
|
||||
this->DeclareVariable(name[0],o);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
GCList ls(gc);
|
||||
|
||||
TObject v = this->GetVariable(name[0]);
|
||||
TDictionary* dict=nullptr;
|
||||
if(std::holds_alternative<THeapObjectHolder>(v))
|
||||
{
|
||||
dict=dynamic_cast<TDictionary*>(std::get<THeapObjectHolder>(v).obj);
|
||||
if(dict == nullptr)
|
||||
{
|
||||
dict = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
this->SetVariable(name[0],dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dict = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
this->DeclareVariable(name[0],dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
for(size_t i = 1; i < name.size()-1; i++)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
auto v = dict->GetValue(name[i]);
|
||||
gc->BarrierEnd();
|
||||
if(std::holds_alternative<THeapObjectHolder>(v))
|
||||
{
|
||||
auto dict2=dynamic_cast<TDictionary*>(std::get<THeapObjectHolder>(v).obj);
|
||||
if(dict2 == nullptr)
|
||||
{
|
||||
dict2 = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue(name[i],dict2);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
dict = dict2;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dict2 = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue(name[i],dict2);
|
||||
gc->BarrierEnd();
|
||||
dict = dict2;
|
||||
}
|
||||
}
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue(name[name.size()-1],o);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
|
||||
TObject TEnvironment::LoadFile(GC* gc, TFile* file)
|
||||
{
|
||||
for(auto fn : file->functions)
|
||||
file->EnsureCanRunInCrossLang();
|
||||
for(size_t i = 0; i < file->classes.size(); i++)
|
||||
{
|
||||
this->GetRootEnvironment()->classes.push_back(std::pair<TFile*,uint32_t>(file,(uint32_t)i));
|
||||
std::vector<std::string> clsPart={"New"};
|
||||
clsPart.insert(clsPart.end(),file->classes[i].name.begin(),file->classes[i].name.end());
|
||||
GCList ls(gc);
|
||||
std::vector<std::string> name=file->classes[i].name;
|
||||
auto rootEnv = this->GetRootEnvironment();
|
||||
this->DeclareVariable(gc, clsPart, TExternalMethod::Create(ls,"Create instance of the class",{"$$args"},[rootEnv,file,i](GCList& ls, std::vector<TObject> args)->TObject{
|
||||
return TClassObject::Create(ls, file,i,rootEnv,args);
|
||||
}));
|
||||
for(auto meth : file->classes[i].entry)
|
||||
{
|
||||
|
||||
if(meth.isFunction && meth.modifier == TClassModifier::Static)
|
||||
{
|
||||
std::vector<std::string> method=file->classes[i].name;
|
||||
method.push_back(meth.name);
|
||||
auto clo = TClosure::Create(ls,this,file,meth.chunkId);
|
||||
clo->documentation = meth.documentation;
|
||||
this->DeclareVariable(gc, method, clo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
for(auto fn : file->functions)
|
||||
{
|
||||
|
||||
std::string name;
|
||||
@@ -59,76 +228,11 @@ namespace Tesses::CrossLang {
|
||||
|
||||
if(fn.second >= file->chunks.size()) throw VMException("ChunkId out of bounds.");
|
||||
TFileChunk* chunk = file->chunks[fn.second];
|
||||
GCList ls(gc);
|
||||
TClosure* closure=TClosure::Create(ls,this,file,fn.second);
|
||||
closure->documentation = fn.first[0];
|
||||
this->DeclareVariable(gc,items,closure);
|
||||
|
||||
|
||||
if(items.size() == 0)
|
||||
throw VMException("Function name can't be empty.");
|
||||
|
||||
else if(items.size() == 1)
|
||||
{
|
||||
GCList ls(gc);
|
||||
TClosure* closure=TClosure::Create(ls,this,file,fn.second);
|
||||
closure->documentation = fn.first[0];
|
||||
gc->BarrierBegin();
|
||||
this->DeclareVariable(items[0],closure);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
GCList ls(gc);
|
||||
TClosure* closure=TClosure::Create(ls,this,file,fn.second);
|
||||
closure->documentation = fn.first[0];
|
||||
TObject v = this->GetVariable(items[0]);
|
||||
TDictionary* dict=nullptr;
|
||||
if(std::holds_alternative<THeapObjectHolder>(v))
|
||||
{
|
||||
dict=dynamic_cast<TDictionary*>(std::get<THeapObjectHolder>(v).obj);
|
||||
if(dict == nullptr)
|
||||
{
|
||||
dict = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
this->SetVariable(items[0],dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dict = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
this->DeclareVariable(items[0],dict);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
|
||||
for(size_t i = 1; i < items.size()-1; i++)
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
auto v = dict->GetValue(items[i]);
|
||||
gc->BarrierEnd();
|
||||
if(std::holds_alternative<THeapObjectHolder>(v))
|
||||
{
|
||||
auto dict2=dynamic_cast<TDictionary*>(std::get<THeapObjectHolder>(v).obj);
|
||||
if(dict2 == nullptr)
|
||||
{
|
||||
dict2 = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue(items[i],dict2);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
dict = dict2;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dict2 = TDictionary::Create(ls);
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue(items[i],dict2);
|
||||
gc->BarrierEnd();
|
||||
dict = dict2;
|
||||
}
|
||||
}
|
||||
gc->BarrierBegin();
|
||||
dict->SetValue(items[items.size()-1],closure);
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
}
|
||||
if(!file->chunks.empty())
|
||||
{
|
||||
@@ -174,7 +278,7 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
void TRootEnvironment::SetVariable(std::string key, TObject value)
|
||||
{
|
||||
return this->dict->SetValue(key,value);
|
||||
this->dict->SetValue(key,value);
|
||||
}
|
||||
void TRootEnvironment::DeclareVariable(std::string key, TObject value)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,88 @@ namespace Tesses::CrossLang {
|
||||
{
|
||||
return this->dict;
|
||||
}
|
||||
bool TSubEnvironment::HasVariableOrFieldRecurse(std::string key,bool setting)
|
||||
{
|
||||
std::string property=(setting? "set":"get") + key;
|
||||
if(this->HasVariable(property))
|
||||
{
|
||||
auto res = this->GetVariable(property);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(res,callable)) return true;
|
||||
}
|
||||
|
||||
if(this->HasVariable(key)) return true;
|
||||
|
||||
return this->env->HasVariableOrFieldRecurse(key,setting);
|
||||
}
|
||||
TObject TSubEnvironment::GetVariable(GCList& ls, std::string key)
|
||||
{
|
||||
ls.GetGC()->BarrierBegin();
|
||||
if(this->HasVariable("get" + key))
|
||||
{
|
||||
auto item = this->GetVariable("get"+key);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(item,callable))
|
||||
{
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return callable->Call(ls,{});
|
||||
}
|
||||
}
|
||||
|
||||
if(this->HasVariable(key))
|
||||
{
|
||||
auto item = this->GetVariable(key);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return item;
|
||||
}
|
||||
if(this->env->HasVariableOrFieldRecurse(key))
|
||||
{
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return this->env->GetVariable(ls,key);
|
||||
}
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
TObject TSubEnvironment::SetVariable(GCList& ls, std::string key, TObject value)
|
||||
{
|
||||
ls.GetGC()->BarrierBegin();
|
||||
if(this->HasVariable("set" + key))
|
||||
{
|
||||
auto item = this->GetVariable("set"+key);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(item,callable))
|
||||
{
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return callable->Call(ls,{value});
|
||||
}
|
||||
}
|
||||
|
||||
if(this->HasVariable(key))
|
||||
{
|
||||
this->SetVariable(key,value);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return value;
|
||||
}
|
||||
if(this->env->HasVariableOrFieldRecurse(key,true))
|
||||
{
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return this->env->SetVariable(ls,key,value);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->env->SetVariable(key,value);
|
||||
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return value;
|
||||
}
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
|
||||
}
|
||||
|
||||
TObject TSubEnvironment::GetVariable(std::string key)
|
||||
{
|
||||
if(this->dict->HasValue(key))
|
||||
|
||||
Reference in New Issue
Block a user