func (ev *Evaluator) eval(name, text string, op Op) (err error) { if op == nil { return nil } defer util.Recover(&err) defer ev.stopEval() ev.name = name ev.text = text op(ev) return nil }
// Eval evaluates a chunk node n. The name and text of it is used for // diagnostic messages. func (ev *Evaluator) Eval(name, text string, n *parse.ChunkNode) (err error) { err = ev.Checker.Check(name, text, n, ev.MakeCheckerScope()) if err != nil { return } defer util.Recover(&err) defer ev.stopEval() ev.name = name ev.text = text ev.evalChunk(n) return nil }
// Parse parses the script to construct a representation of the script for // execution. func (p *Parser) Parse(text string, completing bool) (err error) { defer util.Recover(&err) defer p.recoverCtx() defer p.stopParse() p.completing = completing p.text = text p.lex = Lex(p.Name, text) p.peekCount = 0 p.Ctx = &Context{CommandContext, nil, newTermList(0), newTerm(0), &FactorNode{Node: newString(0, "", "")}} p.Root = p.parse() return nil }
// ResolveCommand tries to find a command with the given name the stream types // it expects for three standard ports. If a command with that name doesn't // exists, err is non-nil. func (ev *Evaluator) ResolveCommand(name string) (cmd Command, streamTypes [2]StreamType, err error) { defer util.Recover(&err) cmd, streamTypes = ev.resolveCommand(name, nil) return cmd, streamTypes, nil }
func (cp *Compiler) Compile(name, text string, n *parse.ChunkNode, scope map[string]Type) (op Op, err error) { cp.startCompile(name, text, scope) defer util.Recover(&err) return cp.compileChunk(n), nil }
func (rd *Reader) readOne(r rune) (k Key, cpr pos, err error) { defer util.Recover(&err) rd.currentSeq = "" switch r { case Tab, Enter, Backspace: k = Key{r, 0} case 0x0: k = Key{'`', Ctrl} // ^@ case 0x1d: k = Key{'6', Ctrl} // ^^ case 0x1f: k = Key{'/', Ctrl} // ^_ case 0x1b: // ^[ Escape //rd.timed.Timeout = EscTimeout //defer func() { rd.timed.Timeout = -1 }() r2 := rd.readRune(EscTimeout) if r2 == RuneTimeout { return Key{'[', Ctrl}, InvalidPos, nil } switch r2 { case '[': // CSI style function key sequence, looks like [\d;]*[^\d;] // Read numeric parameters (if any) nums := make([]int, 0, 2) seq := "\x1b[" timeout := EscTimeout for { r = rd.readRune(timeout) // Timeout can only happen at first readRune. if r == RuneTimeout { return Key{'[', Alt}, InvalidPos, nil } seq += string(r) // After first rune read we turn off the timeout timeout = -1 if r != ';' && (r < '0' || r > '9') { break } if len(nums) == 0 { nums = append(nums, 0) } if r == ';' { nums = append(nums, 0) } else { cur := len(nums) - 1 nums[cur] = nums[cur]*10 + int(r-'0') } } if r == 'R' { // CPR if len(nums) != 2 { rd.badEscSeq("bad cpr") } return ZeroKey, pos{nums[0], nums[1]}, nil } else { k, err := parseCSI(nums, r, seq) return k, InvalidPos, err } case 'O': // G3 style function key sequence: read one rune. r = rd.readRune(EscTimeout) if r == RuneTimeout { return Key{r2, Alt}, InvalidPos, nil } r, ok := g3Seq[r] if ok { return Key{r, 0}, InvalidPos, nil } rd.badEscSeq("") } return Key{r2, Alt}, InvalidPos, nil default: // Sane Ctrl- sequences that agree with the keyboard... if 0x1 <= r && r <= 0x1d { k = Key{r + 0x40, Ctrl} } else { k = Key{r, 0} } } return k, InvalidPos, nil }
// ResolveVar tries to find an variable with the given name in the local and // then global context of the Evaluator. If no variable with the name exists, // err is non-nil. func (ev *Evaluator) ResolveVar(name string) (v Value, err error) { defer util.Recover(&err) return *ev.resolveVar(name), nil }
func (ch *Checker) Check(name, text string, n *parse.ChunkNode, scope map[string]Type) (err error) { ch.startCheck(name, text, scope) defer util.Recover(&err) ch.checkChunk(n) return nil }