// Run runs the parser/evaluator until EOF or error. // The return value says whether we completed without error. If the return // value is true, it means we ran out of data (EOF) and the run was successful. // Typical execution is therefore to loop calling Run until it succeeds. // Error details are reported to the configured error output stream. func Run(p *parse.Parser, context value.Context, interactive bool) (success bool) { conf := context.Config() writer := conf.Output() defer func() { if conf.Debug("panic") { return } err := recover() if err == nil { return } p.FlushToNewline() if err, ok := err.(value.Error); ok { fmt.Fprintf(conf.ErrOutput(), "%s%s\n", p.Loc(), err) if interactive { fmt.Fprintln(writer) } success = false return } panic(err) }() for { if interactive { fmt.Fprint(writer, conf.Prompt()) } exprs, ok := p.Line() var values []value.Value if exprs != nil { if interactive { start := time.Now() values = context.Eval(exprs) conf.SetCPUTime(time.Now().Sub(start)) } else { values = context.Eval(exprs) } } if printValues(conf, writer, values) { context.Assign("_", values[len(values)-1]) } if !ok { return true } if interactive { if exprs != nil && conf.Debug("cpu") && conf.CPUTime() != 0 { fmt.Printf("(%s)\n", conf.PrintCPUTime()) } fmt.Fprintln(writer) } } }
// runFromFile executes the contents of the named file. func (p *Parser) runFromFile(context value.Context, name string) { runDepth++ if runDepth > 10 { p.errorf("get %q nested too deep", name) } defer func() { runDepth-- err := recover() if err == nil { return } if err, ok := err.(value.Error); ok { fmt.Fprintf(p.context.Config().ErrOutput(), "%s%s\n", p.Loc(), err) return } panic(err) }() fd, err := os.Open(name) if err != nil { p.errorf("%s", err) } scanner := scan.New(context, name, bufio.NewReader(fd)) parser := NewParser(name, scanner, p.context) out := p.context.Config().Output() for { exprs, ok := parser.Line() for _, expr := range exprs { val := expr.Eval(p.context) if val == nil { continue } if _, ok := val.(Assignment); ok { continue } fmt.Fprintf(out, "%v\n", val.Sprint(context.Config())) } if !ok { return } } }
// eval runs until EOF or error. It prints every value but the last, and returns the last. // By last we mean the last expression of the last evaluation. // (Expressions are separated by ; in the input.) // It is always called from (somewhere below) run, so if it errors out the recover in // run will catch it. func eval(p *parse.Parser, context value.Context) value.Value { conf := context.Config() writer := conf.Output() var prevValues []value.Value for { exprs, ok := p.Line() var values []value.Value if exprs != nil { values = context.Eval(exprs) } if !ok { if len(prevValues) == 0 { return nil } printValues(conf, writer, prevValues[:len(prevValues)-1]) return prevValues[len(prevValues)-1] } printValues(conf, writer, prevValues) prevValues = values } }