diff --git a/README.md b/README.md index 840177e..3633dff 100644 --- a/README.md +++ b/README.md @@ -61,12 +61,16 @@ join(", ", ["a", "b", "c"]) // "a, b, c" ###### `equals(string, string)` ###### `equals(int64, int64)` +###### `equals([string, ...], [string, ...])` +###### `equals([int64, ...], [int64, ...])` returns `true` if both arguments are equal ```js equals(1, 1) // true equals(1, 0) // false equals("foo", "foo") // true equals("foo", "bar") // false +equals(["foo", 1], ["foo", 1]) // true +equals(["foo"], ["bar"]) // false ``` ###### `intersects([string, ...], [string, ...])` diff --git a/assert/assert.go b/assert/assert.go index 16d2d82..8d52188 100644 --- a/assert/assert.go +++ b/assert/assert.go @@ -10,6 +10,13 @@ var ( errWrongArgType = errors.New("wrong argument type") ) +var ( + TypeBytes = Type(memory.TypeBytes) + TypeInt64 = Type(memory.TypeInt64) + TypeBool = Type(memory.TypeBool) + TypeVector = Type(memory.TypeVector) +) + type Asserter interface { Assert([]memory.Addr) error } @@ -31,10 +38,10 @@ func Len(l int) AsserterFunc { func TypeAt(i int, t memory.Type) AsserterFunc { return func(argv []memory.Addr) error { - if argv[i].Type() != t { - return errWrongArgType + if argv[i].TypeOf(t) { + return nil } - return nil + return errWrongArgType } } @@ -47,7 +54,7 @@ func VectorAt(i int, a Asserter) AsserterFunc { func Type(t memory.Type) AsserterFunc { return func(argv []memory.Addr) error { for _, arg := range argv { - if arg.Type() != t { + if !arg.TypeOf(t) { return errWrongArgType } } diff --git a/exec/vm_test.go b/exec/vm_test.go index f527f9b..55a0218 100644 --- a/exec/vm_test.go +++ b/exec/vm_test.go @@ -183,6 +183,32 @@ func TestVM_Exec(t *testing.T) { assert.True(t, addr.Bool()) }) + t.Run("func equals vector", func(t *testing.T) { + bcode := comp.Compile(value.Nest( + value.Exit(), + value.Nest( + value.Call("equals"), + value.Nest( + value.Arr(), + value.Str("foo"), + value.Str("bar"), + ), + value.Nest( + value.Arr(), + value.Str("foo"), + value.Str("bar"), + ), + ), + )) + + addr, err := exec.Exec(bcode) + require.NoError(t, err) + require.NotNil(t, addr) + + require.Equal(t, memory.TypeBool, addr.Type()) + assert.True(t, addr.Bool()) + }) + t.Run("func equals concat", func(t *testing.T) { bcode := comp.Compile(value.Nest( value.Exit(), diff --git a/memory/addr.go b/memory/addr.go index 28df431..686c232 100644 --- a/memory/addr.go +++ b/memory/addr.go @@ -75,6 +75,14 @@ func (a Addr) Type() Type { return a.typ } +func (a Addr) TypeOf(t Type) bool { + return a.typ == t +} + +func (a Addr) EqualType(b Addr) bool { + return a.typ == b.typ +} + func (a Addr) EqualBytes(b Addr) bool { return bytes.Equal(a.dat, b.dat) } diff --git a/memory/addr_test.go b/memory/addr_test.go index ad2e66c..7020941 100644 --- a/memory/addr_test.go +++ b/memory/addr_test.go @@ -37,6 +37,15 @@ func TestAddr_CopyBytes(t *testing.T) { assert.Equal(t, []byte{1, 2, 3, 4, 5, 6}, addrX.Bytes()) } +func TestAddr_TypeOf(t *testing.T) { + assert.True(t, memory.True.TypeOf(memory.TypeBool)) + assert.False(t, memory.True.TypeOf(memory.TypeNil)) +} + +func TestAddr_EqualType(t *testing.T) { + assert.True(t, memory.True.EqualType(memory.False)) +} + func TestAddr_EqualBytes(t *testing.T) { assert.True(t, memory.True.EqualBytes(memory.True)) assert.False(t, memory.True.EqualBytes(memory.False)) diff --git a/memory/memory_test.go b/memory/memory_test.go index 55495ff..bf4092c 100644 --- a/memory/memory_test.go +++ b/memory/memory_test.go @@ -12,7 +12,6 @@ var mem memory.Memory func TestMemory_AllocBytes(t *testing.T) { t.Run("alloc zero", func(t *testing.T) { - addr := mem.AllocBytes(0) assert.Equal(t, uint32(0), addr.Size()) }) diff --git a/stdlib/compare.go b/stdlib/compare.go index 4867b5c..1d48e7a 100644 --- a/stdlib/compare.go +++ b/stdlib/compare.go @@ -11,8 +11,19 @@ func init() { Assert(assert.Every( assert.Len(2), assert.Any( - assert.Type(memory.TypeInt64), - assert.Type(memory.TypeBytes), + assert.TypeInt64, + assert.TypeBytes, + assert.Every( + assert.TypeVector, + assert.VectorAt(0, assert.Any( + assert.TypeInt64, + assert.TypeBytes, + )), + assert.VectorAt(1, assert.Any( + assert.TypeInt64, + assert.TypeBytes, + )), + ), ), ))) @@ -22,11 +33,11 @@ func init() { assert.TypeAt(0, memory.TypeVector), assert.Any( assert.Every( - assert.VectorAt(0, assert.Type(memory.TypeInt64)), + assert.VectorAt(0, assert.TypeInt64), assert.TypeAt(1, memory.TypeInt64), ), assert.Every( - assert.VectorAt(0, assert.Type(memory.TypeBytes)), + assert.VectorAt(0, assert.TypeBytes), assert.TypeAt(1, memory.TypeBytes), ), ), @@ -35,7 +46,7 @@ func init() { Register("intersects", delegate.DelegatorFunc(intersects). Assert(assert.Every( assert.Len(2), - assert.Type(memory.TypeVector), + assert.TypeVector, assert.Any( assert.Every( assert.VectorAt(0, assert.Type(memory.TypeInt64)), @@ -47,10 +58,23 @@ func init() { ), ), ))) - } func equals(mem *memory.Memory, argv []memory.Addr) (memory.Addr, error) { + if !argv[0].EqualType(argv[1]) { + return memory.False, nil + } + if argv[0].TypeOf(memory.TypeVector) { + if argv[0].VectorLen() != argv[1].VectorLen() { + return memory.False, nil + } + for i, a := range argv[0].Vector() { + if !a.EqualBytes(argv[1].VectorAt(i)) { + return memory.False, nil + } + } + return memory.True, nil + } if argv[0].EqualBytes(argv[1]) { return memory.True, nil } diff --git a/stdlib/strings.go b/stdlib/strings.go index 29d1e71..e3e9a37 100644 --- a/stdlib/strings.go +++ b/stdlib/strings.go @@ -8,14 +8,14 @@ import ( func init() { Register("concat", delegate.DelegatorFunc(concat).Assert( - assert.Type(memory.TypeBytes), + assert.TypeBytes, )) Register("join", delegate.DelegatorFunc(join).Assert(assert.Every( assert.Len(2), assert.TypeAt(0, memory.TypeBytes), assert.TypeAt(1, memory.TypeVector), - assert.VectorAt(1, assert.Type(memory.TypeBytes)), + assert.VectorAt(1, assert.TypeBytes), ))) }