Commit 52c259aa authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Parsing.py parses [] buffer access; fixed a unit test; Node.dump implemented

parent 7308254f
...@@ -91,6 +91,7 @@ def error(position, message): ...@@ -91,6 +91,7 @@ def error(position, message):
#print "Errors.error:", repr(position), repr(message) ### #print "Errors.error:", repr(position), repr(message) ###
global num_errors global num_errors
err = CompileError(position, message) err = CompileError(position, message)
# if position is not None: raise Exception(err) # debug
line = "%s\n" % err line = "%s\n" % err
if listing_file: if listing_file:
listing_file.write(line) listing_file.write(line)
......
...@@ -172,7 +172,27 @@ class Node(object): ...@@ -172,7 +172,27 @@ class Node(object):
self._end_pos = pos self._end_pos = pos
return pos return pos
def dump(self, level=0, filter_out=("pos",)):
def dump_child(x, level):
if isinstance(x, Node):
return x.dump(level)
elif isinstance(x, list):
return "[%s]" % ", ".join(dump_child(item, level) for item in x)
else:
return repr(x)
attrs = [(key, value) for key, value in self.__dict__.iteritems() if key not in filter_out]
if len(attrs) == 0:
return "<%s>" % self.__class__.__name__
else:
indent = " " * level
res = "<%s\n" % (self.__class__.__name__)
for key, value in attrs:
res += "%s %s: %s\n" % (indent, key, dump_child(value, level + 1))
res += "%s>" % indent
return res
class BlockNode: class BlockNode:
# Mixin class for nodes representing a declaration block. # Mixin class for nodes representing a declaration block.
...@@ -587,6 +607,16 @@ class CSimpleBaseTypeNode(CBaseTypeNode): ...@@ -587,6 +607,16 @@ class CSimpleBaseTypeNode(CBaseTypeNode):
else: else:
return PyrexTypes.error_type return PyrexTypes.error_type
class CBufferAccessTypeNode(Node):
# base_type_node CBaseTypeNode
# positional_args [ExprNode] List of positional arguments
# keyword_args DictNode Keyword arguments
child_attrs = ["base_type_node", "positional_args", "keyword_args"]
def analyse(self, env):
return self.base_type_node.analyse(env)
class CComplexBaseTypeNode(CBaseTypeNode): class CComplexBaseTypeNode(CBaseTypeNode):
# base_type CBaseTypeNode # base_type CBaseTypeNode
......
...@@ -281,18 +281,20 @@ def p_trailer(s, node1): ...@@ -281,18 +281,20 @@ def p_trailer(s, node1):
return ExprNodes.AttributeNode(pos, return ExprNodes.AttributeNode(pos,
obj = node1, attribute = name) obj = node1, attribute = name)
# arglist: argument (',' argument)* [','] def p_positional_and_keyword_callargs(s, end_sy_set):
# argument: [test '='] test # Really [keyword '='] test """
Parses positional and keyword call arguments. end_sy_set
def p_call(s, function): should contain any s.sy that terminate the argument chain
# s.sy == '(' (this is ('*', '**', ')') for a normal function call,
pos = s.position() and (']',) for buffers declarators).
s.next()
Returns: (positional_args, keyword_args)
"""
positional_args = [] positional_args = []
keyword_args = [] keyword_args = []
star_arg = None while s.sy not in end_sy_set:
starstar_arg = None if s.sy == '*' or s.sy == '**':
while s.sy not in ('*', '**', ')'): s.error('Argument expansion not allowed here.')
arg = p_simple_expr(s) arg = p_simple_expr(s)
if s.sy == '=': if s.sy == '=':
s.next() s.next()
...@@ -312,6 +314,21 @@ def p_call(s, function): ...@@ -312,6 +314,21 @@ def p_call(s, function):
if s.sy != ',': if s.sy != ',':
break break
s.next() s.next()
return positional_args, keyword_args
# arglist: argument (',' argument)* [',']
# argument: [test '='] test # Really [keyword '='] test
def p_call(s, function):
# s.sy == '('
pos = s.position()
s.next()
star_arg = None
starstar_arg = None
positional_args, keyword_args = (
p_positional_and_keyword_callargs(s,('*', '**', ')')))
if s.sy == '*': if s.sy == '*':
s.next() s.next()
star_arg = p_simple_expr(s) star_arg = p_simple_expr(s)
...@@ -1528,11 +1545,35 @@ def p_c_simple_base_type(s, self_flag, nonempty): ...@@ -1528,11 +1545,35 @@ def p_c_simple_base_type(s, self_flag, nonempty):
else: else:
#print "p_c_simple_base_type: not looking at type at", s.position() #print "p_c_simple_base_type: not looking at type at", s.position()
name = None name = None
return Nodes.CSimpleBaseTypeNode(pos,
type_node = Nodes.CSimpleBaseTypeNode(pos,
name = name, module_path = module_path, name = name, module_path = module_path,
is_basic_c_type = is_basic, signed = signed, is_basic_c_type = is_basic, signed = signed,
longness = longness, is_self_arg = self_flag) longness = longness, is_self_arg = self_flag)
# Treat trailing [] on type as buffer access
if s.sy == '[':
if is_basic:
p.error("Basic C types do not support buffer access")
s.next()
positional_args, keyword_args = (
p_positional_and_keyword_callargs(s, ('[]',)))
s.expect(']')
keyword_dict = ExprNodes.DictNode(pos,
key_value_pairs = [
ExprNodes.DictItemNode(pos=key.pos, key=key, value=value)
for key, value in keyword_args
])
return Nodes.CBufferAccessTypeNode(pos,
positional_args = positional_args,
keyword_args = keyword_dict,
base_type_node = type_node)
else:
return type_node
def looking_at_type(s): def looking_at_type(s):
return looking_at_base_type(s) or s.looking_at_type_name() return looking_at_base_type(s) or s.looking_at_type_name()
......
...@@ -4,6 +4,7 @@ from Cython.Compiler.Nodes import * ...@@ -4,6 +4,7 @@ from Cython.Compiler.Nodes import *
import Cython.Compiler.Naming as Naming import Cython.Compiler.Naming as Naming
class TestTreeFragments(CythonTest): class TestTreeFragments(CythonTest):
def test_basic(self): def test_basic(self):
F = self.fragment(u"x = 4") F = self.fragment(u"x = 4")
T = F.copy() T = F.copy()
...@@ -46,13 +47,14 @@ class TestTreeFragments(CythonTest): ...@@ -46,13 +47,14 @@ class TestTreeFragments(CythonTest):
self.assertEquals(v.pos, a.pos) self.assertEquals(v.pos, a.pos)
def test_temps(self): def test_temps(self):
import Cython.Compiler.Visitor as v
v.tmpnamectr = 0
F = self.fragment(u""" F = self.fragment(u"""
TMP TMP
x = TMP x = TMP
""") """)
T = F.substitute(temps=[u"TMP"]) T = F.substitute(temps=[u"TMP"])
s = T.stats s = T.stats
print s[0].expr.name
self.assert_(s[0].expr.name == Naming.temp_prefix + u"1_TMP", s[0].expr.name) self.assert_(s[0].expr.name == Naming.temp_prefix + u"1_TMP", s[0].expr.name)
self.assert_(s[1].rhs.name == Naming.temp_prefix + u"1_TMP") self.assert_(s[1].rhs.name == Naming.temp_prefix + u"1_TMP")
self.assert_(s[0].expr.name != u"TMP") self.assert_(s[0].expr.name != u"TMP")
......
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