| 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
 |