ParseResult monomod() { ParseResult res = new ParseResult(); PNode node; if (current.type == TokenType.INC || current.type == TokenType.DEC) { LToken op = current; res.Register(Next()); node = res.Register(call(newer())); if (res.error != null) { return(res); } if (op.type == TokenType.INC) { op.type = TokenType.ADD; } else { op.type = TokenType.SUB; } PNode exp = PNode.GetBinOP(node, op, new PNode(new LToken(TokenType.VALUE, new Value(1), op.position))); if (node.TYPE == "VarGet") { return(res.Succes(new PNode("VarAsign", node.val, exp))); } if (!res.isInnnerCall) { return(res.Failure(new InvalidSyntaxError(op.position, "Increment and decrement operators can only edit immediate variables"))); } List <PNode> pns = new List <PNode>(node.PNodes); pns.RemoveAt(0); pns.Add(exp); return(res.Succes(PNode.GetCall("InnerAsign", node.PNodes[0], pns))); } node = res.Register(call(newer())); if (current.type == TokenType.INC || current.type == TokenType.DEC) { LToken op = current; LToken ed = current.Copy(false); if (!res.isInnnerCall && node.TYPE != "VarGet") { return(res.Failure(new InvalidSyntaxError(op.position, "Increment and decrement operators can only edit immediate variables"))); } res.Register(Next()); if (op.type == TokenType.INC) { ed.type = TokenType.ADD; } else { ed.type = TokenType.SUB; } PNode exp = PNode.GetBinOP(node, ed, new PNode(new LToken(TokenType.VALUE, new Value(1), op.position))); if (node.TYPE == "VarGet") { exp = new PNode("VarAsign", node.val, exp); } else { List <PNode> pns = new List <PNode>(node.PNodes); pns.RemoveAt(0); pns.Add(exp); exp = PNode.GetCall("InnerAsign", node.PNodes[0], pns); } return(res.Succes(new PNode("UnarOp", new List <PNode>() { node, exp }, op))); } return(res.Succes(node, true)); }
static public RTResult Visit(PNode node, Context context) { RTResult res = new RTResult(); LToken Ot; Function f; Value v; switch (node.TYPE) { case "VALUE": return(res.Succes(node.val.SetContext(context))); case "VarAsign": case "PublicVarMake": case "PublicPrototype": case "VarMake": Ot = res.Register(VisitVarAsign(node, context)); if (res.error != null) { return(res); } return(res.Succes(Ot)); case "VarGet": f = context.GetFunction(); if (f != null) { if (f.InnerValues.ContainsKey(node.val.value.text)) { return(res.Succes(f.InnerValues[node.val.value.text])); } } if (!context.varlist.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is not defined", context))); } return(res.Succes(context.varlist[node.val.value.text])); case "BinOp": Ot = res.Register(VisitBinOp(node, context)); if (res.error != null) { return(res); } return(res.Succes(Ot)); case "UnarOp": Ot = res.Register(VisitUnarOp(node, context)); if (res.error != null) { return(res); } return(res.Succes(Ot)); case "PublicFuncDeff": f = new Function(node.val, node.right, node.LTokens.ConvertAll(x => x.value.text), context); Function CF = context.GetFunction(); f.InnerValues.parent = CF.InnerValues; CF.InnerValues[node.val.value.text] = new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context);; return(res.Succes(new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context))); case "FuncDef": f = new Function(node.val, node.right, node.LTokens.ConvertAll(x => x.value.text), context); if (node.val.value != null) { context.varlist[node.val.value.text] = new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context); } return(res.Succes(new LToken(TokenType.VALUE, new Value(f), node.val.position).SetContext(context))); case "CallFunc": Ot = res.Register(VisitCall(node, context)); if (res.error != null) { return(res); } Ot.type = TokenType.VALUE; return(res.Succes(Ot)); case "MakeList": List <Value> values = new List <Value>(); foreach (PNode n in node.PNodes) { values.Add(res.Register(Visit(n, context)).value); if (res.error != null) { return(res); } } return(res.Succes(new LToken(TokenType.VALUE, new Value(values), node.val.position).SetContext(context))); case "Prototype": Ot = res.Register(Visit(node.PNodes[0], context)); if (res.error != null) { return(res); } if (Ot.value.type != "FUNC") { return(res.Failure(new RuntimeError(Ot.position, "Value to prototype into has to be a function.", context))); } if (Compiler.forbidden.Contains(Ot.value.function.name.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{Ot.value.function.name.value.text} is a predefined, unmutable variable", context))); } Ot.value.function.body.PNodes.Add(new PNode("PublicPrototype", node.val, node.PNodes[1])); return(res.Succes(Ot)); case "GetProperty": Ot = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } v = Ot.value.GetProperty(node.val.value.text); Ot = new LToken(TokenType.VALUE, v, Ot.position); return(res.Succes(Ot.SetContext(context))); case "PropertyAsign": Ot = res.Register(Visit(node.PNodes[1], context)); v = res.Register(Visit(node.PNodes[0].right, context)).value.SetProperty(node.PNodes[0].val.value.text, Ot); Ot = new LToken(TokenType.VALUE, v, Ot.position); return(res.Succes(Ot.SetContext(context))); case "CallProperty": LToken toCall = res.Register(Visit(node.PNodes[0], context)); if (res.error != null) { return(res); } List <LToken> args = new List <LToken>(); for (int n = 1; n < node.PNodes.Count; n++) { args.Add(res.Register(Visit(node.PNodes[n], context))); if (res.error != null) { return(res); } } LToken t = res.Register(toCall.value.CallProperty(node.val.value.text, args, context, toCall.position)); if (res.error != null) { return(res); } return(res.Succes(t.SetContext(context))); case "GetInner": Ot = res.Register(VisitGetInner(node, context)); if (res.error != null) { return(res); } return(res.Succes(Ot)); case "InnerAsign": Ot = res.Register(VisitSetInner(node, context)); if (res.error != null) { return(res); } return(res.Succes(Ot)); case "IF": { Context ctx = BracketContext(context); Ot = res.Register(Visit(node.PNodes[0], ctx)); if (res.error != null) { return(res); } if (Ot.value.boolean) { Ot = res.Register(Visit(node.PNodes[1], ctx)); if (res.error != null) { return(res); } if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0) { return(res.Succes(Ot)); } } else if (node.PNodes.Count == 3) { Ot = res.Register(Visit(node.PNodes[2], ctx)); if (res.error != null) { return(res); } if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0) { return(res.Succes(Ot)); } } } return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position))); case "WHILE": { Context ctx = BracketContext(context); Ot = res.Register(Visit(node.PNodes[0], ctx)); if (res.error != null) { return(res); } while (Ot.value.boolean) { Ot = res.Register(Visit(node.PNodes[1], ctx)); if (res.error != null) { return(res); } if (Ot.type == TokenType.BREAK) { break; } if (Ot.type == TokenType.RETURN) { return(res.Succes(Ot)); } ctx = BracketContext(context); Ot = res.Register(Visit(node.PNodes[0], ctx)); if (res.error != null) { return(res); } } } return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position))); case "FOR": { Context CON = BracketContext(context); res.Register(Visit(node.PNodes[0], CON)); Ot = res.Register(Visit(node.PNodes[1], CON)); if (res.error != null) { return(res); } Context ctx = BracketContext(CON); while (Ot.value.boolean) { Ot = res.Register(Visit(node.PNodes[3], ctx)); if (res.error != null) { return(res); } if (Ot.type == TokenType.BREAK) { break; } if (Ot.type == TokenType.RETURN) { return(res.Succes(Ot)); } ctx = BracketContext(CON); res.Register(Visit(node.PNodes[2], ctx)); if (res.error != null) { return(res); } Ot = res.Register(Visit(node.PNodes[1], ctx)); if (res.error != null) { return(res); } } return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position))); } case "MultExpr": return(VisitBody(node, BracketContext(context))); case "Body": return(VisitBody(node, context)); case "NEW": Ot = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } if (Ot.value.type != "FUNC") { return(res.Failure(new RuntimeError(node.val.position, "'new' copy can be only aplied to functions.", context))); } return(res.Succes(Ot.Copy(false))); case "RETURN": Ot = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } Ot.type = TokenType.RETURN; return(res.Succes(Ot)); case "BREAK": return(res.Succes(new LToken(TokenType.BREAK, Value.NULL, node.val.position))); case "CONTINUE": return(res.Succes(new LToken(TokenType.CONTINUE, Value.NULL, node.val.position))); case "SUPER": f = context.GetFunction(); if (f == null) { return(res.Failure(new RuntimeError(node.val.position, "Super can only be called inside a function.", context))); } Ot = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } if (Ot.value.type != "FUNC") { return(res.Failure(new RuntimeError(Ot.position, "Function can only accept another function as a Super.", context))); } f.InnerValues.Merge(Ot.value.function.InnerValues, f); return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, node.val.position))); case "RUN": Ot = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } if (Ot.value.type != "STRING") { return(res.Failure(new RuntimeError(node.val.position, "Run statement requires a string argument.", context))); } if (!System.IO.File.Exists(Ot.value.text)) { return(res.Failure(new RuntimeError(Ot.position, $"File {Ot.value.text} does not exist.", context))); } Ot = res.Register(Compiler.Run(System.IO.File.ReadAllText(Ot.value.text), new System.IO.FileInfo(Ot.value.text).Name)); if (res.error != null) { return(res); } return(res.Succes(Ot)); default: throw new Exception("Visit not defined"); } }