issue-1: Added str and int
This commit is contained in:
parent
0138270a69
commit
ca962f5c83
|
@ -206,6 +206,46 @@ func objectsLessThan(l, r object) (bool, error) {
|
|||
return false, errors.New("objects are not comparable")
|
||||
}
|
||||
|
||||
func strBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||
if err := args.expectArgn(1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if args.args[0] == nil {
|
||||
return strObject(""), nil
|
||||
}
|
||||
|
||||
return strObject(args.args[0].String()), nil
|
||||
}
|
||||
|
||||
func intBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||
if err := args.expectArgn(1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if args.args[0] == nil {
|
||||
return intObject(0), nil
|
||||
}
|
||||
|
||||
switch v := args.args[0].(type) {
|
||||
case intObject:
|
||||
return v, nil
|
||||
case strObject:
|
||||
i, err := strconv.Atoi(string(v))
|
||||
if err != nil {
|
||||
return nil, errors.New("cannot convert to int")
|
||||
}
|
||||
return intObject(i), nil
|
||||
case boolObject:
|
||||
if v {
|
||||
return intObject(1), nil
|
||||
}
|
||||
return intObject(0), nil
|
||||
}
|
||||
|
||||
return nil, errors.New("cannot convert to int")
|
||||
}
|
||||
|
||||
func concatBuiltin(ctx context.Context, args invocationArgs) (object, error) {
|
||||
var sb strings.Builder
|
||||
|
||||
|
|
|
@ -64,6 +64,9 @@ func New(opts ...InstOption) *Inst {
|
|||
rootEC.addCmd("lt", invokableFunc(ltBuiltin))
|
||||
rootEC.addCmd("le", invokableFunc(leBuiltin))
|
||||
|
||||
rootEC.addCmd("str", invokableFunc(strBuiltin))
|
||||
rootEC.addCmd("int", invokableFunc(intBuiltin))
|
||||
|
||||
rootEC.addCmd("cat", invokableFunc(concatBuiltin))
|
||||
rootEC.addCmd("break", invokableFunc(breakBuiltin))
|
||||
rootEC.addCmd("continue", invokableFunc(continueBuiltin))
|
||||
|
|
33
ucl/objs.go
33
ucl/objs.go
|
@ -4,9 +4,11 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/lmika/gopkgs/fp/slices"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/lmika/gopkgs/fp/slices"
|
||||
)
|
||||
|
||||
type object interface {
|
||||
|
@ -39,10 +41,33 @@ func (s listObject) Truthy() bool {
|
|||
return len(s) > 0
|
||||
}
|
||||
|
||||
func (s listObject) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s listObject) Index(i int) object {
|
||||
return s[i]
|
||||
}
|
||||
|
||||
type hashObject map[string]object
|
||||
|
||||
func (s hashObject) String() string {
|
||||
return fmt.Sprintf("%v", map[string]object(s))
|
||||
if len(s) == 0 {
|
||||
return "[:]"
|
||||
}
|
||||
|
||||
sb := strings.Builder{}
|
||||
sb.WriteString("[")
|
||||
for k, v := range s {
|
||||
if sb.Len() != 1 {
|
||||
sb.WriteString(" ")
|
||||
}
|
||||
sb.WriteString(k)
|
||||
sb.WriteString(":")
|
||||
sb.WriteString(v.String())
|
||||
}
|
||||
sb.WriteString("]")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (s hashObject) Truthy() bool {
|
||||
|
@ -90,9 +115,9 @@ type boolObject bool
|
|||
|
||||
func (b boolObject) String() string {
|
||||
if b {
|
||||
return "(true)"
|
||||
return "true"
|
||||
}
|
||||
return "(false))"
|
||||
return "false"
|
||||
}
|
||||
|
||||
func (b boolObject) Truthy() bool {
|
||||
|
|
|
@ -1013,3 +1013,74 @@ func TestBuiltins_EqNe(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuiltins_Str(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
expr string
|
||||
want string
|
||||
}{
|
||||
{desc: "str", expr: `str "hello"`, want: "hello"},
|
||||
{desc: "int", expr: `str 123`, want: "123"},
|
||||
{desc: "bool 1", expr: `str (eq 1 1)`, want: "true"},
|
||||
{desc: "bool 2", expr: `str (eq 1 0)`, want: "false"},
|
||||
{desc: "list 1", expr: `str [1 2 3]`, want: "[1 2 3]"},
|
||||
{desc: "list 2", expr: `str []`, want: "[]"},
|
||||
{desc: "dict 1", expr: `str ["hello":"world"]`, want: `[hello:world]`},
|
||||
{desc: "dict 2", expr: `str [:]`, want: "[:]"},
|
||||
{desc: "nil", expr: `str ()`, want: ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
outW := bytes.NewBuffer(nil)
|
||||
|
||||
inst := New(WithOut(outW), WithTestBuiltin())
|
||||
|
||||
eqRes, err := inst.Eval(ctx, tt.expr)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, eqRes)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuiltins_Int(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
expr string
|
||||
want int
|
||||
wantErr bool
|
||||
}{
|
||||
{desc: "str 1", expr: `int "123"`, want: 123},
|
||||
{desc: "str 2", expr: `int "31452"`, want: 31452},
|
||||
{desc: "str 3", expr: `int "-21"`, want: -21},
|
||||
{desc: "int 1", expr: `int 123`, want: 123},
|
||||
{desc: "int 2", expr: `int -21`, want: -21},
|
||||
{desc: "bool 1", expr: `int (eq 1 1)`, want: 1},
|
||||
{desc: "bool 2", expr: `int (eq 1 0)`, want: 0},
|
||||
{desc: "nil", expr: `int ()`, want: 0},
|
||||
|
||||
{desc: "list 1", expr: `int [1 2 3]`, wantErr: true},
|
||||
{desc: "list 2", expr: `int []`, wantErr: true},
|
||||
{desc: "dict 1", expr: `int ["hello":"world"]`, wantErr: true},
|
||||
{desc: "dict 2", expr: `int [:]`, wantErr: true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
outW := bytes.NewBuffer(nil)
|
||||
|
||||
inst := New(WithOut(outW), WithTestBuiltin())
|
||||
|
||||
eqRes, err := inst.Eval(ctx, tt.expr)
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, eqRes)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue