Ejemplo n.º 1
0
def join_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 `join` must be ARRAY, got {args[0].object_type().value}"
        )

    if args[1].object_type() != ObjectType.STRING_OBJ:
        return objects.Error(
            f"second argument to `join` must be STRING, got {args[1].object_type().value}"
        )

    elements = args[0].elements
    if len(elements) == 0:
        return objects.String("")
    if len(elements) == 1:
        return objects.String(str(elements[0]))

    max_ = len(elements) - 1

    out = f""

    for i, el in enumerate(elements):
        out += str(el)
        if i < max_:
            out += str(args[1])

    return objects.String(out)
Ejemplo n.º 2
0
def evaluate_string_infix_expression(operator: str, left: objects.Object,
                                     right: objects.Object) -> objects.Object:
    if operator == "+":
        return objects.String(left.value + right.value)
    elif operator == "==":
        return objects.Boolean(left.value == right.value)
    elif operator == "!=":
        return objects.Boolean(left.value != right.value)

    return new_error(
        f"unknown operator: {left.object_type().value} {operator} {right.object_type().value}"
    )
Ejemplo n.º 3
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}"
    )
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
def str_fn(args: List[objects.Object]) -> objects.Object:
    if len(args) != 1:
        return wrong_number_of_args(actual=len(args), expected=1)
    return objects.String(str(args[0]))
Ejemplo n.º 6
0
def type_fn(args: List[objects.Object]) -> objects.Object:
    if len(args) != 1:
        return wrong_number_of_args(actual=len(args), expected=1)
    return objects.String(args[0].object_type().value)
Ejemplo n.º 7
0
 def exported_hash(self) -> objects.Hash:
     pairs = {}
     for k, v in self.store.items():
         s = objects.String(k)
         pairs[s.hash_key()] = objects.HashPair(s, v)
     return objects.Hash(pairs)
Ejemplo n.º 8
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