| 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()) |