Commit 2affae97 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Get rid of source->ast

parent bcd80646
......@@ -929,7 +929,7 @@ Value ASTInterpreter::visit_langPrimitive(AST_LangPrimitive* node) {
assert(node->args.size() == 1);
assert(node->args[0]->type == AST_TYPE::Name);
RELEASE_ASSERT(source_info->ast->type == AST_TYPE::Module || source_info->ast->type == AST_TYPE::Suite,
RELEASE_ASSERT(source_info->ast_type == AST_TYPE::Module || source_info->ast_type == AST_TYPE::Suite,
"import * not supported in functions");
Value module = visit_expr(node->args[0]);
......
......@@ -59,9 +59,9 @@ void BoxedCode::addVersion(CompiledFunction* compiled) {
}
SourceInfo::SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags future_flags, AST* ast)
: parent_module(m), scoping(std::move(scoping)), ast(ast), cfg(NULL), future_flags(future_flags) {
: parent_module(m), scoping(std::move(scoping)), cfg(NULL), future_flags(future_flags), ast_type(ast->type) {
switch (ast->type) {
switch (ast_type) {
case AST_TYPE::ClassDef:
case AST_TYPE::Module:
case AST_TYPE::Expression:
......@@ -73,7 +73,7 @@ SourceInfo::SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags futur
is_generator = containsYield(ast);
break;
default:
RELEASE_ASSERT(0, "Unknown type: %d", ast->type);
RELEASE_ASSERT(0, "Unknown type: %d", ast_type);
break;
}
}
......
......@@ -551,8 +551,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
if (block == cfg->getStartingBlock()) {
assert(entry_descriptor == NULL);
if (ENABLE_REOPT && effort < EffortLevel::MAXIMAL && source->ast != NULL
&& source->ast->type != AST_TYPE::Module) {
if (ENABLE_REOPT && effort < EffortLevel::MAXIMAL && source->ast_type != AST_TYPE::Module) {
llvm::BasicBlock* preentry_bb = llvm::BasicBlock::Create(
g.context, "pre_entry", irstate->getLLVMFunction(), llvm_entry_blocks[cfg->getStartingBlock()]);
llvm::BasicBlock* reopt_bb = llvm::BasicBlock::Create(g.context, "reopt", irstate->getLLVMFunction());
......@@ -989,9 +988,7 @@ static void computeBlockSetClosure(BlockSet& blocks) {
}
// returns a pointer to the function-info mdnode
static llvm::MDNode* setupDebugInfo(BoxedCode* code, llvm::Function* f, std::string origname) {
int lineno = 0;
if (code->source->ast)
lineno = code->source->ast->lineno;
int lineno = code->firstlineno;
llvm::DIBuilder builder(*g.cur_module);
......
......@@ -54,31 +54,6 @@
namespace pyston {
llvm::ArrayRef<AST_stmt*> SourceInfo::getBody() const {
switch (ast->type) {
case AST_TYPE::ClassDef:
return ((AST_ClassDef*)ast)->body;
case AST_TYPE::Expression:
return ((AST_Expression*)ast)->body;
case AST_TYPE::FunctionDef:
return ((AST_FunctionDef*)ast)->body;
case AST_TYPE::Module:
return ((AST_Module*)ast)->body;
default:
RELEASE_ASSERT(0, "unknown %d", ast->type);
};
}
Box* SourceInfo::getDocString() {
auto body = getBody();
if (body.size() > 0 && body[0]->type == AST_TYPE::Expr
&& static_cast<AST_Expr*>(body[0])->value->type == AST_TYPE::Str) {
return boxString(static_cast<AST_Str*>(static_cast<AST_Expr*>(body[0])->value)->str_data);
}
return incref(Py_None);
}
LivenessAnalysis* SourceInfo::getLiveness() {
if (!liveness_info)
liveness_info = computeLivenessInfo(cfg);
......@@ -258,11 +233,11 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
FutureFlags future_flags = getFutureFlags(m->body, fn);
computeAllCFGs(m, /* globals_from_module */ true, future_flags, autoDecref(boxString(fn)), bm);
BoxedCode* code = codeForAST(m);
BoxedCode* code = m->getCode();
assert(code);
static BoxedString* doc_str = getStaticString("__doc__");
bm->setattr(doc_str, autoDecref(code->source->getDocString()), NULL);
bm->setattr(doc_str, code->_doc, NULL);
static BoxedString* builtins_str = getStaticString("__builtins__");
if (!bm->hasattr(builtins_str))
......@@ -279,12 +254,11 @@ Box* evalOrExec(BoxedCode* code, Box* globals, Box* boxedLocals) {
assert(globals && (globals->cls == module_cls || globals->cls == dict_cls));
Box* doc_string = code->source->getDocString();
// TODO: we're supposed to embed this directly into the bytecode
Box* doc_string = code->_doc;
if (doc_string != Py_None) {
static BoxedString* doc_box = getStaticString("__doc__");
setGlobal(boxedLocals, doc_box, doc_string);
} else {
Py_DECREF(doc_string);
setGlobal(boxedLocals, doc_box, incref(doc_string));
}
return astInterpretFunctionEval(code, globals, boxedLocals);
......@@ -306,7 +280,7 @@ static BoxedCode* compileForEvalOrExec(AST* source, llvm::ArrayRef<AST_stmt*> bo
}
computeAllCFGs(source, /* globals_from_module */ false, future_flags, fn, getCurrentModule());
return codeForAST(source);
return source->getCode();
}
static BoxedCode* compileExec(AST_Module* parsedModule, BoxedString* fn, PyCompilerFlags* flags) {
......
......@@ -988,7 +988,7 @@ private:
assert(node->args.size() == 1);
assert(node->args[0]->type == AST_TYPE::Name);
RELEASE_ASSERT(irstate->getSourceInfo()->ast->type == AST_TYPE::Module,
RELEASE_ASSERT(irstate->getSourceInfo()->ast_type == AST_TYPE::Module,
"import * not supported in functions (yet)");
CompilerVariable* module = evalExpr(node->args[0], unw_info);
......@@ -1709,8 +1709,8 @@ private:
// I think it's better to just not generate bad speculations:
if (rtn->canConvertTo(speculated_type)) {
auto source = irstate->getSourceInfo();
printf("On %s:%d, function %s:\n", irstate->getCode()->filename->c_str(), source->getBody()[0]->lineno,
irstate->getCode()->name->c_str());
printf("On %s:%d, function %s:\n", irstate->getCode()->filename->c_str(),
irstate->getCode()->firstlineno, irstate->getCode()->name->c_str());
irstate->getSourceInfo()->cfg->print();
}
RELEASE_ASSERT(!rtn->canConvertTo(speculated_type), "%s %s", rtn->getType()->debugName().c_str(),
......
......@@ -2261,4 +2261,77 @@ void flatten(AST_expr* root, std::vector<AST*>& output, bool expand_scopes) {
root->accept(&visitor);
}
BoxedCode*& AST::getCode() {
switch (this->type) {
case AST_TYPE::Expression:
return ast_cast<AST_Expression>(this)->code;
case AST_TYPE::FunctionDef:
return ast_cast<AST_FunctionDef>(this)->code;
case AST_TYPE::ClassDef:
return ast_cast<AST_ClassDef>(this)->code;
case AST_TYPE::Module:
return ast_cast<AST_Module>(this)->code;
default:
break;
}
RELEASE_ASSERT(0, "%d", this->type);
}
InternedStringPool& AST::getStringpool() {
switch (this->type) {
case AST_TYPE::Expression:
return *ast_cast<AST_Expression>(this)->interned_strings;
case AST_TYPE::Module:
return *ast_cast<AST_Module>(this)->interned_strings;
default:
break;
}
RELEASE_ASSERT(0, "%d", this->type);
}
llvm::ArrayRef<AST_stmt*> AST::getBody() {
switch (this->type) {
case AST_TYPE::ClassDef:
return ((AST_ClassDef*)this)->body;
case AST_TYPE::Expression:
return ((AST_Expression*)this)->body;
case AST_TYPE::FunctionDef:
return ((AST_FunctionDef*)this)->body;
case AST_TYPE::Module:
return ((AST_Module*)this)->body;
default:
RELEASE_ASSERT(0, "unknown %d", this->type);
};
}
Box* AST::getDocString() {
auto body = this->getBody();
if (body.size() > 0 && body[0]->type == AST_TYPE::Expr
&& static_cast<AST_Expr*>(body[0])->value->type == AST_TYPE::Str) {
return boxString(static_cast<AST_Str*>(static_cast<AST_Expr*>(body[0])->value)->str_data);
}
return incref(Py_None);
}
BORROWED(BoxedString*) AST::getName() noexcept {
static BoxedString* lambda_name = getStaticString("<lambda>");
static BoxedString* module_name = getStaticString("<module>");
switch (this->type) {
case AST_TYPE::ClassDef:
return ast_cast<AST_ClassDef>(this)->name.getBox();
case AST_TYPE::FunctionDef:
if (ast_cast<AST_FunctionDef>(this)->name != InternedString())
return ast_cast<AST_FunctionDef>(this)->name.getBox();
return lambda_name;
case AST_TYPE::Module:
case AST_TYPE::Expression:
case AST_TYPE::Suite:
return module_name;
default:
RELEASE_ASSERT(0, "%d", this->type);
}
}
}
......@@ -188,6 +188,14 @@ public:
#endif
AST(AST_TYPE::AST_TYPE type, uint32_t lineno, uint32_t col_offset = 0)
: type(type), lineno(lineno), col_offset(col_offset) {}
// These could be virtual methods, but since we already keep track of the type use a switch statement
// like everywhere else.
BoxedCode*& getCode();
InternedStringPool& getStringpool();
llvm::ArrayRef<AST_stmt*> getBody();
Box* getDocString();
BORROWED(BoxedString*) getName() noexcept;
};
class AST_expr : public AST {
......
......@@ -251,7 +251,7 @@ public:
ModuleCFGProcessor(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn, BoxedModule* bm)
: scoping(ast, globals_from_module),
stringpool(stringpoolForAST(ast)),
stringpool(ast->getStringpool()),
future_flags(future_flags),
fn(fn),
bm(bm) {}
......@@ -263,7 +263,7 @@ public:
void runRecursively(AST* ast, AST_arguments* args, AST* orig_node);
};
static CFG* computeCFG(BoxedString* fn, SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping,
static CFG* computeCFG(AST* ast, BoxedString* fn, SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping,
ModuleCFGProcessor* cfgizer);
// A class that crawls the AST of a single function and computes the CFG
......@@ -361,7 +361,7 @@ private:
unsigned int next_var_index = 0;
friend CFG* computeCFG(BoxedString* fn, SourceInfo* source, const ParamNames& param_names, ScopeInfo*,
friend CFG* computeCFG(AST* ast, BoxedString* fn, SourceInfo* source, const ParamNames& param_names, ScopeInfo*,
ModuleCFGProcessor*);
public:
......@@ -2961,32 +2961,32 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names) {
}
static CFG* computeCFG(BoxedString* filename, SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping,
ModuleCFGProcessor* cfgizer) {
static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, const ParamNames& param_names,
ScopeInfo* scoping, ModuleCFGProcessor* cfgizer) {
STAT_TIMER(t0, "us_timer_computecfg", 0);
auto body = source->getBody();
auto body = ast->getBody();
CFG* rtn = new CFG();
auto&& stringpool = cfgizer->stringpool;
CFGVisitor visitor(filename, source, stringpool, scoping, source->ast->type, source->future_flags, rtn, cfgizer);
CFGVisitor visitor(filename, source, stringpool, scoping, ast->type, source->future_flags, rtn, cfgizer);
bool skip_first = false;
if (source->ast->type == AST_TYPE::ClassDef) {
if (ast->type == AST_TYPE::ClassDef) {
// A classdef always starts with "__module__ = __name__"
AST_Assign* module_assign = new AST_Assign();
auto module_name_target = new AST_Name(stringpool.get("__module__"), AST_TYPE::Store, source->ast->lineno);
auto module_name_target = new AST_Name(stringpool.get("__module__"), AST_TYPE::Store, ast->lineno);
fillScopingInfo(module_name_target, scoping);
auto module_name_value = new AST_Name(stringpool.get("__name__"), AST_TYPE::Load, source->ast->lineno);
auto module_name_value = new AST_Name(stringpool.get("__name__"), AST_TYPE::Load, ast->lineno);
fillScopingInfo(module_name_value, scoping);
module_assign->targets.push_back(module_name_target);
module_assign->value = module_name_value;
module_assign->lineno = source->ast->lineno;
module_assign->lineno = ast->lineno;
visitor.push_back(module_assign);
// If the first statement is just a single string, transform it to an assignment to __doc__
......@@ -2994,18 +2994,18 @@ static CFG* computeCFG(BoxedString* filename, SourceInfo* source, const ParamNam
AST_Expr* first_expr = ast_cast<AST_Expr>(body[0]);
if (first_expr->value->type == AST_TYPE::Str) {
AST_Assign* doc_assign = new AST_Assign();
auto doc_target_name = new AST_Name(stringpool.get("__doc__"), AST_TYPE::Store, source->ast->lineno);
auto doc_target_name = new AST_Name(stringpool.get("__doc__"), AST_TYPE::Store, ast->lineno);
fillScopingInfo(doc_target_name, scoping);
doc_assign->targets.push_back(doc_target_name);
doc_assign->value = first_expr->value;
doc_assign->lineno = source->ast->lineno;
doc_assign->lineno = ast->lineno;
visitor.push_back(doc_assign);
skip_first = true;
}
}
}
if (source->ast->type == AST_TYPE::FunctionDef || source->ast->type == AST_TYPE::Lambda) {
if (ast->type == AST_TYPE::FunctionDef || ast->type == AST_TYPE::Lambda) {
// Unpack tuple arguments
// Tuple arguments get assigned names ".0", ".1" etc. So this
// def f(a, (b,c), (d,e)):
......@@ -3014,10 +3014,10 @@ static CFG* computeCFG(BoxedString* filename, SourceInfo* source, const ParamNam
// (b, c) = .1
// (d, e) = .2
AST_arguments* args;
if (source->ast->type == AST_TYPE::FunctionDef) {
args = ast_cast<AST_FunctionDef>(source->ast)->args;
if (ast->type == AST_TYPE::FunctionDef) {
args = ast_cast<AST_FunctionDef>(ast)->args;
} else {
args = ast_cast<AST_Lambda>(source->ast)->args;
args = ast_cast<AST_Lambda>(ast)->args;
}
int counter = 0;
for (AST_expr* arg_expr : args->args) {
......@@ -3044,11 +3044,11 @@ static CFG* computeCFG(BoxedString* filename, SourceInfo* source, const ParamNam
// The functions we create for classdefs are supposed to return a dictionary of their locals.
// This is the place that we add all of that:
if (source->ast->type == AST_TYPE::ClassDef) {
if (ast->type == AST_TYPE::ClassDef) {
AST_LangPrimitive* locals = new AST_LangPrimitive(AST_LangPrimitive::LOCALS);
AST_Return* rtn = new AST_Return();
rtn->lineno = getLastLineno(source->ast);
rtn->lineno = getLastLineno(ast);
rtn->value = locals;
visitor.push_back(rtn);
} else {
......@@ -3056,7 +3056,7 @@ static CFG* computeCFG(BoxedString* filename, SourceInfo* source, const ParamNam
// we already have to support multiple return statements in a function, but this way we can avoid
// having to support not having a return statement:
AST_Return* return_stmt = new AST_Return();
return_stmt->lineno = getLastLineno(source->ast);
return_stmt->lineno = getLastLineno(ast);
return_stmt->col_offset = 0;
return_stmt->value = NULL;
visitor.push_back(return_stmt);
......@@ -3261,32 +3261,6 @@ static CFG* computeCFG(BoxedString* filename, SourceInfo* source, const ParamNam
return rtn;
}
BoxedCode*& codeForAST(AST* ast) {
switch (ast->type) {
case AST_TYPE::Expression:
return ast_cast<AST_Expression>(ast)->code;
case AST_TYPE::FunctionDef:
return ast_cast<AST_FunctionDef>(ast)->code;
case AST_TYPE::ClassDef:
return ast_cast<AST_ClassDef>(ast)->code;
case AST_TYPE::Module:
return ast_cast<AST_Module>(ast)->code;
default:
break;
}
RELEASE_ASSERT(0, "%d", ast->type);
}
InternedStringPool& stringpoolForAST(AST* ast) {
switch (ast->type) {
case AST_TYPE::Expression:
return *ast_cast<AST_Expression>(ast)->interned_strings;
case AST_TYPE::Module:
return *ast_cast<AST_Module>(ast)->interned_strings;
default:
break;
}
RELEASE_ASSERT(0, "%d", ast->type);
}
void ModuleCFGProcessor::runRecursively(AST* ast, AST_arguments* args, AST* orig_node) {
ScopeInfo* scope_info = scoping.getScopeInfoForNode(orig_node);
......@@ -3297,18 +3271,20 @@ void ModuleCFGProcessor::runRecursively(AST* ast, AST_arguments* args, AST* orig
for (auto e : param_names.allArgsAsName())
fillScopingInfo(e, scope_info);
si->cfg = computeCFG(fn, si.get(), param_names, scope_info, this);
si->cfg = computeCFG(ast, fn, si.get(), param_names, scope_info, this);
BoxedCode* code;
if (args)
code = new BoxedCode(args->args.size(), args->vararg, args->kwarg, std::move(si), std::move(param_names), fn);
code = new BoxedCode(args->args.size(), args->vararg, args->kwarg, ast->lineno, std::move(si),
std::move(param_names), fn, ast->getName(), autoDecref(ast->getDocString()));
else
code = new BoxedCode(0, false, false, std::move(si), std::move(param_names), fn);
code = new BoxedCode(0, false, false, ast->lineno, std::move(si), std::move(param_names), fn, ast->getName(),
autoDecref(ast->getDocString()));
// XXX very bad! Should properly track this:
constants.push_back(code);
codeForAST(ast) = code;
ast->getCode() = code;
}
void computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn, BoxedModule* bm) {
......
......@@ -330,9 +330,6 @@ public:
iterator end() const { return iterator(*this, this->v.size()); }
};
BoxedCode*& codeForAST(AST* ast);
InternedStringPool& stringpoolForAST(AST* ast);
void computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn, BoxedModule* bm);
void printCFG(CFG* cfg);
}
......
......@@ -491,16 +491,18 @@ private:
public:
BoxedModule* parent_module;
ScopingResults scoping;
AST* ast;
CFG* cfg;
FutureFlags future_flags;
bool is_generator;
LivenessAnalysis* getLiveness();
// This should really be an AST_TYPE::AST_TYPE, using that would require resolving a circular dependency
// between ast.h and core/types.h
int ast_type;
llvm::ArrayRef<AST_stmt*> getBody() const;
LivenessAnalysis* getLiveness();
Box* getDocString();
// llvm::ArrayRef<AST_stmt*> getBody() const;
// Box* getDocString();
SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags future_flags, AST* ast);
~SourceInfo();
......
......@@ -58,17 +58,11 @@ Box* BoxedCode::co_filename(Box* b, void* arg) noexcept {
return incref(code->filename);
}
Box* BoxedCode::firstlineno(Box* b, void*) noexcept {
Box* BoxedCode::co_firstlineno(Box* b, void*) noexcept {
RELEASE_ASSERT(b->cls == code_cls, "");
BoxedCode* code = static_cast<BoxedCode*>(b);
if (!code || !code->source)
return boxInt(code->_firstline);
if (code->source->ast->lineno == (uint32_t)-1)
return boxInt(-1);
return boxInt(code->source->ast->lineno);
return boxInt(code->firstlineno);
}
Box* BoxedCode::argcount(Box* b, void*) noexcept {
......@@ -112,39 +106,21 @@ void BoxedCode::dealloc(Box* b) noexcept {
Py_XDECREF(o->filename);
Py_XDECREF(o->name);
Py_XDECREF(o->_doc);
o->source.~decltype(o->source)();
o->cls->tp_free(o);
}
BORROWED(BoxedString*) getASTName(AST* ast) noexcept {
assert(ast);
static BoxedString* lambda_name = getStaticString("<lambda>");
static BoxedString* module_name = getStaticString("<module>");
switch (ast->type) {
case AST_TYPE::ClassDef:
return ast_cast<AST_ClassDef>(ast)->name.getBox();
case AST_TYPE::FunctionDef:
if (ast_cast<AST_FunctionDef>(ast)->name != InternedString())
return ast_cast<AST_FunctionDef>(ast)->name.getBox();
return lambda_name;
case AST_TYPE::Module:
case AST_TYPE::Expression:
case AST_TYPE::Suite:
return module_name;
default:
RELEASE_ASSERT(0, "%d", ast->type);
}
}
BoxedCode::BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, std::unique_ptr<SourceInfo> source,
ParamNames param_names, BoxedString* filename)
BoxedCode::BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, int firstlineno,
std::unique_ptr<SourceInfo> source, ParamNames param_names, BoxedString* filename,
BoxedString* name, Box* doc)
: source(std::move(source)),
filename(incref(filename)),
name(incref(getASTName(this->source->ast))),
name(incref(name)),
firstlineno(firstlineno),
_doc(incref(doc)),
param_names(std::move(param_names)),
takes_varargs(takes_varargs),
takes_kwargs(takes_kwargs),
......@@ -153,12 +129,14 @@ BoxedCode::BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, std::u
internal_callable(NULL, NULL) {
}
BoxedCode::BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, const ParamNames& param_names,
BoxedString* filename)
BoxedCode::BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, const ParamNames& param_names)
: source(nullptr),
// This should probably be just an "incref"?
filename(xincref(filename)),
name(boxString("???")),
// TODO what to do with these?
filename(nullptr),
name(nullptr),
firstlineno(-1),
_doc(nullptr),
param_names(param_names),
takes_varargs(takes_varargs),
takes_kwargs(takes_kwargs),
......@@ -171,7 +149,9 @@ BoxedCode::BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, const
BoxedCode::BoxedCode(BoxedString* filename, BoxedString* name, int firstline)
: filename(filename),
name(name),
_firstline(firstline),
firstlineno(firstline),
_doc(nullptr),
param_names(ParamNames::empty()),
takes_varargs(false),
takes_kwargs(false),
......@@ -273,7 +253,7 @@ void setupCode() {
code_cls->giveAttrDescriptor("co_name", BoxedCode::co_name, NULL);
code_cls->giveAttrDescriptor("co_filename", BoxedCode::co_filename, NULL);
code_cls->giveAttrDescriptor("co_firstlineno", BoxedCode::firstlineno, NULL);
code_cls->giveAttrDescriptor("co_firstlineno", BoxedCode::co_firstlineno, NULL);
code_cls->giveAttrDescriptor("co_argcount", BoxedCode::argcount, NULL);
code_cls->giveAttrDescriptor("co_varnames", BoxedCode::varnames, NULL);
code_cls->giveAttrDescriptor("co_flags", BoxedCode::flags, NULL);
......
......@@ -364,7 +364,7 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(BoxedCode* code, llvm::ArrayRef<
}
// It's ok for modname to be NULL
this->doc = code->source->getDocString();
this->doc = xincref(code->_doc);
} else {
this->modname = PyString_InternFromString("__builtin__");
this->doc = incref(Py_None);
......@@ -379,7 +379,7 @@ BoxedFunction::BoxedFunction(BoxedCode* code, llvm::ArrayRef<Box*> defaults, Box
: BoxedFunctionBase(code, defaults, closure, globals, can_change_defaults) {
assert(!this->name);
this->name = incref(code->name);
this->name = xincref(code->name);
}
BoxedBuiltinFunctionOrMethod::BoxedBuiltinFunctionOrMethod(BoxedCode* code, const char* name, const char* doc)
......
......@@ -1080,7 +1080,9 @@ public:
BoxedString* filename = nullptr;
BoxedString* name = nullptr;
int _firstline;
int firstlineno;
// In CPython, this is just stored as consts[0]
Box* _doc = nullptr;
const ParamNames param_names;
const bool takes_varargs, takes_kwargs;
......@@ -1109,10 +1111,9 @@ public:
Box**, const std::vector<BoxedString*>*> InternalCallable;
InternalCallable internal_callable;
BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, std::unique_ptr<SourceInfo> source,
ParamNames param_names, BoxedString* filename);
BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, const ParamNames& param_names = ParamNames::empty(),
BoxedString* filename = nullptr);
BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, int firstlineno, std::unique_ptr<SourceInfo> source,
ParamNames param_names, BoxedString* filename, BoxedString* name, Box* doc);
BoxedCode(int num_args, bool takes_varargs, bool takes_kwargs, const ParamNames& param_names = ParamNames::empty());
~BoxedCode();
// The dummy constructor for PyCode_New:
......@@ -1166,7 +1167,7 @@ public:
// static BORROWED(Box*) filename(Box* b, void*) noexcept;
static Box* co_name(Box* b, void*) noexcept;
static Box* co_filename(Box* b, void*) noexcept;
static Box* firstlineno(Box* b, void*) noexcept;
static Box* co_firstlineno(Box* b, void*) noexcept;
static Box* argcount(Box* b, void*) noexcept;
static Box* varnames(Box* b, void*) noexcept;
static Box* flags(Box* b, void*) noexcept;
......
......@@ -251,7 +251,7 @@ extern "C" void dumpEx(void* p, int levels) {
BoxedCode* code = f->code;
if (code->source) {
printf("User-defined function '%s'\n", code->name->c_str());
printf("Defined at %s:%d\n", code->filename->c_str(), code->source->ast->lineno);
printf("Defined at %s:%d\n", code->filename->c_str(), code->firstlineno);
if (code->source->cfg && levels > 0) {
code->source->cfg->print();
......
......@@ -55,3 +55,8 @@ class C4(object):
("a")
assert C3.__doc__ is None
"""
exec """
"hello world"
print __doc__
"""
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