diff --git a/README.md b/README.md index 8fc03d0..a0e6dd0 100644 --- a/README.md +++ b/README.md @@ -43,4 +43,3 @@ sudo make install ``` Ye are of God, little children, and have overcome them: because greater is he that is in you, than he that is in the world. (1 John 4:4) ``` - diff --git a/include/CrossLang.hpp b/include/CrossLang.hpp index d7020e9..80d12c2 100644 --- a/include/CrossLang.hpp +++ b/include/CrossLang.hpp @@ -480,6 +480,16 @@ class CharInstruction : public ByteCodeInstruction { using SyntaxNode = std::variant; +class ObjectEntry { + public: + std::vector name; + std::string doc; + std::vector> variables; + std::vector,uint32_t>> funcs; + std::vector,uint32_t>> static_funcs; + +}; + class CodeGen { uint32_t id; uint32_t NewId(); @@ -494,6 +504,7 @@ class CodeGen { std::vector res; std::vector, std::vector>> chunks; std::vector,uint32_t>> funcs; + std::vector objectEntries; void GenNode(std::vector& instructions, SyntaxNode n,int32_t scope, int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI); void GenPop(std::vector& instrs,SyntaxNode n); public: @@ -575,6 +586,11 @@ constexpr std::string_view EnumerableStatement = "enumerableStatement"; constexpr std::string_view SwitchStatement = "switchStatement"; constexpr std::string_view CaseStatement = "caseStatement"; constexpr std::string_view DefaultStatement = "defaultStatement"; +constexpr std::string_view ObjectStatement = "objectStatement"; +constexpr std::string_view StaticStatement = "staticStatement"; +constexpr std::string_view MethodDeclaration = "methodDeclaration"; + + class AdvancedSyntaxNode { public: std::string nodeName; @@ -659,7 +675,7 @@ class Parser { class MethodInvoker { }; -using TObject = std::variant; +using TObject = std::variant; class TRootEnvironment; class GC; class GC { diff --git a/src/compiler/codegen.cpp b/src/compiler/codegen.cpp index 5ed8c00..8769d3d 100644 --- a/src/compiler/codegen.cpp +++ b/src/compiler/codegen.cpp @@ -911,7 +911,7 @@ namespace Tesses::CrossLang contscope = old_contscope; brkscope = old_brkscope; } - else if(adv.nodeName == CommaExpression && adv.nodeName.size() == 2) + else if(adv.nodeName == CommaExpression && adv.nodes.size() == 2) { GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); GenPop(instructions,adv.nodes[0]); diff --git a/src/compiler/parser.cpp b/src/compiler/parser.cpp index b7b223b..fa98d5e 100644 --- a/src/compiler/parser.cpp +++ b/src/compiler/parser.cpp @@ -165,6 +165,14 @@ namespace Tesses::CrossLang node = AdvancedSyntaxNode::Create(GetVariableExpression, true,{"operator"+variable.text}); } + else if(IsIdentifier("new")) + { + if(i >= tokens.size()) throw std::out_of_range("End of file"); + auto variable = tokens[i]; + i++; + if(variable.type != LexTokenType::Identifier && variable.type != LexTokenType::Symbol) throw SyntaxException(variable.lineInfo, "Expected an identifier or a symbol got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); + node = AdvancedSyntaxNode::Create(GetFieldExpression, true, {AdvancedSyntaxNode::Create(GetVariableExpression,true,{"New"}), variable.text}); + } else if(IsIdentifier("embed")) { EnsureSymbol("("); @@ -339,6 +347,7 @@ namespace Tesses::CrossLang { return AdvancedSyntaxNode::Create(PrefixDecrementExpression,true,{ParseUnary()}); } + return ParseValue(); } @@ -557,6 +566,10 @@ namespace Tesses::CrossLang } return AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body}); } + if(IsIdentifier("object")) + { + //TODO: complete this + } if(IsIdentifier("enumerable")) { auto nameAndArgs = ParseExpression(); diff --git a/src/runtime_methods/std.cpp b/src/runtime_methods/std.cpp index b8a60d5..efd8ba1 100644 --- a/src/runtime_methods/std.cpp +++ b/src/runtime_methods/std.cpp @@ -118,6 +118,18 @@ namespace Tesses::CrossLang TVFSHeapObject* vfs; return GetArgumentHeap(args,0,vfs); } + static TObject New_Color(GCList& ls, std::vector args) + { + int64_t r,g,b,a; + if(GetArgument(args,0,r) && GetArgument(args,1,g) && GetArgument(args,2,b)) + { + if(!GetArgument(args,3,a)) { + a = 255; + } + return Tesses::Framework::Graphics::Color((uint8_t)r,(uint8_t)g,(uint8_t)b,(uint8_t)a); + } + return Tesses::Framework::Graphics::Colors::Black; + } static TObject TypeOf(GCList& ls, std::vector args) { if(args.size() < 1) return "Undefined"; @@ -329,8 +341,10 @@ namespace Tesses::CrossLang void TStd::RegisterRoot(GC* gc, TRootEnvironment* env) { - + GCList ls(gc); + env->permissions.canRegisterRoot=true; + TDictionary* newTypes = TDictionary::Create(ls); env->DeclareFunction(gc, "ParseLong","Parse Long from String",{"arg","$base"},ParseLong); env->DeclareFunction(gc, "ParseDouble","Parse Double from String",{"arg"},ParseDouble); env->DeclareFunction(gc, "YieldEmumerable","Turn yield in function into enumerable",{"closure"},YieldEnumerableFunc); @@ -414,8 +428,10 @@ namespace Tesses::CrossLang return Undefined(); }); env->DeclareFunction(gc,"ByteArray","Create bytearray, with optional either size (to size it) or string argument (to fill byte array)",{"$data"},ByteArray); + newTypes->DeclareFunction(gc,"Color","Create a new color",{"red","green","blue","$alpha"},New_Color); gc->BarrierBegin(); env->DeclareVariable("InvokeMethod",MethodInvoker()); + env->DeclareVariable("New", newTypes); gc->BarrierEnd(); } void TStd::RegisterStd(GC* gc, TRootEnvironment* env) diff --git a/src/runtime_methods/vm.cpp b/src/runtime_methods/vm.cpp index 17688af..44e8ffe 100644 --- a/src/runtime_methods/vm.cpp +++ b/src/runtime_methods/vm.cpp @@ -1,4 +1,3 @@ - #include "CrossLang.hpp" #include #include @@ -6,6 +5,79 @@ 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; @@ -201,7 +273,7 @@ namespace Tesses::CrossLang 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); gc->BarrierBegin(); env->DeclareVariable("VM", dict); diff --git a/src/vm/vm.cpp b/src/vm/vm.cpp index 0538bd2..2540cc4 100644 --- a/src/vm/vm.cpp +++ b/src/vm/vm.cpp @@ -158,10 +158,9 @@ namespace Tesses::CrossLang { } return true; } - else { - this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); - } + } + this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); return false; } bool InterperterThread::Sub(GC* gc)