Ejemplo n.º 1
0
def _InitMem():
    # empty environment, no arena.
    arena = test_lib.MakeArena('<state_test.py>')
    line_id = arena.AddLine(1, 'foo')
    span = ast.line_span(line_id, 0, 1)  # dummy
    arena.AddLineSpan(span)
    return state.Mem('', [], {}, arena)
Ejemplo n.º 2
0
def MakeTestEvaluator():
  arena = alloc.SideArena('<MakeTestEvaluator>')
  mem = state.Mem('', [], {}, arena)
  exec_opts = state.ExecOpts(mem, None)
  splitter = legacy.SplitContext(mem)
  ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter, arena)
  return ev
 def setUp(self):
     arena = test_lib.MakeArena('<ui_test.py>')
     mem = state.Mem('', [], arena, [])
     parse_ctx = test_lib.InitParseContext()
     self.p = prompt.Evaluator('osh', parse_ctx, mem)
     # note: this has a separate 'mem' object
     self.p.word_ev = test_lib.InitWordEvaluator()
Ejemplo n.º 4
0
def EvalCode(code_str, parse_ctx, comp_lookup=None, mem=None, aliases=None):
    """
  Unit tests can evaluate code strings and then use the resulting
  CommandEvaluator.
  """
    arena = parse_ctx.arena

    comp_lookup = comp_lookup or completion.Lookup()
    mem = mem or state.Mem('', [], arena, [])
    parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)
    mem.exec_opts = exec_opts

    state.InitMem(mem, {}, '0.1')
    mutable_opts.Init()

    line_reader, _ = InitLexer(code_str, arena)
    c_parser = parse_ctx.MakeOshParser(line_reader)

    cmd_ev = InitCommandEvaluator(parse_ctx=parse_ctx,
                                  comp_lookup=comp_lookup,
                                  arena=arena,
                                  mem=mem,
                                  aliases=aliases)

    main_loop.Batch(cmd_ev, c_parser, arena)  # Parse and execute!
    return cmd_ev
Ejemplo n.º 5
0
def _MakeRootCompleter(parse_ctx=None, comp_lookup=None):
  compopt_state = completion.OptionState()
  comp_ui_state = comp_ui.State()
  comp_lookup = comp_lookup or completion.Lookup()

  mem = state.Mem('', [], None, [])
  parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)
  mem.exec_opts = exec_opts

  state.InitMem(mem, {}, '0.1')
  mutable_opts.Init()

  if not parse_ctx:
    parse_ctx = test_lib.InitParseContext(parse_opts=parse_opts)
    parse_ctx.Init_Trail(parse_lib.Trail())
    parse_ctx.Init_OnePassParse(True)

  if 1:  # enable for details
    debug_f = util.DebugFile(sys.stdout)
  else:
    debug_f = util.NullDebugFile()

  ev = test_lib.InitWordEvaluator(exec_opts=exec_opts)
  return completion.RootCompleter(ev, mem, comp_lookup, compopt_state,
                                  comp_ui_state, parse_ctx, debug_f)
Ejemplo n.º 6
0
def ParseAndEval(code_str):
    arena = test_lib.MakeArena('<arith_parse_test.py>')
    parse_ctx = test_lib.InitParseContext(arena=arena)
    w_parser = test_lib.InitWordParser(code_str, arena=arena)

    # This is weird but works
    w_parser._Next(lex_mode_e.Arith)  # Calling private method
    anode = w_parser.a_parser.Parse()

    print('node:', anode)

    mem = state.Mem('', [], arena, [])
    parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)
    mem.exec_opts = exec_opts
    state.InitMem(mem, {}, '0.1')

    splitter = split.SplitContext(mem)
    errfmt = ui.ErrorFormatter(arena)

    word_ev = word_eval.CompletionWordEvaluator(mem, exec_opts, mutable_opts,
                                                splitter, errfmt)

    arith_ev = sh_expr_eval.ArithEvaluator(mem, exec_opts, parse_ctx, arena)
    arith_ev.word_ev = word_ev
    return arith_ev.EvalToInt(anode)
Ejemplo n.º 7
0
    def testArgv2(self):
        mem = state.Mem('', ['x', 'y'], {}, None)

        mem.Shift(1)
        self.assertEqual(['y'], mem.GetArgv())

        mem.SetArgv(['i', 'j', 'k'])
        self.assertEqual(['i', 'j', 'k'], mem.GetArgv())
Ejemplo n.º 8
0
  def testExternalCommandAction(self):
    mem = state.Mem('dummy', [], None, [])
    parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)
    mem.exec_opts = exec_opts

    a = completion.ExternalCommandAction(mem)
    comp = self._CompApi([], 0, 'f')
    print(list(a.Matches(comp)))
