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

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