def compile_single(self, codeobject: Code, filename: str, element: Node, line_no: int, result_required: bool, scope: list) -> tuple: """ compiles a single Node """ codeobject.set_lineno(element.content[0].line_no) if isinstance(element.content[0], (IDNode, SymbolNode)): if element.content[0].content == 'defun': # wahey! creating a function! line_no, codeobject = self.compile_function( codeobject, filename, element, line_no ) elif element.content[0].content == 'lambda': raise Exception((element, element.content)) elif element.content[0].content in ('let', 'defparameter', 'defvar'): # inline variable assignments line_no, codeobject = self.handle_variable_assignment( codeobject, filename, element, line_no, scope ) else: # whahey! calling a function! line_no, codeobject = self.call_function( codeobject, filename, element, line_no, scope ) if not result_required: # if the result aint required, clean up the stack codeobject.POP_TOP() else: raise Exception('{} -> {}'.format(element, element.content)) return line_no, codeobject
def _generate_code(self): self.cache = cache = self.static_cache.copy() def callback(*args, **kw): types = tuple( [getattr(arg, '__class__', type(arg)) for arg in args]) key = tuple(map(istype, types)) self.__lock__.acquire() try: action = self.rules.default_action for sig in self.registry: if implies(key, sig): action = combine_actions(action, self.registry[sig]) f = cache[types] = compile_method(action, self) finally: self.__lock__.release() return f(*args, **kw) c = Code.from_function(self.function, copy_lineno=True) types = [ class_or_type_of(Local(name)) for name in flatten(inspect.getargspec(self.function)[0]) ] target = Call(Const(cache.get), (tuple(types), Const(callback))) c.return_(call_thru(self.function, target)) return c.code()
def _regen_code(self): c = Code.from_function(self.function, copy_lineno=True) c.return_( call_thru( self.function, Call( Getattr( Call(Const(Dispatching), (Const(self.function), ), fold=False), '_regenerate')))) return c.code()
def compile(buf, filename, add_return=False): lexer = Lexer(buf) parser = Parser(lexer) ast = parser.parse() ast.apply(SemanticAnalyser()) atoms = ast.getPProgram().getAtom() code = Code() code.co_filename = filename code.LOAD_CONST(None) for atom in atoms: load_value(atom, code) code.RETURN_VALUE() return code.code()
def compile_function(self, codeobject: Code, filename: str, element: Node, line_no: int) -> tuple: """ 'Compiles' function, using the last functions return value in the function body as the return value for the function proper """ _, name, args, *body = element.content name = name.content args = args.content args = [arg.content for arg in args] func_code = codeobject.nested(name, args) if body and any(el.content for el in body): *body, return_func = [el for el in body if el.content] # compile all bar the last statement for body_frag in body: line_no, func_code = self.compile_single( codeobject=func_code, filename=filename, element=body_frag, line_no=line_no, result_required=False, scope=args ) # compile the last statement, and ask for the result value line_no, func_code = self.compile_single( codeobject=func_code, filename=filename, element=return_func, line_no=line_no, result_required=True, scope=args ) func_code.RETURN_VALUE() else: func_code.return_() # inject the function into the codeobject codeobject = self.inject_function_code( codeobject=codeobject, function_codeobj=func_code.code(codeobject), name=name ) return line_no, codeobject
def as_abstract(self): for action in self.rules: raise AssertionError("Can't make abstract: rules already exist") c = Code.from_function(self.function, copy_lineno=True) c.return_(call_thru(self.function, Const(self.rules.default_action))) if self.backup is None: self.function.func_code = c.code() else: self.backup = c.code() return self.function
def _regen_code(self): c = Code.from_function(self.function, copy_lineno=True) c.return_( call_thru( self.function, Call(Getattr( Call(Const(Dispatching), (Const(self.function),), fold=False), '_regenerate' )) ) ) return c.code()
def as_abstract(self): for action in self.rules: raise AssertionError("Can't make abstract: rules already exist") c = Code.from_function(self.function, copy_lineno=True) c.return_(call_thru(self.function, Const(self.rules.default_action))) if self.backup is None: setattr(self.function, CODE, c.code()) else: self.backup = c.code() return self.function
def compile_parse_tree(self, filename: str, parse_tree) -> Code: """ Takes a filename and a parse_tree and returns a BytecodeAssembler Code object :param filename: filename of file to compile :param parse_tree: parse_tree to compile :rtype: Code """ filename = os.path.abspath(filename) line_no = -1 code = Code() code.set_lineno(line_no) code = self.bootstrap_obj(code) line_no += 1 code.co_filename = filename line_no, code = self.compile_parse_tree_internal( codeobject=code, parse_tree=parse_tree, line_no=line_no, filename=filename ) code.return_(None) return code
def _generate_code(self): self.cache = cache = self.static_cache.copy() def callback(*args, **kw): types = tuple([getattr(arg,'__class__',type(arg)) for arg in args]) key = tuple(map(istype, types)) self.__lock__.acquire() try: action = self.rules.default_action for sig in self.registry: if implies(key, sig): action = combine_actions(action, self.registry[sig]) f = cache[types] = compile_method(action, self) finally: self.__lock__.release() return f(*args, **kw) c = Code.from_function(self.function, copy_lineno=True) types = [class_or_type_of(Local(name)) for name in flatten(inspect.getargspec(self.function)[0])] target = Call(Const(cache.get), (tuple(types), Const(callback))) c.return_(call_thru(self.function, target)) return c.code()
def compile_atom(atom, c): if isinstance(atom, AVectorAtom): values = atom.getVector().getAtom() for value in values: load_value(value, c) c.BUILD_LIST(len(values)) return True if isinstance(atom, ADictAtom): values = atom.getDict().getAtom() n = len(values) / 2 c.LOAD_GLOBAL('dict') for i in range(n): load_value(values[i * 2], c) load_value(values[i * 2 + 1], c) c.CALL_FUNCTION(0, n) return True if isinstance(atom, AListAtom): xs = atom.getList().getAtom() head = xs[0] if isinstance(head, AListAtom): for x in xs: load_value(x, c) c.CALL_FUNCTION(len(xs) - 1) return True if isinstance(head, AIdentifierAtom): fn = head.getIdentifier().getText() c.set_lineno(head.getIdentifier().getLine()) if fn == 'def': var = xs[1].getIdentifier().getText() if load_value(xs[2], c): c.STORE_GLOBAL(var) c.LOAD_CONST(var) return True if fn == 'print': if load_value(xs[1], c): c.PRINT_ITEM() c.PRINT_NEWLINE() c.LOAD_CONST(None) return True if fn == 'if' or fn == 'ife': false_part = Label() finish = Label() load_value(xs[1], c) # eval condition c(false_part.JUMP_IF_FALSE) c.POP_TOP() # discard boolean result load_value(xs[2], c) c(finish.JUMP_ABSOLUTE) c(false_part) c.POP_TOP() # discard boolean result if len(xs) == 4: load_value(xs[3], c) else: c.LOAD_CONST(None) c(finish) return True if fn == 'let': pair = xs[1].getVector().getAtom() body = xs[2] n = len(pair) / 2 for i in range(n): load_value(pair[i * 2 + 1], c) print pair[i * 2] unpack_var(pair[i * 2], c) load_value(body, c) # todo: DELETE_FAST return True if fn == 'for': pair = xs[1].getVector().getAtom() var = pair[0] ls = pair[1] body = xs[2] for_loop = Label() for_end = Label() load_value(ls, c) c.GET_ITER() c(for_loop) c(for_end.FOR_ITER) unpack_var(pair[0], c) load_value(body, c) c.POP_TOP() c(for_loop.JUMP_ABSOLUTE) c(for_end) return True if fn == 'defn': name = xs[1].getIdentifier().getText() arguments = xs[2].getVector().getAtom() body = xs[3] func_code = Code() func_code.co_filename = c.co_filename func_code.co_name = name func_code.co_argcount = len(arguments) func_code.co_varnames = [arg.getIdentifier().getText() for arg in arguments] load_value(body, func_code) func_code.RETURN_VALUE() c.LOAD_CONST(func_code.code()) c.MAKE_FUNCTION(0) c.STORE_GLOBAL(name) c.LOAD_CONST(name) return True if fn == 'fn': arguments = xs[1].getVector().getAtom() body = xs[2] func_code = Code() func_code.co_filename = c.co_filename func_code.co_argcount = len(arguments) func_code.co_varnames = [arg.getIdentifier().getText() for arg in arguments] # func_code.co_cellvars = [] load_value(body, func_code) func_code.RETURN_VALUE() c.LOAD_CONST(func_code.code()) c.MAKE_FUNCTION(0) return True if fn == 'import': pkg = xs[1].getIdentifier().getText() c.LOAD_CONST(-1) if len(xs) == 3: names = [t.getIdentifier().getText() for t in xs[2].getVector().getAtom()] imports = tuple(names) c.LOAD_CONST(imports) c.IMPORT_NAME(pkg) for name in names: c.IMPORT_FROM(name) c.STORE_GLOBAL(name) else: c.LOAD_CONST(None) c.IMPORT_NAME(pkg) c.STORE_GLOBAL(pkg) return True if fn == '.': if isinstance(xs[1], AIdentifierAtom): load_value(xs[2], c) c.LOAD_ATTR(xs[1].getIdentifier().getText()) else: c.LOAD_GLOBAL('getattr') load_value(xs[2], c) load_value(xs[1], c) c.CALL_FUNCTION(2) return True if fn == 'exec': load_value(xs[1], c) c.MAKE_FUNCTION(0) c.CALL_FUNCTION(0) return True if load_var(head, c): for x in xs[1:]: load_value(x, c) c.CALL_FUNCTION(len(xs) - 1) return True return False