Commit 58eb408a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Support decorators on classes as well

parent 4d15c2f2
...@@ -470,6 +470,14 @@ private: ...@@ -470,6 +470,14 @@ private:
} }
virtual void visit_classdef(AST_ClassDef* node) { virtual void visit_classdef(AST_ClassDef* node) {
for (auto d : node->decorator_list) {
getType(d);
}
for (auto b : node->bases) {
getType(b);
}
// TODO should we speculate that classdefs will generally return a class? // TODO should we speculate that classdefs will generally return a class?
// CompilerType* t = typeFromClass(type_cls); // CompilerType* t = typeFromClass(type_cls);
CompilerType* t = UNKNOWN; CompilerType* t = UNKNOWN;
...@@ -501,7 +509,17 @@ private: ...@@ -501,7 +509,17 @@ private:
} }
} }
virtual void visit_functiondef(AST_FunctionDef* node) { _doSet(node->name, typeFromClass(function_cls)); } virtual void visit_functiondef(AST_FunctionDef* node) {
for (auto d : node->decorator_list) {
getType(d);
}
for (auto d : node->args->defaults) {
getType(d);
}
_doSet(node->name, typeFromClass(function_cls));
}
virtual void visit_global(AST_Global* node) {} virtual void visit_global(AST_Global* node) {}
......
...@@ -1290,7 +1290,11 @@ private: ...@@ -1290,7 +1290,11 @@ private:
} }
RELEASE_ASSERT(node->bases.size() == 1, ""); RELEASE_ASSERT(node->bases.size() == 1, "");
RELEASE_ASSERT(node->decorator_list.size() == 0, "");
std::vector<CompilerVariable*> decorators;
for (auto d : node->decorator_list) {
decorators.push_back(evalExpr(d, exc_info));
}
CompilerVariable* base = evalExpr(node->bases[0], exc_info); CompilerVariable* base = evalExpr(node->bases[0], exc_info);
ConcreteCompilerVariable* converted_base = base->makeConverted(emitter, base->getBoxType()); ConcreteCompilerVariable* converted_base = base->makeConverted(emitter, base->getBoxType());
...@@ -1324,7 +1328,13 @@ private: ...@@ -1324,7 +1328,13 @@ private:
converted_base->getValue(), converted_attr_dict->getValue()).getInstruction(); converted_base->getValue(), converted_attr_dict->getValue()).getInstruction();
// Note: createuserClass is free to manufacture non-class objects // Note: createuserClass is free to manufacture non-class objects
auto cls = new ConcreteCompilerVariable(UNKNOWN, classobj, true); CompilerVariable* cls = new ConcreteCompilerVariable(UNKNOWN, classobj, true);
for (int i = decorators.size() - 1; i >= 0; i--) {
cls = decorators[i]->call(emitter, getOpInfoForNode(node, exc_info), ArgPassSpec(1), { cls }, NULL);
decorators[i]->decvref(emitter);
}
_doSet(node->name, cls, exc_info); _doSet(node->name, cls, exc_info);
cls->decvref(emitter); cls->decvref(emitter);
} }
...@@ -1503,6 +1513,7 @@ private: ...@@ -1503,6 +1513,7 @@ private:
for (int i = decorators.size() - 1; i >= 0; i--) { for (int i = decorators.size() - 1; i >= 0; i--) {
func = decorators[i]->call(emitter, getOpInfoForNode(node, exc_info), ArgPassSpec(1), { func }, NULL); func = decorators[i]->call(emitter, getOpInfoForNode(node, exc_info), ArgPassSpec(1), { func }, NULL);
decorators[i]->decvref(emitter);
} }
_doSet(node->name, func, exc_info); _doSet(node->name, func, exc_info);
......
# expected: fail
# - decorators
def f(o, msg):
print msg
return o
@f(lambda c: f(c, "calling decorator"), "evaluating decorator object")
class C(f(object, "evaluating base")):
print "in classdef"
...@@ -15,6 +15,16 @@ print ...@@ -15,6 +15,16 @@ print
@print_when_eval(lambda f: print_when_eval((f, 2), ("calling outer decorator", f)), "evaluating outer decorator")
@print_when_eval(lambda f: print_when_eval((f, 1), ("calling inner decorator", f)), "evaluating inner decorator")
class C(print_when_eval(object, "evaluating base")):
print "in classdef"
pass
print
print C
print
def print_args(f): def print_args(f):
......
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