1 | from __future__ import print_function
|
2 |
|
3 | from _devbuild.gen.runtime_asdl import cmd_value
|
4 | from _devbuild.gen.value_asdl import value, value_e
|
5 | from core import dev
|
6 | from core import error
|
7 | from core import state
|
8 | from core import vm
|
9 | from display import ui
|
10 | from frontend import args
|
11 | from frontend import flag_util
|
12 | from mycpp.mylib import log
|
13 |
|
14 | from typing import cast, Dict, TYPE_CHECKING
|
15 | if TYPE_CHECKING:
|
16 | from core import optview
|
17 | from osh import cmd_eval
|
18 |
|
19 | _ = log
|
20 |
|
21 |
|
22 | class IsMain(vm._Builtin):
|
23 | """
|
24 | if is-main { echo hi }
|
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 | """
|
38 | source-guard main || return
|
39 | """
|
40 |
|
41 | def __init__(self, guards, exec_opts, errfmt):
|
42 | # type: (Dict[str, bool], optview.Exec, ui.ErrorFormatter) -> None
|
43 | self.guards = guards
|
44 | self.exec_opts = exec_opts
|
45 | self.errfmt = errfmt
|
46 |
|
47 | def Run(self, cmd_val):
|
48 | # type: (cmd_value.Argv) -> int
|
49 | _, arg_r = flag_util.ParseCmdVal('source-guard', cmd_val)
|
50 | name, _ = arg_r.ReadRequired2('requires a name')
|
51 | #log('guards %s', self.guards)
|
52 | if name in self.guards:
|
53 | # already defined
|
54 | if self.exec_opts.redefine_source():
|
55 | self.errfmt.PrintMessage(
|
56 | '(interactive) Reloading source file %r' % name)
|
57 | return 0
|
58 | else:
|
59 | return 1
|
60 | self.guards[name] = True
|
61 | return 0
|
62 |
|
63 |
|
64 | class ModuleInvoke(vm._Builtin):
|
65 | """
|
66 | This is a builtin for the __invoke__ method of Obj my-module
|
67 |
|
68 | use my-module.ysh
|
69 | my-module my-proc
|
70 | """
|
71 |
|
72 | def __init__(self, cmd_ev, tracer, errfmt):
|
73 | # type: (cmd_eval.CommandEvaluator, dev.Tracer, ui.ErrorFormatter) -> None
|
74 | self.cmd_ev = cmd_ev
|
75 | self.tracer = tracer
|
76 | self.errfmt = errfmt
|
77 |
|
78 | def Run(self, cmd_val):
|
79 | # type: (cmd_value.Argv) -> int
|
80 |
|
81 | arg_r = args.Reader(cmd_val.argv, locs=cmd_val.arg_locs)
|
82 | arg_r.Next() # move past the module name
|
83 |
|
84 | invokable_name, invokable_loc = arg_r.Peek2()
|
85 | if invokable_name is None:
|
86 | raise error.Usage(
|
87 | 'module must be invoked with a proc name argument',
|
88 | cmd_val.arg_locs[0])
|
89 |
|
90 | argv, locs = arg_r.Rest2() # include proc name
|
91 |
|
92 | self_obj = cmd_val.self_obj
|
93 | assert self_obj is not None # wouldn't have been called
|
94 |
|
95 | val = self_obj.d.get(invokable_name)
|
96 |
|
97 | #log('invokable_name %r', invokable_name)
|
98 | #log('argv %r', argv)
|
99 |
|
100 | # Similar to Procs::GetInvokable() - Proc or Obj
|
101 |
|
102 | if val is not None:
|
103 | # OK this is a proc 'log', so we found self, so now just invoke it
|
104 | # with the args. No self obj!
|
105 | cmd_val2 = cmd_value.Argv(argv, locs, cmd_val.is_last_cmd, None,
|
106 | cmd_val.proc_args)
|
107 |
|
108 | if val.tag() == value_e.Proc:
|
109 | proc = cast(value.Proc, val)
|
110 | #log('proc %r', proc.name)
|
111 |
|
112 | with dev.ctx_Tracer(self.tracer, 'module-invoke',
|
113 | cmd_val.argv):
|
114 | status = self.cmd_ev.RunProc(proc, cmd_val2)
|
115 | return status
|
116 |
|
117 | # The module itself is an invokable Obj, but it also CONTAINS an
|
118 | # invokable Obj
|
119 | proc_val, self_obj2 = state.ValueIsInvokableObj(val)
|
120 | cmd_val2.self_obj = self_obj2
|
121 | if proc_val:
|
122 | if proc_val.tag() != value_e.Proc:
|
123 | # Technically we can run it like this, but I don't see a
|
124 | # use case. It seems confusing.
|
125 | #return self.cmd_ev.shell_ex.RunBuiltinProc(proc_val.builtin, cmd_val2)
|
126 |
|
127 | raise error.TypeErr(
|
128 | proc_val,
|
129 | "__invoke__ on %r should be a user-defined Proc" %
|
130 | invokable_name, invokable_loc)
|
131 | proc = cast(value.Proc, proc_val)
|
132 |
|
133 | with dev.ctx_Tracer(self.tracer, 'module-invoke',
|
134 | cmd_val.argv):
|
135 | status = self.cmd_ev.RunProc(proc, cmd_val2)
|
136 | return status
|
137 |
|
138 | # Any other type of value
|
139 | raise error.Usage(
|
140 | "module doesn't contain invokable %r" % invokable_name,
|
141 | invokable_loc)
|