mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
Abstract in-package panic/recover into a utility
This commit is contained in:
parent
3accfa0cb6
commit
6227008696
1
TODO.md
1
TODO.md
|
@ -16,4 +16,3 @@
|
|||
Python/Lua/... and/or error value handling a la golang)
|
||||
- Support evaluating script
|
||||
* All the TODO and XXX's in source :)
|
||||
* Some utilities to faciliate in-package panic/recover
|
||||
|
|
24
eval/eval.go
24
eval/eval.go
|
@ -40,12 +40,12 @@ func NewEvaluator(envSlice []string) *Evaluator {
|
|||
return ev
|
||||
}
|
||||
|
||||
func (ev *Evaluator) Eval(name, text string, n parse.Node) (err *util.ContextualError) {
|
||||
defer ev.recover(&err)
|
||||
func (ev *Evaluator) Eval(name, text string, n parse.Node) (err error) {
|
||||
defer util.Recover(&err)
|
||||
defer ev.stopEval()
|
||||
ev.name = name
|
||||
ev.text = text
|
||||
ev.evalChunk(n.(*parse.ListNode))
|
||||
ev.stopEval()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ func (ev *Evaluator) pop() {
|
|||
}
|
||||
|
||||
func (ev *Evaluator) errorfNode(n parse.Node, format string, args ...interface{}) {
|
||||
panic(util.NewContextualError(ev.name, ev.text, int(n.Position()), format, args...))
|
||||
util.Panic(util.NewContextualError(ev.name, ev.text, int(n.Position()), format, args...))
|
||||
}
|
||||
|
||||
// errorf stops the evaluator. Its panic is supposed to be caught by recover.
|
||||
|
@ -73,22 +73,6 @@ func (ev *Evaluator) errorf(format string, args...interface{}) {
|
|||
ev.errorfNode(ev.nodes[len(ev.nodes) - 1], format, args...)
|
||||
}
|
||||
|
||||
// recover is the handler that turns panics into returns from top level of
|
||||
// evaluation function (currently ExecPipeline).
|
||||
func (ev *Evaluator) recover(perr **util.ContextualError) {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
if _, ok := r.(*util.ContextualError); !ok {
|
||||
panic(r)
|
||||
}
|
||||
if (ev != nil) {
|
||||
ev.stopEval()
|
||||
}
|
||||
*perr = r.(*util.ContextualError)
|
||||
}
|
||||
|
||||
func (ev *Evaluator) resolveVar(name string) Value {
|
||||
val, ok := ev.globals[name]
|
||||
if !ok {
|
||||
|
|
|
@ -47,13 +47,13 @@ func main() {
|
|||
p := parse.NewParser(name)
|
||||
tree, pe := p.Parse(lr.Line, false)
|
||||
if pe != nil {
|
||||
fmt.Print(pe.Pprint())
|
||||
fmt.Print(pe.(*util.ContextualError).Pprint())
|
||||
continue
|
||||
}
|
||||
|
||||
ee := ev.Eval(name, lr.Line, tree.Root)
|
||||
if ee != nil {
|
||||
fmt.Println(ee.Pprint())
|
||||
fmt.Println(ee.(*util.ContextualError).Pprint())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ func NewParser(name string) *Parser {
|
|||
// errorf formats the error and terminates processing.
|
||||
func (p *Parser) errorf(pos int, format string, args ...interface{}) {
|
||||
p.Root = nil
|
||||
panic(util.NewContextualError(p.Name, p.text, pos, format, args...))
|
||||
util.Panic(util.NewContextualError(p.Name, p.text, pos, format, args...))
|
||||
}
|
||||
|
||||
// expect consumes the next token and guarantees it has the required type.
|
||||
|
@ -128,21 +128,6 @@ func (p *Parser) unexpected(token Item, context string) {
|
|||
p.errorf(int(token.Pos), "unexpected %s in %s", token, context)
|
||||
}
|
||||
|
||||
// recover is the handler that turns panics into returns from the top level of Parse.
|
||||
func (p *Parser) recover(errp **util.ContextualError) {
|
||||
e := recover()
|
||||
if e == nil {
|
||||
return
|
||||
}
|
||||
if _, ok := e.(*util.ContextualError); !ok {
|
||||
panic(e)
|
||||
}
|
||||
if p != nil {
|
||||
p.stopParse()
|
||||
}
|
||||
*errp = e.(*util.ContextualError)
|
||||
}
|
||||
|
||||
// stopParse terminates parsing.
|
||||
func (p *Parser) stopParse() {
|
||||
p.lex = nil
|
||||
|
@ -150,8 +135,9 @@ func (p *Parser) stopParse() {
|
|||
|
||||
// Parse parses the script to construct a representation of the script for
|
||||
// execution.
|
||||
func (p *Parser) Parse(text string, tab bool) (tree *Parser, err *util.ContextualError) {
|
||||
defer p.recover(&err)
|
||||
func (p *Parser) Parse(text string, tab bool) (tree *Parser, err error) {
|
||||
defer util.Recover(&err)
|
||||
defer p.stopParse()
|
||||
|
||||
p.text = text
|
||||
p.tab = tab
|
||||
|
|
24
util/exception.go
Normal file
24
util/exception.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package util
|
||||
|
||||
// This file provides an exception-like mechanism.
|
||||
|
||||
// An exception wraps an error.
|
||||
type exception struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func Panic(err error) {
|
||||
panic(exception{err})
|
||||
}
|
||||
|
||||
func Recover(perr *error) {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
if exc, ok := r.(exception); ok {
|
||||
*perr = exc.err
|
||||
} else {
|
||||
panic(r)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user