示例#1
0
def InteractiveLoop(opts, ex, c_parser, w_parser, line_reader):
    # Is this correct?  Are there any non-ANSI terminals?  I guess you can pass
    # -i but redirect stdout.
    if opts.ast_output == '-':
        ast_f = fmt.DetectConsoleOutput(sys.stdout)
    elif opts.ast_output == '-':
        f = open(opts.ast_output,
                 'w')  # implicitly closed when the process ends
        ast_f = fmt.DetectConsoleOutput(f)
    else:
        ast_f = None

    while True:
        try:
            w = c_parser.Peek()
        except KeyboardInterrupt:
            print('Ctrl-C')
            break

        if w is None:
            raise RuntimeError('Failed parse: %s' % c_parser.Error())
        c_id = word.CommandId(w)
        if c_id == Id.Op_Newline:
            print('nothing to execute')
        elif c_id == Id.Eof_Real:
            print('EOF')
            break
        else:
            node = c_parser.ParseCommandLine()

            # TODO: Need an error for an empty command, which we ignore?  GetLine
            # could do that in the first position?
            # ParseSimpleCommand fails with '\n' token?
            if not node:
                # TODO: PrintError here
                raise RuntimeError('failed parse: %s' % c_parser.Error())

            if ast_f:
                ast.PrettyPrint(node)

            status = ex.Execute(node)

            if opts.print_status:
                print('STATUS', repr(status))

        # Reset prompt and clear memory.  TODO: If there are any function
        # definitions ANYWHERE in the node, you should not clear the underlying
        # memory.  We still need to execute those strings!
        line_reader.Reset()

        # Reset internal newline state.
        # NOTE: It would actually be correct to reinitialize all objects (except
        # Env) on every iteration.  But we know that the w_parser is the only thing
        # that needs to be reset, for now.
        w_parser.Reset()
        c_parser.Reset()
示例#2
0
def PrintAst(nodes, opts):
    if len(nodes) == 1:
        node = nodes[0]
    else:
        node = ast.CommandList(nodes)

    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')
示例#3
0
def main(argv):
  # type: (List[str]) -> int
  arena = alloc.Arena()
  arena.PushSource(source.Stdin(''))

  loader = pyutil.GetResourceLoader()
  oil_grammar = meta.LoadOilGrammar(loader)

  parse_ctx = None
  e_parser = expr_parse.ExprParser(parse_ctx, oil_grammar)

  line_lexer = lexer.LineLexer('', arena)
  line_reader = reader.FileLineReader(sys.stdin, arena)
  lex = lexer.Lexer(line_lexer, line_reader)

  try:
    pnode, _ = e_parser.Parse(lex, grammar_nt.command_expr)
  except error.Parse as e:
    ui.PrettyPrintError(e, arena)
    return 2

  #print(pnode)
  tr = expr_to_ast.Transformer(oil_grammar)
  node = tr.Expr(pnode)

  assert node is not None

  tree = node.AbbreviatedTree()
  #tree = node.PrettyTree()

  ast_f = fmt.DetectConsoleOutput(sys.stdout)
  fmt.PrintTree(tree, ast_f)
  ast_f.write('\n')

  return 0
示例#4
0
def t_parse(
        s,  # type: str
        expected=None,  # type: Optional[str]
):
    # type: (...) -> arith_expr_t
    p = typed_arith_parse.MakeParser(s)
    tree = p.Parse()

    print()
    print('---')
    print()

    print(s)
    print()
    print(tree)

    import sys
    from asdl import format as fmt

    ast_f = fmt.DetectConsoleOutput(sys.stdout)
    p_node = tree.AbbreviatedTree()
    fmt.PrintTree(p_node, ast_f)

    #v = PrettyPrinter()
    #v.Visit(tree)

    #print('%-40s %s' % (s, sexpr))
    return tree
示例#5
0
文件: ui.py 项目: mrshu/oil
def PrintAst(nodes, opts):
  # type: (List[command_t], Any) -> None
  if len(nodes) == 1:
    node = nodes[0]
  else:
    node = command.CommandList(nodes)

  if opts.ast_format == 'none':
    print('AST not printed.', file=sys.stderr)

  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

    if 'abbrev-' in opts.ast_format:
      tree = node.AbbreviatedTree()
    else:
      tree = node.PrettyTree()

    ast_f.FileHeader()
    fmt.PrintTree(tree, ast_f)
    ast_f.FileFooter()
    ast_f.write('\n')
