| 1 | from __future__ import print_function
 | 
| 2 | 
 | 
| 3 | from _devbuild.gen.runtime_asdl import scope_e
 | 
| 4 | from _devbuild.gen.syntax_asdl import loc
 | 
| 5 | from _devbuild.gen.value_asdl import (value, value_e)
 | 
| 6 | 
 | 
| 7 | from core import error
 | 
| 8 | from core import state
 | 
| 9 | from core import ui
 | 
| 10 | from core import vm
 | 
| 11 | from frontend import args
 | 
| 12 | from frontend import flag_util
 | 
| 13 | from mycpp.mylib import log
 | 
| 14 | 
 | 
| 15 | from typing import Dict, cast, TYPE_CHECKING
 | 
| 16 | if TYPE_CHECKING:
 | 
| 17 |     from _devbuild.gen.runtime_asdl import cmd_value
 | 
| 18 |     from core import optview
 | 
| 19 | 
 | 
| 20 | _ = log
 | 
| 21 | 
 | 
| 22 | 
 | 
| 23 | class IsMain(vm._Builtin):
 | 
| 24 |     """is-main builtin.
 | 
| 25 |     """
 | 
| 26 | 
 | 
| 27 |     def __init__(self, mem):
 | 
| 28 |         # type: (state.Mem) -> None
 | 
| 29 |         self.mem = mem
 | 
| 30 | 
 | 
| 31 |     def Run(self, cmd_val):
 | 
| 32 |         # type: (cmd_value.Argv) -> int
 | 
| 33 |         return 0 if self.mem.is_main else 1
 | 
| 34 | 
 | 
| 35 | 
 | 
| 36 | class SourceGuard(vm._Builtin):
 | 
| 37 |     """source-guard builtin.
 | 
| 38 | 
 | 
| 39 |     source-guard main || return
 | 
| 40 |     """
 | 
| 41 | 
 | 
| 42 |     def __init__(self, guards, exec_opts, errfmt):
 | 
| 43 |         # type: (Dict[str, bool], optview.Exec, ui.ErrorFormatter) -> None
 | 
| 44 |         self.guards = guards
 | 
| 45 |         self.exec_opts = exec_opts
 | 
| 46 |         self.errfmt = errfmt
 | 
| 47 | 
 | 
| 48 |     def Run(self, cmd_val):
 | 
| 49 |         # type: (cmd_value.Argv) -> int
 | 
| 50 |         _, arg_r = flag_util.ParseCmdVal('source-guard', cmd_val)
 | 
| 51 |         name, _ = arg_r.ReadRequired2('requires a name')
 | 
| 52 |         #log('guards %s', self.guards)
 | 
| 53 |         if name in self.guards:
 | 
| 54 |             # already defined
 | 
| 55 |             if self.exec_opts.redefine_module():
 | 
| 56 |                 self.errfmt.PrintMessage(
 | 
| 57 |                     '(interactive) Reloading source file %r' % name)
 | 
| 58 |                 return 0
 | 
| 59 |             else:
 | 
| 60 |                 return 1
 | 
| 61 |         self.guards[name] = True
 | 
| 62 |         return 0
 | 
| 63 | 
 | 
| 64 | 
 | 
| 65 | class Use(vm._Builtin):
 | 
| 66 |     """use bin, use dialect to control the 'first word'.
 | 
| 67 | 
 | 
| 68 |     Examples:
 | 
| 69 |       use bin grep sed
 | 
| 70 | 
 | 
| 71 |       use dialect ninja   # I think it must be in a 'dialect' scope
 | 
| 72 |       use dialect travis
 | 
| 73 |     """
 | 
| 74 | 
 | 
| 75 |     def __init__(self, mem, errfmt):
 | 
| 76 |         # type: (state.Mem, ui.ErrorFormatter) -> None
 | 
| 77 |         self.mem = mem
 | 
| 78 |         self.errfmt = errfmt
 | 
| 79 | 
 | 
| 80 |     def Run(self, cmd_val):
 | 
| 81 |         # type: (cmd_value.Argv) -> int
 | 
| 82 |         arg_r = args.Reader(cmd_val.argv, locs=cmd_val.arg_locs)
 | 
| 83 |         arg_r.Next()  # skip 'use'
 | 
| 84 | 
 | 
| 85 |         arg, arg_loc = arg_r.Peek2()
 | 
| 86 |         if arg is None:
 | 
| 87 |             raise error.Usage("expected 'bin' or 'dialect'", loc.Missing)
 | 
| 88 |         arg_r.Next()
 | 
| 89 | 
 | 
| 90 |         if arg == 'dialect':
 | 
| 91 |             expected, e_loc = arg_r.Peek2()
 | 
| 92 |             if expected is None:
 | 
| 93 |                 raise error.Usage('expected dialect name', loc.Missing)
 | 
| 94 | 
 | 
| 95 |             UP_actual = self.mem.GetValue('_DIALECT', scope_e.Dynamic)
 | 
| 96 |             if UP_actual.tag() == value_e.Str:
 | 
| 97 |                 actual = cast(value.Str, UP_actual).s
 | 
| 98 |                 if actual == expected:
 | 
| 99 |                     return 0  # OK
 | 
| 100 |                 else:
 | 
| 101 |                     self.errfmt.Print_('Expected dialect %r, got %r' %
 | 
| 102 |                                        (expected, actual),
 | 
| 103 |                                        blame_loc=e_loc)
 | 
| 104 | 
 | 
| 105 |                     return 1
 | 
| 106 |             else:
 | 
| 107 |                 # Not printing expected value
 | 
| 108 |                 self.errfmt.Print_('Expected dialect %r' % expected,
 | 
| 109 |                                    blame_loc=e_loc)
 | 
| 110 |                 return 1
 | 
| 111 | 
 | 
| 112 |         # 'use bin' can be used for static analysis.  Although could it also
 | 
| 113 |         # simplify the SearchPath logic?  Maybe ensure that it is memoized?
 | 
| 114 |         if arg == 'bin':
 | 
| 115 |             rest = arg_r.Rest()
 | 
| 116 |             for name in rest:
 | 
| 117 |                 log('bin %s', name)
 | 
| 118 |             return 0
 | 
| 119 | 
 | 
| 120 |         raise error.Usage("expected 'bin' or 'dialect'", arg_loc)
 |