Minimum Viable Product
This commit is contained in:
parent
b74fd1d083
commit
fd57d7998c
15
AddNode.cs
15
AddNode.cs
|
@ -19,6 +19,19 @@ namespace tlang
|
|||
var rNum = r as TNumber;
|
||||
var lStr = l as TString;
|
||||
var rStr = r as TString;
|
||||
var dleft = l as TDictionary;
|
||||
|
||||
if(dleft != null)
|
||||
{
|
||||
if(dleft.MemberExists("add"))
|
||||
{
|
||||
var mbm = dleft["add"] as ICallable;
|
||||
if(mbm != null)
|
||||
{
|
||||
return mbm.Call(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(lNum != null && rNum != null)
|
||||
|
@ -31,6 +44,8 @@ namespace tlang
|
|||
if(lNum != null && rStr != null)
|
||||
return new TString(lNum.Value.ToString() + rStr.Value);
|
||||
|
||||
|
||||
|
||||
return new TNull();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
namespace tlang
|
||||
{
|
||||
internal class ArraySubscriptNode : MemberGetVariableValue
|
||||
{
|
||||
public Node Argument {get;set;}
|
||||
|
||||
public ArraySubscriptNode(Node parent, string text, Node arg) : base(parent,text)
|
||||
{
|
||||
|
||||
Argument = arg;
|
||||
}
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var arg = Argument.Execute(nodeEnv);
|
||||
var p=Parent.Execute(nodeEnv);
|
||||
var dict = p as TDictionary;
|
||||
var ls = p as TArray;
|
||||
var str = p as TString;
|
||||
if(dict != null)
|
||||
{
|
||||
var sArg = arg as TString;
|
||||
var at = dict["at"] as ICallable;
|
||||
|
||||
if(at != null)
|
||||
{
|
||||
return at.Call(arg);
|
||||
}
|
||||
|
||||
if(sArg != null)
|
||||
{
|
||||
|
||||
return dict[sArg.Value];
|
||||
}
|
||||
}
|
||||
if(ls != null)
|
||||
{
|
||||
var nArg = arg as TNumber;
|
||||
if(nArg != null && nArg.Value < ls.Items.Count)
|
||||
{
|
||||
return ls.Items[(int)nArg.Value];
|
||||
}
|
||||
}
|
||||
if(str != null)
|
||||
{
|
||||
var nArg = arg as TNumber;
|
||||
if(nArg != null && nArg.Value < str.Value.Length)
|
||||
{
|
||||
return new TChar(str.Value[(int)nArg.Value]);
|
||||
}
|
||||
}
|
||||
return TObject.Uninit;
|
||||
}
|
||||
public override void SetValue(IScopeEnvironment nodeEnv, TObject value)
|
||||
{
|
||||
var arg = Argument.Execute(nodeEnv);
|
||||
var p=Parent.Execute(nodeEnv);
|
||||
var dict = p as TDictionary;
|
||||
var ls = p as TArray;
|
||||
var str = p as TString;
|
||||
if(dict != null)
|
||||
{
|
||||
var sArg = arg as TString;
|
||||
var at = dict["setAt"] as ICallable;
|
||||
|
||||
if(at != null)
|
||||
{
|
||||
at.Call(arg,value);
|
||||
}
|
||||
else
|
||||
if(sArg != null)
|
||||
{
|
||||
|
||||
dict[sArg.Value] = value;
|
||||
}
|
||||
}
|
||||
if(ls != null)
|
||||
{
|
||||
var nArg = arg as TNumber;
|
||||
if(nArg != null && nArg.Value < ls.Items.Count)
|
||||
{
|
||||
ls.Items[(int)nArg.Value] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,11 +13,26 @@ namespace tlang
|
|||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var l = Left.Execute(nodeEnv) as TNumber;
|
||||
var r = Right.Execute(nodeEnv) as TNumber;
|
||||
var l = Left.Execute(nodeEnv);
|
||||
var r = Right.Execute(nodeEnv);
|
||||
var lnum = l as TNumber;
|
||||
var rnum = r as TNumber;
|
||||
var dleft = l as TDictionary;
|
||||
|
||||
if(l != null && r != null)
|
||||
return new TNumber(l.Value / r.Value);
|
||||
if(dleft != null)
|
||||
{
|
||||
if(dleft.MemberExists("divide"))
|
||||
{
|
||||
var mbm = dleft["divide"] as ICallable;
|
||||
if(mbm != null)
|
||||
{
|
||||
return mbm.Call(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lnum != null && rnum != null)
|
||||
return new TNumber(lnum.Value / rnum.Value);
|
||||
|
||||
return new TNull();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
namespace tlang
|
||||
{
|
||||
public class EachLoop : Node
|
||||
{
|
||||
public GetVariableValue Name {get;set;}
|
||||
public Node List {get;set;}
|
||||
public Node Body {get;set;}
|
||||
|
||||
public EachLoop(GetVariableValue name, Node ls,Node body)
|
||||
{
|
||||
Name = name;
|
||||
List = ls;
|
||||
Body=body;
|
||||
}
|
||||
private IEnumerable<TObject> CreateItterator(IScopeEnvironment env,TObject ls)
|
||||
{
|
||||
var dict = ls as TDictionary;
|
||||
var str = ls as TString;
|
||||
var array = ls as TArray;
|
||||
if(dict!= null)
|
||||
{
|
||||
var gIttrVar = dict["ittr"] as TDictionary;
|
||||
var gIttrProp = dict["getIttr"] as ICallable;
|
||||
|
||||
if(gIttrProp != null)
|
||||
{
|
||||
var myObj= gIttrProp.Call() as TDictionary;
|
||||
if(myObj != null)
|
||||
{
|
||||
var reset = myObj["reset"] as ICallable;
|
||||
var moveNext = myObj["movenext"] as ICallable;
|
||||
var getCurrent = myObj["getCurrent"] as ICallable;
|
||||
if(reset != null) reset.Call();
|
||||
if(moveNext != null)
|
||||
while(moveNext.Call().AsBoolean)
|
||||
{
|
||||
if(getCurrent != null)
|
||||
{
|
||||
yield return getCurrent.Call();
|
||||
}
|
||||
else
|
||||
{
|
||||
var current = myObj["current"];
|
||||
yield return current;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(array != null)
|
||||
{
|
||||
foreach(var item in array.Items)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
else if(str != null)
|
||||
{
|
||||
foreach(var c in str.Value)
|
||||
{
|
||||
yield return new TChar(c);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var env = nodeEnv.SubEnv;
|
||||
var ls = List.Execute(env);
|
||||
bool isRunning=true;
|
||||
env["last_ittr"]= new TExternalMethod((args)=>{
|
||||
isRunning=false;
|
||||
return new TNumber(1);
|
||||
});
|
||||
TObject last = TObject.Uninit;
|
||||
|
||||
var enumerator=CreateItterator(env,ls).GetEnumerator();
|
||||
while(isRunning && enumerator.MoveNext())
|
||||
{
|
||||
Name.SetValue(env,enumerator.Current);
|
||||
Body.Execute(env);
|
||||
}
|
||||
|
||||
|
||||
return last;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
namespace tlang
|
||||
{
|
||||
internal class ForLoop : Node
|
||||
{
|
||||
public Node Init {get;set;}
|
||||
public Node Condition {get;set;}
|
||||
public Node Increment {get;set;}
|
||||
public Node Body {get;set;}
|
||||
|
||||
public ForLoop(Node init, Node condition, Node inc, Node body)
|
||||
{
|
||||
Init = init;
|
||||
Condition = condition;
|
||||
Increment = inc;
|
||||
Body = body;
|
||||
}
|
||||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var env = nodeEnv.SubEnv;
|
||||
bool isRunning=true;
|
||||
env["last_ittr"]= new TExternalMethod((args)=>{
|
||||
isRunning=false;
|
||||
return new TNumber(1);
|
||||
});
|
||||
Init.Execute(env);
|
||||
TObject obj=new TUninit();
|
||||
while(Condition.Execute(env).AsBoolean && isRunning)
|
||||
{
|
||||
obj=Body.Execute(env);
|
||||
Increment.Execute(env);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,19 +3,20 @@ namespace tlang
|
|||
internal class SetVariableNode : Node
|
||||
{
|
||||
public Node Value {get;set;}
|
||||
public string Name {get;set;}
|
||||
public SetVariableNode(string text,Node v)
|
||||
public GetVariableValue Name {get;set;}
|
||||
public SetVariableNode(GetVariableValue gvn,Node v)
|
||||
{
|
||||
Name=text;
|
||||
Name=gvn;
|
||||
Value=v;
|
||||
}
|
||||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var res=Value.Execute(nodeEnv);
|
||||
nodeEnv[Name]=res;
|
||||
Name.SetValue(nodeEnv,res);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
public class GetVariableValue : Node
|
||||
{
|
||||
|
@ -30,5 +31,9 @@ namespace tlang
|
|||
{
|
||||
return nodeEnv[Name];
|
||||
}
|
||||
public virtual void SetValue(IScopeEnvironment nodeEnv,TObject value)
|
||||
{
|
||||
nodeEnv[Name] = value;
|
||||
}
|
||||
}
|
||||
}
|
14
IfNode.cs
14
IfNode.cs
|
@ -16,19 +16,13 @@ namespace tlang
|
|||
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);
|
||||
|
||||
|
||||
|
||||
return condition.AsBoolean ? Yes.Execute(nodeEnv) : No.Execute(nodeEnv);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,9 @@ namespace tlang
|
|||
|
||||
var dict = res as TDictionary;
|
||||
var integer = res as TNumber;
|
||||
|
||||
var str = res as TString;
|
||||
var chr = res as TChar;
|
||||
var array = res as TArray;
|
||||
if(dict != null)
|
||||
{
|
||||
var n = dict[Text] as ICallable;
|
||||
|
@ -25,6 +27,74 @@ namespace tlang
|
|||
{
|
||||
return n.Call(Args.Select<Node,TObject>(e=>e.Execute(nodeEnv)).ToArray());
|
||||
}
|
||||
}else if(chr != null)
|
||||
{
|
||||
if(Text == "toUpper")
|
||||
{
|
||||
return new TChar(char.ToUpper(chr.Value));
|
||||
}
|
||||
if(Text == "toLower")
|
||||
{
|
||||
return new TChar(char.ToLower(chr.Value));
|
||||
}
|
||||
if(Text == "toString")
|
||||
{
|
||||
return new TString(chr.Value.ToString());
|
||||
}
|
||||
if(Text == "toNumber")
|
||||
{
|
||||
return new TNumber(chr.Value);
|
||||
}
|
||||
}
|
||||
else if(array != null)
|
||||
{
|
||||
if(Text == "add")
|
||||
{
|
||||
if(Args.Count == 1)
|
||||
{
|
||||
TObject obj = Args[0].Execute(nodeEnv);
|
||||
array.Items.Add(obj);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
if(Text == "at")
|
||||
{
|
||||
//at(index)
|
||||
if(Args.Count == 1)
|
||||
{
|
||||
var index=Args[0].Execute(nodeEnv) as TNumber;
|
||||
if(index != null)
|
||||
{
|
||||
if(index.Value < array.Items.Count)
|
||||
return array.Items[(int)index.Value];
|
||||
}
|
||||
}
|
||||
}
|
||||
if(Text == "setAt")
|
||||
{
|
||||
TObject value = TObject.Null;
|
||||
|
||||
//setAt(index,value)
|
||||
//setAt(index) //null
|
||||
if(Args.Count == 2)
|
||||
{
|
||||
value=Args[1].Execute(nodeEnv);
|
||||
}
|
||||
if(Args.Count > 0)
|
||||
{
|
||||
var index=Args[0].Execute(nodeEnv) as TNumber;
|
||||
if(index != null)
|
||||
{
|
||||
if(index.Value < array.Items.Count)
|
||||
array.Items[(int)index.Value]=value;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if(Text == "length" || Text == "count")
|
||||
{
|
||||
return new TNumber(array.Items.Count);
|
||||
}
|
||||
}
|
||||
else if(integer != null)
|
||||
{
|
||||
|
@ -36,6 +106,79 @@ namespace tlang
|
|||
{
|
||||
return new TNumber(Math.Abs(integer.Value));
|
||||
}
|
||||
if(Text == "toChar")
|
||||
{
|
||||
return new TChar((char)integer.Value);
|
||||
}
|
||||
}else if(str != null)
|
||||
{
|
||||
if(Text == "replace")
|
||||
{
|
||||
//todo fill this method out
|
||||
}
|
||||
if(Text == "split")
|
||||
{
|
||||
//todo fill this method out
|
||||
//str.Value.Split(,,StringSplitOptions.TrimEntries);
|
||||
}
|
||||
if(Text == "startsWith")
|
||||
{
|
||||
string val = " ";
|
||||
if(Args.Count > 0){
|
||||
var firstArg = Args[0].Execute(nodeEnv);
|
||||
var c = firstArg as TChar;
|
||||
var mystr = firstArg as TString;
|
||||
var mynum = firstArg as TNumber;
|
||||
if(c!=null) val = c.Value.ToString();
|
||||
if(mystr != null) val = mystr.Value.ToString();
|
||||
if(mynum != null) val = mynum.Value.ToString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return new TNumber(str.Value.StartsWith(val) ? 1 : 0);
|
||||
|
||||
}
|
||||
if(Text == "trimStart")
|
||||
{
|
||||
if(Args.Count == 0)
|
||||
{
|
||||
return new TString(str.Value.TrimStart());
|
||||
}else{
|
||||
|
||||
return new TString(str.Value.TrimStart(Args.Select<Node,char>(n=>{
|
||||
var nV=n.Execute(nodeEnv) as TChar;
|
||||
if(nV != null)
|
||||
{
|
||||
return nV.Value;
|
||||
}
|
||||
return ' ';
|
||||
}).ToArray()));
|
||||
}
|
||||
}
|
||||
if(Text == "trimEnd")
|
||||
{
|
||||
//trimend()
|
||||
if(Args.Count == 0)
|
||||
{
|
||||
return new TString(str.Value.TrimEnd());
|
||||
}else{
|
||||
|
||||
return new TString(str.Value.TrimEnd(Args.Select<Node,char>(n=>{
|
||||
var nV=n.Execute(nodeEnv) as TChar;
|
||||
if(nV != null)
|
||||
{
|
||||
return nV.Value;
|
||||
}
|
||||
return ' ';
|
||||
}).ToArray()));
|
||||
}
|
||||
}
|
||||
if(Text == "toString")
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,4 +187,6 @@ namespace tlang
|
|||
return new TUninit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -7,7 +7,26 @@ namespace tlang
|
|||
{
|
||||
Parent = parent;
|
||||
}
|
||||
public override void SetValue(IScopeEnvironment nodeEnv, TObject value)
|
||||
{
|
||||
var res=Parent.Execute(nodeEnv);
|
||||
var dict = res as TDictionary;
|
||||
if(dict != null)
|
||||
{
|
||||
if(dict.MemberExists($"set{Name}"))
|
||||
{
|
||||
var mbm= dict[$"set{Name}"] as ICallable;
|
||||
if(mbm != null)
|
||||
{
|
||||
mbm.Call(value);
|
||||
}
|
||||
|
||||
}else{
|
||||
dict[Name] = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var res=Parent.Execute(nodeEnv);
|
||||
|
@ -15,6 +34,8 @@ namespace tlang
|
|||
var dict = res as TDictionary;
|
||||
var integer = res as TNumber;
|
||||
var array = res as TArray;
|
||||
var str = res as TString;
|
||||
|
||||
if(array != null)
|
||||
{
|
||||
if(Name == "length" || Name == "count")
|
||||
|
@ -41,8 +62,36 @@ namespace tlang
|
|||
|
||||
if(integer != null)
|
||||
{
|
||||
|
||||
if(Name == "abs")
|
||||
{
|
||||
return new TNumber(Math.Abs(integer.Value));
|
||||
}
|
||||
if(Name == "int")
|
||||
{
|
||||
return new TNumber(Math.Round(integer.Value));
|
||||
}
|
||||
}
|
||||
if(str != null)
|
||||
{
|
||||
|
||||
if(Name == "number")
|
||||
{
|
||||
|
||||
}
|
||||
if(Name == "ittr")
|
||||
{
|
||||
|
||||
}
|
||||
if(Name == "length" || Name == "count")
|
||||
{
|
||||
return new TNumber(str.Value.Length);
|
||||
}
|
||||
if(Name == "list")
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return new TUninit();
|
||||
}
|
||||
|
|
|
@ -13,11 +13,26 @@ namespace tlang
|
|||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var l = Left.Execute(nodeEnv) as TNumber;
|
||||
var r = Right.Execute(nodeEnv) as TNumber;
|
||||
var l = Left.Execute(nodeEnv);
|
||||
var r = Right.Execute(nodeEnv);
|
||||
var lnum = l as TNumber;
|
||||
var rnum = r as TNumber;
|
||||
var dleft = l as TDictionary;
|
||||
|
||||
if(l != null && r != null)
|
||||
return new TNumber(l.Value % r.Value);
|
||||
if(dleft != null)
|
||||
{
|
||||
if(dleft.MemberExists("mod"))
|
||||
{
|
||||
var mbm = dleft["mod"] as ICallable;
|
||||
if(mbm != null)
|
||||
{
|
||||
return mbm.Call(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lnum != null && rnum != null)
|
||||
return new TNumber(lnum.Value % rnum.Value);
|
||||
|
||||
return new TNull();
|
||||
}
|
||||
|
|
|
@ -13,11 +13,26 @@ namespace tlang
|
|||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var l = Left.Execute(nodeEnv) as TNumber;
|
||||
var r = Right.Execute(nodeEnv) as TNumber;
|
||||
var l = Left.Execute(nodeEnv);
|
||||
var r = Right.Execute(nodeEnv);
|
||||
var lnum = l as TNumber;
|
||||
var rnum = r as TNumber;
|
||||
var dleft = l as TDictionary;
|
||||
|
||||
if(l != null && r != null)
|
||||
return new TNumber(l.Value * r.Value);
|
||||
if(dleft != null)
|
||||
{
|
||||
if(dleft.MemberExists("times"))
|
||||
{
|
||||
var mbm = dleft["times"] as ICallable;
|
||||
if(mbm != null)
|
||||
{
|
||||
return mbm.Call(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lnum != null && rnum != null)
|
||||
return new TNumber(lnum.Value * rnum.Value);
|
||||
|
||||
return new TNull();
|
||||
}
|
||||
|
|
263
Parser.cs
263
Parser.cs
|
@ -10,11 +10,12 @@ namespace tlang
|
|||
|
||||
public Node ParseExpression(List<LexToken> tokens,ref int i,bool isFirst=false)
|
||||
{
|
||||
if(i>= tokens.Count) return new ConstNode(new TNumber(0));
|
||||
if(tokens[i].Text == "{" || isFirst)
|
||||
{
|
||||
if(!isFirst)
|
||||
i++;
|
||||
ScopeNode scopeNode = new ScopeNode();
|
||||
ScopeNode scopeNode = new ScopeNode(){First=isFirst};
|
||||
while(i<tokens.Count && tokens[i].Text != "}")
|
||||
{
|
||||
scopeNode.Body.Add(ParseExpression(tokens,ref i));
|
||||
|
@ -41,7 +42,7 @@ namespace tlang
|
|||
GetVariableValue? gvar = myExpression as GetVariableValue;
|
||||
if(gvar != null)
|
||||
{
|
||||
myExpression= new SetVariableNode(gvar.Name,ParseSum(tokens,ref i));
|
||||
myExpression= new SetVariableNode(gvar,ParseSum(tokens,ref i));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +78,7 @@ namespace tlang
|
|||
if(token.IsString) return new ConstNode(new TString(token.Text));
|
||||
if(token.IsChar)
|
||||
{
|
||||
return new ConstNode(new TNumber(token.Text.SingleOrDefault()));
|
||||
return new ConstNode(new TChar(token.Text.SingleOrDefault()));
|
||||
}
|
||||
|
||||
long val;
|
||||
|
@ -126,7 +127,78 @@ namespace tlang
|
|||
}
|
||||
i++;
|
||||
return new ClosureNode(args,ParseExpression(tokens,ref i));
|
||||
} else if(token.Text == "if")
|
||||
}
|
||||
else if(token.Text == "for")
|
||||
{
|
||||
i++;
|
||||
//init;condition;inc)
|
||||
|
||||
Node init = new ConstNode(new TUninit());
|
||||
Node condition = new ConstNode(new TUninit());
|
||||
Node inc = new ConstNode(new TUninit());
|
||||
Node body = new ConstNode(new TUninit());
|
||||
if(i<tokens.Count && (tokens[i].Text != ")" || tokens[i].Text != ";"))
|
||||
{
|
||||
init = ParseExpression(tokens,ref i);
|
||||
}
|
||||
if(i<tokens.Count && tokens[i].Text == ";")
|
||||
i++;
|
||||
if(i<tokens.Count && (tokens[i].Text != ")" || tokens[i].Text != ";"))
|
||||
{
|
||||
condition = ParseExpression(tokens,ref i);
|
||||
}
|
||||
if(i<tokens.Count && tokens[i].Text == ";")
|
||||
i++;
|
||||
if(i<tokens.Count && (tokens[i].Text != ")" || tokens[i].Text != ";"))
|
||||
{
|
||||
inc = ParseExpression(tokens,ref i);
|
||||
}
|
||||
if(i<tokens.Count && tokens[i].Text == ")")
|
||||
i++;
|
||||
if(i<tokens.Count)
|
||||
body = ParseExpression(tokens,ref i);
|
||||
|
||||
return new ForLoop(init,condition,inc,body);
|
||||
}
|
||||
else if(token.Text == "each")
|
||||
{
|
||||
i++;
|
||||
Node ls = ParseExpression(tokens,ref i);
|
||||
GetVariableValue? name = new GetVariableValue("item");
|
||||
if(i<tokens.Count && tokens[i].Text == ":")
|
||||
{
|
||||
i++;
|
||||
var n=ls as GetVariableValue;
|
||||
if(n != null) name = n;
|
||||
ls = ParseExpression(tokens,ref i);
|
||||
}
|
||||
i++;
|
||||
if(i<tokens.Count)
|
||||
{
|
||||
return new EachLoop(name,ls,ParseExpression(tokens,ref i));
|
||||
}
|
||||
}
|
||||
else if(token.Text == "while")
|
||||
{
|
||||
i++;
|
||||
var condition=ParseExpression(tokens,ref i);
|
||||
i++;
|
||||
Node yes = new ConstNode(new TUninit());
|
||||
if(i<tokens.Count && tokens[i].Text != ";")
|
||||
yes = ParseExpression(tokens,ref i);
|
||||
return new WhileLoop(condition,yes,false);
|
||||
}
|
||||
else if(token.Text == "do")
|
||||
{
|
||||
i++;
|
||||
var condition=ParseExpression(tokens,ref i);
|
||||
i++;
|
||||
Node yes = new ConstNode(new TUninit());
|
||||
if(i<tokens.Count && tokens[i].Text != ";")
|
||||
yes = ParseExpression(tokens,ref i);
|
||||
return new WhileLoop(condition,yes,true);
|
||||
}
|
||||
else if(token.Text == "if")
|
||||
{
|
||||
i++;
|
||||
var condition=ParseExpression(tokens,ref i);
|
||||
|
@ -160,7 +232,15 @@ namespace tlang
|
|||
|
||||
}
|
||||
i++;
|
||||
var ret = new FunctionCallNode(token.Text,args);
|
||||
Node ret = new FunctionCallNode(token.Text,args);
|
||||
while(i<tokens.Count && tokens[i].Text == "[")
|
||||
{
|
||||
|
||||
i++;
|
||||
var arg = ParseExpression(tokens,ref i);
|
||||
i++;
|
||||
ret = new ArraySubscriptNode(ret,token.Text,arg);
|
||||
}
|
||||
while(i<tokens.Count && tokens[i].Text == ".")
|
||||
{
|
||||
i++;
|
||||
|
@ -171,7 +251,7 @@ namespace tlang
|
|||
{
|
||||
i++;
|
||||
args = new List<Node>();
|
||||
//function call baby
|
||||
//function call baby
|
||||
while(i<tokens.Count && tokens[i].Text != ")")
|
||||
{
|
||||
|
||||
|
@ -188,30 +268,125 @@ namespace tlang
|
|||
}
|
||||
else if(i<tokens.Count && tokens[i].Text == "[")
|
||||
{
|
||||
|
||||
i++;
|
||||
var arg = ParseExpression(tokens,ref i);
|
||||
i++;
|
||||
ret = new ArraySubscriptNode(ret,token2.Text,arg);
|
||||
}
|
||||
else{
|
||||
|
||||
ret = new MemberGetVariableValue(ret,token2.Text);
|
||||
}
|
||||
|
||||
}
|
||||
if(i<tokens.Count && tokens[i].Text == "++")
|
||||
{
|
||||
var mgvn = ret as GetVariableValue;
|
||||
i++;
|
||||
if(mgvn != null)
|
||||
{
|
||||
return new PostfixIncrementVariableNode(mgvn);
|
||||
}
|
||||
|
||||
}
|
||||
if(i<tokens.Count && tokens[i].Text == "--")
|
||||
{
|
||||
var mgvn = ret as GetVariableValue;
|
||||
i++;
|
||||
if(mgvn != null)
|
||||
{
|
||||
return new PostfixDecrementVariableNode(mgvn);
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}else{
|
||||
Node ret;
|
||||
switch(token.Text)
|
||||
{
|
||||
case "null":
|
||||
return new ConstNode(TObject.Null);
|
||||
ret= new ConstNode(TObject.Null);
|
||||
break;
|
||||
case "undefined":
|
||||
return new ConstNode(TObject.Uninit);
|
||||
ret= new ConstNode(TObject.Uninit);
|
||||
break;
|
||||
case "true":
|
||||
return new ConstNode(new TNumber(1));
|
||||
ret= new ConstNode(new TNumber(1));
|
||||
break;
|
||||
case "false":
|
||||
return new ConstNode(new TNumber(0));
|
||||
ret= new ConstNode(new TNumber(0));
|
||||
break;
|
||||
default:
|
||||
return new GetVariableValue(token.Text);
|
||||
ret= new GetVariableValue(token.Text);
|
||||
break;
|
||||
}
|
||||
while(i<tokens.Count && tokens[i].Text == "[")
|
||||
{
|
||||
|
||||
i++;
|
||||
var arg = ParseExpression(tokens,ref i);
|
||||
i++;
|
||||
ret = new ArraySubscriptNode(ret,token.Text,arg);
|
||||
}
|
||||
|
||||
while(i<tokens.Count && tokens[i].Text == ".")
|
||||
{
|
||||
i++;
|
||||
|
||||
var token2 = tokens[i++];
|
||||
|
||||
if(i<tokens.Count && tokens[i].Text == "(")
|
||||
{
|
||||
i++;
|
||||
var 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 == "[")
|
||||
{
|
||||
i++;
|
||||
var arg = ParseExpression(tokens,ref i);
|
||||
i++;
|
||||
ret = new ArraySubscriptNode(ret,token2.Text,arg);
|
||||
}
|
||||
else{
|
||||
ret = new MemberGetVariableValue(ret,token2.Text);
|
||||
}
|
||||
|
||||
}
|
||||
if(i<tokens.Count && tokens[i].Text == "++")
|
||||
{
|
||||
var mgvn = ret as GetVariableValue;
|
||||
i++;
|
||||
if(mgvn != null)
|
||||
{
|
||||
return new PostfixIncrementVariableNode(mgvn);
|
||||
}
|
||||
|
||||
}
|
||||
if(i<tokens.Count && tokens[i].Text == "--")
|
||||
{
|
||||
var mgvn = ret as GetVariableValue;
|
||||
i++;
|
||||
if(mgvn != null)
|
||||
{
|
||||
return new PostfixDecrementVariableNode(mgvn);
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -243,5 +418,67 @@ namespace tlang
|
|||
}
|
||||
return myExpression;
|
||||
}
|
||||
|
||||
public void LoadEnvironment(RootEnvironment env)
|
||||
{
|
||||
TDictionary fs = new TDictionary();
|
||||
|
||||
fs["enumerate_files"] = new TExternalMethod((args)=>{
|
||||
if(args.Length > 0)
|
||||
{
|
||||
var fileName=args[0].ToString();
|
||||
if(!string.IsNullOrWhiteSpace(fileName) && Directory.Exists(fileName))
|
||||
{
|
||||
var dict = new TDictionary();
|
||||
dict["getIttr"] = new TExternalMethod((args2)=>{
|
||||
var enumerable=Directory.EnumerateFiles(fileName).GetEnumerator();
|
||||
TDictionary dict2 = new TDictionary();
|
||||
|
||||
dict2["movenext"] = new TExternalMethod((args3)=>{
|
||||
|
||||
return new TNumber(enumerable.MoveNext() ? 1 : 0);
|
||||
});
|
||||
dict2["getCurrent"] = new TExternalMethod((args3)=>{
|
||||
return new TString(enumerable.Current);
|
||||
});
|
||||
|
||||
return dict2;
|
||||
});
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
return TObject.Null;
|
||||
});
|
||||
|
||||
fs["enumerate_dirs"] = new TExternalMethod((args)=>{
|
||||
if(args.Length > 0)
|
||||
{
|
||||
var fileName=args[0].ToString();
|
||||
if(!string.IsNullOrWhiteSpace(fileName) && Directory.Exists(fileName))
|
||||
{
|
||||
var dict = new TDictionary();
|
||||
dict["getIttr"] = new TExternalMethod((args2)=>{
|
||||
var enumerable=Directory.EnumerateDirectories(fileName).GetEnumerator();
|
||||
TDictionary dict2 = new TDictionary();
|
||||
|
||||
dict2["movenext"] = new TExternalMethod((args3)=>{
|
||||
|
||||
return new TNumber(enumerable.MoveNext() ? 1 : 0);
|
||||
});
|
||||
dict2["getCurrent"] = new TExternalMethod((args3)=>{
|
||||
return new TString(enumerable.Current);
|
||||
});
|
||||
|
||||
return dict2;
|
||||
});
|
||||
return dict;
|
||||
}
|
||||
}
|
||||
return TObject.Null;
|
||||
});
|
||||
env["fs"]=fs;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
namespace tlang
|
||||
{
|
||||
public class PostfixDecrementVariableNode : Node
|
||||
{
|
||||
public GetVariableValue Node {get;set;}
|
||||
|
||||
public PostfixDecrementVariableNode(GetVariableValue ret)
|
||||
{
|
||||
Node = ret;
|
||||
}
|
||||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
|
||||
var obj=Node.Execute(nodeEnv);
|
||||
|
||||
var newVal=new SubtractNode(new ConstNode(obj),new ConstNode(new TNumber(1))).Execute(nodeEnv);
|
||||
|
||||
Node.SetValue(nodeEnv,newVal);
|
||||
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
namespace tlang
|
||||
{
|
||||
public class PostfixIncrementVariableNode : Node
|
||||
{
|
||||
public GetVariableValue Node {get;set;}
|
||||
|
||||
public PostfixIncrementVariableNode(GetVariableValue ret)
|
||||
{
|
||||
Node = ret;
|
||||
}
|
||||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
|
||||
var obj=Node.Execute(nodeEnv);
|
||||
|
||||
var newVal=new AddNode(new ConstNode(obj),new ConstNode(new TNumber(1))).Execute(nodeEnv);
|
||||
|
||||
|
||||
Node.SetValue(nodeEnv,newVal);
|
||||
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
44
Program.cs
44
Program.cs
|
@ -1,7 +1,7 @@
|
|||
namespace tlang;
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
static int Main(string[] args)
|
||||
{
|
||||
|
||||
//Lexer lexer = new Lexer("testString.tlang");
|
||||
|
@ -9,13 +9,27 @@ class Program
|
|||
//parser.Add(lexer.Tokens);
|
||||
int r=0;
|
||||
RootEnvironment env=new RootEnvironment();
|
||||
env["mol"] = new TNumber(42);
|
||||
env["printargs"] = new TExternalMethod((args2)=>{
|
||||
parser.LoadEnvironment(env);
|
||||
env["array"] = new TExternalMethod((args2)=>{
|
||||
return new TArray();
|
||||
});
|
||||
env["dict"] = new TExternalMethod((args2)=>{
|
||||
return new TDictionary();
|
||||
});
|
||||
env["print"] = new TExternalMethod((args2)=>{
|
||||
foreach(var arg in args2)
|
||||
{
|
||||
Console.WriteLine(arg);
|
||||
Console.Write(arg);
|
||||
}
|
||||
return new TNumber(args2.Length);
|
||||
});
|
||||
env["println"] = new TExternalMethod((args2)=>{
|
||||
foreach(var arg in args2)
|
||||
{
|
||||
Console.Write(arg);
|
||||
}
|
||||
Console.WriteLine();
|
||||
return new TNumber(args2.Length);
|
||||
});
|
||||
env["int"] = new TExternalMethod((args2)=>{
|
||||
|
||||
|
@ -90,9 +104,25 @@ class Program
|
|||
});
|
||||
|
||||
Lexer lexer =new Lexer(new StreamReader("file.tlang"));
|
||||
var res=parser.ParseExpression(lexer.Tokens,ref r,true).Execute(env);
|
||||
r=0;
|
||||
Console.WriteLine(res);
|
||||
var res=parser.ParseExpression(lexer.Tokens,ref r,true).Execute(env) as TNumber;
|
||||
var main = env["main"] as ICallable;
|
||||
|
||||
if(main != null)
|
||||
{
|
||||
List<TString> args2=new List<TString>();
|
||||
foreach(var argument in args)
|
||||
{
|
||||
args2.Add(new TString(argument));
|
||||
}
|
||||
res=main.Call(args2.ToArray()) as TNumber;
|
||||
}
|
||||
|
||||
if(res != null)
|
||||
{
|
||||
return (int)res.Value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,10 @@ namespace tlang
|
|||
|
||||
public TObject GetVariable(string name)
|
||||
{
|
||||
if(name == "last_ittr" && items.ContainsKey("last_ittr"))
|
||||
{
|
||||
return items["last_ittr"];
|
||||
}
|
||||
if(parent.VariableExists(name))
|
||||
{
|
||||
return parent[name];
|
||||
|
@ -66,8 +70,9 @@ namespace tlang
|
|||
|
||||
public void SetVariable(string name, TObject obj)
|
||||
{
|
||||
if(parent.VariableExists(name))
|
||||
if(parent.VariableExists(name) && name != "last_ittr")
|
||||
{
|
||||
|
||||
parent.SetVariable(name,obj);
|
||||
}else if(items.ContainsKey(name))
|
||||
{
|
||||
|
|
|
@ -2,10 +2,11 @@ namespace tlang
|
|||
{
|
||||
public class ScopeNode : Node
|
||||
{
|
||||
public bool First {get;set;}
|
||||
public List<Node> Body {get;set;}= new List<Node>();
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var sub = nodeEnv.SubEnv;
|
||||
var sub = First ? nodeEnv : nodeEnv.SubEnv;
|
||||
TObject obj=new TNull();
|
||||
foreach(var item in Body)
|
||||
{
|
||||
|
|
|
@ -13,11 +13,26 @@ namespace tlang
|
|||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
var l = Left.Execute(nodeEnv) as TNumber;
|
||||
var r = Right.Execute(nodeEnv) as TNumber;
|
||||
var l = Left.Execute(nodeEnv);
|
||||
var r = Right.Execute(nodeEnv);
|
||||
var lnum = l as TNumber;
|
||||
var rnum = r as TNumber;
|
||||
var dleft = l as TDictionary;
|
||||
|
||||
if(l != null && r != null)
|
||||
return new TNumber(l.Value - r.Value);
|
||||
if(dleft != null)
|
||||
{
|
||||
if(dleft.MemberExists("sub"))
|
||||
{
|
||||
var mbm = dleft["sub"] as ICallable;
|
||||
if(mbm != null)
|
||||
{
|
||||
return mbm.Call(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(lnum != null && rnum != null)
|
||||
return new TNumber(lnum.Value - rnum.Value);
|
||||
|
||||
return new TNull();
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ namespace tlang
|
|||
{
|
||||
public class TArray : TObject
|
||||
{
|
||||
public override bool AsBoolean => Items.Count > 0;
|
||||
public TArray()
|
||||
{
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
namespace tlang
|
||||
{
|
||||
internal class TChar : TObject
|
||||
{
|
||||
public override bool AsBoolean => Value != '\0';
|
||||
public char Value {get;set;}
|
||||
public TChar(char v)
|
||||
{
|
||||
Value = v;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ namespace tlang
|
|||
{
|
||||
public class TDictionary : TObject
|
||||
{
|
||||
public override bool AsBoolean {get =>true;}
|
||||
public TDictionary()
|
||||
{
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ namespace tlang
|
|||
{
|
||||
public class TInternalObject : TObject
|
||||
{
|
||||
public override bool AsBoolean => true;
|
||||
public TInternalObject(object val)
|
||||
{
|
||||
Object=val;
|
||||
|
|
14
TMethod.cs
14
TMethod.cs
|
@ -2,6 +2,7 @@ namespace tlang
|
|||
{
|
||||
public class TInternalMethod : TObject, ICallable
|
||||
{
|
||||
public override bool AsBoolean => true;
|
||||
public TInternalMethod(ClosureNode node,IScopeEnvironment env)
|
||||
{
|
||||
Body = node;
|
||||
|
@ -21,24 +22,27 @@ namespace tlang
|
|||
int i = 0;
|
||||
for(;i<optionalArgs(args.Length);i++)
|
||||
{
|
||||
env[Body.Arguments[i].TrimStart('.')] = args[i];
|
||||
env[Body.Arguments[i].TrimStart('$')] = args[i];
|
||||
}
|
||||
if(i==Body.Arguments.Count-1)
|
||||
{
|
||||
var tarray = new TArray();
|
||||
env[Body.Arguments[i].TrimStart('.')] =tarray;
|
||||
env[Body.Arguments[i].TrimStart('$')] =tarray;
|
||||
for(int j = i;j<args.Length;j++)
|
||||
{
|
||||
tarray.Items.Add(args[j]);
|
||||
}
|
||||
i = args.Length;
|
||||
}
|
||||
if(i<args.Length)
|
||||
throw new Exception("too many arguments");
|
||||
return Body.Node.Execute(env);
|
||||
}
|
||||
private int optionalArgs(int argLen)
|
||||
{
|
||||
for(int i =0;i<Body.Arguments.Count;i++)
|
||||
{
|
||||
if(Body.Arguments[i].StartsWith("..."))
|
||||
if(Body.Arguments[i].StartsWith("$$"))
|
||||
{
|
||||
return Math.Min(argLen,i);
|
||||
}
|
||||
|
@ -49,7 +53,7 @@ namespace tlang
|
|||
{
|
||||
for(int i =0;i<Body.Arguments.Count;i++)
|
||||
{
|
||||
if(Body.Arguments[i].StartsWith('.'))
|
||||
if(Body.Arguments[i].StartsWith('$'))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
@ -66,6 +70,8 @@ namespace tlang
|
|||
cb = func;
|
||||
}
|
||||
|
||||
public override bool AsBoolean => true;
|
||||
|
||||
public TObject Call(params TObject[] args)
|
||||
{
|
||||
return cb(args);
|
||||
|
|
1
TNull.cs
1
TNull.cs
|
@ -2,6 +2,7 @@ namespace tlang
|
|||
{
|
||||
public class TNull : TObject
|
||||
{
|
||||
public override bool AsBoolean => false;
|
||||
public override string ToString()
|
||||
{
|
||||
return "null";
|
||||
|
|
|
@ -3,6 +3,9 @@ namespace tlang
|
|||
public class TNumber : TObject
|
||||
{
|
||||
public double Value {get;set;}
|
||||
|
||||
public override bool AsBoolean => Value != 0;
|
||||
|
||||
public TNumber(double number)
|
||||
{
|
||||
Value = number;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
namespace tlang
|
||||
{
|
||||
public class TObject
|
||||
public abstract class TObject
|
||||
{
|
||||
|
||||
public abstract bool AsBoolean {get;}
|
||||
public static TObject Uninit => new TUninit();
|
||||
public static TObject Null => new TNull();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ namespace tlang
|
|||
public class TString : TObject
|
||||
{
|
||||
public string Value {get;set;}
|
||||
|
||||
public override bool AsBoolean => Value.Length > 0;
|
||||
|
||||
public TString(string text)
|
||||
{
|
||||
Value = text;
|
||||
|
|
|
@ -2,6 +2,7 @@ namespace tlang
|
|||
{
|
||||
public class TUninit : TObject
|
||||
{
|
||||
public override bool AsBoolean {get=>false;}
|
||||
public override string ToString()
|
||||
{
|
||||
return "undefined";
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
namespace tlang
|
||||
{
|
||||
public class WhileLoop : Node
|
||||
{
|
||||
public Node Condition {get;set;}
|
||||
public Node Body {get;set;}
|
||||
public bool DoLoop {get;set;}
|
||||
|
||||
public WhileLoop(Node condition, Node yes, bool v)
|
||||
{
|
||||
Condition = condition;
|
||||
Body = yes;
|
||||
DoLoop = v;
|
||||
}
|
||||
|
||||
public override TObject Execute(IScopeEnvironment nodeEnv)
|
||||
{
|
||||
bool isRunning=true;
|
||||
var env = nodeEnv.SubEnv;
|
||||
|
||||
env["last_ittr"]= new TExternalMethod((args)=>{
|
||||
isRunning=false;
|
||||
return new TNumber(1);
|
||||
});
|
||||
|
||||
TObject obj=new TUninit();
|
||||
|
||||
if(!DoLoop) isRunning = Condition.Execute(env).AsBoolean;
|
||||
while(isRunning)
|
||||
{
|
||||
|
||||
obj=Body.Execute(env);
|
||||
isRunning = Condition.Execute(env).AsBoolean;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
15
file.tlang
15
file.tlang
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
if(expression) expression else expression
|
||||
*/
|
||||
|
||||
j = func() 42-43;
|
||||
|
||||
printargs(j().abs());
|
||||
each(dir : fs.enumerate_dirs(fs.home))
|
||||
{
|
||||
println(dir);
|
||||
}
|
||||
each(file : fs.enumerate_files(fs.home))
|
||||
{
|
||||
println(file);
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
var s1="Some \"Some String\" Is Cool";
|
||||
var s2="My String Is Awesome";
|
||||
var s3="Demi\nLovato";
|
||||
|
||||
var main = (args)=>{
|
||||
ret 0;
|
||||
};
|
Loading…
Reference in New Issue