public static Parser.Variable sum(Parser.Variable left, Parser.Variable right) { left = GetVariableValue(left); right = GetVariableValue(right); if (left.type == "string" || right.type == "string") { return(new Parser.Variable(left.value + right.value, "string")); } if (left.IsNaN() || right.IsNaN()) { return(new Parser.Variable("NaN", "number")); } if (!left.CanBeConvertedTo("number") || !right.CanBeConvertedTo("number")) { return(new Parser.Variable("NaN", "number")); } left = left.ConvertTo("number"); right = right.ConvertTo("number"); return(new Parser.Variable(Parse(left.value) + Parse(right.value))); }
public static Parser.Variable RegisterObject(string name) { var value = new Parser.Variable("", "object"); Interpreter.SetVariable(Interpreter.variables, new Parser.Variable(name, "variable"), "object", value); value.constant = true; return(value); }
public static Parser.Variable GetVariableValue(Parser.Variable var) { if (var.type == "variable") { var gvar = Interpreter.GetVariableByName(Interpreter.variables, var.value); if (gvar == null) { return(new Parser.Variable("undefined", "undefined")); } return(new Parser.Variable(gvar.value.value, gvar.value.type)); } return(var); }
public static Parser.Variable GetVariableByName(Parser.Variable prototype, Parser.Variable right) { foreach (var field in prototype.fields) { if (field.Key.IsDeepEqualTo(right)) { return(field.Value as Parser.Variable ?? new Parser.Variable()); } } if (prototype.prototype != null) { return(GetVariableByName(prototype.prototype, right)); } return(new Parser.Variable()); }
internal static Parser.Variable res(Parser.Variable left, Parser.Variable right) { left = GetVariableValue(left); right = GetVariableValue(right); if (left.IsNaN() || right.IsNaN()) { return(new Parser.Variable("NaN", "number")); } if (!left.CanBeConvertedTo("number") || !right.CanBeConvertedTo("number")) { return(new Parser.Variable("NaN", "number")); } left = left.ConvertTo("number"); right = right.ConvertTo("number"); return(new Parser.Variable(Parse(left.value) % Parse(right.value))); }
public static Parser.Variable div(Parser.Variable left, Parser.Variable right) { left = GetVariableValue(left); right = GetVariableValue(right); if (left.IsNaN() || right.IsNaN()) { return(new Parser.Variable("NaN", "number")); } if (!left.CanBeConvertedTo("number") || !right.CanBeConvertedTo("number")) { return(new Parser.Variable("NaN", "number")); } left = left.ConvertTo("number"); right = right.ConvertTo("number"); if (Parse(right.value) == 0) { return(new Parser.Variable(0)); } return(new Parser.Variable(Parse(left.value) / Parse(right.value))); }
public static void SetVariable(List <Variable> vars, Node variable, string type, Parser.Variable value) { var normal = variable as Parser.Variable; if (normal != null) { SetVariable(vars, variable.value, type, value.Clone()); return; } var varop = variable as Operation; if (varop != null) { var left = GetVariableByName(vars, varop.left); if (left.constant) { ShowError("left isde of exppression is constant"); return; } if (left.type == "undefined") { ShowError("Can not read property of undefined"); } else { var right = CalculateTree(varop.right, vars); bool found = false; if (right.value == "prototype") { if (value.type == "object") { left.prototype = value; } else { ShowError($"Prototype need to be object, but {value.type} were given"); } return; } foreach (var key in left.fields) { if (key.Key.IsDeepEqualTo(right)) { (key.Value as Parser.Variable)?.Set(value.Clone()); found = true; } } if (!found) { left.fields.Add(right.Clone(), value.Clone()); } } } }
public static void SetVariable(List <Variable> vars, string name, string type, Parser.Variable value) { for (var now = vars.Count - 1; now != -1; --now) { if (vars[now].name == name) { if (vars[now].value.constant) { ShowError("left isde of exppression is constant"); return; } vars[now].value = value.Clone(); vars[now].value.type = type; return; } } vars.Add(new Variable(name, type, value)); }
private static Parser.Variable ExecuteFunction(FunctionNode func, List <Parser.Variable> args, Parser.Variable caller) { ++depth; Parser.Variable var; var context = new List <Variable>(10); for (int now = 0; now < func.parameters.Count; ++now) { if (args.Count >= now) { context.Add(new Variable(func.parameters[now], args[now].type, args[now])); } } context.Add(new Variable("this", caller.type, caller)); foreach (Node line in func.code.code) { var = CalculateTree(line, context); if (isReturn) { isReturn = false; --depth; return(var); } if (isBreak) { ShowError("break operator need to be placed in cycle"); isBreak = false; } } --depth; return(new Parser.Variable()); }
public static Parser.Variable CalculateTree(Node tree, List <Variable> context) { var varnode = tree as Parser.Variable; if (varnode != null) { Variable var = null; if (varnode.type != "variable") { if (varnode.type == "functionCall") { Parser.Variable left = CalculateTree(varnode.expression, context); Parser.Variable caller; var objectOp = varnode.expression as Operation; if (objectOp == null || objectOp.op.symbol != ".") { caller = new Parser.Variable(); } else { caller = GetVariableByName(context, objectOp.left); } if (left.type == "function") { var = new Variable("anonymous", "function", left); } else { ShowError(left.type + " is not a function"); return(new Parser.Variable()); } if (varnode.args != null) { var func = var.value as FunctionNode; var args = new List <Parser.Variable>(Math.Max(varnode.args.Count, func.parameters.Count)); for (int now = 0; now < args.Capacity; ++now) { if (now < varnode.args.Count) { args.Add(CalculateTree(varnode.args[now], context)); } else { args.Add(new Parser.Variable()); } } if (func.native) { return(func.function(args)); } else { return(ExecuteFunction(func, args, caller)); } } return(new Parser.Variable()); } return(varnode); } var = GetVariableByName(context, varnode.value); if (var != null) { return(var.value); } else { return(new Parser.Variable()); } } var opnode = tree as Operation; if (opnode != null) { Parser.Variable left = null, right = null; if (opnode.op.symbol != ".") { if (opnode.op.symbol != "=") { left = CalculateTree(opnode.left, context); } right = CalculateTree(opnode.right, context); } switch (opnode.op.symbol) { case "+": return(VariableOperations.sum(left, right)); case "-": return(VariableOperations.sub(left, right)); case "*": return(VariableOperations.mul(left, right)); case "/": return(VariableOperations.div(left, right)); case "%": return(VariableOperations.res(left, right)); case ".": var lnode = opnode.left as Parser.Variable; if (lnode != null && lnode.type != "function" && lnode.type != "functionCall") { return(GetVariableByName(context, opnode)); } else { opnode = new Parser.Operation(operators[0], CalculateTree(opnode.left, context), opnode.right); return(GetVariableByName(context, opnode)); } case "=": if (right.fields.Count != 0) { var fields = new Dictionary <Parser.Variable, Parser.Node>(right.fields.Count); foreach (var key in right.fields) { fields.Add(key.Key, CalculateTree(key.Value, context)); } right.fields = fields; } SetVariable(context, opnode.left, right.type, right); return(right); case "+=": var sum = VariableOperations.sum(left, right); SetVariable(context, opnode.left, sum.type, sum); return(sum); case "-=": var sub = VariableOperations.sub(left, right); SetVariable(context, opnode.left, sub.type, sub); return(sub); case "*=": var mult = VariableOperations.mul(left, right); SetVariable(context, opnode.left, mult.type, mult); return(mult); case "/=": var div = VariableOperations.div(left, right); SetVariable(context, opnode.left, div.type, div); return(div); case "==": return(new Parser.Variable(left.IsEqualTo(right))); case "!=": return(new Parser.Variable(!left.IsEqualTo(right))); case "===": return(new Parser.Variable(left.IsDeepEqualTo(right))); case "!==": return(new Parser.Variable(!left.IsDeepEqualTo(right))); case ">": return(new Parser.Variable(left.IsGreaterThan(right))); case ">=": return(new Parser.Variable(left.IsGreaterOrEqualTo(right))); case "<": return(new Parser.Variable(right.IsGreaterThan(left))); case "<=": return(new Parser.Variable(right.IsGreaterOrEqualTo(left))); case "&": case "&&": return(new Parser.Variable(left.IsEqualTo(new Parser.Variable(true)) && right.IsEqualTo(new Parser.Variable(true)))); case "|": case "||": return(left.IsEqualTo(new Parser.Variable(true)) ? left : right); } } var conditionalNode = tree as ConditionalBlock; if (conditionalNode != null) { if (conditionalNode.type == "if") { if (CalculateTree(conditionalNode.condition, context).IsEqualTo(new Parser.Variable(true))) { return(CalculateTree(conditionalNode.code, context)); } else if (conditionalNode.oppositeCode != null) { return(CalculateTree(conditionalNode.oppositeCode, context)); } } if (conditionalNode.type == "for") { CalculateTree(conditionalNode.init, context); while (CalculateTree(conditionalNode.condition, context).IsEqualTo(new Parser.Variable(true))) { varnode = CalculateTree(conditionalNode.code, context); if (isReturn) { return(varnode); } if (isBreak) { isBreak = false; break; } CalculateTree(conditionalNode.post, context); } } if (conditionalNode.type == "while") { while (CalculateTree(conditionalNode.condition, context).IsEqualTo(new Parser.Variable(true))) { varnode = CalculateTree(conditionalNode.code, context); if (isReturn) { return(varnode); } if (isBreak) { isBreak = false; break; } } } return(new Parser.Variable()); } var blocknode = tree as Block; if (blocknode != null) { foreach (var exp in blocknode.code) { varnode = CalculateTree(exp, context); if (isReturn) { return(varnode); } if (isBreak) { break; } } } if (tree?.value == "return") { isReturn = true; return(CalculateTree((tree as ReturnNode).expression, context)); } if (tree?.value == "break") { isBreak = true; } return(new Parser.Variable()); }
public Variable(string name, string type, Parser.Variable value) { this.name = name; this.value = value; this.value.type = type; }