1 #!/usr/bin/env python2
2 """func_hay.py."""
3 from __future__ import print_function
4
5 from _devbuild.gen.runtime_asdl import value, value_e
6 from _devbuild.gen.syntax_asdl import source, loc, command_t
7 from core import alloc
8 from core import error
9 from core import main_loop
10 from core import state
11 from core import ui
12 from core import vm
13 from frontend import reader
14 from frontend import typed_args
15 from mycpp import mylib
16
17 import posix_ as posix
18
19 from typing import TYPE_CHECKING, cast, Any, List, Dict
20
21 if TYPE_CHECKING:
22 from _devbuild.gen.runtime_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 # Wrap in expr.Block?
68 return value.Block(node)
69
70 def Call(self, args):
71 # type: (typed_args.Reader) -> value_t
72
73 string = args.PosStr()
74 args.Done()
75 return self._Call(string)
76
77
78 class EvalHay(vm._Callable):
79 """evalHay()"""
80
81 def __init__(self, hay_state, mutable_opts, mem, cmd_ev):
82 # type: (state.Hay, state.MutableOpts, state.Mem, cmd_eval.CommandEvaluator) -> None
83 self.hay_state = hay_state
84 self.mutable_opts = mutable_opts
85 self.mem = mem
86 self.cmd_ev = cmd_ev
87
88 def _Call(self, cmd):
89 # type: (command_t) -> Dict[str, value_t]
90
91 with state.ctx_HayEval(self.hay_state, self.mutable_opts,
92 self.mem):
93 unused = self.cmd_ev.EvalBlock(cmd)
94
95 return self.hay_state.Result()
96
97 # Note: we should discourage the unvalidated top namespace for files? It
98 # needs more validation.
99
100 def Call(self, args):
101 # type: (typed_args.Reader) -> value_t
102
103 cmd = args.PosCommand()
104 args.Done()
105 return value.Dict(self._Call(cmd))
106
107
108 class BlockAsStr(vm._Callable):
109 """block_as_str
110
111 TODO:
112 - I think this should be cmd->exportAsJson() or something
113 - maybe not toJson(), because that's a bit cavalier?
114 """
115
116 def __init__(self, arena):
117 # type: (alloc.Arena) -> None
118 self.arena = arena
119
120 def _Call(self, block):
121 # type: (value_t) -> value_t
122 return block
123
124 def Call(self, args):
125 # type: (typed_args.Reader) -> value_t
126 val = args.PosValue()
127 args.Done()
128 return self._Call(val)
129
130
131 class HayFunc(vm._Callable):
132 """_hay() register"""
133
134 def __init__(self, hay_state):
135 # type: (state.Hay) -> None
136 self.hay_state = hay_state
137
138 def _Call(self):
139 # type: () -> Dict[str, value_t]
140 return self.hay_state.HayRegister()
141
142 def Call(self, args):
143 # type: (typed_args.Reader) -> value_t
144
145 # TODO: check args
146 return value.Dict(self._Call())
147