Fix bug with classes, use slim exclusively, add package private data and change rehaul cmake configs
This commit is contained in:
@@ -1,247 +1,248 @@
|
||||
#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;
|
||||
namespace Tesses::CrossLang {
|
||||
std::string TClassObject::TypeName() {
|
||||
std::string type = "class ";
|
||||
type += this->name;
|
||||
for (auto &item : this->inherit_tree)
|
||||
type += " : " + item;
|
||||
return type;
|
||||
}
|
||||
TObject TClassObject::CallMethod(GCList &ls, std::string className,
|
||||
std::string name, std::vector<TObject> args) {
|
||||
auto value = this->GetValue(className, name);
|
||||
TCallable *callable;
|
||||
if (GetObjectHeap(value, callable)) {
|
||||
return callable->Call(ls, args);
|
||||
}
|
||||
TObject TClassObject::CallMethod(GCList& ls, std::string className, std::string name,std::vector<TObject> args)
|
||||
{
|
||||
auto value = this->GetValue(className,name);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(value, callable))
|
||||
{
|
||||
return callable->Call(ls,args);
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
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;
|
||||
default:
|
||||
//DO NOTHING
|
||||
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->inherits,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;
|
||||
return Undefined();
|
||||
}
|
||||
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) {
|
||||
|
||||
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.");
|
||||
return &item;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// DO NOTHING
|
||||
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 (entry.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->inherits, 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 (entry.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->closure->name = obj->name + "::" + ent.name;
|
||||
clos->className = ownerNow;
|
||||
clos->documentation = entry.documentation;
|
||||
ent.value = clos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(entry.isAbstract) ent.value = Undefined();
|
||||
} else {
|
||||
if (entry.isAbstract)
|
||||
ent.value = Undefined();
|
||||
else {
|
||||
auto clos = TClosure::Create(ls,obj->env,file,entry.chunkId);
|
||||
auto clos =
|
||||
TClosure::Create(ls, obj->env, file, entry.chunkId);
|
||||
clos->closure->name = obj->name + "::" + ent.name;
|
||||
clos->className = ownerNow;
|
||||
ent.value = clos->Call(*ls,{});
|
||||
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;
|
||||
}
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
Reference in New Issue
Block a user