OILS / builtin / func_hay.py View on Github | oilshell.org

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