mirror of
				https://github.com/MontFerret/ferret.git
				synced 2025-10-30 23:37:40 +02:00 
			
		
		
		
	New type system (#232)
* New type system * Fixed dot notation for HTML elements
This commit is contained in:
		| @@ -2,6 +2,7 @@ package compiler | ||||
|  | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -35,13 +36,13 @@ func (s *scope) GetVariable(name string) (core.Type, error) { | ||||
| 		parents, err := s.parent.GetVariable(name) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return core.NoneType, err | ||||
| 			return types.None, err | ||||
| 		} | ||||
|  | ||||
| 		return parents, nil | ||||
| 	} | ||||
|  | ||||
| 	return core.NoneType, core.Error(ErrVariableNotFound, name) | ||||
| 	return types.None, core.Error(ErrVariableNotFound, name) | ||||
| } | ||||
|  | ||||
| func (s *scope) SetVariable(name string) error { | ||||
| @@ -52,7 +53,7 @@ func (s *scope) SetVariable(name string) error { | ||||
| 	} | ||||
|  | ||||
| 	// TODO: add type detection | ||||
| 	s.vars[name] = core.NoneType | ||||
| 	s.vars[name] = types.None | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,6 @@ package cdp | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"github.com/mafredri/cdp/protocol/dom" | ||||
| 	"hash/fnv" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| @@ -13,7 +12,9 @@ import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/logging" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"github.com/mafredri/cdp" | ||||
| 	"github.com/mafredri/cdp/protocol/dom" | ||||
| 	"github.com/mafredri/cdp/protocol/input" | ||||
| 	"github.com/mafredri/cdp/protocol/page" | ||||
| 	"github.com/mafredri/cdp/rpcc" | ||||
| @@ -142,7 +143,7 @@ func (doc *HTMLDocument) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) Type() core.Type { | ||||
| 	return core.HTMLDocumentType | ||||
| 	return types.HTMLDocument | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) String() string { | ||||
| @@ -176,22 +177,17 @@ func (doc *HTMLDocument) Copy() core.Value { | ||||
| 	return values.None | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) Compare(other core.Value) int { | ||||
| func (doc *HTMLDocument) Compare(other core.Value) int64 { | ||||
| 	doc.Lock() | ||||
| 	defer doc.Unlock() | ||||
|  | ||||
| 	switch other.Type() { | ||||
| 	case core.HTMLDocumentType: | ||||
| 	if other.Type() == types.HTMLDocument { | ||||
| 		other := other.(*HTMLDocument) | ||||
|  | ||||
| 		return doc.url.Compare(other.url) | ||||
| 	default: | ||||
| 		if other.Type() > core.HTMLDocumentType { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(other.Type(), types.HTMLDocument) | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) Close() error { | ||||
| @@ -399,7 +395,7 @@ func (doc *HTMLDocument) ClickBySelector(selector values.String) (values.Boolean | ||||
| 		return values.False, err | ||||
| 	} | ||||
|  | ||||
| 	if res.Type() == core.BooleanType { | ||||
| 	if res.Type() == types.Boolean { | ||||
| 		return res.(values.Boolean), nil | ||||
| 	} | ||||
|  | ||||
| @@ -431,7 +427,7 @@ func (doc *HTMLDocument) ClickBySelectorAll(selector values.String) (values.Bool | ||||
| 		return values.False, err | ||||
| 	} | ||||
|  | ||||
| 	if res.Type() == core.BooleanType { | ||||
| 	if res.Type() == types.Boolean { | ||||
| 		return res.(values.Boolean), nil | ||||
| 	} | ||||
|  | ||||
| @@ -461,7 +457,7 @@ func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Valu | ||||
| 		return values.False, err | ||||
| 	} | ||||
|  | ||||
| 	if res.Type() == core.BooleanType && res.(values.Boolean) == values.False { | ||||
| 	if res.Type() == types.Boolean && res.(values.Boolean) == values.False { | ||||
| 		return values.False, nil | ||||
| 	} | ||||
|  | ||||
| @@ -531,7 +527,7 @@ func (doc *HTMLDocument) SelectBySelector(selector values.String, value *values. | ||||
| 		return arr, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, core.TypeError(core.ArrayType, res.Type()) | ||||
| 	return nil, core.TypeError(types.Array, res.Type()) | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) HoverBySelector(selector values.String) error { | ||||
|   | ||||
| @@ -4,7 +4,6 @@ import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"github.com/gofrs/uuid" | ||||
| 	"hash/fnv" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| @@ -16,6 +15,8 @@ import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers/common" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"github.com/gofrs/uuid" | ||||
| 	"github.com/mafredri/cdp" | ||||
| 	"github.com/mafredri/cdp/protocol/dom" | ||||
| 	"github.com/mafredri/cdp/protocol/input" | ||||
| @@ -195,7 +196,7 @@ func (el *HTMLElement) Close() error { | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) Type() core.Type { | ||||
| 	return core.HTMLElementType | ||||
| 	return types.HTMLElement | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) MarshalJSON() ([]byte, error) { | ||||
| @@ -212,9 +213,8 @@ func (el *HTMLElement) String() string { | ||||
| 	return el.InnerHTML().String() | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.HTMLDocumentType: | ||||
| func (el *HTMLElement) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.HTMLElement { | ||||
| 		other := other.(*HTMLElement) | ||||
|  | ||||
| 		id := int(el.id.backendID) | ||||
| @@ -229,13 +229,9 @@ func (el *HTMLElement) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return -1 | ||||
| 	default: | ||||
| 		if other.Type() > core.HTMLElementType { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(other.Type(), types.HTMLElement) | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) Unwrap() interface{} { | ||||
| @@ -711,7 +707,7 @@ func (el *HTMLElement) WaitForClass(class values.String, timeout values.Int) err | ||||
| 		func() (core.Value, error) { | ||||
| 			current := el.GetAttribute("class") | ||||
|  | ||||
| 			if current.Type() != core.StringType { | ||||
| 			if current.Type() != types.String { | ||||
| 				return values.None, nil | ||||
| 			} | ||||
|  | ||||
| @@ -850,7 +846,7 @@ func (el *HTMLElement) Select(value *values.Array) (*values.Array, error) { | ||||
| 		return arr, nil | ||||
| 	} | ||||
|  | ||||
| 	return nil, core.TypeError(core.ArrayType, res.Type()) | ||||
| 	return nil, core.TypeError(types.Array, res.Type()) | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) ScrollIntoView() error { | ||||
|   | ||||
| @@ -4,6 +4,10 @@ import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"golang.org/x/sync/errgroup" | ||||
| 	"math" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers/cdp/eval" | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers/cdp/events" | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers/common" | ||||
| @@ -13,9 +17,6 @@ import ( | ||||
| 	"github.com/mafredri/cdp/protocol/dom" | ||||
| 	"github.com/mafredri/cdp/protocol/page" | ||||
| 	"github.com/mafredri/cdp/protocol/runtime" | ||||
| 	"golang.org/x/sync/errgroup" | ||||
| 	"math" | ||||
| 	"strings" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
|   | ||||
| @@ -2,9 +2,10 @@ package drivers | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"io" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package http | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"github.com/PuerkitoBio/goquery" | ||||
| ) | ||||
|  | ||||
| @@ -33,22 +34,17 @@ func NewHTMLDocument( | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) Type() core.Type { | ||||
| 	return core.HTMLDocumentType | ||||
| 	return types.HTMLDocument | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.HTMLDocumentType: | ||||
| func (doc *HTMLDocument) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.HTMLDocument { | ||||
| 		otherDoc := other.(values.HTMLDocument) | ||||
|  | ||||
| 		return doc.url.Compare(otherDoc.URL()) | ||||
| 	default: | ||||
| 		if other.Type() > core.HTMLDocumentType { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(other.Type(), types.HTMLDocument) | ||||
| } | ||||
|  | ||||
| func (doc *HTMLDocument) URL() core.Value { | ||||
|   | ||||
| @@ -3,11 +3,11 @@ package http | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"context" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/logging" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers/common" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/logging" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/PuerkitoBio/goquery" | ||||
| 	"github.com/corpix/uarand" | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers/common" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"github.com/PuerkitoBio/goquery" | ||||
| ) | ||||
|  | ||||
| @@ -29,25 +30,20 @@ func (el *HTMLElement) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) Type() core.Type { | ||||
| 	return core.HTMLElementType | ||||
| 	return types.HTMLElement | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) String() string { | ||||
| 	return el.InnerHTML().String() | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.HTMLElementType: | ||||
| func (el *HTMLElement) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.HTMLElement { | ||||
| 		// TODO: complete the comparison | ||||
| 		return -1 | ||||
| 	default: | ||||
| 		if other.Type() > core.HTMLElementType { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(other.Type(), types.HTMLElement) | ||||
| } | ||||
|  | ||||
| func (el *HTMLElement) Unwrap() interface{} { | ||||
|   | ||||
| @@ -10,7 +10,7 @@ import ( | ||||
| type ( | ||||
| 	SortDirection int | ||||
|  | ||||
| 	Comparator func(ctx context.Context, first, second *core.Scope) (int, error) | ||||
| 	Comparator func(ctx context.Context, first, second *core.Scope) (int64, error) | ||||
|  | ||||
| 	Sorter struct { | ||||
| 		fn        Comparator | ||||
| @@ -136,7 +136,7 @@ func (iterator *SortIterator) sort(ctx context.Context, scope *core.Scope) ([]*c | ||||
| 				break | ||||
| 			} | ||||
|  | ||||
| 			eq = eq * int(comp.direction) | ||||
| 			eq = eq * int64(comp.direction) | ||||
|  | ||||
| 			if eq == -1 { | ||||
| 				out = true | ||||
|   | ||||
| @@ -35,7 +35,7 @@ func TestSort(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		s, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				return first.MustGetVariable(collections.DefaultValueVar).Compare(second.MustGetVariable(collections.DefaultValueVar)), nil | ||||
| 			}, | ||||
| 			collections.SortDirectionAsc, | ||||
| @@ -72,7 +72,7 @@ func TestSort(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		s, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				return first.MustGetVariable(collections.DefaultValueVar).Compare(second.MustGetVariable(collections.DefaultValueVar)), nil | ||||
| 			}, | ||||
| 			collections.SortDirectionDesc, | ||||
| @@ -120,7 +120,7 @@ func TestSort(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		s1, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
|  | ||||
| @@ -130,7 +130,7 @@ func TestSort(t *testing.T) { | ||||
| 		) | ||||
|  | ||||
| 		s2, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
|  | ||||
| @@ -183,7 +183,7 @@ func TestSort(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		s1, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
|  | ||||
| @@ -193,7 +193,7 @@ func TestSort(t *testing.T) { | ||||
| 		) | ||||
|  | ||||
| 		s2, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
|  | ||||
| @@ -246,7 +246,7 @@ func TestSort(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		s1, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
|  | ||||
| @@ -256,7 +256,7 @@ func TestSort(t *testing.T) { | ||||
| 		) | ||||
|  | ||||
| 		s2, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
|  | ||||
| @@ -309,7 +309,7 @@ func TestSort(t *testing.T) { | ||||
| 		} | ||||
|  | ||||
| 		s1, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one") | ||||
|  | ||||
| @@ -319,7 +319,7 @@ func TestSort(t *testing.T) { | ||||
| 		) | ||||
|  | ||||
| 		s2, _ := collections.NewSorter( | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 			func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 				o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
| 				o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") | ||||
|  | ||||
|   | ||||
| @@ -24,17 +24,14 @@ func TestSourceError(t *testing.T) { | ||||
|  | ||||
| func TestTypeError(t *testing.T) { | ||||
| 	Convey("Should match", t, func() { | ||||
| 		e := core.TypeError(core.BooleanType) | ||||
| 		e := core.TypeError(TypeA{}) | ||||
| 		So(e, ShouldNotBeNil) | ||||
|  | ||||
| 		e = core.TypeError(core.BooleanType, core.BooleanType) | ||||
| 		e = core.TypeError(TypeA{}, TypeB{}) | ||||
| 		So(e, ShouldNotBeNil) | ||||
|  | ||||
| 		e = core.TypeError(core.BooleanType, core.BooleanType, core.IntType, core.FloatType) | ||||
| 		So(e, ShouldNotBeNil) | ||||
|  | ||||
| 		cause := errors.New("invalid type: expected none or boolean or int or float, but got none") | ||||
| 		e = core.TypeError(core.NoneType, core.NoneType, core.BooleanType, core.IntType, core.FloatType) | ||||
| 		cause := errors.New("invalid type: expected type_b or type_c, but got type_a") | ||||
| 		e = core.TypeError(TypeA{}, TypeB{}, TypeC{}) | ||||
| 		So(e.Error(), ShouldEqual, cause.Error()) | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -160,39 +160,55 @@ func BenchmarkScope(b *testing.B) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type TestCloser struct { | ||||
| 	closed bool | ||||
| type ( | ||||
| 	TestCloserType struct{} | ||||
|  | ||||
| 	TestCloserValue struct { | ||||
| 		closed bool | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| func (tct TestCloserType) ID() int64 { | ||||
| 	return 99 | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) MarshalJSON() ([]byte, error) { | ||||
| func (tct TestCloserType) String() string { | ||||
| 	return "TestCloser" | ||||
| } | ||||
|  | ||||
| func (tct TestCloserType) Equals(other core.Type) bool { | ||||
| 	return other.ID() == tct.ID() | ||||
| } | ||||
|  | ||||
| func (tc *TestCloserValue) MarshalJSON() ([]byte, error) { | ||||
| 	return nil, core.ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) Type() core.Type { | ||||
| 	return core.NoneType | ||||
| func (tc *TestCloserValue) Type() core.Type { | ||||
| 	return TestCloserType{} | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) String() string { | ||||
| func (tc *TestCloserValue) String() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) Compare(other core.Value) int { | ||||
| func (tc *TestCloserValue) Compare(other core.Value) int64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) Unwrap() interface{} { | ||||
| func (tc *TestCloserValue) Unwrap() interface{} { | ||||
| 	return tc | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) Hash() uint64 { | ||||
| func (tc *TestCloserValue) Hash() uint64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) Copy() core.Value { | ||||
| 	return &TestCloser{} | ||||
| func (tc *TestCloserValue) Copy() core.Value { | ||||
| 	return &TestCloserValue{} | ||||
| } | ||||
|  | ||||
| func (tc *TestCloser) Close() error { | ||||
| func (tc *TestCloserValue) Close() error { | ||||
| 	if tc.closed { | ||||
| 		return core.Error(core.ErrInvalidOperation, "already closed") | ||||
| 	} | ||||
| @@ -206,7 +222,7 @@ func TestCloseFunc(t *testing.T) { | ||||
| 	Convey("Should close root scope and close all io.Closer values", t, func() { | ||||
| 		rs, cf := core.NewRootScope() | ||||
|  | ||||
| 		tc := &TestCloser{} | ||||
| 		tc := &TestCloserValue{} | ||||
|  | ||||
| 		rs.SetVariable("disposable", tc) | ||||
| 		So(tc.closed, ShouldBeFalse) | ||||
| @@ -220,7 +236,7 @@ func TestCloseFunc(t *testing.T) { | ||||
| 	Convey("Should return error if it's already closed", t, func() { | ||||
| 		rs, cf := core.NewRootScope() | ||||
|  | ||||
| 		tc := &TestCloser{} | ||||
| 		tc := &TestCloserValue{} | ||||
|  | ||||
| 		rs.SetVariable("disposable", tc) | ||||
| 		So(tc.closed, ShouldBeFalse) | ||||
|   | ||||
							
								
								
									
										83
									
								
								pkg/runtime/core/type.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								pkg/runtime/core/type.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| package core | ||||
|  | ||||
| import ( | ||||
| 	"github.com/pkg/errors" | ||||
| 	"math/rand" | ||||
| ) | ||||
|  | ||||
| // Type represents runtime type with id for quick type check | ||||
| // and Name for error messages | ||||
|  | ||||
| //revive:disable-next-line:redefines-builtin-id | ||||
| type ( | ||||
| 	Type interface { | ||||
| 		ID() int64 | ||||
| 		String() string | ||||
| 		Equals(other Type) bool | ||||
| 	} | ||||
|  | ||||
| 	BaseType struct { | ||||
| 		id   int64 | ||||
| 		name string | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| func NewType(name string) Type { | ||||
| 	return BaseType{rand.Int63(), name} | ||||
| } | ||||
|  | ||||
| func (t BaseType) ID() int64 { | ||||
| 	return t.id | ||||
| } | ||||
|  | ||||
| func (t BaseType) String() string { | ||||
| 	return t.name | ||||
| } | ||||
|  | ||||
| func (t BaseType) Equals(other Type) bool { | ||||
| 	return t.id == other.ID() | ||||
| } | ||||
|  | ||||
| // IsTypeOf return true when value's type | ||||
| // is equal to check type. | ||||
| // Returns false, otherwise. | ||||
| func IsTypeOf(value Value, check Type) bool { | ||||
| 	return value.Type().ID() == check.ID() | ||||
| } | ||||
|  | ||||
| // ValidateType checks the match of | ||||
| // value's type and required types. | ||||
| func ValidateType(value Value, required ...Type) error { | ||||
| 	var valid bool | ||||
| 	tid := value.Type().ID() | ||||
|  | ||||
| 	for _, t := range required { | ||||
| 		if tid == t.ID() { | ||||
| 			valid = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !valid { | ||||
| 		return TypeError(value.Type(), required...) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ValidateValueTypePairs validate pairs of | ||||
| // Values and Types. | ||||
| // Returns error when type didn't match | ||||
| func ValidateValueTypePairs(pairs ...PairValueType) error { | ||||
| 	var err error | ||||
|  | ||||
| 	for idx, pair := range pairs { | ||||
| 		err = ValidateType(pair.Value, pair.Types...) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return errors.Errorf("pair %d: %v", idx, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										109
									
								
								pkg/runtime/core/type_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								pkg/runtime/core/type_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| package core_test | ||||
|  | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| 	Value struct { | ||||
| 		type_ core.Type | ||||
| 	} | ||||
|  | ||||
| 	TypeA struct{} | ||||
|  | ||||
| 	TypeB struct{} | ||||
|  | ||||
| 	TypeC struct{} | ||||
| ) | ||||
|  | ||||
| func (t Value) MarshalJSON() ([]byte, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (t Value) Type() core.Type { | ||||
| 	return t.type_ | ||||
| } | ||||
|  | ||||
| func (t Value) String() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (t Value) Compare(other core.Value) int64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (t Value) Unwrap() interface{} { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (t Value) Hash() uint64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (t Value) Copy() core.Value { | ||||
| 	return t | ||||
| } | ||||
|  | ||||
| func (t TypeA) ID() int64 { | ||||
| 	return 1 | ||||
| } | ||||
|  | ||||
| func (t TypeA) String() string { | ||||
| 	return "type_a" | ||||
| } | ||||
|  | ||||
| func (t TypeA) Equals(other core.Type) bool { | ||||
| 	return t.ID() == other.ID() | ||||
| } | ||||
|  | ||||
| func (t TypeB) ID() int64 { | ||||
| 	return 2 | ||||
| } | ||||
|  | ||||
| func (t TypeB) String() string { | ||||
| 	return "type_b" | ||||
| } | ||||
|  | ||||
| func (t TypeB) Equals(other core.Type) bool { | ||||
| 	return t.ID() == other.ID() | ||||
| } | ||||
|  | ||||
| func (t TypeC) ID() int64 { | ||||
| 	return 3 | ||||
| } | ||||
|  | ||||
| func (t TypeC) String() string { | ||||
| 	return "type_c" | ||||
| } | ||||
|  | ||||
| func (t TypeC) Equals(other core.Type) bool { | ||||
| 	return t.ID() == other.ID() | ||||
| } | ||||
|  | ||||
| func TestType(t *testing.T) { | ||||
| 	typeA := TypeA{} | ||||
| 	typeB := TypeB{} | ||||
|  | ||||
| 	Convey("IsTypeOf", t, func() { | ||||
| 		Convey("Should return 'false' when types are different", func() { | ||||
| 			vA := Value{typeA} | ||||
|  | ||||
| 			So(core.IsTypeOf(vA, typeB), ShouldBeFalse) | ||||
| 		}) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestValidateType(t *testing.T) { | ||||
| 	typeA := TypeA{} | ||||
| 	typeB := TypeB{} | ||||
|  | ||||
| 	Convey("Should validate types", t, func() { | ||||
| 		vA := Value{typeA} | ||||
| 		vB := Value{typeB} | ||||
|  | ||||
| 		So(core.ValidateType(vA, typeA), ShouldBeNil) | ||||
| 		So(core.ValidateType(vB, typeA), ShouldNotBeNil) | ||||
| 	}) | ||||
| } | ||||
| @@ -1,120 +1,41 @@ | ||||
| package core | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/json" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| //revive:disable-next-line:redefines-builtin-id | ||||
| type Type int64 | ||||
| type ( | ||||
| 	// Value represents an interface of | ||||
| 	// any type that needs to be used during runtime | ||||
| 	Value interface { | ||||
| 		json.Marshaler | ||||
| 		Type() Type | ||||
| 		String() string | ||||
| 		Compare(other Value) int64 | ||||
| 		Unwrap() interface{} | ||||
| 		Hash() uint64 | ||||
| 		Copy() Value | ||||
| 	} | ||||
|  | ||||
| const ( | ||||
| 	NoneType         Type = 0 | ||||
| 	BooleanType      Type = 1 | ||||
| 	IntType          Type = 2 | ||||
| 	FloatType        Type = 3 | ||||
| 	StringType       Type = 4 | ||||
| 	DateTimeType     Type = 5 | ||||
| 	ArrayType        Type = 6 | ||||
| 	ObjectType       Type = 7 | ||||
| 	HTMLElementType  Type = 8 | ||||
| 	HTMLDocumentType Type = 9 | ||||
| 	BinaryType       Type = 10 | ||||
| 	CustomType       Type = 99 | ||||
| 	// Getter represents an interface of | ||||
| 	// complex types that needs to be used to read values by path. | ||||
| 	// The interface is created to let user-defined types be used in dot notation data access. | ||||
| 	Getter interface { | ||||
| 		GetIn(ctx context.Context, path []Value) (Value, error) | ||||
| 	} | ||||
|  | ||||
| 	// Setter represents an interface of | ||||
| 	// complex types that needs to be used to write values by path. | ||||
| 	// The interface is created to let user-defined types be used in dot notation assignment. | ||||
| 	Setter interface { | ||||
| 		SetIn(ctx context.Context, path []Value, value Value) error | ||||
| 	} | ||||
|  | ||||
| 	// PairValueType is a supporting | ||||
| 	// structure that used in validateValueTypePairs. | ||||
| 	PairValueType struct { | ||||
| 		Value Value | ||||
| 		Types []Type | ||||
| 	} | ||||
| ) | ||||
|  | ||||
| var typestr = map[Type]string{ | ||||
| 	NoneType:         "none", | ||||
| 	BooleanType:      "boolean", | ||||
| 	IntType:          "int", | ||||
| 	FloatType:        "float", | ||||
| 	StringType:       "string", | ||||
| 	DateTimeType:     "datetime", | ||||
| 	ArrayType:        "array", | ||||
| 	ObjectType:       "object", | ||||
| 	HTMLElementType:  "HTMLElement", | ||||
| 	HTMLDocumentType: "HTMLDocument", | ||||
| 	BinaryType:       "BinaryType", | ||||
| 	CustomType:       "CustomType", | ||||
| } | ||||
|  | ||||
| func (t Type) String() string { | ||||
| 	return typestr[t] | ||||
| } | ||||
|  | ||||
| // Value represents an interface of | ||||
| // any type that needs to be used during runtime | ||||
| type Value interface { | ||||
| 	json.Marshaler | ||||
| 	Type() Type | ||||
| 	String() string | ||||
| 	Compare(other Value) int | ||||
| 	Unwrap() interface{} | ||||
| 	Hash() uint64 | ||||
| 	Copy() Value | ||||
| } | ||||
|  | ||||
| // Getter represents an interface of | ||||
| // complex types that needs to be used to read values by path. | ||||
| // The interface is created to let user-defined types be used in dot notation data access. | ||||
| type Getter interface { | ||||
| 	GetIn(path []Value) (Value, error) | ||||
| } | ||||
|  | ||||
| // Setter represents an interface of | ||||
| // complex types that needs to be used to write values by path. | ||||
| // The interface is created to let user-defined types be used in dot notation assignment. | ||||
| type Setter interface { | ||||
| 	SetIn(path []Value, value Value) error | ||||
| } | ||||
|  | ||||
| // IsTypeOf return true when value's type | ||||
| // is equal to check type. | ||||
| // Returns false, otherwise. | ||||
| func IsTypeOf(value Value, check Type) bool { | ||||
| 	return value.Type() == check | ||||
| } | ||||
|  | ||||
| // ValidateType checks the match of | ||||
| // value's type and required types. | ||||
| func ValidateType(value Value, required ...Type) error { | ||||
| 	var valid bool | ||||
| 	ct := value.Type() | ||||
|  | ||||
| 	for _, t := range required { | ||||
| 		if ct == t { | ||||
| 			valid = true | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !valid { | ||||
| 		return TypeError(value.Type(), required...) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // PairValueType is a supporting | ||||
| // structure that used in validateValueTypePairs. | ||||
| type PairValueType struct { | ||||
| 	Value Value | ||||
| 	Types []Type | ||||
| } | ||||
|  | ||||
| // ValidateValueTypePairs validate pairs of | ||||
| // Values and Types. | ||||
| // Returns error when type didn't match | ||||
| func ValidateValueTypePairs(pairs ...PairValueType) error { | ||||
| 	var err error | ||||
|  | ||||
| 	for idx, pair := range pairs { | ||||
| 		err = ValidateType(pair.Value, pair.Types...) | ||||
| 		if err != nil { | ||||
| 			return errors.Errorf("pair %d: %v", idx, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -1,76 +0,0 @@ | ||||
| package core_test | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers/http" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| ) | ||||
|  | ||||
| func TestTypeString(t *testing.T) { | ||||
| 	Convey("The string representation of the type should match this type", t, func() { | ||||
| 		So(core.Type(0).String(), ShouldEqual, "none") | ||||
| 		So(core.Type(1).String(), ShouldEqual, "boolean") | ||||
| 		So(core.Type(2).String(), ShouldEqual, "int") | ||||
| 		So(core.Type(3).String(), ShouldEqual, "float") | ||||
| 		So(core.Type(4).String(), ShouldEqual, "string") | ||||
| 		So(core.Type(5).String(), ShouldEqual, "datetime") | ||||
| 		So(core.Type(6).String(), ShouldEqual, "array") | ||||
| 		So(core.Type(7).String(), ShouldEqual, "object") | ||||
| 		So(core.Type(8).String(), ShouldEqual, "HTMLElement") | ||||
| 		So(core.Type(9).String(), ShouldEqual, "HTMLDocument") | ||||
| 		So(core.Type(10).String(), ShouldEqual, "BinaryType") | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestIsTypeOf(t *testing.T) { | ||||
| 	Convey("Check type by value", t, func() { | ||||
|  | ||||
| 		So(core.IsTypeOf(values.None, core.NoneType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewBoolean(true), core.BooleanType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewInt(1), core.IntType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewFloat(1.1), core.FloatType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewString("test"), core.StringType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewDateTime(time.Now()), core.DateTimeType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewArray(1), core.ArrayType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewObject(), core.ObjectType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(&http.HTMLElement{}, core.HTMLElementType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(&http.HTMLDocument{}, core.HTMLDocumentType), ShouldBeTrue) | ||||
| 		So(core.IsTypeOf(values.NewBinary([]byte{}), core.BinaryType), ShouldBeTrue) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func TestValidateType(t *testing.T) { | ||||
| 	Convey("Value should match type", t, func() { | ||||
|  | ||||
| 		So(core.ValidateType(values.None, core.NoneType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewBoolean(true), core.BooleanType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewInt(1), core.IntType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewFloat(1.1), core.FloatType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewString("test"), core.StringType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewDateTime(time.Now()), core.DateTimeType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewArray(1), core.ArrayType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewObject(), core.ObjectType), ShouldBeNil) | ||||
| 		So(core.ValidateType(&http.HTMLElement{}, core.HTMLElementType), ShouldBeNil) | ||||
| 		So(core.ValidateType(&http.HTMLDocument{}, core.HTMLDocumentType), ShouldBeNil) | ||||
| 		So(core.ValidateType(values.NewBinary([]byte{}), core.BinaryType), ShouldBeNil) | ||||
| 	}) | ||||
|  | ||||
| 	Convey("Value should not match type", t, func() { | ||||
|  | ||||
| 		So(core.ValidateType(values.None, core.BooleanType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewBoolean(true), core.IntType, core.NoneType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewInt(1), core.NoneType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewFloat(1.1), core.StringType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewString("test"), core.IntType, core.FloatType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewDateTime(time.Now()), core.BooleanType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewArray(1), core.StringType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewObject(), core.BooleanType), ShouldBeError) | ||||
| 		So(core.ValidateType(&http.HTMLElement{}, core.ArrayType), ShouldBeError) | ||||
| 		So(core.ValidateType(&http.HTMLDocument{}, core.HTMLElementType), ShouldBeError) | ||||
| 		So(core.ValidateType(values.NewBinary([]byte{}), core.NoneType), ShouldBeError) | ||||
| 	}) | ||||
| } | ||||
| @@ -2,9 +2,11 @@ package clauses | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/collections" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type CollectIterator struct { | ||||
| @@ -59,7 +61,7 @@ func NewCollectIterator( | ||||
| } | ||||
|  | ||||
| func newGroupSorter(selector *CollectSelector) (*collections.Sorter, error) { | ||||
| 	return collections.NewSorter(func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 	return collections.NewSorter(func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 		f, err := selector.expression.Exec(ctx, first) | ||||
|  | ||||
| 		if err != nil { | ||||
| @@ -213,7 +215,7 @@ func (iterator *CollectIterator) group(ctx context.Context, scope *core.Scope) ( | ||||
| 			arr, ok := groupValue.(*values.Array) | ||||
|  | ||||
| 			if !ok { | ||||
| 				return nil, core.TypeError(groupValue.Type(), core.IntType) | ||||
| 				return nil, core.TypeError(groupValue.Type(), types.Int) | ||||
| 			} | ||||
|  | ||||
| 			value, err := proj.selector.expression.Exec(ctx, dataSourceScope) | ||||
| @@ -235,7 +237,7 @@ func (iterator *CollectIterator) group(ctx context.Context, scope *core.Scope) ( | ||||
| 			counter, ok := groupValue.(values.Int) | ||||
|  | ||||
| 			if !ok { | ||||
| 				return nil, core.TypeError(groupValue.Type(), core.IntType) | ||||
| 				return nil, core.TypeError(groupValue.Type(), types.Int) | ||||
| 			} | ||||
|  | ||||
| 			groupValue = counter + 1 | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package clauses | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/collections" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type LimitClause struct { | ||||
| @@ -71,13 +73,13 @@ func (clause *LimitClause) Iterate(ctx context.Context, scope *core.Scope) (coll | ||||
| } | ||||
|  | ||||
| func (clause *LimitClause) parseValue(val core.Value) (int, error) { | ||||
| 	if val.Type() == core.IntType { | ||||
| 	if val.Type() == types.Int { | ||||
| 		return val.Unwrap().(int), nil | ||||
| 	} | ||||
|  | ||||
| 	if val.Type() == core.FloatType { | ||||
| 	if val.Type() == types.Float { | ||||
| 		return int(val.Unwrap().(float64)), nil | ||||
| 	} | ||||
|  | ||||
| 	return -1, core.TypeError(val.Type(), core.IntType, core.FloatType) | ||||
| 	return -1, core.TypeError(val.Type(), types.Int, types.Float) | ||||
| } | ||||
|   | ||||
| @@ -71,7 +71,7 @@ func (clause *SortClause) Iterate(ctx context.Context, scope *core.Scope) (colle | ||||
| } | ||||
|  | ||||
| func newSorter(srt *SorterExpression) (*collections.Sorter, error) { | ||||
| 	return collections.NewSorter(func(ctx context.Context, first, second *core.Scope) (int, error) { | ||||
| 	return collections.NewSorter(func(ctx context.Context, first, second *core.Scope) (int64, error) { | ||||
| 		f, err := srt.expression.Exec(ctx, first) | ||||
|  | ||||
| 		if err != nil { | ||||
|   | ||||
| @@ -2,9 +2,11 @@ package expressions | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/collections" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type DataSource struct { | ||||
| @@ -44,11 +46,11 @@ func (ds *DataSource) Iterate(ctx context.Context, scope *core.Scope) (collectio | ||||
| 		} | ||||
|  | ||||
| 		switch data.Type() { | ||||
| 		case core.ArrayType: | ||||
| 		case types.Array: | ||||
| 			return collections.NewIndexedIterator(ds.valVariable, ds.keyVariable, data.(collections.IndexedCollection)) | ||||
| 		case core.ObjectType: | ||||
| 		case types.Object: | ||||
| 			return collections.NewKeyedIterator(ds.valVariable, ds.keyVariable, data.(collections.KeyedCollection)) | ||||
| 		case core.HTMLElementType, core.HTMLDocumentType: | ||||
| 		case types.HTMLElement, types.HTMLDocument: | ||||
| 			return collections.NewHTMLNodeIterator(ds.valVariable, ds.keyVariable, data.(values.HTMLNode)) | ||||
| 		default: | ||||
| 			// fallback to user defined types | ||||
| @@ -69,10 +71,10 @@ func (ds *DataSource) Iterate(ctx context.Context, scope *core.Scope) (collectio | ||||
| 			default: | ||||
| 				return nil, core.TypeError( | ||||
| 					data.Type(), | ||||
| 					core.ArrayType, | ||||
| 					core.ObjectType, | ||||
| 					core.HTMLDocumentType, | ||||
| 					core.HTMLElementType, | ||||
| 					types.Array, | ||||
| 					types.Object, | ||||
| 					types.HTMLDocument, | ||||
| 					types.HTMLElement, | ||||
| 				) | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -11,6 +11,8 @@ import ( | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| ) | ||||
|  | ||||
| var testIterableCollectionType = core.NewType("TestIterableCollection") | ||||
|  | ||||
| type ( | ||||
| 	testIterableCollection struct { | ||||
| 		values collections.IndexedCollection | ||||
| @@ -32,12 +34,12 @@ func (c *testIterableCollection) MarshalJSON() ([]byte, error) { | ||||
| 	return nil, core.ErrInvalidOperation | ||||
| } | ||||
| func (c *testIterableCollection) Type() core.Type { | ||||
| 	return core.Type(11) | ||||
| 	return testIterableCollectionType | ||||
| } | ||||
| func (c *testIterableCollection) String() string { | ||||
| 	return "" | ||||
| } | ||||
| func (c *testIterableCollection) Compare(other core.Value) int { | ||||
| func (c *testIterableCollection) Compare(other core.Value) int64 { | ||||
| 	return 1 | ||||
| } | ||||
| func (c *testIterableCollection) Unwrap() interface{} { | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package literals | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -49,8 +51,8 @@ func (l *ObjectLiteral) Exec(ctx context.Context, scope *core.Scope) (core.Value | ||||
| 			return values.None, err | ||||
| 		} | ||||
|  | ||||
| 		if name.Type() != core.StringType { | ||||
| 			return values.None, core.TypeError(name.Type(), core.StringType) | ||||
| 		if name.Type() != types.String { | ||||
| 			return values.None, core.TypeError(name.Type(), types.String) | ||||
| 		} | ||||
|  | ||||
| 		obj.Set(name.(values.String), val) | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package expressions | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
| @@ -46,7 +47,7 @@ func (e *MemberExpression) Exec(ctx context.Context, scope *core.Scope) (core.Va | ||||
| 		strPath[idx] = segment | ||||
| 	} | ||||
|  | ||||
| 	out, err := values.GetIn(val, strPath) | ||||
| 	out, err := values.GetIn(ctx, val, strPath) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, core.SourceError(e.src, err) | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package operators | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -88,7 +90,7 @@ func (operator *ArrayOperator) Exec(ctx context.Context, scope *core.Scope) (cor | ||||
| } | ||||
|  | ||||
| func (operator *ArrayOperator) Eval(ctx context.Context, left, right core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateType(left, core.ArrayType) | ||||
| 	err := core.ValidateType(left, types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		// TODO: Return the error? AQL just returns false | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package operators | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| ) | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package operators | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type InOperator struct { | ||||
| @@ -45,7 +47,7 @@ func (operator *InOperator) Exec(ctx context.Context, scope *core.Scope) (core.V | ||||
| } | ||||
|  | ||||
| func (operator *InOperator) Eval(_ context.Context, left, right core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateType(right, core.ArrayType) | ||||
| 	err := core.ValidateType(right, types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		// TODO: Return the error? AQL just returns false | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package operators | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -70,7 +72,7 @@ func (operator *LogicalOperator) Exec(ctx context.Context, scope *core.Scope) (c | ||||
| 	leftBool := values.ToBoolean(left) | ||||
|  | ||||
| 	if operator.value == LogicalOperatorTypeAnd && leftBool == values.False { | ||||
| 		if left.Type() == core.BooleanType { | ||||
| 		if left.Type() == types.Boolean { | ||||
| 			return values.False, nil | ||||
| 		} | ||||
|  | ||||
| @@ -98,7 +100,7 @@ func (operator *LogicalOperator) Eval(_ context.Context, left, right core.Value) | ||||
| 	leftBool := values.ToBoolean(left) | ||||
|  | ||||
| 	if operator.value == LogicalOperatorTypeAnd && leftBool == values.False { | ||||
| 		if left.Type() == core.BooleanType { | ||||
| 		if left.Type() == types.Boolean { | ||||
| 			return values.False, nil | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package operators | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -89,15 +91,15 @@ func Not(left, _ core.Value) core.Value { | ||||
| // Adds numbers | ||||
| // Concats strings | ||||
| func Add(left, right core.Value) core.Value { | ||||
| 	if left.Type() == core.IntType { | ||||
| 		if right.Type() == core.IntType { | ||||
| 	if left.Type() == types.Int { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| 			return l + r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.FloatType { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| @@ -105,15 +107,15 @@ func Add(left, right core.Value) core.Value { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 		if right.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| 			return l + r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.IntType { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| @@ -125,15 +127,15 @@ func Add(left, right core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Subtract(left, right core.Value) core.Value { | ||||
| 	if left.Type() == core.IntType { | ||||
| 		if right.Type() == core.IntType { | ||||
| 	if left.Type() == types.Int { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| 			return l - r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.FloatType { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| @@ -141,15 +143,15 @@ func Subtract(left, right core.Value) core.Value { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 		if right.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| 			return l - r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.IntType { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| @@ -161,15 +163,15 @@ func Subtract(left, right core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Multiply(left, right core.Value) core.Value { | ||||
| 	if left.Type() == core.IntType { | ||||
| 		if right.Type() == core.IntType { | ||||
| 	if left.Type() == types.Int { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| 			return l * r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.FloatType { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| @@ -177,15 +179,15 @@ func Multiply(left, right core.Value) core.Value { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 		if right.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| 			return l * r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.IntType { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| @@ -197,15 +199,15 @@ func Multiply(left, right core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Divide(left, right core.Value) core.Value { | ||||
| 	if left.Type() == core.IntType { | ||||
| 		if right.Type() == core.IntType { | ||||
| 	if left.Type() == types.Int { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| 			return l / r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.FloatType { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| @@ -213,15 +215,15 @@ func Divide(left, right core.Value) core.Value { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 		if right.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| 			return l / r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.IntType { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| @@ -233,15 +235,15 @@ func Divide(left, right core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Modulus(left, right core.Value) core.Value { | ||||
| 	if left.Type() == core.IntType { | ||||
| 		if right.Type() == core.IntType { | ||||
| 	if left.Type() == types.Int { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| 			return l % r | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.FloatType { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Int) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| @@ -249,15 +251,15 @@ func Modulus(left, right core.Value) core.Value { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 		if right.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		if right.Type() == types.Float { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Float) | ||||
|  | ||||
| 			return values.Int(l) % values.Int(r) | ||||
| 		} | ||||
|  | ||||
| 		if right.Type() == core.IntType { | ||||
| 		if right.Type() == types.Int { | ||||
| 			l := left.(values.Float) | ||||
| 			r := right.(values.Int) | ||||
|  | ||||
| @@ -269,13 +271,13 @@ func Modulus(left, right core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Increment(left, _ core.Value) core.Value { | ||||
| 	if left.Type() == core.IntType { | ||||
| 	if left.Type() == types.Int { | ||||
| 		l := left.(values.Int) | ||||
|  | ||||
| 		return l + 1 | ||||
| 	} | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		l := left.(values.Float) | ||||
|  | ||||
| 		return l + 1 | ||||
| @@ -285,13 +287,13 @@ func Increment(left, _ core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Decrement(left, _ core.Value) core.Value { | ||||
| 	if left.Type() == core.IntType { | ||||
| 	if left.Type() == types.Int { | ||||
| 		l := left.(values.Int) | ||||
|  | ||||
| 		return l - 1 | ||||
| 	} | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		l := left.(values.Float) | ||||
|  | ||||
| 		return l - 1 | ||||
| @@ -301,13 +303,13 @@ func Decrement(left, _ core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Negative(value, _ core.Value) core.Value { | ||||
| 	err := core.ValidateType(value, core.IntType, core.FloatType) | ||||
| 	err := core.ValidateType(value, types.Int, types.Float) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.ZeroInt | ||||
| 	} | ||||
|  | ||||
| 	if value.Type() == core.IntType { | ||||
| 	if value.Type() == types.Int { | ||||
| 		return -value.(values.Int) | ||||
| 	} | ||||
|  | ||||
| @@ -315,13 +317,13 @@ func Negative(value, _ core.Value) core.Value { | ||||
| } | ||||
|  | ||||
| func Positive(value, _ core.Value) core.Value { | ||||
| 	err := core.ValidateType(value, core.IntType, core.FloatType) | ||||
| 	err := core.ValidateType(value, types.Int, types.Float) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.ZeroInt | ||||
| 	} | ||||
|  | ||||
| 	if value.Type() == core.IntType { | ||||
| 	if value.Type() == types.Int { | ||||
| 		return +value.(values.Int) | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package operators | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type RangeOperator struct { | ||||
| @@ -43,13 +45,13 @@ func (operator *RangeOperator) Exec(ctx context.Context, scope *core.Scope) (cor | ||||
| } | ||||
|  | ||||
| func (operator *RangeOperator) Eval(_ context.Context, left, right core.Value) (core.Value, error) { | ||||
| 	err := core.ValidateType(left, core.IntType, core.FloatType) | ||||
| 	err := core.ValidateType(left, types.Int, types.Float) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, core.SourceError(operator.src, err) | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(right, core.IntType, core.FloatType) | ||||
| 	err = core.ValidateType(right, types.Int, types.Float) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, core.SourceError(operator.src, err) | ||||
| @@ -58,13 +60,13 @@ func (operator *RangeOperator) Eval(_ context.Context, left, right core.Value) ( | ||||
| 	var start int | ||||
| 	var end int | ||||
|  | ||||
| 	if left.Type() == core.FloatType { | ||||
| 	if left.Type() == types.Float { | ||||
| 		start = int(left.(values.Float)) | ||||
| 	} else { | ||||
| 		start = int(left.(values.Int)) | ||||
| 	} | ||||
|  | ||||
| 	if right.Type() == core.FloatType { | ||||
| 	if right.Type() == types.Float { | ||||
| 		end = int(right.(values.Float)) | ||||
| 	} else { | ||||
| 		end = int(right.(values.Int)) | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package operators | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| ) | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package expressions_test | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| @@ -41,7 +42,7 @@ func TestParameterExpressionExec(t *testing.T) { | ||||
| 		value, err := existExp.Exec(ctx, &core.Scope{}) | ||||
|  | ||||
| 		So(err, ShouldBeNil) | ||||
| 		So(value.Type(), ShouldEqual, core.IntType) | ||||
| 		So(value.Type().Equals(types.Int), ShouldBeTrue) | ||||
| 		So(value.String(), ShouldEqual, "1") | ||||
| 	}) | ||||
|  | ||||
| @@ -57,6 +58,6 @@ func TestParameterExpressionExec(t *testing.T) { | ||||
|  | ||||
| 		So(err, ShouldNotBeNil) | ||||
| 		So(err, ShouldHaveSameTypeAs, core.ErrNotFound) | ||||
| 		So(value.Type(), ShouldEqual, core.NoneType) | ||||
| 		So(value.Type().Equals(types.None), ShouldBeTrue) | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"sort" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| @@ -32,7 +33,7 @@ func (t *Array) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t *Array) Type() core.Type { | ||||
| 	return core.ArrayType | ||||
| 	return types.Array | ||||
| } | ||||
|  | ||||
| func (t *Array) String() string { | ||||
| @@ -45,22 +46,23 @@ func (t *Array) String() string { | ||||
| 	return string(marshaled) | ||||
| } | ||||
|  | ||||
| func (t *Array) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.ArrayType: | ||||
| func (t *Array) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.Array { | ||||
| 		other := other.(*Array) | ||||
|  | ||||
| 		if t.Length() == 0 && other.Length() == 0 { | ||||
| 			return 0 | ||||
| 		} | ||||
|  | ||||
| 		if t.Length() < other.Length() { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		if t.Length() > other.Length() { | ||||
| 			return 1 | ||||
| 		} | ||||
|  | ||||
| 		var res = 0 | ||||
| 		var res int64 | ||||
| 		var val core.Value | ||||
|  | ||||
| 		other.ForEach(func(otherVal core.Value, idx int) bool { | ||||
| @@ -71,11 +73,9 @@ func (t *Array) Compare(other core.Value) int { | ||||
| 		}) | ||||
|  | ||||
| 		return res | ||||
| 	case core.ObjectType: | ||||
| 		return -1 | ||||
| 	default: | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.Array, other.Type()) | ||||
| } | ||||
|  | ||||
| func (t *Array) Unwrap() interface{} { | ||||
| @@ -216,9 +216,13 @@ func (t *Array) Clone() core.Cloneable { | ||||
| 	var value core.Value | ||||
| 	for idx := NewInt(0); idx < t.Length(); idx++ { | ||||
| 		value = t.Get(idx) | ||||
| 		if IsCloneable(value) { | ||||
| 			value = value.(core.Cloneable).Clone() | ||||
|  | ||||
| 		cloneable, ok := value.(core.Cloneable) | ||||
|  | ||||
| 		if ok { | ||||
| 			value = cloneable.Clone() | ||||
| 		} | ||||
|  | ||||
| 		cloned.Push(value) | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package values_test | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| @@ -56,7 +57,7 @@ func TestArray(t *testing.T) { | ||||
| 		Convey("Should return type", func() { | ||||
| 			arr := values.NewArray(1) | ||||
|  | ||||
| 			So(arr.Type(), ShouldEqual, core.ArrayType) | ||||
| 			So(arr.Type().Equals(types.Array), ShouldBeTrue) | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"io/ioutil" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type Binary []byte | ||||
| @@ -30,17 +31,16 @@ func (b Binary) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (b Binary) Type() core.Type { | ||||
| 	return core.BinaryType | ||||
| 	return types.Binary | ||||
| } | ||||
|  | ||||
| func (b Binary) String() string { | ||||
| 	return string(b) | ||||
| } | ||||
|  | ||||
| func (b Binary) Compare(other core.Value) int { | ||||
| 	// TODO: Lame comparison, need to think more about it | ||||
| 	switch other.Type() { | ||||
| 	case core.BooleanType: | ||||
| func (b Binary) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.Binary { | ||||
| 		// TODO: Lame comparison, need to think more about it | ||||
| 		b2 := other.(*Binary) | ||||
|  | ||||
| 		if b2.Length() == b.Length() { | ||||
| @@ -52,9 +52,9 @@ func (b Binary) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return -1 | ||||
| 	default: | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.Binary, other.Type()) | ||||
| } | ||||
|  | ||||
| func (b Binary) Unwrap() interface{} { | ||||
|   | ||||
| @@ -6,12 +6,15 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type Boolean bool | ||||
|  | ||||
| var False = Boolean(false) | ||||
| var True = Boolean(true) | ||||
| const ( | ||||
| 	False = Boolean(false) | ||||
| 	True  = Boolean(true) | ||||
| ) | ||||
|  | ||||
| func NewBoolean(input bool) Boolean { | ||||
| 	return Boolean(input) | ||||
| @@ -60,7 +63,7 @@ func (t Boolean) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t Boolean) Type() core.Type { | ||||
| 	return core.BooleanType | ||||
| 	return types.Boolean | ||||
| } | ||||
|  | ||||
| func (t Boolean) String() string { | ||||
| @@ -71,11 +74,10 @@ func (t Boolean) String() string { | ||||
| 	return "false" | ||||
| } | ||||
|  | ||||
| func (t Boolean) Compare(other core.Value) int { | ||||
| func (t Boolean) Compare(other core.Value) int64 { | ||||
| 	raw := bool(t) | ||||
|  | ||||
| 	switch other.Type() { | ||||
| 	case core.BooleanType: | ||||
| 	if types.Boolean.Equals(other.Type()) { | ||||
| 		i := other.Unwrap().(bool) | ||||
|  | ||||
| 		if raw == i { | ||||
| @@ -87,11 +89,9 @@ func (t Boolean) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return +1 | ||||
| 	case core.NoneType: | ||||
| 		return 1 | ||||
| 	default: | ||||
| 		return -1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.Boolean, other.Type()) | ||||
| } | ||||
|  | ||||
| func (t Boolean) Unwrap() interface{} { | ||||
|   | ||||
| @@ -3,6 +3,7 @@ package values_test | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| 	"testing" | ||||
| ) | ||||
| @@ -21,7 +22,7 @@ func TestBoolean(t *testing.T) { | ||||
|  | ||||
| 	Convey(".Type", t, func() { | ||||
| 		Convey("Should return a type", func() { | ||||
| 			So(values.True.Type(), ShouldEqual, core.BooleanType) | ||||
| 			So(values.True.Type().Equals(types.Boolean), ShouldBeTrue) | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| const DefaultTimeLayout = time.RFC3339 | ||||
| @@ -59,16 +60,15 @@ func (t DateTime) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t DateTime) Type() core.Type { | ||||
| 	return core.DateTimeType | ||||
| 	return types.DateTime | ||||
| } | ||||
|  | ||||
| func (t DateTime) String() string { | ||||
| 	return t.Time.String() | ||||
| } | ||||
|  | ||||
| func (t DateTime) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.DateTimeType: | ||||
| func (t DateTime) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.DateTime { | ||||
| 		other := other.(DateTime) | ||||
|  | ||||
| 		if t.After(other.Time) { | ||||
| @@ -80,13 +80,9 @@ func (t DateTime) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return 0 | ||||
| 	default: | ||||
| 		if other.Type() > core.DateTimeType { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.DateTime, other.Type()) | ||||
| } | ||||
|  | ||||
| func (t DateTime) Unwrap() interface{} { | ||||
|   | ||||
| @@ -9,11 +9,12 @@ import ( | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type Float float64 | ||||
|  | ||||
| var ZeroFloat = Float(0.0) | ||||
| const ZeroFloat = Float(0.0) | ||||
|  | ||||
| func NewFloat(input float64) Float { | ||||
| 	return Float(input) | ||||
| @@ -75,18 +76,18 @@ func (t Float) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t Float) Type() core.Type { | ||||
| 	return core.FloatType | ||||
| 	return types.Float | ||||
| } | ||||
|  | ||||
| func (t Float) String() string { | ||||
| 	return fmt.Sprintf("%f", t) | ||||
| } | ||||
|  | ||||
| func (t Float) Compare(other core.Value) int { | ||||
| func (t Float) Compare(other core.Value) int64 { | ||||
| 	otherType := other.Type() | ||||
| 	raw := float64(t) | ||||
|  | ||||
| 	switch other.Type() { | ||||
| 	case core.FloatType: | ||||
| 	if otherType == types.Float { | ||||
| 		f := other.Unwrap().(float64) | ||||
|  | ||||
| 		if raw == f { | ||||
| @@ -98,7 +99,9 @@ func (t Float) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return +1 | ||||
| 	case core.IntType: | ||||
| 	} | ||||
|  | ||||
| 	if otherType == types.Int { | ||||
| 		i := other.Unwrap().(int) | ||||
| 		f := float64(i) | ||||
|  | ||||
| @@ -111,11 +114,9 @@ func (t Float) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return +1 | ||||
| 	case core.BooleanType, core.NoneType: | ||||
| 		return 1 | ||||
| 	default: | ||||
| 		return -1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.Float, otherType) | ||||
| } | ||||
|  | ||||
| func (t Float) Unwrap() interface{} { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package values | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"encoding/binary" | ||||
| 	"encoding/json" | ||||
| 	"hash/fnv" | ||||
| @@ -9,9 +10,10 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| func GetIn(from core.Value, byPath []core.Value) (core.Value, error) { | ||||
| func GetIn(ctx context.Context, from core.Value, byPath []core.Value) (core.Value, error) { | ||||
| 	if byPath == nil || len(byPath) == 0 { | ||||
| 		return None, nil | ||||
| 	} | ||||
| @@ -27,32 +29,32 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) { | ||||
| 		segmentType := segment.Type() | ||||
|  | ||||
| 		switch result.Type() { | ||||
| 		case core.ObjectType: | ||||
| 		case types.Object: | ||||
| 			obj := result.(*Object) | ||||
|  | ||||
| 			if segmentType != core.StringType { | ||||
| 				return nil, core.TypeError(segmentType, core.StringType) | ||||
| 			if segmentType != types.String { | ||||
| 				return nil, core.TypeError(segmentType, types.String) | ||||
| 			} | ||||
|  | ||||
| 			result, _ = obj.Get(segment.(String)) | ||||
|  | ||||
| 			break | ||||
| 		case core.ArrayType: | ||||
| 		case types.Array: | ||||
| 			arr := result.(*Array) | ||||
|  | ||||
| 			if segmentType != core.IntType { | ||||
| 				return nil, core.TypeError(segmentType, core.IntType) | ||||
| 			if segmentType != types.Int { | ||||
| 				return nil, core.TypeError(segmentType, types.Int) | ||||
| 			} | ||||
|  | ||||
| 			result = arr.Get(segment.(Int)) | ||||
|  | ||||
| 			break | ||||
| 		case core.HTMLElementType, core.HTMLDocumentType: | ||||
| 		case types.HTMLElement, types.HTMLDocument: | ||||
| 			el := result.(HTMLNode) | ||||
|  | ||||
| 			if segmentType == core.IntType { | ||||
| 			if segmentType == types.Int { | ||||
| 				result = el.GetChildNode(segment.(Int)) | ||||
| 			} else if segmentType == core.StringType { | ||||
| 			} else if segmentType == types.String { | ||||
| 				strSegment := segment.(String) | ||||
|  | ||||
| 				switch strSegment { | ||||
| @@ -73,7 +75,7 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) { | ||||
| 				case "length": | ||||
| 					result = el.Length() | ||||
| 				case "url": | ||||
| 					if result.Type() == core.HTMLDocumentType { | ||||
| 					if result.Type() == types.HTMLDocument { | ||||
| 						doc, ok := result.(HTMLDocument) | ||||
|  | ||||
| 						if ok { | ||||
| @@ -88,22 +90,22 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) { | ||||
| 					return None, err | ||||
| 				} | ||||
| 			} else { | ||||
| 				return nil, core.TypeError(segmentType, core.IntType, core.StringType) | ||||
| 				return nil, core.TypeError(segmentType, types.Int, types.String) | ||||
| 			} | ||||
|  | ||||
| 		default: | ||||
| 			getter, ok := result.(core.Getter) | ||||
|  | ||||
| 			if ok { | ||||
| 				return getter.GetIn(byPath[i:]) | ||||
| 				return getter.GetIn(ctx, byPath[i:]) | ||||
| 			} | ||||
|  | ||||
| 			return None, core.TypeError( | ||||
| 				from.Type(), | ||||
| 				core.ArrayType, | ||||
| 				core.ObjectType, | ||||
| 				core.HTMLDocumentType, | ||||
| 				core.HTMLElementType, | ||||
| 				types.Array, | ||||
| 				types.Object, | ||||
| 				types.HTMLDocument, | ||||
| 				types.HTMLElement, | ||||
| 			) | ||||
| 		} | ||||
| 	} | ||||
| @@ -111,7 +113,7 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) { | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| func SetIn(to core.Value, byPath []core.Value, value core.Value) error { | ||||
| func SetIn(ctx context.Context, to core.Value, byPath []core.Value, value core.Value) error { | ||||
| 	if byPath == nil || len(byPath) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| @@ -126,11 +128,11 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error { | ||||
| 		segmentType := segment.Type() | ||||
|  | ||||
| 		switch parent.Type() { | ||||
| 		case core.ObjectType: | ||||
| 		case types.Object: | ||||
| 			parent := parent.(*Object) | ||||
|  | ||||
| 			if segmentType != core.StringType { | ||||
| 				return core.TypeError(segmentType, core.StringType) | ||||
| 			if segmentType != types.String { | ||||
| 				return core.TypeError(segmentType, types.String) | ||||
| 			} | ||||
|  | ||||
| 			if isTarget == false { | ||||
| @@ -140,9 +142,9 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error { | ||||
| 			} | ||||
|  | ||||
| 			break | ||||
| 		case core.ArrayType: | ||||
| 			if segmentType != core.IntType { | ||||
| 				return core.TypeError(segmentType, core.IntType) | ||||
| 		case types.Array: | ||||
| 			if segmentType != types.Int { | ||||
| 				return core.TypeError(segmentType, types.Int) | ||||
| 			} | ||||
|  | ||||
| 			parent := parent.(*Array) | ||||
| @@ -160,19 +162,19 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error { | ||||
| 			setter, ok := parent.(core.Setter) | ||||
|  | ||||
| 			if ok { | ||||
| 				return setter.SetIn(byPath[idx:], value) | ||||
| 				return setter.SetIn(ctx, byPath[idx:], value) | ||||
| 			} | ||||
|  | ||||
| 			// redefine parent | ||||
| 			isArray := segmentType == core.IntType | ||||
| 			isArray := segmentType == types.Int | ||||
|  | ||||
| 			// it's not an index | ||||
| 			if isArray == false { | ||||
| 				obj := NewObject() | ||||
| 				parent = obj | ||||
|  | ||||
| 				if segmentType != core.StringType { | ||||
| 					return core.TypeError(segmentType, core.StringType) | ||||
| 				if segmentType != types.String { | ||||
| 					return core.TypeError(segmentType, types.String) | ||||
| 				} | ||||
|  | ||||
| 				if isTarget { | ||||
| @@ -190,7 +192,7 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error { | ||||
| 			} | ||||
|  | ||||
| 			// set new parent | ||||
| 			if err := SetIn(to, byPath[0:idx-1], parent); err != nil { | ||||
| 			if err := SetIn(ctx, to, byPath[0:idx-1], parent); err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| @@ -302,9 +304,9 @@ func Unmarshal(value json.RawMessage) (core.Value, error) { | ||||
|  | ||||
| func IsCloneable(value core.Value) Boolean { | ||||
| 	switch value.Type() { | ||||
| 	case core.ArrayType: | ||||
| 	case types.Array: | ||||
| 		return NewBoolean(true) | ||||
| 	case core.ObjectType: | ||||
| 	case types.Object: | ||||
| 		return NewBoolean(true) | ||||
| 	default: | ||||
| 		return NewBoolean(false) | ||||
| @@ -313,15 +315,15 @@ func IsCloneable(value core.Value) Boolean { | ||||
|  | ||||
| func ToBoolean(input core.Value) core.Value { | ||||
| 	switch input.Type() { | ||||
| 	case core.BooleanType: | ||||
| 	case types.Boolean: | ||||
| 		return input | ||||
| 	case core.NoneType: | ||||
| 	case types.None: | ||||
| 		return False | ||||
| 	case core.StringType: | ||||
| 	case types.String: | ||||
| 		return NewBoolean(input.String() != "") | ||||
| 	case core.IntType: | ||||
| 	case types.Int: | ||||
| 		return NewBoolean(input.(Int) != 0) | ||||
| 	case core.FloatType: | ||||
| 	case types.Float: | ||||
| 		return NewBoolean(input.(Float) != 0) | ||||
| 	default: | ||||
| 		return True | ||||
| @@ -330,15 +332,15 @@ func ToBoolean(input core.Value) core.Value { | ||||
|  | ||||
| func ToArray(input core.Value) core.Value { | ||||
| 	switch input.Type() { | ||||
| 	case core.BooleanType, | ||||
| 		core.IntType, | ||||
| 		core.FloatType, | ||||
| 		core.StringType, | ||||
| 		core.DateTimeType: | ||||
| 	case types.Boolean, | ||||
| 		types.Int, | ||||
| 		types.Float, | ||||
| 		types.String, | ||||
| 		types.DateTime: | ||||
|  | ||||
| 		return NewArrayWith(input) | ||||
| 	case core.HTMLElementType, | ||||
| 		core.HTMLDocumentType: | ||||
| 	case types.HTMLElement, | ||||
| 		types.HTMLDocument: | ||||
| 		val := input.(HTMLNode) | ||||
| 		attrs := val.GetAttributes() | ||||
|  | ||||
| @@ -357,9 +359,9 @@ func ToArray(input core.Value) core.Value { | ||||
| 		}) | ||||
|  | ||||
| 		return obj | ||||
| 	case core.ArrayType: | ||||
| 	case types.Array: | ||||
| 		return input.Copy() | ||||
| 	case core.ObjectType: | ||||
| 	case types.Object: | ||||
| 		obj, ok := input.(*Object) | ||||
|  | ||||
| 		if !ok { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package values_test | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"testing" | ||||
| @@ -8,39 +9,41 @@ import ( | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| ) | ||||
|  | ||||
| type CustomType struct { | ||||
| var CustomType = core.NewType("custom") | ||||
|  | ||||
| type CustomValue struct { | ||||
| 	properties map[core.Value]core.Value | ||||
| } | ||||
|  | ||||
| func (t *CustomType) MarshalJSON() ([]byte, error) { | ||||
| func (t *CustomValue) MarshalJSON() ([]byte, error) { | ||||
| 	return nil, core.ErrNotImplemented | ||||
| } | ||||
|  | ||||
| func (t *CustomType) Type() core.Type { | ||||
| 	return core.CustomType | ||||
| func (t *CustomValue) Type() core.Type { | ||||
| 	return CustomType | ||||
| } | ||||
|  | ||||
| func (t *CustomType) String() string { | ||||
| func (t *CustomValue) String() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (t *CustomType) Compare(other core.Value) int { | ||||
| func (t *CustomValue) Compare(other core.Value) int64 { | ||||
| 	return other.Compare(t) * -1 | ||||
| } | ||||
|  | ||||
| func (t *CustomType) Unwrap() interface{} { | ||||
| func (t *CustomValue) Unwrap() interface{} { | ||||
| 	return t | ||||
| } | ||||
|  | ||||
| func (t *CustomType) Hash() uint64 { | ||||
| func (t *CustomValue) Hash() uint64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (t *CustomType) Copy() core.Value { | ||||
| func (t *CustomValue) Copy() core.Value { | ||||
| 	return values.None | ||||
| } | ||||
|  | ||||
| func (t *CustomType) GetIn(path []core.Value) (core.Value, error) { | ||||
| func (t *CustomValue) GetIn(ctx context.Context, path []core.Value) (core.Value, error) { | ||||
| 	if path == nil || len(path) == 0 { | ||||
| 		return values.None, nil | ||||
| 	} | ||||
| @@ -56,10 +59,10 @@ func (t *CustomType) GetIn(path []core.Value) (core.Value, error) { | ||||
| 		return propValue, nil | ||||
| 	} | ||||
|  | ||||
| 	return values.GetIn(propValue, path[1:]) | ||||
| 	return values.GetIn(ctx, propValue, path[1:]) | ||||
| } | ||||
|  | ||||
| func (t *CustomType) SetIn(path []core.Value, value core.Value) error { | ||||
| func (t *CustomValue) SetIn(ctx context.Context, path []core.Value, value core.Value) error { | ||||
| 	if path == nil || len(path) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| @@ -77,17 +80,17 @@ func (t *CustomType) SetIn(path []core.Value, value core.Value) error { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return values.SetIn(propValue, path[1:], value) | ||||
| 	return values.SetIn(ctx, propValue, path[1:], value) | ||||
| } | ||||
|  | ||||
| func TestHelpers(t *testing.T) { | ||||
| 	Convey("Helpers", t, func() { | ||||
| 		Convey("Getter", func() { | ||||
| 			Convey("It should get a value by a given path", func() { | ||||
| 				ct := &CustomType{ | ||||
| 				ct := &CustomValue{ | ||||
| 					properties: map[core.Value]core.Value{ | ||||
| 						values.NewString("foo"): values.NewInt(1), | ||||
| 						values.NewString("bar"): &CustomType{ | ||||
| 						values.NewString("bar"): &CustomValue{ | ||||
| 							properties: map[core.Value]core.Value{ | ||||
| 								values.NewString("qaz"): values.NewInt(2), | ||||
| 							}, | ||||
| @@ -95,14 +98,16 @@ func TestHelpers(t *testing.T) { | ||||
| 					}, | ||||
| 				} | ||||
|  | ||||
| 				foo, err := values.GetIn(ct, []core.Value{ | ||||
| 				ctx := context.Background() | ||||
|  | ||||
| 				foo, err := values.GetIn(ctx, ct, []core.Value{ | ||||
| 					values.NewString("foo"), | ||||
| 				}) | ||||
|  | ||||
| 				So(err, ShouldBeNil) | ||||
| 				So(foo, ShouldEqual, values.NewInt(1)) | ||||
|  | ||||
| 				qaz, err := values.GetIn(ct, []core.Value{ | ||||
| 				qaz, err := values.GetIn(ctx, ct, []core.Value{ | ||||
| 					values.NewString("bar"), | ||||
| 					values.NewString("qaz"), | ||||
| 				}) | ||||
| @@ -114,10 +119,10 @@ func TestHelpers(t *testing.T) { | ||||
|  | ||||
| 		Convey("Setter", func() { | ||||
| 			Convey("It should get a value by a given path", func() { | ||||
| 				ct := &CustomType{ | ||||
| 				ct := &CustomValue{ | ||||
| 					properties: map[core.Value]core.Value{ | ||||
| 						values.NewString("foo"): values.NewInt(1), | ||||
| 						values.NewString("bar"): &CustomType{ | ||||
| 						values.NewString("bar"): &CustomValue{ | ||||
| 							properties: map[core.Value]core.Value{ | ||||
| 								values.NewString("qaz"): values.NewInt(2), | ||||
| 							}, | ||||
| @@ -125,21 +130,23 @@ func TestHelpers(t *testing.T) { | ||||
| 					}, | ||||
| 				} | ||||
|  | ||||
| 				err := values.SetIn(ct, []core.Value{ | ||||
| 				ctx := context.Background() | ||||
|  | ||||
| 				err := values.SetIn(ctx, ct, []core.Value{ | ||||
| 					values.NewString("foo"), | ||||
| 				}, values.NewInt(2)) | ||||
|  | ||||
| 				So(err, ShouldBeNil) | ||||
| 				So(ct.properties[values.NewString("foo")], ShouldEqual, values.NewInt(2)) | ||||
|  | ||||
| 				err = values.SetIn(ct, []core.Value{ | ||||
| 				err = values.SetIn(ctx, ct, []core.Value{ | ||||
| 					values.NewString("bar"), | ||||
| 					values.NewString("qaz"), | ||||
| 				}, values.NewString("foobar")) | ||||
|  | ||||
| 				So(err, ShouldBeNil) | ||||
|  | ||||
| 				qaz, err := values.GetIn(ct, []core.Value{ | ||||
| 				qaz, err := values.GetIn(ctx, ct, []core.Value{ | ||||
| 					values.NewString("bar"), | ||||
| 					values.NewString("qaz"), | ||||
| 				}) | ||||
|   | ||||
| @@ -7,11 +7,12 @@ import ( | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type Int int64 | ||||
|  | ||||
| var ZeroInt = Int(0) | ||||
| const ZeroInt = Int(0) | ||||
|  | ||||
| func NewInt(input int) Int { | ||||
| 	return Int(int64(input)) | ||||
| @@ -65,16 +66,17 @@ func (t Int) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t Int) Type() core.Type { | ||||
| 	return core.IntType | ||||
| 	return types.Int | ||||
| } | ||||
|  | ||||
| func (t Int) String() string { | ||||
| 	return strconv.Itoa(int(t)) | ||||
| } | ||||
|  | ||||
| func (t Int) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.IntType: | ||||
| func (t Int) Compare(other core.Value) int64 { | ||||
| 	otherType := other.Type() | ||||
|  | ||||
| 	if otherType == types.Int { | ||||
| 		i := other.(Int) | ||||
|  | ||||
| 		if t == i { | ||||
| @@ -86,7 +88,9 @@ func (t Int) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return +1 | ||||
| 	case core.FloatType: | ||||
| 	} | ||||
|  | ||||
| 	if otherType == types.Float { | ||||
| 		f := other.(Float) | ||||
| 		f2 := Float(t) | ||||
|  | ||||
| @@ -99,11 +103,9 @@ func (t Int) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return +1 | ||||
| 	case core.BooleanType, core.NoneType: | ||||
| 		return 1 | ||||
| 	default: | ||||
| 		return -1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.Int, otherType) | ||||
| } | ||||
|  | ||||
| func (t Int) Unwrap() interface{} { | ||||
|   | ||||
| @@ -2,6 +2,7 @@ package values | ||||
|  | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type none struct{} | ||||
| @@ -13,20 +14,19 @@ func (t *none) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t *none) Type() core.Type { | ||||
| 	return core.NoneType | ||||
| 	return types.None | ||||
| } | ||||
|  | ||||
| func (t *none) String() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (t *none) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.NoneType: | ||||
| func (t *none) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.None { | ||||
| 		return 0 | ||||
| 	default: | ||||
| 		return -1 | ||||
| 	} | ||||
|  | ||||
| 	return -1 | ||||
| } | ||||
|  | ||||
| func (t *none) Unwrap() interface{} { | ||||
|   | ||||
| @@ -7,14 +7,17 @@ import ( | ||||
| 	"sort" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type ( | ||||
| 	ObjectPredicate = func(value core.Value, key string) bool | ||||
| 	ObjectProperty  struct { | ||||
|  | ||||
| 	ObjectProperty struct { | ||||
| 		key   string | ||||
| 		value core.Value | ||||
| 	} | ||||
|  | ||||
| 	Object struct { | ||||
| 		value map[string]core.Value | ||||
| 	} | ||||
| @@ -43,7 +46,7 @@ func (t *Object) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t *Object) Type() core.Type { | ||||
| 	return core.ObjectType | ||||
| 	return types.Object | ||||
| } | ||||
|  | ||||
| func (t *Object) String() string { | ||||
| @@ -59,22 +62,23 @@ func (t *Object) String() string { | ||||
| // Compare compares the source object with other core.Value | ||||
| // The behavior of the Compare is similar | ||||
| // to the comparison of objects in ArangoDB | ||||
| func (t *Object) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.ObjectType: | ||||
| func (t *Object) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == t.Type() { | ||||
| 		other := other.(*Object) | ||||
|  | ||||
| 		if t.Length() == 0 && other.Length() == 0 { | ||||
| 			return 0 | ||||
| 		} | ||||
|  | ||||
| 		if t.Length() < other.Length() { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		if t.Length() > other.Length() { | ||||
| 			return 1 | ||||
| 		} | ||||
|  | ||||
| 		var res = 0 | ||||
| 		var res int64 | ||||
|  | ||||
| 		sortedT := sort.StringSlice(t.Keys()) | ||||
| 		sortedT.Sort() | ||||
| @@ -92,6 +96,7 @@ func (t *Object) Compare(other core.Value) int { | ||||
| 				tVal, _ = t.Get(NewString(tKey)) | ||||
| 				otherVal, _ = other.Get(NewString(tKey)) | ||||
| 				res = tVal.Compare(otherVal) | ||||
|  | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| @@ -105,9 +110,9 @@ func (t *Object) Compare(other core.Value) int { | ||||
| 		} | ||||
|  | ||||
| 		return res | ||||
| 	default: | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.Object, other.Type()) | ||||
| } | ||||
|  | ||||
| func (t *Object) Unwrap() interface{} { | ||||
| @@ -201,10 +206,6 @@ func (t *Object) Get(key String) (core.Value, Boolean) { | ||||
| 	return None, NewBoolean(found) | ||||
| } | ||||
|  | ||||
| func (t *Object) GetIn(path []core.Value) (core.Value, error) { | ||||
| 	return GetIn(t, path) | ||||
| } | ||||
|  | ||||
| func (t *Object) Set(key String, value core.Value) { | ||||
| 	if value != nil { | ||||
| 		t.value[string(key)] = value | ||||
| @@ -217,20 +218,20 @@ func (t *Object) Remove(key String) { | ||||
| 	delete(t.value, string(key)) | ||||
| } | ||||
|  | ||||
| func (t *Object) SetIn(path []core.Value, value core.Value) error { | ||||
| 	return SetIn(t, path, value) | ||||
| } | ||||
|  | ||||
| func (t *Object) Clone() core.Cloneable { | ||||
| 	cloned := NewObject() | ||||
|  | ||||
| 	var value core.Value | ||||
| 	var keyString String | ||||
|  | ||||
| 	for key := range t.value { | ||||
| 		keyString = NewString(key) | ||||
| 		value, _ = t.Get(keyString) | ||||
| 		if IsCloneable(value) { | ||||
| 			value = value.(core.Cloneable).Clone() | ||||
|  | ||||
| 		cloneable, ok := value.(core.Cloneable) | ||||
|  | ||||
| 		if ok { | ||||
| 			value = cloneable.Clone() | ||||
| 		} | ||||
| 		cloned.Set(keyString, value) | ||||
| 	} | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package values_test | ||||
|  | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| @@ -63,7 +64,7 @@ func TestObject(t *testing.T) { | ||||
| 		Convey("Should return type", func() { | ||||
| 			obj := values.NewObject() | ||||
|  | ||||
| 			So(obj.Type(), ShouldEqual, core.ObjectType) | ||||
| 			So(obj.Type().Equals(types.Object), ShouldBeTrue) | ||||
| 		}) | ||||
| 	}) | ||||
|  | ||||
|   | ||||
| @@ -7,12 +7,15 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type String string | ||||
|  | ||||
| var EmptyString = String("") | ||||
| var SpaceString = String(" ") | ||||
| const ( | ||||
| 	EmptyString = String("") | ||||
| 	SpaceString = String(" ") | ||||
| ) | ||||
|  | ||||
| func NewString(input string) String { | ||||
| 	if input == "" { | ||||
| @@ -69,24 +72,19 @@ func (t String) MarshalJSON() ([]byte, error) { | ||||
| } | ||||
|  | ||||
| func (t String) Type() core.Type { | ||||
| 	return core.StringType | ||||
| 	return types.String | ||||
| } | ||||
|  | ||||
| func (t String) String() string { | ||||
| 	return string(t) | ||||
| } | ||||
|  | ||||
| func (t String) Compare(other core.Value) int { | ||||
| 	switch other.Type() { | ||||
| 	case core.StringType: | ||||
| 		return strings.Compare(string(t), other.Unwrap().(string)) | ||||
| 	default: | ||||
| 		if other.Type() > core.DateTimeType { | ||||
| 			return -1 | ||||
| 		} | ||||
|  | ||||
| 		return 1 | ||||
| func (t String) Compare(other core.Value) int64 { | ||||
| 	if other.Type() == types.String { | ||||
| 		return int64(strings.Compare(string(t), other.Unwrap().(string))) | ||||
| 	} | ||||
|  | ||||
| 	return types.Compare(types.String, other.Type()) | ||||
| } | ||||
|  | ||||
| func (t String) Unwrap() interface{} { | ||||
|   | ||||
							
								
								
									
										44
									
								
								pkg/runtime/values/types/helpers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								pkg/runtime/values/types/helpers.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| package types | ||||
|  | ||||
| import "github.com/MontFerret/ferret/pkg/runtime/core" | ||||
|  | ||||
| // Comparison table of builtin types | ||||
| var typeComparisonTable = map[core.Type]uint64{ | ||||
| 	None:         0, | ||||
| 	Boolean:      1, | ||||
| 	Int:          2, | ||||
| 	Float:        3, | ||||
| 	String:       4, | ||||
| 	DateTime:     5, | ||||
| 	Array:        6, | ||||
| 	Object:       7, | ||||
| 	HTMLElement:  8, | ||||
| 	HTMLDocument: 9, | ||||
| 	Binary:       10, | ||||
| } | ||||
|  | ||||
| func Compare(first, second core.Type) int64 { | ||||
| 	f, ok := typeComparisonTable[first] | ||||
|  | ||||
| 	// custom type | ||||
| 	if !ok { | ||||
| 		return -1 | ||||
| 	} | ||||
|  | ||||
| 	s, ok := typeComparisonTable[second] | ||||
|  | ||||
| 	// custom type | ||||
| 	if !ok { | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	if f == s { | ||||
| 		return 0 | ||||
| 	} | ||||
|  | ||||
| 	if f > s { | ||||
| 		return 1 | ||||
| 	} | ||||
|  | ||||
| 	return -1 | ||||
| } | ||||
							
								
								
									
										176
									
								
								pkg/runtime/values/types/helpers_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								pkg/runtime/values/types/helpers_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| package types_test | ||||
|  | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| func TestHelpers(t *testing.T) { | ||||
| 	Convey("Compare", t, func() { | ||||
| 		typesList := []core.Type{ | ||||
| 			types.None, | ||||
| 			types.Boolean, | ||||
| 			types.Int, | ||||
| 			types.Float, | ||||
| 			types.String, | ||||
| 			types.DateTime, | ||||
| 			types.Array, | ||||
| 			types.Object, | ||||
| 			types.Binary, | ||||
| 		} | ||||
|  | ||||
| 		Convey("None", func() { | ||||
| 			So(types.Compare(types.None, types.None), ShouldEqual, 0) | ||||
|  | ||||
| 			for _, t := range typesList[1:] { | ||||
| 				So(types.Compare(types.None, t), ShouldEqual, -1) | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("Boolean", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.None.ID(): | ||||
| 					So(types.Compare(types.Boolean, t), ShouldEqual, 1) | ||||
| 				case types.Boolean.ID(): | ||||
| 					So(types.Compare(types.Boolean, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.Boolean, t), ShouldEqual, -1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("Int", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.None.ID(): | ||||
| 					So(types.Compare(types.Int, t), ShouldEqual, 1) | ||||
| 				case types.Boolean.ID(): | ||||
| 					So(types.Compare(types.Int, t), ShouldEqual, 1) | ||||
| 				case types.Int.ID(): | ||||
| 					So(types.Compare(types.Int, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.Int, t), ShouldEqual, -1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("Float", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.None.ID(): | ||||
| 					So(types.Compare(types.Float, t), ShouldEqual, 1) | ||||
| 				case types.Boolean.ID(): | ||||
| 					So(types.Compare(types.Float, t), ShouldEqual, 1) | ||||
| 				case types.Int.ID(): | ||||
| 					So(types.Compare(types.Float, t), ShouldEqual, 1) | ||||
| 				case types.Float.ID(): | ||||
| 					So(types.Compare(types.Float, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.Float, t), ShouldEqual, -1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("String", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.None.ID(): | ||||
| 					So(types.Compare(types.String, t), ShouldEqual, 1) | ||||
| 				case types.Boolean.ID(): | ||||
| 					So(types.Compare(types.String, t), ShouldEqual, 1) | ||||
| 				case types.Int.ID(): | ||||
| 					So(types.Compare(types.String, t), ShouldEqual, 1) | ||||
| 				case types.Float.ID(): | ||||
| 					So(types.Compare(types.String, t), ShouldEqual, 1) | ||||
| 				case types.String.ID(): | ||||
| 					So(types.Compare(types.String, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.String, t), ShouldEqual, -1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("DateTime", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.None.ID(): | ||||
| 					So(types.Compare(types.DateTime, t), ShouldEqual, 1) | ||||
| 				case types.Boolean.ID(): | ||||
| 					So(types.Compare(types.DateTime, t), ShouldEqual, 1) | ||||
| 				case types.Int.ID(): | ||||
| 					So(types.Compare(types.DateTime, t), ShouldEqual, 1) | ||||
| 				case types.Float.ID(): | ||||
| 					So(types.Compare(types.DateTime, t), ShouldEqual, 1) | ||||
| 				case types.String.ID(): | ||||
| 					So(types.Compare(types.DateTime, t), ShouldEqual, 1) | ||||
| 				case types.DateTime.ID(): | ||||
| 					So(types.Compare(types.DateTime, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.DateTime, t), ShouldEqual, -1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("Array", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.None.ID(): | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, 1) | ||||
| 				case types.Boolean.ID(): | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, 1) | ||||
| 				case types.Int.ID(): | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, 1) | ||||
| 				case types.Float.ID(): | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, 1) | ||||
| 				case types.String.ID(): | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, 1) | ||||
| 				case types.DateTime.ID(): | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, 1) | ||||
| 				case types.Array.ID(): | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.Array, t), ShouldEqual, -1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("Object", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.None.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 1) | ||||
| 				case types.Boolean.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 1) | ||||
| 				case types.Int.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 1) | ||||
| 				case types.Float.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 1) | ||||
| 				case types.String.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 1) | ||||
| 				case types.DateTime.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 1) | ||||
| 				case types.Array.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 1) | ||||
| 				case types.Object.ID(): | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.Object, t), ShouldEqual, -1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
|  | ||||
| 		Convey("Binary", func() { | ||||
| 			for _, t := range typesList { | ||||
| 				switch t.ID() { | ||||
| 				case types.Binary.ID(): | ||||
| 					So(types.Compare(types.Binary, t), ShouldEqual, 0) | ||||
| 				default: | ||||
| 					So(types.Compare(types.Binary, t), ShouldEqual, 1) | ||||
| 				} | ||||
| 			} | ||||
| 		}) | ||||
| 	}) | ||||
| } | ||||
							
								
								
									
										17
									
								
								pkg/runtime/values/types/types.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								pkg/runtime/values/types/types.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package types | ||||
|  | ||||
| import "github.com/MontFerret/ferret/pkg/runtime/core" | ||||
|  | ||||
| var ( | ||||
| 	None         = core.NewType("none") | ||||
| 	Boolean      = core.NewType("boolean") | ||||
| 	Int          = core.NewType("int") | ||||
| 	Float        = core.NewType("float") | ||||
| 	String       = core.NewType("string") | ||||
| 	DateTime     = core.NewType("date_time") | ||||
| 	Array        = core.NewType("array") | ||||
| 	Object       = core.NewType("object") | ||||
| 	Binary       = core.NewType("binary") | ||||
| 	HTMLElement  = core.NewType("HTMLElement") | ||||
| 	HTMLDocument = core.NewType("HTMLDocument") | ||||
| ) | ||||
							
								
								
									
										84
									
								
								pkg/runtime/values/types/types_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								pkg/runtime/values/types/types_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| package types_test | ||||
|  | ||||
| import ( | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	. "github.com/smartystreets/goconvey/convey" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| type TestValue struct { | ||||
| 	t core.Type | ||||
| } | ||||
|  | ||||
| func (v TestValue) MarshalJSON() ([]byte, error) { | ||||
| 	return nil, nil | ||||
| } | ||||
|  | ||||
| func (v TestValue) Type() core.Type { | ||||
| 	return v.t | ||||
| } | ||||
|  | ||||
| func (v TestValue) String() string { | ||||
| 	return "" | ||||
| } | ||||
|  | ||||
| func (v TestValue) Compare(other core.Value) int64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (v TestValue) Unwrap() interface{} { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (v TestValue) Hash() uint64 { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| func (v TestValue) Copy() core.Value { | ||||
| 	return v | ||||
| } | ||||
|  | ||||
| func TestType(t *testing.T) { | ||||
| 	Convey(".Name", t, func() { | ||||
| 		So(types.None.String(), ShouldEqual, "none") | ||||
| 		So(types.Boolean.String(), ShouldEqual, "boolean") | ||||
| 		So(types.Int.String(), ShouldEqual, "int") | ||||
| 		So(types.Float.String(), ShouldEqual, "float") | ||||
| 		So(types.String.String(), ShouldEqual, "string") | ||||
| 		So(types.DateTime.String(), ShouldEqual, "date_time") | ||||
| 		So(types.Array.String(), ShouldEqual, "array") | ||||
| 		So(types.Object.String(), ShouldEqual, "object") | ||||
| 		So(types.Binary.String(), ShouldEqual, "binary") | ||||
| 	}) | ||||
|  | ||||
| 	Convey("==", t, func() { | ||||
| 		typesList := []core.Type{ | ||||
| 			types.None, | ||||
| 			types.Boolean, | ||||
| 			types.Int, | ||||
| 			types.Float, | ||||
| 			types.String, | ||||
| 			types.DateTime, | ||||
| 			types.Array, | ||||
| 			types.Object, | ||||
| 			types.Binary, | ||||
| 		} | ||||
|  | ||||
| 		valuesList := []core.Value{ | ||||
| 			TestValue{types.None}, | ||||
| 			TestValue{types.Boolean}, | ||||
| 			TestValue{types.Int}, | ||||
| 			TestValue{types.Float}, | ||||
| 			TestValue{types.String}, | ||||
| 			TestValue{types.DateTime}, | ||||
| 			TestValue{types.Array}, | ||||
| 			TestValue{types.Object}, | ||||
| 			TestValue{types.Binary}, | ||||
| 		} | ||||
|  | ||||
| 		for i, t := range typesList { | ||||
| 			So(t == valuesList[i].Type(), ShouldBeTrue) | ||||
| 		} | ||||
| 	}) | ||||
| } | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Append appends a new item to an array and returns a new array with a given element. | ||||
| @@ -19,7 +20,7 @@ func Append(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -30,7 +31,7 @@ func Append(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	unique := values.False | ||||
|  | ||||
| 	if len(args) > 2 { | ||||
| 		err = core.ValidateType(args[2], core.BooleanType) | ||||
| 		err = core.ValidateType(args[2], types.Boolean) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // First returns a first element from a given array. | ||||
| @@ -17,7 +18,7 @@ func First(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, nil | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Flatten turn an array of arrays into a flat array. | ||||
| @@ -22,7 +23,7 @@ func Flatten(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -32,7 +33,7 @@ func Flatten(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	level := 1 | ||||
|  | ||||
| 	if len(args) > 1 { | ||||
| 		err = core.ValidateType(args[1], core.IntType) | ||||
| 		err = core.ValidateType(args[1], types.Int) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
| @@ -49,7 +50,7 @@ func Flatten(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		currentLevel++ | ||||
|  | ||||
| 		input.ForEach(func(value core.Value, idx int) bool { | ||||
| 			if value.Type() != core.ArrayType || currentLevel > level { | ||||
| 			if value.Type() != types.Array || currentLevel > level { | ||||
| 				result.Push(value) | ||||
| 			} else { | ||||
| 				unwrap(value.(*values.Array)) | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Intersection return the intersection of all arrays specified. | ||||
| @@ -27,7 +28,7 @@ func sections(args []core.Value, count int) (core.Value, error) { | ||||
| 	capacity := len(args) | ||||
|  | ||||
| 	for _, i := range args { | ||||
| 		err := core.ValidateType(i, core.ArrayType) | ||||
| 		err := core.ValidateType(i, types.Array) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Last returns the last element of an array. | ||||
| @@ -17,7 +18,7 @@ func Last(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, nil | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Minus return the difference of all arrays specified. | ||||
| @@ -22,7 +23,7 @@ func Minus(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	capacity := values.NewInt(0) | ||||
|  | ||||
| 	for idx, i := range args { | ||||
| 		err := core.ValidateType(i, core.ArrayType) | ||||
| 		err := core.ValidateType(i, types.Array) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Nth returns the element of an array at a given position. | ||||
| @@ -20,13 +21,13 @@ func Nth(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.IntType) | ||||
| 	err = core.ValidateType(args[1], types.Int) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Pop returns a new array without last element. | ||||
| @@ -17,7 +18,7 @@ func Pop(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Position returns a value indicating whether an element is contained in array. Optionally returns its position. | ||||
| @@ -18,7 +19,7 @@ func Position(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -29,7 +30,7 @@ func Position(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	retIdx := false | ||||
|  | ||||
| 	if len(args) > 2 { | ||||
| 		err = core.ValidateType(args[2], core.BooleanType) | ||||
| 		err = core.ValidateType(args[2], types.Boolean) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Push create a new array with appended value. | ||||
| @@ -19,7 +20,7 @@ func Push(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -30,7 +31,7 @@ func Push(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	uniq := false | ||||
|  | ||||
| 	if len(args) > 2 { | ||||
| 		err = core.ValidateType(args[2], core.BooleanType) | ||||
| 		err = core.ValidateType(args[2], types.Boolean) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // RemoveNth returns a new array without an element by a given position. | ||||
| @@ -18,13 +19,13 @@ func RemoveNth(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.IntType) | ||||
| 	err = core.ValidateType(args[1], types.Int) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // RemoveValue returns a new array with removed all occurrences of value in a given array. | ||||
| @@ -20,7 +21,7 @@ func RemoveValue(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -31,7 +32,7 @@ func RemoveValue(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	limit := -1 | ||||
|  | ||||
| 	if len(args) > 2 { | ||||
| 		err = core.ValidateType(args[2], core.IntType) | ||||
| 		err = core.ValidateType(args[2], types.Int) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // RemoveValues returns a new array with removed all occurrences of values in a given array. | ||||
| @@ -18,13 +19,13 @@ func RemoveValues(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.ArrayType) | ||||
| 	err = core.ValidateType(args[1], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Reverse return a new array with its elements reversed. | ||||
| @@ -17,7 +18,7 @@ func Reverse(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Shift returns a new array without the first element. | ||||
| @@ -17,7 +18,7 @@ func Shift(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Slice returns a new sliced array. | ||||
| @@ -19,13 +20,13 @@ func Slice(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.IntType) | ||||
| 	err = core.ValidateType(args[1], types.Int) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -36,7 +37,7 @@ func Slice(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	length := values.NewInt(int(arr.Length())) | ||||
|  | ||||
| 	if len(args) > 2 { | ||||
| 		if args[2].Type() == core.IntType { | ||||
| 		if args[2].Type() == types.Int { | ||||
| 			arg2 := args[2].(values.Int) | ||||
|  | ||||
| 			if arg2 > 0 { | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package arrays | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Sorted sorts all elements in anyArray. | ||||
| @@ -17,7 +19,7 @@ func Sorted(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // SortedUnique sorts all elements in anyArray. | ||||
| @@ -19,7 +20,7 @@ func SortedUnique(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Union returns the union of all passed arrays. | ||||
| @@ -17,7 +18,7 @@ func Union(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -27,7 +28,7 @@ func Union(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	result := values.NewArray(len(args) * int(firstArrLen)) | ||||
|  | ||||
| 	for _, arg := range args { | ||||
| 		err := core.ValidateType(arg, core.ArrayType) | ||||
| 		err := core.ValidateType(arg, types.Array) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -2,8 +2,10 @@ package arrays | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| func UnionDistinct(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| @@ -13,7 +15,7 @@ func UnionDistinct(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -24,7 +26,7 @@ func UnionDistinct(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	hashes := make(map[uint64]bool) | ||||
|  | ||||
| 	for _, arg := range args { | ||||
| 		err := core.ValidateType(arg, core.ArrayType) | ||||
| 		err := core.ValidateType(arg, types.Array) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Unique returns all unique elements from a given array. | ||||
| @@ -17,7 +18,7 @@ func Unique(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Unshift prepends value to a given array. | ||||
| @@ -20,7 +21,7 @@ func Unshift(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.ArrayType) | ||||
| 	err = core.ValidateType(args[0], types.Array) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -31,7 +32,7 @@ func Unshift(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	uniq := values.False | ||||
|  | ||||
| 	if len(args) > 2 { | ||||
| 		err = core.ValidateType(args[2], core.BooleanType) | ||||
| 		err = core.ValidateType(args[2], types.Boolean) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -2,9 +2,11 @@ package collections | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/collections" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| func Length(_ context.Context, inputs ...core.Value) (core.Value, error) { | ||||
| @@ -15,19 +17,20 @@ func Length(_ context.Context, inputs ...core.Value) (core.Value, error) { | ||||
| 	} | ||||
|  | ||||
| 	value := inputs[0] | ||||
| 	err = core.ValidateType( | ||||
| 		value, | ||||
| 		core.StringType, | ||||
| 		core.ArrayType, | ||||
| 		core.ObjectType, | ||||
| 		core.HTMLElementType, | ||||
| 		core.HTMLDocumentType, | ||||
| 		core.BinaryType, | ||||
| 	) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	c, ok := value.(collections.Collection) | ||||
|  | ||||
| 	if !ok { | ||||
| 		return values.None, core.TypeError(value.Type(), | ||||
| 			types.String, | ||||
| 			types.Array, | ||||
| 			types.Object, | ||||
| 			types.HTMLElement, | ||||
| 			types.HTMLDocument, | ||||
| 			types.Binary, | ||||
| 			core.NewType("Collection"), | ||||
| 		) | ||||
| 	} | ||||
|  | ||||
| 	return value.(collections.Collection).Length(), nil | ||||
| 	return c.Length(), nil | ||||
| } | ||||
|   | ||||
| @@ -5,12 +5,13 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	sliceDateTime   = []core.Type{core.DateTimeType} | ||||
| 	sliceIntType    = []core.Type{core.IntType} | ||||
| 	sliceStringType = []core.Type{core.StringType} | ||||
| 	sliceDateTime   = []core.Type{types.DateTime} | ||||
| 	sliceIntType    = []core.Type{types.Int} | ||||
| 	sliceStringType = []core.Type{types.String} | ||||
|  | ||||
| 	emptyDateTime values.DateTime | ||||
| 	emptyInt      values.Int | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| package datetime | ||||
|  | ||||
| import ( | ||||
| 	"github.com/pkg/errors" | ||||
|  | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| // DateCompare check if two partial dates match. | ||||
| @@ -36,7 +36,7 @@ func DateCompare(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	rangeEnd := values.NewString("millisecond") | ||||
|  | ||||
| 	if len(args) == 4 { | ||||
| 		if err = core.ValidateType(args[3], core.StringType); err != nil { | ||||
| 		if err = core.ValidateType(args[3], types.String); err != nil { | ||||
| 			return values.None, err | ||||
| 		} | ||||
| 		rangeEnd = args[3].(values.String) | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Date convert RFC3339 date time string to DateTime object. | ||||
| @@ -17,7 +18,7 @@ func Date(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.StringType) | ||||
| 	err = core.ValidateType(args[0], types.String) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateDay returns the day of date as a number. | ||||
| @@ -16,7 +17,7 @@ func DateDay(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -3,9 +3,9 @@ package datetime | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateDayOfWeek returns number of the weekday from the date. Sunday is the 0th day of week. | ||||
| @@ -17,7 +17,7 @@ func DateDayOfWeek(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -3,9 +3,9 @@ package datetime | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateDayOfYear returns the day of year number of date. | ||||
| @@ -18,7 +18,7 @@ func DateDayOfYear(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| var daysCount = map[time.Month]int{ | ||||
| @@ -32,7 +33,7 @@ func DateDaysInMonth(_ context.Context, args ...core.Value) (core.Value, error) | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateDiff returns the difference between two dates in given time unit. | ||||
| @@ -34,7 +35,7 @@ func DateDiff(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	isFloat := values.NewBoolean(false) | ||||
|  | ||||
| 	if len(args) == 4 { | ||||
| 		err = core.ValidateType(args[3], core.BooleanType) | ||||
| 		err = core.ValidateType(args[3], types.Boolean) | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
| 		} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateFormat format date according to the given format string. | ||||
| @@ -16,12 +17,12 @@ func DateFormat(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.StringType) | ||||
| 	err = core.ValidateType(args[1], types.String) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -31,24 +31,28 @@ func (tc *testCase) Do(t *testing.T, fn core.Function) { | ||||
| 			So(err, ShouldBeNil) | ||||
| 		} | ||||
|  | ||||
| 		So(actual.Type(), ShouldEqual, expected.Type()) | ||||
| 		So(actual.Type().Equals(expected.Type()), ShouldBeTrue) | ||||
| 		So(actual.Compare(expected), ShouldEqual, 0) | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| func mustDefaultLayoutDt(timeString string) values.DateTime { | ||||
| 	dt, err := defaultLayoutDt(timeString) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	return dt | ||||
| } | ||||
|  | ||||
| func mustLayoutDt(layout, value string) values.DateTime { | ||||
| 	dt, err := layoutDt(layout, value) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
|  | ||||
| 	return dt | ||||
| } | ||||
|  | ||||
| @@ -58,8 +62,10 @@ func defaultLayoutDt(timeString string) (values.DateTime, error) { | ||||
|  | ||||
| func layoutDt(layout, value string) (values.DateTime, error) { | ||||
| 	t, err := time.Parse(layout, value) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.DateTime{}, err | ||||
| 	} | ||||
|  | ||||
| 	return values.NewDateTime(t), nil | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateHour returns the hour of date as a number. | ||||
| @@ -16,7 +17,7 @@ func DateHour(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateLeapYear returns true if date is in a leap year else false. | ||||
| @@ -16,7 +17,7 @@ func DateLeapYear(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateMillisecond returns the millisecond of date as a number. | ||||
| @@ -16,7 +17,7 @@ func DateMillisecond(_ context.Context, args ...core.Value) (core.Value, error) | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateMinute returns the minute of date as a number. | ||||
| @@ -16,7 +17,7 @@ func DateMinute(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateMonth returns the month of date as a number. | ||||
| @@ -16,7 +17,7 @@ func DateMonth(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateQuarter returns which quarter date belongs to. | ||||
| @@ -17,7 +18,7 @@ func DateQuarter(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateSecond returns the second of date as a number. | ||||
| @@ -16,7 +17,7 @@ func DateSecond(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // DateYear returns the year extracted from the given date. | ||||
| @@ -16,7 +17,7 @@ func DateYear(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.DateTimeType) | ||||
| 	err = core.ValidateType(args[0], types.DateTime) | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Click dispatches click event on a given element | ||||
| @@ -21,7 +22,7 @@ func Click(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	if len(args) == 1 { | ||||
| 		arg1 := args[0] | ||||
|  | ||||
| 		err := core.ValidateType(arg1, core.HTMLElementType) | ||||
| 		err := core.ValidateType(arg1, types.HTMLElement) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.False, err | ||||
| @@ -40,7 +41,7 @@ func Click(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	arg1 := args[0] | ||||
| 	selector := args[1].String() | ||||
|  | ||||
| 	err = core.ValidateType(arg1, core.HTMLDocumentType) | ||||
| 	err = core.ValidateType(arg1, types.HTMLDocument) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // ClickAll dispatches click event on all matched element | ||||
| @@ -21,7 +22,7 @@ func ClickAll(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	arg1 := args[0] | ||||
| 	selector := args[1].String() | ||||
|  | ||||
| 	err = core.ValidateType(arg1, core.HTMLDocumentType) | ||||
| 	err = core.ValidateType(arg1, types.HTMLDocument) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -2,10 +2,12 @@ package html | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/drivers" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"time" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| type DocumentLoadParams struct { | ||||
| @@ -29,7 +31,7 @@ func Document(ctx context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.StringType) | ||||
| 	err = core.ValidateType(args[0], types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -83,11 +85,11 @@ func newDefaultDocLoadParams() DocumentLoadParams { | ||||
| func newDocLoadParams(arg core.Value) (DocumentLoadParams, error) { | ||||
| 	res := newDefaultDocLoadParams() | ||||
|  | ||||
| 	if err := core.ValidateType(arg, core.BooleanType, core.ObjectType); err != nil { | ||||
| 	if err := core.ValidateType(arg, types.Boolean, types.Object); err != nil { | ||||
| 		return res, err | ||||
| 	} | ||||
|  | ||||
| 	if arg.Type() == core.BooleanType { | ||||
| 	if arg.Type() == types.Boolean { | ||||
| 		res.Dynamic = arg.(values.Boolean) | ||||
|  | ||||
| 		return res, nil | ||||
| @@ -98,7 +100,7 @@ func newDocLoadParams(arg core.Value) (DocumentLoadParams, error) { | ||||
| 	isDynamic, exists := obj.Get(values.NewString("dynamic")) | ||||
|  | ||||
| 	if exists { | ||||
| 		if err := core.ValidateType(isDynamic, core.BooleanType); err != nil { | ||||
| 		if err := core.ValidateType(isDynamic, types.Boolean); err != nil { | ||||
| 			return res, err | ||||
| 		} | ||||
|  | ||||
| @@ -108,7 +110,7 @@ func newDocLoadParams(arg core.Value) (DocumentLoadParams, error) { | ||||
| 	timeout, exists := obj.Get(values.NewString("timeout")) | ||||
|  | ||||
| 	if exists { | ||||
| 		if err := core.ValidateType(timeout, core.IntType); err != nil { | ||||
| 		if err := core.ValidateType(timeout, types.Int); err != nil { | ||||
| 			return res, err | ||||
| 		} | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Download a resource from the given URL. | ||||
| @@ -20,7 +21,7 @@ func Download(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	} | ||||
|  | ||||
| 	arg1 := args[0] | ||||
| 	err = core.ValidateType(arg1, core.StringType) | ||||
| 	err = core.ValidateType(arg1, types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Element finds an element by a given CSS selector. | ||||
| @@ -29,13 +30,13 @@ func queryArgs(args []core.Value) (values.HTMLNode, values.String, error) { | ||||
| 		return nil, values.EmptyString, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.HTMLDocumentType, core.HTMLElementType) | ||||
| 	err = core.ValidateType(args[0], types.HTMLDocument, types.HTMLElement) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, values.EmptyString, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.StringType) | ||||
| 	err = core.ValidateType(args[1], types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return nil, values.EmptyString, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // Hover  fetches an element with selector, scrolls it into view if needed, and then uses page.mouse to hover over the center of the element. | ||||
| @@ -19,14 +20,14 @@ func Hover(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 	} | ||||
|  | ||||
| 	// document or element | ||||
| 	err = core.ValidateType(args[0], core.HTMLDocumentType, core.HTMLElementType) | ||||
| 	err = core.ValidateType(args[0], types.HTMLDocument, types.HTMLElement) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	if len(args) == 2 { | ||||
| 		err = core.ValidateType(args[1], core.StringType) | ||||
| 		err = core.ValidateType(args[1], types.String) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // InnerHTML Returns inner HTML string of a given or matched by CSS selector element | ||||
| @@ -18,7 +19,7 @@ func InnerHTML(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.EmptyString, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.HTMLDocumentType, core.HTMLElementType) | ||||
| 	err = core.ValidateType(args[0], types.HTMLDocument, types.HTMLElement) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -30,7 +31,7 @@ func InnerHTML(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return node.InnerHTML(), nil | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.StringType) | ||||
| 	err = core.ValidateType(args[1], types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // InnerHTMLAll returns an array of inner HTML strings of matched elements. | ||||
| @@ -18,13 +19,13 @@ func InnerHTMLAll(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.HTMLDocumentType, core.HTMLElementType) | ||||
| 	err = core.ValidateType(args[0], types.HTMLDocument, types.HTMLElement) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.StringType) | ||||
| 	err = core.ValidateType(args[1], types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // InnerText returns inner text string of a given or matched by CSS selector element | ||||
| @@ -18,7 +19,7 @@ func InnerText(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.EmptyString, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.HTMLDocumentType, core.HTMLElementType) | ||||
| 	err = core.ValidateType(args[0], types.HTMLDocument, types.HTMLElement) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| @@ -30,7 +31,7 @@ func InnerText(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return node.InnerText(), nil | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.StringType) | ||||
| 	err = core.ValidateType(args[1], types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import ( | ||||
|  | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/core" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values" | ||||
| 	"github.com/MontFerret/ferret/pkg/runtime/values/types" | ||||
| ) | ||||
|  | ||||
| // InnerTextAll returns an array of inner text of matched elements. | ||||
| @@ -18,13 +19,13 @@ func InnerTextAll(_ context.Context, args ...core.Value) (core.Value, error) { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[0], core.HTMLDocumentType, core.HTMLElementType) | ||||
| 	err = core.ValidateType(args[0], types.HTMLDocument, types.HTMLElement) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
| 	} | ||||
|  | ||||
| 	err = core.ValidateType(args[1], core.StringType) | ||||
| 	err = core.ValidateType(args[1], types.String) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return values.None, err | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user