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

388 lines, 188 significant
1"""AST type definitions for Zephyr ASDL itself.
2
3This is not self-hosted! If it were, it would look something like this.
4
5TODO: move it toward this schema
6
7type_expr =
8 NamedType(str name, asdl_type resolved)
9| ParameterizedType(str type_name, List[type_expr] children)
10
11Field = (type_expr typ, str name)
12
13Constructor = (List[Field] fields, str name, str shared_type)
14
15# TODO: use variant instead of constructor
16variant =
17 Simple(str name)
18 Compound(str name, List[fields])
19 SharedVariant(str tag_name, str shared_variant)
20
21Use = (List[str] module_parts, str type_names)
22Extern = (List[str] names)
23
24asdl_type =
25 Sum(List[Constructor] variants, List[str] generate)
26 | SimpleSum() # This is just List[name]
27 | Product(List[Field] fields)
28
29 # These go in the TypeLookup dict!
30 # Shouldn't they be a BINDING?
31 | Use %Use
32 | Extern %Extern
33
34binding =
35 TypeDecl(str name, asdl_type value)
36| SubTypeDecl(str name, type_expr base_class)
37
38Module = (
39 str name,
40 List[Use] uses,
41 List[Extern] externs,
42 # Are Type and SubType ordered? Right now they are. C++ and Python may
43 # differ in terms of order.
44 List[binding] defs
45)
46"""
47from __future__ import print_function
48
49import cStringIO
50
51from typing import List, Optional, Tuple, IO
52
53
54class _Printable(object):
55
56 def Print(self, f, indent):
57 # type: (IO[bytes], int) -> None
58 raise NotImplementedError()
59
60 def __str__(self):
61 # type: () -> str
62 f = cStringIO.StringIO()
63 self.Print(f, 0)
64 return f.getvalue()
65
66
67class asdl_type_t(_Printable):
68 pass
69
70
71class DummyType(asdl_type_t):
72 """
73 Dummy value for subtyping: List_of_command < List[command]
74
75 TODO: Improve this representation
76 """
77 pass
78
79
80class Use(asdl_type_t):
81
82 def __init__(self, module_parts, type_names):
83 # type: (List[str], List[str]) -> None
84 self.module_parts = module_parts
85 self.type_names = type_names
86
87 def Print(self, f, indent):
88 # type: (IO[bytes], int) -> None
89 ind = indent * ' '
90 f.write('%sUse %s {\n' % (ind, ' '.join(self.module_parts)))
91 f.write(' %s%s\n' % (ind, ', '.join(t for t in self.type_names)))
92 f.write('%s}\n' % ind)
93
94
95class Extern(asdl_type_t):
96
97 def __init__(self, names):
98 # type: (List[str]) -> None
99 self.names = names
100
101 def Print(self, f, indent):
102 # type: (IO[bytes], int) -> None
103 ind = indent * ' '
104 f.write('%sExtern [ %s ]\n' % (ind, ' '.join(self.names)))
105
106
107class Module(_Printable):
108
109 def __init__(self, name, uses, externs, dfns):
110 # type: (str, List[Use], List[Extern], List[binding_t]) -> None
111 self.name = name
112 self.uses = uses
113 self.externs = externs
114 self.dfns = dfns
115
116 def Print(self, f, indent):
117 # type: (IO[bytes], int) -> None
118 ind = indent * ' '
119 f.write('%sModule %s {\n' % (ind, self.name))
120
121 for u in self.uses:
122 u.Print(f, indent + 1)
123 f.write('\n')
124
125 for e in self.externs:
126 e.Print(f, indent + 1)
127 f.write('\n')
128
129 for d in self.dfns:
130 d.Print(f, indent + 1)
131 f.write('\n')
132 f.write('%s}\n' % ind)
133
134
135class binding_t(_Printable):
136 pass
137
138
139class TypeDecl(binding_t):
140 """A binding of name to a Sum or Product type."""
141
142 def __init__(self, name, value):
143 # type: (str, asdl_type_t) -> None
144 self.name = name
145 self.value = value
146
147 def Print(self, f, indent):
148 # type: (IO[bytes], int) -> None
149 ind = indent * ' '
150 f.write('%sType %s {\n' % (ind, self.name))
151 self.value.Print(f, indent + 1)
152 f.write('%s}\n' % ind)
153
154
155class SubTypeDecl(binding_t):
156 """A declaration of a subtype.
157
158 CompoundWord < List[word_part]
159 """
160
161 def __init__(self, name, base_class):
162 # type: (str, type_expr_t) -> None
163 self.name = name
164 self.base_class = base_class
165
166 def Print(self, f, indent):
167 # type: (IO[bytes], int) -> None
168 ind = indent * ' '
169 f.write('%sType %s {\n' % (ind, self.name))
170 self.base_class.Print(f, indent + 1)
171 f.write('%s}\n' % ind)
172
173
174class type_expr_t(_Printable):
175 pass
176
177
178class NamedType(type_expr_t):
179 """Int, string are resolved to a Primitive type 'Point' can be resolved to
180 CompoundSum instance, etc."""
181
182 def __init__(self, name):
183 # type: (str) -> None
184 self.name = name
185
186 # Mutated by _ResolveModule / _ResolveType
187 self.resolved = None # type: Optional[asdl_type_t]
188
189 def Print(self, f, indent):
190 # type: (IO[bytes], int) -> None
191 f.write('NamedType %s' % (self.name)) # printed after field
192 f.write(' (%r)' % self.resolved)
193
194
195class ParameterizedType(type_expr_t):
196 """A parameterized type expression, e.g. the type of a field.
197
198 Examples:
199 List[mytype] # used to be mytype*
200 Optional[mytype] # used to by mytype?
201 Dict[str, int]
202 Dict[int, List[str]]
203 """
204
205 def __init__(self, type_name, children):
206 # type: (str, List[type_expr_t]) -> None
207 self.type_name = type_name
208 self.children = children
209
210 def Print(self, f, indent):
211 # type: (IO[bytes], int) -> None
212 """Printed on one line."""
213 f.write('%s' % (self.type_name)) # printed after field
214 if self.children:
215 f.write(' [ ')
216 for i, child in enumerate(self.children):
217 if i != 0:
218 f.write(', ')
219 child.Print(f, indent + 1)
220 f.write(' ]')
221
222
223class Field(_Printable):
224
225 def __init__(self, typ, name):
226 # type: (type_expr_t, str) -> None
227 self.typ = typ # type expression
228 self.name = name # variable name
229
230 def Print(self, f, indent):
231 # type: (IO[bytes], int) -> None
232 ind = indent * ' '
233 f.write('%sField %r ' % (ind, self.name))
234 self.typ.Print(f, indent)
235 f.write('\n')
236
237
238class Constructor(asdl_type_t):
239
240 def __init__(self, name, shared_type, fields):
241 # type: (str, Optional[str], List[Field]) -> None
242 self.name = name
243 self.shared_type = shared_type # for DoubleQuoted %DoubleQuoted
244 self.fields = fields or []
245
246 def Print(self, f, indent):
247 # type: (IO[bytes], int) -> None
248 ind = indent * ' '
249 f.write('%sConstructor %s' % (ind, self.name))
250 if self.shared_type:
251 f.write(' %%%s' % self.shared_type)
252
253 if self.fields:
254 f.write(' {\n')
255 for field in self.fields:
256 field.Print(f, indent + 1)
257 f.write('%s}' % ind)
258
259 f.write('\n')
260
261
262class Sum(_Printable):
263
264 def __init__(self, types, generate=None):
265 # type: (List[Constructor], Optional[List[str]]) -> None
266 self.types = types
267 self.generate = generate or [] # type: List[str]
268
269 def Print(self, f, indent):
270 # type: (IO[bytes], int) -> None
271 ind = indent * ' '
272 f.write('%sSum {\n' % ind)
273 for t in self.types:
274 t.Print(f, indent + 1)
275 if self.generate:
276 f.write('%s generate %s\n' % (ind, self.generate))
277 f.write('%s}\n' % ind)
278
279
280class SimpleSum(Sum):
281 pass
282
283
284class Product(_Printable):
285
286 def __init__(self, fields):
287 # type: (List[Field]) -> None
288 self.fields = fields
289
290 def Print(self, f, indent):
291 # type: (IO[bytes], int) -> None
292 ind = indent * ' '
293 f.write('%sProduct {\n' % ind)
294 for field in self.fields:
295 field.Print(f, indent + 1)
296 f.write('%s}\n' % ind)
297
298
299#
300# Helpers
301#
302
303
304def TypeNameHeuristic(asdl_name):
305 # type: (str) -> Tuple[str, bool]
306 """For 'use'.
307
308 We don't parse the imported file, so we have a heuristic based on
309 the name! e.g. re_t or BraceGroup
310 """
311 is_pointer = True
312
313 if asdl_name == 'id':
314 py_name = 'Id_t'
315 is_pointer = False
316
317 elif asdl_name == 'kind':
318 py_name = 'Kind_t'
319 is_pointer = False
320
321 elif asdl_name[0].islower():
322 py_name = '%s_t' % asdl_name
323
324 else:
325 py_name = asdl_name
326
327 return py_name, is_pointer
328
329
330def NameHack(sum_name):
331 # type: (str) -> str
332 if sum_name == 'id':
333 return 'Id'
334 elif sum_name == 'kind':
335 return 'Kind'
336 return sum_name
337
338
339def MakeSimpleVariant(name):
340 # type: (str) -> Constructor
341 """
342 Used by frontend/{consts,options}_gen.py
343 """
344 return Constructor(name, None, None)
345
346
347def IsOptional(t):
348 # type: (type_expr_t) -> bool
349 if isinstance(t, NamedType):
350 return False
351
352 elif isinstance(t, ParameterizedType):
353 return t.type_name == 'Optional'
354
355 else:
356 raise AssertionError()
357
358
359def IsList(t):
360 # type: (type_expr_t) -> bool
361 if isinstance(t, NamedType):
362 return False
363
364 elif isinstance(t, ParameterizedType):
365 if t.type_name == 'List':
366 return True
367 if t.type_name == 'Optional':
368 return IsList(t.children[0])
369 return False
370
371 else:
372 raise AssertionError()
373
374
375def IsDict(t):
376 # type: (type_expr_t) -> bool
377 if isinstance(t, NamedType):
378 return False
379
380 elif isinstance(t, ParameterizedType):
381 if t.type_name == 'Dict':
382 return True
383 if t.type_name == 'Optional':
384 return IsDict(t.children[0])
385 return False
386
387 else:
388 raise AssertionError()