1 | """
|
2 | transform.py - turn homogeneous nil8.asdl represention into heterogeneous
|
3 | yaks.asdl representation
|
4 | """
|
5 | from __future__ import print_function
|
6 |
|
7 | from _devbuild.gen.nil8_asdl import nvalue, nvalue_e, nvalue_t
|
8 | from _devbuild.gen.yaks_asdl import (Module, Program, mod_def, mod_def_t,
|
9 | ktype, ktype_t, stmt, stmt_t, kexpr_t,
|
10 | Int, Token, Signature, NameType)
|
11 |
|
12 | from mycpp.mylib import log, tagswitch
|
13 |
|
14 | from typing import cast, List
|
15 |
|
16 | _ = log
|
17 |
|
18 |
|
19 | def MustBeSymbol(nval):
|
20 | # type: (nvalue_t) -> str
|
21 | if nval.tag() != nvalue_e.Symbol:
|
22 | raise AssertionError('Expected Symbol, got %s' % nval)
|
23 | return cast(nvalue.Symbol, nval).s
|
24 |
|
25 |
|
26 | def MustBeList(nval):
|
27 | # type: (nvalue_t) -> List[nvalue_t]
|
28 | if nval.tag() != nvalue_e.List:
|
29 | raise AssertionError('Expected List, got %s' % nval)
|
30 | return cast(nvalue.List, nval).items
|
31 |
|
32 |
|
33 | def TransformExpr(nval):
|
34 | # type: (nvalue_t) -> kexpr_t
|
35 |
|
36 | UP_nval = nval
|
37 | with tagswitch(nval) as case:
|
38 | if case(nvalue_e.Int):
|
39 | nval = cast(nvalue.Int, UP_nval)
|
40 | loc = Token('path', 'chunk', 0, 3) # TODO
|
41 | return Int(nval.i, loc)
|
42 |
|
43 | else:
|
44 | raise AssertionError()
|
45 |
|
46 |
|
47 | def TransformType(nval):
|
48 | # type: (nvalue_t) -> ktype_t
|
49 |
|
50 | UP_nval = nval
|
51 | with tagswitch(nval) as case:
|
52 |
|
53 | if case(nvalue_e.Symbol):
|
54 | nval = cast(nvalue.Symbol, UP_nval)
|
55 |
|
56 | # TODO: Is there Void type? That's the same as None in Python?
|
57 | # def f() -> None: ...
|
58 |
|
59 | if nval.s == 'Bool':
|
60 | return ktype.Bool
|
61 | elif nval.s == 'Int':
|
62 | return ktype.Int
|
63 | #elif nval.s == 'Float':
|
64 | # return ktype.Float
|
65 | elif nval.s == 'Str':
|
66 | return ktype.Str
|
67 | else:
|
68 | raise AssertionError(nval.s)
|
69 |
|
70 | elif case(nvalue_e.List):
|
71 | nval = cast(nvalue.List, UP_nval)
|
72 |
|
73 | first = MustBeSymbol(nval.items[0])
|
74 | if first == 'List':
|
75 | return ktype.List(TransformType(nval.items[1]))
|
76 | elif first == 'Dict':
|
77 | return ktype.Dict(TransformType(nval.items[1]),
|
78 | TransformType(nval.items[2]))
|
79 | else:
|
80 | raise AssertionError(first)
|
81 |
|
82 | else:
|
83 | raise AssertionError()
|
84 |
|
85 |
|
86 | def TransformParam(param_n):
|
87 | # type: (List[nvalue_t]) -> NameType
|
88 | """
|
89 | [argv [List Int]]
|
90 | """
|
91 |
|
92 | if len(param_n) != 2:
|
93 | raise AssertionError()
|
94 |
|
95 | name = MustBeSymbol(param_n[0])
|
96 | typ = TransformType(param_n[1])
|
97 | return NameType(name, typ)
|
98 |
|
99 |
|
100 | def TransformParams(params_n):
|
101 | # type: (List[nvalue_t]) -> List[NameType]
|
102 | """
|
103 | (func f [
|
104 | [x Int] [y Int] [z [List Int]]
|
105 | ] => Int
|
106 | (return (+ x y))
|
107 | )
|
108 |
|
109 | With default args and prefix *:
|
110 |
|
111 | runtime_asdl::Cell* GetCell(BigStr* name, runtime_asdl::scope_t which_scopes = scope_e::Shopt);
|
112 |
|
113 | (method GetCell [
|
114 | [name (*BigStr)]
|
115 | [which_scopes runtime_asdl::scope_t scope_e::Shopt]
|
116 | ] => (*runtime_asdl::Cell)
|
117 | (call print "hi")
|
118 | )
|
119 |
|
120 | Can't use = here because (scope_t=scope_e) would be parsed before
|
121 | (scope_e::Shopt)
|
122 |
|
123 | [which_scopes runtime_asdl::scope_t=scope_e::Shopt]
|
124 |
|
125 | We don't have any precedence rules.
|
126 | """
|
127 | result = [] # type: List[NameType]
|
128 | for p in params_n:
|
129 | param_n = MustBeList(p)
|
130 | #log('PN %s', param_n)
|
131 | result.append(TransformParam(param_n))
|
132 | return result
|
133 |
|
134 |
|
135 | def TransformSignature(nval):
|
136 | # type: (nvalue_t) -> Signature
|
137 |
|
138 | sig_n = MustBeList(nval)
|
139 | if len(sig_n) != 3:
|
140 | raise AssertionError(
|
141 | 'Signature should have 3 items: => params return')
|
142 |
|
143 | first = MustBeSymbol(sig_n[0])
|
144 | if first != '=>':
|
145 | raise AssertionError('Signature should start with =>')
|
146 |
|
147 | params_n = MustBeList(sig_n[1])
|
148 |
|
149 | return Signature(TransformParams(params_n), TransformType(sig_n[2]))
|
150 |
|
151 |
|
152 | def TransformFunc(func_n):
|
153 | # type: (List[nvalue_t]) -> mod_def.Func
|
154 |
|
155 | func_name = MustBeSymbol(func_n[1])
|
156 | out_stmts = [] # type: List[stmt_t]
|
157 |
|
158 | sig = TransformSignature(func_n[2])
|
159 | func = mod_def.Func(func_name, sig, out_stmts)
|
160 |
|
161 | stmts = func_n[3:]
|
162 | for st in stmts:
|
163 | stmt_n = MustBeList(st)
|
164 |
|
165 | if len(stmt_n) == 0:
|
166 | raise AssertionError("Statement shouldn't be empty")
|
167 |
|
168 | first = MustBeSymbol(stmt_n[0])
|
169 |
|
170 | if first == 'var':
|
171 | pass
|
172 |
|
173 | elif first == 'setvar':
|
174 | # The simple case could be
|
175 | # x = 42
|
176 | # But there are precedence issues
|
177 | # a,42 = (call f 42)
|
178 | # This seems better:
|
179 | # (setvar a,42 (call f 42))
|
180 | pass
|
181 |
|
182 | elif first == 'call':
|
183 | pass
|
184 |
|
185 | elif first == 'return':
|
186 | expr = TransformExpr(stmt_n[1])
|
187 | out_stmts.append(stmt.Return(expr))
|
188 |
|
189 | elif first == 'break':
|
190 | pass
|
191 |
|
192 | elif first == 'continue':
|
193 | pass
|
194 |
|
195 | else:
|
196 | raise AssertionError('Invalid statment %r' % first)
|
197 |
|
198 | return func
|
199 |
|
200 |
|
201 | def TransformModule(mod_n):
|
202 | # type: (List[nvalue_t]) -> Module
|
203 |
|
204 | if len(mod_n) < 2:
|
205 | raise AssertionError('Module should have at least 2 items, got %d' %
|
206 | len(mod_n))
|
207 |
|
208 | mod_name = MustBeSymbol(mod_n[1])
|
209 | out_defs = [] # type: List[mod_def_t]
|
210 | module = Module(mod_name, out_defs)
|
211 |
|
212 | defs = mod_n[2:]
|
213 |
|
214 | for d in defs:
|
215 | # (global ...) (func ...) (class ...)
|
216 | def_n = MustBeList(d)
|
217 |
|
218 | if len(def_n) == 0:
|
219 | raise AssertionError("Module shouldn't be empty")
|
220 |
|
221 | first = MustBeSymbol(def_n[0])
|
222 |
|
223 | if first == 'global':
|
224 | pass
|
225 |
|
226 | elif first == 'func':
|
227 | out_defs.append(TransformFunc(def_n))
|
228 |
|
229 | elif first == 'class':
|
230 | #out_defs.append(TransformClass(def_n))
|
231 | pass
|
232 |
|
233 | else:
|
234 | raise AssertionError('Invalid module def %r' % first)
|
235 |
|
236 | return module
|
237 |
|
238 |
|
239 | def Transform(nval):
|
240 | # type: (nvalue_t) -> Program
|
241 | """
|
242 | TODO: For imports, add
|
243 |
|
244 | - YAKS_PATH
|
245 | - dict of modules that is populated?
|
246 | """
|
247 | mod_n = MustBeList(nval)
|
248 | module = TransformModule(mod_n)
|
249 | prog = Program('foo', [module])
|
250 | return prog
|