示例#6
0
def main(argv):
  # type: (List[str]) -> int
  arena = alloc.Arena()
  arena.PushSource(source.Stdin(''))

  parse_opts = parse_lib.OilParseOptions()
  # Dummy value; not respecting aliases!
  aliases = {}  # type: Dict[str, Any]
  # parse `` and a[x+1]=bar differently

  loader = pyutil.GetResourceLoader()
  oil_grammar = meta.LoadOilGrammar(loader)

  parse_ctx = parse_lib.ParseContext(arena, parse_opts, aliases, oil_grammar,
                                     one_pass_parse=True)

  line_reader = reader.FileLineReader(mylib.Stdin(), arena)
  c_parser = parse_ctx.MakeOshParser(line_reader)

  try:
    node = main_loop.ParseWholeFile(c_parser)
  except util.ParseError as e:
    ui.PrettyPrintError(e, arena)
    return 2
  assert node is not None

  tree = node.AbbreviatedTree()
  #tree = node.PrettyTree()

  ast_f = fmt.DetectConsoleOutput(mylib.Stdout())
  fmt.PrintTree(tree, ast_f)
  ast_f.write('\n')

  return 0
示例#7
0
def PrintAst(node, flag):
    # type: (command_t, arg_types.main) -> None

    if flag.ast_format == 'none':
        stderr_line('AST not printed.')
        if 0:
            from _devbuild.gen.id_kind_asdl import Id_str
            from frontend.lexer import ID_HIST
            for id_, count in ID_HIST.most_common(10):
                print('%8d %s' % (count, Id_str(id_)))
            print()
            total = sum(ID_HIST.values())
            print('%8d total tokens returned' % total)

    else:  # text output
        f = mylib.Stdout()

        afmt = flag.ast_format  # note: mycpp rewrite to avoid 'in'
        if afmt in ('text', 'abbrev-text'):
            ast_f = fmt.DetectConsoleOutput(f)
        elif afmt in ('html', 'abbrev-html'):
            ast_f = fmt.HtmlOutput(f)
        else:
            raise AssertionError()

        if 'abbrev-' in afmt:
            tree = node.AbbreviatedTree()
        else:
            tree = node.PrettyTree()

        ast_f.FileHeader()
        fmt.PrintTree(tree, ast_f)
        ast_f.FileFooter()
        ast_f.write('\n')
示例#8
0
def main(argv):
    # type: (List[str]) -> int
    pool = alloc.Pool()
    arena = pool.NewArena()
    arena.PushSource('<stdin>')

    line_reader = reader.FileLineReader(sys.stdin, arena)
    # Dummy value; not respecting aliases!
    aliases = {}  # type: Dict[str, Any]
    # parse `` and a[x+1]=bar differently
    parse_ctx = parse_lib.ParseContext(arena, aliases, one_pass_parse=True)
    c_parser = parse_ctx.MakeOshParser(line_reader)

    try:
        node = main_loop.ParseWholeFile(c_parser)
    except util.ParseError as e:
        ui.PrettyPrintError(e, arena)
        return 2
    assert node is not None

    tree = node.AbbreviatedTree()
    #tree = node.PrettyTree()

    ast_f = fmt.DetectConsoleOutput(sys.stdout)
    fmt.PrintTree(tree, ast_f)
    ast_f.write('\n')

    return 0
示例#9
0
def PrintAst(nodes, opts):
    if len(nodes) == 1:
        node = nodes[0]
    else:
        node = command.CommandList(nodes)

    if opts.ast_format == 'none':
        print('AST not printed.', file=sys.stderr)

    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')
示例#10
0
def main(argv):
  try:
    action = argv[1]
  except IndexError:
    raise RuntimeError('Action required')

  if action == 'py':  # Prints the module
    # Called by asdl/run.sh py-cpp

    schema_path = argv[2]
    app_types = {'id': asdl.UserType('id_kind_asdl', 'Id_t')}
    with open(schema_path) as f:
      schema_ast, type_lookup = front_end.LoadSchema(f, app_types)

    root = sys.modules[__name__]
    # NOTE: We shouldn't pass in app_types for arith.asdl, but this is just a
    # demo.
    py_meta.MakeTypes(schema_ast, root, type_lookup)

    log('AST for this ASDL schema:')
    schema_ast.Print(sys.stdout, 0)
    print()

    log('Dynamically created a Python module with these types:')
    for name in dir(root):
      print('\t' + name)

    if 1:
      # NOTE: It can be pickled, but not marshaled
      import marshal
      import cPickle
      print(dir(marshal))
      out_path = schema_path + '.pickle'
      with open(out_path, 'w') as f:
        #marshal.dump(type_lookup, f)
        # Version 2 is the highest protocol for Python 2.7.
        cPickle.dump(type_lookup.runtime_type_lookup, f, protocol=2)

      print('runtime_type_lookup:')
      for name, desc in type_lookup.runtime_type_lookup.items():
        print(name)
        print(desc)
      print()
      print('Wrote %s' % out_path)

  elif action == 'arith-format':  # pretty printing
    expr = argv[2]

    obj = typed_arith_parse.ParseShell(expr)
    tree = obj.PrettyTree()
    #treee= ['hi', 'there', ['a', 'b'], 'c']
    f = fmt.DetectConsoleOutput(sys.stdout)
    fmt.PrintTree(tree, f)
    print()

    # Might need to print the output?
    # out.WriteToFile?

  else:
    raise RuntimeError('Invalid action %r' % action)
