Commit dbac3625 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #292 from tjhance/set-function-name

implement setting __name__ for functions
parents efeaab75 4093d5a8
...@@ -11,19 +11,19 @@ print C ...@@ -11,19 +11,19 @@ print C
C.__module__ = 1 C.__module__ = 1
print C print C
def set_name(cls, name): def set_name(obj, name):
try: try:
cls.__name__ = name obj.__name__ = name
except Exception as e: except Exception as e:
print type(e), e print type(e), e
print cls print obj.__name__
def del_name(cls): def del_name(obj):
try: try:
del cls.__name__ del obj.__name__
except Exception as e: except Exception as e:
print type(e), e print type(e), e
print cls.__name__ print obj.__name__
set_name(int, "bob") set_name(int, "bob")
#TODO implement __del__ for getset descriptors #TODO implement __del__ for getset descriptors
...@@ -32,3 +32,17 @@ set_name(int, "bob") ...@@ -32,3 +32,17 @@ set_name(int, "bob")
set_name(C, 5) set_name(C, 5)
set_name(C, "b\0b") set_name(C, "b\0b")
set_name(C, "car") set_name(C, "car")
def g():
pass
print g.__name__
set_name(g, "bob")
set_name(g, 5)
set_name(g, "b\0b")
f = lambda x : 5
print f.__name__
set_name(f, "bob")
set_name(f, 5)
set_name(f, "b\0b")
#del_name(f)
...@@ -271,7 +271,7 @@ void BoxIterator::gcHandler(GCVisitor* v) { ...@@ -271,7 +271,7 @@ void BoxIterator::gcHandler(GCVisitor* v) {
std::string builtinStr("__builtin__"); std::string builtinStr("__builtin__");
extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f) extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f)
: f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL) { : f(f), closure(NULL), isGenerator(false), ndefaults(0), defaults(NULL), modname(NULL), name(NULL) {
if (f->source) { if (f->source) {
this->modname = f->source->parent_module->getattr("__name__", NULL); this->modname = f->source->parent_module->getattr("__name__", NULL);
} else { } else {
...@@ -285,7 +285,7 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f) ...@@ -285,7 +285,7 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f)
extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults, extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults,
BoxedClosure* closure, bool isGenerator) BoxedClosure* closure, bool isGenerator)
: f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL) { : f(f), closure(closure), isGenerator(isGenerator), ndefaults(0), defaults(NULL), modname(NULL), name(NULL) {
if (defaults.size()) { if (defaults.size()) {
// make sure to initialize defaults first, since the GC behavior is triggered by ndefaults, // make sure to initialize defaults first, since the GC behavior is triggered by ndefaults,
// and a GC can happen within this constructor: // and a GC can happen within this constructor:
...@@ -305,10 +305,32 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_ ...@@ -305,10 +305,32 @@ extern "C" BoxedFunctionBase::BoxedFunctionBase(CLFunction* f, std::initializer_
assert(f->num_defaults == ndefaults); assert(f->num_defaults == ndefaults);
} }
BoxedFunction::BoxedFunction(CLFunction* f) : BoxedFunction(f, {}) {
}
BoxedFunction::BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure,
bool isGenerator)
: BoxedFunctionBase(f, defaults, closure, isGenerator) {
// TODO eventually we want this to assert(f->source), I think, but there are still
// some builtin functions that are BoxedFunctions but really ought to be a type that
// we don't have yet.
if (f->source) {
this->name = static_cast<BoxedString*>(boxString(f->source->getName()));
}
}
extern "C" void functionGCHandler(GCVisitor* v, Box* b) { extern "C" void functionGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b); boxGCHandler(v, b);
BoxedFunctionBase* f = (BoxedFunctionBase*)b; BoxedFunction* f = (BoxedFunction*)b;
// TODO eventually f->name should always be non-NULL, then there'd be no need for this check
if (f->name)
v->visit(f->name);
if (f->modname)
v->visit(f->modname);
if (f->closure) if (f->closure)
v->visit(f->closure); v->visit(f->closure);
...@@ -647,15 +669,19 @@ static Box* functionCall(BoxedFunction* self, Box* args, Box* kwargs) { ...@@ -647,15 +669,19 @@ static Box* functionCall(BoxedFunction* self, Box* args, Box* kwargs) {
static Box* func_name(Box* b, void*) { static Box* func_name(Box* b, void*) {
assert(b->cls == function_cls); assert(b->cls == function_cls);
BoxedFunction* func = static_cast<BoxedFunction*>(b); BoxedFunction* func = static_cast<BoxedFunction*>(b);
RELEASE_ASSERT(func->name != NULL, "func->name is not set");
// TODO this isn't right return func->name;
// (For one thing, we need to able to *set* the __name__ of a function, but that probably
// should not involve setting the name in the source.)
return boxString(func->f->source->getName());
} }
static void func_set_name(Box*, Box*, void*) { static void func_set_name(Box* b, Box* v, void*) {
RELEASE_ASSERT(0, "not implemented"); assert(b->cls == function_cls);
BoxedFunction* func = static_cast<BoxedFunction*>(b);
if (v == NULL || !PyString_Check(v)) {
raiseExcHelper(TypeError, "__name__ must be set to a string object");
}
func->name = static_cast<BoxedString*>(v);
} }
static Box* functionNonzero(BoxedFunction* self) { static Box* functionNonzero(BoxedFunction* self) {
......
...@@ -459,6 +459,7 @@ public: ...@@ -459,6 +459,7 @@ public:
// Accessed via member descriptor // Accessed via member descriptor
Box* modname; // __module__ Box* modname; // __module__
BoxedString* name; // __name__ (should be here or in one of the derived classes?)
BoxedFunctionBase(CLFunction* f); BoxedFunctionBase(CLFunction* f);
BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL, BoxedFunctionBase(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
...@@ -467,10 +468,9 @@ public: ...@@ -467,10 +468,9 @@ public:
class BoxedFunction : public BoxedFunctionBase { class BoxedFunction : public BoxedFunctionBase {
public: public:
BoxedFunction(CLFunction* f) : BoxedFunctionBase(f) {} BoxedFunction(CLFunction* f);
BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL, BoxedFunction(CLFunction* f, std::initializer_list<Box*> defaults, BoxedClosure* closure = NULL,
bool isGenerator = false) bool isGenerator = false);
: BoxedFunctionBase(f, defaults, closure, isGenerator) {}
DEFAULT_CLASS(function_cls); DEFAULT_CLASS(function_cls);
}; };
......
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