boxscript-interperter/AST.cs

1509 lines
50 KiB
C#
Raw Normal View History

2022-11-27 02:16:48 +00:00
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<Math.Min(read,count);i++)
{
byte v=(byte)state.GetBoxValue(box,i);
buffer[i+offset] = v;
}
state.DestroyBox(box);
return Math.Min(read,count);
}
public override long Seek(long offset, SeekOrigin origin)
{
long pos = Position;
switch(origin)
{
case SeekOrigin.Begin:
pos=offset;
break;
case SeekOrigin.Current:
pos+=offset;
break;
case SeekOrigin.End:
pos = Length + offset;
break;
}
Position = pos;
return pos;
}
public override void SetLength(long value)
{
}
public override void Write(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);
//sorry for this inefficency but this is kind of a toy lang and my first one to finish
for(int i = 0;i<count;i++)
{
state.AddToBox(box,buffer[i+offset]);
}
setpos.Evaluate(newSc);
state.DestroyBox(box);
}
public override void Close()
{
destroy.Execute(state);
}
}
public class SubscopeApplicationState : IApplicationState
{
static long CID = 0;
private long _id = CID++;
public long Id {get{return _id;}}
IApplicationState state;
public SubscopeApplicationState(IApplicationState state)
{
this.state =state;
}
public long CreateBox(int boxLen=0)
{
return state.CreateBox(boxLen);
}
Dictionary<string,long> variables=new Dictionary<string, long>();
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<Expression> expressions)
{
return state.ExecuteFunction(str,expressions);
}
public bool HasFunction(string str)
{
return state.HasFunction(str);
}
public void AddFunction(string str, List<string> 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<long,Expression> expressions = new Dictionary<long, Expression>();
public Dictionary<string,(List<string> param,Expression expression)> methods=new Dictionary<string, (List<string> param, Expression expression)>();
public Dictionary<long,Stream> streams=new Dictionary<long, Stream>();
public Dictionary<string,long> variables=new Dictionary<string, long>();
public Dictionary<long,(List<long>,bool perm )> boxes = new Dictionary<long, (List<long> 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<long>(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<Expression> expressions)
{
if(!HasFunction(str)) return 0;
var func=methods[str];
var res=NewScope();
for(int i = 0;i<Math.Min(expressions.Count,func.param.Count);i++)
{
res.SetVariable(func.param[i],expressions[i].Evaluate(res));
}
return func.expression.Evaluate(res);
}
public long CreateBox(string text,bool permanent=false)
{
long i=NoBoxes++;
boxes.Add(i,(new List<long>(text.Select<char,long>((e)=>{return e;})),permanent));
return i;
}
public bool HasFunction(string str)
{
return methods.ContainsKey(str);
}
public void AddFunction(string str, List<string> 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<long> box = boxes[boxId].Item1;
byte[] data=box.Skip((int)offset).Take((int)len).Select<long,byte>((e)=>{
2022-11-27 19:39:06 +00:00
return (byte)(e % 256);
2022-11-27 02:16:48 +00:00
}).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<long> 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<read;i++)
{
box[i+(int)offset] = data[i];
}
return read;
}
public void SetStreamPosition(long streamId, long streamPos)
{
GetStream(streamId).Position = streamPos;
}
public long GetStreamPosition(long streamId)
{
return GetStream(streamId).Position;
}
public long GetStreamLength(long streamId)
{
return GetStream(streamId).Length;
}
public bool CanRead(long streamId)
{
return GetStream(streamId).CanRead;
}
public bool CanWrite(long streamId)
{
return GetStream(streamId).CanWrite;
}
public bool CanSeek(long streamId)
{
return GetStream(streamId).CanSeek;
}
public long OpenWriteFile(long boxId)
{
string filename=BoxToString(boxId);
return CreateStream(File.OpenWrite(filename));
}
public long OpenReadWriteFile(long boxId)
{
string filename=BoxToString(boxId);
return CreateStream(File.Open(filename,FileMode.OpenOrCreate,FileAccess.ReadWrite));
}
public void FlushStream(long stream)
{
if(!streams.ContainsKey(stream)) return;
GetStream(stream).Flush();
}
}
public interface IApplicationState
{
void FlushStream(long stream);
void DestroyBox(long id);
public long e2n(Expression e);
public Expression Calln(long e);
long CreateStream(Stream strm);
long CreateFile(long boxId);
long OpenReadFile(long boxId);
long OpenWriteFile(long boxId);
long OpenReadWriteFile(long boxId);
void CopyStream(long strmSrc,long strmDest);
void CloseStream(long streamId);
void WriteToStream(long streamId,long boxId,long offset,long len);
long ReadFromStream(long streamId,long boxId,long offset,long len);
void SetStreamPosition(long streamId,long streamPos);
long GetStreamPosition(long streamId);
long GetStreamLength(long streamId);
bool CanRead(long streamId);
bool CanWrite(long streamId);
bool CanSeek(long streamId);
long ExecuteFunction(string str,List<Expression> expressions);
bool HasFunction(string str);
void AddFunction(string str,List<string> 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<LexToken> tokens)
{
int i = 0;
ParseNode(node,tokens,ref i,true);
}
public static ListNode Parse(List<LexToken> tokens)
{
int i = 0;
ListNode node=new ListNode();
ParseNode(node,tokens,ref i,true);
return node;
}
public static void ParseNode(ListNode node,List<LexToken> tokens,ref int i,bool root=false)
{
node.Root=root;
//i = 0
//0
//func()
while(i<tokens.Count && tokens[i].Type != LexTokenType.RBRACE)
{
if(tokens[i].Type == LexTokenType.SEMI) i++;
if(i+2 < tokens.Count && tokens[i+1].Type == LexTokenType.EQUALS)
{
string varname = tokens[i].Text;
i+=2;
node.Nodes.Add(new SetVariableNode(ParseExpression(tokens,ref i),varname));
if(!root && i<tokens.Count && tokens[i].Type == LexTokenType.RBRACE) break;
i++;
}
else if(i+1 < tokens.Count && tokens[i+1].Type == LexTokenType.LPAREN)
{
node.Nodes.Add(ParseExpression(tokens,ref i));
if(!root && i<tokens.Count && tokens[i].Type == LexTokenType.RBRACE) break;
i++;
}
else
{
node.Nodes.Add(ParseExpression(tokens,ref i));
if(!root && i<tokens.Count && tokens[i].Type == LexTokenType.RBRACE) break;
i++;
}
}
}
private static Expression ParseExpression(List<LexToken> 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<LexToken> 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<LexToken> 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<tokens.Count && tokens[i].Type == LexTokenType.LPAREN)
{
List<Expression> funcArgs = new List<Expression>();
//check whether its args
i++;
while(i<tokens.Count && tokens[i].Type != LexTokenType.RPAREN)
{
if(tokens[i].Type == LexTokenType.COMMA) i++;
funcArgs.Add(ParseExpression(tokens,ref i));
}
i++;
return new FunctionCallNode(token.Text,funcArgs);
}else{
return new VariableGetValueNode(token.Text);
}
}
if(token.Type == LexTokenType.STRING)
{
i++;
return new StringNode(token.Text);
}
if(token.Type == LexTokenType.NUMBER)
{
i++;
return new ConstantNumber(token.Text);
}
throw new Exception("Not found factor");
}
}
public class StringNode : Expression
{
long boxId=-1;
string text;
public StringNode(string text)
{
this.text = text;
}
public override long Evaluate(IApplicationState state)
{
if(boxId > -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<Expression> expressions;
public FunctionCallNode(string name,List<Expression> 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 == "rshit")
{
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<string> args=new List<string>();
if(vgvn == null) throw new Exception("Name must be identifier");
for(int i = 1;i<expressions.Count -1;i++)
{
VariableGetValueNode? vgvnArg = expressions[i] as VariableGetValueNode;
if(vgvnArg == null) throw new Exception("Arg must be identifier");
args.Add(vgvnArg.Name);
}
state.AddFunction(vgvn.Name,args,expressions[expressions.Count-1]);
}else if(name == "box_insert")
{
if(expressions.Count < 2)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 > 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<Node> Nodes = new List<Node>();
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;
}
}
}