OILS / asdl / front_end_test.py View on Github | oilshell.org

207 lines, 101 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 -- 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("""
143module 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("""
161module 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
206if __name__ == '__main__':
207 unittest.main()