private RuntimeResult VisitWhileNode(WhileNode node, Context context) { RuntimeResult condResult = Visit(node.Condition, context); if (condResult.HasError) { return(condResult); } Values.Value output = new Values.NullValue().SetPositionAndContext(node.Position, context); while (condResult.Value.GetAsBoolean()) { RuntimeResult bodyResult = Visit(node.Body, context); if (bodyResult.HasError) { return(bodyResult); } if (context.Return) { return(bodyResult); } output = bodyResult.Value; if (context.Break) { context.Break = false; break; } condResult = Visit(node.Condition, context); if (condResult.HasError) { return(condResult); } } return(new RuntimeResult(output)); }
private RuntimeResult VisitForEachNode(ForEachNode node, Context context) { RuntimeResult iterResult = Visit(node.Iteratable, context); if (iterResult.HasError) { return(iterResult); } int elementCount = iterResult.Value.GetElementCount(); string varName = node.Token.Value.ToString(); for (int i = 0; i < elementCount; i++) { RuntimeResult runtimeResult = iterResult.Value.GetElementAt(i); if (runtimeResult.HasError) { return(runtimeResult); } context.AddSymbol(varName, runtimeResult.Value); RuntimeResult bodyResult = Visit(node.Body, context); if (bodyResult.HasError) { return(bodyResult); } } return(new RuntimeResult(iterResult.Value)); }
private static void Execute(string code, string fname, Context context, bool inlineOutput) { Tokenizer tokenizer = new Tokenizer(fname, code); TokenizerResult tokenizerResult = tokenizer.GenerateTokens(); if (!tokenizerResult.HasError) { Parser parser = new Parser(tokenizerResult.Tokens); ParserResult parserResult = parser.Parse(); if (!parserResult.HasError) { Interpreter interpreter = new Interpreter(); RuntimeResult runtimeResult = interpreter.Visit(parserResult.Node, context); if (!runtimeResult.HasError) { if (inlineOutput) { Console.WriteLine(runtimeResult.Value); } } else { Console.WriteLine(runtimeResult.Error); } } else { Console.WriteLine(parserResult.Error); } } else { Console.WriteLine(tokenizerResult.Error); } }
private RuntimeResult VisitVarAssignNode(VarAssignNode node, Context context, Context baseCtx = null) { string name = node.Token.Value.ToString(); if (name == "null" || name == "true" || name == "false" || name == "this" || name == "base") { return(new RuntimeResult(new RuntimeError(node.Token.Position, "'" + name + "' is a reserved keyword", context))); } RuntimeResult runtimeResult = Visit(node.Node, baseCtx != null ? baseCtx : context); if (runtimeResult.HasError) { return(runtimeResult); } if (node.TypeToken == null) { if (context.ContainsSymbol(name) && context.GetSymbol(name).TypeDefined) { Values.ValueType toType = context.GetSymbol(name).Type; if (toType != runtimeResult.Value.Type) { Values.Value castedValue = runtimeResult.Value.Cast(toType); if (castedValue == null) { return(new RuntimeResult(new RuntimeError(node.Token.Position, "Can't convert '" + runtimeResult.Value.Type.ToString().ToLower() + "' to '" + toType.ToString().ToLower() + "'", context))); } else { context.AddSymbol(name, castedValue); return(runtimeResult); } } } context.AddSymbol(name, runtimeResult.Value); return(runtimeResult); } else { if (node.TypeToken.CheckKeyword("int")) { return(TypeDefAssign(Values.ValueType.INTEGER, runtimeResult.Value, name, node.Token.Position, context)); } if (node.TypeToken.CheckKeyword("complex")) { return(TypeDefAssign(Values.ValueType.COMPLEX, runtimeResult.Value, name, node.Token.Position, context)); } if (node.TypeToken.CheckKeyword("long")) { return(TypeDefAssign(Values.ValueType.INT64, runtimeResult.Value, name, node.Token.Position, context)); } if (node.TypeToken.CheckKeyword("big")) { return(TypeDefAssign(Values.ValueType.BIGINTEGER, runtimeResult.Value, name, node.Token.Position, context)); } } return(new RuntimeResult(new RuntimeError(node.Token.Position, "Type conversion error", context))); }
private RuntimeResult VisitListNode(ListNode node, Context context) { List <Values.Value> elements = new List <Values.Value>(); for (int i = 0; i < node.ElementNodes.Count; i++) { RuntimeResult runtimeResult = Visit(node.ElementNodes[i], context); if (runtimeResult.HasError) { return(runtimeResult); } elements.Add(runtimeResult.Value); } return(new RuntimeResult(new Values.ListValue(elements).SetPositionAndContext(node.Position, context))); }
private RuntimeResult VisitSubscriptNode(SubscriptNode node, Context context) { RuntimeResult baseResult = Visit(node.BaseNode, context); if (baseResult.HasError) { return(baseResult); } RuntimeResult indexResult = Visit(node.IndexNode, context); if (indexResult.HasError) { return(indexResult); } return(baseResult.Value.Subscript(indexResult.Value)); }
private RuntimeResult VisitReturnNode(ReturnNode node, Context context) { if (node.Node == null) { Values.Value val = new Values.NullValue().SetPositionAndContext(node.Position, context); context.Return = true; return(new RuntimeResult(val)); } else { RuntimeResult result = Visit(node.Node, context); if (result.HasError) { return(result); } context.Return = true; return(new RuntimeResult(result.Value)); } }
private RuntimeResult VisitDictionaryNode(DictionaryNode node, Context context) { List <(Values.Value, Values.Value)> pairs = new List <(Values.Value, Values.Value)>(); for (int i = 0; i < node.KeyValuePairs.Count; i++) { RuntimeResult keyResult = Visit(node.KeyValuePairs[i].Item1, context); if (keyResult.HasError) { return(keyResult); } RuntimeResult valueResult = Visit(node.KeyValuePairs[i].Item2, context); if (valueResult.HasError) { return(valueResult); } pairs.Add((keyResult.Value, valueResult.Value)); } return(new RuntimeResult(new Values.DictionaryValue(pairs).SetPositionAndContext(node.Position, context))); }
private RuntimeResult VisitIfNode(IfNode node, Context context) { for (int i = 0; i < node.Cases.Count; i++) { RuntimeResult condResult = Visit(node.Cases[i].Item1, context); if (condResult.HasError) { return(condResult); } if (condResult.Value.GetAsBoolean()) { return(Visit(node.Cases[i].Item2, context)); } } if (node.ElseCase != null) { return(Visit(node.ElseCase, context)); } return(new RuntimeResult(new Values.NullValue().SetPositionAndContext(node.Position, context))); }
private RuntimeResult VisitUnaryNode(UnaryNode node, Context context) { RuntimeResult runtimeResult = Visit(node.Node, context); if (runtimeResult.HasError) { return(runtimeResult); } if (node.Token.Type == TokenType.MINUS) { return(runtimeResult.Value.Multiply(new Values.IntegerValue(-1).SetPositionAndContext(node.Token.Position, context))); } else if (node.Token.Type == TokenType.BOOLEAN_NOT) { return(runtimeResult.Value.BooleanNot()); } else if (node.Token.Type == TokenType.COMPLEMENT) { return(runtimeResult.Value.BitwiseComplement()); } return(null); // todo: error handling }
private RuntimeResult VisitWhenNode(WhenNode node, Context context) { Values.Value variable = context.GetSymbol(node.Token.Value.ToString()); if (variable == null) { return(new RuntimeResult(new RuntimeError(node.Token.Position, "Variable '" + node.Token.Value + "' not defined", context))); } for (int i = 0; i < node.Cases.Count; i++) { RuntimeResult condResult = Visit(node.Cases[i].Item1, context); if (condResult.HasError) { return(condResult); } if (condResult.Value.Equals(variable).Value.GetAsBoolean()) { return(Visit(node.Cases[i].Item2, context)); } } //if (node.ElseCase != null) // return Visit(node.ElseCase, context); return(new RuntimeResult(new Values.NullValue().SetPositionAndContext(node.Token.Position, context))); }
private RuntimeResult VisitSubscriptAssignNode(SubscriptAssignNode node, Context context) { SubscriptNode subscript = (SubscriptNode)node.Target; RuntimeResult targetResult = Visit(subscript.BaseNode, context); if (targetResult.HasError) { return(targetResult); } RuntimeResult indexResult = Visit(subscript.IndexNode, context); if (indexResult.HasError) { return(indexResult); } RuntimeResult exprResult = Visit(node.Node, context); if (exprResult.HasError) { return(exprResult); } return(targetResult.Value.SubscriptAssign(indexResult.Value, exprResult.Value)); }
private RuntimeResult VisitDoNode(DoNode node, Context context) { Values.Value output = new Values.NullValue().SetPositionAndContext(node.Position, context); while (true) { RuntimeResult bodyResult = Visit(node.Body, context); if (bodyResult.HasError) { return(bodyResult); } output = bodyResult.Value; RuntimeResult condResult = Visit(node.Condition, context); if (condResult.HasError) { return(condResult); } if (!condResult.Value.GetAsBoolean()) { break; } } return(new RuntimeResult(output)); }
private RuntimeResult VisitBlockNode(BlockNode node, Context context) { Values.Value output = new Values.NullValue().SetPositionAndContext(node.Position, context); for (int i = 0; i < node.Statements.Count; i++) { RuntimeResult runtimeResult = Visit(node.Statements[i], context); if (runtimeResult.HasError) { return(runtimeResult); } if (context.Return) { return(runtimeResult); } if (context.Continue) { context.Continue = false; return(runtimeResult); } output = runtimeResult.Value; } return(new RuntimeResult(output)); }
private RuntimeResult VisitAttributeNode(AttributeNode node, Context context) { RuntimeResult runtimeResult = Visit(node.BaseNode, context); if (runtimeResult.HasError) { return(runtimeResult); } if (node.Node.Type == NodeType.VAR_ASSIGN) { return(VisitVarAssignNode((VarAssignNode)node.Node, runtimeResult.Value.Context, context)); } else if (node.Node.Type == NodeType.CALL) { if (runtimeResult.Value.Type == Values.ValueType.ASSEMBLY) { CallNode callNode = (CallNode)node.Node; Values.AssemblyValue asmVal = (Values.AssemblyValue)runtimeResult.Value; string name = ((VarAccessNode)callNode.Node).Token.Value.ToString(); List <object> args = new List <object>(); for (int i = 0; i < callNode.Arguments.Count; i++) { RuntimeResult result = Visit(callNode.Arguments[i].Item2, context); if (result.HasError) { return(result); } if (result.Value.Type == Values.ValueType.LIST) { object[] array = Util.ListToArray(result.Value); if (array == null) { return(new RuntimeResult(new RuntimeError(callNode.Position, "Error while converting list to an array", context))); } args.Add(array); } else if (result.Value.Type == Values.ValueType.BYTE_ARRAY) { byte[] array = ((Values.ByteArrayValue)result.Value).Bytes.ToArray(); args.Add(array); } else if (result.Value.IsBoolean) { args.Add(result.Value.GetAsBoolean()); } else { args.Add(result.Value.Data); } } return(asmVal.Invoke(name, args.ToArray())); } else if (Util.isPremitiveType(runtimeResult.Value.Type) || runtimeResult.Value.Type == Values.ValueType.C_SHARP) { CallNode callNode = (CallNode)node.Node; List <(string, Values.Value)> args = new List <(string, Values.Value)>(); for (int i = 0; i < callNode.Arguments.Count; i++) { RuntimeResult result = Visit(callNode.Arguments[i].Item2, context); if (result.HasError) { return(result); } args.Add((callNode.Arguments[i].Item1, result.Value)); } string name = ((VarAccessNode)callNode.Node).Token.Value.ToString(); return(runtimeResult.Value.CallMethod(name, args)); } return(VisitCallNode((CallNode)node.Node, runtimeResult.Value.Context, context)); } else if (node.Node.Type == NodeType.VAR_ACCESS) { if (runtimeResult.Value.Type == Values.ValueType.ASSEMBLY || runtimeResult.Value.Type == Values.ValueType.C_SHARP) { VarAccessNode vaccess = (VarAccessNode)node.Node; return(runtimeResult.Value.GetAttribute(vaccess.Token.Value.ToString())); } } return(Visit(node.Node, runtimeResult.Value.Context)); }
private RuntimeResult VisitBinaryNode(BinaryNode node, Context context, Context other = null) { RuntimeResult leftResult = Visit(node.LeftNode, context); if (leftResult.HasError) { return(leftResult); } RuntimeResult rightResult = Visit(node.RightNode, other != null ? other : context); if (rightResult.HasError) { return(rightResult); } if (node.OpToken.Type == TokenType.PLUS) { return(leftResult.Value.Add(rightResult.Value)); } else if (node.OpToken.Type == TokenType.MINUS) { return(leftResult.Value.Substract(rightResult.Value)); } else if (node.OpToken.Type == TokenType.MULTIPLY) { return(leftResult.Value.Multiply(rightResult.Value)); } else if (node.OpToken.Type == TokenType.DIVIDE) { return(leftResult.Value.Divide(rightResult.Value)); } else if (node.OpToken.Type == TokenType.MODULUS) { return(leftResult.Value.Modulus(rightResult.Value)); } else if (node.OpToken.Type == TokenType.EXPONENT) { return(leftResult.Value.Exponent(rightResult.Value)); } else if (node.OpToken.Type == TokenType.BITWISE_AND) { return(leftResult.Value.BitwiseAnd(rightResult.Value)); } else if (node.OpToken.Type == TokenType.BITWISE_OR) { return(leftResult.Value.BitwiseOr(rightResult.Value)); } else if (node.OpToken.Type == TokenType.BITWISE_XOR) { return(leftResult.Value.BitwiseXor(rightResult.Value)); } else if (node.OpToken.Type == TokenType.BITWISE_OR) { return(leftResult.Value.BitwiseOr(rightResult.Value)); } else if (node.OpToken.Type == TokenType.BITWISE_XOR) { return(leftResult.Value.BitwiseXor(rightResult.Value)); } else if (node.OpToken.Type == TokenType.LEFT_SHIFT) { return(leftResult.Value.LeftShift(rightResult.Value)); } else if (node.OpToken.Type == TokenType.RIGHT_SHIFT) { return(leftResult.Value.RightShift(rightResult.Value)); } else if (node.OpToken.Type == TokenType.EQUALS_EQUALS) { return(leftResult.Value.Equals(rightResult.Value)); } else if (node.OpToken.Type == TokenType.NOT_EQUALS) { return(leftResult.Value.NotEquals(rightResult.Value)); } else if (node.OpToken.Type == TokenType.GREATER_THAN) { return(leftResult.Value.GreaterThan(rightResult.Value)); } else if (node.OpToken.Type == TokenType.LESS_THAN) { return(leftResult.Value.LessThan(rightResult.Value)); } else if (node.OpToken.Type == TokenType.GREATER_TOE) { return(leftResult.Value.GreaterOrEqual(rightResult.Value)); } else if (node.OpToken.Type == TokenType.LESS_TOE) { return(leftResult.Value.LessOrEqual(rightResult.Value)); } else if (node.OpToken.Type == TokenType.BOOLEAN_AND) { return(leftResult.Value.BooleanAnd(rightResult.Value)); } else if (node.OpToken.Type == TokenType.BOOLEAN_OR) { return(leftResult.Value.BooleanOr(rightResult.Value)); } else if (node.OpToken.Type == TokenType.IN) { return(leftResult.Value.In(rightResult.Value)); } return(null); // todo: error handling }
private RuntimeResult VisitCallNode(CallNode node, Context context, Context fromCtx = null) { List <(string, Values.Value)> args = new List <(string, Values.Value)>(); for (int i = 0; i < node.Arguments.Count; i++) { RuntimeResult result = Visit(node.Arguments[i].Item2, fromCtx == null ? context : fromCtx); if (result.HasError) { return(result); } args.Add((node.Arguments[i].Item1, result.Value)); } if (node.Node.Type == NodeType.VAR_ACCESS) { VarAccessNode accessNode = (VarAccessNode)node.Node; string name = accessNode.Token.Value.ToString(); if (BuiltinMethods.BuiltinMethodList.ContainsKey(name)) { return(BuiltinMethods.Execute(name, args, node.Position, context)); } else { Values.Value method = context.GetSymbol(name); if (method == null) { return(new RuntimeResult(new RuntimeError(node.Position, "Method '" + name + "' is not defined", context))); } if (method.Type == Values.ValueType.METHOD) { return(((Values.MethodValue)method).Execute(args, this)); } else if (method.Type == Values.ValueType.CLASS) { Values.ClassValue classValue = ((Values.ClassValue)method).Clone(); //classValue.Type = Values.ValueType.OBJECT; if (classValue.BaseClass != null) { RuntimeResult baseResult = classValue.InitializeBaseClass(context, this); if (baseResult.HasError) { return(baseResult); } Context newContext = new Context(name, baseResult.Value.Context); classValue.SetPositionAndContext(accessNode.Token.Position, newContext); newContext.AddSymbol("this", classValue); newContext.AddSymbol("base", baseResult.Value); RuntimeResult runtimeResult = Visit(classValue.Body, newContext); if (runtimeResult.HasError) { return(runtimeResult); } //Constructor Values.Value ctorValue = newContext.GetSymbol("init"); if (ctorValue != null && ctorValue.Type == Values.ValueType.METHOD) { Values.MethodValue initMethod = (Values.MethodValue)ctorValue; RuntimeResult res = initMethod.Execute(args, this); if (res.HasError) { return(res); } } return(new RuntimeResult(classValue)); } else { Context newContext = new Context(name, context); classValue.SetPositionAndContext(accessNode.Token.Position, newContext); newContext.AddSymbol("this", classValue); RuntimeResult runtimeResult = Visit(classValue.Body, newContext); if (runtimeResult.HasError) { return(runtimeResult); } //Constructor Values.Value ctorValue = newContext.GetSymbol("init"); if (ctorValue != null && ctorValue.Type == Values.ValueType.METHOD) { Values.MethodValue initMethod = (Values.MethodValue)ctorValue; initMethod.Execute(args, this); } return(new RuntimeResult(classValue)); } } return(new RuntimeResult(new RuntimeError(node.Position, "'" + name + "' is not a method", context))); } } return(new RuntimeResult(new RuntimeError(node.Position, "Can't call as a method", context))); }
private RuntimeResult VisitForNode(ForNode node, Context context) { RuntimeResult startResult = Visit(node.Start, context); if (startResult.HasError) { return(startResult); } if (startResult.Value.Type != Values.ValueType.INTEGER) { return(new RuntimeResult(new RuntimeError(node.Token.Position, "Start value must be an integer", context))); } int start = (int)startResult.Value.Data; RuntimeResult endResult = Visit(node.End, context); if (endResult.HasError) { return(endResult); } if (endResult.Value.Type != Values.ValueType.INTEGER) { return(new RuntimeResult(new RuntimeError(node.Token.Position, "Stop value must be an integer", context))); } int end = (int)endResult.Value.Data; int step = 1; if (node.Step != null) { RuntimeResult stepResult = Visit(node.Step, context); if (stepResult.HasError) { return(stepResult); } if (endResult.Value.Type != Values.ValueType.INTEGER) { return(new RuntimeResult(new RuntimeError(node.Token.Position, "Step value must be an integer", context))); } step = (int)stepResult.Value.Data; } string id = node.Token.Value.ToString(); context.AddSymbol(id, startResult.Value); Values.Value output = new Values.NullValue().SetPositionAndContext(node.Token.Position, context); if (step > 0) { while (start < end) { RuntimeResult bodyResult = Visit(node.Body, context); if (bodyResult.HasError) { return(bodyResult); } if (context.Return) { return(bodyResult); } output = bodyResult.Value; if (context.Break) { context.Break = false; break; } start += step; startResult.Value.Data = start; } } else { while (start > end) { RuntimeResult bodyResult = Visit(node.Body, context); if (bodyResult.HasError) { return(bodyResult); } if (context.Return) { return(bodyResult); } output = bodyResult.Value; if (context.Break) { context.Break = false; break; } start += step; startResult.Value.Data = start; } } return(new RuntimeResult(output)); }