示例#11
0
def main(argv):
  try:
    action = argv[1]
  except IndexError:
    raise RuntimeError('Action required')

  if action == 'py':  # Prints the module
    schema_path = argv[2]

    with open(schema_path) as f:
      module = asdl.parse(f)

    app_types = {'id': asdl.UserType(Id)}
    type_lookup = asdl.ResolveTypes(module, app_types)

    # Note this is a big tree.  But we really want a graph of pointers to
    # instances.
    # Type(name, Product(...))
    # Type(name, Sum([Constructor(...), ...]))
    #print(module)

    root = sys.modules[__name__]
    # NOTE: We shouldn't pass in app_types for arith.asdl, but this is just a
    # demo.
    py_meta.MakeTypes(module, root, type_lookup)

    print('Dynamically created a Python module with these types:')
    for name in dir(root):
      print('\t' + name)

  elif action == 'arith-encode':  # oheap encoding
    expr = argv[2]
    out_path = argv[3]

    obj = arith_parse.ParseShell(expr)
    print('Encoding %r into binary:' % expr)
    print(obj)

    enc = encode.Params()
    with open(out_path, 'wb') as f:
      out = encode.BinOutput(f)
      encode.EncodeRoot(obj, enc, out)

  elif action == 'arith-format':  # pretty printing
    expr = argv[2]

    obj = arith_parse.ParseShell(expr)
    #out = fmt.TextOutput(sys.stdout)
    tree = fmt.MakeTree(obj)
    #treee= ['hi', 'there', ['a', 'b'], 'c']
    f = fmt.DetectConsoleOutput(sys.stdout)
    fmt.PrintTree(tree, f)
    print()

    # Might need to print the output?
    # out.WriteToFile?

  else:
    raise RuntimeError('Invalid action %r' % action)
示例#12
0
文件: runtime.py 项目: mrshu/oil
    def PrettyPrint(self, f=sys.stdout):
        # type: (IO[str]) -> None
        """Print abbreviated tree in color, for debugging."""
        from asdl import format as fmt

        ast_f = fmt.DetectConsoleOutput(f)
        tree = self.AbbreviatedTree()
        fmt.PrintTree(tree, ast_f)
示例#13
0
文件: pybase.py 项目: tekknolagi/oil
    def PrettyPrint(self, f=None):
        # type: (Optional[mylib.Writer]) -> None
        """Print abbreviated tree in color, for debugging."""
        from asdl import format as fmt
        f = f if f else mylib.Stdout()

        ast_f = fmt.DetectConsoleOutput(f)
        tree = self.AbbreviatedTree()
        fmt.PrintTree(tree, ast_f)
示例#14
0
def InteractiveLoop(opts, ex, c_parser, w_parser, line_reader):
    if opts.show_ast:
        ast_f = fmt.DetectConsoleOutput(sys.stdout)
    else:
        ast_f = None

    status = 0
    while True:
        try:
            w = c_parser.Peek()
        except KeyboardInterrupt:
            print('Ctrl-C')
            break

        if w is None:
            raise RuntimeError('Failed parse: %s' % c_parser.Error())
        c_id = word.CommandId(w)
        if c_id == Id.Op_Newline:
            print('nothing to execute')
        elif c_id == Id.Eof_Real:
            print('EOF')
            break
        else:
            node = c_parser.ParseCommandLine()

            # TODO: Need an error for an empty command, which we ignore?  GetLine
            # could do that in the first position?
            # ParseSimpleCommand fails with '\n' token?
            if not node:
                # TODO: PrintError here
                raise RuntimeError('failed parse: %s' % c_parser.Error())

            if ast_f:
                ast_lib.PrettyPrint(node)

            status, is_control_flow = ex.ExecuteAndCatch(node)
            if is_control_flow:  # exit or return
                break

            if opts.print_status:
                print('STATUS', repr(status))

        # Reset prompt to PS1.
        line_reader.Reset()

        # Reset internal newline state.
        # NOTE: It would actually be correct to reinitialize all objects (except
        # Env) on every iteration.  But we know that the w_parser is the only thing
        # that needs to be reset, for now.
        w_parser.Reset()
        c_parser.Reset()

    return status
