| 1 | #!/usr/bin/env python2
 | 
| 2 | """Flag_gen.py."""
 | 
| 3 | from __future__ import print_function
 | 
| 4 | 
 | 
| 5 | import itertools
 | 
| 6 | import sys
 | 
| 7 | 
 | 
| 8 | from _devbuild.gen.runtime_asdl import flag_type_e
 | 
| 9 | from _devbuild.gen.value_asdl import value_e
 | 
| 10 | from frontend import args
 | 
| 11 | from frontend import flag_def  # side effect: flags are defined!
 | 
| 12 | from frontend import flag_spec
 | 
| 13 | from mycpp import mops
 | 
| 14 | from mycpp.mylib import log, switch
 | 
| 15 | # This causes a circular build dependency!  That is annoying.
 | 
| 16 | # builtin_comp -> core/completion -> pylib/{os_path,path_stat,...} -> posix_
 | 
| 17 | #from osh import builtin_comp
 | 
| 18 | 
 | 
| 19 | _ = flag_def
 | 
| 20 | 
 | 
| 21 | 
 | 
| 22 | def CString(s):
 | 
| 23 |     # HACKS for now
 | 
| 24 | 
 | 
| 25 |     assert '"' not in s, s
 | 
| 26 |     assert '\\' not in s, s
 | 
| 27 | 
 | 
| 28 |     # For the default of write --end
 | 
| 29 |     if s == '\n':
 | 
| 30 |         return '"\\n"'
 | 
| 31 | 
 | 
| 32 |     return '"%s"' % s
 | 
| 33 | 
 | 
| 34 | 
 | 
| 35 | def _WriteStrArray(f, var_name, a):
 | 
| 36 |     c_strs = ', '.join(CString(s) for s in sorted(a))
 | 
| 37 |     f.write('const char* %s[] = {%s, nullptr};\n' % (var_name, c_strs))
 | 
| 38 |     f.write('\n')
 | 
| 39 | 
 | 
| 40 | 
 | 
| 41 | def _WriteActionParams(f, actions, counter):
 | 
| 42 |     param_names = []
 | 
| 43 |     for key in sorted(actions):
 | 
| 44 |         action = actions[key]
 | 
| 45 |         to_write = None
 | 
| 46 | 
 | 
| 47 |         if isinstance(action, args.SetToString):
 | 
| 48 |             if action.valid:
 | 
| 49 |                 to_write = action.valid
 | 
| 50 | 
 | 
| 51 |         elif isinstance(action, args.SetNamedOption):
 | 
| 52 |             if action.names:
 | 
| 53 |                 to_write = action.names
 | 
| 54 | 
 | 
| 55 |         elif isinstance(action, args.SetNamedAction):
 | 
| 56 |             if action.names:
 | 
| 57 |                 to_write = action.names
 | 
| 58 | 
 | 
| 59 |         if to_write:
 | 
| 60 |             uniq = counter.next()
 | 
| 61 |             var_name = 'params_%d' % uniq
 | 
| 62 | 
 | 
| 63 |             _WriteStrArray(f, var_name, to_write)
 | 
| 64 |         else:
 | 
| 65 |             var_name = None
 | 
| 66 | 
 | 
| 67 |         param_names.append(var_name)
 | 
| 68 | 
 | 
| 69 |     return param_names
 | 
| 70 | 
 | 
| 71 | 
 | 
| 72 | def _WriteActions(f, var_name, actions, counter):
 | 
| 73 |     # TODO: 'osh' and 'set' duplicate shopt params!!!  Maybe we want the entire
 | 
| 74 |     # action not to be duplicated?
 | 
| 75 |     param_names = _WriteActionParams(f, actions, counter)
 | 
| 76 | 
 | 
| 77 |     f.write('Action_c %s[] = {\n' % var_name)
 | 
| 78 |     for i, key in enumerate(sorted(actions)):
 | 
| 79 |         action = actions[key]
 | 
| 80 |         #log('%s %s', key, action)
 | 
| 81 | 
 | 
| 82 |         name = None
 | 
