Commit 1128d47c authored by Kevin Modzelewski's avatar Kevin Modzelewski

Clean up attribute lookups and add simple 'member' descriptors

parent 1aef0334
......@@ -148,7 +148,10 @@ public:
static RewriterVarUsage2 empty();
#ifndef NDEBUG
~RewriterVarUsage2() { assert(done_using); }
~RewriterVarUsage2() {
if (!std::uncaught_exception())
assert(done_using);
}
#endif
void setDoneUsing();
......
......@@ -841,7 +841,7 @@ public:
virtual bool isFitBy(BoxedClass* c) { return c == cls; }
virtual CompilerType* getattrType(const std::string* attr, bool cls_only) {
if (cls->is_constant && !cls->hasattrs) {
if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) {
Box* rtattr = cls->peekattr(*attr);
if (rtattr == NULL)
return UNDEF;
......@@ -862,7 +862,7 @@ public:
CompilerVariable* getattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool cls_only) {
// printf("%s.getattr %s\n", debugName().c_str(), attr->c_str());
if (cls->is_constant && !cls->hasattrs) {
if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) {
Box* rtattr = cls->peekattr(*attr);
if (rtattr == NULL) {
llvm::CallSite call = emitter.createCall2(info.exc_info, g.funcs.raiseAttributeErrorStr,
......@@ -928,7 +928,7 @@ public:
virtual CompilerVariable* callattr(IREmitter& emitter, const OpInfo& info, ConcreteCompilerVariable* var,
const std::string* attr, bool clsonly,
const std::vector<CompilerVariable*>& args) {
if (cls->is_constant && !cls->hasattrs) {
if (cls->is_constant && !cls->hasattrs && cls->hasGenericGetattr()) {
Box* rtattr = cls->peekattr(*attr);
if (rtattr == NULL) {
llvm::CallSite call
......
......@@ -1305,7 +1305,7 @@ private:
ScopeInfo* scope_info = irstate->getSourceInfo()->scoping->getScopeInfoForNode(node);
llvm::Value* classobj
= emitter.createCall2(exc_info, g.funcs.createClass, embedConstantPtr(&node->name, g.llvm_str_type_ptr),
= emitter.createCall2(exc_info, g.funcs.createUserClass, embedConstantPtr(&node->name, g.llvm_str_type_ptr),
embedConstantPtr(irstate->getSourceInfo()->parent_module, g.llvm_module_type_ptr))
.getInstruction();
ConcreteCompilerVariable* cls = new ConcreteCompilerVariable(typeFromClass(type_cls), classobj, true);
......
......@@ -144,7 +144,7 @@ void initGlobalFuncs(GlobalState& g) {
GET(boxCLFunction);
GET(unboxCLFunction);
GET(createClass);
GET(createUserClass);
GET(boxInt);
GET(unboxInt);
GET(boxFloat);
......
......@@ -21,7 +21,8 @@ struct GlobalFuncs {
llvm::Value* printf, *my_assert, *malloc, *free;
llvm::Value* boxInt, *unboxInt, *boxFloat, *unboxFloat, *boxStringPtr, *boxCLFunction, *unboxCLFunction,
*boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice, *createClass;
*boxInstanceMethod, *boxBool, *unboxBool, *createTuple, *createDict, *createList, *createSlice,
*createUserClass;
llvm::Value* getattr, *setattr, *print, *nonzero, *binop, *compare, *augbinop, *unboxedLen, *getitem, *getclsattr,
*getGlobal, *setitem, *unaryop, *import, *repr, *isinstance;
llvm::Value* checkUnpackingLength, *raiseAttributeError, *raiseAttributeErrorStr, *raiseNotIterableError,
......
......@@ -36,9 +36,9 @@ class GCVisitor {
public:
virtual ~GCVisitor() {}
virtual void visit(void* p) = 0;
virtual void visitRange(void** start, void** end) = 0;
virtual void visitRange(void* const* start, void* const* end) = 0;
virtual void visitPotential(void* p) = 0;
virtual void visitPotentialRange(void** start, void** end) = 0;
virtual void visitPotentialRange(void* const* start, void* const* end) = 0;
};
typedef int kindid_t;
......@@ -369,12 +369,20 @@ public:
// ie they have python-level instance attributes:
const bool hasattrs;
// Whether this class object is constant or not.
// Whether this class object is constant or not, ie whether or not class-level
// attributes can be changed or added.
// Does not necessarily imply that the instances of this class are constant,
// though for now (is_constant && !hasattrs) does imply that the instances are constant.
bool is_constant;
BoxedClass(bool hasattrs);
// Whether this class was defined by the user or is a builtin type.
// this is used mostly for debugging.
const bool is_user_defined;
// will need to update this once we support tp_getattr-style overriding:
bool hasGenericGetattr() { return true; }
BoxedClass(bool hasattrs, bool is_user_defined);
void freeze() {
assert(!is_constant);
is_constant = true;
......
......@@ -54,9 +54,9 @@ void TraceStackGCVisitor::visit(void* p) {
_visit(p);
}
void TraceStackGCVisitor::visitRange(void** start, void** end) {
void TraceStackGCVisitor::visitRange(void* const* start, void* const* end) {
#ifndef NDEBUG
void** cur = start;
void* const* cur = start;
while (cur < end) {
assert(isValid(*cur));
cur++;
......@@ -72,7 +72,7 @@ void TraceStackGCVisitor::visitPotential(void* p) {
}
}
void TraceStackGCVisitor::visitPotentialRange(void** start, void** end) {
void TraceStackGCVisitor::visitPotentialRange(void* const* start, void* const* end) {
while (start < end) {
visitPotential(*start);
start++;
......
......@@ -51,7 +51,7 @@ private:
std::vector<void*> v;
public:
void pushall(void** start, void** end) { v.insert(v.end(), start, end); }
void pushall(void* const* start, void* const* end) { v.insert(v.end(), start, end); }
void push(void* p) { v.push_back(p); }
......@@ -80,9 +80,9 @@ public:
TraceStackGCVisitor(TraceStack* stack) : stack(stack) {}
void visit(void* p) override;
void visitRange(void** start, void** end) override;
void visitRange(void* const* start, void* const* end) override;
void visitPotential(void* p) override;
void visitPotentialRange(void** start, void** end) override;
void visitPotentialRange(void* const* start, void* const* end) override;
};
// Call it a "root obj" because this function takes the pointer to the object, not a pointer
......
......@@ -229,7 +229,8 @@ int main(int argc, char** argv) {
try {
compileAndRunModule(m, main);
} catch (Box* b) {
}
catch (Box* b) {
std::string msg = formatException(b);
fprintf(stderr, "%s\n", msg.c_str());
}
......
......@@ -328,7 +328,7 @@ Box* exceptionRepr(Box* b) {
}
static BoxedClass* makeBuiltinException(const char* name) {
BoxedClass* cls = new BoxedClass(true);
BoxedClass* cls = new BoxedClass(true, false);
cls->giveAttr("__name__", boxStrConstant(name));
// TODO these should be on the base Exception class:
......@@ -346,7 +346,7 @@ void setupBuiltins() {
builtins_module->setattr("None", None, NULL, NULL);
notimplemented_cls = new BoxedClass(false);
notimplemented_cls = new BoxedClass(false, false);
notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType"));
notimplemented_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)notimplementedRepr, NULL, 1, false)));
......
......@@ -121,7 +121,7 @@ BoxedModule* getTestModule() {
}
void setupCAPI() {
capifunc_cls = new BoxedClass(false);
capifunc_cls = new BoxedClass(false, false);
capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));
capifunc_cls->giveAttr("__repr__",
......
......@@ -59,7 +59,7 @@ void force() {
FORCE(createDict);
FORCE(createList);
FORCE(createSlice);
FORCE(createClass);
FORCE(createUserClass);
FORCE(getattr);
FORCE(setattr);
......
......@@ -122,9 +122,9 @@ Box* xrangeIter(Box* self) {
}
void setupXrange() {
xrange_cls = new BoxedClass(false);
xrange_cls = new BoxedClass(false, false);
xrange_cls->giveAttr("__name__", boxStrConstant("xrange"));
xrange_iterator_cls = new BoxedClass(false);
xrange_iterator_cls = new BoxedClass(false, false);
xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator"));
CLFunction* xrange_clf = boxRTFunction((void*)xrange1, NULL, 2, false);
......
......@@ -349,7 +349,7 @@ extern "C" Box* listNew2(Box* cls, Box* container) {
}
void setupList() {
list_iterator_cls = new BoxedClass(false);
list_iterator_cls = new BoxedClass(false, false);
list_cls->giveAttr("__name__", boxStrConstant("list"));
......
This diff is collapsed.
......@@ -172,7 +172,7 @@ using namespace pyston::set;
void setupSet() {
set_cls->giveAttr("__name__", boxStrConstant("set"));
set_iterator_cls = new BoxedClass(false);
set_iterator_cls = new BoxedClass(false, false);
set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator"));
set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1, false)));
......
......@@ -117,6 +117,11 @@ void raiseExcHelper(BoxedClass* cls, const char* msg, ...) {
va_list ap;
va_start(ap, msg);
// printf("Raising: ");
// vprintf(msg, ap);
// printf("\n");
// va_start(ap, msg);
char buf[1024];
vsnprintf(buf, sizeof(buf), msg, ap);
......
......@@ -36,6 +36,10 @@ namespace pyston {
bool IN_SHUTDOWN = false;
#define SLICE_START_OFFSET ((char*)&(((BoxedSlice*)0x01)->start) - (char*)0x1)
#define SLICE_STOP_OFFSET ((char*)&(((BoxedSlice*)0x01)->stop) - (char*)0x1)
#define SLICE_STEP_OFFSET ((char*)&(((BoxedSlice*)0x01)->step) - (char*)0x1)
BoxIterator& BoxIterator::operator++() {
static std::string hasnext_str("__hasnext__");
static std::string next_str("next");
......@@ -154,12 +158,23 @@ extern "C" void listGCHandler(GCVisitor* v, void* p) {
sc.log(size);
}
extern "C" void sliceGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
BoxedSlice* sl = static_cast<BoxedSlice*>(p);
assert(sl->cls == slice_cls);
v->visit(sl->start);
v->visit(sl->stop);
v->visit(sl->step);
}
// This probably belongs in tuple.cpp?
extern "C" void tupleGCHandler(GCVisitor* v, void* p) {
boxGCHandler(v, p);
BoxedTuple* t = (BoxedTuple*)p;
v->visitPotentialRange((void**)&t->elts, (void**)(&t->elts + 1));
v->visitPotentialRange((void* const*)&t->elts, (void* const*)(&t->elts + 1));
}
// This probably belongs in dict.cpp?
......@@ -192,7 +207,7 @@ extern "C" void conservativeGCHandler(GCVisitor* v, void* p) {
extern "C" {
BoxedClass* type_cls, *none_cls, *bool_cls, *int_cls, *float_cls, *str_cls, *function_cls, *instancemethod_cls,
*list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls;
*list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *member_cls;
const ObjectFlavor type_flavor(&typeGCHandler, NULL);
const ObjectFlavor none_flavor(&boxGCHandler, NULL);
......@@ -203,20 +218,21 @@ const ObjectFlavor str_flavor(&boxGCHandler, NULL);
const ObjectFlavor function_flavor(&hcBoxGCHandler, NULL);
const ObjectFlavor instancemethod_flavor(&instancemethodGCHandler, NULL);
const ObjectFlavor list_flavor(&listGCHandler, NULL);
const ObjectFlavor slice_flavor(&hcBoxGCHandler, NULL);
const ObjectFlavor slice_flavor(&sliceGCHandler, NULL);
const ObjectFlavor module_flavor(&hcBoxGCHandler, NULL);
const ObjectFlavor dict_flavor(&dictGCHandler, NULL);
const ObjectFlavor tuple_flavor(&tupleGCHandler, NULL);
const ObjectFlavor file_flavor(&boxGCHandler, NULL);
const ObjectFlavor user_flavor(&hcBoxGCHandler, NULL);
const ObjectFlavor member_flavor(&boxGCHandler, NULL);
const AllocationKind untracked_kind(NULL, NULL);
const AllocationKind hc_kind(&hcGCHandler, NULL);
const AllocationKind conservative_kind(&conservativeGCHandler, NULL);
}
extern "C" Box* createClass(std::string* name, BoxedModule* parent_module) {
BoxedClass* rtn = new BoxedClass(true);
extern "C" Box* createUserClass(std::string* name, BoxedModule* parent_module) {
BoxedClass* rtn = new BoxedClass(true, true);
rtn->giveAttr("__name__", boxString(*name));
Box* modname = parent_module->getattr("__name__", NULL, NULL);
......@@ -275,14 +291,7 @@ Box* range_obj = NULL;
}
extern "C" Box* createSlice(Box* start, Box* stop, Box* step) {
static const std::string start_str("start");
static const std::string stop_str("stop");
static const std::string step_str("step");
BoxedSlice* rtn = new BoxedSlice(start, stop, step);
rtn->setattr(start_str, start, NULL, NULL);
rtn->setattr(stop_str, stop, NULL, NULL);
rtn->setattr(step_str, step, NULL, NULL);
return rtn;
}
......@@ -365,30 +374,31 @@ bool TRACK_ALLOCATIONS = false;
void setupRuntime() {
HiddenClass::getRoot();
type_cls = new BoxedClass(true);
type_cls = new BoxedClass(true, false);
type_cls->cls = type_cls;
none_cls = new BoxedClass(false);
none_cls = new BoxedClass(false, false);
None = new Box(&none_flavor, none_cls);
gc::registerStaticRootObj(None);
module_cls = new BoxedClass(true);
module_cls = new BoxedClass(true, false);
// TODO it'd be nice to be able to do these in the respective setupType methods,
// but those setup methods probably want access to these objects.
// We could have a multi-stage setup process, but that seems overkill for now.
bool_cls = new BoxedClass(false);
int_cls = new BoxedClass(false);
float_cls = new BoxedClass(false);
str_cls = new BoxedClass(false);
function_cls = new BoxedClass(true);
instancemethod_cls = new BoxedClass(false);
list_cls = new BoxedClass(false);
slice_cls = new BoxedClass(true);
dict_cls = new BoxedClass(false);
tuple_cls = new BoxedClass(false);
file_cls = new BoxedClass(false);
set_cls = new BoxedClass(false);
bool_cls = new BoxedClass(false, false);
int_cls = new BoxedClass(false, false);
float_cls = new BoxedClass(false, false);
str_cls = new BoxedClass(false, false);
function_cls = new BoxedClass(true, false);
instancemethod_cls = new BoxedClass(false, false);
list_cls = new BoxedClass(false, false);
slice_cls = new BoxedClass(false, false);
dict_cls = new BoxedClass(false, false);
tuple_cls = new BoxedClass(false, false);
file_cls = new BoxedClass(false, false);
set_cls = new BoxedClass(false, false);
member_cls = new BoxedClass(false, false);
STR = typeFromClass(str_cls);
BOXED_INT = typeFromClass(int_cls);
......@@ -419,6 +429,9 @@ void setupRuntime() {
module_cls->setattr("__str__", module_cls->peekattr("__repr__"), NULL, NULL);
module_cls->freeze();
member_cls->giveAttr("__name__", boxStrConstant("member"));
member_cls->freeze();
setupBool();
setupInt();
setupFloat();
......@@ -446,6 +459,9 @@ void setupRuntime() {
slice_cls->giveAttr("__new__", new BoxedFunction(slice_new));
slice_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)sliceRepr, NULL, 1, true)));
slice_cls->setattr("__str__", slice_cls->peekattr("__repr__"), NULL, NULL);
slice_cls->giveAttr("start", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_START_OFFSET));
slice_cls->giveAttr("stop", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STOP_OFFSET));
slice_cls->giveAttr("step", new BoxedMemberDescriptor(BoxedMemberDescriptor::OBJECT, SLICE_STEP_OFFSET));
slice_cls->freeze();
// sys is the first module that needs to be set up, due to modules
......
......@@ -60,12 +60,12 @@ 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;
*list_cls, *slice_cls, *module_cls, *dict_cls, *tuple_cls, *file_cls, *xrange_cls, *member_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;
xrange_flavor, member_flavor;
}
extern "C" { extern const ObjectFlavor user_flavor; }
......@@ -87,7 +87,7 @@ extern "C" void listAppendInternal(Box* self, Box* v);
extern "C" void listAppendArrayInternal(Box* self, Box** v, int nelts);
extern "C" Box* boxCLFunction(CLFunction* f);
extern "C" CLFunction* unboxCLFunction(Box* b);
extern "C" Box* createClass(std::string* name, BoxedModule* parent_module);
extern "C" Box* createUserClass(std::string* name, BoxedModule* parent_module);
extern "C" double unboxFloat(Box* b);
extern "C" Box* createDict();
extern "C" Box* createList();
......@@ -155,12 +155,8 @@ public:
template <class U> void destroy(U* p) { p->~U(); }
bool operator==(const StlCompatAllocator<T> &rhs) const {
return true;
}
bool operator!=(const StlCompatAllocator<T> &rhs) const {
return false;
}
bool operator==(const StlCompatAllocator<T>& rhs) const { return true; }
bool operator!=(const StlCompatAllocator<T>& rhs) const { return false; }
};
......@@ -187,7 +183,7 @@ public:
class BoxedString : public Box {
public:
//const std::basic_string<char, std::char_traits<char>, StlCompatAllocator<char> > s;
// const std::basic_string<char, std::char_traits<char>, StlCompatAllocator<char> > s;
const std::string s;
BoxedString(const std::string&& s) __attribute__((visibility("default")))
......@@ -276,11 +272,22 @@ public:
std::string name();
};
class BoxedSlice : public HCBox {
class BoxedSlice : public Box {
public:
Box* start, *stop, *step;
BoxedSlice(Box* lower, Box* upper, Box* step)
: HCBox(&slice_flavor, slice_cls), start(lower), stop(upper), step(step) {}
: Box(&slice_flavor, slice_cls), start(lower), stop(upper), step(step) {}
};
class BoxedMemberDescriptor : public Box {
public:
enum MemberType {
OBJECT,
} type;
int offset;
BoxedMemberDescriptor(MemberType type, int offset) : Box(&member_flavor, member_cls), type(type), offset(offset) {}
};
extern "C" void boxGCHandler(GCVisitor* v, void* p);
......
# expected: fail
# - not implemented
# Instance methods forward any missed attribute lookups to their underlying function
class C(object):
pass
def f(self):
pass
C.f = f
c = C()
im = c.f
print type(f), type(im)
f.a = 1
print im.a
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