def len_function(*args): if len(args) != 1: return new_error(f"wrong number of arguments. got={len(args)}, want=1") if isinstance(args[0], b1u3object.String): return b1u3object.Integer(value=len(args[0].value)) elif isinstance(args[0], b1u3object.Array): return b1u3object.Integer(value=len(args[0].elements)) return new_error(f"argument to `len` not supported, got {args[0].type()}")
def test_hash_literals(self): input = """ let two = "two"; { "one": 10 -9, two: 1 + 1, "thr"+ "ee": 6 / 2, 4: 4, true: 5, false: 6 }""" evaluated = self.help_test_eval(input) self.assertTrue(isinstance(evaluated, b1u3object.Hash), f"Eval didn't return Hash. got={type(evaluated)}") expected = { b1u3object.String(value="one").hash_key(): 1, b1u3object.String(value="two").hash_key(): 2, b1u3object.String(value="three").hash_key(): 3, b1u3object.Integer(value=4).hash_key(): 4, b1u3evaluator.TRUE.hash_key(): 5, b1u3evaluator.FALSE.hash_key(): 6 } self.assertEqual( len(evaluated.pairs), len(expected), f"Hash has wrong num of pairs. got={len(evaluated.pairs)}") for expectedKey, expectedValue in expected.items(): p = evaluated.pairs[expectedKey] self.help_test_integer_object(p.value, expectedValue)
def eval_integer_infix_expression(operator, left, right, env): if operator == '+': return b1u3object.Integer(value=left.value+right.value) elif operator == '-': return b1u3object.Integer(value=left.value-right.value) elif operator == '*': return b1u3object.Integer(value=left.value*right.value) elif operator == '/': return b1u3object.Integer(value=left.value//right.value) elif operator == '<': return TRUE if left.value < right.value else FALSE elif operator == '>': return TRUE if left.value > right.value else FALSE elif operator == '==': return TRUE if left.value == right.value else FALSE elif operator == '!=': return TRUE if left.value != right.value else FALSE else: return new_error(f'unknown operator: {left.type()} {operator} {right.type()}')
def b1u3eval(node:b1u3ast.Node, env:Dict[str, b1u3object.Object]) -> b1u3object.Object: print(node) if isinstance(node, b1u3ast.Program): return eval_program(node.statements, env) elif isinstance(node, b1u3ast.ExpressionStatement): return b1u3eval(node.expression, env) elif isinstance(node, b1u3ast.IntegerLiteral): return b1u3object.Integer(value=node.value) elif isinstance(node, b1u3ast.Boolean): if node.value: return TRUE else: return FALSE elif isinstance(node, b1u3ast.PrefixExpression): # then already ast node has right expression right = b1u3eval(node.right, env) if is_error(right): return right return eval_prefix_expression(node.operator, right, env) elif isinstance(node, b1u3ast.InfixExpression): left = b1u3eval(node.left, env) if is_error(left): return left right = b1u3eval(node.right, env) if is_error(right): return right return eval_infix_expression(node.operator, left, right, env) elif isinstance(node, b1u3ast.BlockStatement): return eval_block_statement(node, env) elif isinstance(node, b1u3ast.IfExpression): return eval_if_expression(node, env) elif isinstance(node, b1u3ast.ReturnStatement): val = b1u3eval(node.return_value, env) if is_error(val): return val return b1u3object.ReturnValue(value=val) elif isinstance(node, b1u3ast.LetStatement): val = b1u3eval(node.value, env) if is_error(val): return val env[node.name.value] = val elif isinstance(node, b1u3ast.Identifier): return eval_identifier(node, env) elif isinstance(node, b1u3ast.FunctionLiteral): params = node.parameters body = node.body return b1u3object.Function(parameters=params, env=env, body=body) elif isinstance(node, b1u3ast.CallExpression): if node.function.token_literal() == "quote": return quote(node.arguments[0], env) function = b1u3eval(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 isinstance(node, b1u3ast.StringLiteral): return b1u3object.String(value=node.value) elif isinstance(node, b1u3ast.ArrayLiteral): elements = eval_expressions(node.elements, env) if len(elements) == 1 and is_error(elements[0]): return [0] return b1u3object.Array(elements=elements) elif isinstance(node, b1u3ast.IndexExpression): left = b1u3eval(node.left, env) if is_error(left): return left index = b1u3eval(node.index, env) if is_error(index): return index return eval_index_expression(left, index) elif isinstance(node, b1u3ast.HashLiteral): return eval_hash_literal(node, env) return NULL
def eval_minus_operator_expression(right, env): if right.type() != b1u3object.INTEGER_OBJ: return new_error(f'unknown operator: -{right.type()}') value = right.value return b1u3object.Integer(value=-value)