| 83 |         if isinstance(action, args.SetToString):
 | 
| 84 |             if action.quit_parsing_flags:
 | 
| 85 |                 action_type = 'SetToString_q'
 | 
| 86 |             else:
 | 
| 87 |                 action_type = 'SetToString'
 | 
| 88 |             name = action.name
 | 
| 89 | 
 | 
| 90 |         elif isinstance(action, args.SetToInt):
 | 
| 91 |             action_type = 'SetToInt'
 | 
| 92 |             name = action.name
 | 
| 93 | 
 | 
| 94 |         elif isinstance(action, args.SetToFloat):
 | 
| 95 |             action_type = 'SetToFloat'
 | 
| 96 |             name = action.name
 | 
| 97 | 
 | 
| 98 |         elif isinstance(action, args.SetToTrue):
 | 
| 99 |             action_type = 'SetToTrue'
 | 
| 100 |             name = action.name
 | 
| 101 | 
 | 
| 102 |         elif isinstance(action, args.SetAttachedBool):
 | 
| 103 |             action_type = 'SetAttachedBool'
 | 
| 104 |             name = action.name
 | 
| 105 | 
 | 
| 106 |         elif isinstance(action, args.SetOption):
 | 
| 107 |             action_type = 'SetOption'
 | 
| 108 |             name = action.name
 | 
| 109 | 
 | 
| 110 |         elif isinstance(action, args.SetNamedOption):
 | 
| 111 |             if action.shopt:
 | 
| 112 |                 action_type = 'SetNamedOption_shopt'
 | 
| 113 |             else:
 | 
| 114 |                 action_type = 'SetNamedOption'
 | 
| 115 | 
 | 
| 116 |         elif isinstance(action, args.SetAction):
 | 
| 117 |             action_type = 'SetAction'
 | 
| 118 |             name = action.name
 | 
| 119 | 
 | 
| 120 |         elif isinstance(action, args.SetNamedAction):
 | 
| 121 |             action_type = 'SetNamedAction'
 | 
| 122 | 
 | 
| 123 |         else:
 | 
| 124 |             raise AssertionError(action)
 | 
| 125 | 
 | 
| 126 |         name_str = ('"%s"' % name) if name else 'nullptr'
 | 
| 127 |         params_str = param_names[i] or 'nullptr'
 | 
| 128 |         f.write('    {"%s", ActionType_c::%s, %s, %s},\n' %
 | 
| 129 |                 (key, action_type, name_str, params_str))
 | 
| 130 |     #cc_f.write('SetToArg_c %s[] = {\n' % arity1_name)
 | 
| 131 |     f.write('''\
 | 
| 132 |     {},
 | 
| 133 | };
 | 
| 134 | 
 | 
| 135 | ''')
 | 
| 136 | 
 | 
| 137 | 
 | 
| 138 | def _WriteDefaults(cc_f, defaults_name, defaults):
 | 
| 139 |     cc_f.write('DefaultPair_c %s[] = {\n' % defaults_name)
 | 
| 140 | 
 | 
| 141 |     for name in sorted(defaults):
 | 
| 142 |         val = defaults[name]
 | 
| 143 |         if val.tag() == value_e.Bool:
 | 
| 144 |             typ = 'Bool'
 | 
| 145 |             v = '{.b = %s}' % ('true' if val.b else 'false')
 | 
| 146 |         elif val.tag() == value_e.Int:
 | 
| 147 |             typ = 'Int'
 | 
| 148 |             v = '{.i = %s}' % mops.BigTruncate(val.i)
 | 
| 149 |         elif val.tag() == value_e.Float:
 | 
| 150 |             typ = 'Float'
 | 
| 151 |             # printing this to C++ is problematic
 | 
| 152 |             if val.f != -1.0:
 | 
| 153 |                 raise AssertionError('Float default not supported %r' % val.f)
 | 
| 154 |             v = '{.f = -1.0}'
 | 
| 155 |         elif val.tag() == value_e.Undef:
 | 
| 156 |             typ = 'Str'  # default for string
 | 
| 157 |             v = '{}'
 | 