示例#15
0
  def PrintAst(nodes, opts):
    # type: (List[command_t], Any) -> None
    if len(nodes) == 1:
      node = nodes[0]
    else:
      node = command.CommandList(nodes)

    if opts.ast_format == 'none':
      print('AST not printed.', file=sys.stderr)
      if 0:
        from _devbuild.gen.id_kind_asdl import Id_str
        from frontend.lexer import ID_HIST
        for id_, count in ID_HIST.most_common(10):
          print('%8d %s' % (count, Id_str(id_)))
        print()
        total = sum(ID_HIST.values())
        print('%8d total tokens returned' % total)

    else:  # text output
      f = mylib.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()

      if 'abbrev-' in opts.ast_format:
        tree = node.AbbreviatedTree()
      else:
        tree = node.PrettyTree()

      ast_f.FileHeader()
      fmt.PrintTree(tree, ast_f)
      ast_f.FileFooter()
      ast_f.write('\n')
示例#16
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
示例#17
0
def main(argv):
    # type: (List[str]) -> int
    arena = alloc.Arena()

    opt_array = [False] * option_i.ARRAY_SIZE
    parse_opts = optview.Parse(opt_array)
    # Dummy value; not respecting aliases!
    aliases = {}  # type: Dict[str, str]
    # parse `` and a[x+1]=bar differently

    oil_grammar = None  # type: Grammar
    if mylib.PYTHON:
        loader = pyutil.GetResourceLoader()
        oil_grammar = pyutil.LoadOilGrammar(loader)

    parse_ctx = parse_lib.ParseContext(arena, parse_opts, aliases, oil_grammar)

    pretty_print = True

    if len(argv) == 1:
        line_reader = reader.FileLineReader(mylib.Stdin(), arena)
        src = source.Stdin('')  # type: source_t

    elif len(argv) == 2:
        path = argv[1]
        f = mylib.open(path)
        line_reader = reader.FileLineReader(f, arena)
        src = source.MainFile(path)

    elif len(argv) == 3:
        if argv[1] == '-c':
            # This path is easier to run through GDB
            line_reader = reader.StringLineReader(argv[2], arena)
            src = source.CFlag()

        elif argv[1] == '-n':  # For benchmarking, allow osh_parse -n file.txt
            path = argv[2]
            f = mylib.open(path)
            line_reader = reader.FileLineReader(f, arena)
            src = source.MainFile(path)
            # This is like --ast-format none, which benchmarks/osh-helper.sh passes.
            pretty_print = False

        else:
            raise AssertionError()

    else:
        raise AssertionError()

    arena.PushSource(src)

    c_parser = parse_ctx.MakeOshParser(line_reader)

    try:
        #node = main_loop.ParseWholeFile(c_parser)
        node = ParseWholeFile(c_parser)
    except error.Parse as e:
        ui.PrettyPrintError(e, arena)
        return 2
    assert node is not None

    # C++ doesn't have the abbreviations yet (though there are some differences
    # like omitting spids)
    #tree = node.AbbreviatedTree()
    if pretty_print:
        tree = node.PrettyTree()

        ast_f = fmt.DetectConsoleOutput(mylib.Stdout())
        fmt.PrintTree(tree, ast_f)
        ast_f.write('\n')

    return 0
示例#18
0
def _PrettyPrint(n):
    """Prints in color."""
    ast_f = fmt.DetectConsoleOutput(sys.stdout)
    tree = n.PrettyTree()
    fmt.PrintTree(tree, ast_f)
示例#19
0
文件: braces_test.py 项目: bsa3/oil
def _PrettyPrint(n):
  from asdl import format as fmt
  ast_f = fmt.DetectConsoleOutput(sys.stdout)
  tree = fmt.MakeTree(n)
  fmt.PrintTree(tree, ast_f)
