From 5fbf26d4100fb8a34ae35bc5d80d7b4971496d68 Mon Sep 17 00:00:00 2001 From: Michael Nolan Date: Sun, 30 Jul 2023 02:55:10 -0500 Subject: [PATCH] VM works --- ByteCodeTest/ByteCodeTest.csproj | 4 + ByteCodeTest/Program.cs | 8 +- ByteCodeTest/app.tlang | 5 +- ByteCodeTest/app.tvm | Bin 54 -> 94 bytes ByteCodeTest/ast.json | 65 ++ TLang.BytecodeCompiler/Class1.cs | 38 +- TLang.Common/Instruction.cs | 1 + TLang.Common/TLangDependency.cs | 9 +- TLang.Lexer/Class1.cs | 25 +- TLang.Lexer/LexContext.cs | 1 + TLang.Parser/Class1.cs | 58 +- TLang.Parser/GetArrayNode.cs | 6 +- TLang.Parser/MethodCallNode.cs | 4 +- TLang.Parser/Node.cs | 1 + TLang.VM/.vscode/launch.json | 41 + TLang.VM/ChunkExecuter.cs | 1054 +++++++++++++++++++- TLang.VM/ClassEnvironment.cs | 21 +- TLang.VM/ClassField.cs | 10 + TLang.VM/ClassMethod.cs | 6 +- TLang.VM/DefaultDependencyPool.cs | 13 +- TLang.VM/RootEnvironment.cs | 126 ++- TLang.VM/SubEnvironment.cs | 2 +- TLang.VM/TArray.cs | 20 + TLang.VM/TBool.cs | 18 + TLang.VM/TCallable.cs | 3 + TLang.VM/TChar.cs | 18 + TLang.VM/TClassInstance.cs | 103 +- TLang.VM/TClosure.cs | 2 + TLang.VM/TDictionary.cs | 50 + TLang.VM/TExternalMethod.cs | 20 + TLang.VM/TNull.cs | 6 + TLang.VM/TNumber.cs | 6 + TLang.VM/TObject.cs | 4 +- TLang.VM/TString.cs | 22 + TLang.VM/TUndefined.cs | 6 + TLang.VM/TVMFile.cs | 7 + TLangScriptRunner/.vscode/launch.json | 26 + TLangScriptRunner/.vscode/tasks.json | 41 + TLangScriptRunner/Program.cs | 14 + TLangScriptRunner/TLangScriptRunner.csproj | 15 + TLangScriptRunner/dell.txt | 1 + TLangScriptRunner/fstest.tlang | 4 + TLangScriptRunner/mkdirtest.tlang | 0 TLangScriptRunner/test.tlang | 16 + TVMTest | Bin 0 -> 146 bytes VMTest/Program.cs | 9 +- VMTest/app.tvm | Bin 54 -> 94 bytes 47 files changed, 1823 insertions(+), 86 deletions(-) create mode 100644 ByteCodeTest/ast.json create mode 100644 TLang.VM/.vscode/launch.json create mode 100644 TLang.VM/ClassField.cs create mode 100644 TLang.VM/TArray.cs create mode 100644 TLang.VM/TBool.cs create mode 100644 TLang.VM/TChar.cs create mode 100644 TLang.VM/TDictionary.cs create mode 100644 TLang.VM/TExternalMethod.cs create mode 100644 TLangScriptRunner/.vscode/launch.json create mode 100644 TLangScriptRunner/.vscode/tasks.json create mode 100644 TLangScriptRunner/Program.cs create mode 100644 TLangScriptRunner/TLangScriptRunner.csproj create mode 100644 TLangScriptRunner/dell.txt create mode 100644 TLangScriptRunner/fstest.tlang create mode 100644 TLangScriptRunner/mkdirtest.tlang create mode 100644 TLangScriptRunner/test.tlang create mode 100644 TVMTest diff --git a/ByteCodeTest/ByteCodeTest.csproj b/ByteCodeTest/ByteCodeTest.csproj index 78c6818..1e5c1b9 100644 --- a/ByteCodeTest/ByteCodeTest.csproj +++ b/ByteCodeTest/ByteCodeTest.csproj @@ -4,6 +4,10 @@ + + + + Exe net7.0 diff --git a/ByteCodeTest/Program.cs b/ByteCodeTest/Program.cs index 70f4443..a5582a9 100644 --- a/ByteCodeTest/Program.cs +++ b/ByteCodeTest/Program.cs @@ -1,9 +1,15 @@ using TLang.BytecodeCompiler; using TLang.Common; using TLang.Parser; +using TLang.Lexer; +using Newtonsoft.Json; + +var ctx=Lex.GetTokensFromFile("app.tlang"); + +var res=Parse.ParseFromLexContext(ctx); +File.WriteAllText("ast.json",JsonConvert.SerializeObject(res,Formatting.Indented)); -var res=Parse.ParseFromFiles("app.tlang"); using(var f = File.Create("app.tvm")) { ByteCodeGenerator.GenerateToStream(res,f,new TLangVersion(1,0,0,0),new TLangVersion(1,0,0,0)); diff --git a/ByteCodeTest/app.tlang b/ByteCodeTest/app.tlang index e73eeae..360ba19 100644 --- a/ByteCodeTest/app.tlang +++ b/ByteCodeTest/app.tlang @@ -1 +1,4 @@ -37+5; \ No newline at end of file +if("Demi Lovato") +{ + print("Linus"); +} diff --git a/ByteCodeTest/app.tvm b/ByteCodeTest/app.tvm index 38178877dc690fa7400d8734c4cb9a1bb73cfcf9..b542a218da945c71a79e0b0e56f0a4fcec5f0da5 100644 GIT binary patch delta 65 zcmXquo1kQ4{fB{pf!ifDH&ekUzbvsNU*tVd!1@(Pn6;oNGp_{9^2y9AE&gl&0VoOt KZ(hFxlGXs4judAA delta 25 acmazuo1i2j{MW&$fdK^mI*5R21_l68z68Di diff --git a/ByteCodeTest/ast.json b/ByteCodeTest/ast.json new file mode 100644 index 0000000..8950f9e --- /dev/null +++ b/ByteCodeTest/ast.json @@ -0,0 +1,65 @@ +{ + "RootScope": true, + "IsSwitchScope": false, + "SwitchCondition": { + "LineInfo": null + }, + "Nodes": [ + { + "Condition": { + "Text": "Demi Lovato", + "LineInfo": { + "FileName": "memory.tlang", + "Line": 1, + "Column": 5, + "Position": 4 + } + }, + "Yes": { + "RootScope": false, + "IsSwitchScope": false, + "SwitchCondition": { + "LineInfo": null + }, + "Nodes": [ + { + "Arguments": [ + { + "Text": "Linus", + "LineInfo": { + "FileName": "memory.tlang", + "Line": 3, + "Column": 12, + "Position": 28 + } + } + ], + "Name": "print", + "LineInfo": { + "FileName": "memory.tlang", + "Line": 3, + "Column": 6, + "Position": 22 + } + } + ], + "LineInfo": { + "FileName": "memory.tlang", + "Line": 3, + "Column": 6, + "Position": 22 + } + }, + "No": { + "LineInfo": null + }, + "LineInfo": null + } + ], + "LineInfo": { + "FileName": "memory.tlang", + "Line": 1, + "Column": 2, + "Position": 1 + } +} \ No newline at end of file diff --git a/TLang.BytecodeCompiler/Class1.cs b/TLang.BytecodeCompiler/Class1.cs index 745d2e3..1f6079b 100644 --- a/TLang.BytecodeCompiler/Class1.cs +++ b/TLang.BytecodeCompiler/Class1.cs @@ -89,13 +89,14 @@ namespace TLang.BytecodeCompiler int closure = Chunks.Count; BytecodeChunk _chunk = new BytecodeChunk(); _chunk.Arguments = cValue.Arguments; - GenerateCode(cValue.Node,_chunk,0,0,-1,-1,false); Chunks.Add(_chunk); + GenerateCode(cValue.Node,_chunk,0,0,-1,-1,false); + WriteBigEndianInt(strm,closure); } else { - byte c = 0b00000100; + byte c = 0b00000000; if(classEntry.Modifier == "prot") {c |= 0b00000001;} if(classEntry.Modifier == "pub") {c |= 0b00000010;} @@ -105,9 +106,9 @@ namespace TLang.BytecodeCompiler strm.Write(bytes,0,bytes.Length); int closure = Chunks.Count; BytecodeChunk _chunk = new BytecodeChunk(); - - GenerateCode(new ReturnNode(classEntry.InitialValue),_chunk,0,0,-1,-1,false); Chunks.Add(_chunk); + GenerateCode(new ReturnNode(classEntry.InitialValue),_chunk,0,0,-1,-1,false); + WriteBigEndianInt(strm,closure); } } @@ -183,8 +184,20 @@ namespace TLang.BytecodeCompiler var getMemberNode = node as GetMemberNode; var getArrayValue = node as GetArrayNode; var setVariableNode = node as SetVariableNode; - - + var postFixIncrement = node as PostFixIncrementNode; + var postFixDecrement = node as PostFixDecrementNode; + if(postFixDecrement != null) + { + GenerateCode(postFixDecrement.SymbolNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); + SetVariableNode variableNode = new SetVariableNode(postFixDecrement.SymbolNode,new SubtractNode(postFixDecrement.SymbolNode,new ConstNumberNode(1))); + GenerateCode(variableNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); + } + if(postFixIncrement != null) + { + GenerateCode(postFixIncrement.SymbolNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); + SetVariableNode variableNode = new SetVariableNode(postFixIncrement.SymbolNode,new AddNode(postFixIncrement.SymbolNode,new ConstNumberNode(1))); + GenerateCode(variableNode,chunk,scopeIndex,scopeBreakIndex,_labelBeginningLoop,_labelEndLoop,isRoot); + } if(scNode != null) { if(scNode.IsSwitchScope) @@ -315,11 +328,11 @@ namespace TLang.BytecodeCompiler GenerateCode(variableNode1,chunk,scopeIndex+1,0,_labelBeginningLoop,_labelEndLoop,false); LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}"); chunk.Add(labelNode); - + GenerateCode(new NotNode(new MethodCallNode(variableNode,"movenext")),chunk,scopeBreakIndex+1,0,labelNum,labelNumEnd,false); JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}"); chunk.Add(conditional); - SetVariableNode variableNode2=new SetVariableNode(eachNode.Name,new NotNode(new MethodCallNode(variableNode,"movenext"))); + SetVariableNode variableNode2=new SetVariableNode(eachNode.Name,new GetMemberNode(variableNode,"current")); GenerateCode(variableNode2,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); GenerateCode(eachNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); @@ -336,15 +349,18 @@ namespace TLang.BytecodeCompiler chunk.Add(new SimpleInstruction(Instruction.SCOPE_BEGIN)); GenerateCode(forNode.Init,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); + LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}"); chunk.Add(labelNode); GenerateCode(new NotNode(forNode.Condition),chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); + //chunk.Add(new SimpleInstruction(Instruction.POP)); JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}"); chunk.Add(conditional); GenerateCode(forNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); GenerateCode(forNode.Increment,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false); + JumpUnconditional juC=new JumpUnconditional($"_label{labelNum}"); chunk.Add(juC); LabelInstruction endLabel = new LabelInstruction($"_label{labelNumEnd}"); @@ -403,9 +419,11 @@ namespace TLang.BytecodeCompiler { BytecodeChunk _chunk = new BytecodeChunk(); _chunk.Arguments = closureNode.Arguments; + int i = Chunks.Count; + + Chunks.Add(_chunk); GenerateCode(closureNode.Node,_chunk,0,0,-1,-1,false); - int i = Chunks.Count; - Chunks.Add(_chunk); + chunk.Add(new PushClosureNode(i)); } if(node is NullNode) diff --git a/TLang.Common/Instruction.cs b/TLang.Common/Instruction.cs index 081cdba..e9b9820 100644 --- a/TLang.Common/Instruction.cs +++ b/TLang.Common/Instruction.cs @@ -40,6 +40,7 @@ namespace TLang.Common public const byte GT = 0x17; public const byte GTE = 0x18; + public const byte POP = 0xE9; public const byte SCOPE_BEGIN = 0xEA; public const byte SCOPE_END = 0xEB; diff --git a/TLang.Common/TLangDependency.cs b/TLang.Common/TLangDependency.cs index 719baab..62bf1e0 100644 --- a/TLang.Common/TLangDependency.cs +++ b/TLang.Common/TLangDependency.cs @@ -1,6 +1,8 @@ +using System; + namespace TLang.Common { - public class TLangDependency + public class TLangDependency : IEquatable { public TLangDependency(string name,TLangVersion version) { @@ -13,5 +15,10 @@ namespace TLang.Common } public string Name {get;set;} public TLangVersion Version {get;set;} + + public bool Equals(TLangDependency other) + { + return Name == other.Name && Version.IntegerVersion == other.Version.IntegerVersion; + } } } \ No newline at end of file diff --git a/TLang.Lexer/Class1.cs b/TLang.Lexer/Class1.cs index 39f4162..ab40c28 100644 --- a/TLang.Lexer/Class1.cs +++ b/TLang.Lexer/Class1.cs @@ -64,10 +64,7 @@ namespace TLang.Lexer if(interoplated) { - tokens.Add(LexToken.Token("String").WithLineInfo(lineInfo)); - tokens.Add(LexToken.Token(".").WithLineInfo(lineInfo)); - tokens.Add(LexToken.Token("Concat").WithLineInfo(lineInfo)); - tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); + int e = 0; int escapeI = 0; @@ -80,7 +77,7 @@ namespace TLang.Lexer { if(b2.Length > 0 && escapeI < 1) { - if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + if(e > 0) tokens.Add(LexToken.Token("+").WithLineInfo(lineInfo)); tokens.Add(LexToken.String(b2.ToString()).WithLineInfo(lineInfo)); b2.Clear(); e++; @@ -104,12 +101,17 @@ namespace TLang.Lexer escapeI--; if(b2.Length > 0 && escapeI == 0) { - if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + if(e > 0) tokens.Add(LexToken.Token("+").WithLineInfo(lineInfo)); tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); tokens.AddRange(Lex.GetTokensFromString(b2.ToString(),"compilerGenerated.tlang").Tokens); tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token(".").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token("toString").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + b2.Clear(); e++; } @@ -128,18 +130,23 @@ namespace TLang.Lexer { if(escapeI > 0) { - if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + if(e > 0) tokens.Add(LexToken.Token("+").WithLineInfo(lineInfo)); tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); tokens.AddRange(Lex.GetTokensFromString(b2.ToString(),"compilerGenerated.tlang").Tokens); tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token(".").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token("toString").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo)); + tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + b2.Clear(); e++; } else { - if(e > 0) tokens.Add(LexToken.Token(",").WithLineInfo(lineInfo)); + if(e > 0) tokens.Add(LexToken.Token("+").WithLineInfo(lineInfo)); tokens.Add(LexToken.String(b2.ToString()).WithLineInfo(lineInfo)); b2.Clear(); e++; @@ -147,7 +154,7 @@ namespace TLang.Lexer } - tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo)); + } else diff --git a/TLang.Lexer/LexContext.cs b/TLang.Lexer/LexContext.cs index d545f63..b578d2f 100644 --- a/TLang.Lexer/LexContext.cs +++ b/TLang.Lexer/LexContext.cs @@ -50,6 +50,7 @@ namespace TLang.Lexer } if(consumeIfTrue) Offset += tokenText.Length; return new LexEntryContext(tokens,offset,true); + } public LexEntryContext NextEntries(bool consumeIfTrue,params string[] tokenText) diff --git a/TLang.Parser/Class1.cs b/TLang.Parser/Class1.cs index 3870adb..f086cea 100644 --- a/TLang.Parser/Class1.cs +++ b/TLang.Parser/Class1.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using TLang.Lexer; namespace TLang.Parser { @@ -338,18 +339,63 @@ return res; } return expr; } - + + private Node ParseValue() { var doc = Context.PopDocumentation(); var token = Context.NextEntry(); if(token.IsString) return new StringNode(token.Text){LineInfo = token.Position}; if(token.IsChar) return new CharNode(token.Text){LineInfo = token.Position}; + if(token.Text == "ensure") + { + string t = Context.NextEntry().Text; + + IfNode node = new IfNode(new NotNode(new GetVariableNode(t)),new SetVariableNode(new GetVariableNode(t),new FunctionCallNode("dictionary")),new Node()); + return node; + } if(token.Text == "(") { var assignable = ParseAssigable(); assignable.LineInfo = token.Position; if(!Context.NextEntries(true,")").Success) throw new CompilerError("symbol must be a ')'",assignable); + while(Context.MoreTokens && Context.NextEntries(true,"[").Success) + { + var p = ParseNode(); + assignable = new GetArrayNode(assignable,p){LineInfo = p.LineInfo}; + Context.NextEntries(true,"]"); + } + while(Context.MoreTokens && Context.NextEntries(true,".").Success) + { + var token2 = Context.NextEntry(); + + if(Context.MoreTokens && Context.NextEntries(true,"(").Success) + { + var mCall = new MethodCallNode(assignable,token2.Text){LineInfo=token2.Position}; + assignable = mCall; + while(Context.MoreTokens && !Context.NextEntries(true,")").Success) + { + if(Context.NextEntries(true,",").Success) continue; + mCall.Arguments.Add(ParseNode()); + } + } + else if(Context.MoreTokens && Context.NextEntries(false,"[").Success) + { + assignable = new GetMemberNode(assignable,token2.Text); + while(Context.MoreTokens && Context.NextEntries(true,"[").Success) + { + var p = ParseNode(); + assignable = new GetArrayNode(assignable,p){LineInfo = p.LineInfo}; + Context.NextEntries(true,"]"); + } + } + else + { + assignable = new GetMemberNode(assignable,token2.Text){LineInfo = token2.Position}; + } + + } + return assignable; } if(token.Text == "class") @@ -606,6 +652,7 @@ return res; } else if(Context.MoreTokens && Context.NextEntries(false,"[").Success) { + ret = new GetMemberNode(ret,token2.Text); while(Context.MoreTokens && Context.NextEntries(true,"[").Success) { var p = ParseNode(); @@ -616,9 +663,11 @@ return res; else { ret = new GetMemberNode(ret,token2.Text){LineInfo = token2.Position}; + } } + if(Context.MoreTokens && Context.NextEntries(true,"++").Success) { var r = new PostFixIncrementNode(ret){LineInfo = ret.LineInfo}; @@ -682,7 +731,7 @@ return res; ret = new GetArrayNode(ret,p){LineInfo = p.LineInfo}; Context.NextEntries(true,"]"); } - while(Context.MoreTokens && Context.NextEntries(true,".").Success) + while(Context.MoreTokens && Context.NextEntries(true,".").Success) { var token2 = Context.NextEntry(); @@ -696,8 +745,10 @@ return res; mCall.Arguments.Add(ParseNode()); } } - else if(Context.MoreTokens && Context.NextEntries(false,"[").Success) + else + if(Context.MoreTokens && Context.NextEntries(false,"[").Success) { + ret =new GetMemberNode(ret,token2.Text); while(Context.MoreTokens && Context.NextEntries(true,"[").Success) { var p = ParseNode(); @@ -708,6 +759,7 @@ return res; else { ret = new GetMemberNode(ret,token2.Text){LineInfo = token2.Position}; + } } diff --git a/TLang.Parser/GetArrayNode.cs b/TLang.Parser/GetArrayNode.cs index c558f83..a2d9c95 100644 --- a/TLang.Parser/GetArrayNode.cs +++ b/TLang.Parser/GetArrayNode.cs @@ -2,13 +2,13 @@ namespace TLang.Parser { public class GetArrayNode : SymbolNode { - public SymbolNode Symbol {get;set;} + public Node Symbol {get;set;} public Node Expression {get;set;} - public GetArrayNode(SymbolNode sym, Node expr) + public GetArrayNode(Node sym, Node expr) { Symbol = sym; - this.Name = sym.Name; + this.Name = ""; Expression = expr; } } diff --git a/TLang.Parser/MethodCallNode.cs b/TLang.Parser/MethodCallNode.cs index a689c47..e911eb1 100644 --- a/TLang.Parser/MethodCallNode.cs +++ b/TLang.Parser/MethodCallNode.cs @@ -5,10 +5,10 @@ namespace TLang.Parser { public class MethodCallNode : SymbolNode { - public SymbolNode Symbol {get;set;} + public Node Symbol {get;set;} public List Arguments {get;set;}=new List(); - public MethodCallNode(SymbolNode symbol, string name) + public MethodCallNode(Node symbol, string name) { Symbol = symbol; Name = name; diff --git a/TLang.Parser/Node.cs b/TLang.Parser/Node.cs index 509ad7f..fb08b86 100644 --- a/TLang.Parser/Node.cs +++ b/TLang.Parser/Node.cs @@ -6,5 +6,6 @@ namespace TLang.Parser { public LexLineInfo LineInfo {get;set;} + } } \ No newline at end of file diff --git a/TLang.VM/.vscode/launch.json b/TLang.VM/.vscode/launch.json new file mode 100644 index 0000000..d9bf930 --- /dev/null +++ b/TLang.VM/.vscode/launch.json @@ -0,0 +1,41 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "WARNING01": "*********************************************************************************", + "WARNING02": "The C# extension was unable to automatically decode projects in the current", + "WARNING03": "workspace to create a runnable launch.json file. A template launch.json file has", + "WARNING04": "been created as a placeholder.", + "WARNING05": "", + "WARNING06": "If OmniSharp is currently unable to load your project, you can attempt to resolve", + "WARNING07": "this by restoring any missing project dependencies (example: run 'dotnet restore')", + "WARNING08": "and by fixing any reported errors from building the projects in your workspace.", + "WARNING09": "If this allows OmniSharp to now load your project then --", + "WARNING10": " * Delete this file", + "WARNING11": " * Open the Visual Studio Code command palette (View->Command Palette)", + "WARNING12": " * run the command: '.NET: Generate Assets for Build and Debug'.", + "WARNING13": "", + "WARNING14": "If your project requires a more complex launch configuration, you may wish to delete", + "WARNING15": "this configuration and pick a different template using the 'Add Configuration...'", + "WARNING16": "button at the bottom of this file.", + "WARNING17": "*********************************************************************************", + "preLaunchTask": "build", + "program": "${workspaceFolder}/../VMTest/bin/Debug/net7.0/VMTest.dll", + "args": [], + "cwd": "${workspaceFolder}/../VMTest/", + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/TLang.VM/ChunkExecuter.cs b/TLang.VM/ChunkExecuter.cs index b86d7fd..7c5d3f4 100644 --- a/TLang.VM/ChunkExecuter.cs +++ b/TLang.VM/ChunkExecuter.cs @@ -11,7 +11,7 @@ namespace TLang.VM { File =file; Chunk = chunk; - Environment = env; + Environment = env.GetSubEnvironment(); } public TLangEnvironment Environment {get;set;} public TVMFile File {get;} @@ -20,15 +20,16 @@ namespace TLang.VM public int IP {get;set;}=0; public Stack Stack {get;}=new Stack(); + public TObject Execute(params TObject[] args) { - var env=Environment.GetSubEnvironment(); + for(int i = 0;i< args.Length;i++) { if(i= File.Chunks.Count) throw new IndexOutOfRangeException($"No chunk with id {closureId}"); - Stack.Push(new TClosure(File,File.Chunks[closureId],env)); + Stack.Push(new TClosure(File,File.Chunks[closureId],Environment){ClassName = ClassName}); break; case Instruction.PUSH_STRING: Stack.Push(new TString(ReadString())); @@ -74,25 +122,76 @@ namespace TLang.VM case Instruction.PUSH_VARIABLE_VALUE: { var res=EnsurePop(); - Stack.Push(env.GetObject(res.Value)); + Stack.Push(Environment.GetObject(res.Value)); + } + break; + case Instruction.PUSH_FIELD_VALUE: + { + var res= EnsurePop(); + var symbol = Stack.Pop(); + Stack.Push(GetFieldValue(symbol,res.Value)); + } + break; + case Instruction.POP_FIELD_VALUE: + { + var val = Stack.Pop(); + var res= EnsurePop(); + var symbol = Stack.Pop(); + SetFieldValue(symbol, res.Value, val); } break; case Instruction.POP_VARIABLE_VALUE: { + + var val = Stack.Pop(); var res=EnsurePop(); - env.SetObject(res.Value,Stack.Pop()); + Environment.SetObject(res.Value,val); } break; + case Instruction.NOP: + break; + case Instruction.PUSH_CHAR: + Stack.Push(new TChar((char)Chunk.Code[IP++])); + break; + case Instruction.PUSH_ARRAY_VALUE: + { + var expr = Stack.Pop(); + var symbol = Stack.Pop(); + Stack.Push(GetArrayValue(symbol,expr)); + } + break; + case Instruction.POP_ARRAY_VALUE: + { + var val = Stack.Pop(); + var expr = Stack.Pop(); + var symbol = Stack.Pop(); + SetArrayValue(symbol,expr,val); + } + break; + case Instruction.PUSH_UNDEFINED: + Stack.Push(new TUndefined()); + break; + case Instruction.PUSH_NULL: + Stack.Push(new TNull()); + break; + case Instruction.PUSH_TRUE: + Stack.Push(new TBool(true)); + break; + case Instruction.PUSH_FALSE: + Stack.Push(new TBool(false)); + break; + + case Instruction.CALL_FUNC: { var argC = (int)EnsurePop().Value; TObject[] argV = new TObject[argC]; for(int i = argC;i>0;i--) { - argV[i] = Stack.Pop(); + argV[i-1] = Stack.Pop(); } var name = EnsurePop(); - var callable=env.GetObject(name.Value) as TCallable; + var callable=Environment.GetObject(name.Value) as TCallable; if(callable != null) { Stack.Push(callable.Execute(argV)); @@ -107,7 +206,7 @@ namespace TLang.VM TObject[] argV = new TObject[argC]; for(int i = argC;i>0;i--) { - argV[i] = Stack.Pop(); + argV[i-1] = Stack.Pop(); } var name = EnsurePop(); var symbol = Stack.Pop(); @@ -115,16 +214,436 @@ namespace TLang.VM Stack.Push(ExecuteMethod(symbol,name.Value,argV)); } break; + case Instruction.JMP: + IP=ReadInt(); + break; + case Instruction.JMPC: + { + int jmpPos = ReadInt(); + if(Stack.Pop().True) + IP = jmpPos; + } + break; + case Instruction.LNOT: + { + var res=Stack.Pop(); + Stack.Push(LNot(res)); + } + break; + case Instruction.POP: + Stack.Pop(); + break; + } } if(Stack.Count > 0) return Stack.Pop(); return new TNull(); } + private TObject SetArrayValue(TObject symbol,TObject expr,TObject value) + { + var classMethod = symbol as TClassInstance; + var dict = symbol as TDictionary; + var array = symbol as TArray; + + if(array != null) + { + var index = expr as TNumber; + if(index != null && ((int)index.Value) < array.Items.Count) + { + array.Items[(int)index.Value] = value; + return new TUndefined(); + } + } + if(classMethod != null) + { + if(classMethod.MethodExists(ClassName,"iset")) + { + return classMethod.CallMethod(ClassName,"iset",expr,value); + + } + var index = expr as TString; + if(index != null) + { + classMethod.SetField(ClassName,index.Value,value); + return new TUndefined(); + } + } + if(dict != null) + { + if(dict.HasValue("iset")) + { + var iget = dict.GetValue("iset") as TCallable; + if(iget != null) + { + return iget.Execute(expr,value); + + } + var index = expr as TString; + if(index != null) + dict.SetValue(index.Value,value); + } + } + return new TUndefined(); + } + private TObject GetArrayValue(TObject symbol, TObject expr) + { + var classMethod = symbol as TClassInstance; + var dict = symbol as TDictionary; + var str = symbol as TString; + var array = symbol as TArray; + + if(str != null) + { + var index = expr as TNumber; + if(index != null && ((int)index.Value) < str.Value.Length) + { + return new TChar(str.Value[(int)index.Value]); + } + } + if(array != null) + { + var index = expr as TNumber; + if(index != null && ((int)index.Value) < array.Items.Count) + { + return array.Items[(int)index.Value]; + } + } + if(classMethod != null) + { + if(classMethod.MethodExists(ClassName,"iget")) + { + return classMethod.CallMethod(ClassName,"iget",expr); + } + var index = expr as TString; + if(index != null) + { + return classMethod.GetField(ClassName,index.Value); + } + } + if(dict != null) + { + if(dict.HasValue("iget")) + { + var iget = dict.GetValue("iget") as TCallable; + if(iget != null) + { + return iget.Execute(expr); + } + var index = expr as TString; + if(index != null) + return dict.GetValue(index.Value); + } + } + return new TUndefined(); + } + + private TObject LNot(TObject res) + { + var classMethod = res as TClassInstance; + var dict = res as TDictionary; + + if(classMethod != null) + { + return classMethod.CallMethod(ClassName,"lnot",res); + } + if(dict != null) + { + var callable= dict.GetValue("lnot") as TCallable; + if(callable != null) + { + return callable.Execute(res); + } + } + return new TBool(!res.True); + } + + private TObject Negative(TObject object1) + { + var left = object1 as TNumber; + + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null) + { + return new TNumber(-(left.Value)); + } + + if(lcls != null && lcls.MethodExists(ClassName,"neg")) + { + return lcls.CallMethod(ClassName,"neg"); + } + if(ldict != null) + { + var callable =ldict.GetValue("neg") as TCallable; + if(callable != null) return callable.Execute(); + } + return new TNumber(0); + } + + private TObject BNot(TObject object1) + { + var left = object1 as TNumber; + + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null) + { + return new TNumber(~((long)left.Value)); + } + + if(lcls != null && lcls.MethodExists(ClassName,"band")) + { + return lcls.CallMethod(ClassName,"bnot"); + } + if(ldict != null) + { + var callable =ldict.GetValue("bnot") as TCallable; + if(callable != null) return callable.Execute(); + } + return new TNumber(0); + } + + private TObject GetFieldValue(TObject symbol, string name) + { + var classField = symbol as TClassInstance; + var dict = symbol as TDictionary; + var tArray = symbol as TArray; + var tString = symbol as TString; + if(tArray != null) + { + if(name == "count") + { + return new TNumber(tArray.Items.Count); + } + if(name == "empty") + { + return new TBool(!tArray.True); + } + if(name == "ittr") + { + return TDictionary.FromIEnumerator(tArray.Items.GetEnumerator()); + } + } + if(tString != null) + { + if(name == "count") + { + return new TNumber(tString.Value.Length); + } + if(name == "empty") + { + return new TBool(tString.Value.Length == 0); + } + if(name == "ittr") + { + return TDictionary.FromIEnumerator(tString.GetObjects().GetEnumerator()); + } + } + + if(classField != null) + { + if(classField.MethodExists(ClassName,$"get{name}")) + { + return classField.CallMethod(ClassName,$"get{name}"); + } + return classField.GetField(ClassName,name); + } + if(dict != null) + { + var callable= dict.GetValue($"get{name}") as TCallable; + if(callable != null) + { + return callable.Execute(); + } + else + { + return dict.GetValue(name); + } + } + + return new TUndefined(); + } + + public void SetFieldValue(TObject symbol, string name,TObject newValue) + { + var classField = symbol as TClassInstance; + var dict = symbol as TDictionary; + if(classField != null) + { + if(classField.MethodExists(ClassName,$"set{name}")) + { + classField.CallMethod(ClassName,$"set{name}",newValue); + } + else + { + classField.SetField(ClassName,name,newValue); + } + } + if(dict != null) + { + var callable= dict.GetValue($"set{name}") as TCallable; + if(callable != null) + { + callable.Execute(newValue); + } + else + { + dict.SetValue(name,newValue); + } + } + } private TObject ExecuteMethod(TObject symbol, string name, params TObject[] argV) { + + if(name == "toString" && argV.Length == 0) return new TString(symbol.ToString()); + + var classMethod = symbol as TClassInstance; + var number = symbol as TNumber; + var dict = symbol as TDictionary; + var tArray = symbol as TArray; + var tString = symbol as TString; + + if(tString != null) + { + if(name == "count") + { + return new TNumber(tString.Value.Length); + } + if(name == "empty") + { + return new TBool(tString.Value.Length == 0); + } + var strP=Environment.GetObject("String") as TDictionary; + if(strP != null) + { + var func = strP.GetValue(name) as TCallable; + if(func != null) + { + List arguments = new List(); + arguments.Add(symbol); + arguments.AddRange(argV); + return func.Execute(arguments.ToArray()); + } + } + } + + if(classMethod != null) + { + return classMethod.CallMethod(ClassName,name,argV); + } + if(dict != null) + { + var callable= dict.GetValue(name) as TCallable; + if(callable != null) + { + return callable.Execute(argV); + } + } + if(tArray != null) + { + if(name == "add") + { + if(argV.Length > 0) + { + tArray.Add(argV[0]); + } + return tArray; + } + if(name == "remove") + { + if(argV.Length > 0) + { + tArray.Remove(argV[0]); + } + return tArray; + } + if(name == "removeat") + { + if(argV.Length > 0) + { + var num = argV[0] as TNumber; + if(num != null) + { + tArray.Items.RemoveAt((int)num.Value); + } + } + return tArray; + } + if(name == "clear") + { + tArray.Items.Clear(); + return tArray; + } + if(name == "count") + { + return new TNumber(tArray.Items.Count); + } + if(name == "empty") + { + return new TBool(!tArray.True); + } + + var strP=Environment.GetObject("Array") as TDictionary; + if(strP != null) + { + var func = strP.GetValue(name) as TCallable; + if(func != null) + { + List arguments = new List(); + arguments.Add(symbol); + arguments.AddRange(argV); + return func.Execute(arguments.ToArray()); + } + } + } + if(number != null) + { + if(name == "floor") + { + return new TNumber(Math.Floor(number.Value)); + } + if(name == "ceil") + { + return new TNumber(Math.Ceiling(number.Value)); + } + if(name == "round") + { + if(argV.Length > 0) + { + var n = argV[0] as TNumber; + if(n !=null) + return new TNumber(Math.Round(number.Value,(int)n.Value)); + } + return new TNumber(Math.Round(number.Value)); + } + + if(name == "toChar") + { + return new TChar((char)(int)number.Value); + } + var strP=Environment.GetObject("Number") as TDictionary; + if(strP != null) + { + var func = strP.GetValue(name) as TCallable; + if(func != null) + { + List arguments = new List(); + arguments.Add(symbol); + arguments.AddRange(argV); + return func.Execute(arguments.ToArray()); + } + } + return new TNull(); + } + + return new TUndefined(); } private T EnsurePop() where T : TObject @@ -136,7 +655,7 @@ namespace TLang.VM private double ReadDouble() { - if(IP + 8 < Chunk.Code.Length) + if(IP + 8 <= Chunk.Code.Length) { byte[] data =new byte[8]; Array.Copy(Chunk.Code,IP,data,0,8); @@ -148,7 +667,7 @@ namespace TLang.VM } private int ReadInt() { - if(IP + 4 < Chunk.Code.Length) + if(IP + 4 <= Chunk.Code.Length) { byte[] data =new byte[4]; Array.Copy(Chunk.Code,IP,data,0,4); @@ -161,7 +680,7 @@ namespace TLang.VM private string ReadString() { int strLen = ReadInt(); - if(IP + strLen < Chunk.Code.Length) + if(IP + strLen <= Chunk.Code.Length) { var str=System.Text.Encoding.UTF8.GetString(Chunk.Code,IP,strLen); IP += strLen; @@ -169,32 +688,503 @@ namespace TLang.VM } throw new Exception("Malformed binary"); } + private TObject BAnd(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TNumber((long)left.Value & (long)right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"band")) + { + return lcls.CallMethod(ClassName,"band",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("band") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } + private TObject BOr(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TNumber((long)left.Value | (long)right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"bor")) + { + return lcls.CallMethod(ClassName,"bor",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("bor") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } + private TObject NEq(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + var lChr = object1 as TChar; + var rChr = object2 as TChar; + + var lBool = object1 as TBool; + var rBool = object2 as TBool; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TBool(left.Value != right.Value); + } + if(lStr != null && rStr != null) + { + return new TBool(lStr.Value != lStr.Value); + } + if(lChr != null && rChr != null) + { + return new TBool(lChr.Value != lChr.Value); + } + if(lBool != null && rBool != null) + { + return new TBool(lBool.Value != lBool.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"neq")) + { + return lcls.CallMethod(ClassName,"neq",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("neq") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TBool(object1 != object2); + } + private TObject Eq(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + var lChr = object1 as TChar; + var rChr = object2 as TChar; + + var lBool = object1 as TBool; + var rBool = object2 as TBool; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TBool(left.Value == right.Value); + } + if(lStr != null && rStr != null) + { + return new TBool(lStr.Value == lStr.Value); + } + if(lChr != null && rChr != null) + { + return new TBool(lChr.Value == lChr.Value); + } + if(lBool != null && rBool != null) + { + return new TBool(lBool.Value == lBool.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"eq")) + { + return lcls.CallMethod(ClassName,"eq",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("eq") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TBool(object1 == object2); + } + private TObject RShift(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TNumber((long)left.Value >> (int)right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"rs")) + { + return lcls.CallMethod(ClassName,"rs",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("rs") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } + private TObject LShift(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TNumber((long)left.Value << (int)right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"ls")) + { + return lcls.CallMethod(ClassName,"ls",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("ls") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } + private TObject XOr(TObject object2, TObject object1) + { + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + + + if(lcls != null && lcls.MethodExists(ClassName,"lte")) + { + return lcls.CallMethod(ClassName,"lte",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("lte") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TBool(object1.True ^ object2.True); + } + private TObject LOr(TObject object2, TObject object1) + { + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + + + if(lcls != null && lcls.MethodExists(ClassName,"lor")) + { + return lcls.CallMethod(ClassName,"lor",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("lor") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TBool(object1.True || object2.True); + } + private TObject LAnd(TObject object2, TObject object1) + { + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(lcls != null && lcls.MethodExists(ClassName,"land")) + { + return lcls.CallMethod(ClassName,"land",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("land") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TBool(object1.True && object2.True); + } + private TObject Pow(TObject object1, TObject object2) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + + + if(left != null && right != null) + { + return new TNumber(Math.Pow(left.Value,right.Value)); + } + + if(lcls != null && lcls.MethodExists(ClassName,"pow")) + { + return lcls.CallMethod(ClassName,"pow",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("pow") as TCallable; + if(callable != null) return callable.Execute(object2); + } + + return new TNumber(0); + } + + private TObject Mod(TObject object1, TObject object2) { - throw new NotImplementedException(); + var left = object1 as TNumber; + var right = object2 as TNumber; + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + + + if(left != null && right != null) + { + return new TNumber(left.Value % right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"mod")) + { + return lcls.CallMethod(ClassName,"mod",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("mod") as TCallable; + if(callable != null) return callable.Execute(object2); + } + + return new TNumber(0); } private TObject Divide(TObject object1, TObject object2) { - throw new NotImplementedException(); + var left = object1 as TNumber; + var right = object2 as TNumber; + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + + + if(left != null && right != null) + { + return new TNumber(left.Value / right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"div")) + { + return lcls.CallMethod(ClassName,"div",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("div") as TCallable; + if(callable != null) return callable.Execute(object2); + } + + return new TNumber(0); } private TObject Times(TObject object1, TObject object2) { - throw new NotImplementedException(); + var left = object1 as TNumber; + var right = object2 as TNumber; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + + + if(left != null && right != null) + { + return new TNumber(left.Value + right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"times")) + { + return lcls.CallMethod(ClassName,"times",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("times") as TCallable; + if(callable != null) return callable.Execute(object2); + } + + return new TNumber(0); } private TObject Sub(TObject object2, TObject object1) { - throw new NotImplementedException(); - } + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + var lArray = object1 as TArray; + + if(left != null && right != null) + { + return new TNumber(left.Value - right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"sub")) + { + return lcls.CallMethod(ClassName,"sub",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("sub") as TCallable; + if(callable != null) return callable.Execute(object2); + } + if(lArray != null) + { + lArray.Remove(object2); + return lArray; + } + return new TNumber(0); + } + private TObject GTE(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TBool(left.Value >= right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"gte")) + { + return lcls.CallMethod(ClassName,"gte",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("gte") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } + private TObject GT(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TBool(left.Value > right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"gt")) + { + return lcls.CallMethod(ClassName,"gt",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("gt") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } + private TObject LTE(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TBool(left.Value <= right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"lte")) + { + return lcls.CallMethod(ClassName,"lte",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("lte") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } + + private TObject LT(TObject object2, TObject object1) + { + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + if(left != null && right != null) + { + return new TBool(left.Value < right.Value); + } + + if(lcls != null && lcls.MethodExists(ClassName,"lt")) + { + return lcls.CallMethod(ClassName,"lt",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("lt") as TCallable; + if(callable != null) return callable.Execute(object2); + } + return new TNumber(0); + } private TObject Add(TObject object2, TObject object1) { - var left = object2 as TNumber; - var right = object1 as TNumber; - var lStr = object2 as TString; - var rStr = object1 as TString; + var left = object1 as TNumber; + var right = object2 as TNumber; + var lStr = object1 as TString; + var rStr = object2 as TString; + + var lcls = object1 as TClassInstance; + var ldict = object1 as TDictionary; + + var lArray = object1 as TArray; + if(left != null && right != null) { return new TNumber(left.Value + right.Value); @@ -203,6 +1193,20 @@ namespace TLang.VM { return new TString(lStr.Value + rStr.Value); } + if(lcls != null && lcls.MethodExists(ClassName,"add")) + { + return lcls.CallMethod(ClassName,"add",object2); + } + if(ldict != null) + { + var callable =ldict.GetValue("add") as TCallable; + if(callable != null) return callable.Execute(object2); + } + if(lArray != null) + { + lArray.Add(object2); + return lArray; + } return new TNumber(0); } } diff --git a/TLang.VM/ClassEnvironment.cs b/TLang.VM/ClassEnvironment.cs index fba324d..65a3eba 100644 --- a/TLang.VM/ClassEnvironment.cs +++ b/TLang.VM/ClassEnvironment.cs @@ -13,37 +13,44 @@ namespace TLang.VM public override TObject GetObject(string key) { - throw new System.NotImplementedException(); + if(key == "this") + { + return classInstance; + } + return oGenv.GetObject(key); } public override TLangEnvironment GetParentEnvironment() { - throw new System.NotImplementedException(); + return oGenv; } public override RootEnvironment GetRootEnvironment() { - throw new System.NotImplementedException(); + return oGenv.GetRootEnvironment(); } public override TLangEnvironment GetSubEnvironment() { - throw new System.NotImplementedException(); + return new SubEnvironment(this); } public override bool HasObject(string key) { - throw new System.NotImplementedException(); + if(key == "this") return true; + return oGenv.HasObject(key); } public override bool HasObjectRecurse(string key) { - throw new System.NotImplementedException(); + if(key == "this") return true; + return oGenv.HasObjectRecurse(key); } public override void SetObject(string key, TObject value) { - throw new System.NotImplementedException(); + if(key == "this") return; + oGenv.SetObject(key,value); } } } \ No newline at end of file diff --git a/TLang.VM/ClassField.cs b/TLang.VM/ClassField.cs new file mode 100644 index 0000000..1024aa7 --- /dev/null +++ b/TLang.VM/ClassField.cs @@ -0,0 +1,10 @@ +namespace TLang.VM +{ + public class ClassField + { + public bool Protected {get;set;} + public bool Private {get;set;} + public string ClassName {get;set;} + public TObject Value {get;set;} + } +} \ No newline at end of file diff --git a/TLang.VM/ClassMethod.cs b/TLang.VM/ClassMethod.cs index f757777..01d3626 100644 --- a/TLang.VM/ClassMethod.cs +++ b/TLang.VM/ClassMethod.cs @@ -2,14 +2,12 @@ namespace TLang.VM { public class ClassMethod { - public bool Public {get;set;} + public string ClassName {get;set;} public bool Private {get;set;} public bool Protected {get;set;} - public Chunk Chunk {get;set;} - - public TVMFile File {get;set;} + public TCallable Closure {get;set;} } } \ No newline at end of file diff --git a/TLang.VM/DefaultDependencyPool.cs b/TLang.VM/DefaultDependencyPool.cs index 45d7132..a795f51 100644 --- a/TLang.VM/DefaultDependencyPool.cs +++ b/TLang.VM/DefaultDependencyPool.cs @@ -1,6 +1,7 @@ using System.Collections; using System.Collections.Generic; using System.IO; +using System.Linq; using TLang.Common; namespace TLang.VM @@ -8,14 +9,14 @@ namespace TLang.VM public class DefaultDependencyPool : IDependencyPool { List<(TLangDependency Dependency,TVMFile File)> items = new List<(TLangDependency Dependency, TVMFile File)>(); - public bool AddDependency(TLangDependency dependency) + public bool AddDependency(TLangDependency dependency,RootEnvironment env) { string fileName = $"{dependency.Name}-{dependency.Version}.tvm"; if(File.Exists(fileName)) { using(var f = File.OpenRead(fileName)) { - TVMFile file = new TVMFile(f); + TVMFile file = new TVMFile(f,env); items.Add((dependency,file)); return file.LoadDependencies(this); } @@ -34,17 +35,19 @@ namespace TLang.VM public bool DependencyExists(TLangDependency dependency) { - throw new System.NotImplementedException(); + return items.Any(e=> + e.Dependency.Equals(dependency) + ); } public IEnumerator<(TLangDependency Dependency, TVMFile File)> GetEnumerator() { - throw new System.NotImplementedException(); + return items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - throw new System.NotImplementedException(); + return this.GetEnumerator(); } } } \ No newline at end of file diff --git a/TLang.VM/RootEnvironment.cs b/TLang.VM/RootEnvironment.cs index 046b3fe..ab1c79b 100644 --- a/TLang.VM/RootEnvironment.cs +++ b/TLang.VM/RootEnvironment.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; namespace TLang.VM { @@ -7,7 +8,7 @@ namespace TLang.VM { public RootEnvironment() { - + } public Dictionary AvailableClasses {get;set;}=new Dictionary(); @@ -48,5 +49,128 @@ namespace TLang.VM { return new SubEnvironment(this); } + + public void LoadStd() + { + + SetObject("array",new TExternalMethod((e)=>{ + TArray array=new TArray(); + if(e.Length > 0) + { + var n = e[0] as TNumber; + if(n != null) array.Items=new List((int)n.Value); + } + return array; + })); + SetObject("arrayof",new TExternalMethod((e)=>{ + TArray array=new TArray(); + foreach(var item in e) array.Add(item); + return array; + })); + SetObject("dictionary",new TExternalMethod(e=>{ + return new TDictionary(); + })); + SetObject("toNumber",new TExternalMethod(e=>{ + if(double.TryParse(e[0].ToString(),out var res)) + { + return new TNumber(res); + } + return new TNumber(0); + })); + + SetObject("typeof",new TExternalMethod(e=>{ + if(e.Length > 0) + { + return new TString(e[0].Type); + } + return new TString(""); + })); + + SetObject("con",Con()); + SetObject("fs",Filesystem()); + } + private TObject Con() + { + TDictionary con=new TDictionary(); + con.SetValue("println",new TExternalMethod((e)=>{ + Console.WriteLine(e[0].ToString()); + return new TNull(); + })); + con. SetValue("print",new TExternalMethod((e)=>{ + Console.Write(e[0].ToString()); + return new TNull(); + })); + con.SetValue("readln",new TExternalMethod((e)=>{ + return new TString(Console.ReadLine()); + + })); + return con; + } + + private TObject Filesystem() + { + TDictionary fs=new TDictionary(); + + fs.SetValue("mkdir",new TExternalMethod((e)=>{ + if(e.Length > 0) + { + return new TBool(Directory.CreateDirectory(e[0].ToString()).Exists); + } + return new TBool(false); + })); + fs.SetValue("directoryExists",new TExternalMethod((e)=>{ + if(e.Length > 0) + { + return new TBool(Directory.Exists(e[0].ToString())); + } + return new TBool(false); + })); + fs.SetValue("fileExists",new TExternalMethod((e)=>{ + if(e.Length > 0) + { + return new TBool(File.Exists(e[0].ToString())); + } + return new TBool(false); + })); + fs.SetValue("readAllText",new TExternalMethod((e)=>{ + if(e.Length > 0) + { + return new TString(File.ReadAllText(e[0].ToString())); + } + return new TNull(); + })); + fs.SetValue("writeAllText",new TExternalMethod((e)=>{ + if(e.Length > 1) + { + File.WriteAllText(e[0].ToString(),e[1].ToString()); + } + return new TNull(); + })); + + fs.SetValue("getFiles",new TExternalMethod((e)=>{ + TArray array=new TArray(); + if(e.Length > 0) + { + foreach(var item in Directory.GetFiles(e[0].ToString())) + { + array.Items.Add(new TString(Path.GetFileName(item))); + } + } + return array; + })); + fs.SetValue("getDirectories",new TExternalMethod((e)=>{ + TArray array=new TArray(); + if(e.Length > 0) + { + foreach(var item in Directory.GetDirectories(e[0].ToString())) + { + array.Items.Add(new TString(Path.GetFileName(item))); + } + } + return array; + })); + + return fs; + } } } \ No newline at end of file diff --git a/TLang.VM/SubEnvironment.cs b/TLang.VM/SubEnvironment.cs index 731d661..aba7e70 100644 --- a/TLang.VM/SubEnvironment.cs +++ b/TLang.VM/SubEnvironment.cs @@ -31,7 +31,7 @@ namespace TLang.VM } public override bool HasObjectRecurse(string key) { - return HasObject(key) && pEnv.HasObjectRecurse(key); + return HasObject(key) || pEnv.HasObjectRecurse(key); } diff --git a/TLang.VM/TArray.cs b/TLang.VM/TArray.cs new file mode 100644 index 0000000..55e2109 --- /dev/null +++ b/TLang.VM/TArray.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace TLang.VM +{ + public class TArray : TObject + { + public override string Type => "array"; + public List Items {get;set;}=new List(); + public override bool True => Items.Count > 0; + + public void Add(TObject value) + { + Items.Add(value); + } + public void Remove(TObject value) + { + Items.Remove(value); + } + } +} \ No newline at end of file diff --git a/TLang.VM/TBool.cs b/TLang.VM/TBool.cs new file mode 100644 index 0000000..735bcc8 --- /dev/null +++ b/TLang.VM/TBool.cs @@ -0,0 +1,18 @@ +namespace TLang.VM +{ + public class TBool : TObject + { + public override string Type => "bool"; + public override bool True => Value; + public bool Value {get;set;} + + public TBool(bool value) + { + Value = value; + } + public override string ToString() + { + return Value ? "true" : "false"; + } + } +} \ No newline at end of file diff --git a/TLang.VM/TCallable.cs b/TLang.VM/TCallable.cs index 75f3892..62926fb 100644 --- a/TLang.VM/TCallable.cs +++ b/TLang.VM/TCallable.cs @@ -2,6 +2,9 @@ namespace TLang.VM { public abstract class TCallable : TObject { + public string ClassName {get;set;} + public override string Type => "function"; + public override bool True => true; public abstract TObject Execute(params TObject[] args); } } \ No newline at end of file diff --git a/TLang.VM/TChar.cs b/TLang.VM/TChar.cs new file mode 100644 index 0000000..cf54d5e --- /dev/null +++ b/TLang.VM/TChar.cs @@ -0,0 +1,18 @@ +namespace TLang.VM +{ + public class TChar : TObject + { + public override string Type => "char"; + public override bool True => true; + public char Value {get;set;} + + public TChar(char value) + { + Value = value; + } + public override string ToString() + { + return Value.ToString(); + } + } +} \ No newline at end of file diff --git a/TLang.VM/TClassInstance.cs b/TLang.VM/TClassInstance.cs index 8a26bb6..a087a9b 100644 --- a/TLang.VM/TClassInstance.cs +++ b/TLang.VM/TClassInstance.cs @@ -5,6 +5,8 @@ namespace TLang.VM { public class TClassInstance : TObject { + public override string Type => $"class {classEntry.Name} : {classEntry.InheritsFrom}"; + public override bool True => true; TVMFile file; Class classEntry; TLangEnvironment oGenv; @@ -17,6 +19,8 @@ namespace TLang.VM public List InheritenceTree {get;}=new List(); public Dictionary Methods {get;} = new Dictionary(); + public Dictionary Fields {get;} = new Dictionary(); + public void Init(params TObject[] args) @@ -25,12 +29,34 @@ namespace TLang.VM foreach(var item in classEntry.ClassEntries) { - + if(item.Method) + { + ClassMethod meth=new ClassMethod(); + TClosure closure=new TClosure(file,file.Chunks[item.ChunkId],Environment); + + meth.Private = item.Private; + meth.Protected = item.Protected; + meth.Closure = closure; + meth.ClassName = classEntry.Name; + + Methods.Add(item.Name,meth); + } + else + { + ClassField field = new ClassField(); + field.ClassName = classEntry.Name; + TClosure closure = new TClosure(file,file.Chunks[item.ChunkId],Environment); + field.Private = item.Private; + field.Protected = item.Protected; + field.Value = closure.Execute(); + Fields.Add(item.Name,field); + + } } var cE = classEntry; var aC =oGenv.GetRootEnvironment().AvailableClasses; //we need to check inheritence - while(cE.InheritsFrom != "object") + while(cE.InheritsFrom != "object" && cE.InheritsFrom != "") { InheritenceTree.Add(cE.InheritsFrom); if(aC.ContainsKey(cE.InheritsFrom)) @@ -39,43 +65,104 @@ namespace TLang.VM cE = aC2.ToClass(cE.InheritsFrom); foreach(var item in cE.ClassEntries) { + if(!Fields.ContainsKey(item.Name) && !item.Method) + { + ClassField field = new ClassField(); + field.ClassName = cE.Name; + TClosure closure = new TClosure(aC2.File,aC2.File.Chunks[item.ChunkId],Environment); + field.Private = item.Private; + field.Protected = item.Protected; + field.Value = closure.Execute(); + Fields.Add(item.Name,field); + } if(!Methods.ContainsKey(item.Name) && item.Method) { if(item.Abstract) throw new Exception("Method is abstract"); ClassMethod meth=new ClassMethod(); - meth.File = aC2.File; - meth.Chunk = aC2.File.Chunks[item.ChunkId]; + TClosure closure=new TClosure(aC2.File,aC2.File.Chunks[item.ChunkId],Environment); + meth.ClassName = cE.Name; + meth.Closure = closure; meth.Private = item.Private; meth.Protected = item.Protected; - meth.Public = item.Public; + Methods.Add(item.Name,meth); } + } } } + if(!Methods.ContainsKey("toString")) + { + Methods.Add("toString",new ClassMethod(){ClassName="object", Closure = new TExternalMethod(e=>new TString($"class {classEntry.Name} : {classEntry.InheritsFrom}")), Private=false, Protected = false}); + } + if(Methods.ContainsKey(classEntry.Name)) + { + var ctor=Methods[classEntry.Name]; + if(ctor.ClassName == classEntry.Name) + { + ctor.Closure.ClassName = classEntry.Name; + ctor.Closure.Execute(args); + } + } } public TLangEnvironment Environment {get; private set;} - public void SetField(bool inside,string className,string key,TObject obj) + public void SetField(string className,string key,TObject obj) { - + if(Fields.ContainsKey(key)) + { + var field=Fields[key]; + if(field.Private && className != classEntry.Name) return; + if(field.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return; + + + field.Value=obj; + } } public TObject GetField(string className,string key) { - + if(Fields.ContainsKey(key)) + { + var field=Fields[key]; + if(field.Private && className != classEntry.Name) return new TUndefined(); + if(field.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return new TUndefined(); + + + return field.Value; + } return new TUndefined(); } + + public bool MethodExists(string className,string key) + { + if(Methods.ContainsKey(key)) + { + var method=Methods[key]; + if(method.Private && className != classEntry.Name) return false; + if(method.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return false; + return true; + } + return false; + } public TObject CallMethod(string className,string key,params TObject[] args) { if(Methods.ContainsKey(key)) { var method=Methods[key]; if(method.Private && className != classEntry.Name) return new TUndefined(); + if(method.Protected && className != classEntry.Name && !InheritenceTree.Contains(className)) return new TUndefined(); + method.Closure.ClassName = method.ClassName; + return method.Closure.Execute(args); } return new TUndefined(); } + public override string ToString() + { + return CallMethod(classEntry.Name,"toString").ToString(); + } + } } \ No newline at end of file diff --git a/TLang.VM/TClosure.cs b/TLang.VM/TClosure.cs index 3b65328..e585da9 100644 --- a/TLang.VM/TClosure.cs +++ b/TLang.VM/TClosure.cs @@ -2,6 +2,7 @@ namespace TLang.VM { public class TClosure : TCallable { + private TVMFile file; private Chunk chunk; private TLangEnvironment env; @@ -16,6 +17,7 @@ namespace TLang.VM public override TObject Execute(params TObject[] args) { ChunkExecuter executer = new ChunkExecuter(file,chunk,env); + executer.ClassName=ClassName; return executer.Execute(args); } } diff --git a/TLang.VM/TDictionary.cs b/TLang.VM/TDictionary.cs new file mode 100644 index 0000000..2e02677 --- /dev/null +++ b/TLang.VM/TDictionary.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; + +namespace TLang.VM +{ + public class TDictionary : TObject + { + public override string Type => "dictonary"; + public override bool True => true; + public Dictionary Items{get;}=new Dictionary(); + public void SetValue(string key,TObject value) + { + Items[key] = value; + } + public TObject GetValue(string key) + { + if(Items.ContainsKey(key)) return Items[key]; + return new TUndefined(); + } + public bool HasValue(string key) + { + return Items.ContainsKey(key); + } + + + public static TDictionary FromIEnumerator(IEnumerator enumerator) + { + TDictionary dictionary=new TDictionary(); + + dictionary.SetValue("movenext",new TExternalMethod(e=>{ + return new TBool(enumerator.MoveNext()); + })); + dictionary.SetValue("reset",new TExternalMethod(e=>{ + try{ + enumerator.Reset(); + }catch(Exception ex) + { + _=ex; + return new TBool(false); + } + return new TBool(true); + })); + dictionary.SetValue("getcurrent",new TExternalMethod(e=>{ + return enumerator.Current; + })); + return dictionary; + } + + } +} \ No newline at end of file diff --git a/TLang.VM/TExternalMethod.cs b/TLang.VM/TExternalMethod.cs new file mode 100644 index 0000000..34f670e --- /dev/null +++ b/TLang.VM/TExternalMethod.cs @@ -0,0 +1,20 @@ +using System; + +namespace TLang.VM +{ + internal class TExternalMethod : TCallable + { + public Func Callback {get;set;} + public TExternalMethod(Func value) + { + Callback = (args)=>{ + return value(args); + }; + } + + public override TObject Execute(params TObject[] args) + { + return Callback(args); + } + } +} \ No newline at end of file diff --git a/TLang.VM/TNull.cs b/TLang.VM/TNull.cs index fffed42..7f9be95 100644 --- a/TLang.VM/TNull.cs +++ b/TLang.VM/TNull.cs @@ -2,5 +2,11 @@ namespace TLang.VM { public class TNull : TObject { + public override string Type => "null"; + public override bool True => false; + public override string ToString() + { + return "null"; + } } } \ No newline at end of file diff --git a/TLang.VM/TNumber.cs b/TLang.VM/TNumber.cs index 144ab55..bfa84b7 100644 --- a/TLang.VM/TNumber.cs +++ b/TLang.VM/TNumber.cs @@ -2,11 +2,17 @@ namespace TLang.VM { public class TNumber : TObject { + public override string Type => "number"; + public override bool True => Value != 0; public double Value {get;set;} public TNumber(double value) { this.Value = value; } + public override string ToString() + { + return Value.ToString(); + } } } \ No newline at end of file diff --git a/TLang.VM/TObject.cs b/TLang.VM/TObject.cs index 7819649..f33162c 100644 --- a/TLang.VM/TObject.cs +++ b/TLang.VM/TObject.cs @@ -1,6 +1,8 @@ namespace TLang.VM { - public class TObject + public abstract class TObject { + public abstract string Type {get;} + public abstract bool True { get; } } } \ No newline at end of file diff --git a/TLang.VM/TString.cs b/TLang.VM/TString.cs index c4bc272..b9ba336 100644 --- a/TLang.VM/TString.cs +++ b/TLang.VM/TString.cs @@ -1,12 +1,34 @@ +using System.Collections.Generic; + namespace TLang.VM { public class TString : TObject { + public override string Type => "string"; + public override bool True => !string.IsNullOrWhiteSpace(Value); public string Value {get;set;} + public IEnumerable GetObjects() + { + foreach(var item in Value) + { + yield return new TChar(item); + } + } + public IEnumerable GetChars() + { + foreach(var item in Value) + { + yield return new TChar(item); + } + } public TString(string value) { this.Value = value; } + public override string ToString() + { + return Value; + } } } \ No newline at end of file diff --git a/TLang.VM/TUndefined.cs b/TLang.VM/TUndefined.cs index fecdb48..fa5543a 100644 --- a/TLang.VM/TUndefined.cs +++ b/TLang.VM/TUndefined.cs @@ -2,5 +2,11 @@ namespace TLang.VM { public class TUndefined : TObject { + public override string Type => "undefined"; + public override bool True => false; + public override string ToString() + { + return "undefined"; + } } } \ No newline at end of file diff --git a/TLang.VM/TVMFile.cs b/TLang.VM/TVMFile.cs index 849dc84..2e9f175 100644 --- a/TLang.VM/TVMFile.cs +++ b/TLang.VM/TVMFile.cs @@ -14,6 +14,8 @@ namespace TLang.VM public List Chunks {get;set;}=new List(); public TLangVersion Version {get;set;} public RootEnvironment Environment {get;private set;} + + public ChunkExecuter DefaultChunkExecuter => new ChunkExecuter(this,Chunks[0],Environment); public TVMFile(Stream file,RootEnvironment env) { Environment = env; @@ -141,6 +143,11 @@ namespace TLang.VM foreach(var class0 in Classes) { Environment.AvailableClasses.Add(class0.Name,new LoadedClassData(class0.InheritsFrom,this,class0.ClassEntries)); + Environment.SetObject(class0.Name,new TExternalMethod(args=>{ + TClassInstance instance = new TClassInstance(this,class0,Environment); + instance.Init(args); + return instance; + })); } return true; diff --git a/TLangScriptRunner/.vscode/launch.json b/TLangScriptRunner/.vscode/launch.json new file mode 100644 index 0000000..6d5fa00 --- /dev/null +++ b/TLangScriptRunner/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/net7.0/TLangScriptRunner.dll", + "args": ["${workspaceFolder}/fstest.tlang"], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/TLangScriptRunner/.vscode/tasks.json b/TLangScriptRunner/.vscode/tasks.json new file mode 100644 index 0000000..3e347d8 --- /dev/null +++ b/TLangScriptRunner/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/TLangScriptRunner.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/TLangScriptRunner.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/TLangScriptRunner.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/TLangScriptRunner/Program.cs b/TLangScriptRunner/Program.cs new file mode 100644 index 0000000..ddd5ec8 --- /dev/null +++ b/TLangScriptRunner/Program.cs @@ -0,0 +1,14 @@ +using TLang.VM; +using TLang.BytecodeCompiler; +using TLang.Parser; +using TLang.Common; +var node=Parse.ParseFromFiles(args); +MemoryStream memoryStream=new MemoryStream(); +ByteCodeGenerator.GenerateToStream(node,memoryStream,TLangVersion.Version,new TLangVersion(1,0,0,0)); +memoryStream.Position=0; +RootEnvironment environment=new RootEnvironment(); +environment.LoadStd(); +TVMFile file=new TVMFile(memoryStream,environment); +file.LoadDependencies(new DefaultDependencyPool()); + +file.DefaultChunkExecuter.Execute(); \ No newline at end of file diff --git a/TLangScriptRunner/TLangScriptRunner.csproj b/TLangScriptRunner/TLangScriptRunner.csproj new file mode 100644 index 0000000..6ac7e51 --- /dev/null +++ b/TLangScriptRunner/TLangScriptRunner.csproj @@ -0,0 +1,15 @@ + + + + + + + + + Exe + net7.0 + enable + enable + + + diff --git a/TLangScriptRunner/dell.txt b/TLangScriptRunner/dell.txt new file mode 100644 index 0000000..1e271c7 --- /dev/null +++ b/TLangScriptRunner/dell.txt @@ -0,0 +1 @@ +Demi Lovato \ No newline at end of file diff --git a/TLangScriptRunner/fstest.tlang b/TLangScriptRunner/fstest.tlang new file mode 100644 index 0000000..aa50559 --- /dev/null +++ b/TLangScriptRunner/fstest.tlang @@ -0,0 +1,4 @@ +ensure Api; + + +con.println(typeof(Api)); \ No newline at end of file diff --git a/TLangScriptRunner/mkdirtest.tlang b/TLangScriptRunner/mkdirtest.tlang new file mode 100644 index 0000000..e69de29 diff --git a/TLangScriptRunner/test.tlang b/TLangScriptRunner/test.tlang new file mode 100644 index 0000000..81a02c5 --- /dev/null +++ b/TLangScriptRunner/test.tlang @@ -0,0 +1,16 @@ +print("Please say your age: "); +i = toNumber(readln()); +if(i < 18) +{ + if(i < 13) + println("You are a preteen"); + else + println("You are a teenager"); +} +else +{ + if(i < 20) + println("You are an adult, but are still a teenager"); + else + println("You are an adult"); +} diff --git a/TVMTest b/TVMTest new file mode 100644 index 0000000000000000000000000000000000000000..daf6c1e846485de7cf460e20ffbedd02f2f3a809 GIT binary patch literal 146 zcmWFu^JQdUU;tq>029jp1C(H`Oie5*{_9`|QS=2YR#23gR{~=3yQJo3D){7=C6?qX tWELwRbbJLdIZE<_OMq(A|3Y*#FuY{|iE}A{O;yOxNn!YF{{bTT1^^C^B8mV2 literal 0 HcmV?d00001 diff --git a/VMTest/Program.cs b/VMTest/Program.cs index e7b795e..79b407a 100644 --- a/VMTest/Program.cs +++ b/VMTest/Program.cs @@ -1,10 +1,11 @@ using TLang.VM; using var f = File.OpenRead("app.tvm"); -TVMFile file = new TVMFile(f); - -ChunkExecuter executer=new ChunkExecuter(file,file.Chunks[0],new RootEnvironment()); +var env=new RootEnvironment(); +TVMFile file = new TVMFile(f,env); +file.LoadDependencies(new DefaultDependencyPool()); +ChunkExecuter executer=new ChunkExecuter(file,file.Chunks[0],env); var res=executer.Execute() as TNumber; if(res != null) { Console.WriteLine($"Number: {res.Value}"); -} \ No newline at end of file +} diff --git a/VMTest/app.tvm b/VMTest/app.tvm index 38178877dc690fa7400d8734c4cb9a1bb73cfcf9..b542a218da945c71a79e0b0e56f0a4fcec5f0da5 100644 GIT binary patch delta 65 zcmXquo1kQ4{fB{pf!ifDH&ekUzbvsNU*tVd!1@(Pn6;oNGp_{9^2y9AE&gl&0VoOt KZ(hFxlGXs4judAA delta 25 acmazuo1i2j{MW&$fdK^mI*5R21_l68z68Di