def execute_run(self, exec_ctx): fn = exec_ctx.symbol_table.get("fn") if not isinstance(fn, String): return RTResult().failure( RTError(self.pos_start, self.pos_end, "First argument must be string", exec_ctx)) fn = fn.value try: with open(fn, "r") as f: if os.path.splitext(f.name)[1] == ".ds": script = f.read() else: return RTResult().failure( InvalidSyntaxError(self.pos_start, self.pos_end, f"{f.name} is not a valid file!")) except Exception as e: return RTResult().failure( RTError(self.pos_start, self.pos_end, f"Failed to load script \"{fn}\"\n" + str(e), exec_ctx)) _, error = run(fn, script) if error: return RTResult().failure( RTError( self.pos_start, self.pos_end, f"Failed to finish executing script \"{fn}\"\n" + error.as_string(), exec_ctx)) return RTResult().success(Number.null)
def execute_lower(self, exec_ctx): value = exec_ctx.symbol_table.get("value") if isinstance(value, String): lower = value.value.lower() else: return RTResult().failure( RTError(self.pos_start, self.pos_end, "Value is not a String", exec_ctx)) return RTResult().success(String(lower))
def execute_split(self, exec_ctx): value = exec_ctx.symbol_table.get("value") if not isinstance(value1, String): return RTResult().failure( RTError(self.pos_start, self.pos_end, "Value is not a String", exec_ctx)) return RTResult().success(String(value.value.split()))
def visit_VarAssignNode(self, node, context): res = RTResult() var_name = node.var_name_tok.value value = res.register(self.visit(node.value_node, context)) if res.should_return(): return res context.symbol_table.set(var_name, value) return res.success(value)
def execute_len(self, exec_ctx): value = exec_ctx.symbol_table.get("value") if isinstance(value, String): length = len(value.value) elif isinstance(value, List): length = len(value.value) else: return RTResult().failure( RTError(self.pos_start, self.pos_end, "Value is not String", exec_ctx)) return RTResult().success(Number(length))
def execute_ord(self, exec_ctx): value = exec_ctx.symbol_table.get("value") if isinstance(value, String): uni = ord(value.value[0]) else: return RTResult().failure( RTError(self.pos_start, self.pos_end, f"Value is not String", exec_ctx)) return RTResult().success(Number(uni))
def visit_ReturnNode(self, node, context): res = RTResult() if node.node_to_return: value = res.register(self.visit(node.node_to_return, context)) if res.should_return(): return res else: value = Number.null return res.success_return(value)
def execute_append(self, exec_ctx): list_ = exec_ctx.symbol_table.get("list") value = exec_ctx.symbol_table.get("value") if not isinstance(list_, List): return RTResult().failure( RTError(self.pos_start, self.pos_end, "First argument must be list", exec_ctx)) list_.elements.append(value) return RTResult().success(Number.null)
def execute_py_eval(self, exec_ctx): code = exec_ctx.symbol_table.get("code").value try: res = exec(code) except BaseException as e: return RTResult().failure( RTError(self.pos_start, self.pos_end, f"A error has occured when executing!\nError: {e}", exec_ctx)) return RTResult().success(String(res) if res else Number.null)
def execute_bin(self, exec_ctx): value = exec_ctx.symbol_table.get("value") if isinstance(value, Number): binop = bin(value.value) else: return RTResult().failure( RTError(self.pos_start, self.pos_end, f"Value is not a Number", exec_ctx)) return RTResult().success(Number(int(binop[2:])))
def visit_DictNode(self, node, context): res = RTResult() elements = [] for element_node in node.element_nodes: elements.append(res.register(self.visit(element_node, context))) if res.should_return(): return res return res.success( Dictionary(elements).set_context(context).set_pos( node.pos_start, node.pos_end) )
def visit_FuncDefNode(self, node, context): res = RTResult() func_name = node.var_name_tok.value if node.var_name_tok else None body_node = node.body_node arg_names = [arg_name.value for arg_name in node.arg_name_toks] func_value = Function(func_name, body_node, arg_names, node.should_auto_return).set_context( context).set_pos(node.pos_start, node.pos_end) if node.var_name_tok: context.symbol_table.set(func_name, func_value) return res.success(func_value)
def visit_VarAccessNode(self, node, context): res = RTResult() var_name = node.var_name_tok.value value = context.symbol_table.get(var_name) if not value: return res.failure(RTError( node.pos_start, node.pos_end, f"'{var_name}' is not defined", context )) value = value.copy().set_pos(node.pos_start, node.pos_end).set_context(context) return res.success(value)
def execute_reverse(self, exec_ctx): value = exec_ctx.symbol_table.get("value") if isinstance(value, List): value.elements.reverse() return RTResult().success(List(value.elements)) elif isinstance(value, String): return RTResult().success(String(value.value[::-1])) elif isinstance(value, Number): return RTResult().success(Number(int(str(value.value)[::-1]))) return RTResult().failure( RTError(self.pos_start, self.pos_end, "Value is not string, number, or list", exec_ctx))
def execute_random(self, exec_ctx): value1 = exec_ctx.symbol_table.get("value1") value2 = exec_ctx.symbol_table.get("value2") if not isinstance(value1, Number): return RTResult().failure( RTError(self.pos_start, self.pos_end, "Value1 is not a Number", exec_ctx)) if not isinstance(value2, Number): return RTResult().failure( RTError(self.pos_start, self.pos_end, "Value2 is not a Number", exec_ctx)) return RTResult().success( Number(random.randint(value1.value, value2.value)))
def execute_extend(self, exec_ctx): listA = exec_ctx.symbol_table.get("listA") listB = exec_ctx.symbol_table.get("listB") if not isinstance(listA, List): return RTResult().failure( RTError(self.pos_start, self.pos_end, "First argument must be list", exec_ctx)) if not isinstance(listB, List): return RTResult().failure( RTError(self.pos_start, self.pos_end, "Second argument must be list", exec_ctx)) listA.elements.extend(listB.elements) return RTResult().success(Number.null)
def visit_WhileNode(self, node, context): res = RTResult() elements = [] while True: condition = res.register(self.visit(node.condition_node, context)) if res.should_return(): return res if not condition.is_true(): break value = res.register(self.visit(node.body_node, context)) if res.should_return() and res.loop_should_continue == False and res.loop_should_break == False: return res if res.loop_should_continue: continue if res.loop_should_break: break elements.append(value) return res.success( Number.null if node.should_return_null else List(elements).set_context(context).set_pos( node.pos_start, node.pos_end) )
def check_args(self, arg_names, args): res = RTResult() 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 execute_input_int(self, exec_ctx): while True: text = input() try: number = int(text) break except ValueError: print(f"'{text}' must be an integer. Try again!") return RTResult().success(Number(number))
def check_and_populate_args(self, arg_names, args, exec_ctx): res = RTResult() res.register(self.check_args(arg_names, args)) if res.should_return(): return res self.populate_args(arg_names, args, exec_ctx) return res.success(None)
def execute(self, args): res = RTResult() exec_ctx = self.generate_new_context() method_name = f'execute_{self.name}' method = getattr(self, method_name, self.no_visit_method) res.register( self.check_and_populate_args(method.arg_names, args, exec_ctx)) if res.should_return(): return res return_value = res.register(method(exec_ctx)) if res.should_return(): return res return res.success(return_value)
def execute_pop(self, exec_ctx): list_ = exec_ctx.symbol_table.get("list") index = exec_ctx.symbol_table.get("index") if not isinstance(list_, List): return RTResult().failure( RTError(self.pos_start, self.pos_end, "First argument must be list", exec_ctx)) if not isinstance(index, Number): return RTResult().failure( RTError(self.pos_start, self.pos_end, "Second argument must be number", exec_ctx)) try: element = list_.elements.pop(index.value) except: return RTResult().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 RTResult().success(element)
def visit_CallNode(self, node, context): res = RTResult() args = [] value_to_call = res.register(self.visit(node.node_to_call, context)) if res.should_return(): return res value_to_call = value_to_call.copy().set_pos(node.pos_start, node.pos_end) for arg_node in node.arg_nodes: args.append(res.register(self.visit(arg_node, context))) if res.should_return(): return res return_value = res.register(value_to_call.execute(args)) if res.should_return(): return res return_value = return_value.copy().set_pos( node.pos_start, node.pos_end).set_context(context) return res.success(return_value)
def execute(self, args): res = RTResult() interpreter = Interpreter() exec_ctx = self.generate_new_context() res.register( self.check_and_populate_args(self.arg_names, args, exec_ctx)) if res.should_return(): return res value = res.register(interpreter.visit(self.body_node, exec_ctx)) if res.should_return() and res.func_return_value == None: return res ret_value = (value if self.should_auto_return else None) or res.func_return_value or Number.null return res.success(ret_value)
def visit_BinOpNode(self, node, context): res = RTResult() left = res.register(self.visit(node.left_node, context)) if res.should_return(): return res right = res.register(self.visit(node.right_node, context)) if res.should_return(): return res if node.op_tok.type == TT_PLUS: result, error = left.added_to(right) elif node.op_tok.type == TT_MINUS: result, error = left.subbed_by(right) elif node.op_tok.type == TT_MUL: result, error = left.multed_by(right) elif node.op_tok.type == TT_DIV: result, error = left.dived_by(right) elif node.op_tok.type == TT_POW: result, error = left.powed_by(right) elif node.op_tok.type == TT_EE: result, error = left.get_comparison_eq(right) elif node.op_tok.type == TT_NE: result, error = left.get_comparison_ne(right) elif node.op_tok.type == TT_LT: result, error = left.get_comparison_lt(right) elif node.op_tok.type == TT_GT: result, error = left.get_comparison_gt(right) elif node.op_tok.type == TT_LTE: result, error = left.get_comparison_lte(right) elif node.op_tok.type == TT_GTE: result, error = left.get_comparison_gte(right) elif node.op_tok.matches(TT_KEYWORD, 'and'): result, error = left.anded_by(right) elif node.op_tok.matches(TT_KEYWORD, 'or'): result, error = left.ored_by(right) if error: return res.failure(error) else: return res.success(result.set_pos(node.pos_start, node.pos_end))
def visit_UnaryOpNode(self, node, context): res = RTResult() number = res.register(self.visit(node.node, context)) if res.should_return(): return res error = None if node.op_tok.type == TT_MINUS: number, error = number.multed_by(Number(-1)) elif node.op_tok.matches(TT_KEYWORD, 'not'): number, error = number.notted() if error: return res.failure(error) else: return res.success(number.set_pos(node.pos_start, node.pos_end))
def execute_global(self, exec_ctx): _vars = [] for x in exec_ctx.symbol_table.parent.symbols: _vars.append(x) return RTResult().success(List(_vars))
def execute_lag(self, exec_ctx): return RTResult().success(String("LanguageArtsGrade"))
def execute_murgn(self, exec_ctx): return RTResult().success(String("is gay."))
def execute_getch(self, exec_ctx): value = getch().decode("utf-8") return RTResult().success(String(value))