Esempio n. 1
0
def rest_fn(args: List[objects.Object]) -> objects.Object:
    if len(args) != 1:
        return wrong_number_of_args(actual=len(args), expected=1)
    if args[0].object_type() != ObjectType.ARRAY_OBJ:
        return objects.Error(
            f"argument to `rest` must be ARRAY, got {args[0].object_type().value}"
        )
    arr = args[0]
    if len(arr.elements):
        return objects.Array(arr.elements[1:])
    return objects.Array([])
Esempio n. 2
0
def evaluate_array_infix_expression(operator: str, left: objects.Object,
                                    right: objects.Object) -> objects.Object:
    if operator != "+":
        return new_error(
            f"unknown operator: {left.object_type().value} {operator} {right.object_type().value}"
        )

    return objects.Array(left.elements + right.elements)
Esempio n. 3
0
def push_fn(args: List[objects.Object]) -> objects.Object:
    if len(args) != 2:
        return wrong_number_of_args(actual=len(args), expected=2)
    if args[0].object_type() != ObjectType.ARRAY_OBJ:
        return objects.Error(
            f"first argument to `push` must be ARRAY, got {args[0].object_type().value}"
        )
    arr = args[0]
    new_elements = list(arr.elements)
    new_elements.append(args[1])
    return objects.Array(new_elements)
Esempio n. 4
0
def reverse_fn(args: List[objects.Object]) -> objects.Object:
    if len(args) != 1:
        return wrong_number_of_args(actual=len(args), expected=1)
    src = args[0]
    if src.object_type() == ObjectType.ARRAY_OBJ:
        reversed_elements = src.elements[::-1]
        return objects.Array(reversed_elements)
    elif src.object_type() == ObjectType.STRING_OBJ:
        return objects.String(src.value[::-1])
    return objects.Error(
        f"argument to `reverse` must be ARRAY or STRING, got {src.object_type().value}"
    )
Esempio n. 5
0
def split_fn(args: List[objects.Object]) -> objects.Object:
    if len(args) != 2:
        return wrong_number_of_args(actual=len(args), expected=2)

    string = args[0]
    delimiter = args[1]
    if not isinstance(string, objects.String):
        return objects.Error(
            f"first argument to `split` must be STRING, got {string.object_type().value}({args[0]})"
        )
    if not isinstance(delimiter, objects.String):
        return objects.Error(
            f"second argument to `split` must be STRING, got {delimiter.object_type().value}({args[1]})"
        )

    elements = string.value.split(delimiter.value)
    strElements = [objects.String(el) for el in elements]

    return objects.Array(strElements)
Esempio n. 6
0
def values_fn(args: List[objects.Object]) -> objects.Object:
    if len(args) != 1:
        return wrong_number_of_args(actual=len(args), expected=1)
    src = args[0]
    if src.object_type() == ObjectType.HASH_OBJ:
        hash_ = src
    elif src.object_type() == ObjectType.MODULE:
        if not isinstance(src, objects.Module):
            return objects.Error(
                f"argument to `values` must be HASH or MODULE, got {src.object_type().value}({src})"
            )
        hash_ = module.attrs
    else:
        return objects.Error(
            f"argument to `values` must be HASH or MODULE, got {src.object_type().value}({src})"
        )

    values = [hash_pair.value for hash_key, hash_pair in hash_.pairs.items()]

    return objects.Array(values)
Esempio n. 7
0
def evaluate(node: ast.Node, env: objects.Environment) -> objects.Object:
    # print(f"EVALUATING: node:<{node}>, type: <{type(node)}>")
    if isinstance(node, ast.Program):
        return evaluate_program(node, env)
    elif isinstance(node, ast.ExpressionStatement):
        return evaluate(node.expression, env)
    elif isinstance(node, ast.BlockStatement):
        return evaluate_block_statement(node, env)
    elif isinstance(node, ast.ReturnStatement):
        value = evaluate(node.return_value, env)
        if is_error(value):
            return value
        return objects.ReturnValue(value)
    elif isinstance(node, ast.LetStatement):
        val = evaluate(node.value, env)
        if is_error(val):
            return val
        env.set(node.name.value, val)
    elif isinstance(node, ast.IntegerLiteral):
        return objects.Integer(node.value)
    elif isinstance(node, ast.StringLiteral):
        return objects.String(node.value)
    elif isinstance(node, ast.ArrayLiteral):
        elements = evaluate_expressions(node.elements, env)
        if len(elements) == 1 and is_error(elements[0]):
            return elements[0]
        return objects.Array(elements)
    elif isinstance(node, ast.HashLiteral):
        return evaluate_hash_literal(node, env)
    elif isinstance(node, ast.Boolean):
        if node.value:
            return objects.Boolean(True)
        return objects.Boolean(False)
    elif isinstance(node, ast.PrefixExpression):
        right = evaluate(node.right, env)
        if is_error(right):
            return right
        return evaluate_prefix_expression(node.operator, right)
    elif isinstance(node, ast.InfixExpression):
        left = evaluate(node.left, env)
        if is_error(left):
            return left
        right = evaluate(node.right, env)
        if is_error(right):
            return right
        return evaluate_infix_expression(node.operator, left, right)
    elif isinstance(node, ast.IfExpression):
        return evaluate_if_expression(node, env)
    elif isinstance(node, ast.Identifier):
        return evaluate_identifier(node, env)
    elif isinstance(node, ast.FunctionLiteral):
        params = node.parameters
        body = node.body
        return objects.Function(params, body, env)
    elif isinstance(node, ast.CallExpression):
        function = evaluate(node.function, env)
        if is_error(function):
            return function
        args = evaluate_expressions(node.arguments, env)
        if len(args) == 1 and is_error(args[0]):
            return args[0]
        return apply_function(function, args)
    elif isinstance(node, ast.IndexExpression):
        left = evaluate(node.left, env)
        if is_error(left):
            return left
        index = evaluate(node.index, env)
        if is_error(index):
            return index
        return evaluate_index_expression(left, index)
    elif isinstance(node, ast.ImportExpression):
        return evaluate_import_expression(node, env)
    elif isinstance(node, ast.WhileStatement):
        return evaluate_while_statement(node, env)
    return None