Ejemplo n.º 9
0
    def testUnset(self):
        mem = state.Mem('', [], {})
        # unset a
        mem.Unset(runtime.LhsName('a'), scope.Dynamic)

        return  # not implemented yet

        # unset a[1]
        mem.Unset(runtime.LhsIndexedName('a', 1), scope.Dynamic)
Ejemplo n.º 10
0
def _InitMem():
    # empty environment, no arena.
    arena = test_lib.MakeArena('<state_test.py>')
    line_id = arena.AddLine(1, 'foo')
    unused = arena.AddLineSpan(line_id, 0, 1)  # dummy
    mem = state.Mem('', [], arena, [])

    parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)

    mem.exec_opts = exec_opts
    return mem
Ejemplo n.º 11
0
    def testGetVar(self):
        mem = state.Mem('', [], {})

        # readonly a=x
        mem.SetVar(runtime.LhsName('a'), runtime.Str('x'),
                   (var_flags.ReadOnly, ), scope.Dynamic)

        val = mem.GetVar('a', scope.Dynamic)
        self.assertEqual(runtime.Str('x'), val)

        val = mem.GetVar('undef', scope.Dynamic)
        self.assertEqual(runtime.Undef(), val)
Ejemplo n.º 12
0
def InitParseContext(arena=None, oil_grammar=None, aliases=None,
                     parse_opts=None):
  arena = arena or MakeArena('<test_lib>')

  if aliases is None:
    aliases = {}

  mem = state.Mem('', [], arena, [])
  if parse_opts is None:
    parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)

  parse_ctx = parse_lib.ParseContext(arena, parse_opts, aliases, oil_grammar)
  return parse_ctx
Ejemplo n.º 13
0
    def testExportThenAssign(self):
        """Regression Test"""
        mem = state.Mem('', [], {})

        # export U
        mem.SetVar(runtime.LhsName('U'), None, (var_flags.Exported, ),
                   scope.Dynamic)
        print(mem)

        # U=u
        mem.SetVar(runtime.LhsName('U'), runtime.Str('u'), (), scope.Dynamic)
        print(mem)
        e = mem.GetExported()
        self.assertEqual({'U': 'u'}, e)
Ejemplo n.º 14
0
def InitExecutor(arena=None):
  arena = arena or MakeArena('<InitExecutor>')

  mem = state.Mem('', [], {}, arena)
  fd_state = process.FdState()
  funcs = {}
  comp_funcs = {}
  # For the tests, we do not use 'readline'.
  exec_opts = state.ExecOpts(mem, None)
  parse_ctx = parse_lib.ParseContext(arena, {})

  debug_f = util.DebugFile(sys.stderr)
  devtools = dev.DevTools(dev.CrashDumper(''), debug_f, debug_f)

  return cmd_exec.Executor(mem, fd_state, funcs, comp_funcs, exec_opts,
                           parse_ctx, devtools)
Ejemplo n.º 15
0
def ParseAndEval(code_str):
    arena = test_lib.MakeArena('<arith_parse_test.py>')
    parse_ctx = parse_lib.ParseContext(arena, {})
    w_parser, _ = parse_ctx.MakeParserForCompletion(code_str, arena)
    w_parser._Next(lex_mode_e.ARITH)  # Calling private method
    anode = w_parser._ReadArithExpr()  # need the right lex state?
    print('node:', anode)

    mem = state.Mem('', [], {}, arena)
    exec_opts = state.ExecOpts(mem, None)
    splitter = legacy.SplitContext(mem)
    ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter, arena)

    arith_ev = expr_eval.ArithEvaluator(mem, exec_opts, ev, arena)
    value = arith_ev.Eval(anode)
    return value
Ejemplo n.º 16
0
def InitWordParser(word_str, oil_at=False, arena=None):
  arena = arena or MakeArena('<test_lib>')

  mem = state.Mem('', [], arena, [])
  parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)

  # CUSTOM SETTING
  mutable_opts.opt0_array[option_i.parse_at] = oil_at

  loader = pyutil.GetResourceLoader()
  oil_grammar = pyutil.LoadOilGrammar(loader)
  parse_ctx = parse_lib.ParseContext(arena, parse_opts, {}, oil_grammar)
  line_reader, _ = InitLexer(word_str, arena)
  c_parser = parse_ctx.MakeOshParser(line_reader)
  # Hack
  return c_parser.w_parser
Ejemplo n.º 17
0
def InitWordEvaluator(exec_opts=None):
    arena = MakeArena('<InitWordEvaluator>')
    mem = state.Mem('', [], arena, [])
    state.InitMem(mem, {}, '0.1')

    if exec_opts is None:
        parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)
        mem.exec_opts = exec_opts  # circular dep

    cmd_deps = cmd_eval.Deps()
    cmd_deps.trap_nodes = []

    splitter = split.SplitContext(mem)
    errfmt = ui.ErrorFormatter(arena)

    ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter, errfmt)
    return ev
