Пример #1
0
    def execute_run(self, exec_ctx):
        import main
        fn = exec_ctx.symbol_table.get("fn")

        if not isinstance(fn, String):
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                "Second argument must be string",
                exec_ctx
            ))

        fn = fn.value

        try:
            with open(fn, "r") as f:
                script = f.read()
        except Exception as e:
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                f"Failed to load script \"{fn}\"\n" + str(e),
                exec_ctx
            ))

        _, error = main.run(fn, script)
        
        if error:
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                f"Failed to finish executing script \"{fn}\"\n" +
                error.as_string(),
                exec_ctx
            ))

        return RuntimeResult().success(Number.null)
Пример #2
0
    def execute_pop(self, exec_ctx):
        list_ = exec_ctx.symbol_table.get("list")
        index = exec_ctx.symbol_table.get("index")

        if not isinstance(list_, LinkedList):
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                "First argument must be list",
                exec_ctx
            ))

        if not isinstance(index, Number):
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                "Second argument must be number",
                exec_ctx
            ))

        try:
            element = list_.elements.pop(index.value)
        except:
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                'Element at this index could not be removed from list because index is out of bounds',
                exec_ctx
            ))
        return RuntimeResult().success(element)
Пример #3
0
    def execute(self, args):
        res = RTResult()
        interpreter = inter.Interpreter()

        new_context = Context(self.name, self.context, self.pos_start)
        new_context.symbol_table = SymbolTable(new_context.parent.symbol_table)

        if len(args) < len(self.arg_names):
            return res.failure(
                RTError(
                    self.pos_start, self.pos_end,
                    f"'{len(self.arg_names) - len(args)}' less args than expected passed into '{self.name}",
                    self.context))

        if len(args) > len(self.arg_names):
            return res.failure(
                RTError(
                    self.pos_start, self.pos_end,
                    f"'{len(args) - len(self.arg_names)}' more args than expected passed into '{self.name}",
                    self.context))

        for i in range(len(args)):
            arg_name = self.arg_names[i]
            arg_value = args[i]
            arg_value.set_context(new_context)
            new_context.symbol_table.set(arg_name, arg_value)

        value = res.register(interpreter.visit(self.body_node, new_context))
        if res.error: return res
        return res.success(value)
Пример #4
0
 def div_by(self, other):
     if isinstance(other, Number):
         if other._value == 0:
             return None, RTError(other._start_pos, other._end_pos,
                                  "Division by Zero", self._context)
         return Number(self._value / other._value).set_context(
             self._context), None
Пример #5
0
 def illegal_operation(self, another = None):
     if not another:
         another = self
     return RTError(
         pos_start =self.pos_start, pos_end=self.pos_end,
         details= 'Illegal Operation',
         context = self.context
     )
Пример #6
0
 def dived_by(self, other):
     if isinstance(other, Number):
         if other.value == 0:
             return None, RTError(
                 other.pos_start, other.pos_end,
                 'Division by zero', self.context
             )
         return Number(self.value / other.value).set_context(self.context), None
Пример #7
0
    def check_args(self, arg_names, args):
        res = RuntimeResult()

        if len(args) > len(arg_names):
            return res.failure(RTError(
                self.pos_start, self.pos_end,
                f"{len(args) - len(arg_names)} too many args passed into {self}",
                self.context
            ))
        
        if len(args) < len(arg_names):
            return res.failure(RTError(
                self.pos_start, self.pos_end,
                f"{len(arg_names) - len(args)} too few args passed into {self}",
                self.context
            ))

        return res.success(None)
Пример #8
0
    def div_by(self, other):
        if isinstance(other, Number):
            if other.value == 0:
                return None, RTError(other.pos_start, other.pos_end,
                                     'Division by zero', self.context)

            return Number(self.value / other.value).set_context(
                self.context), None
        else:
            return None, Value.illegal_operation(self, other)
Пример #9
0
 def visit_VariableAccessNode(self, node, context):
     res = RuntimeResult()
     var_name = node.get_token().get_value()
     value = context._symbol_table.get(var_name)
     if not value:
         return res.failed(
             RTError(node.get_start_pos(), node.get_end_pos(),
                     f"'{var_name}' is not defined.", context))
     value = value.copy().set_position(node.get_start_pos(),
                                       node.get_end_pos())
     return res.success(value)
Пример #10
0
 def divided_by(self, num):
     if isinstance(num, Number):
         if num.value == 0:
             return None, RTError(
                 num.pos_start, num.pos_end,
                 'Division by zero',
                 self.context
             )
         return Number(self.value/num.value).set_context(self.context), None
     else:
         return None, Value.illegal_operation(self, num)
