Commit 4d15c2f2 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Implement function decorators

parent 2d55194c
......@@ -1494,9 +1494,17 @@ private:
if (state == PARTIAL)
return;
assert(!node->decorator_list.size());
std::vector<CompilerVariable*> decorators;
for (auto d : node->decorator_list) {
decorators.push_back(evalExpr(d, exc_info));
}
CompilerVariable* func = _createFunction(node, exc_info, node->args, node->body);
for (int i = decorators.size() - 1; i >= 0; i--) {
func = decorators[i]->call(emitter, getOpInfoForNode(node, exc_info), ArgPassSpec(1), { func }, NULL);
}
_doSet(node->name, func, exc_info);
func->decvref(emitter);
}
......
......@@ -1195,7 +1195,13 @@ bool PrintVisitor::visit_for(AST_For* node) {
}
bool PrintVisitor::visit_functiondef(AST_FunctionDef* node) {
assert(node->decorator_list.size() == 0);
for (auto d : node->decorator_list) {
printf("@");
d->accept(this);
printf("\n");
printIndent();
}
printf("def %s(", node->name.c_str());
node->args->accept(this);
printf(")");
......
......@@ -92,7 +92,7 @@ extern "C" Box* div_i64_i64(i64 lhs, i64 rhs) {
raiseExcHelper(ZeroDivisionError, "integer division or modulo by zero");
}
// It's possible for division to overflow:
// It's possible for division to overflow:
#if PYSTON_INT_MIN < -PYSTON_INT_MAX
static_assert(PYSTON_INT_MIN == -PYSTON_INT_MAX - 1, "");
......@@ -548,7 +548,7 @@ extern "C" Box* intPos(BoxedInt* v) {
extern "C" Box* intNeg(BoxedInt* v) {
assert(v->cls == int_cls);
// It's possible for this to overflow:
// It's possible for this to overflow:
#if PYSTON_INT_MIN < -PYSTON_INT_MAX
static_assert(PYSTON_INT_MIN == -PYSTON_INT_MAX - 1, "");
......
# expected: fail
# - decorators
def print_when_eval(x, msg):
print msg
return x
# Test the order that decorators and function defaults get evaluated
@print_when_eval(lambda f: print_when_eval(f, "calling decorator"), "evaluating decorator")
@print_when_eval(lambda f: print_when_eval(lambda *args, **kw: print_when_eval(f, "calling function (outer)")(*args, **kw), "calling outer decorator"), "evaluating outer decorator")
@print_when_eval(lambda f: print_when_eval(lambda *args, **kw: print_when_eval(f, "calling function (inner)")(*args, **kw), "calling inner decorator"), "evaluating inner decorator")
def f(x=print_when_eval(1, "evaluating default")):
pass
# Result: looks like it's decorator first, then defaults, then the decorator is called.
return x
# Result: looks like it's decorators get evaluated first (outer in), then defaults, then the decorators are called (inside out).
print
print f()
print f(2)
print
def print_args(f):
print "calling print_args decorator"
def inner(*args, **kw):
print args, kw
return f(*args, **kw)
return inner
def f1(a, b):
print a + b
pf1 = print_args(f1)
pf1(1, 2)
pf1(2, b=2)
@print_args
def f2(a, b):
print a - b
print f2.__name__
f2(1, 3)
f2(2, b=3)
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