1 | """
|
2 | runtime.py: Objects and types needed at runtime.
|
3 |
|
4 | asdl/front_end.py and asdl/asdl_.py should not be shipped with the binary.
|
5 | They are only needed for the gen_python.py compiler.
|
6 | """
|
7 | from __future__ import print_function
|
8 |
|
9 | #import posix
|
10 |
|
11 | import cStringIO
|
12 | Buffer = cStringIO.StringIO
|
13 |
|
14 |
|
15 | # Type Descriptors
|
16 | #
|
17 | # These are more convenient than using the AST directly, since it still has
|
18 | # string type names?
|
19 | #
|
20 | # Although we share Product and Sum.
|
21 |
|
22 | class _RuntimeType(object):
|
23 | """A node hierarchy that exists at runtime."""
|
24 | pass
|
25 |
|
26 |
|
27 | class StrType(_RuntimeType):
|
28 | def __repr__(self):
|
29 | return '<Str>'
|
30 |
|
31 |
|
32 | class IntType(_RuntimeType):
|
33 | def __repr__(self):
|
34 | return '<Int>'
|
35 |
|
36 |
|
37 | class BoolType(_RuntimeType):
|
38 | def __repr__(self):
|
39 | return '<Bool>'
|
40 |
|
41 |
|
42 | class DictType(_RuntimeType):
|
43 | def __repr__(self):
|
44 | return '<Dict>'
|
45 |
|
46 |
|
47 | class ArrayType(_RuntimeType):
|
48 | def __init__(self, desc):
|
49 | self.desc = desc
|
50 |
|
51 | def __repr__(self):
|
52 | return '<Array %s>' % self.desc
|
53 |
|
54 |
|
55 | class MaybeType(_RuntimeType):
|
56 | def __init__(self, desc):
|
57 | self.desc = desc # another descriptor
|
58 |
|
59 | def __repr__(self):
|
60 | return '<Maybe %s>' % self.desc
|
61 |
|
62 |
|
63 | class UserType(_RuntimeType):
|
64 | def __init__(self, typ):
|
65 | assert isinstance(typ, type), typ
|
66 | self.typ = typ
|
67 |
|
68 | def __repr__(self):
|
69 | return '<UserType %s>' % self.typ
|
70 |
|
71 |
|
72 | class SumType(_RuntimeType):
|
73 | """Dummy node that doesn't require any reflection.
|
74 |
|
75 | obj.ASDL_TYPE points directly to the constructor, which you reflect on.
|
76 | """
|
77 | def __init__(self, is_simple):
|
78 | self.is_simple = is_simple # for type checking
|
79 | self.cases = [] # list of _RuntimeType for type checking
|
80 |
|
81 | def __repr__(self):
|
82 | # We need an entry for this but we don't use it?
|
83 | return '<SumType with %d cases at %d>' % (
|
84 | len(self.cases), id(self))
|
85 |
|
86 |
|
87 | class CompoundType(_RuntimeType):
|
88 | """A product or Constructor instance. Both have fields."""
|
89 | def __init__(self, fields):
|
90 | # List of (name, _RuntimeType) tuples.
|
91 | # NOTE: This list may be mutated after its set.
|
92 | self.fields = fields
|
93 |
|
94 | def __repr__(self):
|
95 | return '<CompoundType %s>' % self.fields
|
96 |
|
97 | def GetFieldNames(self):
|
98 | for field_name, _ in self.fields:
|
99 | yield field_name
|
100 |
|
101 | def GetFields(self):
|
102 | for field_name, descriptor in self.fields:
|
103 | yield field_name, descriptor
|
104 |
|
105 | def LookupFieldType(self, field_name):
|
106 | """
|
107 | NOTE: Only used by py_meta.py.
|
108 | """
|
109 | for n, descriptor in self.fields:
|
110 | if n == field_name:
|
111 | return descriptor
|
112 | raise TypeError('Invalid field %r' % field_name)
|
113 |
|
114 |
|
115 | BUILTIN_TYPES = {
|
116 | 'string': StrType(),
|
117 | 'int': IntType(),
|
118 | 'bool': BoolType(),
|
119 | 'dict': DictType(),
|
120 | }
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | class Obj(object):
|
126 | # NOTE: We're using CAPS for these static fields, since they are constant at
|
127 | # runtime after metaprogramming.
|
128 | ASDL_TYPE = None # Used for type checking
|
129 |
|
130 |
|
131 | class SimpleObj(Obj):
|
132 | """An enum value.
|
133 |
|
134 | Other simple objects: int, str, maybe later a float.
|
135 | """
|
136 | def __init__(self, enum_id, name):
|
137 | self.enum_id = enum_id
|
138 | self.name = name
|
139 |
|
140 | # TODO: Why is __hash__ needed? Otherwise native/fastlex_test.py fails.
|
141 | # util.Enum required it too. I thought that instances would hash by
|
142 | # identity?
|
143 | #
|
144 | # Example:
|
145 | # class bool_arg_type_e(py_meta.SimpleObj):
|
146 | # ASDL_TYPE = TYPE_LOOKUP['bool_arg_type']
|
147 | # bool_arg_type_e.Undefined = bool_arg_type_e(1, 'Undefined')
|
148 |
|
149 | def __hash__(self):
|
150 | # Could it be the integer self.enum_id?
|
151 | return hash(self.__class__.__name__ + self.name)
|
152 |
|
153 | def __repr__(self):
|
154 | return '<%s %s %s>' % (self.__class__.__name__, self.name, self.enum_id)
|
155 |
|
156 |
|
157 | NUM_TYPE_CHECKS = 0
|
158 |
|
159 | class CompoundObj(Obj):
|
160 | # TODO: Remove tag?
|
161 | # The tag is always set for constructor types, which are subclasses of sum
|
162 | # types. Never set for product types.
|
163 | tag = None
|
164 |
|
165 |
|
166 | # Other possible dynamic checking:
|
167 | # - CheckUnassigned in the constructor? Fields should be all initialized or
|
168 | # none.
|
169 | # - Maybe spids should never be mutated? It can only be appended to?
|
170 | # - SimpleObj could deny all __setattr__?
|