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)
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)
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)
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
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 )
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
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)
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)
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)
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)
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)))
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)
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)
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)
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)
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)
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
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
def illegal_operation(self, other=None): if not other: other = self return RTError(self.pos_start, other.pos_end, 'Illegal operation', self.context)