Ejemplo n.º 18
0
def ParseAndEval(code_str):
  arena = test_lib.MakeArena('<arith_parse_test.py>')
  w_parser, _ = parse_lib.MakeParserForCompletion(code_str, arena)
  anode = w_parser._ReadArithExpr()  # need the right lex state?

  if not anode:
    raise ExprSyntaxError("failed %s" % w_parser.Error())

  print('node:', anode)

  mem = state.Mem('', [], {}, None)
  exec_opts = state.ExecOpts(mem)
  splitter = legacy.SplitContext(mem)
  ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter)

  arith_ev = expr_eval.ArithEvaluator(mem, exec_opts, ev)
  value = arith_ev.Eval(anode)
  return value
Ejemplo n.º 19
0
def InitWordEvaluator():
    arena = MakeArena('<InitWordEvaluator>')
    mem = state.Mem('', [], arena, [])
    state.InitMem(mem, {})

    opt_array = [False] * option_i.ARRAY_SIZE
    errexit = state._ErrExit()
    parse_opts = optview.Parse(opt_array)
    exec_opts = optview.Exec(opt_array, errexit)
    mem.exec_opts = exec_opts  # circular dep

    exec_deps = cmd_exec.Deps()
    exec_deps.trap_nodes = []

    splitter = split.SplitContext(mem)
    errfmt = ui.ErrorFormatter(arena)

    ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter, errfmt)
    return ev
Ejemplo n.º 20
0
    def setUp(self):
        self.arena = test_lib.MakeArena('process_test.py')

        mem = state.Mem('', [], self.arena, [])
        parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)
        mem.exec_opts = exec_opts

        state.InitMem(mem, {}, '0.1')

        self.job_state = process.JobState()
        sig_state = pyos.SignalState()
        self.tracer = dev.Tracer(None, exec_opts, mutable_opts, mem,
                                 mylib.Stderr())
        self.waiter = process.Waiter(self.job_state, exec_opts, sig_state,
                                     self.tracer)
        errfmt = ui.ErrorFormatter(self.arena)
        self.fd_state = process.FdState(errfmt, self.job_state, None,
                                        self.tracer)
        self.ext_prog = process.ExternalProgram('', self.fd_state, errfmt,
                                                util.NullDebugFile())
Ejemplo n.º 21
0
def ParseAndEval(code_str):
    arena = test_lib.MakeArena('<arith_parse_test.py>')
    w_parser = test_lib.InitWordParser(code_str, arena=arena)
    w_parser._Next(lex_mode_e.Arith)  # Calling private method
    anode = w_parser._ReadArithExpr()  # need the right lex state?
    print('node:', anode)

    mem = state.Mem('', [], arena, [])
    state.InitMem(mem, {})
    parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)

    splitter = split.SplitContext(mem)
    errfmt = ui.ErrorFormatter(arena)

    word_ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter,
                                                errfmt)

    arith_ev = sh_expr_eval.ArithEvaluator(mem, exec_opts, arena)
    arith_ev.word_ev = word_ev
    return arith_ev.EvalToInt(anode)
Ejemplo n.º 22
0
def EvalCode(code_str, parse_ctx, comp_lookup=None, mem=None, aliases=None):
    """
  Unit tests can evaluate code strings and then use the resulting Executor.
  """
    arena = parse_ctx.arena

    comp_lookup = comp_lookup or completion.Lookup()
    mem = mem or state.Mem('', [], arena, [])
    state.InitMem(mem, {})

    line_reader, _ = InitLexer(code_str, arena)
    c_parser = parse_ctx.MakeOshParser(line_reader)

    ex = InitExecutor(parse_ctx=parse_ctx,
                      comp_lookup=comp_lookup,
                      arena=arena,
                      mem=mem,
                      aliases=aliases)

    main_loop.Batch(ex, c_parser, arena)  # Parse and execute!
    return ex
Ejemplo n.º 23
0
    def testArgv(self):
        mem = state.Mem('', [], {})
        mem.PushCall('my-func', ['a', 'b'])
        self.assertEqual(['a', 'b'], mem.GetArgv())

        mem.PushCall('my-func', ['x', 'y'])
        self.assertEqual(['x', 'y'], mem.GetArgv())

        status = mem.Shift(1)
        self.assertEqual(['y'], mem.GetArgv())
        self.assertEqual(0, status)

        status = mem.Shift(1)
        self.assertEqual([], mem.GetArgv())
        self.assertEqual(0, status)

        status = mem.Shift(1)
        self.assertEqual([], mem.GetArgv())
        self.assertEqual(1, status)  # error

        mem.PopCall()
        self.assertEqual(['a', 'b'], mem.GetArgv())