| 158 |         elif val.tag() == value_e.Str:
 | 
| 159 |             # NOTE: 'osh' FlagSpecAndMore_ has default='nice' and default='abbrev-text'
 | 
| 160 |             typ = 'Str'
 | 
| 161 |             v = '{.s = %s}' % CString(val.s)
 | 
| 162 | 
 | 
| 163 |         else:
 | 
| 164 |             raise AssertionError(val)
 | 
| 165 | 
 | 
| 166 |         cc_f.write('    {%s, flag_type_e::%s, %s},\n' %
 | 
| 167 |                    (CString(name), typ, v))
 | 
| 168 | 
 | 
| 169 |     cc_f.write('''\
 | 
| 170 |     {},
 | 
| 171 | };
 | 
| 172 | 
 | 
| 173 | ''')
 | 
| 174 | 
 | 
| 175 | 
 | 
| 176 | def Cpp(specs, header_f, cc_f):
 | 
| 177 |     counter = itertools.count()
 | 
| 178 | 
 | 
| 179 |     header_f.write("""\
 | 
| 180 | // arg_types.h is generated by frontend/flag_gen.py
 | 
| 181 | 
 | 
| 182 | #ifndef ARG_TYPES_H
 | 
| 183 | #define ARG_TYPES_H
 | 
| 184 | 
 | 
| 185 | #include "cpp/frontend_flag_spec.h"  // for FlagSpec_c
 | 
| 186 | #include "mycpp/gc_mylib.h"
 | 
| 187 | 
 | 
| 188 | using value_asdl::value;
 | 
| 189 | using value_asdl::value_e;
 | 
| 190 | 
 | 
| 191 | namespace arg_types {
 | 
| 192 | """)
 | 
| 193 |     for spec_name in sorted(specs):
 | 
| 194 |         spec = specs[spec_name]
 | 
| 195 | 
 | 
| 196 |         if not spec.fields:
 | 
| 197 |             continue  # skip empty 'eval' spec
 | 
| 198 | 
 | 
| 199 |         #
 | 
| 200 |         # Figure out how to initialize the class
 | 
| 201 |         #
 | 
| 202 | 
 | 
| 203 |         init_vals = []
 | 
| 204 |         field_names = []
 | 
| 205 |         field_decls = []
 | 
| 206 |         bits = []
 | 
| 207 |         for field_name in sorted(spec.fields):
 | 
| 208 |             typ = spec.fields[field_name]
 | 
| 209 |             field_name = field_name.replace('-', '_')
 | 
| 210 |             field_names.append(field_name)
 | 
| 211 | 
 | 
| 212 |             with switch(typ) as case:
 | 
| 213 |                 if case(flag_type_e.Bool):
 | 
| 214 |                     init_vals.append(
 | 
| 215 |                         'static_cast<value::Bool*>(attrs->at(StrFromC("%s")))->b'
 | 
| 216 |                         % field_name)
 | 
| 217 |                     field_decls.append('bool %s;' % field_name)
 | 
| 218 | 
 | 
| 219 |                     # Bug that test should find
 | 
| 220 |                     #bits.append('maskbit(offsetof(%s, %s))' % (spec_name, field_name))
 | 
| 221 | 
 | 
| 222 |                 elif case(flag_type_e.Str):
 | 
| 223 |                     # TODO: This code is ugly and inefficient!  Generate something
 | 
| 224 |                     # better.  At least get rid of 'new' everywhere?
 | 
| 225 |                     init_vals.append('''\
 | 
| 226 | attrs->at(StrFromC("%s"))->tag() == value_e::Undef
 | 
| 227 |           ? nullptr
 | 
| 228 |           : static_cast<value::Str*>(attrs->at(StrFromC("%s")))->s''' %
 | 
| 229 |                                      (field_name, field_name))
 | 
| 230 | 
 | 
| 231 |                     field_decls.append('BigStr* %s;' % field_name)
 | 
| 232 | 
 | 
| 233 |                     # BigStr* is a pointer type, so add a field here
 | 
