def eval(node: ast.Node, env: object.Environment): if type(node) is ast.Program: return eval_program(node.statements, env) elif type(node) is ast.ExpressionStatement: return eval(node.expression, env) elif type(node) is ast.LetStatement: val = eval(node.value, env) if is_error(val): return val env.set(node.name.value, val) elif type(node) is ast.Identifier: return eval_identifier(node, env) elif type(node) is ast.StringLiteral: return object.String(value=node.value) elif type(node) is ast.FunctionLiteral: parameters = node.parameters body = node.body return object.Function(parameters=parameters, body=body, env=env) elif type(node) is ast.CallExpression: fun = eval(node.function, env) if is_error(fun): return fun args = eval_expressions(node.arguments, env) if len(args) == 1 and is_error(args[0]): return args[0] return apply_function(fun, args) elif type(node) is ast.PrefixExpression: right = eval(node.right, env) if is_error(right): return right return eval_prefix_expression(node.operator, right) elif type(node) is ast.InfixExpression: left = eval(node.left, env) if is_error(left): return left right = eval(node.right, env) if is_error(right): return right return eval_infix_expression(node.operator, left, right) elif type(node) is ast.IntegerLiteral: return object.Integer(value=node.value) elif type(node) is ast.BlockStatement: return eval_block_statements(node.statements, env) elif type(node) is ast.IfExpression: return eval_if_expression(node, env) elif type(node) is ast.ReturnStatement: val = eval(node.return_value, env) return object.ReturnValue(value=val) elif type(node) is ast.Boolean: return object.TRUE if node.value is True else object.FALSE
def addMacro(stmt: ast.Statement, env: object.Environment) -> None: letStatement = cast(ast.LetStatement, stmt) macroLiteral = cast(ast.MacroLiteral, letStatement.Value) macro = object.Macro( Parameters=macroLiteral.Parameters, Env=env, Body=macroLiteral.Body, ) env.Set(letStatement.Name.Value, macro)
def eval_identifier(node: ast.Identifier, env: object.Environment): val = env.get(node.value) if val is not None: return val if node.value in builtins: return builtins[node.value] return object.Error("identifier not found: {}".format(node.token.literal))
def eval_identifier(node: ast.Identifier, env: object.Environment) -> object.Object: val, ok = env.get(node.value) if ok: return val if node.value in builtins: return builtins[node.value] return new_error('identifier not found: ' + node.value)
def evalIdentifier(node: ast.Identifier, env: object.Environment) -> Optional[object.Object]: val = env.Get(node.Value) if val: return val builtin = builtins.get(node.Value) if builtin: return builtin return newError('identifier not found: ' + node.Value, tuple())
def isMacroCall(exp: ast.CallExpression, env: object.Environment) -> Optional[object.Macro]: if type(exp.Function) != ast.Identifier: return None identifier = cast(ast.Identifier, exp.Function) obj = env.Get(identifier.Value) if not obj: return None if type(obj) != object.Macro: return None macro = cast(object.Macro, obj) return macro
def Eval(node: Any, env: object.Environment) -> Optional[object.Object]: if type(node) == ast.Program: return evalProgram(node, env) elif type(node) == ast.ExpressionStatement: return Eval(node.ExpressionValue, env) elif type(node) == ast.IntegerLiteral: return object.Integer(Value=node.Value) elif type(node) == ast.Boolean: return nativeBoolToBooleanObject(node.Value) elif type(node) == ast.PrefixExpression: right = Eval(node.Right, env) if right: if isError(right): return right return evalPrefixExpression(node.Operator, right) else: return None elif type(node) == ast.InfixExpression: left = Eval(node.Left, env) if not left: return None if isError(left): return left right = Eval(node.Right, env) if not right: return None if isError(right): return right evaluated = evalInfixExpression(node.Operator, left, right) return evaluated elif type(node) == ast.BlockStatement: return evalBlockStatement(node, env) elif type(node) == ast.IfExpression: return evalIfExpression(node, env) elif type(node) == ast.ReturnStatement: val = Eval(node.ReturnValue, env) if val: if isError(val): return val return object.ReturnValue(Value=val) else: return None elif type(node) == ast.LetStatement: val = Eval(node.Value, env) if val: if isError(val): return val env.Set(node.Name.Value, val) else: return None elif type(node) == ast.Identifier: return evalIdentifier(node, env) elif type(node) == ast.FunctionLiteral: params = node.Parameters body = node.Body return object.Function(Parameters=params, Env=env, Body=body) elif type(node) == ast.CallExpression: if node.Function.TokenLiteral() == 'quote': return quote(node.Arguments[0], env) function = Eval(node.Function, env) if function: if isError(function): return function args = evalExpressions(node.Arguments, env) if len(args) == 1 and isError(args[0]): return args[0] if not function: return None return applyFunction(function, args) elif type(node) == ast.StringLiteral: return object.String(Value=node.Value) elif type(node) == ast.ArrayLiteral: elements = evalExpressions(node.Elements, env) if len(elements) == 1 and isError(elements[0]): return elements[0] return object.Array(Elements=elements) elif type(node) == ast.IndexExpression: left = Eval(node.Left, env) if not left: return None if isError(left): return left index = Eval(node.Index, env) if not index: return None if isError(index): return index return evalIndexExpression(left, index) elif type(node) == ast.HashLiteral: return evalHashLiteral(node, env) return None
def eval(node: ast.Node, env: object.Environment) -> Union[object.Object, None]: # Statements if issubclass(node.__class__, ast.Program): return eval_program(node, env) elif issubclass(node.__class__, ast.BlockStatement): return eval_block_statement(node, env) elif issubclass(node.__class__, ast.ExpressionStatement): return eval(node.expression, env) elif issubclass(node.__class__, ast.ReturnStatement): val = eval(node.return_value, env) if is_error(val): return val return object.ReturnValue(val) elif issubclass(node.__class__, ast.LetStatement): val = eval(node.value, env) if is_error(val): return val env.set(node.name.value, val) # Expressions elif issubclass(node.__class__, ast.IntegerLiteral): return object.Integer(node.value) elif issubclass(node.__class__, ast.StringLiteral): return object.String(node.value) elif issubclass(node.__class__, ast.Boolean): return native_bool_to_boolean_object(node.value) elif issubclass(node.__class__, ast.PrefixExpression): right = eval(node.right, env) if is_error(right): return right return eval_prefix_expression(node.operator, right) elif issubclass(node.__class__, ast.InfixExpression): left = eval(node.left, env) if is_error(left): return left right = eval(node.right, env) if is_error(right): return right return eval_infix_expression(node.operator, left, right) elif issubclass(node.__class__, ast.IfExpression): return eval_if_expression(node, env) elif issubclass(node.__class__, ast.Identifier): return eval_identifier(node, env) elif issubclass(node.__class__, ast.FunctionLiteral): params = node.parameters body = node.body return object.Function(params, body, env) elif issubclass(node.__class__, ast.CallExpression): function = eval(node.function, env) if is_error(function): return function args = eval_expressions(node.arguments, env) if len(args) == 1 and is_error(args[0]): return args[0] return apply_function(function, args) elif issubclass(node.__class__, ast.ArrayLiteral): elements = eval_expressions(node.elements, env) if len(elements) == 1 and is_error(elements[0]): return elements[0] return object.Array(elements) elif issubclass(node.__class__, ast.IndexExpression): left = eval(node.left, env) if is_error(left): return left index = eval(node.index, env) if is_error(index): return index return eval_index_expression(left, index) elif issubclass(node.__class__, ast.HashLiteral): return eval_hash_literal(node, env) return None