static Object.Object evalBlockStatement(ast.BlockStatement block, Object.Environment env) { Object.Object result = null; foreach (ast.Statement statement in block.Statements) { result = Eval(statement, env); if (result != null) { string rt = result.Type(); if (rt == Object._ObjectType.RETURN_VALUE_OBJ || rt == Object._ObjectType.ERROR_OBJ) { return(result); } } } return(result); }
static ast.BlockStatement parseBlockStatement() { ast.BlockStatement block = new ast.BlockStatement { Token = curToken }; block.Statements = new List <ast.Statement>(); nextToken(); while (!curTokenIs(token.RBRACE) && !curTokenIs(token.EOF)) { ast.Statement stmt = parseStatement(); if (stmt != null) { block.Statements.Add(stmt); } nextToken(); } return(block); }
public static Object.Object Eval(ast.Node node, Object.Environment env) { // Statements if (node is ast.Program) { return(evalProgram((ast.Program)node, env)); } if (node is ast.BlockStatement) { return(evalBlockStatement((ast.BlockStatement)node, env)); } if (node is ast.ExpressionStatement) { return(Eval(((ast.ExpressionStatement)node).Expression, env)); } if (node is ast.ReturnStatement) { Object.Object val = Eval(((ast.ReturnStatement)node).ReturnValue, env); if (isError(val)) { return(val); } return(new Object.ReturnValue { Value = val }); } if (node is ast.LetStatement) { Object.Object val = Eval(((ast.LetStatement)node).Value, env); if (isError(val)) { return(val); } env.Set(((ast.LetStatement)node).Name.Value, val); } // Expressions if (node is ast.IntegerLiteral) // Go can use a switch here! { return new Object.Integer { Value = ((ast.IntegerLiteral)node).Value } } ; if (node is ast.StringLiteral) { return new Object.String { Value = ((ast.StringLiteral)node).Value } } ; if (node is ast.Boolean) { return(nativeToBooleanObject(((ast.Boolean)node).Value)); } if (node is ast.PrefixExpression) { Object.Object right = Eval(((ast.PrefixExpression)node).Right, env); if (isError(right)) { return(right); } return(evalPrefixExpression(((ast.PrefixExpression)node).Operator, right)); } if (node is ast.InfixExpression) { Object.Object left = Eval(((ast.InfixExpression)node).Left, env); if (isError(left)) { return(left); } Object.Object right = Eval(((ast.InfixExpression)node).Right, env); if (isError(right)) { return(right); } return(evalInfixExpression(((ast.InfixExpression)node).Operator, left, right)); } if (node is ast.IfExpression) { return(evalIfExpression((ast.IfExpression)node, env)); } if (node is ast.Identifier) { return(evalIdentifier((ast.Identifier)node, env)); } if (node is ast.FunctionLiteral) { List <ast.Identifier> params_ = ((ast.FunctionLiteral)node).Parameters; ast.BlockStatement body = ((ast.FunctionLiteral)node).Body; return(new Object.Function { Parameters = params_, Env = env, Body = body }); } if (node is ast.CallExpression) { if (((ast.CallExpression)node).Function.TokenLiteral() == "quote") { return(quote_unquote.quote(((ast.CallExpression)node).Arguments[0], env)); } Object.Object function = Eval(((ast.CallExpression)node).Function, env); if (isError(function)) { return(function); } List <Object.Object> args = evalExpressions(((ast.CallExpression)node).Arguments, env); if (args.Count == 1 && isError(args[0])) { return(args[0]); } return(applyFunction(function, args)); } if (node is ast.ArrayLiteral) { List <Object.Object> elements = evalExpressions(((ast.ArrayLiteral)node).Elements, env); if (elements.Count == 1 && isError(elements[0])) { return(elements[0]); } return(new Object.Array { Elements = elements }); } if (node is ast.IndexExpression) { Object.Object left = Eval(((ast.IndexExpression)node).Left, env); if (isError(left)) { return(left); } Object.Object index = Eval(((ast.IndexExpression)node).Index, env); if (isError(index)) { return(index); } return(evalIndexExpression(left, index)); } if (node is ast.HashLiteral) { return(evalHashLiteral((ast.HashLiteral)node, env)); } return(null); }