Working on MemberGetVariableValue
This commit is contained in:
commit
b74fd1d083
|
@ -0,0 +1,133 @@
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.log
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.Publish.xml
|
||||||
|
*.pubxml
|
||||||
|
*.azurePubxml
|
||||||
|
|
||||||
|
# NuGet Packages Directory
|
||||||
|
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
|
||||||
|
packages/
|
||||||
|
## TODO: If the tool you use requires repositories.config, also uncomment the next line
|
||||||
|
!packages/repositories.config
|
||||||
|
|
||||||
|
# Windows Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Windows Store app package directory
|
||||||
|
AppPackages/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
sql/
|
||||||
|
*.Cache
|
||||||
|
ClientBin/
|
||||||
|
[Ss]tyle[Cc]op.*
|
||||||
|
![Ss]tyle[Cc]op.targets
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
|
||||||
|
*.publishsettings
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file to a newer
|
||||||
|
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
App_Data/*.mdf
|
||||||
|
App_Data/*.ldf
|
||||||
|
|
||||||
|
# =========================
|
||||||
|
# Windows detritus
|
||||||
|
# =========================
|
||||||
|
|
||||||
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Mac desktop service store files
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
_NCrunch*
|
|
@ -0,0 +1,37 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class AddNode : Node
|
||||||
|
{
|
||||||
|
public Node Left {get;set;}
|
||||||
|
public Node Right {get;set;}
|
||||||
|
|
||||||
|
public AddNode(Node left, Node right)
|
||||||
|
{
|
||||||
|
this.Left = left;
|
||||||
|
this.Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var l=Left.Execute(nodeEnv);
|
||||||
|
var r = Right.Execute(nodeEnv);
|
||||||
|
var lNum = l as TNumber;
|
||||||
|
var rNum = r as TNumber;
|
||||||
|
var lStr = l as TString;
|
||||||
|
var rStr = r as TString;
|
||||||
|
|
||||||
|
|
||||||
|
if(lNum != null && rNum != null)
|
||||||
|
return new TNumber(lNum.Value + rNum.Value);
|
||||||
|
|
||||||
|
if(lStr != null && rStr != null)
|
||||||
|
return new TString(lStr.Value + rStr.Value);
|
||||||
|
if(lStr != null && rNum != null)
|
||||||
|
return new TString(lStr.Value + rNum.Value.ToString());
|
||||||
|
if(lNum != null && rStr != null)
|
||||||
|
return new TString(lNum.Value.ToString() + rStr.Value);
|
||||||
|
|
||||||
|
return new TNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class ClosureNode : Node
|
||||||
|
{
|
||||||
|
//j=func(a,b,c,d) 4
|
||||||
|
public ClosureNode(List<string> args,Node node)
|
||||||
|
{
|
||||||
|
Arguments = args;
|
||||||
|
Node=node;
|
||||||
|
}
|
||||||
|
public Node Node {get;set;}
|
||||||
|
public List<string> Arguments {get;set;}
|
||||||
|
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
return new TInternalMethod(this,nodeEnv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class ConstNode : Node
|
||||||
|
{
|
||||||
|
public TObject Value {get;set;}
|
||||||
|
|
||||||
|
public ConstNode(TObject value)
|
||||||
|
{
|
||||||
|
this.Value= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class DivideNode : Node
|
||||||
|
{
|
||||||
|
public Node Left {get;set;}
|
||||||
|
public Node Right {get;set;}
|
||||||
|
|
||||||
|
public DivideNode(Node left, Node right)
|
||||||
|
{
|
||||||
|
this.Left = left;
|
||||||
|
this.Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var l = Left.Execute(nodeEnv) as TNumber;
|
||||||
|
var r = Right.Execute(nodeEnv) as TNumber;
|
||||||
|
|
||||||
|
if(l != null && r != null)
|
||||||
|
return new TNumber(l.Value / r.Value);
|
||||||
|
|
||||||
|
return new TNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class EnvironmentNode : Node
|
||||||
|
{
|
||||||
|
public List<Node> Nodes {get;set;}=new List<Node>();
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
|
||||||
|
TObject returnType = TObject.Null;
|
||||||
|
foreach(var node in Nodes)
|
||||||
|
{
|
||||||
|
if(node is EnvironmentNode)
|
||||||
|
{
|
||||||
|
returnType =node.Execute(nodeEnv.SubEnv);
|
||||||
|
}else{
|
||||||
|
returnType = node.Execute(nodeEnv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class FunctionCallNode : Node
|
||||||
|
{
|
||||||
|
public string Text {get;set;}
|
||||||
|
public List<Node> Args {get;set;}
|
||||||
|
|
||||||
|
public FunctionCallNode(string text, List<Node> args)
|
||||||
|
{
|
||||||
|
this.Text = text;
|
||||||
|
this.Args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var n = nodeEnv[Text] as ICallable;
|
||||||
|
if(n != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
return n.Call(Args.Select<Node,TObject>(e=>e.Execute(nodeEnv)).ToArray());
|
||||||
|
}
|
||||||
|
return new TUninit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class SetVariableNode : Node
|
||||||
|
{
|
||||||
|
public Node Value {get;set;}
|
||||||
|
public string Name {get;set;}
|
||||||
|
public SetVariableNode(string text,Node v)
|
||||||
|
{
|
||||||
|
Name=text;
|
||||||
|
Value=v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var res=Value.Execute(nodeEnv);
|
||||||
|
nodeEnv[Name]=res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class GetVariableValue : Node
|
||||||
|
{
|
||||||
|
public string Name {get;set;}
|
||||||
|
|
||||||
|
public GetVariableValue(string text)
|
||||||
|
{
|
||||||
|
this.Name = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
return nodeEnv[Name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class IfNode : Node
|
||||||
|
{
|
||||||
|
public Node Condition {get;set;}
|
||||||
|
public Node Yes {get;set;}
|
||||||
|
public Node No {get;set;}
|
||||||
|
|
||||||
|
public IfNode(Node condition, Node yes, Node no)
|
||||||
|
{
|
||||||
|
this.Condition = condition;
|
||||||
|
this.Yes = yes;
|
||||||
|
this.No = no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var condition = Condition.Execute(nodeEnv);
|
||||||
|
var cInt = condition as TNumber;
|
||||||
|
|
||||||
|
|
||||||
|
bool condition_bool=false;
|
||||||
|
|
||||||
|
if(cInt != null)
|
||||||
|
{
|
||||||
|
condition_bool=cInt.Value != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return condition_bool ? Yes.Execute(nodeEnv) : No.Execute(nodeEnv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class LexToken
|
||||||
|
{
|
||||||
|
private LexToken(string text)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LexToken FromGeneralToken(int c)
|
||||||
|
{
|
||||||
|
return new LexToken(((char)c).ToString());
|
||||||
|
}
|
||||||
|
public static LexToken FromGeneralToken(string text)
|
||||||
|
{
|
||||||
|
return new LexToken(text);
|
||||||
|
}
|
||||||
|
public static LexToken FromString(string text)
|
||||||
|
{
|
||||||
|
return new LexToken(text){IsString = true};
|
||||||
|
}
|
||||||
|
public static LexToken FromChar(string text)
|
||||||
|
{
|
||||||
|
return new LexToken(text){IsChar = true};
|
||||||
|
}
|
||||||
|
public bool IsString {get;private set;}=false;
|
||||||
|
|
||||||
|
public bool IsChar {get;private set;}=false;
|
||||||
|
public string Text {get;private set;}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,237 @@
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class Lexer
|
||||||
|
{
|
||||||
|
TextReader reader;
|
||||||
|
public Lexer(string fName) : this(new StreamReader(fName))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public Lexer(TextReader reader)
|
||||||
|
{
|
||||||
|
this.reader = reader;
|
||||||
|
}
|
||||||
|
List<LexToken>? tokens=null;
|
||||||
|
public List<LexToken> Tokens
|
||||||
|
{
|
||||||
|
get{
|
||||||
|
if(tokens == null)
|
||||||
|
{
|
||||||
|
tokens = _getTokens();
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<LexToken> _tokens = new List<LexToken>();
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
private void FlushBuilder()
|
||||||
|
{
|
||||||
|
if(b.Length > 0)
|
||||||
|
{
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken(b.ToString()));
|
||||||
|
b.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool escaped=false;
|
||||||
|
private char getChar()
|
||||||
|
{
|
||||||
|
int read = reader.Read();
|
||||||
|
if(read == '\\')
|
||||||
|
{
|
||||||
|
escaped = true;
|
||||||
|
read = reader.Read();
|
||||||
|
if(read == 'x')
|
||||||
|
{
|
||||||
|
return (char)Convert.FromHexString($"{(char)reader.Read()}{(char)reader.Read()}")[0];
|
||||||
|
}
|
||||||
|
else if(read == 'n')
|
||||||
|
{
|
||||||
|
return '\n';
|
||||||
|
}
|
||||||
|
else if(read == 't')
|
||||||
|
{
|
||||||
|
return '\t';
|
||||||
|
}
|
||||||
|
else if(read == 'r')
|
||||||
|
{
|
||||||
|
return '\r';
|
||||||
|
}
|
||||||
|
return (char)read;
|
||||||
|
}
|
||||||
|
escaped=false;
|
||||||
|
return (char)read;
|
||||||
|
}
|
||||||
|
private List<LexToken> _getTokens()
|
||||||
|
{
|
||||||
|
|
||||||
|
int read;
|
||||||
|
while((read = reader.Read()) != -1)
|
||||||
|
{
|
||||||
|
int next=reader.Peek();
|
||||||
|
switch(read)
|
||||||
|
{
|
||||||
|
case '\"':
|
||||||
|
FlushBuilder();
|
||||||
|
//"Some \"Some String\" Is OK"
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
char r = getChar();
|
||||||
|
if(r == -1 || (!escaped && r == '\"'))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
b.Append(r);
|
||||||
|
}
|
||||||
|
_tokens.Add(LexToken.FromString(b.ToString()));
|
||||||
|
b.Clear();
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
FlushBuilder();
|
||||||
|
LexToken.FromChar(getChar().ToString());
|
||||||
|
reader.Read();
|
||||||
|
break;
|
||||||
|
case '#':
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
read = reader.Read();
|
||||||
|
if(read == -1) return _tokens;
|
||||||
|
|
||||||
|
if(read == '\n')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
FlushBuilder();
|
||||||
|
if(next == '=')
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken($"{(char)read}{(char)next}"));
|
||||||
|
}
|
||||||
|
else if(next == '/')
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
read = reader.Read();
|
||||||
|
if(read == -1) return _tokens;
|
||||||
|
|
||||||
|
if(read == '\n')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(next == '*')
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
bool lastIsAstrick=false;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
read = reader.Read();
|
||||||
|
if(read == -1) return _tokens;
|
||||||
|
if(read == '*')
|
||||||
|
{
|
||||||
|
lastIsAstrick=true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if(read == '/')
|
||||||
|
{
|
||||||
|
if(lastIsAstrick)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastIsAstrick=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken(read));
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case '^':
|
||||||
|
case '*':
|
||||||
|
case '%':
|
||||||
|
FlushBuilder();
|
||||||
|
if(next == '=')
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken($"{(char)read}{(char)next}"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken(read));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '|':
|
||||||
|
case '&':
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '+':
|
||||||
|
case '-':
|
||||||
|
case '!':
|
||||||
|
FlushBuilder();
|
||||||
|
if(next == read || next == '=')
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken($"{(char)read}{(char)next}"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken(read));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '{':
|
||||||
|
case '}':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
case '(':
|
||||||
|
case ')':
|
||||||
|
case '.':
|
||||||
|
case '?':
|
||||||
|
case ':':
|
||||||
|
case ',':
|
||||||
|
case ';':
|
||||||
|
FlushBuilder();
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken(read));
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
FlushBuilder();
|
||||||
|
if(next == read || next == '>')
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken($"{(char)read}{(char)next}"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_tokens.Add(LexToken.FromGeneralToken(read));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case ' ':
|
||||||
|
case '\n':
|
||||||
|
case '\t':
|
||||||
|
case '\r':
|
||||||
|
FlushBuilder();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
b.Append((char)read);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
FlushBuilder();
|
||||||
|
return _tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class MemberFunctionCallNode : FunctionCallNode
|
||||||
|
{
|
||||||
|
public Node Parent {get;set;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public MemberFunctionCallNode(Node parent, string name, List<Node> args) : base(name,args)
|
||||||
|
{
|
||||||
|
Parent = parent;
|
||||||
|
|
||||||
|
}
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var res=Parent.Execute(nodeEnv);
|
||||||
|
|
||||||
|
var dict = res as TDictionary;
|
||||||
|
var integer = res as TNumber;
|
||||||
|
|
||||||
|
if(dict != null)
|
||||||
|
{
|
||||||
|
var n = dict[Text] as ICallable;
|
||||||
|
if(n != null)
|
||||||
|
{
|
||||||
|
return n.Call(Args.Select<Node,TObject>(e=>e.Execute(nodeEnv)).ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(integer != null)
|
||||||
|
{
|
||||||
|
if(Text == "toString")
|
||||||
|
{
|
||||||
|
return new TString(integer.Value.ToString());
|
||||||
|
}
|
||||||
|
if(Text == "abs")
|
||||||
|
{
|
||||||
|
return new TNumber(Math.Abs(integer.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(Text == "toString") return new TString("");
|
||||||
|
|
||||||
|
return new TUninit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class MemberGetVariableValue : GetVariableValue
|
||||||
|
{
|
||||||
|
public Node Parent {get;set;}
|
||||||
|
public MemberGetVariableValue(Node parent,string text) : base(text)
|
||||||
|
{
|
||||||
|
Parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var res=Parent.Execute(nodeEnv);
|
||||||
|
|
||||||
|
var dict = res as TDictionary;
|
||||||
|
var integer = res as TNumber;
|
||||||
|
var array = res as TArray;
|
||||||
|
if(array != null)
|
||||||
|
{
|
||||||
|
if(Name == "length" || Name == "count")
|
||||||
|
{
|
||||||
|
return new TNumber(array.Items.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(dict != null)
|
||||||
|
{
|
||||||
|
if(dict.MemberExists($"get{Name}"))
|
||||||
|
{
|
||||||
|
var mbm= dict[$"get{Name}"] as ICallable;
|
||||||
|
if(mbm != null)
|
||||||
|
return mbm.Call();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dict.MemberExists(Name))
|
||||||
|
{
|
||||||
|
return dict[Name];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(integer != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TUninit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class ModuloNode : Node
|
||||||
|
{
|
||||||
|
public Node Left {get;set;}
|
||||||
|
public Node Right {get;set;}
|
||||||
|
|
||||||
|
public ModuloNode(Node left, Node right)
|
||||||
|
{
|
||||||
|
this.Left = left;
|
||||||
|
this.Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var l = Left.Execute(nodeEnv) as TNumber;
|
||||||
|
var r = Right.Execute(nodeEnv) as TNumber;
|
||||||
|
|
||||||
|
if(l != null && r != null)
|
||||||
|
return new TNumber(l.Value % r.Value);
|
||||||
|
|
||||||
|
return new TNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class MultiplyNode : Node
|
||||||
|
{
|
||||||
|
public Node Left {get;set;}
|
||||||
|
public Node Right {get;set;}
|
||||||
|
|
||||||
|
public MultiplyNode(Node left, Node right)
|
||||||
|
{
|
||||||
|
this.Left = left;
|
||||||
|
this.Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var l = Left.Execute(nodeEnv) as TNumber;
|
||||||
|
var r = Right.Execute(nodeEnv) as TNumber;
|
||||||
|
|
||||||
|
if(l != null && r != null)
|
||||||
|
return new TNumber(l.Value * r.Value);
|
||||||
|
|
||||||
|
return new TNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public abstract class Node
|
||||||
|
{
|
||||||
|
public abstract TObject Execute(IScopeEnvironment nodeEnv);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,247 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class Parser
|
||||||
|
{
|
||||||
|
|
||||||
|
public Parser()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node ParseExpression(List<LexToken> tokens,ref int i,bool isFirst=false)
|
||||||
|
{
|
||||||
|
if(tokens[i].Text == "{" || isFirst)
|
||||||
|
{
|
||||||
|
if(!isFirst)
|
||||||
|
i++;
|
||||||
|
ScopeNode scopeNode = new ScopeNode();
|
||||||
|
while(i<tokens.Count && tokens[i].Text != "}")
|
||||||
|
{
|
||||||
|
scopeNode.Body.Add(ParseExpression(tokens,ref i));
|
||||||
|
if(i<tokens.Count && tokens[i].Text == ";")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
return scopeNode;
|
||||||
|
}else{
|
||||||
|
return ParseAssignable(tokens,ref i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Node ParseAssignable(List<LexToken> tokens,ref int i)
|
||||||
|
{
|
||||||
|
Node myExpression = ParseSum(tokens,ref i);
|
||||||
|
while(i<tokens.Count && (tokens[i].Text == "="))
|
||||||
|
{
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "=")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
GetVariableValue? gvar = myExpression as GetVariableValue;
|
||||||
|
if(gvar != null)
|
||||||
|
{
|
||||||
|
myExpression= new SetVariableNode(gvar.Name,ParseSum(tokens,ref i));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return myExpression;
|
||||||
|
}
|
||||||
|
private Node ParseSum(List<LexToken> tokens,ref int i)
|
||||||
|
{
|
||||||
|
Node myExpression = ParseFactor(tokens,ref i);
|
||||||
|
while(i<tokens.Count && (tokens[i].Text == "+" || tokens[i].Text == "-"))
|
||||||
|
{
|
||||||
|
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "+"){
|
||||||
|
i++;
|
||||||
|
myExpression = new AddNode(myExpression,ParseFactor(tokens,ref i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "-")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
myExpression = new SubtractNode(myExpression,ParseFactor(tokens,ref i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
return myExpression;
|
||||||
|
}
|
||||||
|
private Node ParseValue(List<LexToken> tokens,ref int i)
|
||||||
|
{
|
||||||
|
var token=tokens[i++];
|
||||||
|
if(token.IsString) return new ConstNode(new TString(token.Text));
|
||||||
|
if(token.IsChar)
|
||||||
|
{
|
||||||
|
return new ConstNode(new TNumber(token.Text.SingleOrDefault()));
|
||||||
|
}
|
||||||
|
|
||||||
|
long val;
|
||||||
|
if(long.TryParse(token.Text,out val))
|
||||||
|
{
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "." && !tokens[i].IsChar && !tokens[i].IsString)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if(i<tokens.Count)
|
||||||
|
{
|
||||||
|
var token2=tokens[i++];
|
||||||
|
double dblR;
|
||||||
|
if(double.TryParse($"{val}.{token2.Text}",out dblR))
|
||||||
|
{
|
||||||
|
return new ConstNode(new TNumber(dblR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return new ConstNode(new TNumber( val ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(i<tokens.Count && tokens[i].Text=="(")
|
||||||
|
{
|
||||||
|
if(token.Text == "func")
|
||||||
|
{
|
||||||
|
List<string> args = new List<string>();
|
||||||
|
i++;
|
||||||
|
while(i<tokens.Count && tokens[i].Text != ")")
|
||||||
|
{
|
||||||
|
|
||||||
|
if(tokens[i].Text == ",") {i++;continue;}
|
||||||
|
|
||||||
|
if(i<tokens.Count)
|
||||||
|
{
|
||||||
|
var exp = ParseExpression(tokens,ref i);
|
||||||
|
var gvExp = exp as GetVariableValue;
|
||||||
|
if(gvExp != null)
|
||||||
|
{
|
||||||
|
args.Add(gvExp.Name);
|
||||||
|
}else{
|
||||||
|
throw new Exception("not a getvariablenode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
return new ClosureNode(args,ParseExpression(tokens,ref i));
|
||||||
|
} else if(token.Text == "if")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
var condition=ParseExpression(tokens,ref i);
|
||||||
|
i++;
|
||||||
|
Node yes = new ConstNode(new TUninit());
|
||||||
|
Node no = new ConstNode(new TUninit());
|
||||||
|
if(i<tokens.Count && tokens[i].Text != "else")
|
||||||
|
yes=ParseExpression(tokens,ref i);
|
||||||
|
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "else")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
no = ParseExpression(tokens,ref i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new IfNode(condition,yes,no);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
i++;
|
||||||
|
List<Node> args = new List<Node>();
|
||||||
|
//function call baby
|
||||||
|
while(i<tokens.Count && tokens[i].Text != ")")
|
||||||
|
{
|
||||||
|
|
||||||
|
if(tokens[i].Text == ",") {i++;continue;}
|
||||||
|
|
||||||
|
if(i<tokens.Count)
|
||||||
|
{
|
||||||
|
args.Add(ParseExpression(tokens,ref i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
var ret = new FunctionCallNode(token.Text,args);
|
||||||
|
while(i<tokens.Count && tokens[i].Text == ".")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
|
||||||
|
var token2 = tokens[i++];
|
||||||
|
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "(")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
args = new List<Node>();
|
||||||
|
//function call baby
|
||||||
|
while(i<tokens.Count && tokens[i].Text != ")")
|
||||||
|
{
|
||||||
|
|
||||||
|
if(tokens[i].Text == ",") {i++;continue;}
|
||||||
|
|
||||||
|
if(i<tokens.Count)
|
||||||
|
{
|
||||||
|
args.Add(ParseExpression(tokens,ref i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
ret = new MemberFunctionCallNode(ret,token2.Text,args);
|
||||||
|
}
|
||||||
|
else if(i<tokens.Count && tokens[i].Text == "[")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
switch(token.Text)
|
||||||
|
{
|
||||||
|
case "null":
|
||||||
|
return new ConstNode(TObject.Null);
|
||||||
|
case "undefined":
|
||||||
|
return new ConstNode(TObject.Uninit);
|
||||||
|
case "true":
|
||||||
|
return new ConstNode(new TNumber(1));
|
||||||
|
case "false":
|
||||||
|
return new ConstNode(new TNumber(0));
|
||||||
|
default:
|
||||||
|
return new GetVariableValue(token.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node ParseFactor(List<LexToken> tokens,ref int i)
|
||||||
|
{
|
||||||
|
Node myExpression = ParseValue(tokens,ref i);
|
||||||
|
while(i<tokens.Count && (tokens[i].Text == "*" || tokens[i].Text == "/" || tokens[i].Text == "%"))
|
||||||
|
{
|
||||||
|
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "*"){
|
||||||
|
i++;
|
||||||
|
myExpression = new MultiplyNode(myExpression,ParseValue(tokens,ref i));
|
||||||
|
}
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "/")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
myExpression = new DivideNode(myExpression,ParseValue(tokens,ref i));
|
||||||
|
}
|
||||||
|
if(i<tokens.Count && tokens[i].Text == "%")
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
myExpression = new ModuloNode(myExpression,ParseValue(tokens,ref i));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return myExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
namespace tlang;
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
|
||||||
|
//Lexer lexer = new Lexer("testString.tlang");
|
||||||
|
Parser parser = new Parser();
|
||||||
|
//parser.Add(lexer.Tokens);
|
||||||
|
int r=0;
|
||||||
|
RootEnvironment env=new RootEnvironment();
|
||||||
|
env["mol"] = new TNumber(42);
|
||||||
|
env["printargs"] = new TExternalMethod((args2)=>{
|
||||||
|
foreach(var arg in args2)
|
||||||
|
{
|
||||||
|
Console.WriteLine(arg);
|
||||||
|
}
|
||||||
|
return new TNumber(args2.Length);
|
||||||
|
});
|
||||||
|
env["int"] = new TExternalMethod((args2)=>{
|
||||||
|
|
||||||
|
if(args2.Length == 1)
|
||||||
|
{
|
||||||
|
var arg = args2[0];
|
||||||
|
var sArg = arg as TString;
|
||||||
|
var dArg = arg as TNumber;
|
||||||
|
if(sArg != null)
|
||||||
|
{
|
||||||
|
long val;
|
||||||
|
if(long.TryParse(sArg.Value,out val))
|
||||||
|
{
|
||||||
|
return new TNumber(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dArg != null)
|
||||||
|
{
|
||||||
|
return new TNumber(Math.Round(dArg.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return TObject.Null;
|
||||||
|
});
|
||||||
|
|
||||||
|
env["filecreate"]=new TExternalMethod((args2)=>{
|
||||||
|
|
||||||
|
if(args2.Length == 1)
|
||||||
|
{
|
||||||
|
var fileName = args2[0] as TString;
|
||||||
|
if(fileName != null)
|
||||||
|
{
|
||||||
|
return new TInternalObject(File.Create(fileName.Value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new TNull();
|
||||||
|
});
|
||||||
|
env["streamwritestr"]=new TExternalMethod((args2)=>{
|
||||||
|
if(args2.Length == 2)
|
||||||
|
{
|
||||||
|
var internalObj = args2[0] as TInternalObject;
|
||||||
|
if(internalObj != null)
|
||||||
|
{
|
||||||
|
var strm = internalObj.Object as Stream;
|
||||||
|
if(strm != null)
|
||||||
|
{
|
||||||
|
var str = args2[1] as TString;
|
||||||
|
if(str != null)
|
||||||
|
{
|
||||||
|
var bytes=System.Text.Encoding.UTF8.GetBytes(str.Value);
|
||||||
|
strm.Write(bytes,0,bytes.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TObject.Null;
|
||||||
|
});
|
||||||
|
env["streamclose"]=new TExternalMethod((args2)=>{
|
||||||
|
if(args2.Length == 1)
|
||||||
|
{
|
||||||
|
var internalObj = args2[0] as TInternalObject;
|
||||||
|
if(internalObj != null)
|
||||||
|
{
|
||||||
|
var strm = internalObj.Object as Stream;
|
||||||
|
if(strm != null)
|
||||||
|
{
|
||||||
|
strm.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TObject.Null;
|
||||||
|
});
|
||||||
|
|
||||||
|
Lexer lexer =new Lexer(new StreamReader("file.tlang"));
|
||||||
|
var res=parser.ParseExpression(lexer.Tokens,ref r,true).Execute(env);
|
||||||
|
r=0;
|
||||||
|
Console.WriteLine(res);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public interface IScopeEnvironment : IEnumerable<KeyValuePair<string,TObject>>
|
||||||
|
{
|
||||||
|
bool VariableExists(string name);
|
||||||
|
void SetVariable(string name,TObject obj);
|
||||||
|
TObject GetVariable(string names);
|
||||||
|
|
||||||
|
IScopeEnvironment SubEnv {get;}
|
||||||
|
|
||||||
|
IScopeEnvironment RootEnv {get;}
|
||||||
|
|
||||||
|
TObject this[string variable] {get;set;}
|
||||||
|
}
|
||||||
|
public class SubEnvironment : IScopeEnvironment
|
||||||
|
{
|
||||||
|
Dictionary<string,TObject> items = new Dictionary<string, TObject>();
|
||||||
|
|
||||||
|
IScopeEnvironment root;
|
||||||
|
IScopeEnvironment parent;
|
||||||
|
|
||||||
|
public SubEnvironment(IScopeEnvironment root,IScopeEnvironment parent)
|
||||||
|
{
|
||||||
|
this.root=root;
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TObject this[string variable] { get => GetVariable(variable); set => SetVariable(variable,value); }
|
||||||
|
|
||||||
|
public IScopeEnvironment SubEnv => new SubEnvironment(root,this);
|
||||||
|
|
||||||
|
public IScopeEnvironment RootEnv => root;
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<string, TObject>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return getVars().GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<KeyValuePair<string,TObject>> getVars()
|
||||||
|
{
|
||||||
|
foreach(var v in parent)
|
||||||
|
{
|
||||||
|
yield return v;
|
||||||
|
}
|
||||||
|
foreach(var item in items)
|
||||||
|
{
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TObject GetVariable(string name)
|
||||||
|
{
|
||||||
|
if(parent.VariableExists(name))
|
||||||
|
{
|
||||||
|
return parent[name];
|
||||||
|
}
|
||||||
|
if(items.ContainsKey(name))
|
||||||
|
{
|
||||||
|
return items[name];
|
||||||
|
}
|
||||||
|
return TObject.Uninit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetVariable(string name, TObject obj)
|
||||||
|
{
|
||||||
|
if(parent.VariableExists(name))
|
||||||
|
{
|
||||||
|
parent.SetVariable(name,obj);
|
||||||
|
}else if(items.ContainsKey(name))
|
||||||
|
{
|
||||||
|
items[name] = obj;
|
||||||
|
}else{
|
||||||
|
items.Add(name,obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VariableExists(string name)
|
||||||
|
{
|
||||||
|
if(parent.VariableExists(name)) return true;
|
||||||
|
return items.ContainsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return getVars().GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class RootEnvironment : IScopeEnvironment
|
||||||
|
{
|
||||||
|
Dictionary<string,TObject> items = new Dictionary<string, TObject>();
|
||||||
|
|
||||||
|
public IScopeEnvironment SubEnv => new SubEnvironment(this,this);
|
||||||
|
|
||||||
|
public IScopeEnvironment RootEnv => this;
|
||||||
|
|
||||||
|
public IEnumerator<KeyValuePair<string, TObject>> GetEnumerator()
|
||||||
|
{
|
||||||
|
return items.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TObject GetVariable(string name)
|
||||||
|
{
|
||||||
|
if(items.ContainsKey(name))
|
||||||
|
{
|
||||||
|
return items[name];
|
||||||
|
}else{
|
||||||
|
return TObject.Uninit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetVariable(string name, TObject obj)
|
||||||
|
{
|
||||||
|
if(items.ContainsKey(name))
|
||||||
|
{
|
||||||
|
items[name] = obj;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
items.Add(name,obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VariableExists(string name)
|
||||||
|
{
|
||||||
|
return items.ContainsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return items.GetEnumerator();
|
||||||
|
}
|
||||||
|
public TObject this[string variable] { get => GetVariable(variable); set => SetVariable(variable,value); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class ScopeNode : Node
|
||||||
|
{
|
||||||
|
public List<Node> Body {get;set;}= new List<Node>();
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var sub = nodeEnv.SubEnv;
|
||||||
|
TObject obj=new TNull();
|
||||||
|
foreach(var item in Body)
|
||||||
|
{
|
||||||
|
obj=item.Execute(sub);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
internal class SubtractNode : Node
|
||||||
|
{
|
||||||
|
public Node Left {get;set;}
|
||||||
|
public Node Right {get;set;}
|
||||||
|
|
||||||
|
public SubtractNode(Node left, Node right)
|
||||||
|
{
|
||||||
|
this.Left = left;
|
||||||
|
this.Right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||||
|
{
|
||||||
|
var l = Left.Execute(nodeEnv) as TNumber;
|
||||||
|
var r = Right.Execute(nodeEnv) as TNumber;
|
||||||
|
|
||||||
|
if(l != null && r != null)
|
||||||
|
return new TNumber(l.Value - r.Value);
|
||||||
|
|
||||||
|
return new TNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TArray : TObject
|
||||||
|
{
|
||||||
|
public TArray()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TObject> Items {get;set;}=new List<TObject>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TDictionary : TObject
|
||||||
|
{
|
||||||
|
public TDictionary()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<string,TObject> items {get;set;}=new Dictionary<string, TObject>();
|
||||||
|
|
||||||
|
public TObject GetMember(string name)
|
||||||
|
{
|
||||||
|
if(items.ContainsKey(name))
|
||||||
|
{
|
||||||
|
return items[name];
|
||||||
|
}else{
|
||||||
|
return TObject.Uninit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMember(string name, TObject obj)
|
||||||
|
{
|
||||||
|
if(items.ContainsKey(name))
|
||||||
|
{
|
||||||
|
items[name] = obj;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
items.Add(name,obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MemberExists(string name)
|
||||||
|
{
|
||||||
|
return items.ContainsKey(name);
|
||||||
|
}
|
||||||
|
public TObject this[string variable] { get => GetMember(variable); set => SetMember(variable,value); }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TInternalObject : TObject
|
||||||
|
{
|
||||||
|
public TInternalObject(object val)
|
||||||
|
{
|
||||||
|
Object=val;
|
||||||
|
}
|
||||||
|
public object Object {get;set;}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TInternalMethod : TObject, ICallable
|
||||||
|
{
|
||||||
|
public TInternalMethod(ClosureNode node,IScopeEnvironment env)
|
||||||
|
{
|
||||||
|
Body = node;
|
||||||
|
Environment = env;
|
||||||
|
}
|
||||||
|
public ClosureNode Body {get;set;}
|
||||||
|
public IScopeEnvironment Environment {get;set;}
|
||||||
|
public TObject Call(params TObject[] args)
|
||||||
|
{
|
||||||
|
var env=Environment.SubEnv;
|
||||||
|
int argCountClosure = Body.Arguments.Count;
|
||||||
|
int argCountCaller = args.Length;
|
||||||
|
if(argCountCaller < requiredArguments())
|
||||||
|
{
|
||||||
|
throw new Exception("not enough arguments");
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
for(;i<optionalArgs(args.Length);i++)
|
||||||
|
{
|
||||||
|
env[Body.Arguments[i].TrimStart('.')] = args[i];
|
||||||
|
}
|
||||||
|
if(i==Body.Arguments.Count-1)
|
||||||
|
{
|
||||||
|
var tarray = new TArray();
|
||||||
|
env[Body.Arguments[i].TrimStart('.')] =tarray;
|
||||||
|
for(int j = i;j<args.Length;j++)
|
||||||
|
{
|
||||||
|
tarray.Items.Add(args[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Body.Node.Execute(env);
|
||||||
|
}
|
||||||
|
private int optionalArgs(int argLen)
|
||||||
|
{
|
||||||
|
for(int i =0;i<Body.Arguments.Count;i++)
|
||||||
|
{
|
||||||
|
if(Body.Arguments[i].StartsWith("..."))
|
||||||
|
{
|
||||||
|
return Math.Min(argLen,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Math.Min(argLen,Body.Arguments.Count);
|
||||||
|
}
|
||||||
|
private int requiredArguments()
|
||||||
|
{
|
||||||
|
for(int i =0;i<Body.Arguments.Count;i++)
|
||||||
|
{
|
||||||
|
if(Body.Arguments[i].StartsWith('.'))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Body.Arguments.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public class TExternalMethod : TObject,ICallable
|
||||||
|
{
|
||||||
|
Func<TObject[],TObject> cb;
|
||||||
|
public TExternalMethod(Func<TObject[],TObject> func)
|
||||||
|
{
|
||||||
|
cb = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TObject Call(params TObject[] args)
|
||||||
|
{
|
||||||
|
return cb(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ICallable
|
||||||
|
{
|
||||||
|
TObject Call(params TObject[] args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TNull : TObject
|
||||||
|
{
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TNumber : TObject
|
||||||
|
{
|
||||||
|
public double Value {get;set;}
|
||||||
|
public TNumber(double number)
|
||||||
|
{
|
||||||
|
Value = number;
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TObject
|
||||||
|
{
|
||||||
|
|
||||||
|
public static TObject Uninit => new TUninit();
|
||||||
|
public static TObject Null => new TNull();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TString : TObject
|
||||||
|
{
|
||||||
|
public string Value {get;set;}
|
||||||
|
public TString(string text)
|
||||||
|
{
|
||||||
|
Value = text;
|
||||||
|
}
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace tlang
|
||||||
|
{
|
||||||
|
public class TUninit : TObject
|
||||||
|
{
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "undefined";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
/*
|
||||||
|
if(expression) expression else expression
|
||||||
|
*/
|
||||||
|
|
||||||
|
j = func() 42-43;
|
||||||
|
|
||||||
|
printargs(j().abs());
|
|
@ -0,0 +1,7 @@
|
||||||
|
var s1="Some \"Some String\" Is Cool";
|
||||||
|
var s2="My String Is Awesome";
|
||||||
|
var s3="Demi\nLovato";
|
||||||
|
|
||||||
|
var main = (args)=>{
|
||||||
|
ret 0;
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
Loading…
Reference in New Issue