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