using System.Net; using System.Net.Sockets; using System.Text; namespace langtest { public class ExpressionStream : Stream { Expression read,write,setpos,getpos,getlen,canread,canwrite,canseek,flush,destroy; IApplicationState state; public ExpressionStream(IApplicationState state,Expression read,Expression write,Expression setpos,Expression getpos,Expression getlen,Expression canread,Expression canwrite,Expression canseek,Expression flush,Expression destroy) { this.read =read; this.write =canwrite; this.setpos = setpos; this.getpos = getpos; this.getlen =getlen; this.canread = canread; this.canwrite = canwrite; this.canseek = canseek; this.destroy=destroy; this.state = state; this.flush = flush; } public override bool CanRead => canread.Evaluate(state) > 0; public override bool CanSeek => canseek.Evaluate(state) > 0; public override bool CanWrite => canwrite.Evaluate(state) > 0; public override long Length => getlen.Evaluate(state); private void _setLen(long len) { var newSc = state.NewScope(); newSc.SetVariable("stream_length_value",len); setpos.Evaluate(newSc); } public override long Position { get => getlen.Evaluate(state); set => _setLen(value); } public override void Flush() { flush.Execute(state); } public override int Read(byte[] buffer, int offset, int count) { var box=state.CreateBox(count); var newSc = state.NewScope(); newSc.SetVariable("stream_count_value",count); newSc.SetVariable("stream_buffer",box); int read=(int)setpos.Evaluate(newSc); //sorry for this inefficency but this is kind of a toy lang and my first one to finish for(int i = 0;i variables=new Dictionary(); public long GetBoxValue(long bId, int index) { return state.GetBoxValue(bId,index); } public long GetVariable(string name) { if(!name.StartsWith("cur.") && state.HasVariable(name)) { return state.GetVariable(name); }else{ if(variables.ContainsKey(name)) { return variables[name]; } } return 0; } public bool HasVariable(string name) { return variables.ContainsKey(name) || (!name.StartsWith("cur.") && state.HasVariable(name)); } public IApplicationState NewScope() { return new SubscopeApplicationState(this); } public void SetVariable(string name, long value) { if(!name.StartsWith("cur.") && state.HasVariable(name)) { state.SetVariable(name,value); }else{ if(variables.ContainsKey(name)) { variables[name]=value; }else{ variables.Add(name,value); } } } public void ClearBox(long bId) { state.ClearBox(bId); } public void AddToBox(long bId, long value) { state.AddToBox(bId,value); } public void RemoveFromBox(long bId, long value) { state.RemoveFromBox(bId,value); } public void RemoveAtFromBox(long bId, int index) { state.RemoveAtFromBox(bId,index); } public void InsertToBox(long bId, int index, long value) { state.InsertToBox(bId,index,value); } public void SetBoxValue(long bId, int index, long value) { state.SetBoxValue(bId,index,value); } public long BoxLength(long boxId) { return state.BoxLength(boxId); } public long CreateBox(string text,bool permanent=false) { return state.CreateBox(text,permanent); } public string BoxToString(long boxId) { return state.BoxToString(boxId); } public long ExecuteFunction(string str, List expressions) { return state.ExecuteFunction(str,expressions); } public bool HasFunction(string str) { return state.HasFunction(str); } public void AddFunction(string str, List args, Expression exp) { state.AddFunction(str,args,exp); } public long CreateFile(long boxId) { return state.CreateFile(boxId); } public long OpenReadFile(long boxId) { return state.OpenReadFile(boxId); } public void CopyStream(long strmSrc, long strmDest) { state.CopyStream(strmSrc,strmDest); } public void CloseStream(long streamId) { state.CloseStream(streamId); } public void WriteToStream(long streamId, long boxId, long offset, long len) { state.WriteToStream(streamId,boxId,offset,len); } public long ReadFromStream(long streamId, long boxId, long offset, long len) { return state.ReadFromStream(streamId,boxId,offset,len); } public void SetStreamPosition(long streamId, long streamPos) { state.SetStreamPosition(streamId,streamPos); } public long GetStreamPosition(long streamId) { return state.GetStreamPosition(streamId); } public long GetStreamLength(long streamId) { return state.GetStreamLength(streamId); } public bool CanRead(long streamId) { return state.CanRead(streamId); } public bool CanWrite(long streamId) { return state.CanWrite(streamId); } public bool CanSeek(long streamId) { return state.CanSeek(streamId); } public long OpenWriteFile(long boxId) { return state.OpenWriteFile(boxId); } public long OpenReadWriteFile(long boxId) { return state.OpenReadWriteFile(boxId); } public long CreateStream(Stream strm) { return state.CreateStream(strm); } public long e2n(Expression e) { return state.e2n(e); } public Expression Calln(long e) { return state.Calln(e); } public void FlushStream(long stream) { state.FlushStream(stream); } public void DestroyBox(long id) { state.DestroyBox(id); } } public class ApplicationState : IApplicationState { static long CID = 0; private long _id = CID++; public long Id {get{return _id;}} public long NoStreams=0; public long NoBoxes = 0; public long NoExpressions=0; public Dictionary expressions = new Dictionary(); public Dictionary param,Expression expression)> methods=new Dictionary param, Expression expression)>(); public Dictionary streams=new Dictionary(); public Dictionary variables=new Dictionary(); public Dictionary,bool perm )> boxes = new Dictionary data,bool perm)>(); public Expression Calln(long e) { if(expressions.ContainsKey(e)) { return expressions[e]; } return new ConstantNumber("0"); } public long e2n(Expression e) { long eId = NoExpressions++; expressions.Add(eId,e); return eId; } public string BoxToString(long boxId) { StringBuilder bu= new StringBuilder(); if(!boxes.ContainsKey(boxId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[boxId].Item1; foreach(var item in b) { char c = (char)(item % char.MaxValue); bu.Append(c); } } return bu.ToString(); } public long CreateBox(int boxLen=0) { long i=NoBoxes++; boxes.Add(i,(new List(boxLen),false)); return i; } public void DestroyBox(long boxId) { if(!boxes.ContainsKey(boxId)) return; if(!boxes[boxId].perm) { boxes[boxId].Item1.Clear(); boxes.Remove(boxId); } } public long CreateStream(Stream strm) { long i = NoStreams++; streams.Add(i,strm); return i; } public long GetBoxValue(long bId, int index) { if(!boxes.ContainsKey(bId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[bId]; if(index > b.Item1.Count) { throw new IndexOutOfRangeException(); }else{ return b.Item1[index]; } } } public void SetBoxValue(long bId,int index,long value) { if(value > int.MaxValue) throw new ArgumentOutOfRangeException("value > int.maxvalue"); if(!boxes.ContainsKey(bId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[bId]; if(b.perm) throw new ArgumentException("Cant manipulate read only value"); if(index > b.Item1.Count) { throw new IndexOutOfRangeException(); }else{ b.Item1[index] = value; } } } public bool HasVariable(string name) { return variables.ContainsKey(name); } public virtual long GetVariable(string name) { if(variables.ContainsKey(name)) { //create_method(a,b,c,d,{}) return variables[name]; }else{ return 0; } } public IApplicationState NewScope() { return new SubscopeApplicationState(this); } public virtual void SetVariable(string name, long value) { if(variables.ContainsKey(name)) { variables[name]=value; }else{ variables.Add(name,value); } } public void ClearBox(long bId) { if(!boxes.ContainsKey(bId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[bId]; if(b.perm) throw new ArgumentException("Cant manipulate read only value"); b.Item1.Clear(); } } public void AddToBox(long bId, long value) { if(!boxes.ContainsKey(bId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[bId]; if(b.perm) throw new ArgumentException("Cant manipulate read only value"); b.Item1.Add(value); } } public void RemoveFromBox(long bId, long value) { if(!boxes.ContainsKey(bId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[bId]; if(b.perm) throw new ArgumentException("Cant manipulate read only value"); b.Item1.Remove(value); } } public void RemoveAtFromBox(long bId, int index) { if(!boxes.ContainsKey(bId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[bId]; if(b.perm) throw new ArgumentException("Cant manipulate read only value"); b.Item1.RemoveAt(index); } } public void InsertToBox(long bId, int index, long value) { if(!boxes.ContainsKey(bId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[bId]; if(b.perm) throw new ArgumentException("Cant manipulate read only value"); b.Item1.Insert(index,value); } } public long BoxLength(long boxId) { if(!boxes.ContainsKey(boxId)) { throw new Exception("Box does not exist"); }else{ var b = boxes[boxId]; return b.Item1.Count; } } public long ExecuteFunction(string str,List expressions) { if(!HasFunction(str)) return 0; var func=methods[str]; var res=NewScope(); for(int i = 0;i(text.Select((e)=>{return e;})),permanent)); return i; } public bool HasFunction(string str) { return methods.ContainsKey(str); } public void AddFunction(string str, List args, Expression exp) { if(!HasFunction(str)) { methods.Add(str,(args,exp)); } } public long CreateFile(long boxId) { string filename=BoxToString(boxId); return CreateStream(File.Create(filename)); } public long OpenReadFile(long boxId) { string filename=BoxToString(boxId); return CreateStream(File.OpenRead(filename)); } private Stream GetStream(long strmId) { if(!streams.ContainsKey(strmId)) throw new Exception("No stream with specified id"); return streams[strmId]; } public void CopyStream(long strmSrc, long strmDest) { GetStream(strmSrc).CopyTo(GetStream(strmDest)); } public void CloseStream(long streamId) { if(!streams.ContainsKey(streamId)) return; GetStream(streamId).Dispose(); streams.Remove(streamId); } public void WriteToStream(long streamId, long boxId, long offset, long len) { List box = boxes[boxId].Item1; byte[] data=box.Skip((int)offset).Take((int)len).Select((e)=>{ return (byte)(e % 256); }).ToArray(); GetStream(streamId).Write(data,0,data.Length); } public long ReadFromStream(long streamId, long boxId, long offset, long len) { var bo = boxes[boxId]; if(bo.perm) return 0; List box = boxes[boxId].Item1; len = Math.Min(len,box.Count - offset); byte[] data=new byte[len]; int read=GetStream(streamId).Read(data,0,(int)len); for(int i =0;i expressions); bool HasFunction(string str); void AddFunction(string str,List args,Expression exp); string BoxToString(long boxId); void ClearBox(long bId); void AddToBox(long bId,long value); void RemoveFromBox(long bId,long value); void RemoveAtFromBox(long bId,int index); void InsertToBox(long bId,int index,long value); void SetBoxValue(long bId,int index,long value); void SetVariable(string name,long value); long GetVariable(string name); long BoxLength(long boxId); long CreateBox(int len=0); long CreateBox(string text,bool permanent=false); long GetBoxValue(long bId, int index); bool HasVariable(string name); IApplicationState NewScope(); } public static class Ast { public static void Parse(ListNode node,List tokens) { int i = 0; ParseNode(node,tokens,ref i,true); } public static ListNode Parse(List tokens) { int i = 0; ListNode node=new ListNode(); ParseNode(node,tokens,ref i,true); return node; } public static void ParseNode(ListNode node,List tokens,ref int i,bool root=false) { node.Root=root; //i = 0 //0 //func() while(i tokens,ref int i) { Expression res= ParseTerm(tokens,ref i); while(i < tokens.Count && (tokens[i].Type == LexTokenType.PLUS || tokens[i].Type == LexTokenType.MINUS)) { if(i < tokens.Count && tokens[i].Type == LexTokenType.PLUS) { i++; res = new AddNode(res,ParseTerm(tokens,ref i)); } if(i < tokens.Count && tokens[i].Type == LexTokenType.MINUS) { i++; res = new MinusNode(res,ParseTerm(tokens,ref i)); } } return res; } private static Expression ParseTerm(List tokens,ref int i) { Expression res= ParseFactor(tokens,ref i); while(i < tokens.Count && (tokens[i].Type == LexTokenType.MULTIPLY || tokens[i].Type == LexTokenType.DIVIDE || tokens[i].Type == LexTokenType.MOD)) { if(i < tokens.Count && tokens[i].Type == LexTokenType.MULTIPLY) { i++; res = new MultiplyNode(res,ParseFactor(tokens,ref i)); } if(i < tokens.Count && tokens[i].Type == LexTokenType.DIVIDE) { i++; res = new DivideNode(res,ParseFactor(tokens,ref i)); } if(i < tokens.Count && tokens[i].Type == LexTokenType.MOD) { i++; res = new ModulusNode(res,ParseFactor(tokens,ref i)); } } return res; } private static Expression ParseFactor(List tokens,ref int i) { if(i>=tokens.Count) throw new ArgumentOutOfRangeException("i>=tokens.Count"); var token = tokens[i]; if(token.Type == LexTokenType.LPAREN) { i++; var res = ParseExpression(tokens,ref i); if(i>=tokens.Count) throw new ArgumentOutOfRangeException("i>=tokens.Count"); if(tokens[i].Type != LexTokenType.RPAREN) throw new ArgumentException("tokens[i].Type != RPAREN"); i++; return res; } if(token.Type == LexTokenType.LBRACE) { i++; ListNode res=new ListNode(); ParseNode(res,tokens,ref i,false); if(i>=tokens.Count) throw new ArgumentOutOfRangeException("i>=tokens.Count"); if(tokens[i].Type != LexTokenType.RBRACE) throw new ArgumentException("tokens[i].Type != RBRACE"); i++; return res; } if(token.Type == LexTokenType.IDENTIFER) { i++; if(i funcArgs = new List(); //check whether its args i++; while(i -1) return boxId; boxId = state.CreateBox(text,true); return boxId; } } public class ConstantNumber : Expression { long num; public ConstantNumber(string num) { if(!long.TryParse(num,out this.num)) { this.num=0; } } public override long Evaluate(IApplicationState state) { return num; } } public class SetVariableNode : Node { Expression e; string vname; public SetVariableNode(Expression expression,string varName) { this.e=expression; this.vname = varName; } public override void Execute(IApplicationState state) { var v =e.Evaluate(state); state.SetVariable(vname,v); } } public class FunctionCallNode : Expression { string name; List expressions; public FunctionCallNode(string name,List expressions) { this.name=name; this.expressions=expressions; } public override long Evaluate(IApplicationState state) { if(name == "gt") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) > expressions[1].Evaluate(state) ? 1 : 0; } else if(name == "gte") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) >= expressions[1].Evaluate(state) ? 1 : 0; }else if(name == "lt") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) < expressions[1].Evaluate(state) ? 1 : 0; }else if(name == "lte") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) <= expressions[1].Evaluate(state) ? 1 : 0; } else if(name == "eq") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) == expressions[1].Evaluate(state) ? 1 : 0; } else if(name == "not") { if(expressions.Count < 1) throw new Exception("need two param"); return expressions[0].Evaluate(state) != 0 ? 0 : 1; }else if(name == "xor") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) ^ expressions[1].Evaluate(state); }else if(name == "bor") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) | expressions[1].Evaluate(state); }else if(name == "cor") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) != 0 || expressions[1].Evaluate(state) != 0 ? 1 : 0; }else if(name == "band") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) & expressions[1].Evaluate(state); }else if(name == "cand") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) != 0 && expressions[1].Evaluate(state) != 0 ? 1 : 0; }else if(name == "lshift") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) << (int) expressions[1].Evaluate(state); }else if(name == "rshift") { if(expressions.Count < 2) throw new Exception("need two param"); return expressions[0].Evaluate(state) >> (int) expressions[1].Evaluate(state); } if(name == "printint") { foreach(var exp in expressions) { Console.WriteLine(exp.Evaluate(state)); } }else if(name == "printchars") { foreach(var exp in expressions) { char res = (char)(exp.Evaluate(state) % char.MaxValue); Console.Write(res); } } else if(name == "tcp_client") { Expression listenIp = expressions[0]; Expression listenPort = expressions[1]; TcpClient clt=new TcpClient(state.BoxToString(listenIp.Evaluate(state)),(int)listenPort.Evaluate(state)); var strm=clt.GetStream(); return state.CreateStream(strm); } else if(name == "tcp_server") { Expression listenIp = expressions[0]; Expression listenPort = expressions[1]; VariableGetValueNode? stream_name = expressions[2] as VariableGetValueNode; Expression exp = expressions[3]; if(stream_name == null) throw new Exception("You must use identifier at positional arg #3 (starting from 1)"); string name = stream_name.Name; //tcpserver("0.0.0.0",4202,strm,{}) TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Parse(state.BoxToString(listenIp.Evaluate(state))),(int)listenPort.Evaluate(state))); listener.Start(); while(true) { var clt= listener.AcceptTcpClient(); NetworkStream stream = clt.GetStream(); var s=state.NewScope(); long str =s.CreateStream(stream); s.SetVariable(name,str); exp.Execute(s); s.CloseStream(str); } }else if(name == "clear") { Console.Clear(); }else if(name == "exit") { if(expressions.Count == 0){ Environment.Exit(0); }else{ int i = (int)(expressions[0].Evaluate(state) % int.MaxValue); Environment.Exit(i); } }else if(name == "for") { if(expressions.Count < 4) throw new Exception("Need variable, max, incrementer, scope"); //for(i,30,i+1,) VariableGetValueNode? vgvn = expressions[0] as VariableGetValueNode; if(vgvn == null) throw new Exception("Not get value node"); string variableName = vgvn.Name; long max= expressions[1].Evaluate(state); Expression increment = expressions[2]; Expression runInFor = expressions[3]; for(;state.GetVariable(variableName) < max; state.SetVariable(variableName,increment.Evaluate(state))) { runInFor.Execute(state); } }else if(name == "if") { //if(condition,truth,false) if(expressions.Count < 3) throw new Exception("Need condition, true, false, hint use 0 to not use true or false"); Expression condition = expressions[0]; Expression truth = expressions[1]; Expression falsey = expressions[2]; if(condition.Evaluate(state) != 0) { truth.Execute(state); }else{ falsey.Execute(state); } }else if(name == "e2n") { if(expressions.Count > 0) { return state.e2n(expressions[0]); } throw new Exception("I need an expression"); }else if(name == "calln") { if(expressions.Count > 0) { return state.Calln(expressions[0].Evaluate(state)).Evaluate(state); } throw new Exception("I need a number"); } else if(name == "box_create") { if(expressions.Count > 0) { long esize = expressions[0].Evaluate(state); if(esize > int.MaxValue) throw new ArgumentOutOfRangeException("size > int.maxvalue"); int size = (int)esize; return state.CreateBox(size); } return state.CreateBox(); }else if(name == "box_getvalue") { if(expressions.Count < 2) throw new Exception("Need box id and index"); long bId = expressions[0].Evaluate(state); long eindex = expressions[1].Evaluate(state); if(eindex > int.MaxValue) throw new ArgumentOutOfRangeException("index > int.maxvalue"); int index = (int)eindex; return state.GetBoxValue(bId,index); }else if(name == "box_setvalue") { if(expressions.Count < 3) throw new Exception("Need box id and index and value"); long bId = expressions[0].Evaluate(state); long eindex = expressions[1].Evaluate(state); if(eindex > int.MaxValue) throw new ArgumentOutOfRangeException("index > max.value"); int index = (int)eindex; long value = expressions[2].Evaluate(state); state.SetBoxValue(bId,index,value); } else if(name == "box_print") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); Console.Write(state.BoxToString(bId)); }else if(name == "box_println") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); Console.WriteLine(state.BoxToString(bId)); } else if(name == "box_len") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); return state.BoxLength(bId); }else if(name == "box_add") { if(expressions.Count < 2)throw new Exception("Need box id and value"); long bId = expressions[0].Evaluate(state); long value = expressions[1].Evaluate(state); state.AddToBox(bId,value); }else if(name == "box_remove") { if(expressions.Count < 2)throw new Exception("Need box id and value"); long bId = expressions[0].Evaluate(state); long value = expressions[1].Evaluate(state); state.RemoveFromBox(bId,value); }else if(name == "box_clear") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); state.ClearBox(bId); } else if(name == "file_create") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); return state.CreateFile(bId); }else if(name == "file_open_read") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); return state.OpenReadFile(bId); }else if(name == "file_open_write") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); return state.OpenWriteFile(bId); } else if(name == "file_open_readwrite") { if(expressions.Count < 1)throw new Exception("Need box id"); long bId = expressions[0].Evaluate(state); return state.OpenReadWriteFile(bId); } else if(name == "stream_copy") { if(expressions.Count < 2)throw new Exception("Need src and dest streamid"); long sId1= expressions[0].Evaluate(state); long sId2 = expressions[1].Evaluate(state); state.CopyStream(sId1,sId2); } else if(name == "stream_read") { if(expressions.Count < 4)throw new Exception("Need stream id and box id and offset and length"); long sId = expressions[0].Evaluate(state); long bId = expressions[1].Evaluate(state); long offset = expressions[2].Evaluate(state); long len = expressions[3].Evaluate(state); return state.ReadFromStream(sId,bId,offset,len); } else if(name == "stream_write") { if(expressions.Count < 4)throw new Exception("Need stream id and box id and offset and length"); long sId = expressions[0].Evaluate(state); long bId = expressions[1].Evaluate(state); long offset = expressions[2].Evaluate(state); long len = expressions[3].Evaluate(state); state.WriteToStream(sId,bId,offset,len); }else if(name == "stream_close") { if(expressions.Count < 1)throw new Exception("Need stream id"); long sId = expressions[0].Evaluate(state); state.CloseStream(sId); } else if(name == "create_function") { if(expressions.Count < 2) throw new Exception("Need at least a name and body"); //create_function(function_name,arg0,arg1,arg2,scope) VariableGetValueNode? vgvn = expressions[0] as VariableGetValueNode; List args=new List(); if(vgvn == null) throw new Exception("Name must be identifier"); for(int i = 1;i int.MaxValue) throw new ArgumentOutOfRangeException("index > int.maxvalue"); int index = (int)eindex; long value = expressions[2].Evaluate(state); state.InsertToBox(bId,index,value); }else if(name == "box_removeat") { if(expressions.Count < 2)throw new Exception("Need box id and index"); long bId = expressions[0].Evaluate(state); long eindex = expressions[1].Evaluate(state); if(eindex > int.MaxValue) throw new ArgumentOutOfRangeException("index > int.maxvalue"); int index = (int)eindex; state.RemoveAtFromBox(bId,index); } else if(name == "stream_create") { if(expressions.Count < 10)throw new Exception("Need box stream read, write,setpos,getpos,getlen,canread,canwrite,canseek,flush,destroy"); var cstrm=new ExpressionStream(state,expressions[0],expressions[1],expressions[2],expressions[3],expressions[4],expressions[5],expressions[6],expressions[7],expressions[8],expressions[9]); return state.CreateStream(cstrm); } else if(name == "stream_flush") { if(expressions.Count < 1) throw new Exception("Need stream id"); state.FlushStream(expressions[0].Evaluate(state)); } else if(name == "box_readline") { string? text = Console.ReadLine(); if(string.IsNullOrWhiteSpace(text)) text=""; state.CreateBox(text); }else if(name == "readchar") { return Console.Read(); }else if(name == "mean") { long v=0; foreach(var exp in expressions) { v += exp.Evaluate(state); } v /= expressions.Count; return v; }else if(state.HasFunction(name)) { return state.ExecuteFunction(name,expressions); } return 0; } } public class VariableGetValueNode : Expression { public string Name {get{return var;}} string var; public VariableGetValueNode(string var) { this.var=var; } public override long Evaluate(IApplicationState state) { return state.GetVariable(var); } } public class AddNode : Expression { public AddNode(Expression left,Expression right) { Left=left; Right = right; } public Expression? Left; public Expression? Right; public override long Evaluate(IApplicationState state) { if(Left != null && Right != null) { return Left.Evaluate(state) + Right.Evaluate(state); } return 0; } } public class MinusNode : Expression { public MinusNode(Expression left,Expression right) { Left=left; Right = right; } public Expression? Left; public Expression? Right; public override long Evaluate(IApplicationState state) { if(Left != null && Right != null) { return Left.Evaluate(state) - Right.Evaluate(state); } return 0; } } public class MultiplyNode : Expression { public MultiplyNode(Expression left,Expression right) { Left=left; Right = right; } public Expression? Left; public Expression? Right; public override long Evaluate(IApplicationState state) { if(Left != null && Right != null) { return Left.Evaluate(state) * Right.Evaluate(state); } return 0; } } public class DivideNode : Expression { public DivideNode(Expression left,Expression right) { Left=left; Right = right; } public Expression? Left; public Expression? Right; public override long Evaluate(IApplicationState state) { if(Left != null && Right != null) { return Left.Evaluate(state) / Right.Evaluate(state); } return 0; } } public class ModulusNode : Expression { public ModulusNode(Expression left,Expression right) { Left=left; Right = right; } public Expression? Left; public Expression? Right; public override long Evaluate(IApplicationState state) { if(Left != null && Right != null) { return Left.Evaluate(state) % Right.Evaluate(state); } return 0; } } public abstract class Expression : Node { public abstract long Evaluate(IApplicationState state); public override void Execute(IApplicationState state) { Evaluate(state); } } public abstract class Node { public override string ToString() { StringBuilder b=new StringBuilder(); var t=GetType(); foreach(var p in t.GetProperties()) { b.AppendLine($"{p.Name}:\n{TabOver(p.GetValue(this))}"); } return b.ToString(); } private string TabOver(object? p) { StringBuilder b=new StringBuilder(); string? j = p?.ToString(); if(string.IsNullOrWhiteSpace(j)) j =""; foreach(var ln in j.Split(Environment.NewLine)) { b.AppendLine($"\t{ln}"); } return b.ToString(); } public abstract void Execute(IApplicationState state); } public class ListNode : Expression { public bool Root {get;set;} public List Nodes = new List(); public override long Evaluate(IApplicationState state) { var s = Root ? state : state.NewScope(); long res=0; foreach(var node in Nodes) { Expression? e = node as Expression; if(e != null) { res=e.Evaluate(s); } else{ node.Execute(s); } } return res; } } }