#include "CrossLang.hpp" #include #include #include namespace Tesses::CrossLang { static TObject AstToTObject(GCList& ls,SyntaxNode node) { if(std::holds_alternative(node)) return nullptr; if(std::holds_alternative(node)) { return std::get(node); } if(std::holds_alternative(node)) { return std::get(node); } if(std::holds_alternative(node)) { return std::get(node); } if(std::holds_alternative(node)) { std::string str = std::get(node); return str; } if(std::holds_alternative(node)) { char c = std::get(node); return c; } if(std::holds_alternative(node)) { auto r = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); r->SetValue("Type",std::string(UndefinedExpression)); ls.GetGC()->BarrierEnd(); return r; } if(std::holds_alternative(node)) { auto asn = std::get(node); auto r = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); r->SetValue("Type",asn.nodeName); r->SetValue("IsExpression",asn.isExpression); TList* ls2 = TList::Create(ls); for(auto item : asn.nodes) { ls2->Add(AstToTObject(ls,item)); } r->SetValue("Arguments", ls2); ls.GetGC()->BarrierEnd(); return r; } return nullptr; } static TObject VM_SourceToAst(GCList& ls, std::vector args) { std::string str; if(GetArgument(args,0,str)) { std::stringstream strm(str); std::vector tokens; int res = Lex("memory.tcross",strm,tokens); if(res != 0) { throw VMException("Lex error at line: " + std::to_string(res)); } Parser p(tokens); auto res2 =p.ParseRoot(); return AstToTObject(ls,res2); } return nullptr; } static TObject VM_Eval(GCList& ls, std::vector args) { std::string str; if(GetArgument(args,0,str)) { if(current_function != nullptr) { return current_function->env->Eval(ls,str); } } return nullptr; } static TObject Failure(GCList& ls, std::string reason) { TDictionary* dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); dict->SetValue("Success",false); dict->SetValue("Reason", reason); ls.GetGC()->BarrierEnd(); return dict; } static TObject Success(GCList& ls) { TDictionary* dict = TDictionary::Create(ls); ls.GetGC()->BarrierBegin(); dict->SetValue("Success",true); ls.GetGC()->BarrierEnd(); return dict; } static TObject VM_getCurrentEnvironment(GCList& ls2,std::vector args) { if(current_function != nullptr) return current_function->env; return Undefined(); } static TObject VM_Compile(GCList& ls, std::vector args) { try { TDictionary* dict; if(!GetArgumentHeap(args,0,dict)) return Undefined(); /* VM.Compile { Name = "My name", Info = "", Sources = [], Version = "", Dependencies = [{Name="Name", Version}], ResourceDirectory = "", } */ std::string name = "Out"; std::vector> sources; TVMVersion version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE); std::vector> dependencies; std::vector> tools; std::string info; std::string icon; TVFSHeapObject* vfsHO =nullptr; ls.GetGC()->BarrierBegin(); TObject _name = dict->GetValue("Name"); TObject _version = dict->GetValue("Version"); TObject _sources = dict->GetValue("Sources"); TObject _dependencies = dict->GetValue("Dependencies"); TObject _tools = dict->GetValue("Tools"); TObject _info = dict->GetValue("Info"); TObject _icon = dict->GetValue("Icon"); TObject _resourceFileSystem = dict->GetValue("ResourceFileSystem"); TObject _out = dict->GetValue("Output"); TList* _toolList; TList* _depList; TList* srcLst; GetObject(_name,name); GetObject(_info,info); GetObject(_icon,icon); GetObjectHeap(_resourceFileSystem, vfsHO); std::string v2; if(GetObject(_version,v2)) TVMVersion::TryParse(v2, version); else GetObject(_version,version); if(GetObjectHeap(_dependencies,_depList)) { for(int64_t i = 0; i < _depList->Count(); i++) { TObject _dep = _depList->Get(i); TDictionary* _depD; if(GetObjectHeap(_dep, _depD)) { TObject _name2 = _depD->GetValue("Name"); TObject _version2 = _depD->GetValue("Version"); std::string name2; std::string version2; TVMVersion version02; if(GetObject(_name2,name2) && GetObject(_version2,version2) && TVMVersion::TryParse(version2,version02)) { dependencies.push_back(std::pair(name2, version02)); } else if(GetObject(_name2,name2) && GetObject(_version2,version02)) { dependencies.push_back(std::pair(name2, version02)); } } } } if(GetObjectHeap(_tools,_toolList)) { for(int64_t i = 0; i < _toolList->Count(); i++) { TObject _dep = _toolList->Get(i); TDictionary* _depD; if(GetObjectHeap(_dep, _depD)) { TObject _name2 = _depD->GetValue("Name"); TObject _version2 = _depD->GetValue("Version"); std::string name2; std::string version2; TVMVersion version02; if(GetObject(_name2,name2) && GetObject(_version2,version2) && TVMVersion::TryParse(version2,version02)) { tools.push_back(std::pair(name2, version02)); } else if(GetObject(_name2,name2) && GetObject(_version2,version02)) { tools.push_back(std::pair(name2, version02)); } } } } if(GetObjectHeap(_sources,srcLst)) { for(int64_t i = 0; i < srcLst->Count(); i++) { TObject _src = srcLst->Get(i); TDictionary* _srcD; if(GetObjectHeap(_src, _srcD)) { TObject _sourceTxt = _srcD->GetValue("Source"); TObject _filename = _srcD->GetValue("FileName"); std::string srctxt = ""; std::string filename = "memory_" + std::to_string(i) + ".tcross"; bool fromFile = false; GetObject(_sourceTxt,srctxt); GetObject(_filename,filename); sources.push_back(std::pair(srctxt,filename)); } } } ls.GetGC()->BarrierEnd(); std::vector tokens; for(auto source : sources) { std::stringstream strm(source.first); int res = Lex(source.second, strm, tokens); if(res != 0) { return Failure(ls, "Lex error in file \"" + source.second + "\":" + std::to_string(res)); } } Parser parser(tokens); SyntaxNode n = parser.ParseRoot(); CodeGen gen; gen.GenRoot(n); gen.dependencies = dependencies; gen.tools = tools; gen.info = info; gen.name = name; gen.version = version; gen.icon = icon; std::string outpath; TStreamHeapObject* stream; if(GetObjectHeap(_out, stream)) { gen.Save(vfsHO != nullptr ? vfsHO->vfs : nullptr, stream->stream); } return Success(ls); } catch(std::exception& ex) { return Failure(ls, ex.what()); } } void TStd::RegisterVM(GC* gc,TRootEnvironment* env) { env->permissions.canRegisterVM=true; GCList ls(gc); TDictionary* dict = TDictionary::Create(ls); dict->DeclareFunction(gc, "getRootEnvironmentAsDictionary","Get root environment as a dictionary",{},[env](GCList& ls, std::vector args)-> TObject{ return env->GetDictionary(); }); dict->DeclareFunction(gc, "getRootEnvironment","Get root environment, for reflection purposes",{},[env](GCList& ls2,std::vector args)->TObject {return env;}); dict->DeclareFunction(gc, "getCurrentEnvironment","Get current environment, for reflection purposes",{},VM_getCurrentEnvironment); dict->DeclareFunction(gc, "CreateEnvironment","Create root environment",{"$dict"},[](GCList& ls,std::vector args)->TObject{ TDictionary* dict; if(GetArgumentHeap(args,0,dict)) { return TRootEnvironment::Create(ls,dict); } else { return TRootEnvironment::Create(ls,TDictionary::Create(ls)); } }); dict->DeclareFunction(gc, "LoadExecutable", "Load a crossvm executable",{"stream"},[](GCList& ls,std::vector args)->TObject{ TStreamHeapObject* strm; if(GetArgumentHeap(args,0,strm)) { TFile* f =TFile::Create(ls); f->Load(ls.GetGC(),strm->stream); return f; } return nullptr; }); dict->DeclareFunction(gc, "Eval", "Eval source code",{"source"}, VM_Eval); dict->DeclareFunction(gc, "Compile", "Compile Source",{"dict"},VM_Compile); dict->DeclareFunction(gc, "SourceToAst", "Convert source to ast", {"source"}, VM_SourceToAst); dict->DeclareFunction(gc, "getRuntimeVersion","Get the runtime version",{},[](GCList& ls,std::vector args)->TObject { return TVMVersion(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE); }); gc->BarrierBegin(); env->DeclareVariable("VM", dict); gc->BarrierEnd(); } }