Ejemplo n.º 24
0
def OshMain(argv, login_shell):
    spec = args.FlagsAndOptions()
    spec.ShortFlag('-c', args.Str, quit_parsing_flags=True)  # command string
    spec.ShortFlag('-i')  # interactive

    # TODO: -h too
    spec.LongFlag('--help')
    spec.LongFlag('--version')
    spec.LongFlag('--ast-format',
                  ['text', 'abbrev-text', 'html', 'abbrev-html', 'oheap'],
                  default='abbrev-text')
    spec.LongFlag('--show-ast')  # execute and show
    spec.LongFlag('--fix')
    spec.LongFlag('--debug-spans')
    spec.LongFlag('--print-status')
    spec.LongFlag(
        '--trace',
        ['cmd-parse', 'word-parse', 'lexer'])  # NOTE: can only trace one now
    spec.LongFlag('--hijack-shebang')

    builtin.AddOptionsToArgSpec(spec)

    try:
        opts, opt_index = spec.Parse(argv)
    except args.UsageError as e:
        util.usage(str(e))
        return 2

    if opts.help:
        loader = util.GetResourceLoader()  # TOOD: Use Global
        builtin.Help(['osh-usage'], loader)
        return 0
    if opts.version:
        # OSH version is the only binary in Oil right now, so it's all one version.
        _ShowVersion()
        return 0

    trace_state = util.TraceState()
    if 'cmd-parse' == opts.trace:
        util.WrapMethods(cmd_parse.CommandParser, trace_state)
    if 'word-parse' == opts.trace:
        util.WrapMethods(word_parse.WordParser, trace_state)
    if 'lexer' == opts.trace:
        util.WrapMethods(lexer.Lexer, trace_state)

    if opt_index == len(argv):
        dollar0 = sys.argv[0]  # e.g. bin/osh
    else:
        dollar0 = argv[opt_index]  # the script name, or the arg after -c

    # TODO: Create a --parse action or 'osh parse' or 'oil osh-parse'
    # osh-fix
    # It uses a different memory-management model.  It's a batch program and not
    # an interactive program.

    pool = alloc.Pool()
    arena = pool.NewArena()

    # TODO: Maybe wrap this initialization sequence up in an oil_State, like
    # lua_State.
    status_lines = ui.MakeStatusLines()
    mem = state.Mem(dollar0, argv[opt_index + 1:], os.environ)
    funcs = {}

    # Passed to Executor for 'complete', and passed to completion.Init
    if completion:
        comp_lookup = completion.CompletionLookup()
    else:
        # TODO: NullLookup?
        comp_lookup = None
    exec_opts = state.ExecOpts()
    builtin.SetExecOpts(exec_opts, opts.opt_changes)

    # TODO: How to get a handle to initialized builtins here?
    # tokens.py has it.  I think you just make a separate table, with
    # metaprogramming.
    ex = cmd_exec.Executor(mem, status_lines, funcs, completion, comp_lookup,
                           exec_opts, arena)

    # NOTE: The rc file can contain both commands and functions... ideally we
    # would only want to save nodes/lines for the functions.
    try:
        rc_path = 'oilrc'
        arena.PushSource(rc_path)
        with open(rc_path) as f:
            rc_line_reader = reader.FileLineReader(f, arena=arena)
            _, rc_c_parser = parse_lib.MakeParser(rc_line_reader, arena)
            try:
                rc_node = rc_c_parser.ParseWholeFile()
                if not rc_node:
                    # TODO: Error should return a token, and then the token should have a
                    # arena index, and then look that up in the arena.
                    err = rc_c_parser.Error()
                    ui.PrintErrorStack(err, arena, sys.stderr)
                    return 2  # parse error is code 2
            finally:
                arena.PopSource()

        status = ex.Execute(rc_node)
        #print('oilrc:', status, cflow, file=sys.stderr)
        # Ignore bad status?
    except IOError as e:
        if e.errno != errno.ENOENT:
            raise

    if opts.c is not None:
        arena.PushSource('<command string>')
        line_reader = reader.StringLineReader(opts.c, arena=arena)
        interactive = False
    elif opts.i:  # force interactive
        arena.PushSource('<stdin -i>')
        line_reader = reader.InteractiveLineReader(OSH_PS1, arena=arena)
        interactive = True
    else:
        try:
            script_name = argv[opt_index]
        except IndexError:
            if sys.stdin.isatty():
                arena.PushSource('<interactive>')
                line_reader = reader.InteractiveLineReader(OSH_PS1,
                                                           arena=arena)
                interactive = True
            else:
                arena.PushSource('<stdin>')
                line_reader = reader.FileLineReader(sys.stdin, arena=arena)
                interactive = False
        else:
            arena.PushSource(script_name)
            # TODO: Does this open file descriptor need to be moved beyond 3..9 ?
            # Yes!  See dash input.c setinputfile.  It calls savefd().
            # TODO: It also needs to be closed later.
            try:
                f = open(script_name)
            except IOError as e:
                util.error("Couldn't open %r: %s", script_name,
                           os.strerror(e.errno))
                return 1
            line_reader = reader.FileLineReader(f, arena=arena)
            interactive = False

    # TODO: assert arena.NumSourcePaths() == 1
    # TODO: .rc file needs its own arena.
    w_parser, c_parser = parse_lib.MakeParser(line_reader, arena)

    if interactive:
        # NOTE: We're using a different evaluator here.  The completion system can
        # also run functions... it gets the Executor through Executor._Complete.
        if HAVE_READLINE:
            ev = word_eval.CompletionWordEvaluator(mem, exec_opts)
            status_out = completion.StatusOutput(status_lines, exec_opts)
            completion.Init(builtin.BUILTIN_DEF, mem, funcs, comp_lookup,
                            status_out, ev)

        # TODO: Could instantiate "printer" instead of showing ops
        InteractiveLoop(opts, ex, c_parser, w_parser, line_reader)
        status = 0  # TODO: set code
    else:
        # Parse the whole thing up front
        #print('Parsing file')

        tlog('ParseWholeFile')
        # TODO: Do I need ParseAndEvalLoop?  How is it different than
        # InteractiveLoop?
        try:
            node = c_parser.ParseWholeFile()
        except util.ParseError as e:
            ui.PrettyPrintError(e, arena, sys.stderr)
            print('parse error: %s' % e.UserErrorString(), file=sys.stderr)
            return 2
        else:
            # TODO: Remove this older form of error handling.
            if not node:
                err = c_parser.Error()
                ui.PrintErrorStack(err, arena, sys.stderr)
                return 2  # parse error is code 2

        do_exec = True
        if opts.fix:
            osh2oil.PrintAsOil(arena, node, opts.debug_spans)
            do_exec = False
        if exec_opts.noexec:
            do_exec = False

        if exec_opts.noexec or opts.show_ast:  # -n shows the AST
            if opts.ast_format == 'oheap':
                # TODO: Make this a separate flag?
                if sys.stdout.isatty():
                    raise RuntimeError(
                        'ERROR: Not dumping binary data to a TTY.')
                f = sys.stdout

                enc = encode.Params()
                out = encode.BinOutput(f)
                encode.EncodeRoot(node, enc, out)

            else:  # text output
                f = sys.stdout

                if opts.ast_format in ('text', 'abbrev-text'):
                    ast_f = fmt.DetectConsoleOutput(f)
                elif opts.ast_format in ('html', 'abbrev-html'):
                    ast_f = fmt.HtmlOutput(f)
                else:
                    raise AssertionError
                abbrev_hook = (ast.AbbreviateNodes
                               if 'abbrev-' in opts.ast_format else None)
                tree = fmt.MakeTree(node, abbrev_hook=abbrev_hook)
                ast_f.FileHeader()
                fmt.PrintTree(tree, ast_f)
                ast_f.FileFooter()
                ast_f.write('\n')

            #util.log("Execution skipped because 'noexec' is on ")
            status = 0

        if do_exec:
            tlog('Execute(node)')
            status = ex.Execute(node)
        else:
            status = 0

    return status