示例#20
0
def main(argv):
  # type: (List[str]) -> int
  arena = alloc.Arena()

  dollar0 = argv[0]
  debug_stack = []  # type: List[state.DebugFrame]

  argv = argv[1:]  # remove binary name
  i, flag_a, flag_c, flag_n = Parse(argv)
  argv = argv[i:]  # truncate

  mem = state.Mem(dollar0, argv, arena, debug_stack)

  # TODO: look at extern char** environ;

  environ = {}  # type: Dict[str, str]
  environ['PWD'] = posix.getcwd()
  state.InitMem(mem, environ, 'VERSION')

  opt_hook = state.OptHook()
  parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, opt_hook)
  # Dummy value; not respecting aliases!
  aliases = {}  # type: Dict[str, str]
  # parse `` and a[x+1]=bar differently

  oil_grammar = None  # type: Grammar
  if mylib.PYTHON:
    loader = pyutil.GetResourceLoader()
    oil_grammar = meta.LoadOilGrammar(loader)

  parse_ctx = parse_lib.ParseContext(arena, parse_opts, aliases, oil_grammar)

  if flag_c:
    # This path is easier to run through GDB
    line_reader = reader.StringLineReader(flag_c, arena)
    src = source.CFlag()  # type: source_t

  elif len(argv) == 0:
    line_reader = reader.FileLineReader(mylib.Stdin(), arena)
    src = source.Stdin('')

  elif len(argv) == 1:
    path = argv[0]
    f = mylib.open(path)
    line_reader = reader.FileLineReader(f, arena)
    src = source.MainFile(path)

  else:
    raise AssertionError(argv)

  arena.PushSource(src)
  c_parser = parse_ctx.MakeOshParser(line_reader)

  # C++ doesn't have the abbreviations yet (though there are some differences
  # like omitting spids)
  #tree = node.AbbreviatedTree()
  if flag_n:
    try:
      node = main_loop.ParseWholeFile(c_parser)
    except error.Parse as e:
      ui.PrettyPrintError(e, arena)
      return 2
    assert node is not None

    if flag_a:
      tree = node.PrettyTree()

      ast_f = fmt.DetectConsoleOutput(mylib.Stdout())
      fmt.PrintTree(tree, ast_f)
      ast_f.write('\n')
    return 0

  # New osh_eval.py instantiations

  errfmt = ui.ErrorFormatter(arena)

  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)
  word_ev = word_eval.NormalWordEvaluator(mem, exec_opts, splitter, errfmt)
  prompt_ev = prompt.Evaluator('osh', parse_ctx, mem)

  arith_ev.word_ev = word_ev
  word_ev.arith_ev = arith_ev
  word_ev.prompt_ev = prompt_ev

  prompt_ev.word_ev = word_ev

  procs = {}  # type: Dict[str, command__ShFunction]

  assign_builtins = {}  # type: Dict[int, _AssignBuiltin]

  new_var = builtin_assign.NewVar(mem, procs, errfmt)
  assign_builtins[builtin_i.declare] = new_var
  assign_builtins[builtin_i.typeset] = new_var
  assign_builtins[builtin_i.local] = new_var
  assign_builtins[builtin_i.export_] = builtin_assign.Export(mem, errfmt)
  assign_builtins[builtin_i.readonly] = builtin_assign.Readonly(mem, errfmt)

  #assign_builtins = {
  #    # ShAssignment (which are pure)
  #    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),
  #}

  cmd_deps = cmd_eval.Deps()
  cmd_deps.mutable_opts = mutable_opts
  cmd_deps.traps = {}
  cmd_deps.trap_nodes = []  # TODO: Clear on fork() to avoid duplicates

  cmd_deps.dumper = dev.CrashDumper('')

  search_path = state.SearchPath(mem)

  builtins = {}  # type: Dict[int, vm._Builtin]
  builtins[builtin_i.echo] = builtin_pure.Echo(exec_opts)

  builtins[builtin_i.set] = Set(mutable_opts)  # DUMMY until ParseMore()
  if mylib.PYTHON:
    # Use the real one
    builtins[builtin_i.set] = builtin_pure.Set(mutable_opts, mem)

  builtins[builtin_i.shopt] = builtin_pure.Shopt(mutable_opts)
  builtins[builtin_i.alias] = builtin_pure.Alias(aliases, errfmt)
  builtins[builtin_i.unalias] = builtin_pure.UnAlias(aliases, errfmt)

  builtins[builtin_i.hash] = builtin_pure.Hash(search_path)
  builtins[builtin_i.getopts] = builtin_pure.GetOpts(mem, errfmt)

  builtins[builtin_i.shift] = builtin_assign.Shift(mem)
  builtins[builtin_i.unset] = builtin_assign.Unset(
      mem, exec_opts, procs, parse_ctx, arith_ev, errfmt)

  true_ = builtin_pure.Boolean(0)
  builtins[builtin_i.colon] = true_  # a "special" builtin 
  builtins[builtin_i.true_] = true_
  builtins[builtin_i.false_] = builtin_pure.Boolean(1)

  # builtin_meta
  builtins[builtin_i.type] = builtin_meta.Type(procs, aliases, search_path, errfmt)

  shell_ex = NullExecutor(exec_opts, mutable_opts, procs, builtins)

  trace_f = util.DebugFile(mylib.Stderr())
  tracer = dev.Tracer(parse_ctx, exec_opts, mutable_opts, mem, word_ev, trace_f)

  cmd_ev = cmd_eval.CommandEvaluator(mem, exec_opts, errfmt, procs,
                                     assign_builtins, arena, cmd_deps)

  # TODO: can't instantiate this yet
  #fd_state = None

  # needs cmd_ev
  builtins[builtin_i.eval] = builtin_meta.Eval(parse_ctx, exec_opts, cmd_ev)
  #source_builtin = builtin_meta.Source(
  #    parse_ctx, search_path, cmd_ev, fd_state, errfmt)
  #builtins[builtin_i.source] = source_builtin
  #builtins[builtin_i.dot] = source_builtin

  builtins[builtin_i.builtin] = builtin_meta.Builtin(shell_ex, errfmt)
  builtins[builtin_i.command] = builtin_meta.Command(shell_ex, procs, aliases,
                                                     search_path)

  builtins[builtin_i.printf] = builtin_printf.Printf(mem, parse_ctx, errfmt)

  builtins[builtin_i.test] = builtin_bracket.Test(False, exec_opts, mem, errfmt)
  builtins[builtin_i.bracket] = builtin_bracket.Test(True, exec_opts, mem, errfmt)

  dir_stack = state.DirStack()
  builtins[builtin_i.pushd] = builtin_misc.Pushd(mem, dir_stack, errfmt)
  builtins[builtin_i.popd] = builtin_misc.Popd(mem, dir_stack, errfmt)
  builtins[builtin_i.dirs] = builtin_misc.Dirs(mem, dir_stack, errfmt)
  builtins[builtin_i.pwd] = builtin_misc.Pwd(mem, errfmt)

  builtins[builtin_i.times] = builtin_misc.Times()
  builtins[builtin_i.read] = builtin_misc.Read(splitter, mem)

  builtins[builtin_i.cat] = builtin_misc.Cat()  # for $(<file)
  builtins[builtin_i.cd] = builtin_misc.Cd(mem, dir_stack, cmd_ev, errfmt)

  # vm.InitCircularDeps
  cmd_ev.arith_ev = arith_ev
  cmd_ev.bool_ev = bool_ev
  cmd_ev.word_ev = word_ev
  cmd_ev.tracer = tracer
  cmd_ev.shell_ex = shell_ex

  shell_ex.cmd_ev = cmd_ev

  bool_ev.word_ev = word_ev

  try:
    status = main_loop.Batch(cmd_ev, c_parser, arena,
                             cmd_flags=cmd_eval.IsMainProgram)
  except util.UserExit as e:
    # TODO: fix this
    #status = e.status
    status = 1
  return status
