extern "C" Box* boolRepr(BoxedBool* v) { static BoxedString* true_str = internStringImmortal("True"); static BoxedString* false_str = internStringImmortal("False"); if (v == True) return true_str; return false_str; }
static Box* createAndRunModule(BoxedString* name, const std::string& fn, const std::string& module_path) { BoxedModule* module = createModule(name, fn.c_str()); Box* b_path = boxString(module_path); BoxedList* path_list = new BoxedList(); listAppendInternal(path_list, b_path); static BoxedString* path_str = internStringImmortal("__path__"); module->setattr(path_str, path_list, NULL); AST_Module* ast = caching_parse_file(fn.c_str(), /* future_flags = */ 0); assert(ast); try { compileAndRunModule(ast, module); } catch (ExcInfo e) { removeModule(name); throw e; } Box* r = getSysModulesDict()->getOrNull(name); if (!r) raiseExcHelper(ImportError, "Loaded module %.200s not found in sys.modules", name->c_str()); return r; }
static Box* importSub(const std::string& name, BoxedString* full_name, Box* parent_module) { BoxedDict* sys_modules = getSysModulesDict(); if (sys_modules->d.find(full_name) != sys_modules->d.end()) { return sys_modules->d[full_name]; } BoxedList* path_list; if (parent_module == NULL || parent_module == None) { path_list = NULL; } else { static BoxedString* path_str = internStringImmortal("__path__"); path_list = static_cast<BoxedList*>(getattrInternal<ExceptionStyle::CXX>(parent_module, path_str)); if (path_list == NULL || path_list->cls != list_cls) { return None; } } SearchResult sr = findModule(name, full_name, path_list); if (sr.type != SearchResult::SEARCH_ERROR) { Box* module; try { if (sr.type == SearchResult::PY_SOURCE) module = createAndRunModule(full_name, sr.path); else if (sr.type == SearchResult::PKG_DIRECTORY) module = createAndRunModule(full_name, sr.path + "/__init__.py", sr.path); else if (sr.type == SearchResult::C_EXTENSION) module = importCExtension(full_name, name, sr.path); else if (sr.type == SearchResult::IMP_HOOK) { static BoxedString* loadmodule_str = internStringImmortal("load_module"); CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(1) }; module = callattr(sr.loader, loadmodule_str, callattr_flags, full_name, NULL, NULL, NULL, NULL); } else RELEASE_ASSERT(0, "%d", sr.type); } catch (ExcInfo e) { removeModule(full_name); throw e; } if (parent_module && parent_module != None) parent_module->setattr(internStringMortal(name), module, NULL); return module; }
BoxedString* getReverseOpName(int op_type) { bool reversed = false; op_type = getReverseCmpOp(op_type, reversed); if (reversed) return getOpName(op_type); BoxedString* normal_name = getOpName(op_type); // TODO inefficient return internStringImmortal(("__r" + normal_name->s().substr(2).str()).c_str()); }
InternedString InternedStringPool::get(llvm::StringRef arg) { // HACK: should properly track this liveness: BoxedString* s = internStringImmortal(arg); #ifndef NDEBUG return InternedString(s, this); #else return InternedString(s); #endif }
// Ported from the CPython version: BoxedClass* supercheck(BoxedClass* type, Box* obj) { if (PyType_Check(obj) && isSubclass(static_cast<BoxedClass*>(obj), type)) return static_cast<BoxedClass*>(obj); if (isSubclass(obj->cls, type)) { return obj->cls; } static BoxedString* class_str = internStringImmortal("__class__"); Box* class_attr = obj->getattr(class_str); if (class_attr && PyType_Check(class_attr) && class_attr != obj->cls) { Py_FatalError("warning: this path never tested"); // blindly copied from CPython return static_cast<BoxedClass*>(class_attr); } raiseExcHelper(TypeError, "super(type, obj): obj must be an instance or subtype of type"); }
void prependToSysPath(llvm::StringRef path) { BoxedList* sys_path = getSysPath(); static BoxedString* insert_str = internStringImmortal("insert"); CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(2) }; callattr(sys_path, insert_str, callattr_flags, boxInt(0), boxString(path), NULL, NULL, NULL); } static BoxedClass* sys_flags_cls; class BoxedSysFlags : public Box { public: Box* division_warning, *bytes_warning, *no_user_site, *optimize; BoxedSysFlags() { auto zero = boxInt(0); assert(zero); division_warning = zero; bytes_warning = zero; no_user_site = zero; optimize = zero; } DEFAULT_CLASS(sys_flags_cls); static void gcHandler(GCVisitor* v, Box* _b) { assert(_b->cls == sys_flags_cls); Box::gcHandler(v, _b); BoxedSysFlags* self = static_cast<BoxedSysFlags*>(_b); v->visit(self->division_warning); v->visit(self->bytes_warning); v->visit(self->no_user_site); v->visit(self->optimize); } static Box* __new__(Box* cls, Box* args, Box* kwargs) { raiseExcHelper(TypeError, "cannot create 'sys.flags' instances"); } }; static std::string generateVersionString() { std::ostringstream oss; oss << PYTHON_VERSION_MAJOR << '.' << PYTHON_VERSION_MINOR << '.' << PYTHON_VERSION_MICRO; oss << '\n'; oss << "[Pyston " << PYSTON_VERSION_MAJOR << '.' << PYSTON_VERSION_MINOR << "]"; return oss.str(); }
// Ported from the CPython version: template <ExceptionStyle S> BoxedClass* superCheck(BoxedClass* type, Box* obj) noexcept(S == CAPI) { if (PyType_Check(obj) && isSubclass(static_cast<BoxedClass*>(obj), type)) return static_cast<BoxedClass*>(obj); if (isSubclass(obj->cls, type)) { return obj->cls; } static BoxedString* class_str = internStringImmortal("__class__"); Box* class_attr = obj->getattr(class_str); if (class_attr && PyType_Check(class_attr) && class_attr != obj->cls) { Py_FatalError("warning: this path never tested"); // blindly copied from CPython return static_cast<BoxedClass*>(class_attr); } if (S == CXX) raiseExcHelper(TypeError, "super(type, obj): obj must be an instance or subtype of type"); else PyErr_SetString(TypeError, "super(type, obj): obj must be an instance or subtype of type"); return NULL; }
extern "C" PyObject* PyString_InternFromString(const char* s) noexcept { RELEASE_ASSERT(s, ""); return internStringImmortal(s); }
BoxedString* getInplaceOpName(int op_type) { BoxedString* normal_name = getOpName(op_type); // TODO inefficient return internStringImmortal(("__i" + normal_name->s().substr(2).str()).c_str()); }
/* Return the package that an import is being performed in. If globals comes from the module foo.bar.bat (not itself a package), this returns the sys.modules entry for foo.bar. If globals is from a package's __init__.py, the package's entry in sys.modules is returned, as a borrowed reference. The *name* of the returned package is returned in buf. If globals doesn't come from a package or a module in a package, or a corresponding entry is not found in sys.modules, Py_None is returned. */ static Box* getParent(Box* globals, int level, std::string& buf) { int orig_level = level; if (globals == NULL || globals == None || level == 0) return None; static BoxedString* package_str = internStringImmortal("__package__"); BoxedString* pkgname = static_cast<BoxedString*>(getFromGlobals(globals, package_str)); if (pkgname != NULL && pkgname != None) { /* __package__ is set, so use it */ if (pkgname->cls != str_cls) { raiseExcHelper(ValueError, "__package__ set to non-string"); } size_t len = pkgname->size(); if (len == 0) { if (level > 0) { raiseExcHelper(ValueError, "Attempted relative import in non-package"); } return None; } if (len > PATH_MAX) { raiseExcHelper(ValueError, "Package name too long"); } buf += pkgname->s(); } else { static BoxedString* name_str = internStringImmortal("__name__"); /* __package__ not set, so figure it out and set it */ BoxedString* modname = static_cast<BoxedString*>(getFromGlobals(globals, name_str)); if (modname == NULL || modname->cls != str_cls) return None; static BoxedString* path_str = internStringImmortal("__path__"); Box* modpath = getFromGlobals(globals, path_str); if (modpath != NULL) { /* __path__ is set, so modname is already the package name */ if (modname->size() > PATH_MAX) { raiseExcHelper(ValueError, "Module name too long"); } buf += modname->s(); setGlobal(globals, package_str, modname); } else { /* Normal module, so work out the package name if any */ size_t lastdot = modname->s().rfind('.'); if (lastdot == std::string::npos && level > 0) { raiseExcHelper(ValueError, "Attempted relative import in non-package"); } if (lastdot == std::string::npos) { setGlobal(globals, package_str, None); return None; } if (lastdot >= PATH_MAX) { raiseExcHelper(ValueError, "Module name too long"); } buf = std::string(modname->s(), 0, lastdot); setGlobal(globals, package_str, boxString(buf)); } } size_t dot = buf.size() - 1; while (--level > 0) { dot = buf.rfind('.', dot); if (dot == std::string::npos) { raiseExcHelper(ValueError, "Attempted relative import beyond toplevel package"); } dot--; } buf = std::string(buf, 0, dot + 1); BoxedDict* sys_modules = getSysModulesDict(); Box* boxed_name = boxString(buf); Box* parent = sys_modules->d.find(boxed_name) != sys_modules->d.end() ? sys_modules->d[boxed_name] : NULL; if (parent == NULL) { if (orig_level < 1) { printf("Warning: Parent module '%.200s' not found " "while handling absolute import\n", buf.c_str()); } else { raiseExcHelper(SystemError, "Parent module '%.200s' not loaded, " "cannot perform relative import", buf.c_str()); } } return parent; /* We expect, but can't guarantee, if parent != None, that: - parent.__name__ == buf - parent.__dict__ is globals If this is violated... Who cares? */ }
SearchResult findModule(const std::string& name, BoxedString* full_name, BoxedList* path_list) { static BoxedString* meta_path_str = internStringImmortal("meta_path"); BoxedList* meta_path = static_cast<BoxedList*>(sys_module->getattr(meta_path_str)); if (!meta_path || meta_path->cls != list_cls) raiseExcHelper(RuntimeError, "sys.meta_path must be a list of import hooks"); static BoxedString* findmodule_str = internStringImmortal("find_module"); for (int i = 0; i < meta_path->size; i++) { Box* finder = meta_path->elts->elts[i]; auto path_pass = path_list ? path_list : None; CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(2) }; Box* loader = callattr(finder, findmodule_str, callattr_flags, full_name, path_pass, NULL, NULL, NULL); if (loader != None) return SearchResult(loader); } if (!path_list) path_list = getSysPath(); if (path_list == NULL || path_list->cls != list_cls) { raiseExcHelper(RuntimeError, "sys.path must be a list of directory names"); } static BoxedString* path_hooks_str = internStringImmortal("path_hooks"); BoxedList* path_hooks = static_cast<BoxedList*>(sys_module->getattr(path_hooks_str)); if (!path_hooks || path_hooks->cls != list_cls) raiseExcHelper(RuntimeError, "sys.path_hooks must be a list of import hooks"); static BoxedString* path_importer_cache_str = internStringImmortal("path_importer_cache"); BoxedDict* path_importer_cache = static_cast<BoxedDict*>(sys_module->getattr(path_importer_cache_str)); if (!path_importer_cache || path_importer_cache->cls != dict_cls) raiseExcHelper(RuntimeError, "sys.path_importer_cache must be a dict"); llvm::SmallString<128> joined_path; for (int i = 0; i < path_list->size; i++) { Box* _p = path_list->elts->elts[i]; if (_p->cls != str_cls) continue; BoxedString* p = static_cast<BoxedString*>(_p); joined_path.clear(); llvm::sys::path::append(joined_path, p->s(), name); std::string dn(joined_path.str()); llvm::sys::path::append(joined_path, "__init__.py"); std::string fn(joined_path.str()); PyObject* importer = get_path_importer(path_importer_cache, path_hooks, _p); if (importer == NULL) throwCAPIException(); if (importer != None) { CallattrFlags callattr_flags{.cls_only = false, .null_on_nonexistent = false, .argspec = ArgPassSpec(1) }; Box* loader = callattr(importer, findmodule_str, callattr_flags, full_name, NULL, NULL, NULL, NULL); if (loader != None) return SearchResult(loader); } if (pathExists(fn)) return SearchResult(std::move(dn), SearchResult::PKG_DIRECTORY); joined_path.clear(); llvm::sys::path::append(joined_path, std::string(p->s()), name + ".py"); fn = joined_path.str(); if (pathExists(fn)) return SearchResult(std::move(fn), SearchResult::PY_SOURCE); joined_path.clear(); llvm::sys::path::append(joined_path, p->s(), name + ".pyston.so"); fn = joined_path.str(); if (pathExists(fn)) return SearchResult(std::move(fn), SearchResult::C_EXTENSION); } return SearchResult("", SearchResult::SEARCH_ERROR); } PyObject* PyImport_GetImporter(PyObject* path) noexcept { PyObject* importer = NULL, * path_importer_cache = NULL, * path_hooks = NULL; if ((path_importer_cache = PySys_GetObject("path_importer_cache"))) { if ((path_hooks = PySys_GetObject("path_hooks"))) { importer = get_path_importer(path_importer_cache, path_hooks, path); } } Py_XINCREF(importer); /* get_path_importer returns a borrowed reference */ return importer; }