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 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_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