示例#21
0
文件: ast_lib.py 项目: bsa3/oil
def PrettyPrint(node, f=sys.stdout):
    ast_f = fmt.DetectConsoleOutput(f)
    tree = fmt.MakeTree(node, AbbreviateNodes)
    fmt.PrintTree(tree, ast_f)
    f.write('\n')
示例#22
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
示例#23
0
def main(argv):
    # type: (List[str]) -> int
    arena = alloc.Arena()

    dollar0 = argv[0]
    debug_stack = []  # type: List[state.DebugFrame]
    mem = state.Mem(dollar0, argv, arena, debug_stack)
    parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, None)
    # Dummy value; not respecting aliases!
    aliases = {}  # type: Dict[str, str]
    # parse `` and a[x+1]=bar differently

    oil_grammar = None  # type: Grammar
    if mylib.PYTHON:
        loader = pyutil.GetResourceLoader()
        oil_grammar = meta.LoadOilGrammar(loader)

    parse_ctx = parse_lib.ParseContext(arena, parse_opts, aliases, oil_grammar)

    pretty_print = True

    if len(argv) == 1:
        line_reader = reader.FileLineReader(mylib.Stdin(), arena)
        src = source.Stdin('')  # type: source_t

    elif len(argv) == 2:
        path = argv[1]
        f = mylib.open(path)
        line_reader = reader.FileLineReader(f, arena)
        src = source.MainFile(path)

    elif len(argv) == 3:
        if argv[1] == '-c':
            # This path is easier to run through GDB
            line_reader = reader.StringLineReader(argv[2], arena)
            src = source.CFlag()

        elif argv[1] == '-n':  # For benchmarking, allow osh_parse -n file.txt
            path = argv[2]
            f = mylib.open(path)
            line_reader = reader.FileLineReader(f, arena)
            src = source.MainFile(path)
            # This is like --ast-format none, which benchmarks/osh-helper.sh passes.
            pretty_print = False

        else:
            raise AssertionError()

    else:
        raise AssertionError()

    arena.PushSource(src)

    c_parser = parse_ctx.MakeOshParser(line_reader)

    try:
        #node = main_loop.ParseWholeFile(c_parser)
        node = ParseWholeFile(c_parser)
    except error.Parse as e:
        ui.PrettyPrintError(e, arena)
        return 2
    assert node is not None

    # C++ doesn't have the abbreviations yet (though there are some differences
    # like omitting spids)
    #tree = node.AbbreviatedTree()
    if 0:
        tree = node.PrettyTree()

        ast_f = fmt.DetectConsoleOutput(mylib.Stdout())
        fmt.PrintTree(tree, ast_f)
        ast_f.write('\n')

    # New osh_eval.py instantiations

    errfmt = ui.ErrorFormatter(arena)

    splitter = split.SplitContext(mem)
    arith_ev = sh_expr_eval.ArithEvaluator(mem, exec_opts, errfmt)
    word_ev = word_eval.NormalWordEvaluator(mem, exec_opts, splitter, errfmt)

    arith_ev.word_ev = word_ev
    word_ev.arith_ev = arith_ev

    test_ev = TestEvaluator(arith_ev, word_ev)
    test_ev.Eval(node)

    return 0
