Commit 4b90a4a3 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Rudimentary importing support

Doesn't handle packages or anything other than importing a .py file
(ex zip import, .so, .pyc), but has some basic support for
sys.path and sys.modules.
parent abcc2dd0
Pyston currently only supports installing from source; the following instructions have only been tested on Ubuntu, and currently has some non-trivial build issues on Mac (hopefully will be addressed soon once we get access to a Mac VM).
Pyston's build system expects to find all of its dependencies in `~/pyston_deps`:
```
mkdir ~/pyston_deps
```
The build instructions assume that you will put the Pyston source code in `~/pyston` and put the dependencies in `~/pyston_deps`. Barring any bugs, you should be free to put them anywhere you'd like, though the instructions in this file would have to be altered before following. Also, if you want to change the dependency dir, you'll have to change the value of the the `DEPS_DIR` variable in `src/Makefile`.
The instructions in this file assume that pyston is checked out to `~/pyston`, though it can be checked out anywhere as long as the rest of these instructions are appropriately modified.
Start off by making the relevant directories:
```
mkdir ~/pyston_deps
git clone https://github.com/dropbox/pyston.git ~/pyston
```
......@@ -74,6 +72,16 @@ make -j4
make install
```
Note: if you followed the previous version of the directions and installed libunwind globally, you'll need to uninstall it by doing the following:
```
cd ~/pyston_deps/libunwind-1.1
./configure
sudo make uninstall
```
and then repeat the correct process
### zsh
`zsh` is needed when running pyston tests.
```
......
......@@ -125,17 +125,6 @@ else
VALGRIND := VALGRIND_LIB=$(DEPS_DIR)/valgrind-3.9.0-install/lib/valgrind $(DEPS_DIR)/valgrind-3.9.0-install/bin/valgrind
endif
# Extra flags to enable soon:
COMMON_CXXFLAGS += -Wno-sign-conversion -Wnon-virtual-dtor -Winit-self -Wimplicit-int -Wmissing-include-dirs -Wstrict-overflow=5 -Wundef -Wpointer-arith -Wtype-limits -Wwrite-strings -Wempty-body -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-field-initializers -Wredundant-decls -Wnested-externs -Winline -Wint-to-pointer-cast -Wpointer-to-int-cast -Wlong-long -Wvla
# Want this one but there's a lot of places that I haven't followed it:
# COMMON_CXXFLAGS += -Wold-style-cast
# llvm headers fail on this one:
# COMMON_CXXFLAGS += -Wswitch-enum
# Not sure about these:
# COMMON_CXXFLAGS += -Wbad-function-cast -Wcast-qual -Wcast-align -Wmissing-prototypes -Wunreachable-code -Wfloat-equal -Wunused -Wunused-variable
# Or everything:
# COMMON_CXXFLAGS += -Weverything -Wno-c++98-compat-pedantic -Wno-shadow -Wno-padded -Wno-zero-length-array
# libunwind's include files warn on -Wextern-c-compat, so turn that off;
# ideally would just turn it off for header files in libunwind, maybe by
# having an internal libunwind.h that pushed/popped the diagnostic state,
......@@ -202,6 +191,17 @@ endif
CLANGFLAGS := $(CXXFLAGS) $(CLANG_EXTRA_FLAGS)
CLANGFLAGS_RELEASE := $(CXXFLAGS_RELEASE) $(CLANG_EXTRA_FLAGS)
# Extra flags to enable soon:
CLANGFLAGS += -Wno-sign-conversion -Wnon-virtual-dtor -Winit-self -Wimplicit-int -Wmissing-include-dirs -Wstrict-overflow=5 -Wundef -Wpointer-arith -Wtype-limits -Wwrite-strings -Wempty-body -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-field-initializers -Wredundant-decls -Wnested-externs -Winline -Wint-to-pointer-cast -Wpointer-to-int-cast -Wlong-long -Wvla
# Want this one but there's a lot of places that I haven't followed it:
# CLANGFLAGS += -Wold-style-cast
# llvm headers fail on this one:
# CLANGFLAGS += -Wswitch-enum
# Not sure about these:
# CLANGFLAGS += -Wbad-function-cast -Wcast-qual -Wcast-align -Wmissing-prototypes -Wunreachable-code -Wfloat-equal -Wunused -Wunused-variable
# Or everything:
# CLANGFLAGS += -Weverything -Wno-c++98-compat-pedantic -Wno-shadow -Wno-padded -Wno-zero-length-array
CXX := $(GPP)
CXX_PROFILE := $(GPP)
CLANG_CXX := $(CLANG_EXE)
......
......@@ -160,7 +160,7 @@ class DefinednessVisitor : public ASTVisitor {
case AST_TYPE::Subscript:
break;
case AST_TYPE::Tuple: {
AST_Tuple *tt = static_cast<AST_Tuple*>(t);
AST_Tuple *tt = ast_cast<AST_Tuple>(t);
for (int i = 0; i < tt->elts.size(); i++) {
_doSet(tt->elts[i]);
}
......@@ -192,17 +192,16 @@ class DefinednessVisitor : public ASTVisitor {
return true;
}
virtual bool visit_import(AST_Import *node) {
for (int i = 0; i < node->names.size(); i++) {
AST_alias *alias = node->names[i];
std::string &name = alias->name;
if (alias->asname.size())
name = alias->asname;
virtual bool visit_alias(AST_alias* node) {
const std::string* name = &node->name;
if (node->asname.size())
name = &node->asname;
_doSet(name);
}
_doSet(*name);
return true;
}
virtual bool visit_import(AST_Import *node) { return false; }
virtual bool visit_importfrom(AST_ImportFrom *node) { return false; }
virtual bool visit_assign(AST_Assign *node) {
for (int i = 0; i < node->targets.size(); i++) {
......
......@@ -63,10 +63,10 @@ static BoxedClass* simpleCallSpeculation(AST_Call* node, CompilerType* rtn_type,
return NULL;
}
if (node->func->type == AST_TYPE::Name && static_cast<AST_Name*>(node->func)->id == "xrange")
if (node->func->type == AST_TYPE::Name && ast_cast<AST_Name>(node->func)->id == "xrange")
return xrange_cls;
//if (node->func->type == AST_TYPE::Attribute && static_cast<AST_Attribute*>(node->func)->attr == "dot")
//if (node->func->type == AST_TYPE::Attribute && ast_cast<AST_Attribute>(node->func)->attr == "dot")
//return float_cls;
return NULL;
......@@ -141,12 +141,12 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
// doesn't affect types (yet?)
break;
case AST_TYPE::Name:
_doSet(static_cast<AST_Name*>(target)->id, t);
_doSet(ast_cast<AST_Name>(target)->id, t);
break;
case AST_TYPE::Subscript:
break;
case AST_TYPE::Tuple: {
AST_Tuple *tt = static_cast<AST_Tuple*>(target);
AST_Tuple *tt = ast_cast<AST_Tuple>(target);
for (int i = 0; i < tt->elts.size(); i++) {
_doSet(tt->elts[i], UNKNOWN);
}
......@@ -427,15 +427,22 @@ class BasicBlockTypePropagator : public ExprVisitor, public StmtVisitor {
virtual void visit_global(AST_Global* node) {
}
virtual void visit_alias(AST_alias* node) {
const std::string *name = &node->name;
if (node->asname.size())
name = &node->asname;
_doSet(*name, UNKNOWN);
}
virtual void visit_import(AST_Import *node) {
for (int i = 0; i < node->names.size(); i++) {
AST_alias *alias = node->names[i];
std::string &name = alias->name;
if (alias->asname.size())
name = alias->asname;
for (AST_alias* alias : node->names)
visit_alias(alias);
}
_doSet(name, UNKNOWN);
}
virtual void visit_importfrom(AST_ImportFrom *node) {
for (AST_alias* alias : node->names)
visit_alias(alias);
}
virtual void visit_jump(AST_Jump* node) {}
......@@ -542,7 +549,7 @@ class PropagatingTypeAnalysis : public TypeAnalysis {
for (int i = 0; i < arg_names.size(); i++) {
AST_expr* arg = arg_names[i];
assert(arg->type == AST_TYPE::Name);
AST_Name *arg_name = static_cast<AST_Name*>(arg);
AST_Name *arg_name = ast_cast<AST_Name>(arg);
initial_types[arg_name->id] = unboxedType(arg_types[i]);
}
}
......
......@@ -263,24 +263,7 @@ void printAllIR() {
fprintf(stderr, "==============\n");
}
static BoxedModule* main_module = NULL;
BoxedModule* createMainModule(const char* fn) {
//static std::unordered_map<AST_Module*, BoxedModule*> made;
//assert(made.count(m) == 0);
assert(main_module == NULL);
std::string s_fn;
if (fn != NULL)
s_fn = fn;
else
s_fn = "<stdin>";
std::string name("__main__");
main_module = createModule(&name, &s_fn);
return main_module;
}
int joinRuntime() {
assert(main_module != NULL);
// In the future this will have to wait for non-daemon
// threads to finish
......
......@@ -24,9 +24,7 @@ class CompiledFunction;
void initCodegen();
void teardownCodegen();
void printAllIR();
CompiledFunction* compileModule(AST_Module *m, BoxedModule* bm); // hacky but this method is actually defined in irgen.cpp
int joinRuntime();
BoxedModule* createMainModule(const char* fn);
}
......
......@@ -50,7 +50,7 @@ const std::string SourceInfo::getName() {
assert(ast);
switch (ast->type) {
case AST_TYPE::FunctionDef:
return static_cast<AST_FunctionDef*>(ast)->name;
return ast_cast<AST_FunctionDef>(ast)->name;
case AST_TYPE::Module:
return "module";
default:
......@@ -62,7 +62,7 @@ AST_arguments* SourceInfo::getArgsAST() {
assert(ast);
switch (ast->type) {
case AST_TYPE::FunctionDef:
return static_cast<AST_FunctionDef*>(ast)->args;
return ast_cast<AST_FunctionDef>(ast)->args;
case AST_TYPE::Module:
return NULL;
default:
......@@ -83,9 +83,9 @@ const std::vector<AST_stmt*>& SourceInfo::getBody() {
assert(ast);
switch (ast->type) {
case AST_TYPE::FunctionDef:
return static_cast<AST_FunctionDef*>(ast)->body;
return ast_cast<AST_FunctionDef>(ast)->body;
case AST_TYPE::Module:
return static_cast<AST_Module*>(ast)->body;
return ast_cast<AST_Module>(ast)->body;
default:
RELEASE_ASSERT(0, "%d", ast->type);
}
......@@ -226,7 +226,7 @@ static EffortLevel::EffortLevel initialEffort() {
return EffortLevel::MINIMAL;
}
CompiledFunction* compileModule(AST_Module *m, BoxedModule *bm) {
void compileAndRunModule(AST_Module *m, BoxedModule *bm) {
Timer _t("for compileModule()");
ScopingAnalysis *scoping = runScopingAnalysis(m);
......@@ -244,7 +244,12 @@ CompiledFunction* compileModule(AST_Module *m, BoxedModule *bm) {
CompiledFunction *cf = _doCompile(cl_f, new FunctionSignature(VOID, false), effort, NULL);
assert(cf->clfunc->versions.size());
return cf;
_t.end();
if (cf->is_interpreted)
interpretFunction(cf->func, 0, NULL, NULL, NULL, NULL);
else
((void (*)())cf->code)();
}
/// Reoptimizes the given function version at the new effort level.
......
......@@ -21,6 +21,10 @@ class OSRExit;
void* compilePartialFunc(OSRExit*);
extern "C" char* reoptCompiledFunc(CompiledFunction*);
class AST_Module;
class BoxedModule;
void compileAndRunModule(AST_Module *m, BoxedModule *bm);
}
#endif
This diff is collapsed.
......@@ -147,12 +147,12 @@ static int readColOffset(BufferedReader *reader) {
}
AST_alias* read_alias(BufferedReader *reader) {
AST_alias *rtn = new AST_alias();
std::string asname = readString(reader);
std::string name = readString(reader);
rtn->asname = readString(reader);
AST_alias *rtn = new AST_alias(name, asname);
rtn->col_offset = -1;
rtn->lineno = -1;
rtn->name = readString(reader);
return rtn;
}
......@@ -341,7 +341,7 @@ AST_FunctionDef* read_functiondef(BufferedReader *reader) {
printf("reading functiondef\n");
AST_FunctionDef *rtn = new AST_FunctionDef();
rtn->args = static_cast<AST_arguments*>(readASTMisc(reader));
rtn->args = ast_cast<AST_arguments>(readASTMisc(reader));
readStmtVector(rtn->body, reader);
rtn->col_offset = readColOffset(reader);
readExprVector(rtn->decorator_list, reader);
......@@ -386,13 +386,18 @@ AST_Import* read_import(BufferedReader *reader) {
rtn->col_offset = readColOffset(reader);
rtn->lineno = reader->readULL();
readMiscVector(rtn->names, reader);
return rtn;
}
int num_elts = reader->readShort();
for (int i = 0; i < num_elts; i++) {
AST* elt = readASTMisc(reader);
assert(elt->type == AST_TYPE::alias);
rtn->names.push_back(static_cast<AST_alias*>(elt));
}
AST_ImportFrom* read_importfrom(BufferedReader *reader) {
AST_ImportFrom *rtn = new AST_ImportFrom();
rtn->col_offset = readColOffset(reader);
rtn->level = reader->readULL();
rtn->lineno = reader->readULL();
rtn->module = readString(reader);
readMiscVector(rtn->names, reader);
return rtn;
}
......@@ -668,6 +673,8 @@ AST_stmt* readASTStmt(BufferedReader *reader) {
return read_if(reader);
case AST_TYPE::Import:
return read_import(reader);
case AST_TYPE::ImportFrom:
return read_importfrom(reader);
case AST_TYPE::Pass:
return read_pass(reader);
case AST_TYPE::Print:
......@@ -735,7 +742,7 @@ AST_Module* parse(const char* fn) {
static StatCounter us_parsing("us_parsing");
us_parsing.log(us);
return static_cast<AST_Module*>(rtn);
return ast_cast<AST_Module>(rtn);
}
#define MAGIC_STRING "a\ncg"
......@@ -843,7 +850,7 @@ AST_Module* caching_parse(const char* fn) {
static StatCounter us_parsing("us_parsing");
us_parsing.log(us);
return static_cast<AST_Module*>(rtn);
return ast_cast<AST_Module>(rtn);
}
}
......@@ -103,7 +103,8 @@ void initGlobalFuncs(GlobalState &g) {
g.llvm_opaque_type = llvm::StructType::create(g.context, "opaque");
g.llvm_clfunction_type_ptr = lookupFunction("boxCLFunction")->arg_begin()->getType();
g.llvm_module_type_ptr = lookupFunction("createModule")->getReturnType();
g.llvm_module_type_ptr = g.stdlib_module->getTypeByName("class.pyston::BoxedModule")->getPointerTo();
assert(g.llvm_module_type_ptr);
g.llvm_bool_type_ptr = lookupFunction("boxBool")->getReturnType();
g.llvm_value_type_ptr = lookupFunction("getattr")->getReturnType();
......
......@@ -51,6 +51,8 @@ std::string getOpSymbol(int op_type) {
return ">";
case AST_TYPE::GtE:
return ">=";
case AST_TYPE::In:
return "in";
case AST_TYPE::Invert:
return "~";
case AST_TYPE::Is:
......@@ -117,6 +119,8 @@ std::string getOpName(int op_type) {
return "__gt__";
case AST_TYPE::GtE:
return "__ge__";
case AST_TYPE::In:
return "__contains__";
case AST_TYPE::Invert:
return "__invert__";
case AST_TYPE::Mod:
......@@ -433,6 +437,17 @@ void AST_Import::accept_stmt(StmtVisitor *v) {
v->visit_import(this);
}
void AST_ImportFrom::accept(ASTVisitor *v) {
bool skip = v->visit_importfrom(this);
if (skip) return;
visitVector(names, v);
}
void AST_ImportFrom::accept_stmt(StmtVisitor *v) {
v->visit_importfrom(this);
}
void AST_Index::accept(ASTVisitor *v) {
bool skip = v->visit_index(this);
if (skip) return;
......@@ -976,6 +991,15 @@ bool PrintVisitor::visit_import(AST_Import *node) {
return true;
}
bool PrintVisitor::visit_importfrom(AST_ImportFrom *node) {
printf("from %s import ", node->module.c_str());
for (int i = 0; i < node->names.size(); i++) {
if (i > 0) printf(", ");
node->names[i]->accept(this);
}
return true;
}
bool PrintVisitor::visit_index(AST_Index *node) {
return false;
}
......@@ -1220,6 +1244,7 @@ class FlattenVisitor : public ASTVisitor {
virtual bool visit_global(AST_Global *node) { output->push_back(node); return false; }
virtual bool visit_if(AST_If *node) { output->push_back(node); return false; }
virtual bool visit_import(AST_Import *node) { output->push_back(node); return false; }
virtual bool visit_importfrom(AST_ImportFrom *node) { output->push_back(node); return false; }
virtual bool visit_index(AST_Index *node) { output->push_back(node); return false; }
virtual bool visit_keyword(AST_keyword *node) { output->push_back(node); return false; }
virtual bool visit_list(AST_List *node) { output->push_back(node); return false; }
......
This diff is collapsed.
......@@ -299,7 +299,7 @@ class CFGVisitor : public ASTVisitor {
// TODO this is a cludge to make sure that "callattrs" stick together.
// Probably better to create an AST_Callattr type, and solidify the
// idea that a callattr is a single expression.
rtn->func = remapAttribute(static_cast<AST_Attribute*>(node->func));
rtn->func = remapAttribute(ast_cast<AST_Attribute>(node->func));
} else {
rtn->func = remapExpr(node->func);
}
......@@ -594,52 +594,52 @@ class CFGVisitor : public ASTVisitor {
AST_expr* rtn;
switch (node->type) {
case AST_TYPE::Attribute:
rtn = remapAttribute(static_cast<AST_Attribute*>(node));
rtn = remapAttribute(ast_cast<AST_Attribute>(node));
break;
case AST_TYPE::BinOp:
rtn = remapBinOp(static_cast<AST_BinOp*>(node));
rtn = remapBinOp(ast_cast<AST_BinOp>(node));
break;
case AST_TYPE::BoolOp:
rtn = remapBoolOp(static_cast<AST_BoolOp*>(node));
rtn = remapBoolOp(ast_cast<AST_BoolOp>(node));
break;
case AST_TYPE::Call:
rtn = remapCall(static_cast<AST_Call*>(node));
rtn = remapCall(ast_cast<AST_Call>(node));
break;
case AST_TYPE::Compare:
rtn = remapCompare(static_cast<AST_Compare*>(node));
rtn = remapCompare(ast_cast<AST_Compare>(node));
break;
case AST_TYPE::Dict:
rtn = remapDict(static_cast<AST_Dict*>(node));
rtn = remapDict(ast_cast<AST_Dict>(node));
break;
case AST_TYPE::IfExp:
rtn = remapIfExp(static_cast<AST_IfExp*>(node));
rtn = remapIfExp(ast_cast<AST_IfExp>(node));
break;
case AST_TYPE::Index:
rtn = remapIndex(static_cast<AST_Index*>(node));
rtn = remapIndex(ast_cast<AST_Index>(node));
break;
case AST_TYPE::List:
rtn = remapList(static_cast<AST_List*>(node));
rtn = remapList(ast_cast<AST_List>(node));
break;
case AST_TYPE::ListComp:
rtn = remapListComp(static_cast<AST_ListComp*>(node));
rtn = remapListComp(ast_cast<AST_ListComp>(node));
break;
case AST_TYPE::Name:
return node;
case AST_TYPE::Num:
return node;
case AST_TYPE::Slice:
rtn = remapSlice(static_cast<AST_Slice*>(node));
rtn = remapSlice(ast_cast<AST_Slice>(node));
break;
case AST_TYPE::Str:
return node;
case AST_TYPE::Subscript:
rtn = remapSubscript(static_cast<AST_Subscript*>(node));
rtn = remapSubscript(ast_cast<AST_Subscript>(node));
break;
case AST_TYPE::Tuple:
rtn = remapTuple(static_cast<AST_Tuple*>(node));
rtn = remapTuple(ast_cast<AST_Tuple>(node));
break;
case AST_TYPE::UnaryOp:
rtn = remapUnaryOp(static_cast<AST_UnaryOp*>(node));
rtn = remapUnaryOp(ast_cast<AST_UnaryOp>(node));
break;
default:
RELEASE_ASSERT(0, "%d", node->type);
......@@ -674,6 +674,7 @@ class CFGVisitor : public ASTVisitor {
virtual bool visit_functiondef(AST_FunctionDef* node) { push_back(node); return true; }
virtual bool visit_global(AST_Global* node) { push_back(node); return true; }
virtual bool visit_import(AST_Import* node) { push_back(node); return true; }
virtual bool visit_importfrom(AST_ImportFrom* node) { push_back(node); return true; }
virtual bool visit_pass(AST_Pass* node) { return true; }
virtual bool visit_assign(AST_Assign* node) {
......@@ -708,7 +709,7 @@ class CFGVisitor : public ASTVisitor {
// TODO bad that it's reusing the AST nodes?
switch (node->target->type) {
case AST_TYPE::Name: {
AST_Name* n = static_cast<AST_Name*>(node->target);
AST_Name* n = ast_cast<AST_Name>(node->target);
assert(n->ctx_type == AST_TYPE::Store);
push_back(makeAssign(nodeName(node), makeName(n->id, AST_TYPE::Load)));
remapped_target = n;
......@@ -716,7 +717,7 @@ class CFGVisitor : public ASTVisitor {
break;
}
case AST_TYPE::Subscript: {
AST_Subscript *s = static_cast<AST_Subscript*>(node->target);
AST_Subscript *s = ast_cast<AST_Subscript>(node->target);
assert(s->ctx_type == AST_TYPE::Store);
AST_Subscript *s_target = new AST_Subscript();
......@@ -734,7 +735,7 @@ class CFGVisitor : public ASTVisitor {
break;
}
case AST_TYPE::Attribute: {
AST_Attribute *a = static_cast<AST_Attribute*>(node->target);
AST_Attribute *a = ast_cast<AST_Attribute>(node->target);
assert(a->ctx_type == AST_TYPE::Store);
AST_Attribute *a_target = new AST_Attribute();
......
......@@ -364,10 +364,12 @@ class BoxedClass : public HCBox {
// TODO these shouldn't be here
void setupRuntime();
void teardownRuntime();
extern "C" BoxedModule* createModule(const std::string *name, const std::string *fn);
BoxedModule* createModule(const std::string &name, const std::string &fn);
std::string getPythonFuncAt(void* ip, void* sp);
// TODO where to put this
void addToSysPath(const std::string &path);
}
......
......@@ -21,7 +21,8 @@
#include <sys/time.h>
#include "llvm/Support/ManagedStatic.h"
//#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
#include "core/common.h"
......@@ -33,8 +34,8 @@
#include "core/util.h"
#include "codegen/entry.h"
#include "codegen/llvm_interpreter.h"
#include "codegen/parser.h"
#include "codegen/irgen/hooks.h"
#ifndef GITREV
......@@ -103,10 +104,23 @@ int main(int argc, char** argv) {
initCodegen();
}
BoxedModule* main = createMainModule(fn);
BoxedModule* main = createModule("__main__", fn);
_t.split("to run");
if (fn != NULL) {
llvm::SmallString<128> path;
if (!llvm::sys::path::is_absolute(fn)) {
char cwd_buf[1026];
char* cwd = getcwd(cwd_buf, sizeof(cwd_buf));
assert(cwd);
path = cwd;
}
llvm::sys::path::append(path, fn);
llvm::sys::path::remove_filename(path);
addToSysPath(path.str());
int num_iterations = 1;
if (BENCH)
num_iterations = 1000;
......@@ -124,15 +138,7 @@ int main(int argc, char** argv) {
fprintf(stderr, "==============\n");
}
CompiledFunction* compiled = compileModule(m, main);
if (VERBOSITY() >= 1)
fprintf(stderr, "compiled module.main to machine code; running:\n");
if (compiled->is_interpreted)
interpretFunction(compiled->func, 0, NULL, NULL, NULL, NULL);
else
((void (*)())compiled->code)();
if (VERBOSITY() >= 1)
fprintf(stderr, "finished running\n");
compileAndRunModule(m, main);
}
}
......@@ -146,11 +152,7 @@ int main(int argc, char** argv) {
run++;
AST_Module *m = new AST_Module();
CompiledFunction* compiled = compileModule(m, main);
if (compiled->is_interpreted)
interpretFunction(compiled->func, 0, NULL, NULL, NULL, NULL);
else
((void (*)())compiled->code)();
compileAndRunModule(m, main);
if (run >= MAX_RUNS) {
printf("Quitting after %d iterations\n", run);
......@@ -201,7 +203,7 @@ int main(int argc, char** argv) {
removeDirectoryIfExists(tmpdir);
if (m->body.size() > 0 && m->body[0]->type == AST_TYPE::Expr) {
AST_Expr *e = static_cast<AST_Expr*>(m->body[0]);
AST_Expr *e = ast_cast<AST_Expr>(m->body[0]);
AST_Print *p = new AST_Print();
p->dest = NULL;
p->nl = true;
......@@ -209,11 +211,7 @@ int main(int argc, char** argv) {
m->body[0] = p;
}
CompiledFunction* compiled = compileModule(m, main);
if (compiled->is_interpreted)
interpretFunction(compiled->func, 0, NULL, NULL, NULL, NULL);
else
((void (*)())compiled->code)();
compileAndRunModule(m, main);
if (VERBOSITY() >= 1) {
gettimeofday(&end, NULL);
......
......@@ -222,9 +222,7 @@ BoxedClass *notimplemented_cls;
BoxedModule* builtins_module;
void setupBuiltins() {
std::string name("__builtin__");
std::string fn("__builtin__");
builtins_module = new BoxedModule(&name, &fn);
builtins_module = createModule("__builtin__", "__builtin__");
builtins_module->setattr("None", None, NULL, NULL);
......
......@@ -56,9 +56,7 @@ Box* mathTan(Box* b) {
}
void setupMath() {
std::string name("math");
std::string fn("__builtin__");
math_module = new BoxedModule(&name, &fn);
math_module = createModule("math", "__builtin__");
math_module->giveAttr("pi", boxFloat(M_PI));
......
// Copyright (c) 2014 Dropbox, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cmath>
#include "core/types.h"
#include "runtime/gc_runtime.h"
#include "runtime/types.h"
#include "runtime/util.h"
#include "runtime/inline/boxing.h"
#include "gc/collector.h"
namespace pyston {
BoxedModule* sys_module;
BoxedDict* sys_modules_dict;
BoxedDict* getSysModulesDict() {
// PyPy's behavior: fetch from sys.modules each time:
//Box *_sys_modules = sys_module->peekattr("modules");
//assert(_sys_modules);
//assert(_sys_modules->cls == dict_cls);
//return static_cast<BoxedDict*>(_sys_modules);
// CPython's behavior: return an internalized reference:
return sys_modules_dict;
}
BoxedList* getSysPath() {
// Unlike sys.modules, CPython handles sys.path by fetching it each time:
Box *_sys_path = sys_module->peekattr("path");
assert(_sys_path);
if (_sys_path->cls != list_cls) {
fprintf(stderr, "RuntimeError: sys.path must be a list of directory name\n");
raiseExc();
}
assert(_sys_path->cls == list_cls);
return static_cast<BoxedList*>(_sys_path);
}
void addToSysPath(const std::string &path) {
BoxedList *sys_path = getSysPath();
listAppendInternal(sys_path, boxStringPtr(&path));
}
void setupSys() {
sys_modules_dict = new BoxedDict();
gc::registerStaticRootObj(sys_modules_dict);
// This is ok to call here because we've already created the sys_modules_dict
sys_module = createModule("sys", "__builtin__");
sys_module->giveAttr("modules", sys_modules_dict);
BoxedList* sys_path = new BoxedList();
sys_module->giveAttr("path", sys_path);
}
}
......@@ -32,9 +32,7 @@ Box* timeTime() {
}
void setupTime() {
std::string name("time");
std::string fn("__builtin__");
time_module = new BoxedModule(&name, &fn);
time_module = createModule("time", "__builtin__");
time_module->giveAttr("time", new BoxedFunction(boxRTFunction((void*)timeTime, NULL, 0, false)));
}
......
......@@ -53,9 +53,7 @@ class BoxedCApiFunction : public Box {
};
extern "C" void* Py_InitModule4(const char *arg0, PyMethodDef *arg1, const char *arg2, PyObject *arg3, int arg4) {
std::string name("test");
std::string fn("../test/test_extension/test.so");
test_module = new BoxedModule(&name, &fn);
test_module = createModule("test", "../test/test_extension/test.so");
while (arg1->ml_name) {
if (VERBOSITY()) printf("Loading method %s\n", arg1->ml_name);
......
......@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef PYSTON_RUNTIME_IMPORTING_H
#define PYSTON_RUNTIME_IMPORTING_H
#ifndef PYSTON_RUNTIME_CAPI_H
#define PYSTON_RUNTIME_CAPI_H
namespace pyston {
......
......@@ -19,20 +19,25 @@
#include <cstring>
#include <memory>
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "core/ast.h"
#include "core/options.h"
#include "core/stats.h"
#include "core/types.h"
#include "codegen/parser.h"
#include "codegen/type_recording.h"
#include "codegen/irgen/hooks.h"
#include "asm_writing/icinfo.h"
#include "asm_writing/rewriter.h"
#include "asm_writing/rewriter2.h"
#include "runtime/capi.h"
#include "runtime/float.h"
#include "runtime/gc_runtime.h"
#include "runtime/importing.h"
#include "runtime/objmodel.h"
#include "runtime/types.h"
#include "runtime/util.h"
......@@ -2241,21 +2246,54 @@ extern "C" Box* getGlobal(BoxedModule* m, std::string *name, bool from_global) {
raiseExc();
}
// TODO I feel like importing should go somewhere else; it's more closely tied to codegen
// than to the object model.
extern "C" Box* import(const std::string *name) {
assert(name);
static StatCounter slowpath_import("slowpath_import");
slowpath_import.log();
assert(name);
BoxedDict *sys_modules = getSysModulesDict();
Box *s = boxStringPtr(name);
if (sys_modules->d.find(s) != sys_modules->d.end())
return sys_modules->d[s];
if ((*name) == "math") {
return math_module;
BoxedList *sys_path = getSysPath();
if (sys_path->cls != list_cls) {
fprintf(stderr, "RuntimeError: sys.path must be a list of directory name\n");
raiseExc();
}
if ((*name) == "time") {
return time_module;
llvm::SmallString<128> joined_path;
for (int i = 0; i < sys_path->size; i++) {
Box* _p = sys_path->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 + ".py");
std::string fn(joined_path.str());
if (VERBOSITY() >= 2) printf("Searching for %s at %s...\n", name->c_str(), fn.c_str());
bool exists;
llvm::error_code code = llvm::sys::fs::exists(joined_path.str(), exists);
assert(code == 0);
if (!exists)
continue;
if (VERBOSITY() >= 1) printf("Beginning import of %s...\n", fn.c_str());
// TODO duplication with jit.cpp:
BoxedModule* module = createModule(*name, fn);
AST_Module* ast = caching_parse(fn.c_str());
compileAndRunModule(ast, module);
return module;
}
if ((*name) == "test") {
if (*name == "test") {
return getTestModule();
}
......
......@@ -46,9 +46,9 @@ extern "C" BoxedFunction::BoxedFunction(CLFunction *f) : HCBox(&function_flavor,
}
}
BoxedModule::BoxedModule(const std::string *name, const std::string *fn) : HCBox(&module_flavor, module_cls), fn(*fn) {
this->giveAttr("__name__", boxString(*name));
this->giveAttr("__file__", boxString(*fn));
BoxedModule::BoxedModule(const std::string &name, const std::string &fn) : HCBox(&module_flavor, module_cls), fn(fn) {
this->giveAttr("__name__", boxString(name));
this->giveAttr("__file__", boxString(fn));
}
extern "C" Box* boxCLFunction(CLFunction *f) {
......@@ -230,10 +230,6 @@ extern "C" BoxedString* functionRepr(BoxedFunction* v) {
return new BoxedString("function");
}
extern "C" BoxedModule* createModule(const std::string *name, const std::string *fn) {
return new BoxedModule(name, fn);
}
extern "C" {
Box *None = NULL;
Box *NotImplemented = NULL;
......@@ -311,8 +307,11 @@ Box* moduleRepr(BoxedModule* m) {
os << sname->s;
}
// TODO not all modules will be built-in
os << "' (built-in)>";
if (m->fn == "__builtin__") {
os << "' (built-in)>";
} else {
os << "' from '" << m->fn << "'>";
}
return boxString(os.str());
}
......@@ -402,19 +401,30 @@ void setupRuntime() {
slice_cls->setattr("__str__", slice_cls->peekattr("__repr__"), NULL, NULL);
slice_cls->freeze();
// sys is the first module that needs to be set up, due to modules
// being tracked in sys.modules:
setupSys();
setupMath();
gc::registerStaticRootObj(math_module);
setupTime();
gc::registerStaticRootObj(time_module);
setupBuiltins();
gc::registerStaticRootObj(builtins_module);
setupCAPI();
TRACK_ALLOCATIONS = true;
}
BoxedModule* createModule(const std::string &name, const std::string &fn) {
assert(fn.size() && "probably wanted to set the fn to <stdin>?");
BoxedModule* module = new BoxedModule(name, fn);
BoxedDict* d = getSysModulesDict();
Box *b_name = boxStringPtr(&name);
assert(d->d.count(b_name) == 0);
d->d[b_name] = module;
return module;
}
void freeHiddenClasses(HiddenClass *hcls) {
for (auto it : hcls->children) {
freeHiddenClasses(it.second);
......
......@@ -50,17 +50,21 @@ void teardownFile();
void setupCAPI();
void teardownCAPI();
void setupSys();
void setupMath();
void setupTime();
void setupBuiltins();
BoxedDict* getSysModulesDict();
BoxedList* getSysPath();
extern "C" { extern BoxedClass *type_cls, *bool_cls, *int_cls, *float_cls, *str_cls, *function_cls, *none_cls, *instancemethod_cls, *list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls; }
extern "C" { extern const ObjectFlavor type_flavor, bool_flavor, int_flavor, float_flavor, str_flavor, function_flavor, none_flavor, instancemethod_flavor, list_flavor, slice_flavor, module_flavor, dict_flavor, tuple_flavor, file_flavor, xrange_flavor; }
extern "C" { extern const ObjectFlavor user_flavor; }
extern "C" { extern Box *None, *NotImplemented, *True, *False; }
extern "C" { extern Box *repr_obj, *len_obj, *hash_obj, *range_obj, *abs_obj, *min_obj, *max_obj, *open_obj, *chr_obj, *trap_obj; } // these are only needed for functionRepr, which is hacky
extern "C" { extern BoxedModule *math_module, *time_module, *builtins_module; }
extern "C" { extern BoxedModule *sys_module, *math_module, *time_module, *builtins_module; }
extern "C" Box* boxBool(bool);
extern "C" Box* boxInt(i64);
......@@ -82,65 +86,75 @@ extern "C" Box* createTuple(int64_t nelts, Box* *elts);
extern "C" void printFloat(double d);
struct BoxedInt : public Box {
int64_t n;
class BoxedInt : public Box {
public:
int64_t n;
BoxedInt(int64_t n) __attribute__((visibility("default"))) : Box(&int_flavor, int_cls), n(n) {}
BoxedInt(int64_t n) __attribute__((visibility("default"))) : Box(&int_flavor, int_cls), n(n) {}
};
struct BoxedFloat : public Box {
double d;
class BoxedFloat : public Box {
public:
double d;
BoxedFloat(double d) __attribute__((visibility("default"))) : Box(&float_flavor, float_cls), d(d) {}
BoxedFloat(double d) __attribute__((visibility("default"))) : Box(&float_flavor, float_cls), d(d) {}
};
struct BoxedBool : public Box {
bool b;
class BoxedBool : public Box {
public:
bool b;
BoxedBool(bool b) __attribute__((visibility("default"))) : Box(&bool_flavor, bool_cls), b(b) {}
BoxedBool(bool b) __attribute__((visibility("default"))) : Box(&bool_flavor, bool_cls), b(b) {}
};
struct BoxedString : public Box {
const std::string s;
class BoxedString : public Box {
public:
const std::string s;
BoxedString(const std::string &s) __attribute__((visibility("default"))) : Box(&str_flavor, str_cls), s(s) {}
BoxedString(const std::string &&s) __attribute__((visibility("default"))) : Box(&str_flavor, str_cls), s(std::move(s)) {}
BoxedString(const std::string &s) __attribute__((visibility("default"))) : Box(&str_flavor, str_cls), s(s) {}
};
struct BoxedInstanceMethod : public Box {
Box *obj, *func;
class BoxedInstanceMethod : public Box {
public:
Box *obj, *func;
BoxedInstanceMethod(Box *obj, Box *func) __attribute__((visibility("default"))) : Box(&instancemethod_flavor, instancemethod_cls), obj(obj), func(func) {}
BoxedInstanceMethod(Box *obj, Box *func) __attribute__((visibility("default"))) : Box(&instancemethod_flavor, instancemethod_cls), obj(obj), func(func) {}
};
struct BoxedList : public Box {
struct ElementArray : GCObject {
Box* elts[0];
class BoxedList : public Box {
public:
class ElementArray : GCObject {
public:
Box* elts[0];
ElementArray() : GCObject(&untracked_kind) {}
ElementArray() : GCObject(&untracked_kind) {}
void *operator new(size_t size, int capacity) {
return rt_alloc(capacity * sizeof(Box*) + sizeof(BoxedList::ElementArray));
}
};
void *operator new(size_t size, int capacity) {
return rt_alloc(capacity * sizeof(Box*) + sizeof(BoxedList::ElementArray));
}
};
int64_t size, capacity;
ElementArray *elts;
int64_t size, capacity;
ElementArray *elts;
BoxedList() __attribute__((visibility("default"))) : Box(&list_flavor, list_cls), size(0), capacity(0) {}
BoxedList() __attribute__((visibility("default"))) : Box(&list_flavor, list_cls), size(0), capacity(0) {}
void ensure(int space);
void ensure(int space);
};
struct BoxedTuple : public Box {
const std::vector<Box*> elts;
class BoxedTuple : public Box {
public:
const std::vector<Box*> elts;
BoxedTuple(std::vector<Box*> &elts) __attribute__((visibility("default"))) : Box(&tuple_flavor, tuple_cls), elts(elts) {}
BoxedTuple(std::vector<Box*> &elts) __attribute__((visibility("default"))) : Box(&tuple_flavor, tuple_cls), elts(elts) {}
};
struct BoxedFile : public Box {
FILE *f;
bool closed;
BoxedFile(FILE* f) __attribute__((visibility("default"))) : Box(&file_flavor, file_cls), f(f), closed(false) {}
class BoxedFile : public Box {
public:
FILE *f;
bool closed;
BoxedFile(FILE* f) __attribute__((visibility("default"))) : Box(&file_flavor, file_cls), f(f), closed(false) {}
};
struct PyHasher {
......@@ -155,24 +169,25 @@ struct PyLt {
bool operator()(Box*, Box*) const;
};
struct ConservativeWrapper : GCObject {
void* data[0];
class ConservativeWrapper : public GCObject {
public:
void* data[0];
ConservativeWrapper(size_t data_size) : GCObject(&conservative_kind), data() {
assert(data_size % sizeof(void*) == 0);
gc_header.kind_data = data_size;
}
ConservativeWrapper(size_t data_size) : GCObject(&conservative_kind), data() {
assert(data_size % sizeof(void*) == 0);
gc_header.kind_data = data_size;
}
void *operator new(size_t size, size_t data_size) {
assert(size == sizeof(ConservativeWrapper));
return rt_alloc(data_size + size);
}
void *operator new(size_t size, size_t data_size) {
assert(size == sizeof(ConservativeWrapper));
return rt_alloc(data_size + size);
}
static ConservativeWrapper* fromPointer(void* p) {
ConservativeWrapper* o = (ConservativeWrapper*)((void**)p - 1);
assert(&o->data == p);
return o;
}
static ConservativeWrapper* fromPointer(void* p) {
ConservativeWrapper* o = (ConservativeWrapper*)((void**)p - 1);
assert(&o->data == p);
return o;
}
};
template <class T>
......@@ -221,28 +236,32 @@ class StlCompatAllocator {
}
};
struct BoxedDict : public Box {
typedef std::unordered_map<Box*, Box*, PyHasher, PyEq, StlCompatAllocator<std::pair<Box*, Box*> > > PyDict;
PyDict d;
class BoxedDict : public Box {
public:
typedef std::unordered_map<Box*, Box*, PyHasher, PyEq, StlCompatAllocator<std::pair<Box*, Box*> > > PyDict;
PyDict d;
BoxedDict() __attribute__((visibility("default"))) : Box(&dict_flavor, dict_cls) {}
BoxedDict() __attribute__((visibility("default"))) : Box(&dict_flavor, dict_cls) {}
};
struct BoxedFunction : public HCBox {
CLFunction *f;
class BoxedFunction : public HCBox {
public:
CLFunction *f;
BoxedFunction(CLFunction *f);
BoxedFunction(CLFunction *f);
};
struct BoxedModule : public HCBox {
const std::string fn; // for traceback purposes; not the same as __file__
class BoxedModule : public HCBox {
public:
const std::string fn; // for traceback purposes; not the same as __file__
BoxedModule(const std::string *name, const std::string *fn);
BoxedModule(const std::string &name, const std::string &fn);
};
struct BoxedSlice : public HCBox {
Box *start, *stop, *step;
BoxedSlice(Box *lower, Box *upper, Box *step) : HCBox(&slice_flavor, slice_cls), start(lower), stop(upper), step(step) {}
class BoxedSlice : public HCBox {
public:
Box *start, *stop, *step;
BoxedSlice(Box *lower, Box *upper, Box *step) : HCBox(&slice_flavor, slice_cls), start(lower), stop(upper), step(step) {}
};
extern "C" void boxGCHandler(GCVisitor *v, void* p);
......
<module 'test' (built-in)>
<module 'test' from '../test/test_extension/test.so'>
[]
This will break
[]
......@@ -8,7 +8,7 @@ class C(object):
def __init__(self):
self.x = self.y = self.z = self.w = self.k = self.a = self.b = self.c = 1
for i in xrange(1000000):
for i in xrange(100000):
C()
print "This will break"
......
print "importing nested", __name__
y = 2
def bar():
print "bar"
class D(object):
pass
print "starting import of", __name__
import import_nested_target
x = 1
def foo():
print "foo()"
# def k():
# print x
# foo()
class C(object):
pass
# expected: fail
# (doesn't collapse '..' in module paths)
# imports test
import sys
print sys.path[0]
import import_target
print import_target.x
import import_target
import_target.foo()
c = import_target.C()
print import_target.import_nested_target.y
import_target.import_nested_target.bar()
d = import_target.import_nested_target.D()
print "testing importfrom:"
from import_target import x as z
print z
import_nested_target = 15
from import_nested_target import y
print "This should still be 15:",import_nested_target
import import_nested_target
print import_nested_target
print import_nested_target.y
import_target.import_nested_target.y = import_nested_target.y + 1
print import_nested_target.y
print z
print y
print __name__
# expected: fail
# (del statement)
# Not sure how important or necessary this behavior is, but
# CPython's behavior around sys.modules seems to be that it saves
# an internal reference to the object, so if you set sys.modules
# to something else, importing will still work. If you modify sys.modules,
# though, that affects importing.
# PyPy seems to not do this, and setting sys.modules to something else
# raises an exception when you try to import something else.
# Jython seems to crash.
import sys
print 'sys' in sys.modules
print 'import_target' in sys.modules
import import_target
import import_target
print 'import_target' in sys.modules
del sys.modules['import_target']
import import_target
import import_target
sys_modules = sys.modules
print "setting sys.modules=0"
sys.modules = 0
import import_target
print "clearing old sys.modules"
sys_modules.clear()
import import_target
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment