OILS / yaks / transform.py View on Github | oilshell.org

250 lines, 126 significant
1"""
2transform.py - turn homogeneous nil8.asdl represention into heterogeneous
3yaks.asdl representation
4"""
5from __future__ import print_function
6
7from _devbuild.gen.nil8_asdl import nvalue, nvalue_e, nvalue_t
8from _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
12from mycpp.mylib import log, tagswitch
13
14from typing import cast, List
15
16_ = log
17
18
19def 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
26def 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
33def 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
47def 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
86def 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
100def 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
135def 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
152def 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
201def 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
239def 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