| 234 |                     bits.append('maskbit(offsetof(%s, %s))' %
 | 
| 235 |                                 (spec_name, field_name))
 | 
| 236 | 
 | 
| 237 |                 elif case(flag_type_e.Int):
 | 
| 238 |                     init_vals.append('''\
 | 
| 239 | attrs->at(StrFromC("%s"))->tag() == value_e::Undef
 | 
| 240 |           ? -1
 | 
| 241 |           : static_cast<value::Int*>(attrs->at(StrFromC("%s")))->i''' %
 | 
| 242 |                                      (field_name, field_name))
 | 
| 243 |                     field_decls.append('int %s;' % field_name)
 | 
| 244 | 
 | 
| 245 |                 elif case(flag_type_e.Float):
 | 
| 246 |                     init_vals.append('''\
 | 
| 247 | attrs->at(StrFromC("%s"))->tag() == value_e::Undef
 | 
| 248 |           ? -1
 | 
| 249 |           : static_cast<value::Float*>(attrs->at(StrFromC("%s")))->f''' %
 | 
| 250 |                                      (field_name, field_name))
 | 
| 251 |                     field_decls.append('float %s;' % field_name)
 | 
| 252 | 
 | 
| 253 |                 else:
 | 
| 254 |                     raise AssertionError(typ)
 | 
| 255 | 
 | 
| 256 |         #
 | 
| 257 |         # Now emit the class
 | 
| 258 |         #
 | 
| 259 | 
 | 
| 260 |         if bits:
 | 
| 261 |             obj_tag = 'HeapTag::FixedSize'
 | 
| 262 |             mask_str = 'field_mask()'
 | 
| 263 |         else:
 | 
| 264 |             obj_tag = 'HeapTag::Opaque'
 | 
| 265 |             mask_str = 'kZeroMask'
 | 
| 266 | 
 | 
| 267 |         header_f.write("""
 | 
| 268 | class %s {
 | 
| 269 |  public:
 | 
| 270 |   %s(Dict<BigStr*, value_asdl::value_t*>* attrs)""" % (spec_name, spec_name))
 | 
| 271 | 
 | 
| 272 |         if field_names:
 | 
| 273 |             header_f.write('\n      : ')
 | 
| 274 |             for i, field_name in enumerate(field_names):
 | 
| 275 |                 if i != 0:
 | 
| 276 |                     header_f.write(',\n        ')
 | 
| 277 |                 header_f.write('%s(%s)' % (field_name, init_vals[i]))
 | 
| 278 |         header_f.write(' {\n')
 | 
| 279 |         header_f.write('  }\n')
 | 
| 280 |         header_f.write('\n')
 | 
| 281 | 
 | 
| 282 |         for decl in field_decls:
 | 
| 283 |             header_f.write('  %s\n' % decl)
 | 
| 284 | 
 | 
| 285 |         header_f.write('\n')
 | 
| 286 |         header_f.write('  static constexpr ObjHeader obj_header() {\n')
 | 
| 287 |         header_f.write('    return ObjHeader::Class(%s, %s, sizeof(%s));\n' %
 | 
| 288 |                        (obj_tag, mask_str, spec_name))
 | 
| 289 |         header_f.write('  }\n')
 | 
| 290 | 
 | 
| 291 |         if bits:
 | 
| 292 |             header_f.write('\n')
 | 
| 293 |             header_f.write('  static constexpr uint32_t field_mask() {\n')
 | 
| 294 |             header_f.write('    return\n')
 | 
| 295 |             header_f.write('      ')
 | 
| 296 |             header_f.write('\n    | '.join(bits))
 | 
| 297 |             header_f.write(';\n')
 | 
| 298 |             header_f.write('  }\n')
 | 
| 299 |             header_f.write('\n')
 | 
| 300 | 
 | 
| 301 |         header_f.write("""\
 | 
| 302 | };
 | 
| 303 | """)
 | 
| 304 | 
 | 
