Пример #1
0
    def visit_InfixExpression(self, node, env):
        left = self.visit(node.left, env)
        if is_error(left):
            return left

        right = self.visit(node.right, env)
        if is_error(right):
            return right

        if isinstance(left, Integer) and isinstance(right, Integer):
            return eval_integer_infix_expression(node.operator, left, right)
        elif isinstance(left, String) and isinstance(right, String):
            return eval_string_infix_expression(node.operator, left, right)
        elif node.operator == "==":
            return to_bool(left.value == right.value)
        elif node.operator == "!=":
            return to_bool(left.value != right.value)
        elif left.type() != right.type():
            return Error(
                f"type mismatch: {left.type().value} {node.operator} {right.type().value}"
            )
        else:
            return Error(
                f"unknown operator: {left.type().value} {node.operator} {right.type().value}"
            )
Пример #2
0
def push_fn(args):
    if len(args) != 2:
        return Error(f"wrong number of arguments. got={len(args)}, want=2")

    if not isinstance(args[0], Array):
        return Error(
            f"argument to 'push' must be ARRAY, got {args[0].type().value}")

    new_arr = list(args[0].elements)
    new_arr.append(args[1])
    return Array(new_arr)
Пример #3
0
def rest_fn(args):
    if len(args) != 1:
        return Error(f"wrong number of arguments. got={len(args)}, want=1")

    if not isinstance(args[0], Array):
        return Error(
            f"argument to 'rest' must be ARRAY, got {args[0].type().value}")

    arr = args[0].elements

    return Array(list(arr[1:])) if len(arr) > 0 else NULL
Пример #4
0
def first_fn(args):
    if len(args) != 1:
        return Error(f"wrong number of arguments. got={len(args)}, want=1")

    if not isinstance(args[0], Array):
        return Error(
            f"argument to 'first' must be ARRAY, got {args[0].type().value}")

    arr = args[0]

    return arr.elements[0] if len(arr.elements) > 0 else NULL
Пример #5
0
def len_fn(args):
    if len(args) != 1:
        return Error(f"wrong number of arguments. got={len(args)}, want=1")

    arg = args[0]
    if isinstance(arg, String):
        return Integer(len(arg.value))
    elif isinstance(arg, Array):
        return Integer(len(arg.elements))
    else:
        return Error(
            f"argument to 'len' not supported, got {arg.type().value}")
Пример #6
0
def eval_index_expression(left, index):
    if isinstance(left, Array) and isinstance(index, Integer):
        return eval_array_index_expression(left, index)
    elif isinstance(left, Hash):
        return eval_hash_index_expression(left, index)
    else:
        return Error(f"index operator not supported {left.type().value}")
Пример #7
0
def eval_prefix_expression(operator, right):
    if operator == "!":
        return eval_bang_operator_expression(right)
    elif operator == "-":
        return eval_minus_prefix_operator_expression(right)
    else:
        return Error(f"unknown operator: {operator}{right.type().value}")
Пример #8
0
    def visit_Identifier(self, node, env):
        val = env.get(node.value)
        if val is not None:
            return val

        val = BUILTIN.get(node.value)
        if val is not None:
            return val

        return Error(f"identifier not found: {node.value}")
Пример #9
0
    def apply_function(self, fn, args):
        if isinstance(fn, Function):
            extended_env = extend_function_env(fn, args)
            if isinstance(extended_env, Error):
                return extended_env

            evaluated = self.visit(fn.body, extended_env)
            if evaluated is None:
                return None

            return unwrap_return_value(evaluated)

        elif isinstance(fn, BuiltIn):
            return fn.function(args)
        else:
            return Error(f"not a function: {fn}")
Пример #10
0
    def visit_HashLiteral(self, node, env):
        pairs = {}

        for key_node, val_node in node.pairs.items():
            key = self.visit(key_node, env)
            if is_error(key):
                return key

            if not isinstance(key, Hashable):
                return Error(f"unusable as hash key: {key.type().value}")

            value = self.visit(val_node, env)
            if is_error(value):
                return value

            hashed_key = key.hash_key()
            pairs[hashed_key] = HashPair(key, value)

        return Hash(pairs)
Пример #11
0
def eval_integer_infix_expression(operator, left, right):
    left_val = left.value
    right_val = right.value

    if operator == "+":
        return Integer(left_val + right_val)
    elif operator == "-":
        return Integer(left_val - right_val)
    elif operator == "*":
        return Integer(left_val * right_val)
    elif operator == "/":
        return Integer(left_val / right_val)
    elif operator == "<":
        return to_bool(left_val < right_val)
    elif operator == ">":
        return to_bool(left_val > right_val)
    elif operator == "==":
        return to_bool(left_val == right_val)
    elif operator == "!=":
        return to_bool(left_val != right_val)
    else:
        return Error(
            f"unknown operator: {left.type().value} {operator} {right.type().value}"
        )
Пример #12
0
def eval_hash_index_expression(hash_obj, index):
    if not isinstance(index, Hashable):
        return Error(f"unusable as hash key: {index.type().value}")

    pair = hash_obj.pairs.get(index.hash_key())
    return pair.value if pair is not None else NULL
Пример #13
0
def eval_string_infix_expression(operator, left, right):
    if operator != "+":
        return Error(
            f"unknown operator: {left.type().value} {operator} {right.type().value}"
        )
    return String(left.value + right.value)
Пример #14
0
def eval_minus_prefix_operator_expression(right):
    if not isinstance(right, Integer):
        return Error(f"unknown operator: -{right.type().value}")
    return Integer(-right.value)