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 3817887..b542a21 100644
Binary files a/ByteCodeTest/app.tvm and b/ByteCodeTest/app.tvm differ
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 0000000..daf6c1e
Binary files /dev/null and b/TVMTest differ
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 3817887..b542a21 100644
Binary files a/VMTest/app.tvm and b/VMTest/app.tvm differ