From fdbaf1c8ccb21202f6cc2af838b3973977bdc977 Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Mon, 21 Oct 2024 22:00:06 +1100 Subject: [PATCH] Finished implementing try catch --- ucl/ast.go | 1 + ucl/builtins.go | 41 ++++++++++++++++++++++++++++++++++------- ucl/errors.go | 37 +++++++++++++++++++++++++++++++++++++ ucl/objs.go | 10 ++++++++++ 4 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 ucl/errors.go diff --git a/ucl/ast.go b/ucl/ast.go index fd4252d..43815d8 100644 --- a/ucl/ast.go +++ b/ucl/ast.go @@ -68,6 +68,7 @@ type astDot struct { } type astCmd struct { + Pos lexer.Position Name astDot `parser:"@@"` Args []astDot `parser:"@@*"` } diff --git a/ucl/builtins.go b/ucl/builtins.go index 83496da..89a26ac 100644 --- a/ucl/builtins.go +++ b/ucl/builtins.go @@ -263,6 +263,40 @@ func geBuiltin(ctx context.Context, args invocationArgs) (object, error) { return boolObject(isGreater || objectsEqual(args.args[0], args.args[1])), nil } +func andBuiltin(ctx context.Context, args invocationArgs) (object, error) { + if err := args.expectArgn(2); err != nil { + return nil, err + } + + for _, a := range args.args { + if a == nil || !a.Truthy() { + return boolObject(false), nil + } + } + return args.args[len(args.args)-1], nil +} + +func orBuiltin(ctx context.Context, args invocationArgs) (object, error) { + if err := args.expectArgn(2); err != nil { + return nil, err + } + + for _, a := range args.args { + if a != nil && a.Truthy() { + return a, nil + } + } + return boolObject(false), nil +} + +func notBuiltin(ctx context.Context, args invocationArgs) (object, error) { + if err := args.expectArgn(1); err != nil { + return nil, err + } + + return boolObject(!args.args[0].Truthy()), nil +} + var errObjectsNotEqual = errors.New("objects not equal") func objectsEqual(l, r object) bool { @@ -319,13 +353,6 @@ func objectsEqual(l, r object) bool { return false } return true - case OpaqueObject: - rv, ok := r.(OpaqueObject) - if !ok { - return false - } - - return lv.v == rv.v } return false } diff --git a/ucl/errors.go b/ucl/errors.go new file mode 100644 index 0000000..6e0adb7 --- /dev/null +++ b/ucl/errors.go @@ -0,0 +1,37 @@ +package ucl + +import ( + "fmt" + "github.com/alecthomas/participle/v2/lexer" +) + +var ( + tooManyFinallyBlocksError = newBadUsage("try needs at most 1 finally") +) + +type errorWithPos struct { + err error + pos lexer.Position +} + +func (e errorWithPos) Error() string { + return fmt.Sprintf("%v:%v - %v", e.pos.Line, e.pos.Offset, e.err.Error()) +} + +func (e errorWithPos) Unwrap() error { + return e.err +} + +type errBadUsage struct { + msg string +} + +func newBadUsage(msg string) func(pos lexer.Position) error { + return func(pos lexer.Position) error { + return errorWithPos{err: errBadUsage{msg: msg}, pos: pos} + } +} + +func (e errBadUsage) Error() string { + return "bad usage: " + e.msg +} diff --git a/ucl/objs.go b/ucl/objs.go index 3530ea3..8e18095 100644 --- a/ucl/objs.go +++ b/ucl/objs.go @@ -283,6 +283,16 @@ func (ma macroArgs) evalBlock(ctx context.Context, n int, args []object, pushSco return nil, errors.New("expected an invokable arg") } +type errObject struct{ err error } + +func (eo errObject) String() string { + return "error:" + eo.err.Error() +} + +func (eo errObject) Truthy() bool { + return true +} + type invocationArgs struct { eval evaluator inst *Inst