示例#24
0
def OshMain(argv):
    (opts, argv) = Options().parse_args(argv)

    state = util.TraceState()
    if 'cp' in opts.trace:
        util.WrapMethods(cmd_parse.CommandParser, state)
    if 'wp' in opts.trace:
        util.WrapMethods(word_parse.WordParser, state)
    if 'lexer' in opts.trace:
        util.WrapMethods(lexer.Lexer, state)

    if len(argv) == 0:
        dollar0 = sys.argv[0]  # e.g. bin/osh
    else:
        dollar0 = argv[0]  # the script name

    # 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 = Pool()
    arena = pool.NewArena()

    # TODO: Maybe wrap this initialization sequence up in an oil_State, like
    # lua_State.
    status_lines = ui.MakeStatusLines()
    mem = cmd_exec.Mem(dollar0, argv[1:])
    builtins = builtin.Builtins(status_lines[0])
    funcs = {}

    # Passed to Executor for 'complete', and passed to completion.Init
    comp_lookup = completion.CompletionLookup()
    exec_opts = cmd_exec.ExecOpts()

    # 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, builtins, funcs, comp_lookup, exec_opts,
                           parse_lib.MakeParserForExecutor)

    # 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'
        with open(rc_path) as f:
            contents = f.read()
        arena.AddSourcePath(rc_path)
        #print(repr(contents))

        rc_line_reader = reader.StringLineReader(contents, arena=arena)
        _, rc_c_parser = parse_lib.MakeParserForTop(rc_line_reader)
        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.PrintError(err, arena, sys.stderr)
            return 2  # parse error is code 2

        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.command is not None:
        arena.AddSourcePath('<-c arg>')
        line_reader = reader.StringLineReader(opts.command, arena=arena)
        interactive = False
    elif opts.interactive:  # force interactive
        arena.AddSourcePath('<stdin -i>')
        line_reader = reader.InteractiveLineReader(OSH_PS1, arena=arena)
        interactive = True
    else:
        try:
            script_name = argv[0]
        except IndexError:
            if sys.stdin.isatty():
                arena.AddSourcePath('<interactive>')
                line_reader = reader.InteractiveLineReader(OSH_PS1,
                                                           arena=arena)
                interactive = True
            else:
                arena.AddSourcePath('<stdin>')
                line_reader = reader.StringLineReader(sys.stdin.read(),
                                                      arena=arena)
                interactive = False
        else:
            arena.AddSourcePath(script_name)
            with open(script_name) as f:
                line_reader = reader.StringLineReader(f.read(), arena=arena)
            interactive = False

    # TODO: assert arena.NumSourcePaths() == 1
    # TODO: .rc file needs its own arena.
    w_parser, c_parser = parse_lib.MakeParserForTop(line_reader, arena=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.
        ev = word_eval.CompletionWordEvaluator(mem, exec_opts)
        completion.Init(builtins, mem, funcs, comp_lookup, status_lines, 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')

        # TODO: Do I need ParseAndEvalLoop?  How is it different than
        # InteractiveLoop?
        node = c_parser.ParseWholeFile()
        if not node:
            err = c_parser.Error()
            ui.PrintError(err, arena, sys.stderr)
            return 2  # parse error is code 2

        if opts.ast_output:

            if opts.ast_format == 'oheap':
                if opts.ast_output == '-':
                    if sys.stdout.isatty():
                        raise RuntimeError(
                            'ERROR: Not dumping binary data to a TTY.')
                    f = sys.stdout
                else:
                    f = open(opts.ast_output, 'wb')  # implicitly closed

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

            else:  # text output
                if opts.ast_output == '-':
                    f = sys.stdout
                else:
                    f = open(opts.ast_output, 'w')  # implicitly closed

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

        if opts.do_exec:
            status = ex.Execute(node)
        else:
            util.log('Execution skipped because --no-exec was passed')
            status = 0

    if opts.fix:
        fix.PrintAsOil(arena, node, opts.debug_spans)
    return status
示例#25
0
def main(argv):
  # type: (List[str]) -> int
  arena = alloc.Arena()

  dollar0 = argv[0]
  debug_stack = []  # type: List[state.DebugFrame]
  mem = state.Mem(dollar0, argv, arena, debug_stack)
  opt_hook = state.OptHook()
  parse_opts, exec_opts, mutable_opts = state.MakeOpts(mem, opt_hook)
  # Dummy value; not respecting aliases!
  aliases = {}  # type: Dict[str, str]
  # parse `` and a[x+1]=bar differently

  state.SetGlobalString(mem, 'SHELLOPTS', '')

  oil_grammar = None  # type: Grammar
  if mylib.PYTHON:
    loader = pyutil.GetResourceLoader()
    oil_grammar = meta.LoadOilGrammar(loader)

  parse_ctx = parse_lib.ParseContext(arena, parse_opts, aliases, oil_grammar)

  argv = argv[1:]  # remove binary name
  i, flag_a, flag_c, flag_n = Parse(argv)

  argv = argv[i:]  # truncate

  if flag_c:
    # This path is easier to run through GDB
    line_reader = reader.StringLineReader(flag_c, arena)
    src = source.CFlag()  # type: source_t

  elif len(argv) == 0:
    line_reader = reader.FileLineReader(mylib.Stdin(), arena)
    src = source.Stdin('')

  elif len(argv) == 1:
    path = argv[0]
    f = mylib.open(path)
    line_reader = reader.FileLineReader(f, arena)
    src = source.MainFile(path)

  else:
    raise AssertionError(argv)

  arena.PushSource(src)
  c_parser = parse_ctx.MakeOshParser(line_reader)

  # C++ doesn't have the abbreviations yet (though there are some differences
  # like omitting spids)
  #tree = node.AbbreviatedTree()
  if flag_n:
    try:
      node = main_loop.ParseWholeFile(c_parser)
    except error.Parse as e:
      ui.PrettyPrintError(e, arena)
      return 2
    assert node is not None

    if flag_a:
      tree = node.PrettyTree()

      ast_f = fmt.DetectConsoleOutput(mylib.Stdout())
      fmt.PrintTree(tree, ast_f)
      ast_f.write('\n')
    return 0

  # New osh_eval.py instantiations

  errfmt = ui.ErrorFormatter(arena)

  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)
  word_ev = word_eval.NormalWordEvaluator(mem, exec_opts, splitter, errfmt)

  arith_ev.word_ev = word_ev
  word_ev.arith_ev = arith_ev

  procs = {}  # type: Dict[str, command__ShFunction]

  assign_builtins = {}  # type: Dict[int, _AssignBuiltin]

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

  #assign_builtins = {
  #    # ShAssignment (which are pure)
  #    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),
  #}

  cmd_deps = cmd_eval.Deps()
  cmd_deps.mutable_opts = mutable_opts
  cmd_deps.traps = {}
  cmd_deps.trap_nodes = []  # TODO: Clear on fork() to avoid duplicates

  cmd_deps.dumper = dev.CrashDumper('')

  builtins = {}  # type: Dict[int, _Builtin]
  builtins[builtin_i.echo] = Echo()
  builtins[builtin_i.shopt] = Shopt(mutable_opts)
  builtins[builtin_i.set] = Set(mutable_opts)
  ex = NullExecutor(builtins)

  trace_f = util.DebugFile(mylib.Stderr())
  tracer = dev.Tracer(parse_ctx, exec_opts, mutable_opts, mem, word_ev, trace_f)

  cmd_ev = cmd_eval.CommandEvaluator(mem, exec_opts, errfmt, procs,
                                     assign_builtins, arena, cmd_deps)

  # vm.InitCircularDeps
  cmd_ev.arith_ev = arith_ev
  cmd_ev.bool_ev = bool_ev
  cmd_ev.word_ev = word_ev
  cmd_ev.tracer = tracer
  cmd_ev.shell_ex = ex

  bool_ev.word_ev = word_ev

  status = main_loop.Batch(cmd_ev, c_parser, arena, is_main=True)
  return status