| 305 |     header_f.write("""
 | 
| 306 | extern FlagSpec_c kFlagSpecs[];
 | 
| 307 | extern FlagSpecAndMore_c kFlagSpecsAndMore[];
 | 
| 308 | 
 | 
| 309 | }  // namespace arg_types
 | 
| 310 | 
 | 
| 311 | #endif  // ARG_TYPES_H
 | 
| 312 | 
 | 
| 313 | """)
 | 
| 314 | 
 | 
| 315 |     cc_f.write("""\
 | 
| 316 | // arg_types.cc is generated by frontend/flag_gen.py
 | 
| 317 | 
 | 
| 318 | #include "arg_types.h"
 | 
| 319 | using runtime_asdl::flag_type_e;
 | 
| 320 | 
 | 
| 321 | namespace arg_types {
 | 
| 322 | 
 | 
| 323 | """)
 | 
| 324 | 
 | 
| 325 |     var_names = []
 | 
| 326 |     for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC)):
 | 
| 327 |         spec = specs[spec_name]
 | 
| 328 |         arity0_name = None
 | 
| 329 |         arity1_name = None
 | 
| 330 |         actions_long_name = None
 | 
| 331 |         plus_name = None
 | 
| 332 |         defaults_name = None
 | 
| 333 | 
 | 
| 334 |         if spec.arity0:
 | 
| 335 |             arity0_name = 'arity0_%d' % i
 | 
| 336 |             _WriteStrArray(cc_f, arity0_name, spec.arity0)
 | 
| 337 | 
 | 
| 338 |         if spec.arity1:
 | 
| 339 |             arity1_name = 'arity1_%d' % i
 | 
| 340 |             _WriteActions(cc_f, arity1_name, spec.arity1, counter)
 | 
| 341 | 
 | 
| 342 |         if spec.actions_long:
 | 
| 343 |             actions_long_name = 'actions_long_%d' % i
 | 
| 344 |             _WriteActions(cc_f, actions_long_name, spec.actions_long, counter)
 | 
| 345 | 
 | 
| 346 |         if spec.plus_flags:
 | 
| 347 |             plus_name = 'plus_%d' % i
 | 
| 348 |             _WriteStrArray(cc_f, plus_name, spec.plus_flags)
 | 
| 349 | 
 | 
| 350 |         if spec.defaults:
 | 
| 351 |             defaults_name = 'defaults_%d' % i
 | 
| 352 |             _WriteDefaults(cc_f, defaults_name, spec.defaults)
 | 
| 353 | 
 | 
| 354 |         var_names.append((arity0_name, arity1_name, actions_long_name,
 | 
| 355 |                           plus_name, defaults_name))
 | 
| 356 | 
 | 
| 357 |     cc_f.write('FlagSpec_c kFlagSpecs[] = {\n')
 | 
| 358 | 
 | 
| 359 |     # Now print a table
 | 
| 360 |     for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC)):
 | 
| 361 |         spec = specs[spec_name]
 | 
| 362 |         names = var_names[i]
 | 
| 363 |         cc_f.write('    { "%s", %s, %s, %s, %s, %s },\n' % (
 | 
| 364 |             spec_name,
 | 
| 365 |             names[0] or 'nullptr',
 | 
| 366 |             names[1] or 'nullptr',
 | 
| 367 |             names[2] or 'nullptr',
 | 
| 368 |             names[3] or 'nullptr',
 | 
| 369 |             names[4] or 'nullptr',
 | 
| 370 |         ))
 | 
| 371 | 
 | 
| 372 |     cc_f.write("""\
 | 
| 373 |     {},
 | 
| 374 | };
 | 
| 375 | 
 | 
| 376 | """)
 | 
| 377 | 
 | 
| 378 |     n = len(var_names)
 | 
| 379 |     var_names = []
 | 
| 380 |     for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC_AND_MORE)):
 | 
| 381 |         spec = specs[spec_name]
 | 
| 382 |         actions_short_name = None
 | 
| 383 |         actions_long_name = None
 | 
| 384 |         plus_name = None
 | 
| 385 |         defaults_name = None
 | 
| 386 | 
 | 
| 387 |         if spec.actions_short:
 | 
