From fd57d7998cb5ec8cee879cf554b3c3e11be2182c Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Thu, 9 Mar 2023 17:57:16 -0600 Subject: [PATCH] Minimum Viable Product --- AddNode.cs | 15 ++ ArraySubscriptNode.cs | 86 +++++++++++ DivideNode.cs | 23 ++- EachLoop.cs | 90 +++++++++++ ForLoop.cs | 36 +++++ GetVariableValue.cs | 13 +- IfNode.cs | 12 +- MemberFunctionCallNode.cs | 147 +++++++++++++++++- MemberGetValueNode.cs | 51 +++++- ModuloNode.cs | 23 ++- MultiplyNode.cs | 23 ++- Parser.cs | 265 ++++++++++++++++++++++++++++++-- PostfixDecrementVariableNode.cs | 26 ++++ PostfixIncrementVariableNode.cs | 26 ++++ Program.cs | 44 +++++- ScopeEnvironment.cs | 7 +- ScopeNode.cs | 3 +- SubtractNode.cs | 23 ++- TArray.cs | 1 + TChar.cs | 19 +++ TDictionary.cs | 1 + TInternalObject.cs | 1 + TMethod.cs | 16 +- TNull.cs | 1 + TNumber.cs | 3 + TObject.cs | 4 +- TString.cs | 3 + TUninit.cs | 1 + WhileLoop.cs | 38 +++++ file.tlang | 15 +- testString.tlang | 7 - 31 files changed, 948 insertions(+), 75 deletions(-) create mode 100644 ArraySubscriptNode.cs create mode 100644 EachLoop.cs create mode 100644 ForLoop.cs create mode 100644 PostfixDecrementVariableNode.cs create mode 100644 PostfixIncrementVariableNode.cs create mode 100644 TChar.cs create mode 100644 WhileLoop.cs delete mode 100644 testString.tlang diff --git a/AddNode.cs b/AddNode.cs index 18c949a..e3b5e50 100644 --- a/AddNode.cs +++ b/AddNode.cs @@ -19,8 +19,21 @@ 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) return new TNumber(lNum.Value + rNum.Value); @@ -31,6 +44,8 @@ namespace tlang if(lNum != null && rStr != null) return new TString(lNum.Value.ToString() + rStr.Value); + + return new TNull(); } } diff --git a/ArraySubscriptNode.cs b/ArraySubscriptNode.cs new file mode 100644 index 0000000..9dc2a33 --- /dev/null +++ b/ArraySubscriptNode.cs @@ -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; + } + } + } + } +} \ No newline at end of file diff --git a/DivideNode.cs b/DivideNode.cs index 94728b2..c7ff7e2 100644 --- a/DivideNode.cs +++ b/DivideNode.cs @@ -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(); } diff --git a/EachLoop.cs b/EachLoop.cs new file mode 100644 index 0000000..5072d5a --- /dev/null +++ b/EachLoop.cs @@ -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 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; + } + } +} \ No newline at end of file diff --git a/ForLoop.cs b/ForLoop.cs new file mode 100644 index 0000000..44b2694 --- /dev/null +++ b/ForLoop.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/GetVariableValue.cs b/GetVariableValue.cs index e0b6356..414bee6 100644 --- a/GetVariableValue.cs +++ b/GetVariableValue.cs @@ -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; + } } } \ No newline at end of file diff --git a/IfNode.cs b/IfNode.cs index 0c4ff79..a220f5a 100644 --- a/IfNode.cs +++ b/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); } } } \ No newline at end of file diff --git a/MemberFunctionCallNode.cs b/MemberFunctionCallNode.cs index 182d980..4bd2201 100644 --- a/MemberFunctionCallNode.cs +++ b/MemberFunctionCallNode.cs @@ -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(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(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(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(); } } + + } \ No newline at end of file diff --git a/MemberGetValueNode.cs b/MemberGetValueNode.cs index 2c1fc35..097b206 100644 --- a/MemberGetValueNode.cs +++ b/MemberGetValueNode.cs @@ -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(); } diff --git a/ModuloNode.cs b/ModuloNode.cs index 76c8d4f..424c262 100644 --- a/ModuloNode.cs +++ b/ModuloNode.cs @@ -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(); } diff --git a/MultiplyNode.cs b/MultiplyNode.cs index 6c588fc..3aec5e7 100644 --- a/MultiplyNode.cs +++ b/MultiplyNode.cs @@ -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(); } diff --git a/Parser.cs b/Parser.cs index 1eedfda..5fe961e 100644 --- a/Parser.cs +++ b/Parser.cs @@ -10,11 +10,12 @@ namespace tlang public Node ParseExpression(List 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(); - //function call baby + //function call baby while(i(); + //function call baby + while(i{ + 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; + } + + } } \ No newline at end of file diff --git a/PostfixDecrementVariableNode.cs b/PostfixDecrementVariableNode.cs new file mode 100644 index 0000000..aaf83d6 --- /dev/null +++ b/PostfixDecrementVariableNode.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/PostfixIncrementVariableNode.cs b/PostfixIncrementVariableNode.cs new file mode 100644 index 0000000..0964f55 --- /dev/null +++ b/PostfixIncrementVariableNode.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index 73eb09f..b8ac8f4 100644 --- a/Program.cs +++ b/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 args2=new List(); + 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; } } diff --git a/ScopeEnvironment.cs b/ScopeEnvironment.cs index f2bf78c..6901590 100644 --- a/ScopeEnvironment.cs +++ b/ScopeEnvironment.cs @@ -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)) { diff --git a/ScopeNode.cs b/ScopeNode.cs index 73d29fc..064d2f3 100644 --- a/ScopeNode.cs +++ b/ScopeNode.cs @@ -2,10 +2,11 @@ namespace tlang { public class ScopeNode : Node { + public bool First {get;set;} public List Body {get;set;}= new List(); 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) { diff --git a/SubtractNode.cs b/SubtractNode.cs index 77ef934..80d8024 100644 --- a/SubtractNode.cs +++ b/SubtractNode.cs @@ -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(); } diff --git a/TArray.cs b/TArray.cs index 14a6efd..b44ec9c 100644 --- a/TArray.cs +++ b/TArray.cs @@ -2,6 +2,7 @@ namespace tlang { public class TArray : TObject { + public override bool AsBoolean => Items.Count > 0; public TArray() { diff --git a/TChar.cs b/TChar.cs new file mode 100644 index 0000000..9a0c22f --- /dev/null +++ b/TChar.cs @@ -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(); + } + } + + +} + \ No newline at end of file diff --git a/TDictionary.cs b/TDictionary.cs index efaa9dc..6804d17 100644 --- a/TDictionary.cs +++ b/TDictionary.cs @@ -2,6 +2,7 @@ namespace tlang { public class TDictionary : TObject { + public override bool AsBoolean {get =>true;} public TDictionary() { diff --git a/TInternalObject.cs b/TInternalObject.cs index 8486193..f0737f1 100644 --- a/TInternalObject.cs +++ b/TInternalObject.cs @@ -2,6 +2,7 @@ namespace tlang { public class TInternalObject : TObject { + public override bool AsBoolean => true; public TInternalObject(object val) { Object=val; diff --git a/TMethod.cs b/TMethod.cs index 15f2eb8..80a4bd0 100644 --- a/TMethod.cs +++ b/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 true; + public TObject Call(params TObject[] args) { return cb(args); diff --git a/TNull.cs b/TNull.cs index adc5dcf..8e4b1af 100644 --- a/TNull.cs +++ b/TNull.cs @@ -2,6 +2,7 @@ namespace tlang { public class TNull : TObject { + public override bool AsBoolean => false; public override string ToString() { return "null"; diff --git a/TNumber.cs b/TNumber.cs index 87a46b8..018d531 100644 --- a/TNumber.cs +++ b/TNumber.cs @@ -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; diff --git a/TObject.cs b/TObject.cs index ee68f93..30a6914 100644 --- a/TObject.cs +++ b/TObject.cs @@ -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(); } diff --git a/TString.cs b/TString.cs index f5ecbd6..55ed317 100644 --- a/TString.cs +++ b/TString.cs @@ -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; diff --git a/TUninit.cs b/TUninit.cs index 7b31b5d..14c396e 100644 --- a/TUninit.cs +++ b/TUninit.cs @@ -2,6 +2,7 @@ namespace tlang { public class TUninit : TObject { + public override bool AsBoolean {get=>false;} public override string ToString() { return "undefined"; diff --git a/WhileLoop.cs b/WhileLoop.cs new file mode 100644 index 0000000..3477e36 --- /dev/null +++ b/WhileLoop.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/file.tlang b/file.tlang index 4e686e2..10a4d6a 100644 --- a/file.tlang +++ b/file.tlang @@ -1,7 +1,8 @@ -/* - if(expression) expression else expression -*/ - -j = func() 42-43; - -printargs(j().abs()); \ No newline at end of file +each(dir : fs.enumerate_dirs(fs.home)) +{ + println(dir); +} +each(file : fs.enumerate_files(fs.home)) +{ + println(file); +} \ No newline at end of file diff --git a/testString.tlang b/testString.tlang deleted file mode 100644 index ce9eb0e..0000000 --- a/testString.tlang +++ /dev/null @@ -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; -}; \ No newline at end of file