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