class Interpret: def __init__(self, input_file): """[Interpreter for hasky lang] Args: input_file ([string none]): [Input] on_interpreter (bool, optional): [description]. Defaults to False. """ self.token = Token() self.parser = None # self.context = {} self.init_context() if not input_file: print(HASKY) self.start_interpreter() else: self.parser = Parser(self.token.lexer(input_file=input_file)) def start_interpreter(self): while True: try: text_ = input("hasky> ") except EOFError: break if not text_: continue parser = Parser(self.token.lexer(text=text_)) parser.program() self.interpret(parser.root_ast) def init_context(self): self.context = { "eval": ContextValue( "default", Function( "eval", None, lambda x: self.context[x.value.token_value].eval_cvalue(), ), ), "+": ContextValue( "default", Function( "+", None, lambda x, y: self.control_values(x, y) + self. control_values(y, x), ), ), "-": ContextValue( "default", Function( "-", None, lambda x, y: self.control_values(x, y) - self. control_values(y, x), ), ), "/": ContextValue( "default", Function( "/", None, lambda x, y: self.control_values(x, y) * self. control_values(y, x), ), ), "*": ContextValue( "default", Function( "*", None, lambda x, y: self.control_values(x, y) / self. control_values(y, x), ), ), "stack": ContextValue( "default", Function("stack", None, lambda _: self.print_context_data())), "type": ContextValue( "default", Function( "type", None, lambda a: self.context[untoken(ast_value(a))].cont_val_data .name, ), ), "latex": ContextValue( "default", Function("latex", None, lambda a: Latex(untoken(ast_value(a))).outprint()), ), } def print_context_data(self): for key, val in self.context.items(): print(f" {key}: {val.cont_val_data.value}") def control_values(self, a, b): def unbox(value_): try: return untoken(ast_value(value_.cont_val_data)) except: return untoken(ast_value(value_)) if type(unbox(a)) == type(unbox(b)): return unbox(a) elif unbox(a) in self.context: return unbox(self.context[unbox(a)]) elif unbox(b) in self.context: return unbox(a) else: raise DiffenrentTypes( "You are trying to call fucntion on two different types") def interpret(self, data=None, ast=[]): def return_lambda(fn, args, contx): if fn in contx: if contx[fn].cont_val_type == "default": return ast_value(contx[fn].cont_val_data)(*args) else: """this feauture shoudl be added to control_values fucntion""" data = list( map( lambda x: untoken(x.value), ast_value(contx[fn].cont_val_data), )) lambda_ = eval( f"lambda {data[1]}: {data[1]} {data[0]} {data[2]}") return lambda_(*args) else: return fn def search_function(name_of_function): for searching_fn in list( filter( lambda x: x.cont_val_type != "CallingFunction", self.context.values(), )): if (searching_fn.cont_val_data.name == "Function" and untoken(searching_fn.cont_val_data.keyword) == name_of_function.token_value): return searching_fn raise FunctionNotFound( f"Function {untoken(name_of_function)} not found") def check_context(local_cont, glob_cont, ch_val): try: found = local_cont[ch_val] """ if foudn fn is in global need to continue""" return found except KeyError: if ch_val in glob_cont: return glob_cont[ch_val].cont_val_data.value else: print(f"{ch_val} not found") """ FIXME this code break behaviour elif local_cont[ch_val] in glob_cont: if glob_cont[local_cont[ch_val]].cont_val_type == "default": return ast_value(glob_cont[local_cont[ch_val]].cont_val_data) else: data = list(map(lambda x: x.cont_val_data,glob_cont[found].cont_val_data.value)) return_lambda(data[0], *data[1:], glob_cont) k""" def control_eval(fnd_func, context, set_args={}): def ctrlvar_scp(local_scope, global_scope, variable): """fucntion that controlos value for first local scope and then for global scope""" if untoken(variable.value) in local_scope: return local_scope[untoken(variable.value)] elif untoken(variable.value) in global_scope: return untoken( ast_value(global_scope[untoken( variable.value)].cont_val_data)) else: return untoken(variable.value) for arg_number in range(len(fnd_func.cont_val_data.args)): set_args[untoken( fnd_func.cont_val_data.args[arg_number])] = untoken( operation.value[arg_number].value) func_ = check_context( set_args, context, untoken(ast_value(fnd_func.cont_val_data.value[0]))) args_ = list( map( lambda a: ctrlvar_scp(set_args, context, a), fnd_func.cont_val_data.value[1:], )) if isinstance(func_, types.LambdaType): return func_(*args_) else: return return_lambda(func_, args_, self.context) if not data and self.parser: print(self.parser.program()) ast = self.parser.root_ast else: ast = data if data else [] for operation in ast: # f"{operation.keyword.value}_{str(uuid.uuid4())[:8]}" key = untoken(operation.keyword) if key in self.context and operation.name != "CallingFunction": print(f"Variable {key} already exits") elif operation.name == "CallingFunction": try: found_fn = search_function(operation.keyword) except FunctionNotFound as fnf: print(fnf) return 1 if found_fn.cont_val_type != "default": """ if found function is not default user made it""" print(control_eval(found_fn, self.context)) else: """ fucntion is defautl""" if isinstance(operation.value[0], List): """refactoring need fix dry""" data = list( map(lambda x: untoken(x.value), operation.value[0].value)) lambda_ = eval( f"lambda _: {data[1]} {data[0]} {data[2]}") return found_fn.cont_val_data.value(lambda_(None)) else: # print(found_fn.cont_val_data.value(*operation.value[0])) try: print( found_fn.cont_val_data.value(*operation.value)) except KeyError as e: print(f"Variable {e.args[0]} doesn't exit") else: self.context[key] = ContextValue(operation.name, operation.value) print( f"{operation.keyword.token_value} = {operation.value[0].name}" )
self.next_token() self.ignore = True return self.expression() elif self.token.token_type == TokenType.left_braces: self.body() else: self.error("identifier") def body(self): # print("body") if self.token.token_type == TokenType.left_braces: self.next_token() self.binding_list() if self.is_identifier("in"): self.next_token() self.expression() else: self.error("in") if self.token.token_type == TokenType.right_braces: self.next_token() else: self.error("}}") else: self.error("{{") if __name__ == "__main__": t = Token() p = Parser(t.lexer()) print(p.program())