summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorAnthony Baxter <anthonybaxter@gmail.com>2004-08-02 06:10:11 (GMT)
committerAnthony Baxter <anthonybaxter@gmail.com>2004-08-02 06:10:11 (GMT)
commitc2a5a636545a88f349dbe3e452ffb4494b68e534 (patch)
treeaaa24074dcdcce5afa51523969971bdd05381b01 /Python/compile.c
parentfd7dc5169c3ca7d64109512f38762c4ce9e96c5f (diff)
downloadcpython-c2a5a636545a88f349dbe3e452ffb4494b68e534.zip
cpython-c2a5a636545a88f349dbe3e452ffb4494b68e534.tar.gz
cpython-c2a5a636545a88f349dbe3e452ffb4494b68e534.tar.bz2
PEP-0318, @decorator-style. In Guido's words:
"@ seems the syntax that everybody can hate equally" Implementation by Mark Russell, from SF #979728.
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c127
1 files changed, 112 insertions, 15 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 771bc2f..337cc2e 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1876,6 +1876,7 @@ com_testlist_gexp(struct compiling *c, node *n)
else com_list(c, n, 0);
}
+
static void
com_dictmaker(struct compiling *c, node *n)
{
@@ -3963,8 +3964,9 @@ com_argdefs(struct compiling *c, node *n)
n = CHILD(n, 1);
}
else {
- REQ(n, funcdef); /* funcdef: 'def' NAME parameters ... */
- n = CHILD(n, 2);
+ REQ(n, funcdef);
+ /* funcdef: [decorators] 'def' NAME parameters ':' suite */
+ n = RCHILD(n, -3);
REQ(n, parameters); /* parameters: '(' [varargslist] ')' */
n = CHILD(n, 1);
}
@@ -4009,15 +4011,89 @@ com_argdefs(struct compiling *c, node *n)
}
static void
+com_decorator_name(struct compiling *c, node *n)
+{
+ /* dotted_name: NAME ('.' NAME)* */
+
+ int i, nch;
+ node *varname;
+
+ REQ(n, dotted_name);
+ nch = NCH(n);
+ assert(nch >= 1 && nch % 2 == 1);
+
+ varname = CHILD(n, 0);
+ REQ(varname, NAME);
+ com_addop_varname(c, VAR_LOAD, STR(varname));
+
+ for (i = 1; i < nch; i += 2) {
+ node *attrname;
+
+ REQ(CHILD(n, i), DOT);
+
+ attrname = CHILD(n, i + 1);
+ REQ(attrname, NAME);
+ com_addop_name(c, LOAD_ATTR, STR(attrname));
+ }
+}
+
+static void
+com_decorator(struct compiling *c, node *n)
+{
+ /* decorator: '@' dotted_name [ '(' [arglist] ')' ] */
+ int nch = NCH(n);
+ assert(nch >= 2);
+ REQ(CHILD(n, 0), AT);
+ com_decorator_name(c, CHILD(n, 1));
+
+ if (nch > 2) {
+ assert(nch == 4 || nch == 5);
+ REQ(CHILD(n, 2), LPAR);
+ REQ(CHILD(n, nch - 1), RPAR);
+ com_call_function(c, CHILD(n, 3));
+ }
+}
+
+static int
+com_decorators(struct compiling *c, node *n)
+{
+ int i, nch, ndecorators;
+
+ /* decorator ([NEWLINE] decorator)* NEWLINE */
+ nch = NCH(n);
+ assert(nch >= 2);
+ REQ(CHILD(n, nch - 1), NEWLINE);
+
+ ndecorators = 0;
+ for (i = NCH(n) - 1; i >= 0; --i) {
+ node *ch = CHILD(n, i);
+ if (TYPE(ch) != NEWLINE) {
+ com_decorator(c, ch);
+ ++ndecorators;
+ }
+ }
+
+ return ndecorators;
+}
+
+static void
com_funcdef(struct compiling *c, node *n)
{
PyObject *co;
- int ndefs;
- REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
+ int ndefs, ndecorators;
+ REQ(n, funcdef);
+ /* -6 -5 -4 -3 -2 -1
+ funcdef: [decorators] 'def' NAME parameters ':' suite */
+
+ if (NCH(n) == 6)
+ ndecorators = com_decorators(c, CHILD(n, 0));
+ else
+ ndecorators = 0;
+
ndefs = com_argdefs(c, n);
if (ndefs < 0)
return;
- symtable_enter_scope(c->c_symtable, STR(CHILD(n, 1)), TYPE(n),
+ symtable_enter_scope(c->c_symtable, STR(RCHILD(n, -4)), TYPE(n),
n->n_lineno);
co = (PyObject *)icompile(n, c);
symtable_exit_scope(c->c_symtable);
@@ -4033,7 +4109,12 @@ com_funcdef(struct compiling *c, node *n)
else
com_addoparg(c, MAKE_FUNCTION, ndefs);
com_pop(c, ndefs);
- com_addop_varname(c, VAR_STORE, STR(CHILD(n, 1)));
+ while (ndecorators > 0) {
+ com_addoparg(c, CALL_FUNCTION, 1);
+ com_pop(c, 1);
+ ndecorators--;
+ }
+ com_addop_varname(c, VAR_STORE, STR(RCHILD(n, -4)));
com_pop(c, 1);
Py_DECREF(co);
}
@@ -4112,7 +4193,7 @@ com_node(struct compiling *c, node *n)
switch (TYPE(n)) {
/* Definition nodes */
-
+
case funcdef:
com_funcdef(c, n);
break;
@@ -4377,21 +4458,23 @@ compile_funcdef(struct compiling *c, node *n)
{
PyObject *doc;
node *ch;
- REQ(n, funcdef); /* funcdef: 'def' NAME parameters ':' suite */
- c->c_name = STR(CHILD(n, 1));
- doc = get_docstring(c, CHILD(n, 4));
+ REQ(n, funcdef);
+ /* -6 -5 -4 -3 -2 -1
+ funcdef: [decorators] 'def' NAME parameters ':' suite */
+ c->c_name = STR(RCHILD(n, -4));
+ doc = get_docstring(c, RCHILD(n, -1));
if (doc != NULL) {
(void) com_addconst(c, doc);
Py_DECREF(doc);
}
else
(void) com_addconst(c, Py_None); /* No docstring */
- ch = CHILD(n, 2); /* parameters: '(' [varargslist] ')' */
+ ch = RCHILD(n, -3); /* parameters: '(' [varargslist] ')' */
ch = CHILD(ch, 1); /* ')' | varargslist */
if (TYPE(ch) == varargslist)
com_arglist(c, ch);
c->c_infunction = 1;
- com_node(c, CHILD(n, 4));
+ com_node(c, RCHILD(n, -1));
c->c_infunction = 0;
com_strip_lnotab(c);
com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
@@ -5587,9 +5670,12 @@ symtable_node(struct symtable *st, node *n)
loop:
switch (TYPE(n)) {
case funcdef: {
- char *func_name = STR(CHILD(n, 1));
+ char *func_name;
+ if (NCH(n) == 6)
+ symtable_node(st, CHILD(n, 0));
+ func_name = STR(RCHILD(n, -4));
symtable_add_def(st, func_name, DEF_LOCAL);
- symtable_default_args(st, CHILD(n, 2));
+ symtable_default_args(st, RCHILD(n, -3));
symtable_enter_scope(st, func_name, TYPE(n), n->n_lineno);
symtable_funcdef(st, n);
symtable_exit_scope(st);
@@ -5734,6 +5820,17 @@ symtable_node(struct symtable *st, node *n)
to be coded with great care, even though they look like
rather innocuous. Each case must double-check TYPE(n).
*/
+ case decorator:
+ if (TYPE(n) == decorator) {
+ /* decorator: '@' dotted_name [ '(' [arglist] ')' ] */
+ node *name, *varname;
+ name = CHILD(n, 1);
+ REQ(name, dotted_name);
+ varname = CHILD(name, 0);
+ REQ(varname, NAME);
+ symtable_add_use(st, STR(varname));
+ }
+ /* fall through */
case argument:
if (TYPE(n) == argument && NCH(n) == 3) {
n = CHILD(n, 2);
@@ -5787,7 +5884,7 @@ symtable_funcdef(struct symtable *st, node *n)
if (NCH(n) == 4)
symtable_params(st, CHILD(n, 1));
} else
- symtable_params(st, CHILD(n, 2));
+ symtable_params(st, RCHILD(n, -3));
body = CHILD(n, NCH(n) - 1);
symtable_node(st, body);
}