diff --git a/evaluator/value.go b/evaluator/value.go index 77a05ee..097ea42 100644 --- a/evaluator/value.go +++ b/evaluator/value.go @@ -148,13 +148,23 @@ func (v structValue) Contains(elem Value) bool { func (v arrayValue) IndexValue(index Value) Value { rv := reflect.ValueOf(v.basis) - if n, ok := index.Interface().(int); ok { - if n < 0 { - n += rv.Len() - } - if 0 <= n && n < rv.Len() { - return ValueOf(rv.Index(n).Interface()) - } + var n int + switch ix := index.Interface().(type) { + case int: + n = ix + case float32: + // this how Ruby arrays, and therefore Liquid arrays, work + n = int(ix) + case float64: + n = int(ix) + default: + return nilValue + } + if n < 0 { + n += rv.Len() + } + if 0 <= n && n < rv.Len() { + return ValueOf(rv.Index(n).Interface()) } return nilValue } diff --git a/evaluator/value_test.go b/evaluator/value_test.go index 22a206c..6d9facd 100644 --- a/evaluator/value_test.go +++ b/evaluator/value_test.go @@ -53,6 +53,8 @@ func TestValue_IndexValue(t *testing.T) { av := ValueOf([]string{"first", "second", "third"}) require.Equal(t, "first", av.IndexValue(ValueOf(0)).Interface()) require.Equal(t, "third", av.IndexValue(ValueOf(-1)).Interface()) + require.Equal(t, "second", av.IndexValue(ValueOf(1.0)).Interface()) + require.Equal(t, "second", av.IndexValue(ValueOf(1.1)).Interface()) hv := ValueOf(map[string]interface{}{"key": "value"}) require.Equal(t, "value", hv.IndexValue(ValueOf("key")).Interface())