Пример #11
0
    def execute_len(self, exec_ctx):
        list_ = exec_ctx.symbol_table.get("list")

        if not isinstance(list_, LinkedList):
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                "Argument must be list",
                exec_ctx
            ))

        return RuntimeResult().success(Number(len(list_.elements)))
Пример #12
0
    def execute_extend(self, exec_ctx):
        listA = exec_ctx.symbol_table.get("listA")
        listB = exec_ctx.symbol_table.get("listB")

        if not isinstance(listA, LinkedList):
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                "First argument must be list",
                exec_ctx
            ))

        if not isinstance(listB, LinkedList):
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                "Second argument must be list",
                exec_ctx
            ))

        listA.elements.extend(listB.elements)
        return RuntimeResult().success(Number.null)
Пример #13
0
 def divided_by(self, other):
     if isinstance(other, Number):
         try:
             return self.elements[other.value], None
         except:
             return None, RTError(
             other.pos_start, other.pos_end,
             'Element at this index could not be retrieved from list because index is out of bounds',
             self.context
             )
     else:
         return None, Value.illegal_operation(self, other)
Пример #14
0
    def execute_append(self, exec_ctx):
        list_ = exec_ctx.symbol_table.get("list")
        value = exec_ctx.symbol_table.get("value")

        if not isinstance(list_, LinkedList):
            return RuntimeResult().failure(RTError(
                self.pos_start, self.pos_end,
                "First argument must be list",
                exec_ctx
            ))

        list_.elements.append(value)
        return RuntimeResult().success(Number.null)
Пример #15
0
    def visit_VarAccessNode(self, node, context):
        res = RuntimeResult()
        var_name = node.var_name_tok.value
        value = context.symbol_table.get(var_name)

        if not value:
            details = f"\'{var_name}\' is not defined"
            return res.failure(RTError(
                node.pos_start, node.pos_end,
                details,
                context
            ))
        value = value.copy().set_pos(node.pos_start, node.pos_end).set_context(context)
        return res.success(value)
Пример #16
0
 def subtracted_by(self, other):
     if isinstance(other, Number):
         new_list = self.copy()
         try:
             new_list.elements.pop(other.value)
             return new_list, None
         except:
             return None, RTError(
             other.pos_start, other.pos_end,
             'Element at this index could not be removed from list because index is out of bounds',
             self.context
             )
     else:
         return None, Value.illegal_operation(self, other)
Пример #17
0
    def visit_UnaryOperationNode(self, node):
        value_code, error = self.visit(node.node)
        if error:
            return None, error

        if node.operation_tok.type == PLUS:
            code = "+" + value_code
        elif node.operation_tok.type == MINUS:
            code = "-" + value_code
        #elif node.operation_tok.matches(KEYWORD, "nu"):
        #code = "!" + value_code
        else:
            return None, RTError(
                "Unary operator of type {} is unhandled!".format(
                    node.operation_tok.type), node.position_start,
                node.position_end)

        return "(" + code + ")", None
Пример #18
0
    def visit_BinaryOperationNode(self, node):
        left_code, error = self.visit(node.left_node)
        if error:
            return None, error

        right_code, error = self.visit(node.right_node)
        if error:
            return None, error

        if node.operation_tok.type == PLUS:
            code = left_code + "+" + right_code
        elif node.operation_tok.type == MINUS:
            code = left_code + "-" + right_code
        elif node.operation_tok.type == MUL:
            code = left_code + "*" + right_code
        elif node.operation_tok.type == DIV:
            code = left_code + "/" + right_code
        elif node.operation_tok.type == LT:
            code = left_code + "<" + right_code
        elif node.operation_tok.type == LTOREQ:
            code = left_code + "<=" + right_code
        elif node.operation_tok.type == GT:
            code = left_code + ">" + right_code
        elif node.operation_tok.type == GTOREQ:
            code = left_code + ">=" + right_code
        elif node.operation_tok.type == DOUBLE_EQUALS:
            code = left_code + "==" + right_code
        elif node.operation_tok.type == NOT_EQUALS:
            code = left_code + "!=" + right_code
        elif node.operation_tok.matches(KEYWORD, "si"):
            code = left_code + "&&" + right_code
        elif node.operation_tok.matches(KEYWORD, "sau"):
            code = left_code + "||" + right_code
        else:
            return None, RTError(
                "Binary operator of type {} is unhandled!".format(
                    node.operation_tok.type), node.position_start,
                node.position_end)

        return "(" + code + ")", None
Пример #19
0
 def illegal_operation(self, other=None):
     if not other: other = self
     return RTError(self.pos_start, other.pos_end, 'Illegal operation',
                    self.context)