def new(self): self.name = self.ll_mod.name n = "__main__" if self.hlnode.is_main else self.hlnode.python_name self.v.ctx.add(c.Comment('Create module "{}" with __name__ "{}"'.format(self.hlnode.python_name, n))) self.v.ctx.add( c.Assignment( "=", c.ID(self.ll_mod.name), c.FuncCall(c.ID("PyModule_New"), c.ExprList(c.Constant("string", n))) ) ) self.fail_if_null(self.ll_mod.name) # get the modules dict mods = PyDictLL(None, self.v) mods.declare_tmp(name="_modules") self.v.ctx.add(c.Comment("Insert into sys.modules")) self.v.ctx.add(c.Assignment("=", c.ID(mods.name), c.FuncCall(c.ID("PyImport_GetModuleDict"), c.ExprList()))) self.fail_if_null(self.ll_mod.name) mods.incref() # add ourself to the modules dict mods.set_item_string(n, self) # clear the ref so we don't free it later mods.clear() # grab the module dict self.v.ctx.add( c.Assignment( "=", c.ID(self.ll_dict.name), c.FuncCall(c.ID("PyModule_GetDict"), c.ExprList(c.ID(self.ll_mod.name))) ) ) self.fail_if_null(self.ll_dict.name) # set the builtins on the module self.set_attr_string("__builtins__", self.v.builtins) # set builtin properties self.set_initial_string_attribute("__name__", n)
def attach_annotations(self, ret, args, vararg_name, vararg, kwonlyargs, kwarg_name, kwarg): if not (ret or args or vararg or kwonlyargs or kwarg): return self.v.ctx.add(c.Comment("build annotations dict")) tmp = PyDictLL(None, self.v) tmp.declare_tmp(name=self.hlnode.owner.name + '_annotations') tmp.new() if ret: tmp.set_item_string('return', ret) if vararg: tmp.set_item_string(vararg_name, vararg) if kwarg: tmp.set_item_string(kwarg_name, kwarg) for name, ann in args: if ann: tmp.set_item_string(str(name), ann) for name, ann in kwonlyargs: if ann: tmp.set_item_string(str(name), ann) self.c_obj.set_attr_string('__annotations__', tmp) tmp.decref()
class PyModuleLL(PyObjectLL): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # the ll instance representing the dict of global variables self.ll_dict = None # the ll name and instance representing the function that builds the module self.c_builder_name = self.v.tu.reserve_global_name(self.hlnode.name + "_builder") self.c_builder_func = None def declare(self): # create the namespace dict self.ll_dict = PyDictLL(self.hlnode, self.v) self.ll_dict.declare(is_global=True, quals=["static"], name=self.hlnode.name + "_dict") # create the module creation function self.c_builder_func = c.FuncDef( c.Decl( self.c_builder_name, c.FuncDecl(c.ParamList(), c.PtrDecl(c.TypeDecl(self.c_builder_name, c.IdentifierType("PyObject")))), quals=["static"], ), c.Compound(), ) self.v.tu.add_fwddecl(self.c_builder_func.decl) self.v.tu.add(self.c_builder_func) # declare the module self.ll_mod = PyObjectLL(self.hlnode, self.v) self.ll_mod.declare(is_global=True, quals=["static"]) def return_existing(self): self.v.ctx.add(c.If(c.ID(self.ll_mod.name), c.Compound(c.Return(c.ID(self.ll_mod.name))), None)) def new(self): self.name = self.ll_mod.name n = "__main__" if self.hlnode.is_main else self.hlnode.python_name self.v.ctx.add(c.Comment('Create module "{}" with __name__ "{}"'.format(self.hlnode.python_name, n))) self.v.ctx.add( c.Assignment( "=", c.ID(self.ll_mod.name), c.FuncCall(c.ID("PyModule_New"), c.ExprList(c.Constant("string", n))) ) ) self.fail_if_null(self.ll_mod.name) # get the modules dict mods = PyDictLL(None, self.v) mods.declare_tmp(name="_modules") self.v.ctx.add(c.Comment("Insert into sys.modules")) self.v.ctx.add(c.Assignment("=", c.ID(mods.name), c.FuncCall(c.ID("PyImport_GetModuleDict"), c.ExprList()))) self.fail_if_null(self.ll_mod.name) mods.incref() # add ourself to the modules dict mods.set_item_string(n, self) # clear the ref so we don't free it later mods.clear() # grab the module dict self.v.ctx.add( c.Assignment( "=", c.ID(self.ll_dict.name), c.FuncCall(c.ID("PyModule_GetDict"), c.ExprList(c.ID(self.ll_mod.name))) ) ) self.fail_if_null(self.ll_dict.name) # set the builtins on the module self.set_attr_string("__builtins__", self.v.builtins) # set builtin properties self.set_initial_string_attribute("__name__", n) # self.ll_module.set_initial_string_attribute(self.context, '__name__', self.hl_module.owner.python_name) def set_initial_string_attribute(self, name: str, s: str): if s is not None: ps = PyStringLL(None, self.v) ps.declare_tmp() ps.new(s) else: ps = PyObjectLL(None, self.v) ps.declare_tmp() ps.assign_none() self.set_attr_string(name, ps) ps.decref() def intro(self): self.v.scope.ctx.add_variable( c.Decl( "__return_value__", c.PtrDecl(c.TypeDecl("__return_value__", c.IdentifierType("PyObject"))), init=c.ID("NULL"), ), False, ) def outro(self): self.v.ctx.add(c.Assignment("=", c.ID("__return_value__"), c.ID(self.ll_mod.name))) self.v.ctx.add(c.Label("end")) for name in reversed(self.v.scope.ctx.cleanup): self.v.ctx.add(c.FuncCall(c.ID("Py_XDECREF"), c.ExprList(c.ID(name)))) self.v.ctx.add(c.Return(c.ID("__return_value__"))) @contextmanager def maybe_recursive_call(self): yield def del_attr_string(self, name: str): self.ll_dict.del_item_string(name) def set_attr_string(self, name: str, val: LLType): self.ll_dict.set_item_string(name, val) # FIXME: do we really need both dict and attr? don't these go to the same place? # super().set_attr_string(name, val) def get_attr_string(self, attrname: str, out: LLType): if str(attrname) in PY_BUILTINS: mode = "likely" else: mode = "unlikely" # access globals first, fall back to builtins -- remember to ref the global if we get it, since dict get item borrows # out.xdecref() self.ll_dict.get_item_string_nofail(attrname, out) frombuiltins = self.v.ctx.add( c.If(c.FuncCall(c.ID(mode), c.ExprList(c.UnaryOp("!", c.ID(out.name)))), c.Compound(), None) ) with self.v.new_context(frombuiltins.iftrue): self.v.builtins.get_attr_string_with_exception( attrname, out, "PyExc_NameError", "name '{}' is not defined".format(attrname) )