| 388 |             actions_short_name = 'short_%d' % (n + i)
 | 
| 389 |             _WriteActions(cc_f, actions_short_name, spec.actions_short,
 | 
| 390 |                           counter)
 | 
| 391 | 
 | 
| 392 |         #if spec.actions_long:
 | 
| 393 |         if spec.actions_long:
 | 
| 394 |             actions_long_name = 'long_%d' % (n + i)
 | 
| 395 |             _WriteActions(cc_f, actions_long_name, spec.actions_long, counter)
 | 
| 396 | 
 | 
| 397 |         if spec.plus_flags:
 | 
| 398 |             plus_name = 'plus_%d' % i
 | 
| 399 |             _WriteStrArray(cc_f, plus_name, spec.plus_flags)
 | 
| 400 | 
 | 
| 401 |         if spec.defaults:
 | 
| 402 |             defaults_name = 'defaults_%d' % (n + i)
 | 
| 403 |             _WriteDefaults(cc_f, defaults_name, spec.defaults)
 | 
| 404 | 
 | 
| 405 |         var_names.append(
 | 
| 406 |             (actions_short_name, actions_long_name, plus_name, defaults_name))
 | 
| 407 | 
 | 
| 408 |     cc_f.write('FlagSpecAndMore_c kFlagSpecsAndMore[] = {\n')
 | 
| 409 |     for i, spec_name in enumerate(sorted(flag_spec.FLAG_SPEC_AND_MORE)):
 | 
| 410 |         names = var_names[i]
 | 
| 411 |         cc_f.write('    { "%s", %s, %s, %s, %s },\n' % (
 | 
| 412 |             spec_name,
 | 
| 413 |             names[0] or 'nullptr',
 | 
| 414 |             names[1] or 'nullptr',
 | 
| 415 |             names[2] or 'nullptr',
 | 
| 416 |             names[3] or 'nullptr',
 | 
| 417 |         ))
 | 
| 418 | 
 | 
| 419 |     cc_f.write("""\
 | 
| 420 |     {},
 | 
| 421 | };
 | 
| 422 | """)
 | 
| 423 | 
 | 
| 424 |     cc_f.write("""\
 | 
| 425 | }  // namespace arg_types
 | 
| 426 | """)
 | 
| 427 | 
 | 
| 428 | 
 | 
| 429 | def main(argv):
 | 
| 430 |     try:
 | 
| 431 |         action = argv[1]
 | 
| 432 |     except IndexError:
 | 
| 433 |         raise RuntimeError('Action required')
 | 
| 434 | 
 | 
| 435 |     if 0:
 | 
| 436 |         for spec_name in sorted(flag_spec.FLAG_SPEC_AND_MORE):
 | 
| 437 |             log('%s', spec_name)
 | 
| 438 | 
 | 
| 439 |     # Both kinds of specs have 'fields' attributes
 | 
| 440 |     specs = {}
 | 
| 441 |     specs.update(flag_spec.FLAG_SPEC)
 | 
| 442 |     specs.update(flag_spec.FLAG_SPEC_AND_MORE)
 | 
| 443 |     #log('SPECS %s', specs)
 | 
| 444 | 
 | 
| 445 |     for spec_name in sorted(specs):
 | 
| 446 |         spec = specs[spec_name]
 | 
| 447 |         #spec.spec.PrettyPrint(f=sys.stderr)
 | 
| 448 |         #log('spec.arity1 %s', spec.spec.arity1)
 | 
| 449 |         #log('%s', spec_name)
 | 
| 450 | 
 | 
| 451 |         #print(dir(spec))
 | 
| 452 |         #print(spec.arity0)
 | 
| 453 |         #print(spec.arity1)
 | 
| 454 |         #print(spec.options)
 | 
| 455 |         # Every flag has a default
 | 
| 456 |         #log('%s', spec.fields)
 | 
| 457 | 
 | 
| 458 |     if action == 'cpp':
 | 
| 459 |         prefix = argv[2]
 | 
| 460 | 
 | 
| 461 |         with open(prefix + '.h', 'w') as header_f:
 | 