Ejemplo n.º 25
0
def InitCommandEvaluator(parse_ctx=None, comp_lookup=None, arena=None, mem=None,
                 aliases=None, ext_prog=None):
  opt0_array = state.InitOpts()
  opt_stacks = [None] * option_i.ARRAY_SIZE
  if parse_ctx:
    arena = parse_ctx.arena
    parse_opts = parse_ctx.parse_opts
  else:
    parse_ctx = InitParseContext()

  mem = mem or state.Mem('', [], arena, [])
  exec_opts = optview.Exec(opt0_array, opt_stacks)
  mutable_opts = state.MutableOpts(mem, opt0_array, opt_stacks, None)
  mem.exec_opts = exec_opts
  state.InitMem(mem, {}, '0.1')
  mutable_opts.Init()

  # No 'readline' in the tests.

  errfmt = ui.ErrorFormatter(arena)
  job_state = process.JobState()
  fd_state = process.FdState(errfmt, job_state)
  aliases = {} if aliases is None else aliases
  procs = {}

  compopt_state = completion.OptionState()
  comp_lookup = comp_lookup or completion.Lookup()

  readline = None  # simulate not having it

  new_var = builtin_assign.NewVar(mem, procs, errfmt)
  assign_builtins = {
      builtin_i.declare: new_var,
      builtin_i.typeset: new_var,
      builtin_i.local: new_var,

      builtin_i.export_: builtin_assign.Export(mem, errfmt),
      builtin_i.readonly: builtin_assign.Readonly(mem, errfmt),
  }
  builtins = {  # Lookup
      builtin_i.echo: builtin_pure.Echo(exec_opts),
      builtin_i.shift: builtin_assign.Shift(mem),

      builtin_i.history: builtin_lib.History(readline, mylib.Stdout()),

      builtin_i.compopt: builtin_comp.CompOpt(compopt_state, errfmt),
      builtin_i.compadjust: builtin_comp.CompAdjust(mem),

      builtin_i.alias: builtin_pure.Alias(aliases, errfmt),
      builtin_i.unalias: builtin_pure.UnAlias(aliases, errfmt),
  }

  debug_f = util.DebugFile(sys.stderr)
  cmd_deps = cmd_eval.Deps()
  cmd_deps.mutable_opts = mutable_opts
  cmd_deps.trap_nodes = []

  search_path = state.SearchPath(mem)
  waiter = process.Waiter(job_state, exec_opts)

  ext_prog = \
      ext_prog or process.ExternalProgram('', fd_state, errfmt, debug_f)

  cmd_deps.dumper = dev.CrashDumper('')
  cmd_deps.debug_f = debug_f

  splitter = split.SplitContext(mem)

  arith_ev = sh_expr_eval.ArithEvaluator(mem, exec_opts, parse_ctx, errfmt)
  bool_ev = sh_expr_eval.BoolEvaluator(mem, exec_opts, parse_ctx, errfmt)
  expr_ev = expr_eval.OilEvaluator(mem, procs, splitter, errfmt)
  word_ev = word_eval.NormalWordEvaluator(mem, exec_opts, mutable_opts,
                                          splitter, errfmt)
  cmd_ev = cmd_eval.CommandEvaluator(mem, exec_opts, errfmt, procs,
                                     assign_builtins, arena, cmd_deps)

  shell_ex = executor.ShellExecutor(
      mem, exec_opts, mutable_opts, procs, builtins, search_path,
      ext_prog, waiter, job_state, fd_state, errfmt)

  assert cmd_ev.mutable_opts is not None, cmd_ev
  prompt_ev = prompt.Evaluator('osh', parse_ctx, mem)

  tracer = dev.Tracer(parse_ctx, exec_opts, mutable_opts, mem, word_ev,
                      debug_f)

  vm.InitCircularDeps(arith_ev, bool_ev, expr_ev, word_ev, cmd_ev, shell_ex,
                      prompt_ev, tracer)

  spec_builder = builtin_comp.SpecBuilder(cmd_ev, parse_ctx, word_ev, splitter,
                                          comp_lookup)
  # Add some builtins that depend on the executor!
  complete_builtin = builtin_comp.Complete(spec_builder, comp_lookup)
  builtins[builtin_i.complete] = complete_builtin
  builtins[builtin_i.compgen] = builtin_comp.CompGen(spec_builder)

  return cmd_ev
