def execute_findIndex(self, exec_ctx): string = exec_ctx.symbol_table.get('string') char = exec_ctx.symbol_table.get('char') if not isinstance(string, String): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "First argument must be a string", exec_ctx )) if not isinstance(char, String): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a string", exec_ctx )) if len(list(char.value)) > 1: return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a single character string", exec_ctx )) res_index = string.value.find(char.value) return RTResult().success(Number(res_index))
def execute_insert(self, exec_ctx): list_ = exec_ctx.symbol_table.get('list') index = exec_ctx.symbol_table.get('index') char = exec_ctx.symbol_table.get('char') if not isinstance(list_, List): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "First argument must be a list", exec_ctx )) if not isinstance(index, Number): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a number", exec_ctx )) if index.value > len(list_.elements): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be less than length of list", exec_ctx )) list_.elements.insert(index.value, char.value) return RTResult().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_, List): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "First argument must be a list", exec_ctx )) if not isinstance(index, Number): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a number", exec_ctx )) try: element = list_.elements.pop(index.value) except: return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Element at this index could not be removed from the list because the index is out of bounds", exec_ctx )) return RTResult().success(element)
def visit_VarAccessNode(self, node, context): res = RTResult() var_name = node.var_name_tok.value var_module_name = node.module_tok.value if node.module_tok else None if var_module_name: symbol_table = find_symbol_table(var_module_name) if not symbol_table: return res.failure(errors.RTError( node.pos_start, node.pos_end, f"'{var_module_name}' module is not defined", context )) value = symbol_table.get(var_name) else: value = context.symbol_table.get(var_name) if not value: return res.failure(errors.RTError( node.pos_start, node.pos_end, f"'{var_name}' is not defined", context )) # print(type(value)) value = value.copy().set_pos(node.pos_start, node.pos_end).set_context(context) return res.success(value)
def execute_concat(self, exec_ctx): str1 = exec_ctx.symbol_table.get('string1') str2 = exec_ctx.symbol_table.get('string2') if not isinstance(str1, String): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, "First argument must be a string", exec_ctx)) if not isinstance(str2, String): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, "Second argument must be a string", exec_ctx)) res_str = str1.value + str2.value return RTResult().success(String(res_str))
def execute_run(self, exec_ctx, importFile=False, module_name=""): global global_symbol_table if not importFile: global_symbol_table = reset_global_symbol_table() else: new_symbol_table = SymbolTable(parent=None, name = module_name) modules_symbol_table.append(new_symbol_table) fn = exec_ctx.symbol_table.get('fn') if not isinstance(fn, String): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Argument must be a string", exec_ctx )) a = fn.value.split('.') if a[len(a)-1] != "kode": return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "File extension must be .kode", exec_ctx )) fn = fn.value try: with open(fn, "r") as f: script = f.read() except Exception as e: return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, f"Failed to load the file \"{fn}\"\n" + str(e), exec_ctx )) _, error = run(fn, script, module_name) if error: return RTResult().failure(errors.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_max(self, exec_ctx): a = exec_ctx.symbol_table.get('b') b = exec_ctx.symbol_table.get('a') if not isinstance(a, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Argument must be a number", exec_ctx)) if not isinstance(b, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Argument must be a number", exec_ctx)) return RTResult().success(Number(max(a.value, b.value)))
def execute_min(self, exec_ctx): numberA = exec_ctx.symbol_table.get('numberA') numberB = exec_ctx.symbol_table.get('numberB') if not isinstance(numberA, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Argument must be a number", exec_ctx)) if not isinstance(numberB, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Argument must be a number", exec_ctx)) return RTResult().success(Number(min(numberA.value, numberB.value)))
def illegal_operation(self, other=None): if not other: other = self return errors.RTError( self.pos_start, other.pos_end, 'Illegal operation', self.context )
def visit_FunctionDefNode(self, node, context): res = RTResult() func_name = node.var_name_tok.value if node.var_name_tok else None if func_name in global_symbol_table.symbols: return res.failure(errors.RTError( node.pos_start, node.pos_end, f"There is a function called '{func_name}' already defined", context )) body_node = node.body_node arg_names = [arg_name.value for arg_name in node.arg_name_toks] optional_arg_names = [optional_arg.value for optional_arg in node.optional_arg_names] optional_arg_values = [] for i in node.optional_arg_values: optional_arg_values.append(res.register(self.visit(i, context))) if res.error: return res module = node.module func_value = Function(func_name, body_node, arg_names, optional_arg_names, optional_arg_values, node.should_auto_return, module).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_CallNode(self, node, context): res = RTResult() args = [] optional_arg_names = [] optional_arg_values = [] 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 optional_names = value_to_call.optional_arg_names for i in range(len(node.optional_arg_names)): if node.optional_arg_names[i].value not in optional_names: return res.failure(errors.RTError( node.pos_start, node.pos_end, f"There is no argument named {node.optional_arg_names[i].var_name_tok.value}", context )) optional_arg_names.append(node.optional_arg_names[i].value) optional_arg_values.append(res.register(self.visit(node.optional_arg_values[i], context))) return_value = res.register(value_to_call.execute(args, optional_arg_names, optional_arg_values)) 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_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( errors.RTError(self.pos_start, self.pos_end, "First argument must be a list", exec_ctx)) if not isinstance(listB, List): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, "Second argument must be a list", exec_ctx)) listA.elements.extend(listB.elements) return RTResult().success(Number.null)
def check_args(self, arg_names, args): res = RTResult() if len(args) > len(arg_names): return res.failure(errors.RTError( self.pos_start, self.pos_end, f"{len(args) - len(arg_names)} too many args passed into '{self.name}'", self.context )) if len(args) < len(arg_names): return res.failure(errors.RTError( self.pos_start, self.pos_end, f"{len(arg_names) - len(args)} too few args passed into '{self.name}'", self.context )) return res.success(None)
def execute_set(self, exec_ctx): list_ = exec_ctx.symbol_table.get('list') index = exec_ctx.symbol_table.get('index') value = exec_ctx.symbol_table.get('value') if not isinstance(list_, List) and not isinstance(list_, Dict): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "First argument must be a list", exec_ctx )) if isinstance(list_, List): if not isinstance(index, Number): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a number", exec_ctx )) try: list_.elements[index.value] = value except: return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Could not set that value to the list because the index is out of bounds", exec_ctx )) return RTResult().success(Number.null) if not isinstance(index, String): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a string", exec_ctx )) for k in list_.elements: if index.value == k.value: list_.elements[k] = value return RTResult().success(Number.null) list_.elements[index] = value return RTResult().success(Number.null)
def execute_to_str(self, exec_ctx): value = exec_ctx.symbol_table.get('value') if isinstance(value, BaseFunction): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Cannot convert Function to String", exec_ctx)) return RTResult().success(String(str(value)))
def execute_abs(self, exec_ctx): number = exec_ctx.symbol_table.get('number') if not isinstance(number, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Argument must be a number", exec_ctx)) return RTResult().success(Number(abs(number.value)))
def execute_len(self, exec_ctx): list_ = exec_ctx.symbol_table.get('list') if not isinstance(list_, List): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, "Argument must be a list", exec_ctx)) return RTResult().success(Number(len(list_.elements)))
def execute_get(self, exec_ctx): list_ = exec_ctx.symbol_table.get('list') index = exec_ctx.symbol_table.get('index') if not isinstance(list_, List) and not isinstance(list_, Dict): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "First argument must be a list or a dictionary", exec_ctx )) if isinstance(list_, List): if not isinstance(index, Number): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a number", exec_ctx )) try: return RTResult().success(list_.elements[index.value]) except: return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Element at this index could not be retrieved because the index is out of bounds", exec_ctx )) if not isinstance(index, String): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a string", exec_ctx )) for k in list_.elements: if index.value == k.value: return RTResult().success(list_.elements[k]) return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Could not get any value because that key doesn't exist", exec_ctx ))
def remainder_of(self, other): if isinstance(other, Number): if other.value == 0: return None, errors.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 execute_has_key(self, exec_ctx): d = exec_ctx.symbol_table.get('d') key = exec_ctx.symbol_table.get('key') if not isinstance(d, Dict): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"First argument must be a dictionary", exec_ctx)) if not isinstance(key, String): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Second argument must be a string", exec_ctx)) for k in d.elements: if key.value == k.value: return RTResult().success(Number.true) return RTResult().success(Number.false)
def execute_to_float(self, exec_ctx): number = exec_ctx.symbol_table.get('number') try: return RTResult().success(Number(float(number.value))) except: return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Argument can't be converted to Integer", exec_ctx))
def execute_range(self, exec_ctx): begin = exec_ctx.symbol_table.get('begin') end = exec_ctx.symbol_table.get('end') if not isinstance(begin, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"First argument must be a number", exec_ctx)) if not isinstance(end, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"First argument must be a number", exec_ctx)) arr = [] for i in range(begin.value, end.value): arr.append(Number(i)) return RTResult().success(List(arr))
def dived_by(self, other): if isinstance(other, Number): try: return self.elements[other.value], None except: return None, errors.RTError( other.pos_start, other.pos_end, "Element at this index could not be retrieved form the list because the 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_, List): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, "First argument must be a list", exec_ctx)) list_.elements.append(value) return RTResult().success(Number.null)
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( errors.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_imports(self, exec_ctx): path = exec_ctx.symbol_table.get('path') if not isinstance(path, String): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, "Argument must be a string", exec_ctx)) exec_ctx.symbol_table.set('fn', path) self.execute_run(exec_ctx, importFile=True) return RTResult().success(Number.null)
def execute_fact(self, exec_ctx): number = exec_ctx.symbol_table.get('number') if not isinstance(number, Number): return RTResult().failure( errors.RTError(self.pos_start, self.pos_end, f"Argument must be a number", exec_ctx)) fact = 1 for i in range(1, number.value + 1): fact = fact * i number.value = fact return RTResult().success(Number(number.value))
def execute_sort(self, exec_ctx): list_ = exec_ctx.symbol_table.get('list') if not isinstance(list_, List): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Argument must be a list", exec_ctx )) length = len(list_.elements) arr = [list_.elements[i].value for i in range(0,length)] return RTResult().success((List(sorted(arr))))
def execute_importAs(self, exec_ctx): path = exec_ctx.symbol_table.get('path') name = exec_ctx.symbol_table.get('name') if not isinstance(path, String): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "First argument must be a string", exec_ctx )) if not isinstance(name, String): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, "Second argument must be a string", exec_ctx )) exec_ctx.symbol_table.set('fn', path) self.execute_run(exec_ctx, importFile=True, module_name = name.value) return RTResult().success(Number.null)
def execute_is_prime(self, exec_ctx): number = exec_ctx.symbol_table.get('number') if not isinstance(number, Number): return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, f"Argument must be a number", exec_ctx )) elif number.value%1 != 0: return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, f"Argument must be a positive integer", exec_ctx )) elif number.value <= 0: return RTResult().failure(errors.RTError( self.pos_start, self.pos_end, f"Argument must be a positive number", exec_ctx )) is_prime = Number.true if number.value == 1: is_prime = Number.false elif number.value == 2 or number.value == 3: is_prime = Number.true elif number.value%2 == 0: is_prime = Number.false elif number.value%3 == 0: is_prime = Number.false else: for i in range(5, int(number.value**(1/2))+1, 6): if number.value%i == 0 or number.value%(i+2) == 0: is_prime = number.false break return RTResult().success(is_prime)