mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-01 00:33:05 +08:00
pkg/eval: Don't use panics for propagating compilation errors.
This also enables saving multiple compilation errors.
This commit is contained in:
parent
ff0feb4311
commit
69715b05fe
|
@ -789,7 +789,7 @@ func compilePragma(cp *compiler, fn *parse.Form) effectOp {
|
|||
args := getArgs(cp, fn)
|
||||
name := args.get(0, "pragma name").stringLiteral()
|
||||
eq := args.get(1, "literal =").stringLiteral()
|
||||
if eq != "=" {
|
||||
if args.has(1) && eq != "=" {
|
||||
args.errorpf(fn.Args[1], "must be literal =")
|
||||
}
|
||||
valueNode := args.get(2, "pragma value").any()
|
||||
|
|
|
@ -38,6 +38,7 @@ func (cp *compiler) parseCompoundLValues(ns []*parse.Compound, f lvalueFlag) lva
|
|||
for _, n := range ns {
|
||||
if len(n.Indexings) != 1 {
|
||||
cp.errorpf(n, "lvalue may not be composite expressions")
|
||||
break
|
||||
}
|
||||
more := cp.parseIndexingLValue(n.Indexings[0], f)
|
||||
if more.rest == -1 {
|
||||
|
|
|
@ -28,32 +28,27 @@ type compiler struct {
|
|||
deprecations deprecationRegistry
|
||||
// Information about the source.
|
||||
srcMeta parse.Source
|
||||
// Compilation errrors.
|
||||
errors []*diag.Error
|
||||
}
|
||||
|
||||
type scopePragma struct {
|
||||
unknownCommandIsExternal bool
|
||||
}
|
||||
|
||||
func compile(b, g *staticNs, tree parse.Tree, w io.Writer) (op nsOp, err error) {
|
||||
func compile(b, g *staticNs, tree parse.Tree, w io.Writer) (nsOp, error) {
|
||||
g = g.clone()
|
||||
cp := &compiler{
|
||||
b, []*staticNs{g}, []*staticUpNs{new(staticUpNs)},
|
||||
[]*scopePragma{{unknownCommandIsExternal: true}},
|
||||
w, newDeprecationRegistry(), tree.Source}
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
} else if e := GetCompilationError(r); e != nil {
|
||||
// Save the compilation error and stop the panic.
|
||||
err = e
|
||||
} else {
|
||||
// Resume the panic; it is not supposed to be handled here.
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
w, newDeprecationRegistry(), tree.Source, nil}
|
||||
chunkOp := cp.chunkOp(tree.Root)
|
||||
return nsOp{chunkOp, g}, nil
|
||||
var err error
|
||||
if len(cp.errors) > 0 {
|
||||
// TODO: Preserve all compilation errors.
|
||||
err = cp.errors[0]
|
||||
}
|
||||
return nsOp{chunkOp, g}, err
|
||||
}
|
||||
|
||||
type nsOp struct {
|
||||
|
@ -84,8 +79,7 @@ func (op nsOp) prepare(fm *Frame) (*Ns, func() Exception) {
|
|||
const compilationErrorType = "compilation error"
|
||||
|
||||
func (cp *compiler) errorpf(r diag.Ranger, format string, args ...any) {
|
||||
// The panic is caught by the recover in compile above.
|
||||
panic(&diag.Error{
|
||||
cp.errors = append(cp.errors, &diag.Error{
|
||||
Type: compilationErrorType,
|
||||
Message: fmt.Sprintf(format, args...),
|
||||
Context: *diag.NewContext(cp.srcMeta.Name, cp.srcMeta.Code, r)})
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
go test fuzz v1
|
||||
string("{}= 0")
|
Loading…
Reference in New Issue
Block a user