def push(*args: List[object.Object]) -> object.Object: if len(args) != 2: return evaluator.new_error('wrong number of arguments. got={}, want=2', len(args)) if args[0].type() != object.ARRAY_OBJ: return evaluator.new_error('argument to `push` must be ARRAY, got {}'.format(args[0].type())) arr = args[0] new_elements = copy.deepcopy(arr.elements) new_elements.append(args[1]) return object.Array(new_elements)
def _builtin_push(args: List[monkey_obj.Object]) -> monkey_obj.Object: if len(args) != 2: return monkey_obj.Error( f"wrong number of arguments. got={len(args)}, want=2") arr, obj = args if not isinstance(arr, monkey_obj.Array): return monkey_obj.Error( f"argumetn to `push` must be ARRAY, got {type(arr)}") return monkey_obj.Array(arr.elements + [obj])
def rest(*args: List[object.Object]) -> object.Object: if len(args) != 1: return evaluator.new_error('wrong number of arguments. got={}, want=1', len(args)) if args[0].type() != object.ARRAY_OBJ: return evaluator.new_error('argument to `rest` must be ARRAY, got {}'.format(args[0].type())) arr = args[0] length = len(arr.elements) if length > 0: new_elements = copy.deepcopy(arr.elements[1:length]) return object.Array(new_elements) return evaluator.NULL
def _builtin_rest(args: List[monkey_obj.Object]) -> monkey_obj.Object: if len(args) != 1: return monkey_obj.Error( f"wrong number of arguments. got={len(args)}, want=1") item = next(iter(args)) if not isinstance(item, monkey_obj.Array): return monkey_obj.Error( f"argumetn to `rest` must be ARRAY, got {type(item)}") if len(item.elements) > 0: return monkey_obj.Array(item.elements[1:]) return monkey_obj.NULL
def builtin_push(args: List[object.Object]) -> object.Object: if len(args) != 2: return newError('wrong number of arguments. got=%s, want=2', (len(args), )) arg = args[0] if arg.Type.TypeName != object.ARRAY_OBJ: return newError('argument to `push` must be ARRAY, got %s', (args[0].Type.TypeName, )) arr = cast(object.Array, arg) newElements = copy.deepcopy(arr.Elements) newElements.append(args[1]) return object.Array(Elements=newElements)
def builtin_rest(args: List[object.Object]) -> object.Object: if len(args) != 1: return newError('wrong number of arguments. got=%s, want=1', (len(args), )) arg = args[0] if arg.Type.TypeName != object.ARRAY_OBJ: return newError('argument to `rest` must be ARRAY, got %s', (args[0].Type.TypeName, )) arr = cast(object.Array, arg) length = len(arr.Elements) if length > 0: newElements = copy.deepcopy(arr.Elements[1:]) return object.Array(Elements=newElements) return NULL
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) -> monkey_obj.Object: if isinstance(node, ast.Program): return eval_program(node.statements, env) elif isinstance(node, ast.HashLiteral): return eval_hash_literal(node, env) elif isinstance(node, ast.ArrayLiteral): elements = [Eval(e, env) for e in node.elements] if len(elements) == 1 and isinstance(elements[0], monkey_obj.Error): return elements[0] return monkey_obj.Array(elements=elements) elif isinstance(node, ast.IndexExpression): left = Eval(node.left, env) if left is not None and isinstance(left, monkey_obj.Error): return left index = Eval(node.index, env) if index is not None and isinstance(index, monkey_obj.Error): return index return eval_index_expression(left, index) elif isinstance(node, ast.StringLiteral): return monkey_obj.String(value=node.value) elif isinstance(node, ast.CallExpression): function = Eval(node.function, env) if function is not None and isinstance(function, monkey_obj.Error): return function args = [Eval(e, env) for e in node.arguments] for arg in args: if arg is not None and isinstance(function, monkey_obj.Error): return arg return apply_function(function, args) elif isinstance(node, ast.FunctionLiteral): params = node.params body = node.body return monkey_obj.Function(params, env, body) elif isinstance(node, ast.BlockStatement): return eval_block_statements(node.statements, env) elif isinstance(node, ast.IfExpression): return eval_if_expression(node, env) elif isinstance(node, ast.Identifier): return eval_identifier(node, env) elif isinstance(node, ast.LetStatement): val = Eval(node.value, env) if val is not None and isinstance(val, monkey_obj.Error): return val env[node.name.value] = val return monkey_obj.NULL elif isinstance(node, ast.ReturnStatement): val = Eval(node.value, env) if val is not None and isinstance(val, monkey_obj.Error): return val return monkey_obj.ReturnValue(value=val) elif isinstance(node, ast.ExpressionStatement): return Eval(node.expression, env) elif isinstance(node, ast.Boolean): return native_bool_to_boolean_object(node.value) elif isinstance(node, ast.IntegerLiteral): return monkey_obj.Integer(value=node.value) elif isinstance(node, ast.PrefixExpression): right = Eval(node.right, env) if right is not None and isinstance(right, monkey_obj.Error): return val return eval_prefix_expression(node.operator, right) elif isinstance(node, ast.InfixExpression): left = Eval(node.left, env) if left is not None and isinstance(left, monkey_obj.Error): return left right = Eval(node.right, env) if right is not None and isinstance(right, monkey_obj.Error): return val return eval_infix_expression(node.operator, left, right) else: raise NotImplementedError(str(node), node.token_literal())
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