| 462 |             with open(prefix + '.cc', 'w') as cc_f:
 | 
| 463 |                 Cpp(specs, header_f, cc_f)
 | 
| 464 | 
 | 
| 465 |     elif action == 'mypy':
 | 
| 466 |         print("""
 | 
| 467 | from _devbuild.gen.value_asdl import value, value_e, value_t
 | 
| 468 | from frontend.args import _Attributes
 | 
| 469 | from mycpp import mops
 | 
| 470 | from typing import cast, Dict, Optional
 | 
| 471 | """)
 | 
| 472 |         for spec_name in sorted(specs):
 | 
| 473 |             spec = specs[spec_name]
 | 
| 474 | 
 | 
| 475 |             #log('%s spec.fields %s', spec_name, spec.fields)
 | 
| 476 |             if not spec.fields:
 | 
| 477 |                 continue  # skip empty specs, e.g. eval
 | 
| 478 | 
 | 
| 479 |             print("""
 | 
| 480 | class %s(object):
 | 
| 481 |   def __init__(self, attrs):
 | 
| 482 |     # type: (Dict[str, value_t]) -> None
 | 
| 483 | """ % spec_name)
 | 
| 484 | 
 | 
| 485 |             i = 0
 | 
| 486 |             for field_name in sorted(spec.fields):
 | 
| 487 |                 typ = spec.fields[field_name]
 | 
| 488 |                 field_name = field_name.replace('-', '_')
 | 
| 489 | 
 | 
| 490 |                 with switch(typ) as case:
 | 
| 491 |                     if case(flag_type_e.Bool):
 | 
| 492 |                         print(
 | 
| 493 |                             '    self.%s = cast(value.Bool, attrs[%r]).b  # type: bool'
 | 
| 494 |                             % (field_name, field_name))
 | 
| 495 | 
 | 
| 496 |                     elif case(flag_type_e.Str):
 | 
| 497 |                         tmp = 'val%d' % i
 | 
| 498 |                         print('    %s = attrs[%r]' % (tmp, field_name))
 | 
| 499 |                         print(
 | 
| 500 |                             '    self.%s = None if %s.tag() == value_e.Undef else cast(value.Str, %s).s  # type: Optional[str]'
 | 
| 501 |                             % (field_name, tmp, tmp))
 | 
| 502 | 
 | 
| 503 |                     elif case(flag_type_e.Int):
 | 
| 504 |                         tmp = 'val%d' % i
 | 
| 505 |                         print('    %s = attrs[%r]' % (tmp, field_name))
 | 
| 506 |                         print(
 | 
| 507 |                             '    self.%s = mops.BigInt(-1) if %s.tag() == value_e.Undef else cast(value.Int, %s).i  # type: mops.BigInt'
 | 
| 508 |                             % (field_name, tmp, tmp))
 | 
| 509 | 
 | 
| 510 |                     elif case(flag_type_e.Float):
 | 
| 511 |                         tmp = 'val%d' % i
 | 
| 512 |                         print('    %s = attrs[%r]' % (tmp, field_name))
 | 
| 513 |                         print(
 | 
| 514 |                             '    self.%s = -1.0 if %s.tag() == value_e.Undef else cast(value.Float, %s).f  # type: float'
 | 
| 515 |                             % (field_name, tmp, tmp))
 | 
| 516 |                     else:
 | 
| 517 |                         raise AssertionError(typ)
 | 
| 518 | 
 | 
| 519 |                 i += 1
 | 
| 520 | 
 | 
| 521 |             print()
 | 
| 522 | 
 | 
| 523 |     else:
 | 
| 524 |         raise RuntimeError('Invalid action %r' % action)
 | 
| 525 | 
 | 
| 526 | 
 | 
| 527 | if __name__ == '__main__':
 | 
| 528 |     try:
 | 
| 529 |         main(sys.argv)
 | 
| 530 |     except RuntimeError as e:
 | 
| 531 |         print('FATAL: %s' % e, file=sys.stderr)
 | 
| 532 |         sys.exit(1)
 |