예제 #1
0
def eval_infix_expression(operator: str, lhs: monkey_obj.Object,
                          rhs: monkey_obj.Object) -> monkey_obj.Object:
    if isinstance(lhs, monkey_obj.Integer) and isinstance(
            rhs, monkey_obj.Integer):
        return eval_integer_infix_expression(operator, lhs, rhs)
    elif type(lhs) != type(rhs):
        return monkey_obj.Error(
            f"type mismatch: {lhs.object_type()} {operator} {rhs.object_type()}"
        )

    elif isinstance(lhs, monkey_obj.String) and isinstance(
            rhs, monkey_obj.String):
        if operator != "+":
            return monkey_obj.Error(
                f"unknown operator: {lhs.object_type()} {operator} {rhs.object_type()}"
            )
        return monkey_obj.String(value=lhs.value + rhs.value)

    elif operator == "==":
        return native_bool_to_boolean_object(lhs == rhs)
    elif operator == "!=":
        return native_bool_to_boolean_object(lhs != rhs)
    return monkey_obj.Error(
        f"unknown operator: {lhs.object_type()} {operator} {rhs.object_type()}"
    )
예제 #2
0
def len_builtin(*args):
    if len(args) != 1:
        return object.Error(
            'wrong number of arguments, got= {}, want = 1'.format(len(args)))
    if type(args[0]) is object.String:
        return object.Integer(value=len(args[0].value))
    else:
        return object.Error("argument to 'len' not supported, got {}".format(
            args[0].object_type))
예제 #3
0
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])
예제 #4
0
def _builtin_len(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 isinstance(item, monkey_obj.String):
        return monkey_obj.Integer(value=len(item.value))
    elif isinstance(item, monkey_obj.Array):
        return monkey_obj.Integer(value=len(item.elements))
    else:
        return monkey_obj.Error(
            f"argument to `len` not supported, got {item.object_type()}")
예제 #5
0
def eval_infix_expression(operator, left, right):
    if type(left) is object.Integer and type(right) is object.Integer:
        return eval_integer_infix_expression(operator, left, right)
    if type(left) is object.String and type(right) is object.String:
        return eval_string_infix_expression(operator, left, right)
    elif operator == '==':
        return native_bool_to_boolean_object(left == right)
    elif operator == '!=':
        return native_bool_to_boolean_object(left != right)
    elif type(left) != type(right):
        return object.Error("type mismatch: {} {} {}".format(left.object_type, operator, right.object_type))
    else:
        return object.Error(message="unknown operator: {} {} {}".format(left.object_type, operator, right.object_type))
예제 #6
0
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
예제 #7
0
def eval_prefix_expression(operator: str,
                           rhs=monkey_obj.Object) -> monkey_obj.Object:
    if operator == "!":
        return eval_bang_operator(rhs)
    elif operator == "-":
        return eval_minus_prefix_operator(rhs)
    else:
        return monkey_obj.Error(
            f"unknown operator: {operator}{rhs.object_type()}")
예제 #8
0
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))
예제 #9
0
def eval_identifier(node: ast.Identifier, env):
    val = env.get(node.value)
    if val is not None:
        return val

    builtin = builtins.get(node.value)
    if builtin is not None:
        return builtin

    return monkey_obj.Error(f"identifier not found: {node.value}")
예제 #10
0
def apply_function(fun, arguments):
    if type(fun) is object.Function:
        extended_env = extend_function_env(fun, arguments)
        evaluated = eval(fun.body, extended_env)
        if type(evaluated) is object.ReturnValue:
            return evaluated.value
        return evaluated
    elif type(fun) is object.Builtin:
        return fun.fn(*arguments)
    return object.Error("not a function")
예제 #11
0
def eval_index_expression(left: monkey_obj.Object,
                          index: monkey_obj.Object) -> monkey_obj.Object:
    if isinstance(left, monkey_obj.Array) and isinstance(
            index, monkey_obj.Integer):
        return eval_array_index_expression(left, index)

    elif isinstance(left, monkey_obj.Hash):
        return eval_hash_index_expression(left, index)
    else:
        return monkey_obj.Error(f"index operator not supported: {type(left)}")
예제 #12
0
def apply_function(fn: monkey_obj.Object,
                   args: List[monkey_obj.Object]) -> monkey_obj.Object:

    if isinstance(fn, monkey_obj.Function):
        func_environment = {
            param.value: args[index]
            for index, param in enumerate(fn.params)
        }
        evaluated = Eval(fn.body, ChainMap(func_environment, fn.env))
        return unwrap_return_value(evaluated)
    elif isinstance(fn, monkey_obj.Builtin):
        return fn.fn(args)
    else:
        return monkey_obj.Error(f"not a function: {type(fn)}")
예제 #13
0
def eval_integer_infix_expression(
        operator: str, lhs: monkey_obj.Integer,
        rhs: monkey_obj.Integer) -> monkey_obj.Object:
    if operator == "+":
        return monkey_obj.Integer(value=lhs.value + rhs.value)
    elif operator == "-":
        return monkey_obj.Integer(value=lhs.value - rhs.value)
    elif operator == "*":
        return monkey_obj.Integer(value=lhs.value * rhs.value)
    elif operator == "/":
        return monkey_obj.Integer(value=lhs.value // rhs.value)
    elif operator == "<":
        return native_bool_to_boolean_object(lhs.value < rhs.value)
    elif operator == ">":
        return native_bool_to_boolean_object(lhs.value > rhs.value)
    elif operator == "==":
        return native_bool_to_boolean_object(lhs.value == rhs.value)
    elif operator == "!=":
        return native_bool_to_boolean_object(lhs.value != rhs.value)
    else:
        return monkey_obj.Error(
            f"unknown operator: {lhs.object_type()} {operator} {rhs.object_type()}"
        )
예제 #14
0
def eval_minus_prefix_operator(rhs: monkey_obj.Object) -> monkey_obj.Object:
    if not isinstance(rhs, monkey_obj.Integer):
        return monkey_obj.Error(f"unknown operator: -{rhs.object_type()}")
    return monkey_obj.Integer(value=-(rhs.value))
예제 #15
0
def eval_minus_prefix_operator_expression(right):
    if type(right) is not object.Integer:
        return object.Error(message="unknown operator: {}{}".format("-", right.object_type))
    else:
        return object.Integer(value=-right.value)
예제 #16
0
def eval_string_infix_expression(operator, left, right):
    if operator is not "+":
        return object.Error("unknown operator: {} {} {}".format(left.object_type, operator, right.object_type))
        # use python string concat underneath
    return object.String(value=left.value + right.value)
예제 #17
0
def newError(template: str, a: Tuple[Any, ...]) -> object.Error:
    return object.Error(Message=template % a)
예제 #18
0
def new_error(format: str, *a) -> object.Error:
    return object.Error(format.format(*a))