Started working on 'try' statement
Build / build (push) Successful in 2m8s
Details
Build / build (push) Successful in 2m8s
Details
This commit is contained in:
parent
699ff18dab
commit
bb78a39cdb
|
@ -770,6 +770,71 @@ func ifBuiltin(ctx context.Context, args macroArgs) (object, error) {
|
||||||
return nil, errors.New("malformed if-elif-else")
|
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) {
|
func foreachBuiltin(ctx context.Context, args macroArgs) (object, error) {
|
||||||
var (
|
var (
|
||||||
items object
|
items object
|
||||||
|
|
|
@ -88,6 +88,7 @@ func New(opts ...InstOption) *Inst {
|
||||||
rootEC.addMacro("if", macroFunc(ifBuiltin))
|
rootEC.addMacro("if", macroFunc(ifBuiltin))
|
||||||
rootEC.addMacro("foreach", macroFunc(foreachBuiltin))
|
rootEC.addMacro("foreach", macroFunc(foreachBuiltin))
|
||||||
rootEC.addMacro("proc", macroFunc(procBuiltin))
|
rootEC.addMacro("proc", macroFunc(procBuiltin))
|
||||||
|
rootEC.addMacro("try", macroFunc(tryBuiltin))
|
||||||
|
|
||||||
inst := &Inst{
|
inst := &Inst{
|
||||||
out: os.Stdout,
|
out: os.Stdout,
|
||||||
|
|
|
@ -3,6 +3,7 @@ package ucl
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -36,6 +37,13 @@ func WithTestBuiltin() InstOption {
|
||||||
return listObject(args.args), nil
|
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) {
|
i.rootEC.addCmd("joinpipe", invokableFunc(func(ctx context.Context, args invocationArgs) (object, error) {
|
||||||
sb := strings.Builder{}
|
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) {
|
func TestBuiltins_ForEach(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|
Loading…
Reference in New Issue