summaryrefslogtreecommitdiffstats
path: root/Lib/compiler/transformer.py
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 /Lib/compiler/transformer.py
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 'Lib/compiler/transformer.py')
-rw-r--r--Lib/compiler/transformer.py66
1 files changed, 59 insertions, 7 deletions
diff --git a/Lib/compiler/transformer.py b/Lib/compiler/transformer.py
index aa5a28b..229657b 100644
--- a/Lib/compiler/transformer.py
+++ b/Lib/compiler/transformer.py
@@ -185,29 +185,81 @@ class Transformer:
### is this sufficient?
return Expression(self.com_node(nodelist[0]))
+ def decorator_name(self, nodelist):
+ listlen = len(nodelist)
+ assert listlen >= 1 and listlen % 2 == 1
+
+ item = self.atom_name(nodelist)
+ i = 1
+ while i < listlen:
+ assert nodelist[i][0] == token.DOT
+ assert nodelist[i + 1][0] == token.NAME
+ item = Getattr(item, nodelist[i + 1][1])
+ i += 2
+
+ return item
+
+ def decorator(self, nodelist):
+ # '@' dotted_name [ '(' [arglist] ')' ]
+ assert len(nodelist) in (2, 4, 5)
+ assert nodelist[0][0] == token.AT
+
+ assert nodelist[1][0] == symbol.dotted_name
+ funcname = self.decorator_name(nodelist[1][1:])
+
+ if len(nodelist) > 2:
+ assert nodelist[2][0] == token.LPAR
+ expr = self.com_call_function(funcname, nodelist[3])
+ else:
+ expr = funcname
+
+ return expr
+
+ def decorators(self, nodelist):
+ # decorators: decorator ([NEWLINE] decorator)* NEWLINE
+ listlen = len(nodelist)
+ i = 0
+ items = []
+ while i < listlen:
+ assert nodelist[i][0] == symbol.decorator
+ items.append(self.decorator(nodelist[i][1:]))
+ i += 1
+
+ if i < listlen and nodelist[i][0] == token.NEWLINE:
+ i += 1
+ return Decorators(items)
+
def funcdef(self, nodelist):
- # funcdef: 'def' NAME parameters ':' suite
+ # -6 -5 -4 -3 -2 -1
+ # funcdef: [decorators] 'def' NAME parameters ':' suite
# parameters: '(' [varargslist] ')'
- lineno = nodelist[1][2]
- name = nodelist[1][1]
- args = nodelist[2][2]
+ if len(nodelist) == 6:
+ assert nodelist[0][0] == symbol.decorators
+ decorators = self.decorators(nodelist[0][1:])
+ else:
+ assert len(nodelist) == 5
+ decorators = None
+
+ lineno = nodelist[-4][2]
+ name = nodelist[-4][1]
+ args = nodelist[-3][2]
if args[0] == symbol.varargslist:
names, defaults, flags = self.com_arglist(args[1:])
else:
names = defaults = ()
flags = 0
- doc = self.get_docstring(nodelist[4])
+ doc = self.get_docstring(nodelist[-1])
# code for function
- code = self.com_node(nodelist[4])
+ code = self.com_node(nodelist[-1])
if doc is not None:
assert isinstance(code, Stmt)
assert isinstance(code.nodes[0], Discard)
del code.nodes[0]
- n = Function(name, names, defaults, flags, doc, code)
+ n = Function(decorators, name, names, defaults, flags, doc, code)
n.lineno = lineno
return n