1 | #!/usr/bin/env python2
|
2 | from __future__ import print_function
|
3 |
|
4 | from _devbuild.gen.syntax_asdl import source, loc, command_t
|
5 | from _devbuild.gen.value_asdl import value, cmd_frag
|
6 | from builtin import hay_ysh
|
7 | from core import alloc
|
8 | from core import error
|
9 | from core import main_loop
|
10 | from core import state
|
11 | from display import ui
|
12 | from core import vm
|
13 | from frontend import reader
|
14 | from frontend import typed_args
|
15 |
|
16 | import posix_ as posix
|
17 |
|
18 | from typing import TYPE_CHECKING, Dict
|
19 |
|
20 | if TYPE_CHECKING:
|
21 | from _devbuild.gen.value_asdl import value_t
|
22 | from core import process
|
23 | from frontend import parse_lib
|
24 | from osh import cmd_eval
|
25 |
|
26 |
|
27 | class ParseHay(vm._Callable):
|
28 | """parseHay()"""
|
29 |
|
30 | def __init__(
|
31 | self,
|
32 | fd_state, # type:process.FdState
|
33 | parse_ctx, # type: parse_lib.ParseContext
|
34 | mem, # type: state.Mem
|
35 | errfmt, # type: ui.ErrorFormatter
|
36 | ):
|
37 | # type: (...) -> None
|
38 | self.fd_state = fd_state
|
39 | self.parse_ctx = parse_ctx
|
40 | self.mem = mem
|
41 | self.errfmt = errfmt
|
42 |
|
43 | def _Call(self, path):
|
44 | # type: (str) -> value_t
|
45 |
|
46 | call_loc = loc.Missing # TODO: location info
|
47 |
|
48 | # TODO: need to close the file!
|
49 | try:
|
50 | f = self.fd_state.Open(path)
|
51 | except (IOError, OSError) as e:
|
52 | msg = posix.strerror(e.errno)
|
53 | raise error.Expr("Couldn't open %r: %s" % (path, msg), call_loc)
|
54 |
|
55 | arena = self.parse_ctx.arena
|
56 | line_reader = reader.FileLineReader(f, arena)
|
57 |
|
58 | parse_opts = state.MakeYshParseOpts()
|
59 | # Note: runtime needs these options and totally different memory
|
60 |
|
61 | # TODO: CommandParser needs parse_opts
|
62 | c_parser = self.parse_ctx.MakeConfigParser(line_reader)
|
63 |
|
64 | # TODO: Should there be a separate config file source?
|
65 | src = source.OtherFile(path, call_loc)
|
66 | try:
|
67 | with alloc.ctx_SourceCode(arena, src):
|
68 | node = main_loop.ParseWholeFile(c_parser)
|
69 | except error.Parse as e:
|
70 | self.errfmt.PrettyPrintError(e)
|
71 | return None
|
72 |
|
73 | return value.Command(cmd_frag.Expr(node), self.mem.CurrentFrame(),
|
74 | self.mem.GlobalFrame())
|
75 |
|
76 | def Call(self, rd):
|
77 | # type: (typed_args.Reader) -> value_t
|
78 |
|
79 | string = rd.PosStr()
|
80 | rd.Done()
|
81 | return self._Call(string)
|
82 |
|
83 |
|
84 | class EvalHay(vm._Callable):
|
85 | """evalHay()"""
|
86 |
|
87 | def __init__(
|
88 | self,
|
89 | hay_state, # type: hay_ysh.HayState
|
90 | mutable_opts, # type: state.MutableOpts
|
91 | mem, # type: state.Mem
|
92 | cmd_ev, #type: cmd_eval.CommandEvaluator
|
93 | ):
|
94 | # type: (...) -> None
|
95 | self.hay_state = hay_state
|
96 | self.mutable_opts = mutable_opts
|
97 | self.mem = mem
|
98 | self.cmd_ev = cmd_ev
|
99 |
|
100 | def _Call(self, cmd):
|
101 | # type: (command_t) -> Dict[str, value_t]
|
102 |
|
103 | with hay_ysh.ctx_HayEval(self.hay_state, self.mutable_opts, self.mem):
|
104 | unused = self.cmd_ev.EvalCommandFrag(cmd)
|
105 |
|
106 | return self.hay_state.Result()
|
107 |
|
108 | # Note: we should discourage the unvalidated top namespace for files? It
|
109 | # needs more validation.
|
110 |
|
111 | def Call(self, rd):
|
112 | # type: (typed_args.Reader) -> value_t
|
113 |
|
114 | cmd = rd.PosCommandFrag()
|
115 | rd.Done()
|
116 | return value.Dict(self._Call(cmd))
|
117 |
|
118 |
|
119 | class BlockAsStr(vm._Callable):
|
120 | """block_as_str
|
121 |
|
122 | TODO:
|
123 | - I think this should be cmd->exportAsJson() or something
|
124 | - maybe not toJson(), because that's a bit cavalier?
|
125 | """
|
126 |
|
127 | def __init__(self, arena):
|
128 | # type: (alloc.Arena) -> None
|
129 | self.arena = arena
|
130 |
|
131 | def _Call(self, block):
|
132 | # type: (value_t) -> value_t
|
133 | return block
|
134 |
|
135 | def Call(self, rd):
|
136 | # type: (typed_args.Reader) -> value_t
|
137 | val = rd.PosValue()
|
138 | rd.Done()
|
139 | return self._Call(val)
|
140 |
|
141 |
|
142 | class HayFunc(vm._Callable):
|
143 | """_hay() register"""
|
144 |
|
145 | def __init__(self, hay_state):
|
146 | # type: (hay_ysh.HayState) -> None
|
147 | self.hay_state = hay_state
|
148 |
|
149 | def _Call(self):
|
150 | # type: () -> Dict[str, value_t]
|
151 | return self.hay_state.HayRegister()
|
152 |
|
153 | def Call(self, rd):
|
154 | # type: (typed_args.Reader) -> value_t
|
155 |
|
156 | # TODO: check args
|
157 | return value.Dict(self._Call())
|