mirror of
https://github.com/MontFerret/ferret.git
synced 2025-02-21 19:50:09 +02:00
New type system (#232)
* New type system * Fixed dot notation for HTML elements
This commit is contained in:
parent
b3bcbda3b9
commit
1af8b37a0f
@ -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)
|
||||
@ -228,14 +228,10 @@ func (el *HTMLElement) Compare(other core.Value) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
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 {
|
||||
type (
|
||||
TestCloserType struct{}
|
||||
|
||||
TestCloserValue struct {
|
||||
closed bool
|
||||
}
|
||||
)
|
||||
|
||||
func (tc *TestCloser) MarshalJSON() ([]byte, error) {
|
||||
func (tct TestCloserType) ID() int64 {
|
||||
return 99
|
||||
}
|
||||
|
||||
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,55 +1,18 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
//revive:disable-next-line:redefines-builtin-id
|
||||
type Type int64
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
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]
|
||||
}
|
||||
|
||||
type (
|
||||
// Value represents an interface of
|
||||
// any type that needs to be used during runtime
|
||||
type Value interface {
|
||||
Value interface {
|
||||
json.Marshaler
|
||||
Type() Type
|
||||
String() string
|
||||
Compare(other Value) int
|
||||
Compare(other Value) int64
|
||||
Unwrap() interface{}
|
||||
Hash() uint64
|
||||
Copy() Value
|
||||
@ -58,63 +21,21 @@ type Value interface {
|
||||
// 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)
|
||||
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.
|
||||
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
|
||||
Setter interface {
|
||||
SetIn(ctx context.Context, path []Value, value Value) error
|
||||
}
|
||||
|
||||
// PairValueType is a supporting
|
||||
// structure that used in validateValueTypePairs.
|
||||
type PairValueType struct {
|
||||
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 {
|
||||
func (b Binary) Compare(other core.Value) int64 {
|
||||
if other.Type() == types.Binary {
|
||||
// TODO: Lame comparison, need to think more about it
|
||||
switch other.Type() {
|
||||
case core.BooleanType:
|
||||
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 {
|
||||
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
|
||||
func (t String) Compare(other core.Value) int64 {
|
||||
if other.Type() == types.String {
|
||||
return int64(strings.Compare(string(t), other.Unwrap().(string)))
|
||||
}
|
||||
|
||||
return 1
|
||||
}
|
||||
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,
|
||||
|
||||
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"),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return values.None, err
|
||||
}
|
||||
|
||||
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
Loading…
x
Reference in New Issue
Block a user