1 | #!/usr/bin/env python2
|
2 | """front_end_test.py: Tests for front_end.py."""
|
3 | from __future__ import print_function
|
4 |
|
5 | import cStringIO
|
6 | import unittest
|
7 |
|
8 | from asdl import front_end # module under test
|
9 | from asdl import ast
|
10 | from asdl import format as fmt
|
11 |
|
12 |
|
13 | class FrontEndTest(unittest.TestCase):
|
14 |
|
15 | def testLoadSchema(self):
|
16 | with open('asdl/examples/typed_demo.asdl') as f:
|
17 | schema_ast = front_end.LoadSchema(f, {}, verbose=True)
|
18 | print(schema_ast)
|
19 |
|
20 | def testSharedVariant(self):
|
21 | with open('asdl/examples/shared_variant.asdl') as f:
|
22 | schema_ast = front_end.LoadSchema(f, {}, verbose=False)
|
23 | print(schema_ast)
|
24 |
|
25 | def testSharedVariantCode(self):
|
26 | # generated by build/dev.sh minimal
|
27 | from _devbuild.gen.shared_variant_asdl import (DoubleQuoted, expr,
|
28 | expr_e, word_part,
|
29 | word_part_e)
|
30 | print(DoubleQuoted)
|
31 |
|
32 | print(expr)
|
33 | print(expr_e)
|
34 |
|
35 | print(word_part)
|
36 | print(word_part_e)
|
37 |
|
38 | # These have the same value!
|
39 | self.assertEqual(65, expr_e.DoubleQuoted)
|
40 | self.assertEqual(expr_e.DoubleQuoted, word_part_e.DoubleQuoted)
|
41 |
|
42 | d = DoubleQuoted(5, ['foo', 'bar'])
|
43 | fmt.PrettyPrint(d)
|
44 | print()
|
45 |
|
46 | b = expr.Binary(d, d)
|
47 | b.spids = [42, 43]
|
48 | fmt.PrettyPrint(b)
|
49 |
|
50 | def _assertParse(self, code_str):
|
51 | f = cStringIO.StringIO(code_str)
|
52 | p = front_end.ASDLParser()
|
53 | schema_ast = p.parse(f)
|
54 | print(schema_ast)
|
55 | # For now just test its type
|
56 | self.assert_(isinstance(schema_ast, ast.Module))
|
57 |
|
58 | def testParse(self):
|
59 | self._assertParse("""
|
60 | module foo {
|
61 | -- these are invalid, but checked in name resolution stage
|
62 | point = (int? x, int* y)
|
63 |
|
64 | action = Foo | Bar(point z)
|
65 |
|
66 | foo = (List[int] span_ids)
|
67 | bar = (Dict[string, int] options)
|
68 |
|
69 | -- this check happens later
|
70 | does_not_resolve = (typo zz)
|
71 |
|
72 | color = Red | Green
|
73 |
|
74 | color2 = Red | Green generate []
|
75 |
|
76 | color3 = Red | Green
|
77 | generate [integers]
|
78 |
|
79 | color4 = Blue | Purple
|
80 | generate [uint16]
|
81 |
|
82 | -- New optional lists
|
83 | spam = (Optional[List[int]] pipe_status)
|
84 | -- Nicer way of writing it
|
85 | spam2 = (List[int]? pipe_status)
|
86 |
|
87 | # New syntax for subtypes
|
88 | CompoundWord < List[action]
|
89 | }
|
90 | """)
|
91 |
|
92 | def _assertParseError(self, code_str):
|
93 | f = cStringIO.StringIO(code_str)
|
94 | p = front_end.ASDLParser()
|
95 | try:
|
96 | schema_ast = p.parse(f)
|
97 | except front_end.ASDLSyntaxError as e:
|
98 | print(e)
|
99 | else:
|
100 | self.fail("Expected parse failure: %r" % code_str)
|
101 |
|
102 | def testParseErrors(self):
|
103 | # Need field name
|
104 | self._assertParseError('module foo { t = (int) }')
|
105 |
|
106 | # Need []
|
107 | self._assertParseError('module foo { t = (List foo) }')
|
108 |
|
109 | # Shouldn't have []
|
110 | self._assertParseError('module foo { t = (string[string] a) }')
|
111 |
|
112 | # Not enough params
|
113 | self._assertParseError('module foo { t = (Dict[] a) }')
|
114 | self._assertParseError('module foo { t = (Dict[string] a) }')
|
115 | self._assertParseError('module foo { t = (Dict[string, ] a) }')
|
116 |
|
117 | self._assertParseError('module foo { ( }')
|
118 |
|
119 | # Abandoned syntax
|
120 | self._assertParseError('module foo { simple: integers = A | B }')
|
121 |
|
122 | self._assertParseError('module foo { integers = A | B generate }')
|
123 |
|
124 | self._assertParseError(
|
125 | 'module foo { integers = A | B generate [integers, ,] }')
|
126 |
|
127 | self._assertParseError(
|
128 | 'module foo { integers = A | B generate [invalid] }')
|
129 |
|
130 | self._assertParseError('module foo { CompoundWord < }')
|
131 |
|
132 | self._assertParseError('module foo { CompoundWord < (str s) }')
|
133 |
|
134 | def _assertResolve(self, code_str):
|
135 | f = cStringIO.StringIO(code_str)
|
136 | schema_ast = front_end.LoadSchema(f, {})
|
137 |
|
138 | print(type(schema_ast))
|
139 | print(schema_ast)
|
140 |
|
141 | def testResolve(self):
|
142 | self._assertResolve("""
|
143 | module foo {
|
144 | point = (int x, int y)
|
145 | place = None | Two(point a, point b)
|
146 | options = (Dict[string, int] names)
|
147 | }
|
148 | """)
|
149 |
|
150 | def _assertResolveError(self, code_str):
|
151 | f = cStringIO.StringIO(code_str)
|
152 | try:
|
153 | schema_ast = front_end.LoadSchema(f, {})
|
154 | except front_end.ASDLSyntaxError as e:
|
155 | print(e)
|
156 | else:
|
157 | self.fail("Expected name resolution error: %r" % code_str)
|
158 |
|
159 | def testResolveErrors(self):
|
160 | self._assertResolveError("""
|
161 | module foo {
|
162 | place = None | Two(typo b)
|
163 | }
|
164 | """)
|
165 |
|
166 | # Optional integer isn't allowed, because C++ can't express it
|
167 | # Integers are initialized to -1
|
168 | self._assertResolveError('module foo { t = (int? status) }')
|
169 |
|
170 | # Optional simple sum isn't allowed
|
171 | self._assertResolveError('''
|
172 | module foo {
|
173 | color = Red | Green
|
174 | t = (color? status)
|
175 | }
|
176 | ''')
|
177 |
|
178 | # Duplicate types
|
179 | self._assertResolveError('''
|
180 | module foo {
|
181 | Color = (str a)
|
182 | Color = (str b)
|
183 | }
|
184 | ''')
|
185 |
|
186 | # Duplicate type and subtype
|
187 | self._assertResolveError('''
|
188 | module foo {
|
189 | CompoundWord = (str a)
|
190 | CompoundWord < List[int]
|
191 | }
|
192 | ''')
|
193 |
|
194 | def testAstNodes(self):
|
195 | # maybe[string]
|
196 | n1 = ast.NamedType('string')
|
197 | print(n1)
|
198 |
|
199 | n2 = ast.ParameterizedType('Optional', [n1])
|
200 | print(n2)
|
201 |
|
202 | n3 = ast.ParameterizedType('Dict', [n1, ast.NamedType('int')])
|
203 | print(n3)
|
204 |
|
205 |
|
206 | if __name__ == '__main__':
|
207 | unittest.main()
|