OILS / asdl / front_end_test.py View on Github | oils.pub

217 lines, 106 significant
1#!/usr/bin/env python2
2"""front_end_test.py: Tests for front_end.py."""
3from __future__ import print_function
4
5import cStringIO
6import unittest
7
8from asdl import front_end # module under test
9from asdl import ast
10from asdl import format as fmt
11
12
13class 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("""
60module foo {
61 extern [core vm _Builtin]
62 extern [core vm _Callable]
63
64 -- these are invalid, but checked in name resolution stage
65 point = (int? x, int* y)
66
67 action = Foo | Bar(point z)
68
69 foo = (List[int] span_ids)
70 bar = (Dict[string, int] options)
71
72 -- this check happens later
73 does_not_resolve = (typo zz)
74
75 color = Red | Green
76
77 color2 = Red | Green generate []
78
79 color3 = Red | Green
80 generate [integers]
81
82 color4 = Blue | Purple
83 generate [uint16]
84
85 -- New optional lists
86 spam = (Optional[List[int]] pipe_status)
87 -- Nicer way of writing it
88 spam2 = (List[int]? pipe_status)
89
90 # New syntax for subtypes
91 CompoundWord < List[action]
92}
93""")
94
95 def _assertParseError(self, code_str):
96 f = cStringIO.StringIO(code_str)
97 p = front_end.ASDLParser()
98 try:
99 schema_ast = p.parse(f)
100 except front_end.ASDLSyntaxError as e:
101 print(e)
102 else:
103 self.fail("Expected parse failure: %r" % code_str)
104
105 def testParseErrors(self):
106 # Need field name
107 self._assertParseError('module foo { t = (int) }')
108
109 # Need []
110 self._assertParseError('module foo { t = (List foo) }')
111
112 # Shouldn't have []
113 self._assertParseError('module foo { t = (string[string] a) }')
114
115 # Not enough params
116 self._assertParseError('module foo { t = (Dict[] a) }')
117 self._assertParseError('module foo { t = (Dict[string] a) }')
118 self._assertParseError('module foo { t = (Dict[string, ] a) }')
119
120 self._assertParseError('module foo { ( }')
121
122 # Abandoned syntax
123 self._assertParseError('module foo { simple: integers = A | B }')
124
125 self._assertParseError('module foo { integers = A | B generate }')
126
127 self._assertParseError(
128 'module foo { integers = A | B generate [integers, ,] }')
129
130 self._assertParseError(
131 'module foo { integers = A | B generate [invalid] }')
132
133 self._assertParseError('module foo { CompoundWord < }')
134
135 self._assertParseError('module foo { CompoundWord < (str s) }')
136
137 self._assertParseError('module foo { extern }')
138 self._assertParseError('module foo { extern extern }')
139 self._assertParseError('module foo { extern [ }')
140 self._assertParseError('module foo { extern [] }')
141
142 self._assertParseError('module foo { extern [ foo ] extern [ use ] }')
143
144 def _assertResolve(self, code_str):
145 f = cStringIO.StringIO(code_str)
146 schema_ast = front_end.LoadSchema(f, {})
147
148 print(type(schema_ast))
149 print(schema_ast)
150
151 def testResolve(self):
152 self._assertResolve("""
153module foo {
154 point = (int x, int y)
155 place = None | Two(point a, point b)
156 options = (Dict[string, int] names)
157}
158""")
159
160 def _assertResolveError(self, code_str):
161 f = cStringIO.StringIO(code_str)
162 try:
163 schema_ast = front_end.LoadSchema(f, {})
164 except front_end.ASDLSyntaxError as e:
165 print(e)
166 else:
167 self.fail("Expected name resolution error: %r" % code_str)
168
169 def testResolveErrors(self):
170 self._assertResolveError("""
171module foo {
172 place = None | Two(typo b)
173}
174""")
175
176 # Optional integer isn't allowed, because C++ can't express it
177 # Integers are initialized to -1
178 self._assertResolveError('module foo { t = (int? status) }')
179
180 # Optional simple sum isn't allowed
181 self._assertResolveError('''
182 module foo {
183 color = Red | Green
184 t = (color? status)
185 }
186 ''')
187
188 # Duplicate types
189 self._assertResolveError('''
190 module foo {
191 Color = (str a)
192 Color = (str b)
193 }
194 ''')
195
196 # Duplicate type and subtype
197 self._assertResolveError('''
198 module foo {
199 CompoundWord = (str a)
200 CompoundWord < List[int]
201 }
202 ''')
203
204 def testAstNodes(self):
205 # maybe[string]
206 n1 = ast.NamedType('string')
207 print(n1)
208
209 n2 = ast.ParameterizedType('Optional', [n1])
210 print(n2)
211
212 n3 = ast.ParameterizedType('Dict', [n1, ast.NamedType('int')])
213 print(n3)
214
215
216if __name__ == '__main__':
217 unittest.main()