VM works
This commit is contained in:
parent
461b439d5b
commit
5fbf26d410
|
@ -4,6 +4,10 @@
|
||||||
<ProjectReference Include="..\TLang.BytecodeCompiler\TLang.BytecodeCompiler.csproj" />
|
<ProjectReference Include="..\TLang.BytecodeCompiler\TLang.BytecodeCompiler.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
using TLang.BytecodeCompiler;
|
using TLang.BytecodeCompiler;
|
||||||
using TLang.Common;
|
using TLang.Common;
|
||||||
using TLang.Parser;
|
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"))
|
using(var f = File.Create("app.tvm"))
|
||||||
{
|
{
|
||||||
ByteCodeGenerator.GenerateToStream(res,f,new TLangVersion(1,0,0,0),new TLangVersion(1,0,0,0));
|
ByteCodeGenerator.GenerateToStream(res,f,new TLangVersion(1,0,0,0),new TLangVersion(1,0,0,0));
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
37+5;
|
if("Demi Lovato")
|
||||||
|
{
|
||||||
|
print("Linus");
|
||||||
|
}
|
||||||
|
|
Binary file not shown.
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -89,13 +89,14 @@ namespace TLang.BytecodeCompiler
|
||||||
int closure = Chunks.Count;
|
int closure = Chunks.Count;
|
||||||
BytecodeChunk _chunk = new BytecodeChunk();
|
BytecodeChunk _chunk = new BytecodeChunk();
|
||||||
_chunk.Arguments = cValue.Arguments;
|
_chunk.Arguments = cValue.Arguments;
|
||||||
GenerateCode(cValue.Node,_chunk,0,0,-1,-1,false);
|
|
||||||
Chunks.Add(_chunk);
|
Chunks.Add(_chunk);
|
||||||
|
GenerateCode(cValue.Node,_chunk,0,0,-1,-1,false);
|
||||||
|
|
||||||
WriteBigEndianInt(strm,closure);
|
WriteBigEndianInt(strm,closure);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte c = 0b00000100;
|
byte c = 0b00000000;
|
||||||
|
|
||||||
if(classEntry.Modifier == "prot") {c |= 0b00000001;}
|
if(classEntry.Modifier == "prot") {c |= 0b00000001;}
|
||||||
if(classEntry.Modifier == "pub") {c |= 0b00000010;}
|
if(classEntry.Modifier == "pub") {c |= 0b00000010;}
|
||||||
|
@ -105,9 +106,9 @@ namespace TLang.BytecodeCompiler
|
||||||
strm.Write(bytes,0,bytes.Length);
|
strm.Write(bytes,0,bytes.Length);
|
||||||
int closure = Chunks.Count;
|
int closure = Chunks.Count;
|
||||||
BytecodeChunk _chunk = new BytecodeChunk();
|
BytecodeChunk _chunk = new BytecodeChunk();
|
||||||
|
|
||||||
GenerateCode(new ReturnNode(classEntry.InitialValue),_chunk,0,0,-1,-1,false);
|
|
||||||
Chunks.Add(_chunk);
|
Chunks.Add(_chunk);
|
||||||
|
GenerateCode(new ReturnNode(classEntry.InitialValue),_chunk,0,0,-1,-1,false);
|
||||||
|
|
||||||
WriteBigEndianInt(strm,closure);
|
WriteBigEndianInt(strm,closure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,8 +184,20 @@ namespace TLang.BytecodeCompiler
|
||||||
var getMemberNode = node as GetMemberNode;
|
var getMemberNode = node as GetMemberNode;
|
||||||
var getArrayValue = node as GetArrayNode;
|
var getArrayValue = node as GetArrayNode;
|
||||||
var setVariableNode = node as SetVariableNode;
|
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 != null)
|
||||||
{
|
{
|
||||||
if(scNode.IsSwitchScope)
|
if(scNode.IsSwitchScope)
|
||||||
|
@ -315,11 +328,11 @@ namespace TLang.BytecodeCompiler
|
||||||
GenerateCode(variableNode1,chunk,scopeIndex+1,0,_labelBeginningLoop,_labelEndLoop,false);
|
GenerateCode(variableNode1,chunk,scopeIndex+1,0,_labelBeginningLoop,_labelEndLoop,false);
|
||||||
LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}");
|
LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}");
|
||||||
chunk.Add(labelNode);
|
chunk.Add(labelNode);
|
||||||
|
GenerateCode(new NotNode(new MethodCallNode(variableNode,"movenext")),chunk,scopeBreakIndex+1,0,labelNum,labelNumEnd,false);
|
||||||
JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}");
|
JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}");
|
||||||
chunk.Add(conditional);
|
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(variableNode2,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
||||||
GenerateCode(eachNode.Body,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));
|
chunk.Add(new SimpleInstruction(Instruction.SCOPE_BEGIN));
|
||||||
GenerateCode(forNode.Init,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
GenerateCode(forNode.Init,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
||||||
|
|
||||||
LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}");
|
LabelInstruction labelNode=new LabelInstruction($"_label{labelNum}");
|
||||||
chunk.Add(labelNode);
|
chunk.Add(labelNode);
|
||||||
|
|
||||||
GenerateCode(new NotNode(forNode.Condition),chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
GenerateCode(new NotNode(forNode.Condition),chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
||||||
|
//chunk.Add(new SimpleInstruction(Instruction.POP));
|
||||||
JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}");
|
JumpConditional conditional = new JumpConditional($"_label{labelNumEnd}");
|
||||||
chunk.Add(conditional);
|
chunk.Add(conditional);
|
||||||
|
|
||||||
GenerateCode(forNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
GenerateCode(forNode.Body,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
||||||
GenerateCode(forNode.Increment,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
GenerateCode(forNode.Increment,chunk,scopeIndex+1,0,labelNum,labelNumEnd,false);
|
||||||
|
|
||||||
JumpUnconditional juC=new JumpUnconditional($"_label{labelNum}");
|
JumpUnconditional juC=new JumpUnconditional($"_label{labelNum}");
|
||||||
chunk.Add(juC);
|
chunk.Add(juC);
|
||||||
LabelInstruction endLabel = new LabelInstruction($"_label{labelNumEnd}");
|
LabelInstruction endLabel = new LabelInstruction($"_label{labelNumEnd}");
|
||||||
|
@ -403,9 +419,11 @@ namespace TLang.BytecodeCompiler
|
||||||
{
|
{
|
||||||
BytecodeChunk _chunk = new BytecodeChunk();
|
BytecodeChunk _chunk = new BytecodeChunk();
|
||||||
_chunk.Arguments = closureNode.Arguments;
|
_chunk.Arguments = closureNode.Arguments;
|
||||||
GenerateCode(closureNode.Node,_chunk,0,0,-1,-1,false);
|
|
||||||
int i = Chunks.Count;
|
int i = Chunks.Count;
|
||||||
|
|
||||||
Chunks.Add(_chunk);
|
Chunks.Add(_chunk);
|
||||||
|
GenerateCode(closureNode.Node,_chunk,0,0,-1,-1,false);
|
||||||
|
|
||||||
chunk.Add(new PushClosureNode(i));
|
chunk.Add(new PushClosureNode(i));
|
||||||
}
|
}
|
||||||
if(node is NullNode)
|
if(node is NullNode)
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace TLang.Common
|
||||||
public const byte GT = 0x17;
|
public const byte GT = 0x17;
|
||||||
public const byte GTE = 0x18;
|
public const byte GTE = 0x18;
|
||||||
|
|
||||||
|
public const byte POP = 0xE9;
|
||||||
|
|
||||||
public const byte SCOPE_BEGIN = 0xEA;
|
public const byte SCOPE_BEGIN = 0xEA;
|
||||||
public const byte SCOPE_END = 0xEB;
|
public const byte SCOPE_END = 0xEB;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace TLang.Common
|
namespace TLang.Common
|
||||||
{
|
{
|
||||||
public class TLangDependency
|
public class TLangDependency : IEquatable<TLangDependency>
|
||||||
{
|
{
|
||||||
public TLangDependency(string name,TLangVersion version)
|
public TLangDependency(string name,TLangVersion version)
|
||||||
{
|
{
|
||||||
|
@ -13,5 +15,10 @@ namespace TLang.Common
|
||||||
}
|
}
|
||||||
public string Name {get;set;}
|
public string Name {get;set;}
|
||||||
public TLangVersion Version {get;set;}
|
public TLangVersion Version {get;set;}
|
||||||
|
|
||||||
|
public bool Equals(TLangDependency other)
|
||||||
|
{
|
||||||
|
return Name == other.Name && Version.IntegerVersion == other.Version.IntegerVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -64,10 +64,7 @@ namespace TLang.Lexer
|
||||||
if(interoplated)
|
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 e = 0;
|
||||||
int escapeI = 0;
|
int escapeI = 0;
|
||||||
|
|
||||||
|
@ -80,7 +77,7 @@ namespace TLang.Lexer
|
||||||
{
|
{
|
||||||
if(b2.Length > 0 && escapeI < 1)
|
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));
|
tokens.Add(LexToken.String(b2.ToString()).WithLineInfo(lineInfo));
|
||||||
b2.Clear();
|
b2.Clear();
|
||||||
e++;
|
e++;
|
||||||
|
@ -104,12 +101,17 @@ namespace TLang.Lexer
|
||||||
escapeI--;
|
escapeI--;
|
||||||
if(b2.Length > 0 && escapeI == 0)
|
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.Add(LexToken.Token("(").WithLineInfo(lineInfo));
|
||||||
tokens.AddRange(Lex.GetTokensFromString(b2.ToString(),"compilerGenerated.tlang").Tokens);
|
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(".").WithLineInfo(lineInfo));
|
||||||
|
tokens.Add(LexToken.Token("toString").WithLineInfo(lineInfo));
|
||||||
|
tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo));
|
||||||
|
tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo));
|
||||||
|
|
||||||
b2.Clear();
|
b2.Clear();
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
|
@ -128,18 +130,23 @@ namespace TLang.Lexer
|
||||||
{
|
{
|
||||||
if(escapeI > 0)
|
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.Add(LexToken.Token("(").WithLineInfo(lineInfo));
|
||||||
tokens.AddRange(Lex.GetTokensFromString(b2.ToString(),"compilerGenerated.tlang").Tokens);
|
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(".").WithLineInfo(lineInfo));
|
||||||
|
tokens.Add(LexToken.Token("toString").WithLineInfo(lineInfo));
|
||||||
|
tokens.Add(LexToken.Token("(").WithLineInfo(lineInfo));
|
||||||
|
tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo));
|
||||||
|
|
||||||
b2.Clear();
|
b2.Clear();
|
||||||
e++;
|
e++;
|
||||||
}
|
}
|
||||||
else
|
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));
|
tokens.Add(LexToken.String(b2.ToString()).WithLineInfo(lineInfo));
|
||||||
b2.Clear();
|
b2.Clear();
|
||||||
e++;
|
e++;
|
||||||
|
@ -147,7 +154,7 @@ namespace TLang.Lexer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tokens.Add(LexToken.Token(")").WithLineInfo(lineInfo));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace TLang.Lexer
|
||||||
}
|
}
|
||||||
if(consumeIfTrue) Offset += tokenText.Length;
|
if(consumeIfTrue) Offset += tokenText.Length;
|
||||||
return new LexEntryContext(tokens,offset,true);
|
return new LexEntryContext(tokens,offset,true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LexEntryContext NextEntries(bool consumeIfTrue,params string[] tokenText)
|
public LexEntryContext NextEntries(bool consumeIfTrue,params string[] tokenText)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using TLang.Lexer;
|
using TLang.Lexer;
|
||||||
namespace TLang.Parser
|
namespace TLang.Parser
|
||||||
{
|
{
|
||||||
|
@ -339,17 +340,62 @@ return res;
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Node ParseValue()
|
private Node ParseValue()
|
||||||
{
|
{
|
||||||
var doc = Context.PopDocumentation();
|
var doc = Context.PopDocumentation();
|
||||||
var token = Context.NextEntry();
|
var token = Context.NextEntry();
|
||||||
if(token.IsString) return new StringNode(token.Text){LineInfo = token.Position};
|
if(token.IsString) return new StringNode(token.Text){LineInfo = token.Position};
|
||||||
if(token.IsChar) return new CharNode(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 == "(")
|
if(token.Text == "(")
|
||||||
{
|
{
|
||||||
var assignable = ParseAssigable();
|
var assignable = ParseAssigable();
|
||||||
assignable.LineInfo = token.Position;
|
assignable.LineInfo = token.Position;
|
||||||
if(!Context.NextEntries(true,")").Success) throw new CompilerError("symbol must be a ')'",assignable);
|
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;
|
return assignable;
|
||||||
}
|
}
|
||||||
if(token.Text == "class")
|
if(token.Text == "class")
|
||||||
|
@ -606,6 +652,7 @@ return res;
|
||||||
}
|
}
|
||||||
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)
|
while(Context.MoreTokens && Context.NextEntries(true,"[").Success)
|
||||||
{
|
{
|
||||||
var p = ParseNode();
|
var p = ParseNode();
|
||||||
|
@ -616,9 +663,11 @@ return res;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = new GetMemberNode(ret,token2.Text){LineInfo = token2.Position};
|
ret = new GetMemberNode(ret,token2.Text){LineInfo = token2.Position};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Context.MoreTokens && Context.NextEntries(true,"++").Success)
|
if(Context.MoreTokens && Context.NextEntries(true,"++").Success)
|
||||||
{
|
{
|
||||||
var r = new PostFixIncrementNode(ret){LineInfo = ret.LineInfo};
|
var r = new PostFixIncrementNode(ret){LineInfo = ret.LineInfo};
|
||||||
|
@ -696,8 +745,10 @@ return res;
|
||||||
mCall.Arguments.Add(ParseNode());
|
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)
|
while(Context.MoreTokens && Context.NextEntries(true,"[").Success)
|
||||||
{
|
{
|
||||||
var p = ParseNode();
|
var p = ParseNode();
|
||||||
|
@ -708,6 +759,7 @@ return res;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = new GetMemberNode(ret,token2.Text){LineInfo = token2.Position};
|
ret = new GetMemberNode(ret,token2.Text){LineInfo = token2.Position};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,13 @@ namespace TLang.Parser
|
||||||
{
|
{
|
||||||
public class GetArrayNode : SymbolNode
|
public class GetArrayNode : SymbolNode
|
||||||
{
|
{
|
||||||
public SymbolNode Symbol {get;set;}
|
public Node Symbol {get;set;}
|
||||||
public Node Expression {get;set;}
|
public Node Expression {get;set;}
|
||||||
|
|
||||||
public GetArrayNode(SymbolNode sym, Node expr)
|
public GetArrayNode(Node sym, Node expr)
|
||||||
{
|
{
|
||||||
Symbol = sym;
|
Symbol = sym;
|
||||||
this.Name = sym.Name;
|
this.Name = "";
|
||||||
Expression = expr;
|
Expression = expr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,10 @@ namespace TLang.Parser
|
||||||
{
|
{
|
||||||
public class MethodCallNode : SymbolNode
|
public class MethodCallNode : SymbolNode
|
||||||
{
|
{
|
||||||
public SymbolNode Symbol {get;set;}
|
public Node Symbol {get;set;}
|
||||||
public List<Node> Arguments {get;set;}=new List<Node>();
|
public List<Node> Arguments {get;set;}=new List<Node>();
|
||||||
|
|
||||||
public MethodCallNode(SymbolNode symbol, string name)
|
public MethodCallNode(Node symbol, string name)
|
||||||
{
|
{
|
||||||
Symbol = symbol;
|
Symbol = symbol;
|
||||||
Name = name;
|
Name = name;
|
||||||
|
|
|
@ -6,5 +6,6 @@ namespace TLang.Parser
|
||||||
{
|
{
|
||||||
public LexLineInfo LineInfo {get;set;}
|
public LexLineInfo LineInfo {get;set;}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -13,37 +13,44 @@ namespace TLang.VM
|
||||||
|
|
||||||
public override TObject GetObject(string key)
|
public override TObject GetObject(string key)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
if(key == "this")
|
||||||
|
{
|
||||||
|
return classInstance;
|
||||||
|
}
|
||||||
|
return oGenv.GetObject(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override TLangEnvironment GetParentEnvironment()
|
public override TLangEnvironment GetParentEnvironment()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return oGenv;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override RootEnvironment GetRootEnvironment()
|
public override RootEnvironment GetRootEnvironment()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return oGenv.GetRootEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override TLangEnvironment GetSubEnvironment()
|
public override TLangEnvironment GetSubEnvironment()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return new SubEnvironment(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HasObject(string key)
|
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)
|
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)
|
public override void SetObject(string key, TObject value)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
if(key == "this") return;
|
||||||
|
oGenv.SetObject(key,value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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;}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,14 +2,12 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class ClassMethod
|
public class ClassMethod
|
||||||
{
|
{
|
||||||
public bool Public {get;set;}
|
public string ClassName {get;set;}
|
||||||
|
|
||||||
public bool Private {get;set;}
|
public bool Private {get;set;}
|
||||||
|
|
||||||
public bool Protected {get;set;}
|
public bool Protected {get;set;}
|
||||||
|
|
||||||
public Chunk Chunk {get;set;}
|
public TCallable Closure {get;set;}
|
||||||
|
|
||||||
public TVMFile File {get;set;}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using TLang.Common;
|
using TLang.Common;
|
||||||
|
|
||||||
namespace TLang.VM
|
namespace TLang.VM
|
||||||
|
@ -8,14 +9,14 @@ namespace TLang.VM
|
||||||
public class DefaultDependencyPool : IDependencyPool
|
public class DefaultDependencyPool : IDependencyPool
|
||||||
{
|
{
|
||||||
List<(TLangDependency Dependency,TVMFile File)> items = new List<(TLangDependency Dependency, TVMFile File)>();
|
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";
|
string fileName = $"{dependency.Name}-{dependency.Version}.tvm";
|
||||||
if(File.Exists(fileName))
|
if(File.Exists(fileName))
|
||||||
{
|
{
|
||||||
using(var f = File.OpenRead(fileName))
|
using(var f = File.OpenRead(fileName))
|
||||||
{
|
{
|
||||||
TVMFile file = new TVMFile(f);
|
TVMFile file = new TVMFile(f,env);
|
||||||
items.Add((dependency,file));
|
items.Add((dependency,file));
|
||||||
return file.LoadDependencies(this);
|
return file.LoadDependencies(this);
|
||||||
}
|
}
|
||||||
|
@ -34,17 +35,19 @@ namespace TLang.VM
|
||||||
|
|
||||||
public bool DependencyExists(TLangDependency dependency)
|
public bool DependencyExists(TLangDependency dependency)
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return items.Any(e=>
|
||||||
|
e.Dependency.Equals(dependency)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<(TLangDependency Dependency, TVMFile File)> GetEnumerator()
|
public IEnumerator<(TLangDependency Dependency, TVMFile File)> GetEnumerator()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return items.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
{
|
{
|
||||||
throw new System.NotImplementedException();
|
return this.GetEnumerator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
namespace TLang.VM
|
namespace TLang.VM
|
||||||
{
|
{
|
||||||
|
@ -48,5 +49,128 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
return new SubEnvironment(this);
|
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<TObject>((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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,7 +31,7 @@ namespace TLang.VM
|
||||||
}
|
}
|
||||||
public override bool HasObjectRecurse(string key)
|
public override bool HasObjectRecurse(string key)
|
||||||
{
|
{
|
||||||
return HasObject(key) && pEnv.HasObjectRecurse(key);
|
return HasObject(key) || pEnv.HasObjectRecurse(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace TLang.VM
|
||||||
|
{
|
||||||
|
public class TArray : TObject
|
||||||
|
{
|
||||||
|
public override string Type => "array";
|
||||||
|
public List<TObject> Items {get;set;}=new List<TObject>();
|
||||||
|
public override bool True => Items.Count > 0;
|
||||||
|
|
||||||
|
public void Add(TObject value)
|
||||||
|
{
|
||||||
|
Items.Add(value);
|
||||||
|
}
|
||||||
|
public void Remove(TObject value)
|
||||||
|
{
|
||||||
|
Items.Remove(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,9 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
public abstract class TCallable : TObject
|
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);
|
public abstract TObject Execute(params TObject[] args);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class TClassInstance : TObject
|
public class TClassInstance : TObject
|
||||||
{
|
{
|
||||||
|
public override string Type => $"class {classEntry.Name} : {classEntry.InheritsFrom}";
|
||||||
|
public override bool True => true;
|
||||||
TVMFile file;
|
TVMFile file;
|
||||||
Class classEntry;
|
Class classEntry;
|
||||||
TLangEnvironment oGenv;
|
TLangEnvironment oGenv;
|
||||||
|
@ -17,6 +19,8 @@ namespace TLang.VM
|
||||||
public List<string> InheritenceTree {get;}=new List<string>();
|
public List<string> InheritenceTree {get;}=new List<string>();
|
||||||
public Dictionary<string,ClassMethod> Methods {get;} = new Dictionary<string, ClassMethod>();
|
public Dictionary<string,ClassMethod> Methods {get;} = new Dictionary<string, ClassMethod>();
|
||||||
|
|
||||||
|
public Dictionary<string,ClassField> Fields {get;} = new Dictionary<string, ClassField>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void Init(params TObject[] args)
|
public void Init(params TObject[] args)
|
||||||
|
@ -25,12 +29,34 @@ namespace TLang.VM
|
||||||
|
|
||||||
foreach(var item in classEntry.ClassEntries)
|
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 cE = classEntry;
|
||||||
var aC =oGenv.GetRootEnvironment().AvailableClasses;
|
var aC =oGenv.GetRootEnvironment().AvailableClasses;
|
||||||
//we need to check inheritence
|
//we need to check inheritence
|
||||||
while(cE.InheritsFrom != "object")
|
while(cE.InheritsFrom != "object" && cE.InheritsFrom != "")
|
||||||
{
|
{
|
||||||
InheritenceTree.Add(cE.InheritsFrom);
|
InheritenceTree.Add(cE.InheritsFrom);
|
||||||
if(aC.ContainsKey(cE.InheritsFrom))
|
if(aC.ContainsKey(cE.InheritsFrom))
|
||||||
|
@ -39,43 +65,104 @@ namespace TLang.VM
|
||||||
cE = aC2.ToClass(cE.InheritsFrom);
|
cE = aC2.ToClass(cE.InheritsFrom);
|
||||||
foreach(var item in cE.ClassEntries)
|
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(!Methods.ContainsKey(item.Name) && item.Method)
|
||||||
{
|
{
|
||||||
if(item.Abstract) throw new Exception("Method is abstract");
|
if(item.Abstract) throw new Exception("Method is abstract");
|
||||||
ClassMethod meth=new ClassMethod();
|
ClassMethod meth=new ClassMethod();
|
||||||
meth.File = aC2.File;
|
TClosure closure=new TClosure(aC2.File,aC2.File.Chunks[item.ChunkId],Environment);
|
||||||
meth.Chunk = aC2.File.Chunks[item.ChunkId];
|
meth.ClassName = cE.Name;
|
||||||
|
meth.Closure = closure;
|
||||||
meth.Private = item.Private;
|
meth.Private = item.Private;
|
||||||
meth.Protected = item.Protected;
|
meth.Protected = item.Protected;
|
||||||
meth.Public = item.Public;
|
|
||||||
Methods.Add(item.Name,meth);
|
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 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)
|
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();
|
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)
|
public TObject CallMethod(string className,string key,params TObject[] args)
|
||||||
{
|
{
|
||||||
if(Methods.ContainsKey(key))
|
if(Methods.ContainsKey(key))
|
||||||
{
|
{
|
||||||
var method=Methods[key];
|
var method=Methods[key];
|
||||||
if(method.Private && className != classEntry.Name) return new TUndefined();
|
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();
|
return new TUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return CallMethod(classEntry.Name,"toString").ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,6 +2,7 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class TClosure : TCallable
|
public class TClosure : TCallable
|
||||||
{
|
{
|
||||||
|
|
||||||
private TVMFile file;
|
private TVMFile file;
|
||||||
private Chunk chunk;
|
private Chunk chunk;
|
||||||
private TLangEnvironment env;
|
private TLangEnvironment env;
|
||||||
|
@ -16,6 +17,7 @@ namespace TLang.VM
|
||||||
public override TObject Execute(params TObject[] args)
|
public override TObject Execute(params TObject[] args)
|
||||||
{
|
{
|
||||||
ChunkExecuter executer = new ChunkExecuter(file,chunk,env);
|
ChunkExecuter executer = new ChunkExecuter(file,chunk,env);
|
||||||
|
executer.ClassName=ClassName;
|
||||||
return executer.Execute(args);
|
return executer.Execute(args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<string,TObject> Items{get;}=new Dictionary<string, TObject>();
|
||||||
|
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<TObject> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace TLang.VM
|
||||||
|
{
|
||||||
|
internal class TExternalMethod : TCallable
|
||||||
|
{
|
||||||
|
public Func<TObject[], TObject> Callback {get;set;}
|
||||||
|
public TExternalMethod(Func<TObject[], TObject> value)
|
||||||
|
{
|
||||||
|
Callback = (args)=>{
|
||||||
|
return value(args);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(params TObject[] args)
|
||||||
|
{
|
||||||
|
return Callback(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,5 +2,11 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class TNull : TObject
|
public class TNull : TObject
|
||||||
{
|
{
|
||||||
|
public override string Type => "null";
|
||||||
|
public override bool True => false;
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,11 +2,17 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class TNumber : TObject
|
public class TNumber : TObject
|
||||||
{
|
{
|
||||||
|
public override string Type => "number";
|
||||||
|
public override bool True => Value != 0;
|
||||||
public double Value {get;set;}
|
public double Value {get;set;}
|
||||||
|
|
||||||
public TNumber(double value)
|
public TNumber(double value)
|
||||||
{
|
{
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
}
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
namespace TLang.VM
|
namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class TObject
|
public abstract class TObject
|
||||||
{
|
{
|
||||||
|
public abstract string Type {get;}
|
||||||
|
public abstract bool True { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,34 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace TLang.VM
|
namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class TString : TObject
|
public class TString : TObject
|
||||||
{
|
{
|
||||||
|
public override string Type => "string";
|
||||||
|
public override bool True => !string.IsNullOrWhiteSpace(Value);
|
||||||
public string Value {get;set;}
|
public string Value {get;set;}
|
||||||
|
|
||||||
|
public IEnumerable<TObject> GetObjects()
|
||||||
|
{
|
||||||
|
foreach(var item in Value)
|
||||||
|
{
|
||||||
|
yield return new TChar(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public IEnumerable<TObject> GetChars()
|
||||||
|
{
|
||||||
|
foreach(var item in Value)
|
||||||
|
{
|
||||||
|
yield return new TChar(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
public TString(string value)
|
public TString(string value)
|
||||||
{
|
{
|
||||||
this.Value = value;
|
this.Value = value;
|
||||||
}
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,5 +2,11 @@ namespace TLang.VM
|
||||||
{
|
{
|
||||||
public class TUndefined : TObject
|
public class TUndefined : TObject
|
||||||
{
|
{
|
||||||
|
public override string Type => "undefined";
|
||||||
|
public override bool True => false;
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,6 +14,8 @@ namespace TLang.VM
|
||||||
public List<Chunk> Chunks {get;set;}=new List<Chunk>();
|
public List<Chunk> Chunks {get;set;}=new List<Chunk>();
|
||||||
public TLangVersion Version {get;set;}
|
public TLangVersion Version {get;set;}
|
||||||
public RootEnvironment Environment {get;private set;}
|
public RootEnvironment Environment {get;private set;}
|
||||||
|
|
||||||
|
public ChunkExecuter DefaultChunkExecuter => new ChunkExecuter(this,Chunks[0],Environment);
|
||||||
public TVMFile(Stream file,RootEnvironment env)
|
public TVMFile(Stream file,RootEnvironment env)
|
||||||
{
|
{
|
||||||
Environment = env;
|
Environment = env;
|
||||||
|
@ -141,6 +143,11 @@ namespace TLang.VM
|
||||||
foreach(var class0 in Classes)
|
foreach(var class0 in Classes)
|
||||||
{
|
{
|
||||||
Environment.AvailableClasses.Add(class0.Name,new LoadedClassData(class0.InheritsFrom,this,class0.ClassEntries));
|
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;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -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();
|
|
@ -0,0 +1,15 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\TLang.BytecodeCompiler\TLang.BytecodeCompiler.csproj" />
|
||||||
|
<ProjectReference Include="..\TLang.VM\TLang.VM.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1 @@
|
||||||
|
Demi Lovato
|
|
@ -0,0 +1,4 @@
|
||||||
|
ensure Api;
|
||||||
|
|
||||||
|
|
||||||
|
con.println(typeof(Api));
|
|
@ -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");
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
using TLang.VM;
|
using TLang.VM;
|
||||||
using var f = File.OpenRead("app.tvm");
|
using var f = File.OpenRead("app.tvm");
|
||||||
TVMFile file = new TVMFile(f);
|
var env=new RootEnvironment();
|
||||||
|
TVMFile file = new TVMFile(f,env);
|
||||||
ChunkExecuter executer=new ChunkExecuter(file,file.Chunks[0],new RootEnvironment());
|
file.LoadDependencies(new DefaultDependencyPool());
|
||||||
|
ChunkExecuter executer=new ChunkExecuter(file,file.Chunks[0],env);
|
||||||
var res=executer.Execute() as TNumber;
|
var res=executer.Execute() as TNumber;
|
||||||
if(res != null)
|
if(res != null)
|
||||||
{
|
{
|
||||||
|
|
BIN
VMTest/app.tvm
BIN
VMTest/app.tvm
Binary file not shown.
Loading…
Reference in New Issue