Ejemplo n.º 26
0
 def testExternalCommandAction(self):
     mem = state.Mem('dummy', [], {}, None)
     a = completion.ExternalCommandAction(mem)
     print(list(a.Matches([], 0, 'f')))
Ejemplo n.º 27
0
def _MakeTestEvaluator():
    mem = state.Mem('', [], {}, None)
    exec_opts = state.ExecOpts(mem)
    splitter = legacy.SplitContext(mem)
    ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter)
    return ev
Ejemplo n.º 28
0
from osh import builtin_misc
from asdl import runtime

Process = process.Process
ExternalThunk = process.ExternalThunk


def Banner(msg):
  print('-' * 60)
  print(msg)


# TODO: Put these all in a function.
_ARENA = test_lib.MakeArena('process_test.py')

_MEM = state.Mem('', [], _ARENA, [])
state.InitMem(_MEM, {}, '0.1')

_OPT_ARRAY = [False] * option_i.ARRAY_SIZE
_PARSE_OPTS = optview.Parse(_OPT_ARRAY)
_ERREXIT = state._ErrExit()
_EXEC_OPTS = state.MutableOpts(_MEM, _OPT_ARRAY, _ERREXIT, None)
_JOB_STATE = process.JobState()
_WAITER = process.Waiter(_JOB_STATE, _EXEC_OPTS)
_ERRFMT = ui.ErrorFormatter(_ARENA)
_FD_STATE = process.FdState(_ERRFMT, _JOB_STATE)
_EXT_PROG = process.ExternalProgram('', _FD_STATE, _ERRFMT,
                                    util.NullDebugFile())


