func (e variableExpr) Eval(context value.Context) value.Value { v := context.Lookup(e.name) if v == nil { value.Errorf("undefined variable %q", e.name) } return v }
// run runs until EOF or error. The return value says whether we completed without error. func run(p *parse.Parser, writer io.Writer, context value.Context, interactive bool) (success bool) { defer func() { if conf.Debug("panic") { return } err := recover() if err == nil { return } p.FlushToNewline() if err, ok := err.(value.Error); ok { fmt.Fprintf(os.Stderr, "%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 { values = context.Eval(exprs) } if values != nil { if conf.Debug("types") { for i, v := range values { if i > 0 { fmt.Fprint(writer, ",") } fmt.Fprintf(writer, "%T", v) } fmt.Fprintln(writer) } for i, v := range values { s := v.String() if i > 0 && len(s) > 0 && s[len(s)-1] != '\n' { fmt.Fprint(writer, " ") } fmt.Fprint(writer, v) } fmt.Fprintln(writer) context.Assign("_", values[len(values)-1]) } if !ok { return true } if interactive { fmt.Fprintln(writer) } } }
func (b *binary) Eval(context value.Context) value.Value { rhs := b.right.Eval(context) if b.op == "=" { // Special handling as we cannot evaluate the left. // We know the left is a variableExpr. lhs := b.left.(variableExpr) context.Assign(lhs.name, rhs) return Assignment{Value: rhs} } lhs := b.left.Eval(context) return context.EvalBinary(lhs, b.op, rhs) }
// run runs until EOF or error. The return value says whether we completed without error. func run(p *parse.Parser, context value.Context, interactive bool) (success bool) { 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(os.Stderr, "%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 { values = context.Eval(exprs) } if values != nil { printValues(writer, values) context.Assign("_", values[len(values)-1]) } if !ok { return true } if interactive { fmt.Fprintln(writer) } } }
// 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 { 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(writer, prevValues[:len(prevValues)-1]) return prevValues[len(prevValues)-1] } printValues(writer, prevValues) prevValues = values } }
// 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 } } }
func (b *binaryCall) Eval(context value.Context) value.Value { left := b.left.Eval(context) right := b.right.Eval(context) context.Push() defer context.Pop() exec := context.(*execContext) // Sigh. fn := exec.binaryFn[b.name] if fn == nil || fn.body == nil { value.Errorf("binary %q undefined", b.name) } context.AssignLocal(fn.left.name, left) context.AssignLocal(fn.right.name, right) var v value.Value for _, e := range fn.body { v = e.Eval(context) } if v == nil { value.Errorf("no value returned by %q", b.name) } return v }
func (u *unaryCall) Eval(context value.Context) value.Value { arg := u.arg.Eval(context) context.Push() defer context.Pop() exec := context.(*execContext) // Sigh. fn := exec.unaryFn[u.name] if fn == nil || fn.body == nil { value.Errorf("unary %q undefined", u.name) } context.AssignLocal(fn.right.name, arg) var v value.Value for _, e := range fn.body { v = e.Eval(context) } if v == nil { value.Errorf("no value returned by %q", u.name) } return v }
func (u *unary) Eval(context value.Context) value.Value { return context.EvalUnary(u.op, u.right.Eval(context)) }
func (a *assignment) Eval(context value.Context) value.Value { context.Assign(a.variable.name, a.expr.Eval(context)) return nil }
func (b *binary) Eval(context value.Context) value.Value { return context.EvalBinary(b.left.Eval(context), b.op, b.right.Eval(context)) }