Commit 22adf0c9 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'sqlalchemy2'

Conflicts:
	src/runtime/types.cpp
parents 3c62f10f b0c5cc2f
...@@ -525,17 +525,9 @@ check: ...@@ -525,17 +525,9 @@ check:
quick_check: quick_check:
$(MAKE) pyston_dbg $(MAKE) pyston_dbg
$(call checksha,./pyston_dbg -q $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d) $(MAKE) check_format
$(call checksha,./pyston_dbg -qn $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d) $(MAKE) unittests
$(call checksha,./pyston_dbg -qO $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d) $(PYTHON) $(TOOLS_DIR)/tester.py -R pyston_dbg -j$(TEST_THREADS) -a=-S -k --order-by-mtime $(TESTS_DIR) $(ARGS)
$(MAKE) pyston
$(call checksha,./pyston -q $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
$(call checksha,./pyston -qn $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
$(call checksha,./pyston -qO $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
$(MAKE) pyston_prof
$(call checksha,./pyston_prof -q $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
$(call checksha,./pyston_prof -qn $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
$(call checksha,./pyston_prof -qO $(TESTS_DIR)/raytrace_small.py,0544f4621dd45fe94205219488a2576b84dc044d)
Makefile.local: Makefile.local:
echo "Creating default Makefile.local" echo "Creating default Makefile.local"
......
...@@ -132,6 +132,9 @@ PyObject* PyGC_AddRoot(PyObject*) PYSTON_NOEXCEPT; ...@@ -132,6 +132,9 @@ PyObject* PyGC_AddRoot(PyObject*) PYSTON_NOEXCEPT;
#define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str) #define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
#define PyDoc_STR(str) str #define PyDoc_STR(str) str
// This is in Python-ast.h in CPython, which we don't yet have:
int PyAST_Check(PyObject* obj) PYSTON_NOEXCEPT;
#ifdef __cplusplus #ifdef __cplusplus
#define PyMODINIT_FUNC extern "C" void #define PyMODINIT_FUNC extern "C" void
#else #else
......
...@@ -73,6 +73,7 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS} ...@@ -73,6 +73,7 @@ add_library(PYSTON_OBJECTS OBJECT ${OPTIONAL_SRCS}
gc/gc_alloc.cpp gc/gc_alloc.cpp
gc/heap.cpp gc/heap.cpp
runtime/bool.cpp runtime/bool.cpp
runtime/builtin_modules/ast.cpp
runtime/builtin_modules/builtins.cpp runtime/builtin_modules/builtins.cpp
runtime/builtin_modules/gc.cpp runtime/builtin_modules/gc.cpp
runtime/builtin_modules/pyston.cpp runtime/builtin_modules/pyston.cpp
......
...@@ -845,7 +845,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) { ...@@ -845,7 +845,7 @@ void ScopingAnalysis::processNameUsages(ScopingAnalysis::NameUsageMap* usages) {
} }
InternedStringPool& ScopingAnalysis::getInternedStrings() { InternedStringPool& ScopingAnalysis::getInternedStrings() {
return interned_strings; return *interned_strings;
} }
ScopeInfo* ScopingAnalysis::analyzeSubtree(AST* node) { ScopeInfo* ScopingAnalysis::analyzeSubtree(AST* node) {
...@@ -889,19 +889,25 @@ ScopeInfo* ScopingAnalysis::getScopeInfoForNode(AST* node) { ...@@ -889,19 +889,25 @@ ScopeInfo* ScopingAnalysis::getScopeInfoForNode(AST* node) {
return analyzeSubtree(node); return analyzeSubtree(node);
} }
ScopingAnalysis::ScopingAnalysis(AST_Module* m) ScopingAnalysis::ScopingAnalysis(AST* ast, bool globals_from_module)
: parent_module(m), interned_strings(*m->interned_strings.get()), globals_from_module(true) { : parent_module(NULL), globals_from_module(globals_from_module) {
scopes[m] = new ModuleScopeInfo(); switch (ast->type) {
} case AST_TYPE::Module:
assert(globals_from_module);
ScopingAnalysis::ScopingAnalysis(AST_Expression* e, bool globals_from_module) scopes[ast] = new ModuleScopeInfo();
: interned_strings(*e->interned_strings.get()), globals_from_module(globals_from_module) { interned_strings = static_cast<AST_Module*>(ast)->interned_strings.get();
// It's an expression, so it can't have a `global` statement parent_module = static_cast<AST_Module*>(ast);
scopes[e] = new EvalExprScopeInfo(globals_from_module); break;
} case AST_TYPE::Expression:
scopes[ast] = new EvalExprScopeInfo(globals_from_module);
ScopingAnalysis::ScopingAnalysis(AST_Suite* s, bool globals_from_module) interned_strings = static_cast<AST_Expression*>(ast)->interned_strings.get();
: interned_strings(*s->interned_strings.get()), globals_from_module(globals_from_module) { break;
scopes[s] = new EvalExprScopeInfo(s, globals_from_module); case AST_TYPE::Suite:
scopes[ast] = new EvalExprScopeInfo(ast, globals_from_module);
interned_strings = static_cast<AST_Suite*>(ast)->interned_strings.get();
break;
default:
RELEASE_ASSERT(0, "%d", ast->type);
}
} }
} }
...@@ -151,7 +151,7 @@ public: ...@@ -151,7 +151,7 @@ public:
private: private:
std::unordered_map<AST*, ScopeInfo*> scopes; std::unordered_map<AST*, ScopeInfo*> scopes;
AST_Module* parent_module; AST_Module* parent_module;
InternedStringPool& interned_strings; InternedStringPool* interned_strings;
std::unordered_map<AST*, AST*> scope_replacements; std::unordered_map<AST*, AST*> scope_replacements;
...@@ -170,9 +170,7 @@ public: ...@@ -170,9 +170,7 @@ public:
// a scope-node with a different node. // a scope-node with a different node.
void registerScopeReplacement(AST* original_node, AST* new_node); void registerScopeReplacement(AST* original_node, AST* new_node);
ScopingAnalysis(AST_Module* m); ScopingAnalysis(AST* ast, bool globals_from_module);
ScopingAnalysis(AST_Expression* e, bool globals_from_module);
ScopingAnalysis(AST_Suite* s, bool globals_from_module);
ScopeInfo* getScopeInfoForNode(AST* node); ScopeInfo* getScopeInfoForNode(AST* node);
InternedStringPool& getInternedStrings(); InternedStringPool& getInternedStrings();
......
...@@ -34,9 +34,9 @@ namespace pyston { ...@@ -34,9 +34,9 @@ namespace pyston {
DS_DEFINE_RWLOCK(codegen_rwlock); DS_DEFINE_RWLOCK(codegen_rwlock);
SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, const std::vector<AST_stmt*>& body, SourceInfo::SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, std::vector<AST_stmt*> body, std::string fn)
std::string fn) : parent_module(m), scoping(scoping), ast(ast), cfg(NULL), liveness(NULL), fn(std::move(fn)),
: parent_module(m), scoping(scoping), ast(ast), cfg(NULL), liveness(NULL), fn(std::move(fn)), body(body) { body(std::move(body)) {
assert(this->fn.size()); assert(this->fn.size());
switch (ast->type) { switch (ast->type) {
......
...@@ -313,7 +313,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -313,7 +313,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
RELEASE_ASSERT(fn, ""); RELEASE_ASSERT(fn, "");
bm->future_flags = getFutureFlags(m, fn); bm->future_flags = getFutureFlags(m, fn);
ScopingAnalysis* scoping = new ScopingAnalysis(m); ScopingAnalysis* scoping = new ScopingAnalysis(m, true);
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, m, m->body, fn)); std::unique_ptr<SourceInfo> si(new SourceInfo(bm, scoping, m, m->body, fn));
bm->setattr("__doc__", si->getDocString(), NULL); bm->setattr("__doc__", si->getDocString(), NULL);
...@@ -353,38 +353,78 @@ Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) { ...@@ -353,38 +353,78 @@ Box* evalOrExec(CLFunction* cl, Box* globals, Box* boxedLocals) {
return astInterpretFunctionEval(cf, globals, boxedLocals); return astInterpretFunctionEval(cf, globals, boxedLocals);
} }
template <typename AST_Type> CLFunction* compileForEvalOrExec(AST* source, std::vector<AST_stmt*> body, std::string fn) {
CLFunction* compileForEvalOrExec(AST_Type* source, std::vector<AST_stmt*>& body, std::string fn) {
LOCK_REGION(codegen_rwlock.asWrite()); LOCK_REGION(codegen_rwlock.asWrite());
Timer _t("for evalOrExec()"); Timer _t("for evalOrExec()");
ScopingAnalysis* scoping = new ScopingAnalysis(source, false); ScopingAnalysis* scoping = new ScopingAnalysis(source, false);
std::unique_ptr<SourceInfo> si(new SourceInfo(getCurrentModule(), scoping, source, body, std::move(fn))); std::unique_ptr<SourceInfo> si(new SourceInfo(getCurrentModule(), scoping, source, std::move(body), std::move(fn)));
CLFunction* cl_f = new CLFunction(0, 0, false, false, std::move(si)); CLFunction* cl_f = new CLFunction(0, 0, false, false, std::move(si));
return cl_f; return cl_f;
} }
static CLFunction* compileExec(llvm::StringRef source, llvm::StringRef fn) { // TODO: CPython parses execs as Modules, not as Suites. This is probably not too hard to change,
// but is non-trivial since we will later decide some things (ex in scoping_analysis) based off
// the type of the root ast node.
static AST_Suite* parseExec(llvm::StringRef source) {
// TODO error message if parse fails or if it isn't an expr // TODO error message if parse fails or if it isn't an expr
// TODO should have a cleaner interface that can parse the Expression directly // TODO should have a cleaner interface that can parse the Expression directly
// TODO this memory leaks // TODO this memory leaks
const char* code = source.data(); const char* code = source.data();
AST_Module* parsedModule = parse_string(code); AST_Module* parsedModule = parse_string(code);
AST_Suite* parsedSuite = new AST_Suite(std::move(parsedModule->interned_strings)); AST_Suite* parsedSuite = new AST_Suite(std::move(parsedModule->interned_strings));
parsedSuite->body = parsedModule->body; parsedSuite->body = std::move(parsedModule->body);
return parsedSuite;
}
static CLFunction* compileExec(AST_Suite* parsedSuite, llvm::StringRef fn) {
return compileForEvalOrExec(parsedSuite, parsedSuite->body, fn); return compileForEvalOrExec(parsedSuite, parsedSuite->body, fn);
} }
static AST_Expression* parseEval(llvm::StringRef source) {
const char* code = source.data();
// TODO error message if parse fails or if it isn't an expr
// TODO should have a cleaner interface that can parse the Expression directly
// TODO this memory leaks
// Hack: we need to support things like `eval(" 2")`.
// This is over-accepting since it will accept things like `eval("\n 2")`
while (*code == ' ' || *code == '\t' || *code == '\n' || *code == '\r')
code++;
AST_Module* parsedModule = parse_string(code);
if (parsedModule->body.size() == 0)
raiseSyntaxError("unexpected EOF while parsing", 0, 0, "<string>", "");
RELEASE_ASSERT(parsedModule->body.size() == 1, "");
RELEASE_ASSERT(parsedModule->body[0]->type == AST_TYPE::Expr, "");
AST_Expression* parsedExpr = new AST_Expression(std::move(parsedModule->interned_strings));
parsedExpr->body = static_cast<AST_Expr*>(parsedModule->body[0])->value;
return parsedExpr;
}
static CLFunction* compileEval(AST_Expression* parsedExpr, llvm::StringRef fn) {
// We need body (list of statements) to compile.
// Obtain this by simply making a single statement which contains the expression.
AST_Return* stmt = new AST_Return();
stmt->value = parsedExpr->body;
std::vector<AST_stmt*> body = { stmt };
return compileForEvalOrExec(parsedExpr, std::move(body), fn);
}
Box* compile(Box* source, Box* fn, Box* type, Box** _args) { Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
Box* flags = _args[0]; Box* flags = _args[0];
Box* dont_inherit = _args[0]; Box* dont_inherit = _args[1];
RELEASE_ASSERT(flags == boxInt(0), "");
RELEASE_ASSERT(dont_inherit == boxInt(0), ""); RELEASE_ASSERT(dont_inherit == boxInt(0), "");
RELEASE_ASSERT(flags->cls == int_cls, "");
int64_t iflags = static_cast<BoxedInt*>(flags)->n;
// source is allowed to be an AST, unicode, or anything that supports the buffer protocol // source is allowed to be an AST, unicode, or anything that supports the buffer protocol
if (source->cls == unicode_cls) { if (source->cls == unicode_cls) {
source = PyUnicode_AsUTF8String(source); source = PyUnicode_AsUTF8String(source);
...@@ -410,15 +450,47 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { ...@@ -410,15 +450,47 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
llvm::StringRef filename_str = static_cast<BoxedString*>(fn)->s; llvm::StringRef filename_str = static_cast<BoxedString*>(fn)->s;
llvm::StringRef type_str = static_cast<BoxedString*>(type)->s; llvm::StringRef type_str = static_cast<BoxedString*>(type)->s;
RELEASE_ASSERT(isSubclass(source->cls, str_cls), ""); if (iflags & ~(/*PyCF_MASK | PyCF_MASK_OBSOLETE | PyCF_DONT_IMPLY_DEDENT | */ PyCF_ONLY_AST)) {
llvm::StringRef source_str = static_cast<BoxedString*>(source)->s; raiseExcHelper(ValueError, "compile(): unrecognised flags");
}
bool only_ast = (bool)(iflags & PyCF_ONLY_AST);
iflags &= ~PyCF_ONLY_AST;
RELEASE_ASSERT(iflags == 0, "");
AST* parsed;
if (PyAST_Check(source)) {
parsed = unboxAst(source);
} else {
RELEASE_ASSERT(isSubclass(source->cls, str_cls), "");
llvm::StringRef source_str = static_cast<BoxedString*>(source)->s;
if (type_str == "exec") {
parsed = parseExec(source_str);
} else if (type_str == "eval") {
parsed = parseEval(source_str);
} else if (type_str == "single") {
fatalOrError(NotImplemented, "unimplemented");
throwCAPIException();
} else {
raiseExcHelper(ValueError, "compile() arg 3 must be 'exec', 'eval' or 'single'");
}
}
if (only_ast)
return boxAst(parsed);
CLFunction* cl; CLFunction* cl;
if (type_str == "exec") { if (type_str == "exec") {
cl = compileExec(source_str, filename_str); // TODO: CPython parses execs as Modules
if (parsed->type != AST_TYPE::Suite)
raiseExcHelper(TypeError, "expected Suite node, got %s", boxAst(parsed)->cls->tp_name);
cl = compileExec(static_cast<AST_Suite*>(parsed), filename_str);
} else if (type_str == "eval") { } else if (type_str == "eval") {
fatalOrError(NotImplemented, "unimplemented"); if (parsed->type != AST_TYPE::Expression)
throwCAPIException(); raiseExcHelper(TypeError, "expected Expression node, got %s", boxAst(parsed)->cls->tp_name);
cl = compileEval(static_cast<AST_Expression*>(parsed), filename_str);
} else if (type_str == "single") { } else if (type_str == "single") {
fatalOrError(NotImplemented, "unimplemented"); fatalOrError(NotImplemented, "unimplemented");
throwCAPIException(); throwCAPIException();
...@@ -429,14 +501,30 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) { ...@@ -429,14 +501,30 @@ Box* compile(Box* source, Box* fn, Box* type, Box** _args) {
return codeForCLFunction(cl); return codeForCLFunction(cl);
} }
Box* eval(Box* boxedCode) { Box* eval(Box* boxedCode, Box* globals, Box* locals) {
Box* boxedLocals = fastLocalsToBoxedLocals(); if (globals == None)
BoxedModule* module = getCurrentModule(); globals = NULL;
Box* globals = getGlobals();
if (locals == None)
locals = NULL;
if (locals == NULL) {
locals = globals;
}
if (locals == NULL) {
locals = fastLocalsToBoxedLocals();
}
if (globals == NULL)
globals = getGlobals();
BoxedModule* module = getCurrentModule();
if (globals && globals->cls == attrwrapper_cls && unwrapAttrWrapper(globals) == module) if (globals && globals->cls == attrwrapper_cls && unwrapAttrWrapper(globals) == module)
globals = module; globals = module;
assert(globals && (globals->cls == module_cls || globals->cls == dict_cls));
if (boxedCode->cls == unicode_cls) { if (boxedCode->cls == unicode_cls) {
boxedCode = PyUnicode_AsUTF8String(boxedCode); boxedCode = PyUnicode_AsUTF8String(boxedCode);
if (!boxedCode) if (!boxedCode)
...@@ -444,36 +532,16 @@ Box* eval(Box* boxedCode) { ...@@ -444,36 +532,16 @@ Box* eval(Box* boxedCode) {
// cf.cf_flags |= PyCF_SOURCE_IS_UTF8 // cf.cf_flags |= PyCF_SOURCE_IS_UTF8
} }
// TODO error message if parse fails or if it isn't an expr CLFunction* cl;
// TODO should have a cleaner interface that can parse the Expression directly if (boxedCode->cls == str_cls) {
// TODO this memory leaks AST_Expression* parsed = parseEval(static_cast<BoxedString*>(boxedCode)->s);
RELEASE_ASSERT(boxedCode->cls == str_cls, "%s", boxedCode->cls->tp_name); cl = compileEval(parsed, "<string>");
const char* code = static_cast<BoxedString*>(boxedCode)->s.data(); } else if (boxedCode->cls == code_cls) {
cl = clfunctionFromCode(boxedCode);
// Hack: we need to support things like `eval(" 2")`. } else {
// This is over-accepting since it will accept things like `eval("\n 2")` abort();
while (*code == ' ' || *code == '\t' || *code == '\n' || *code == '\r') }
code++; return evalOrExec(cl, globals, locals);
AST_Module* parsedModule = parse_string(code);
if (parsedModule->body.size() == 0)
raiseSyntaxError("unexpected EOF while parsing", 0, 0, "<string>", "");
RELEASE_ASSERT(parsedModule->body.size() == 1, "");
RELEASE_ASSERT(parsedModule->body[0]->type == AST_TYPE::Expr, "");
AST_Expression* parsedExpr = new AST_Expression(std::move(parsedModule->interned_strings));
parsedExpr->body = static_cast<AST_Expr*>(parsedModule->body[0])->value;
// We need body (list of statements) to compile.
// Obtain this by simply making a single statement which contains the expression.
AST_Return* stmt = new AST_Return();
stmt->value = parsedExpr->body;
std::vector<AST_stmt*> body = { stmt };
assert(globals && (globals->cls == module_cls || globals->cls == dict_cls));
CLFunction* cl = compileForEvalOrExec(parsedExpr, body, "<string>");
return evalOrExec(cl, globals, boxedLocals);
} }
Box* exec(Box* boxedCode, Box* globals, Box* locals) { Box* exec(Box* boxedCode, Box* globals, Box* locals) {
...@@ -530,7 +598,8 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) { ...@@ -530,7 +598,8 @@ Box* exec(Box* boxedCode, Box* globals, Box* locals) {
CLFunction* cl; CLFunction* cl;
if (boxedCode->cls == str_cls) { if (boxedCode->cls == str_cls) {
cl = compileExec(static_cast<BoxedString*>(boxedCode)->s, "<string>"); AST_Suite* parsed = parseExec(static_cast<BoxedString*>(boxedCode)->s);
cl = compileExec(parsed, "<string>");
} else if (boxedCode->cls == code_cls) { } else if (boxedCode->cls == code_cls) {
cl = clfunctionFromCode(boxedCode); cl = clfunctionFromCode(boxedCode);
} else { } else {
......
...@@ -38,7 +38,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm); ...@@ -38,7 +38,7 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm);
CompiledFunction* cfForMachineFunctionName(const std::string&); CompiledFunction* cfForMachineFunctionName(const std::string&);
extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals); extern "C" Box* exec(Box* boxedCode, Box* globals, Box* locals);
extern "C" Box* eval(Box* boxedCode); extern "C" Box* eval(Box* boxedCode, Box* globals, Box* locals);
extern "C" Box* compile(Box* source, Box* filename, Box* mode, Box** _args /* flags, dont_inherit */); extern "C" Box* compile(Box* source, Box* filename, Box* mode, Box** _args /* flags, dont_inherit */);
} }
......
...@@ -261,7 +261,7 @@ public: ...@@ -261,7 +261,7 @@ public:
Box* getDocString(); Box* getDocString();
SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, const std::vector<AST_stmt*>& body, std::string fn); SourceInfo(BoxedModule* m, ScopingAnalysis* scoping, AST* ast, std::vector<AST_stmt*> body, std::string fn);
}; };
typedef std::vector<CompiledFunction*> FunctionList; typedef std::vector<CompiledFunction*> FunctionList;
......
...@@ -136,7 +136,7 @@ public: ...@@ -136,7 +136,7 @@ public:
assert(((uint8_t*)cur + size) < end && "arena full"); assert(((uint8_t*)cur + size) < end && "arena full");
void* mrtn = mmap(cur, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); void* mrtn = mmap(cur, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert((uintptr_t)mrtn != -1 && "failed to allocate memory from OS"); RELEASE_ASSERT((uintptr_t)mrtn != -1, "failed to allocate memory from OS");
ASSERT(mrtn == cur, "%p %p\n", mrtn, cur); ASSERT(mrtn == cur, "%p %p\n", mrtn, cur);
cur = (uint8_t*)cur + size; cur = (uint8_t*)cur + size;
return mrtn; return mrtn;
......
// Copyright (c) 2014-2015 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 <algorithm>
#include <cmath>
#include <langinfo.h>
#include <sstream>
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "codegen/unwinding.h"
#include "core/types.h"
#include "gc/collector.h"
#include "runtime/file.h"
#include "runtime/inline/boxing.h"
#include "runtime/int.h"
#include "runtime/types.h"
#include "runtime/util.h"
namespace pyston {
static BoxedClass* AST_cls;
class BoxedAST : public Box {
public:
AST* ast;
BoxedAST() {}
};
static std::unordered_map<int, BoxedClass*> type_to_cls;
Box* boxAst(AST* ast) {
assert(ast);
BoxedClass* cls = type_to_cls[ast->type];
assert(cls);
BoxedAST* rtn = new (cls) BoxedAST();
assert(rtn->cls == cls);
rtn->ast = ast;
return rtn;
}
AST* unboxAst(Box* b) {
assert(isSubclass(b->cls, AST_cls));
AST* rtn = static_cast<BoxedAST*>(b)->ast;
assert(rtn);
return rtn;
}
extern "C" int PyAST_Check(PyObject* o) noexcept {
return isSubclass(o->cls, AST_cls);
}
void setupAST() {
BoxedModule* ast_module = createModule("_ast", "__builtin__");
ast_module->giveAttr("PyCF_ONLY_AST", boxInt(PyCF_ONLY_AST));
// ::create takes care of registering the class as a GC root.
#define MAKE_CLS(name, base_cls) \
BoxedClass* name##_cls = BoxedHeapClass::create(type_cls, base_cls, /* gchandler = */ NULL, 0, 0, \
sizeof(BoxedAST), false, STRINGIFY(name)); \
ast_module->giveAttr(STRINGIFY(name), name##_cls); \
type_to_cls[AST_TYPE::name] = name##_cls; \
name##_cls->giveAttr("__module__", boxString("_ast")); \
name##_cls->freeze()
AST_cls
= BoxedHeapClass::create(type_cls, object_cls, /* gchandler = */ NULL, 0, 0, sizeof(BoxedAST), false, "AST");
// ::create takes care of registering the class as a GC root.
AST_cls->giveAttr("__module__", boxString("_ast"));
AST_cls->freeze();
// TODO(kmod) you can call the class constructors, such as "ast.AST()", so we need new/init
// TODO(kmod) there is more inheritance than "they all inherit from AST"
MAKE_CLS(alias, AST_cls);
MAKE_CLS(arguments, AST_cls);
MAKE_CLS(Assert, AST_cls);
MAKE_CLS(Assign, AST_cls);
MAKE_CLS(Attribute, AST_cls);
MAKE_CLS(AugAssign, AST_cls);
MAKE_CLS(BinOp, AST_cls);
MAKE_CLS(BoolOp, AST_cls);
MAKE_CLS(Call, AST_cls);
MAKE_CLS(ClassDef, AST_cls);
MAKE_CLS(Compare, AST_cls);
MAKE_CLS(comprehension, AST_cls);
MAKE_CLS(Delete, AST_cls);
MAKE_CLS(Dict, AST_cls);
MAKE_CLS(Exec, AST_cls);
MAKE_CLS(ExceptHandler, AST_cls);
MAKE_CLS(ExtSlice, AST_cls);
MAKE_CLS(Expr, AST_cls);
MAKE_CLS(For, AST_cls);
MAKE_CLS(FunctionDef, AST_cls);
MAKE_CLS(GeneratorExp, AST_cls);
MAKE_CLS(Global, AST_cls);
MAKE_CLS(If, AST_cls);
MAKE_CLS(IfExp, AST_cls);
MAKE_CLS(Import, AST_cls);
MAKE_CLS(ImportFrom, AST_cls);
MAKE_CLS(Index, AST_cls);
MAKE_CLS(keyword, AST_cls);
MAKE_CLS(Lambda, AST_cls);
MAKE_CLS(List, AST_cls);
MAKE_CLS(ListComp, AST_cls);
MAKE_CLS(Module, AST_cls);
MAKE_CLS(Num, AST_cls);
MAKE_CLS(Name, AST_cls);
MAKE_CLS(Pass, AST_cls);
MAKE_CLS(Pow, AST_cls);
MAKE_CLS(Print, AST_cls);
MAKE_CLS(Raise, AST_cls);
MAKE_CLS(Repr, AST_cls);
MAKE_CLS(Return, AST_cls);
MAKE_CLS(Slice, AST_cls);
MAKE_CLS(Str, AST_cls);
MAKE_CLS(Subscript, AST_cls);
MAKE_CLS(TryExcept, AST_cls);
MAKE_CLS(TryFinally, AST_cls);
MAKE_CLS(Tuple, AST_cls);
MAKE_CLS(UnaryOp, AST_cls);
MAKE_CLS(With, AST_cls);
MAKE_CLS(While, AST_cls);
MAKE_CLS(Yield, AST_cls);
MAKE_CLS(Store, AST_cls);
MAKE_CLS(Load, AST_cls);
MAKE_CLS(Param, AST_cls);
MAKE_CLS(Not, AST_cls);
MAKE_CLS(In, AST_cls);
MAKE_CLS(Is, AST_cls);
MAKE_CLS(IsNot, AST_cls);
MAKE_CLS(Or, AST_cls);
MAKE_CLS(And, AST_cls);
MAKE_CLS(Eq, AST_cls);
MAKE_CLS(NotEq, AST_cls);
MAKE_CLS(NotIn, AST_cls);
MAKE_CLS(GtE, AST_cls);
MAKE_CLS(Gt, AST_cls);
MAKE_CLS(Mod, AST_cls);
MAKE_CLS(Add, AST_cls);
MAKE_CLS(Continue, AST_cls);
MAKE_CLS(Lt, AST_cls);
MAKE_CLS(LtE, AST_cls);
MAKE_CLS(Break, AST_cls);
MAKE_CLS(Sub, AST_cls);
MAKE_CLS(Del, AST_cls);
MAKE_CLS(Mult, AST_cls);
MAKE_CLS(Div, AST_cls);
MAKE_CLS(USub, AST_cls);
MAKE_CLS(BitAnd, AST_cls);
MAKE_CLS(BitOr, AST_cls);
MAKE_CLS(BitXor, AST_cls);
MAKE_CLS(RShift, AST_cls);
MAKE_CLS(LShift, AST_cls);
MAKE_CLS(Invert, AST_cls);
MAKE_CLS(UAdd, AST_cls);
MAKE_CLS(FloorDiv, AST_cls);
MAKE_CLS(DictComp, AST_cls);
MAKE_CLS(Set, AST_cls);
MAKE_CLS(Ellipsis, AST_cls);
MAKE_CLS(Expression, AST_cls);
MAKE_CLS(SetComp, AST_cls);
MAKE_CLS(Suite, AST_cls);
#undef MAKE_CLS
// Uncommenting this makes `import ast` work, which may or may not be desired.
// For now it seems like making the import fail is better than having the module not work properly.
// ast_module->giveAttr("__version__", boxInt(82160));
}
}
...@@ -1211,8 +1211,9 @@ void setupBuiltins() { ...@@ -1211,8 +1211,9 @@ void setupBuiltins() {
PyType_Ready(&PyBuffer_Type); PyType_Ready(&PyBuffer_Type);
builtins_module->giveAttr("buffer", &PyBuffer_Type); builtins_module->giveAttr("buffer", &PyBuffer_Type);
builtins_module->giveAttr( builtins_module->giveAttr("eval",
"eval", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)eval, UNKNOWN, 1, 0, false, false), "eval")); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)eval, UNKNOWN, 3, 2, false, false),
"eval", { NULL, NULL }));
builtins_module->giveAttr("callable", builtins_module->giveAttr("callable",
new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)callable, UNKNOWN, 1), "callable")); new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)callable, UNKNOWN, 1), "callable"));
......
...@@ -471,7 +471,7 @@ static bool loadNext(Box* mod, Box* altmod, std::string& name, std::string& buf, ...@@ -471,7 +471,7 @@ static bool loadNext(Box* mod, Box* altmod, std::string& name, std::string& buf,
static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool recursive); static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool recursive);
Box* importModuleLevel(const std::string& name, Box* globals, Box* from_imports, int level) { Box* importModuleLevel(const std::string& name, Box* globals, Box* from_imports, int level) {
assert(!globals || globals == None || isSubclass(globals->cls, module_cls)); RELEASE_ASSERT(!globals || globals == None || isSubclass(globals->cls, module_cls), "");
bool return_first = from_imports == None; bool return_first = from_imports == None;
static StatCounter slowpath_import("slowpath_import"); static StatCounter slowpath_import("slowpath_import");
......
...@@ -834,6 +834,32 @@ static Box* functionDefaults(Box* self, void*) { ...@@ -834,6 +834,32 @@ static Box* functionDefaults(Box* self, void*) {
return BoxedTuple::create(func->ndefaults, &func->defaults->elts[0]); return BoxedTuple::create(func->ndefaults, &func->defaults->elts[0]);
} }
static void functionSetDefaults(Box* b, Box* v, void*) {
RELEASE_ASSERT(v, "can't delete __defaults__");
assert(b->cls == function_cls);
BoxedFunction* func = static_cast<BoxedFunction*>(b);
if (v == None)
v = EmptyTuple;
if (!isSubclass(v->cls, tuple_cls)) {
raiseExcHelper(TypeError, "__defaults__ must be set to a tuple object");
}
BoxedTuple* t = static_cast<BoxedTuple*>(v);
if (t->size() == func->ndefaults) {
for (int i = 0; i < func->ndefaults; i++) {
func->defaults->elts[i] = t->elts[i];
}
return;
} else {
RELEASE_ASSERT(0, "can't change number of defaults on a function for now");
}
abort();
}
static Box* functionNonzero(BoxedFunction* self) { static Box* functionNonzero(BoxedFunction* self) {
return True; return True;
} }
...@@ -2256,9 +2282,10 @@ void setupRuntime() { ...@@ -2256,9 +2282,10 @@ void setupRuntime() {
new BoxedFunction(boxRTFunction((void*)functionCall, UNKNOWN, 1, 0, true, true))); new BoxedFunction(boxRTFunction((void*)functionCall, UNKNOWN, 1, 0, true, true)));
function_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)functionNonzero, BOXED_BOOL, 1))); function_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)functionNonzero, BOXED_BOOL, 1)));
function_cls->giveAttr("func_code", new (pyston_getset_cls) BoxedGetsetDescriptor(functionCode, NULL, NULL)); function_cls->giveAttr("func_code", new (pyston_getset_cls) BoxedGetsetDescriptor(functionCode, NULL, NULL));
function_cls->giveAttr("func_defaults",
new (pyston_getset_cls) BoxedGetsetDescriptor(functionDefaults, NULL, NULL));
function_cls->giveAttr("func_name", function_cls->getattr("__name__")); function_cls->giveAttr("func_name", function_cls->getattr("__name__"));
function_cls->giveAttr("func_defaults",
new (pyston_getset_cls) BoxedGetsetDescriptor(functionDefaults, functionSetDefaults, NULL));
function_cls->giveAttr("__defaults__", function_cls->getattr("func_defaults"));
function_cls->freeze(); function_cls->freeze();
builtin_function_or_method_cls->giveAttr( builtin_function_or_method_cls->giveAttr(
...@@ -2283,8 +2310,10 @@ void setupRuntime() { ...@@ -2283,8 +2310,10 @@ void setupRuntime() {
"__call__", new BoxedFunction(boxRTFunction((void*)instancemethodCall, UNKNOWN, 1, 0, true, true))); "__call__", new BoxedFunction(boxRTFunction((void*)instancemethodCall, UNKNOWN, 1, 0, true, true)));
instancemethod_cls->giveAttr( instancemethod_cls->giveAttr(
"im_func", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedInstanceMethod, func))); "im_func", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedInstanceMethod, func)));
instancemethod_cls->giveAttr("__func__", instancemethod_cls->getattr("im_func"));
instancemethod_cls->giveAttr( instancemethod_cls->giveAttr(
"im_self", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedInstanceMethod, obj))); "im_self", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, offsetof(BoxedInstanceMethod, obj)));
instancemethod_cls->giveAttr("__self__", instancemethod_cls->getattr("im_self"));
instancemethod_cls->freeze(); instancemethod_cls->freeze();
slice_cls->giveAttr("__new__", slice_cls->giveAttr("__new__",
...@@ -2331,6 +2360,7 @@ void setupRuntime() { ...@@ -2331,6 +2360,7 @@ void setupRuntime() {
setupGC(); setupGC();
setupImport(); setupImport();
setupPyston(); setupPyston();
setupAST();
PyType_Ready(&PyByteArrayIter_Type); PyType_Ready(&PyByteArrayIter_Type);
PyType_Ready(&PyCapsule_Type); PyType_Ready(&PyCapsule_Type);
......
...@@ -75,6 +75,7 @@ void setupBuiltins(); ...@@ -75,6 +75,7 @@ void setupBuiltins();
void setupPyston(); void setupPyston();
void setupThread(); void setupThread();
void setupImport(); void setupImport();
void setupAST();
void setupSysEnd(); void setupSysEnd();
BoxedDict* getSysModulesDict(); BoxedDict* getSysModulesDict();
...@@ -834,6 +835,9 @@ Box* unwrapAttrWrapper(Box* b); ...@@ -834,6 +835,9 @@ Box* unwrapAttrWrapper(Box* b);
Box* attrwrapperKeys(Box* b); Box* attrwrapperKeys(Box* b);
void attrwrapperDel(Box* b, const std::string& attr); void attrwrapperDel(Box* b, const std::string& attr);
Box* boxAst(AST* ast);
AST* unboxAst(Box* b);
#define SystemError ((BoxedClass*)PyExc_SystemError) #define SystemError ((BoxedClass*)PyExc_SystemError)
#define StopIteration ((BoxedClass*)PyExc_StopIteration) #define StopIteration ((BoxedClass*)PyExc_StopIteration)
#define NameError ((BoxedClass*)PyExc_NameError) #define NameError ((BoxedClass*)PyExc_NameError)
......
import _ast
def ast_parse(source, filename='<unknown>', mode='exec'):
return compile(source, filename, mode, _ast.PyCF_ONLY_AST)
# TODO(kmod) unfortunately we don't expose any of the data members yet, and we don't even display
# the types correctly, so just parse the code and make sure that we didn't crash
ast_parse("print 1")
ast_parse("print 1", "t.py", "exec")
ast_parse("1", "t.py", "eval")
c = compile(ast_parse("print 1", "t.py", "exec"), "u.py", "exec")
print c.co_filename
exec c
try:
c = compile(ast_parse("print 1", "t.py", "exec"), "u.py", "eval")
except Exception as e:
print type(e)
c = compile(ast_parse("print 2", "t.py", "exec"), "u.py", "exec")
print eval(c)
c = compile("a", "test.py", "eval")
print type(c), c.co_filename, c.co_name
print
a = 0
print eval(c)
print
a = 0
g = {'a':1}
print eval(c, g)
print
a = 0
g = {'a':1}
l = {'a':2}
print eval(c, g, l)
print
g = {}
exec """
c = compile("a", "test.py", "eval")
""" in g
a = 0
print eval(g['c'])
print
a = 0
g = {'a':1, '_c':c}
exec "print eval(_c)" in g
...@@ -19,3 +19,24 @@ f.func_name = "f" ...@@ -19,3 +19,24 @@ f.func_name = "f"
print f.__name__, f.func_name print f.__name__, f.func_name
print bool(f) print bool(f)
def func_with_defaults(a, b=1):
print a, b
func_with_defaults(0)
print type(func_with_defaults.func_code)
print func_with_defaults.func_defaults
print func_with_defaults.__defaults__
try:
func_with_defaults.func_defaults = [2]
except TypeError as e:
print e
# del func_with_defaults.__defaults__
# func_with_defaults.__defaults__ = (1, 2)
# func_with_defaults()
def func_without_defaults():
pass
print repr(func_without_defaults.__defaults__)
class C(object):
def foo(self):
pass
print type(C.foo)
print type(C.foo.im_func), type(C.foo.__func__)
print type(C.foo.im_self), type(C.foo.__self__)
...@@ -27,7 +27,7 @@ TEST_F(AnalysisTest, augassign) { ...@@ -27,7 +27,7 @@ TEST_F(AnalysisTest, augassign) {
AST_Module* module = caching_parse_file(fn.c_str()); AST_Module* module = caching_parse_file(fn.c_str());
assert(module); assert(module);
ScopingAnalysis *scoping = new ScopingAnalysis(module); ScopingAnalysis *scoping = new ScopingAnalysis(module, true);
assert(module->body[0]->type == AST_TYPE::FunctionDef); assert(module->body[0]->type == AST_TYPE::FunctionDef);
AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]); AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]);
...@@ -57,7 +57,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -57,7 +57,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
AST_Module* module = caching_parse_file(fn.c_str()); AST_Module* module = caching_parse_file(fn.c_str());
assert(module); assert(module);
ScopingAnalysis *scoping = new ScopingAnalysis(module); ScopingAnalysis *scoping = new ScopingAnalysis(module, true);
assert(module->body[0]->type == AST_TYPE::FunctionDef); assert(module->body[0]->type == AST_TYPE::FunctionDef);
AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]); AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]);
......
...@@ -428,6 +428,8 @@ parser.add_argument('-e', '--exit-code-only', action='store_true', ...@@ -428,6 +428,8 @@ parser.add_argument('-e', '--exit-code-only', action='store_true',
help="only check exit code; don't run CPython to get expected output to compare against") help="only check exit code; don't run CPython to get expected output to compare against")
parser.add_argument('--skip-failing', action='store_true', parser.add_argument('--skip-failing', action='store_true',
help="skip tests expected to fail") help="skip tests expected to fail")
parser.add_argument('--order-by-mtime', action='store_true',
help="order test execution by modification time, instead of file size")
parser.add_argument('test_dir') parser.add_argument('test_dir')
parser.add_argument('pattern', nargs='*') parser.add_argument('pattern', nargs='*')
...@@ -504,7 +506,10 @@ def main(orig_dir): ...@@ -504,7 +506,10 @@ def main(orig_dir):
IMAGE = '/usr/local/bin/pypy' IMAGE = '/usr/local/bin/pypy'
if not patterns: if not patterns:
tests.sort(key=fileSize) if opts.order_by_mtime:
tests.sort(key=lambda fn:os.stat(fn).st_mtime, reverse=True)
else:
tests.sort(key=fileSize)
for fn in tests: for fn in tests:
check_stats = fn not in IGNORE_STATS check_stats = fn not in IGNORE_STATS
......
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