def _CommandNode(code_str, arena):
Ejemplo n.º 29
0
def OshMain(argv0, argv, login_shell):
    spec = args.FlagsAndOptions()
    spec.ShortFlag('-c', args.Str, quit_parsing_flags=True)  # command string
    spec.ShortFlag('-i')  # interactive

    # TODO: -h too
    spec.LongFlag('--help')
    spec.LongFlag('--version')
    spec.LongFlag(
        '--ast-format',
        ['text', 'abbrev-text', 'html', 'abbrev-html', 'oheap', 'none'],
        default='abbrev-text')
    spec.LongFlag('--show-ast')  # execute and show
    spec.LongFlag('--fix')
    spec.LongFlag('--debug-spans')  # For oshc translate
    spec.LongFlag('--print-status')
    spec.LongFlag(
        '--trace',
        ['cmd-parse', 'word-parse', 'lexer'])  # NOTE: can only trace one now
    spec.LongFlag('--hijack-shebang')

    # For benchmarks/*.sh
    spec.LongFlag('--parser-mem-dump', args.Str)
    spec.LongFlag('--runtime-mem-dump', args.Str)

    builtin.AddOptionsToArgSpec(spec)

    try:
        opts, opt_index = spec.Parse(argv)
    except args.UsageError as e:
        util.usage(str(e))
        return 2

    if opts.help:
        loader = util.GetResourceLoader()
        builtin.Help(['osh-usage'], loader)
        return 0
    if opts.version:
        # OSH version is the only binary in Oil right now, so it's all one version.
        _ShowVersion()
        return 0

    trace_state = util.TraceState()
    if 'cmd-parse' == opts.trace:
        util.WrapMethods(cmd_parse.CommandParser, trace_state)
    if 'word-parse' == opts.trace:
        util.WrapMethods(word_parse.WordParser, trace_state)
    if 'lexer' == opts.trace:
        util.WrapMethods(lexer.Lexer, trace_state)

    if opt_index == len(argv):
        dollar0 = argv0
    else:
        dollar0 = argv[opt_index]  # the script name, or the arg after -c

    # TODO: Create a --parse action or 'osh parse' or 'oil osh-parse'
    # osh-fix
    # It uses a different memory-management model.  It's a batch program and not
    # an interactive program.

    pool = alloc.Pool()
    arena = pool.NewArena()

    # TODO: Maybe wrap this initialization sequence up in an oil_State, like
    # lua_State.
    status_lines = ui.MakeStatusLines()
    mem = state.Mem(dollar0, argv[opt_index + 1:], os.environ, arena)
    funcs = {}

    # Passed to Executor for 'complete', and passed to completion.Init
    if completion:
        comp_lookup = completion.CompletionLookup()
    else:
        # TODO: NullLookup?
        comp_lookup = None

    exec_opts = state.ExecOpts(mem)
    builtin.SetExecOpts(exec_opts, opts.opt_changes)

    fd_state = process.FdState()
    ex = cmd_exec.Executor(mem, fd_state, status_lines, funcs, readline,
                           completion, comp_lookup, exec_opts, arena)

    # NOTE: The rc file can contain both commands and functions... ideally we
    # would only want to save nodes/lines for the functions.
    try:
        rc_path = 'oilrc'
        arena.PushSource(rc_path)
        with open(rc_path) as f:
            rc_line_reader = reader.FileLineReader(f, arena)
            _, rc_c_parser = parse_lib.MakeParser(rc_line_reader, arena)
            try:
                rc_node = rc_c_parser.ParseWholeFile()
                if not rc_node:
                    err = rc_c_parser.Error()
                    ui.PrintErrorStack(err, arena, sys.stderr)
                    return 2  # parse error is code 2
            finally:
                arena.PopSource()

        status = ex.Execute(rc_node)
        #print('oilrc:', status, cflow, file=sys.stderr)
        # Ignore bad status?
    except IOError as e:
        if e.errno != errno.ENOENT:
            raise

    if opts.c is not None:
        arena.PushSource('<command string>')
        line_reader = reader.StringLineReader(opts.c, arena)
        if opts.i:  # -c and -i can be combined
            exec_opts.interactive = True
    elif opts.i:  # force interactive
        arena.PushSource('<stdin -i>')
        line_reader = reader.InteractiveLineReader(OSH_PS1, arena)
        exec_opts.interactive = True
    else:
        try:
            script_name = argv[opt_index]
        except IndexError:
            if sys.stdin.isatty():
                arena.PushSource('<interactive>')
                line_reader = reader.InteractiveLineReader(OSH_PS1, arena)
                exec_opts.interactive = True
            else:
                arena.PushSource('<stdin>')
                line_reader = reader.FileLineReader(sys.stdin, arena)
        else:
            arena.PushSource(script_name)
            try:
                f = fd_state.Open(script_name)
            except OSError as e:
                util.error("Couldn't open %r: %s", script_name,
                           os.strerror(e.errno))
                return 1
            line_reader = reader.FileLineReader(f, arena)

    # TODO: assert arena.NumSourcePaths() == 1
    # TODO: .rc file needs its own arena.
    w_parser, c_parser = parse_lib.MakeParser(line_reader, arena)

    if exec_opts.interactive:
        # NOTE: We're using a different evaluator here.  The completion system can
        # also run functions... it gets the Executor through Executor._Complete.
        if HAVE_READLINE:
            splitter = legacy.SplitContext(mem)
            ev = word_eval.CompletionWordEvaluator(mem, exec_opts, splitter)
            status_out = completion.StatusOutput(status_lines, exec_opts)
            completion.Init(pool, builtin.BUILTIN_DEF, mem, funcs, comp_lookup,
                            status_out, ev)

        return InteractiveLoop(opts, ex, c_parser, w_parser, line_reader)
    else:
        # Parse the whole thing up front
        #print('Parsing file')

        _tlog('ParseWholeFile')
        # TODO: Do I need ParseAndEvalLoop?  How is it different than
        # InteractiveLoop?
        try:
            node = c_parser.ParseWholeFile()
        except util.ParseError as e:
            ui.PrettyPrintError(e, arena, sys.stderr)
            print('parse error: %s' % e.UserErrorString(), file=sys.stderr)
            return 2
        else:
            # TODO: Remove this older form of error handling.
            if not node:
                err = c_parser.Error()
                assert err, err  # can't be empty
                ui.PrintErrorStack(err, arena, sys.stderr)
                return 2  # parse error is code 2

        do_exec = True
        if opts.fix:
            #log('SPANS: %s', arena.spans)
            osh2oil.PrintAsOil(arena, node, opts.debug_spans)
            do_exec = False
        if exec_opts.noexec:
            do_exec = False

        # Do this after parsing the entire file.  There could be another option to
        # do it before exiting runtime?
        if opts.parser_mem_dump:
            # This might be superstition, but we want to let the value stabilize
            # after parsing.  bash -c 'cat /proc/$$/status' gives different results
            # with a sleep.
            time.sleep(0.001)
            input_path = '/proc/%d/status' % os.getpid()
            with open(input_path) as f, open(opts.parser_mem_dump, 'w') as f2:
                contents = f.read()
                f2.write(contents)
                log('Wrote %s to %s (--parser-mem-dump)', input_path,
                    opts.parser_mem_dump)

        # -n prints AST, --show-ast prints and executes
        if exec_opts.noexec or opts.show_ast:
            if opts.ast_format == 'none':
                print('AST not printed.', file=sys.stderr)
            elif opts.ast_format == 'oheap':
                # TODO: Make this a separate flag?
                if sys.stdout.isatty():
                    raise RuntimeError(
                        'ERROR: Not dumping binary data to a TTY.')
                f = sys.stdout

                enc = encode.Params()
                out = encode.BinOutput(f)
                encode.EncodeRoot(node, enc, out)

            else:  # text output
                f = sys.stdout

                if opts.ast_format in ('text', 'abbrev-text'):
                    ast_f = fmt.DetectConsoleOutput(f)
                elif opts.ast_format in ('html', 'abbrev-html'):
                    ast_f = fmt.HtmlOutput(f)
                else:
                    raise AssertionError
                abbrev_hook = (ast_lib.AbbreviateNodes
                               if 'abbrev-' in opts.ast_format else None)
                tree = fmt.MakeTree(node, abbrev_hook=abbrev_hook)
                ast_f.FileHeader()
                fmt.PrintTree(tree, ast_f)
                ast_f.FileFooter()
                ast_f.write('\n')

            #util.log("Execution skipped because 'noexec' is on ")
            status = 0

        if do_exec:
            _tlog('Execute(node)')
            status = ex.ExecuteAndRunExitTrap(node)
            # NOTE: 'exit 1' is ControlFlow and gets here, but subshell/commandsub
            # don't because they call sys.exit().
            if opts.runtime_mem_dump:
                # This might be superstition, but we want to let the value stabilize
                # after parsing.  bash -c 'cat /proc/$$/status' gives different results
                # with a sleep.
                time.sleep(0.001)
                input_path = '/proc/%d/status' % os.getpid()
                with open(input_path) as f, open(opts.runtime_mem_dump,
                                                 'w') as f2:
                    contents = f.read()
                    f2.write(contents)
                    log('Wrote %s to %s (--runtime-mem-dump)', input_path,
                        opts.runtime_mem_dump)

        else:
            status = 0

    return status
Ejemplo n.º 30
0
from core import test_lib
from core import word_eval
from core import ui
from core.id_kind import Id

from osh import ast_ as ast
from osh import parse_lib

assign_op_e = ast.assign_op_e

A1 = completion.WordsAction(['foo.py', 'foo', 'bar.py'])

C1 = completion.ChainedCompleter([A1])

status_lines = [ui.TestStatusLine()] * 10  # A bunch of dummies
mem = state.Mem('', [], {}, None)
exec_opts = state.ExecOpts(mem)
STATUS = completion.StatusOutput(status_lines, exec_opts)

V1 = completion.WordsAction(['$var1', '$var2', '$another_var'])

EMPTY = completion.WordsAction(['grep', 'sed', 'test'])
FIRST = completion.WordsAction(['grep', 'sed', 'test'])


class CompletionTest(unittest.TestCase):
    def testLookup(self):
        c = completion.CompletionLookup()
        c.RegisterName('grep', C1)
        print(c.GetCompleterForName('grep'))
        print(c.GetCompleterForName('/usr/bin/grep'))