public static RTResult ReadText(Context ctx, int argN) { RTResult res = new RTResult(); if (argN == 0) { if (!ctx.lastIn.InnerValues.ContainsKey("path")) { return(res.Failure(new RuntimeError(ctx.parentEntry, "Zero parameter version of this function can only be run from an already defined file.", ctx))); } if (ctx.lastIn.InnerValues["path"].value.type != "STRING") { return(res.Failure(new RuntimeError(ctx.parentEntry, "File path has to be a string", ctx))); } if (!File.Exists(ctx.lastIn.InnerValues["path"].value.text)) { return(res.Failure(new RuntimeError(ctx.parentEntry, $"File '{ctx.lastIn.InnerValues["path"].value.text}' does not exist.", ctx))); } return(res.Succes(new LToken(TokenType.VALUE, new Value(File.ReadAllText(ctx.lastIn.InnerValues["path"].value.text)), ctx.parentEntry).SetContext(ctx))); } if (ctx.varlist["_ARG0"].value.type != "STRING") { return(res.Failure(new RuntimeError(ctx.parentEntry, "File path has to be a string", ctx))); } if (!File.Exists(ctx.varlist["_ARG0"].value.text)) { return(res.Failure(new RuntimeError(ctx.parentEntry, $"File '{ctx.varlist["_ARG0"].value.text}' does not exist.", ctx))); } return(res.Succes(new LToken(TokenType.VALUE, new Value(File.ReadAllText(ctx.varlist["_ARG0"].value.text)), ctx.parentEntry).SetContext(ctx))); }
static void Main(string[] args) { RTResult res = new RTResult(); Compiler.Prepare(); if (args.Length == 1) { res = Compiler.Run(File.ReadAllText(args[0]), new FileInfo(args[0]).Name); if (res.error != null) { Console.WriteLine(res.error); } Console.Read(); return; } while (true) { Console.Write("ModScript> "); string inp = Console.ReadLine(); res = Compiler.Run(inp, "<console>"); if (res.error != null) { Console.WriteLine(res.error); } Console.WriteLine(); } }
static RTResult VisitSetInner(PNode node, Context context) { RTResult res = new RTResult(); LToken toCall = res.Register(Visit(node.PNodes[0], context)); if (res.error != null) { return(res); } if (toCall.value.type == "LIST") { LToken v = res.Register(Visit(node.PNodes[1], context)); if (res.error != null) { return(res); } if (v.value.type != "INT") { return(res.Failure(new RuntimeError(v.position, "Element argument has to be an integer.", context))); } LToken exp = res.Register(Visit(node.PNodes[2], context)); if (res.error != null) { return(res); } if (v.value.integer < 0 || v.value.integer >= toCall.value.values.Count) { return(res.Failure(new RuntimeError(v.position, $"Element argument has to be between 0 and the length of the list ({toCall.value.values.Count}).", context))); } toCall.value.values[v.value.integer] = exp.value; return(res.Succes(exp.SetContext(context))); } return(res.Failure(new RuntimeError(toCall.position, "List expected", context))); }
static RTResult VisitCall(PNode node, Context context) { RTResult res = new RTResult(); LToken toCall = res.Register(Visit(node.PNodes[0], context)); if (res.error != null) { return(res); } if (toCall.value.function == null) { return(res.Failure(new RuntimeError(node.PNodes[0].val.position, $"{node.PNodes[0].val.value.text} is not a function.", context))); } 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.function.Execute(args, context, toCall.position)); if (res.error != null) { return(res); } return(res.Succes(t.SetContext(context))); }
public static RTResult WriteText(Context ctx, int argN) { RTResult res = new RTResult(); if (argN < 1) { return(MinArgError(ctx, 1)); } if (argN == 1) { if (!ctx.lastIn.InnerValues.ContainsKey("path")) { return(res.Failure(new RuntimeError(ctx.parentEntry, "Zero parameter version of this function can only be run from an already defined file.", ctx))); } if (ctx.lastIn.InnerValues["path"].value.type != "STRING") { return(res.Failure(new RuntimeError(ctx.parentEntry, "File path has to be a string", ctx))); } File.WriteAllText(ctx.lastIn.InnerValues["path"].value.text, ctx.varlist["_ARG0"].value.ToString()); return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, ctx.parentEntry).SetContext(ctx))); } if (ctx.varlist["_ARG0"].value.type != "STRING") { return(res.Failure(new RuntimeError(ctx.parentEntry, "File path has to be a string", ctx))); } File.WriteAllText(ctx.varlist["_ARG0"].value.text, ctx.varlist["_ARG1"].value.ToString()); return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, ctx.parentEntry).SetContext(ctx))); }
public static RTResult Insert(Value v, List <LToken> args, Context _context, TextPosition pos) { RTResult res = new RTResult(); if (args.Count != 2) { return(res.Failure(new RuntimeError(pos, "Function 'Insert' requres 2 arguments.", _context))); } if (args[0].value.type != "INT") { return(res.Failure(new RuntimeError(pos, "Function 'Insert' a int argument1.", _context))); } if (v.type == "STRING") { if (args[0].value.integer > v.text.Length) { return(res.Failure(new RuntimeError(pos, "Insertion position cannot be greater then string length", _context))); } v.text.Insert(args[0].value.integer, args[1].value.ToString()); return(res.Succes(new LToken(TokenType.VALUE, v, pos).SetContext(_context))); } if (v.type == "LIST") { if (args[0].value.integer > v.values.Count) { return(res.Failure(new RuntimeError(pos, "Insertion position cannot be greater then list length", _context))); } v.values.Insert(args[0].value.integer, args[1].value); return(res.Succes(new LToken(TokenType.VALUE, v, pos).SetContext(_context))); } return(res.Failure(new RuntimeError(pos, "Function 'Insert' can be used only for string and list types.", _context))); }
public LToken Register(RTResult res) { if (res.error != null) { error = res.error; } return(res.value); }
static RTResult VisitGetInner(PNode node, Context context) { RTResult res = new RTResult(); LToken toCall = res.Register(Visit(node.PNodes[0], context)); if (res.error != null) { return(res); } if (toCall.value.type == "LIST") { LToken v = res.Register(Visit(node.PNodes[1], context)); if (res.error != null) { return(res); } if (v.value.type != "INT") { return(res.Failure(new RuntimeError(v.position, "Element argument has to be an integer.", context))); } if (v.value.integer < 0) { return(res.Failure(new RuntimeError(v.position, "Element argument cannot be less then 0.", context))); } if (v.value.integer < toCall.value.values.Count && v.value.integer >= 0) { return(res.Succes(new LToken(TokenType.VALUE, toCall.value.values[v.value.integer], toCall.position).SetContext(context))); } return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, toCall.position).SetContext(context))); } else if (toCall.value.type == "STRING") { LToken v = res.Register(Visit(node.PNodes[1], context)); if (res.error != null) { return(res); } if (v.value.type != "INT") { return(res.Failure(new RuntimeError(v.position, "Element argument has to be an integer.", context))); } if (v.value.integer < 0) { return(res.Failure(new RuntimeError(v.position, "Element argument cannot be less then 0.", context))); } if (v.value.integer < toCall.value.text.Length && v.value.integer >= 0) { return(res.Succes(new LToken(TokenType.VALUE, new Value(toCall.value.text[v.value.integer].ToString()), toCall.position).SetContext(context))); } return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, toCall.position).SetContext(context))); } return(res.Failure(new RuntimeError(toCall.position, "List expected", context))); }
public RTResult Execute(List <LToken> args, Context _context, TextPosition pos) { RTResult res = new RTResult(); Context ctx = parent.context.Copy(); ctx.name = name.value.text; ctx.parentEntry = pos; ctx.parent = _context; ctx.lastIn = this; ctx.varlist.parent = DeffCon.varlist; if (Predefs.ContainsKey(name.value.text) || Special.ContainsKey(name.value.text)) { for (int n = 0; n < args.Count; n++) { ctx.varlist.Add("_ARG" + n, args[n].SetContext(ctx)); } } else { for (int n = 0; n < argNames.Count; n++) { if (n < args.Count) { ctx.varlist.Add(argNames[n], args[n].SetContext(ctx)); } else { ctx.varlist.Add(argNames[n], new LToken(TokenType.VALUE, Value.NULL, pos).SetContext(ctx)); } } } LToken t; if (Predefs.ContainsKey(name.value.text)) { t = res.Register(Predefs[name.value.text](ctx, args.Count)); } else if (Special.ContainsKey(name.value.text)) { t = res.Register(Special[name.value.text](ctx, args.Count)); } else { t = res.Register(Interpreter.Visit(body, ctx)); } if (res.error != null) { return(res); } return(res.Succes(t.SetContext(ctx))); }
public static RTResult sqrt(Context ctx, int argN) { RTResult res = new RTResult(); if (argN < 1) { return(MinArgError(ctx, 1)); } if (!ctx.varlist["_ARG0"].value.isNumber) { return(res.Failure(new RuntimeError(ctx.parentEntry, "Sqrt can be applied only to numbers", ctx))); } return(res.Succes(new LToken(TokenType.VALUE, new Value(Math.Sqrt(ctx.varlist["_ARG0"].value.number)), ctx.parentEntry).SetContext(ctx))); }
public static RTResult FileF(Context ctx, int argN) { RTResult res = new RTResult(); if (argN > 0) { if (ctx.varlist["_ARG0"].value.type != "STRING") { return(res.Failure(new RuntimeError(ctx.parentEntry, "File path has to be a string", ctx))); } ctx.lastIn.InnerValues["path"] = ctx.varlist["_ARG0"]; return(res.Succes(new LToken(TokenType.VALUE, new Value(ctx.lastIn), ctx.parentEntry).SetContext(ctx))); } return(res.Succes(new LToken(TokenType.VALUE, Value.NULL, ctx.parentEntry).SetContext(ctx))); }
static RTResult VisitUnarOp(PNode node, Context context) { RTResult res = new RTResult(); if ((node.val.type & (TokenType.INC | TokenType.DEC)) != 0) { LToken Out = res.Register(Visit(node.PNodes[0], context)); if (res.error != null) { return(res); } Out = new LToken(TokenType.VALUE, Out.value, Out.position); res.Register(Visit(node.PNodes[1], context)); if (res.error != null) { return(res); } return(res.Succes(Out)); } LToken n = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } if (node.val.type == TokenType.SUB) { if (n.value.isNumber) { return(res.Succes(new LToken(TokenType.VALUE, new Value(-n.value.number), n.position).SetContext(n.value.context))); } } if (node.val.type == TokenType.NOT) { if (n.value.type == "BOOLEAN") { return(res.Succes(new LToken(TokenType.VALUE, new Value(!n.value.boolean), n.position).SetContext(n.value.context))); } else { return(res.Failure(new RuntimeError(n.position, "Expected boolean", context))); } } return(res.Succes(n)); }
public static RTResult PrintAscii(Context ctx, int argN) { RTResult res = new RTResult(); if (argN < 1) { return(MinArgError(ctx, 1)); } if (ctx.varlist["_ARG0"].value.type != "INT") { return(res.Failure(new RuntimeError(ctx.varlist["_ARG0"].position, "PrintAscii requies an integer.", ctx))); } if (ctx.varlist["_ARG0"].value.integer < 0 || ctx.varlist["_ARG0"].value.integer > 255) { return(res.Failure(new RuntimeError(ctx.varlist["_ARG0"].position, "PrintAscii requies argument to be between 0 and 256 (IE).", ctx))); } Console.Write(System.Text.ASCIIEncoding.UTF8.GetChars(new byte[] { (byte)ctx.varlist["_ARG0"].value.integer })[0]); return(res.Succes(ctx.varlist["_ARG0"])); }
public static RTResult ParseNumber(Context ctx, int argN) { RTResult res = new RTResult(); if (argN < 1) { return(MinArgError(ctx, 1)); } if (ctx.varlist["_ARG0"].value.type != "STRING") { return(res.Failure(new RuntimeError(ctx.parentEntry, "File path has to be a string", ctx))); } double d; if (!double.TryParse(ctx.varlist["_ARG0"].value.text.Replace('.', ','), out d)) { d = 0; } return(res.Succes(new LToken(TokenType.VALUE, new Value(d), ctx.parentEntry).SetContext(ctx))); }
static RTResult VisitBody(PNode node, Context context) { RTResult res = new RTResult(); LToken Ot; List <PNode> PNodes = new List <PNode>(node.PNodes); foreach (PNode n in PNodes.FindAll(x => x.TYPE == "FuncDef" || x.TYPE == "PublicPrototype" || x.TYPE == "PublicFuncDeff" || x.TYPE == "SUPER" || x.TYPE == "RUN" || x.TYPE == "Prototype" || x.isMakeValid())) { Ot = res.Register(Visit(n, context)); if (res.error != null) { return(res); } if ((Ot.type & (TokenType.BREAK | TokenType.CONTINUE | TokenType.RETURN)) != 0) { return(res.Succes(Ot)); } PNodes.Remove(n); } foreach (PNode n in PNodes) { Ot = res.Register(Visit(n, context)); 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))); }
public static RTResult Concat(Context ctx, int argN) { RTResult res = new RTResult(); if (argN < 1) { return(MinArgError(ctx, 1)); } if (argN == 1 && ctx.varlist["_ARG0"].value.type == "LIST") { return(res.Succes(new LToken(TokenType.VALUE, new Value(string.Join("", ctx.varlist["_ARG0"].value.values.ConvertAll(v => v.ToString()))), ctx.parentEntry).SetContext(ctx))); } if (argN == 2 && ctx.varlist["_ARG0"].value.type == "LIST" && ctx.varlist["_ARG1"].value.type == "STRING") { return(res.Succes(new LToken(TokenType.VALUE, new Value(string.Join(ctx.varlist["_ARG1"].value.text, ctx.varlist["_ARG0"].value.values.ConvertAll(v => v.ToString()))), ctx.parentEntry).SetContext(ctx))); } string s = ""; for (int n = 0; n < argN; n++) { s += ctx.varlist["_ARG" + n].value.ToString(); } return(res.Succes(new LToken(TokenType.VALUE, new Value(s), ctx.parentEntry).SetContext(ctx))); }
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"); } }
static RTResult VisitBinOp(PNode node, Context context) { RTResult res = new RTResult(); LToken r = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } LToken l = res.Register(Visit(node.left, context)); if (res.error != null) { return(res); } switch (node.val.type) { case TokenType.EE: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value == r.value), l.position).SetContext(context))); case TokenType.NE: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value != r.value), l.position).SetContext(context))); } if (l.value.isNumber && r.value.isNumber) { switch (node.val.type) { case TokenType.ADD: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number + r.value.number), l.position).SetContext(l.value.context))); case TokenType.SUB: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number - r.value.number), l.position).SetContext(l.value.context))); case TokenType.MULT: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number * r.value.number), l.position).SetContext(l.value.context))); case TokenType.DIV: if (r.value.number == 0) { res.Failure(new RuntimeError(node.val.position, "Division by zero error", context)); } return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number / r.value.number), l.position).SetContext(l.value.context))); case TokenType.POW: return(res.Succes(new LToken(TokenType.VALUE, new Value(Math.Pow(l.value.number, r.value.number)), l.position).SetContext(l.value.context))); case TokenType.MOD: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number % r.value.number), l.position).SetContext(l.value.context))); case TokenType.GT: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number > r.value.number), l.position).SetContext(context))); case TokenType.LT: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number < r.value.number), l.position).SetContext(context))); case TokenType.GTE: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number >= r.value.number), l.position).SetContext(context))); case TokenType.LTE: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.number <= r.value.number), l.position).SetContext(context))); } } else if (l.value.type == "BOOLEAN" && r.value.type == "BOOLEAN") { switch (node.val.type) { case TokenType.AND: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.boolean && r.value.boolean), l.position).SetContext(l.value.context))); case TokenType.OR: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.boolean || r.value.boolean), l.position).SetContext(l.value.context))); } } else if (l.value.type == "LIST" && r.value.type == "LIST") { switch (node.val.type) { case TokenType.ADD: List <Value> Vs = new List <Value>(l.value.values.ToArray()); Vs.AddRange(r.value.values); return(res.Succes(new LToken(TokenType.VALUE, new Value(Vs), l.position).SetContext(l.value.context))); } } else if (l.value.type == "STRING" || r.value.type == "STRING") { switch (node.val.type) { case TokenType.ADD: return(res.Succes(new LToken(TokenType.VALUE, new Value(l.value.ToString() + r.value.ToString()), l.position).SetContext(l.value.context))); } } return(res.Failure(new RuntimeError(node.val.position, $"Invalid operation for {l.value.type} and {r.value.type}.", context))); }
static RTResult VisitVarAsign(PNode node, Context context) { RTResult res = new RTResult(); if (Compiler.forbidden.Contains(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is a predefined, unmutable variable", context))); } if (node.TYPE == "PublicVarMake" || node.TYPE == "PublicPrototype") { if (context.GetFunction() == null) { return(res.Failure(new RuntimeError(node.val.position, "Public variables have to be declared in an object.", context))); } } if (node.TYPE == "VarAsign") { if (context.GetFunction() == null) { if (!context.varlist.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is not Defined", context))); } } else if (!context.varlist.ContainsKey(node.val.value.text) && !context.GetFunction().InnerValues.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is not Defined", context))); } } else if (node.TYPE == "PublicVarMake") { if (context.GetFunction().InnerValues.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is already Defined", context))); } } else if (node.TYPE != "PublicPrototype") { if (context.varlist.ContainsKey(node.val.value.text)) { return(res.Failure(new RuntimeError(node.val.position, $"{node.val.value.text} is already Defined", context))); } } LToken n = res.Register(Visit(node.right, context)); if (res.error != null) { return(res); } LToken Val = new LToken(TokenType.VALUE, n.value, node.val.position).SetContext(n.value.context); Function f = context.GetFunction(); if (node.TYPE == "PublicVarMake" || node.TYPE == "PublicPrototype") { if (Val.value.type == "FUNC") { Val.value.function.InnerValues.parent = f.InnerValues; } f.InnerValues[node.val.value.text] = Val; } else if (f != null) { if (f.InnerValues.ContainsKey(node.val.value.text)) { if (Val.value.type == "FUNC") { Val.value.function.InnerValues.parent = f.InnerValues; } f.InnerValues[node.val.value.text] = Val; } else { context.varlist[node.val.value.text] = Val; } } else { context.varlist[node.val.value.text] = Val; } return(res.Succes(Val.SetContext(context))); }