Started working on 'try' statement
Build / build (push) Successful in 2m8s Details

This commit is contained in:
Leon Mika 2024-10-21 15:21:28 +11:00
parent 699ff18dab
commit bb78a39cdb
3 changed files with 120 additions and 0 deletions

View File

@ -770,6 +770,71 @@ func ifBuiltin(ctx context.Context, args macroArgs) (object, error) {
return nil, errors.New("malformed if-elif-else")
}
func tryBuiltin(ctx context.Context, args macroArgs) (object, error) {
if args.nargs() < 1 {
return nil, errors.New("need at least 1 arguments")
}
res, err := args.evalBlock(ctx, 0, nil, false)
if err == nil {
return res, nil
}
args.shift(1)
for args.identIs(ctx, 0, "catch") {
args.shift(1)
if args.nargs() < 1 {
return nil, errors.New("need at least 1 arguments")
}
res, err := args.evalBlock(ctx, 0, nil, false)
if err == nil {
return res, nil
}
args.shift(2)
}
// TODO: handle uncaught error
return nil, nil
/*
if guard, err := args.evalArg(ctx, 0); err == nil && isTruthy(guard) {
return args.evalBlock(ctx, 1, nil, false)
} else if err != nil {
return nil, err
}
args.shift(2)
for args.identIs(ctx, 0, "elif") {
args.shift(1)
if args.nargs() < 2 {
return nil, errors.New("need at least 2 arguments")
}
if guard, err := args.evalArg(ctx, 0); err == nil && isTruthy(guard) {
return args.evalBlock(ctx, 1, nil, false)
} else if err != nil {
return nil, err
}
args.shift(2)
}
if args.identIs(ctx, 0, "else") && args.nargs() > 1 {
return args.evalBlock(ctx, 1, nil, false)
} else if args.nargs() == 0 {
// no elif or else
return nil, nil
}
return nil, errors.New("malformed if-elif-else")
*/
}
func foreachBuiltin(ctx context.Context, args macroArgs) (object, error) {
var (
items object

View File

@ -88,6 +88,7 @@ func New(opts ...InstOption) *Inst {
rootEC.addMacro("if", macroFunc(ifBuiltin))
rootEC.addMacro("foreach", macroFunc(foreachBuiltin))
rootEC.addMacro("proc", macroFunc(procBuiltin))
rootEC.addMacro("try", macroFunc(tryBuiltin))
inst := &Inst{
out: os.Stdout,

View File

@ -3,6 +3,7 @@ package ucl
import (
"bytes"
"context"
"errors"
"fmt"
"strings"
"testing"
@ -36,6 +37,13 @@ func WithTestBuiltin() InstOption {
return listObject(args.args), nil
}))
i.rootEC.addCmd("error", invokableFunc(func(ctx context.Context, args invocationArgs) (object, error) {
if len(args.args) == 0 {
return nil, errors.New("an error occurred")
}
return nil, errors.New(args.args[0].String())
}))
i.rootEC.addCmd("joinpipe", invokableFunc(func(ctx context.Context, args invocationArgs) (object, error) {
sb := strings.Builder{}
@ -188,6 +196,52 @@ func TestBuiltins_If(t *testing.T) {
}
}
func TestBuiltins_Try(t *testing.T) {
tests := []struct {
desc string
expr string
want string
}{
{desc: "single try - successful", expr: `
try {
echo "good"
}
echo "after"`, want: "good\nafter\n(nil)\n"},
{desc: "single try - unsuccessful", expr: `
try {
error "bang"
}
echo "after"`, want: "after\n(nil)\n"},
{desc: "try with catch - successful", expr: `
try {
echo "good"
} catch {
echo "something happened"
}
echo "after"`, want: "good\nafter\n(nil)\n"},
{desc: "try with catch - unsuccessful", expr: `
try {
error "bang"
} catch {
echo "something happened"
}
echo "after"`, want: "something happened\nafter\n(nil)\n"},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
ctx := context.Background()
outW := bytes.NewBuffer(nil)
inst := New(WithOut(outW), WithTestBuiltin())
err := EvalAndDisplay(ctx, inst, tt.expr)
assert.NoError(t, err)
assert.Equal(t, tt.want, outW.String())
})
}
}
func TestBuiltins_ForEach(t *testing.T) {
tests := []struct {
desc string