1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-07-05 00:49:00 +02:00

New type system (#232)

* New type system

* Fixed dot notation for HTML elements
This commit is contained in:
Tim Voronov
2019-02-13 12:31:18 -05:00
committed by GitHub
parent b3bcbda3b9
commit 1af8b37a0f
185 changed files with 1379 additions and 820 deletions

View File

@ -2,6 +2,7 @@ package compiler
import ( import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type ( type (
@ -35,13 +36,13 @@ func (s *scope) GetVariable(name string) (core.Type, error) {
parents, err := s.parent.GetVariable(name) parents, err := s.parent.GetVariable(name)
if err != nil { if err != nil {
return core.NoneType, err return types.None, err
} }
return parents, nil return parents, nil
} }
return core.NoneType, core.Error(ErrVariableNotFound, name) return types.None, core.Error(ErrVariableNotFound, name)
} }
func (s *scope) SetVariable(name string) error { func (s *scope) SetVariable(name string) error {
@ -52,7 +53,7 @@ func (s *scope) SetVariable(name string) error {
} }
// TODO: add type detection // TODO: add type detection
s.vars[name] = core.NoneType s.vars[name] = types.None
return nil return nil
} }

View File

@ -3,7 +3,6 @@ package cdp
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/mafredri/cdp/protocol/dom"
"hash/fnv" "hash/fnv"
"sync" "sync"
"time" "time"
@ -13,7 +12,9 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/logging" "github.com/MontFerret/ferret/pkg/runtime/logging"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
"github.com/mafredri/cdp" "github.com/mafredri/cdp"
"github.com/mafredri/cdp/protocol/dom"
"github.com/mafredri/cdp/protocol/input" "github.com/mafredri/cdp/protocol/input"
"github.com/mafredri/cdp/protocol/page" "github.com/mafredri/cdp/protocol/page"
"github.com/mafredri/cdp/rpcc" "github.com/mafredri/cdp/rpcc"
@ -142,7 +143,7 @@ func (doc *HTMLDocument) MarshalJSON() ([]byte, error) {
} }
func (doc *HTMLDocument) Type() core.Type { func (doc *HTMLDocument) Type() core.Type {
return core.HTMLDocumentType return types.HTMLDocument
} }
func (doc *HTMLDocument) String() string { func (doc *HTMLDocument) String() string {
@ -176,22 +177,17 @@ func (doc *HTMLDocument) Copy() core.Value {
return values.None return values.None
} }
func (doc *HTMLDocument) Compare(other core.Value) int { func (doc *HTMLDocument) Compare(other core.Value) int64 {
doc.Lock() doc.Lock()
defer doc.Unlock() defer doc.Unlock()
switch other.Type() { if other.Type() == types.HTMLDocument {
case core.HTMLDocumentType:
other := other.(*HTMLDocument) other := other.(*HTMLDocument)
return doc.url.Compare(other.url) 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 { func (doc *HTMLDocument) Close() error {
@ -399,7 +395,7 @@ func (doc *HTMLDocument) ClickBySelector(selector values.String) (values.Boolean
return values.False, err return values.False, err
} }
if res.Type() == core.BooleanType { if res.Type() == types.Boolean {
return res.(values.Boolean), nil return res.(values.Boolean), nil
} }
@ -431,7 +427,7 @@ func (doc *HTMLDocument) ClickBySelectorAll(selector values.String) (values.Bool
return values.False, err return values.False, err
} }
if res.Type() == core.BooleanType { if res.Type() == types.Boolean {
return res.(values.Boolean), nil return res.(values.Boolean), nil
} }
@ -461,7 +457,7 @@ func (doc *HTMLDocument) InputBySelector(selector values.String, value core.Valu
return values.False, err 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 return values.False, nil
} }
@ -531,7 +527,7 @@ func (doc *HTMLDocument) SelectBySelector(selector values.String, value *values.
return arr, nil 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 { func (doc *HTMLDocument) HoverBySelector(selector values.String) error {

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/gofrs/uuid"
"hash/fnv" "hash/fnv"
"strconv" "strconv"
"strings" "strings"
@ -16,6 +15,8 @@ import (
"github.com/MontFerret/ferret/pkg/drivers/common" "github.com/MontFerret/ferret/pkg/drivers/common"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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"
"github.com/mafredri/cdp/protocol/dom" "github.com/mafredri/cdp/protocol/dom"
"github.com/mafredri/cdp/protocol/input" "github.com/mafredri/cdp/protocol/input"
@ -195,7 +196,7 @@ func (el *HTMLElement) Close() error {
} }
func (el *HTMLElement) Type() core.Type { func (el *HTMLElement) Type() core.Type {
return core.HTMLElementType return types.HTMLElement
} }
func (el *HTMLElement) MarshalJSON() ([]byte, error) { func (el *HTMLElement) MarshalJSON() ([]byte, error) {
@ -212,9 +213,8 @@ func (el *HTMLElement) String() string {
return el.InnerHTML().String() return el.InnerHTML().String()
} }
func (el *HTMLElement) Compare(other core.Value) int { func (el *HTMLElement) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == types.HTMLElement {
case core.HTMLDocumentType:
other := other.(*HTMLElement) other := other.(*HTMLElement)
id := int(el.id.backendID) id := int(el.id.backendID)
@ -228,14 +228,10 @@ func (el *HTMLElement) Compare(other core.Value) int {
return 1 return 1
} }
return -1
default:
if other.Type() > core.HTMLElementType {
return -1 return -1
} }
return 1 return types.Compare(other.Type(), types.HTMLElement)
}
} }
func (el *HTMLElement) Unwrap() interface{} { func (el *HTMLElement) Unwrap() interface{} {
@ -711,7 +707,7 @@ func (el *HTMLElement) WaitForClass(class values.String, timeout values.Int) err
func() (core.Value, error) { func() (core.Value, error) {
current := el.GetAttribute("class") current := el.GetAttribute("class")
if current.Type() != core.StringType { if current.Type() != types.String {
return values.None, nil return values.None, nil
} }
@ -850,7 +846,7 @@ func (el *HTMLElement) Select(value *values.Array) (*values.Array, error) {
return arr, nil return arr, nil
} }
return nil, core.TypeError(core.ArrayType, res.Type()) return nil, core.TypeError(types.Array, res.Type())
} }
func (el *HTMLElement) ScrollIntoView() error { func (el *HTMLElement) ScrollIntoView() error {

View File

@ -4,6 +4,10 @@ import (
"bytes" "bytes"
"context" "context"
"errors" "errors"
"golang.org/x/sync/errgroup"
"math"
"strings"
"github.com/MontFerret/ferret/pkg/drivers/cdp/eval" "github.com/MontFerret/ferret/pkg/drivers/cdp/eval"
"github.com/MontFerret/ferret/pkg/drivers/cdp/events" "github.com/MontFerret/ferret/pkg/drivers/cdp/events"
"github.com/MontFerret/ferret/pkg/drivers/common" "github.com/MontFerret/ferret/pkg/drivers/common"
@ -13,9 +17,6 @@ import (
"github.com/mafredri/cdp/protocol/dom" "github.com/mafredri/cdp/protocol/dom"
"github.com/mafredri/cdp/protocol/page" "github.com/mafredri/cdp/protocol/page"
"github.com/mafredri/cdp/protocol/runtime" "github.com/mafredri/cdp/protocol/runtime"
"golang.org/x/sync/errgroup"
"math"
"strings"
) )
type ( type (

View File

@ -2,9 +2,10 @@ package drivers
import ( import (
"context" "context"
"io"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"io"
) )
type ( type (

View File

@ -3,6 +3,7 @@ package http
import ( import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
) )
@ -33,22 +34,17 @@ func NewHTMLDocument(
} }
func (doc *HTMLDocument) Type() core.Type { func (doc *HTMLDocument) Type() core.Type {
return core.HTMLDocumentType return types.HTMLDocument
} }
func (doc *HTMLDocument) Compare(other core.Value) int { func (doc *HTMLDocument) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == types.HTMLDocument {
case core.HTMLDocumentType:
otherDoc := other.(values.HTMLDocument) otherDoc := other.(values.HTMLDocument)
return doc.url.Compare(otherDoc.URL()) 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 { func (doc *HTMLDocument) URL() core.Value {

View File

@ -3,11 +3,11 @@ package http
import ( import (
"bytes" "bytes"
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/logging"
"net/http" "net/http"
"net/url" "net/url"
"github.com/MontFerret/ferret/pkg/drivers/common" "github.com/MontFerret/ferret/pkg/drivers/common"
"github.com/MontFerret/ferret/pkg/runtime/logging"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
"github.com/corpix/uarand" "github.com/corpix/uarand"

View File

@ -7,6 +7,7 @@ import (
"github.com/MontFerret/ferret/pkg/drivers/common" "github.com/MontFerret/ferret/pkg/drivers/common"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
"github.com/PuerkitoBio/goquery" "github.com/PuerkitoBio/goquery"
) )
@ -29,25 +30,20 @@ func (el *HTMLElement) MarshalJSON() ([]byte, error) {
} }
func (el *HTMLElement) Type() core.Type { func (el *HTMLElement) Type() core.Type {
return core.HTMLElementType return types.HTMLElement
} }
func (el *HTMLElement) String() string { func (el *HTMLElement) String() string {
return el.InnerHTML().String() return el.InnerHTML().String()
} }
func (el *HTMLElement) Compare(other core.Value) int { func (el *HTMLElement) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == types.HTMLElement {
case core.HTMLElementType:
// TODO: complete the comparison // TODO: complete the comparison
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{} { func (el *HTMLElement) Unwrap() interface{} {

View File

@ -10,7 +10,7 @@ import (
type ( type (
SortDirection int 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 { Sorter struct {
fn Comparator fn Comparator
@ -136,7 +136,7 @@ func (iterator *SortIterator) sort(ctx context.Context, scope *core.Scope) ([]*c
break break
} }
eq = eq * int(comp.direction) eq = eq * int64(comp.direction)
if eq == -1 { if eq == -1 {
out = true out = true

View File

@ -35,7 +35,7 @@ func TestSort(t *testing.T) {
} }
s, _ := collections.NewSorter( 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 return first.MustGetVariable(collections.DefaultValueVar).Compare(second.MustGetVariable(collections.DefaultValueVar)), nil
}, },
collections.SortDirectionAsc, collections.SortDirectionAsc,
@ -72,7 +72,7 @@ func TestSort(t *testing.T) {
} }
s, _ := collections.NewSorter( 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 return first.MustGetVariable(collections.DefaultValueVar).Compare(second.MustGetVariable(collections.DefaultValueVar)), nil
}, },
collections.SortDirectionDesc, collections.SortDirectionDesc,
@ -120,7 +120,7 @@ func TestSort(t *testing.T) {
} }
s1, _ := collections.NewSorter( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one")
o2, _ := second.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( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two")
o2, _ := second.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( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one")
o2, _ := second.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( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two")
o2, _ := second.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( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one")
o2, _ := second.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( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two")
o2, _ := second.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( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("one")
o2, _ := second.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( 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") o1, _ := first.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two")
o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two") o2, _ := second.MustGetVariable(collections.DefaultValueVar).(*values.Object).Get("two")

View File

@ -24,17 +24,14 @@ func TestSourceError(t *testing.T) {
func TestTypeError(t *testing.T) { func TestTypeError(t *testing.T) {
Convey("Should match", t, func() { Convey("Should match", t, func() {
e := core.TypeError(core.BooleanType) e := core.TypeError(TypeA{})
So(e, ShouldNotBeNil) So(e, ShouldNotBeNil)
e = core.TypeError(core.BooleanType, core.BooleanType) e = core.TypeError(TypeA{}, TypeB{})
So(e, ShouldNotBeNil) So(e, ShouldNotBeNil)
e = core.TypeError(core.BooleanType, core.BooleanType, core.IntType, core.FloatType) cause := errors.New("invalid type: expected type_b or type_c, but got type_a")
So(e, ShouldNotBeNil) e = core.TypeError(TypeA{}, TypeB{}, TypeC{})
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)
So(e.Error(), ShouldEqual, cause.Error()) So(e.Error(), ShouldEqual, cause.Error())
}) })
} }

View File

@ -160,39 +160,55 @@ func BenchmarkScope(b *testing.B) {
} }
} }
type TestCloser struct { type (
TestCloserType struct{}
TestCloserValue struct {
closed bool 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 return nil, core.ErrNotImplemented
} }
func (tc *TestCloser) Type() core.Type { func (tc *TestCloserValue) Type() core.Type {
return core.NoneType return TestCloserType{}
} }
func (tc *TestCloser) String() string { func (tc *TestCloserValue) String() string {
return "" return ""
} }
func (tc *TestCloser) Compare(other core.Value) int { func (tc *TestCloserValue) Compare(other core.Value) int64 {
return 0 return 0
} }
func (tc *TestCloser) Unwrap() interface{} { func (tc *TestCloserValue) Unwrap() interface{} {
return tc return tc
} }
func (tc *TestCloser) Hash() uint64 { func (tc *TestCloserValue) Hash() uint64 {
return 0 return 0
} }
func (tc *TestCloser) Copy() core.Value { func (tc *TestCloserValue) Copy() core.Value {
return &TestCloser{} return &TestCloserValue{}
} }
func (tc *TestCloser) Close() error { func (tc *TestCloserValue) Close() error {
if tc.closed { if tc.closed {
return core.Error(core.ErrInvalidOperation, "already 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() { Convey("Should close root scope and close all io.Closer values", t, func() {
rs, cf := core.NewRootScope() rs, cf := core.NewRootScope()
tc := &TestCloser{} tc := &TestCloserValue{}
rs.SetVariable("disposable", tc) rs.SetVariable("disposable", tc)
So(tc.closed, ShouldBeFalse) So(tc.closed, ShouldBeFalse)
@ -220,7 +236,7 @@ func TestCloseFunc(t *testing.T) {
Convey("Should return error if it's already closed", t, func() { Convey("Should return error if it's already closed", t, func() {
rs, cf := core.NewRootScope() rs, cf := core.NewRootScope()
tc := &TestCloser{} tc := &TestCloserValue{}
rs.SetVariable("disposable", tc) rs.SetVariable("disposable", tc)
So(tc.closed, ShouldBeFalse) So(tc.closed, ShouldBeFalse)

83
pkg/runtime/core/type.go Normal file
View 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
}

View 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)
})
}

View File

@ -1,55 +1,18 @@
package core package core
import ( import (
"context"
"encoding/json" "encoding/json"
"github.com/pkg/errors"
) )
//revive:disable-next-line:redefines-builtin-id type (
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]
}
// Value represents an interface of // Value represents an interface of
// any type that needs to be used during runtime // any type that needs to be used during runtime
type Value interface { Value interface {
json.Marshaler json.Marshaler
Type() Type Type() Type
String() string String() string
Compare(other Value) int Compare(other Value) int64
Unwrap() interface{} Unwrap() interface{}
Hash() uint64 Hash() uint64
Copy() Value Copy() Value
@ -58,63 +21,21 @@ type Value interface {
// Getter represents an interface of // Getter represents an interface of
// complex types that needs to be used to read values by path. // 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. // The interface is created to let user-defined types be used in dot notation data access.
type Getter interface { Getter interface {
GetIn(path []Value) (Value, error) GetIn(ctx context.Context, path []Value) (Value, error)
} }
// Setter represents an interface of // Setter represents an interface of
// complex types that needs to be used to write values by path. // 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. // The interface is created to let user-defined types be used in dot notation assignment.
type Setter interface { Setter interface {
SetIn(path []Value, value Value) error SetIn(ctx context.Context, path []Value, value Value) error
}
// IsTypeOf return true when value's type
// is equal to check type.
// Returns false, otherwise.
func IsTypeOf(value Value, check Type) bool {
return value.Type() == check
}
// ValidateType checks the match of
// value's type and required types.
func ValidateType(value Value, required ...Type) error {
var valid bool
ct := value.Type()
for _, t := range required {
if ct == t {
valid = true
break
}
}
if !valid {
return TypeError(value.Type(), required...)
}
return nil
} }
// PairValueType is a supporting // PairValueType is a supporting
// structure that used in validateValueTypePairs. // structure that used in validateValueTypePairs.
type PairValueType struct { PairValueType struct {
Value Value Value Value
Types []Type 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
}

View File

@ -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)
})
}

View File

@ -2,9 +2,11 @@ package clauses
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/collections" "github.com/MontFerret/ferret/pkg/runtime/collections"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type CollectIterator struct { type CollectIterator struct {
@ -59,7 +61,7 @@ func NewCollectIterator(
} }
func newGroupSorter(selector *CollectSelector) (*collections.Sorter, error) { 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) f, err := selector.expression.Exec(ctx, first)
if err != nil { if err != nil {
@ -213,7 +215,7 @@ func (iterator *CollectIterator) group(ctx context.Context, scope *core.Scope) (
arr, ok := groupValue.(*values.Array) arr, ok := groupValue.(*values.Array)
if !ok { 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) 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) counter, ok := groupValue.(values.Int)
if !ok { if !ok {
return nil, core.TypeError(groupValue.Type(), core.IntType) return nil, core.TypeError(groupValue.Type(), types.Int)
} }
groupValue = counter + 1 groupValue = counter + 1

View File

@ -2,8 +2,10 @@ package clauses
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/collections" "github.com/MontFerret/ferret/pkg/runtime/collections"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type LimitClause struct { 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) { func (clause *LimitClause) parseValue(val core.Value) (int, error) {
if val.Type() == core.IntType { if val.Type() == types.Int {
return val.Unwrap().(int), nil return val.Unwrap().(int), nil
} }
if val.Type() == core.FloatType { if val.Type() == types.Float {
return int(val.Unwrap().(float64)), nil 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)
} }

View File

@ -71,7 +71,7 @@ func (clause *SortClause) Iterate(ctx context.Context, scope *core.Scope) (colle
} }
func newSorter(srt *SorterExpression) (*collections.Sorter, error) { 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) f, err := srt.expression.Exec(ctx, first)
if err != nil { if err != nil {

View File

@ -2,9 +2,11 @@ package expressions
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/collections" "github.com/MontFerret/ferret/pkg/runtime/collections"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type DataSource struct { type DataSource struct {
@ -44,11 +46,11 @@ func (ds *DataSource) Iterate(ctx context.Context, scope *core.Scope) (collectio
} }
switch data.Type() { switch data.Type() {
case core.ArrayType: case types.Array:
return collections.NewIndexedIterator(ds.valVariable, ds.keyVariable, data.(collections.IndexedCollection)) 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)) 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)) return collections.NewHTMLNodeIterator(ds.valVariable, ds.keyVariable, data.(values.HTMLNode))
default: default:
// fallback to user defined types // fallback to user defined types
@ -69,10 +71,10 @@ func (ds *DataSource) Iterate(ctx context.Context, scope *core.Scope) (collectio
default: default:
return nil, core.TypeError( return nil, core.TypeError(
data.Type(), data.Type(),
core.ArrayType, types.Array,
core.ObjectType, types.Object,
core.HTMLDocumentType, types.HTMLDocument,
core.HTMLElementType, types.HTMLElement,
) )
} }
} }

View File

@ -11,6 +11,8 @@ import (
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
var testIterableCollectionType = core.NewType("TestIterableCollection")
type ( type (
testIterableCollection struct { testIterableCollection struct {
values collections.IndexedCollection values collections.IndexedCollection
@ -32,12 +34,12 @@ func (c *testIterableCollection) MarshalJSON() ([]byte, error) {
return nil, core.ErrInvalidOperation return nil, core.ErrInvalidOperation
} }
func (c *testIterableCollection) Type() core.Type { func (c *testIterableCollection) Type() core.Type {
return core.Type(11) return testIterableCollectionType
} }
func (c *testIterableCollection) String() string { func (c *testIterableCollection) String() string {
return "" return ""
} }
func (c *testIterableCollection) Compare(other core.Value) int { func (c *testIterableCollection) Compare(other core.Value) int64 {
return 1 return 1
} }
func (c *testIterableCollection) Unwrap() interface{} { func (c *testIterableCollection) Unwrap() interface{} {

View File

@ -2,8 +2,10 @@ package literals
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type ( type (
@ -49,8 +51,8 @@ func (l *ObjectLiteral) Exec(ctx context.Context, scope *core.Scope) (core.Value
return values.None, err return values.None, err
} }
if name.Type() != core.StringType { if name.Type() != types.String {
return values.None, core.TypeError(name.Type(), core.StringType) return values.None, core.TypeError(name.Type(), types.String)
} }
obj.Set(name.(values.String), val) obj.Set(name.(values.String), val)

View File

@ -2,6 +2,7 @@ package expressions
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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 strPath[idx] = segment
} }
out, err := values.GetIn(val, strPath) out, err := values.GetIn(ctx, val, strPath)
if err != nil { if err != nil {
return values.None, core.SourceError(e.src, err) return values.None, core.SourceError(e.src, err)

View File

@ -2,8 +2,10 @@ package operators
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type ( 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) { 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 { if err != nil {
// TODO: Return the error? AQL just returns false // TODO: Return the error? AQL just returns false

View File

@ -2,6 +2,7 @@ package operators
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
) )

View File

@ -2,8 +2,10 @@ package operators
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type InOperator struct { 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) { 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 { if err != nil {
// TODO: Return the error? AQL just returns false // TODO: Return the error? AQL just returns false

View File

@ -2,8 +2,10 @@ package operators
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type ( type (
@ -70,7 +72,7 @@ func (operator *LogicalOperator) Exec(ctx context.Context, scope *core.Scope) (c
leftBool := values.ToBoolean(left) leftBool := values.ToBoolean(left)
if operator.value == LogicalOperatorTypeAnd && leftBool == values.False { if operator.value == LogicalOperatorTypeAnd && leftBool == values.False {
if left.Type() == core.BooleanType { if left.Type() == types.Boolean {
return values.False, nil return values.False, nil
} }
@ -98,7 +100,7 @@ func (operator *LogicalOperator) Eval(_ context.Context, left, right core.Value)
leftBool := values.ToBoolean(left) leftBool := values.ToBoolean(left)
if operator.value == LogicalOperatorTypeAnd && leftBool == values.False { if operator.value == LogicalOperatorTypeAnd && leftBool == values.False {
if left.Type() == core.BooleanType { if left.Type() == types.Boolean {
return values.False, nil return values.False, nil
} }

View File

@ -2,8 +2,10 @@ package operators
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type ( type (
@ -89,15 +91,15 @@ func Not(left, _ core.Value) core.Value {
// Adds numbers // Adds numbers
// Concats strings // Concats strings
func Add(left, right core.Value) core.Value { func Add(left, right core.Value) core.Value {
if left.Type() == core.IntType { if left.Type() == types.Int {
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Int) r := right.(values.Int)
return l + r return l + r
} }
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Float) r := right.(values.Float)
@ -105,15 +107,15 @@ func Add(left, right core.Value) core.Value {
} }
} }
if left.Type() == core.FloatType { if left.Type() == types.Float {
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Float) r := right.(values.Float)
return l + r return l + r
} }
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Int) r := right.(values.Int)
@ -125,15 +127,15 @@ func Add(left, right core.Value) core.Value {
} }
func Subtract(left, right core.Value) core.Value { func Subtract(left, right core.Value) core.Value {
if left.Type() == core.IntType { if left.Type() == types.Int {
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Int) r := right.(values.Int)
return l - r return l - r
} }
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Float) r := right.(values.Float)
@ -141,15 +143,15 @@ func Subtract(left, right core.Value) core.Value {
} }
} }
if left.Type() == core.FloatType { if left.Type() == types.Float {
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Float) r := right.(values.Float)
return l - r return l - r
} }
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Int) r := right.(values.Int)
@ -161,15 +163,15 @@ func Subtract(left, right core.Value) core.Value {
} }
func Multiply(left, right core.Value) core.Value { func Multiply(left, right core.Value) core.Value {
if left.Type() == core.IntType { if left.Type() == types.Int {
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Int) r := right.(values.Int)
return l * r return l * r
} }
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Float) r := right.(values.Float)
@ -177,15 +179,15 @@ func Multiply(left, right core.Value) core.Value {
} }
} }
if left.Type() == core.FloatType { if left.Type() == types.Float {
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Float) r := right.(values.Float)
return l * r return l * r
} }
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Int) r := right.(values.Int)
@ -197,15 +199,15 @@ func Multiply(left, right core.Value) core.Value {
} }
func Divide(left, right core.Value) core.Value { func Divide(left, right core.Value) core.Value {
if left.Type() == core.IntType { if left.Type() == types.Int {
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Int) r := right.(values.Int)
return l / r return l / r
} }
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Float) r := right.(values.Float)
@ -213,15 +215,15 @@ func Divide(left, right core.Value) core.Value {
} }
} }
if left.Type() == core.FloatType { if left.Type() == types.Float {
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Float) r := right.(values.Float)
return l / r return l / r
} }
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Int) r := right.(values.Int)
@ -233,15 +235,15 @@ func Divide(left, right core.Value) core.Value {
} }
func Modulus(left, right core.Value) core.Value { func Modulus(left, right core.Value) core.Value {
if left.Type() == core.IntType { if left.Type() == types.Int {
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Int) r := right.(values.Int)
return l % r return l % r
} }
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Int) l := left.(values.Int)
r := right.(values.Float) r := right.(values.Float)
@ -249,15 +251,15 @@ func Modulus(left, right core.Value) core.Value {
} }
} }
if left.Type() == core.FloatType { if left.Type() == types.Float {
if right.Type() == core.FloatType { if right.Type() == types.Float {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Float) r := right.(values.Float)
return values.Int(l) % values.Int(r) return values.Int(l) % values.Int(r)
} }
if right.Type() == core.IntType { if right.Type() == types.Int {
l := left.(values.Float) l := left.(values.Float)
r := right.(values.Int) r := right.(values.Int)
@ -269,13 +271,13 @@ func Modulus(left, right core.Value) core.Value {
} }
func Increment(left, _ 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) l := left.(values.Int)
return l + 1 return l + 1
} }
if left.Type() == core.FloatType { if left.Type() == types.Float {
l := left.(values.Float) l := left.(values.Float)
return l + 1 return l + 1
@ -285,13 +287,13 @@ func Increment(left, _ core.Value) core.Value {
} }
func Decrement(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) l := left.(values.Int)
return l - 1 return l - 1
} }
if left.Type() == core.FloatType { if left.Type() == types.Float {
l := left.(values.Float) l := left.(values.Float)
return l - 1 return l - 1
@ -301,13 +303,13 @@ func Decrement(left, _ core.Value) core.Value {
} }
func Negative(value, _ 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 { if err != nil {
return values.ZeroInt return values.ZeroInt
} }
if value.Type() == core.IntType { if value.Type() == types.Int {
return -value.(values.Int) return -value.(values.Int)
} }
@ -315,13 +317,13 @@ func Negative(value, _ core.Value) core.Value {
} }
func Positive(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 { if err != nil {
return values.ZeroInt return values.ZeroInt
} }
if value.Type() == core.IntType { if value.Type() == types.Int {
return +value.(values.Int) return +value.(values.Int)
} }

View File

@ -2,8 +2,10 @@ package operators
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type RangeOperator struct { 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) { 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 { if err != nil {
return values.None, core.SourceError(operator.src, err) 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 { if err != nil {
return values.None, core.SourceError(operator.src, err) 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 start int
var end int var end int
if left.Type() == core.FloatType { if left.Type() == types.Float {
start = int(left.(values.Float)) start = int(left.(values.Float))
} else { } else {
start = int(left.(values.Int)) start = int(left.(values.Int))
} }
if right.Type() == core.FloatType { if right.Type() == types.Float {
end = int(right.(values.Float)) end = int(right.(values.Float))
} else { } else {
end = int(right.(values.Int)) end = int(right.(values.Int))

View File

@ -2,6 +2,7 @@ package operators
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
) )

View File

@ -2,6 +2,7 @@ package expressions_test
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
"testing" "testing"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
@ -41,7 +42,7 @@ func TestParameterExpressionExec(t *testing.T) {
value, err := existExp.Exec(ctx, &core.Scope{}) value, err := existExp.Exec(ctx, &core.Scope{})
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(value.Type(), ShouldEqual, core.IntType) So(value.Type().Equals(types.Int), ShouldBeTrue)
So(value.String(), ShouldEqual, "1") So(value.String(), ShouldEqual, "1")
}) })
@ -57,6 +58,6 @@ func TestParameterExpressionExec(t *testing.T) {
So(err, ShouldNotBeNil) So(err, ShouldNotBeNil)
So(err, ShouldHaveSameTypeAs, core.ErrNotFound) So(err, ShouldHaveSameTypeAs, core.ErrNotFound)
So(value.Type(), ShouldEqual, core.NoneType) So(value.Type().Equals(types.None), ShouldBeTrue)
}) })
} }

View File

@ -7,6 +7,7 @@ import (
"sort" "sort"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type ( type (
@ -32,7 +33,7 @@ func (t *Array) MarshalJSON() ([]byte, error) {
} }
func (t *Array) Type() core.Type { func (t *Array) Type() core.Type {
return core.ArrayType return types.Array
} }
func (t *Array) String() string { func (t *Array) String() string {
@ -45,22 +46,23 @@ func (t *Array) String() string {
return string(marshaled) return string(marshaled)
} }
func (t *Array) Compare(other core.Value) int { func (t *Array) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == types.Array {
case core.ArrayType:
other := other.(*Array) other := other.(*Array)
if t.Length() == 0 && other.Length() == 0 { if t.Length() == 0 && other.Length() == 0 {
return 0 return 0
} }
if t.Length() < other.Length() { if t.Length() < other.Length() {
return -1 return -1
} }
if t.Length() > other.Length() { if t.Length() > other.Length() {
return 1 return 1
} }
var res = 0 var res int64
var val core.Value var val core.Value
other.ForEach(func(otherVal core.Value, idx int) bool { other.ForEach(func(otherVal core.Value, idx int) bool {
@ -71,11 +73,9 @@ func (t *Array) Compare(other core.Value) int {
}) })
return res return res
case core.ObjectType:
return -1
default:
return 1
} }
return types.Compare(types.Array, other.Type())
} }
func (t *Array) Unwrap() interface{} { func (t *Array) Unwrap() interface{} {
@ -216,9 +216,13 @@ func (t *Array) Clone() core.Cloneable {
var value core.Value var value core.Value
for idx := NewInt(0); idx < t.Length(); idx++ { for idx := NewInt(0); idx < t.Length(); idx++ {
value = t.Get(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) cloned.Push(value)
} }

View File

@ -2,6 +2,7 @@ package values_test
import ( import (
"encoding/json" "encoding/json"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
"testing" "testing"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
@ -56,7 +57,7 @@ func TestArray(t *testing.T) {
Convey("Should return type", func() { Convey("Should return type", func() {
arr := values.NewArray(1) arr := values.NewArray(1)
So(arr.Type(), ShouldEqual, core.ArrayType) So(arr.Type().Equals(types.Array), ShouldBeTrue)
}) })
}) })

View File

@ -7,6 +7,7 @@ import (
"io/ioutil" "io/ioutil"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type Binary []byte type Binary []byte
@ -30,17 +31,16 @@ func (b Binary) MarshalJSON() ([]byte, error) {
} }
func (b Binary) Type() core.Type { func (b Binary) Type() core.Type {
return core.BinaryType return types.Binary
} }
func (b Binary) String() string { func (b Binary) String() string {
return string(b) 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 // TODO: Lame comparison, need to think more about it
switch other.Type() {
case core.BooleanType:
b2 := other.(*Binary) b2 := other.(*Binary)
if b2.Length() == b.Length() { if b2.Length() == b.Length() {
@ -52,9 +52,9 @@ func (b Binary) Compare(other core.Value) int {
} }
return -1 return -1
default:
return 1
} }
return types.Compare(types.Binary, other.Type())
} }
func (b Binary) Unwrap() interface{} { func (b Binary) Unwrap() interface{} {

View File

@ -6,12 +6,15 @@ import (
"strings" "strings"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type Boolean bool type Boolean bool
var False = Boolean(false) const (
var True = Boolean(true) False = Boolean(false)
True = Boolean(true)
)
func NewBoolean(input bool) Boolean { func NewBoolean(input bool) Boolean {
return Boolean(input) return Boolean(input)
@ -60,7 +63,7 @@ func (t Boolean) MarshalJSON() ([]byte, error) {
} }
func (t Boolean) Type() core.Type { func (t Boolean) Type() core.Type {
return core.BooleanType return types.Boolean
} }
func (t Boolean) String() string { func (t Boolean) String() string {
@ -71,11 +74,10 @@ func (t Boolean) String() string {
return "false" return "false"
} }
func (t Boolean) Compare(other core.Value) int { func (t Boolean) Compare(other core.Value) int64 {
raw := bool(t) raw := bool(t)
switch other.Type() { if types.Boolean.Equals(other.Type()) {
case core.BooleanType:
i := other.Unwrap().(bool) i := other.Unwrap().(bool)
if raw == i { if raw == i {
@ -87,11 +89,9 @@ func (t Boolean) Compare(other core.Value) int {
} }
return +1 return +1
case core.NoneType:
return 1
default:
return -1
} }
return types.Compare(types.Boolean, other.Type())
} }
func (t Boolean) Unwrap() interface{} { func (t Boolean) Unwrap() interface{} {

View File

@ -3,6 +3,7 @@ package values_test
import ( import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"testing" "testing"
) )
@ -21,7 +22,7 @@ func TestBoolean(t *testing.T) {
Convey(".Type", t, func() { Convey(".Type", t, func() {
Convey("Should return a type", func() { Convey("Should return a type", func() {
So(values.True.Type(), ShouldEqual, core.BooleanType) So(values.True.Type().Equals(types.Boolean), ShouldBeTrue)
}) })
}) })

View File

@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
const DefaultTimeLayout = time.RFC3339 const DefaultTimeLayout = time.RFC3339
@ -59,16 +60,15 @@ func (t DateTime) MarshalJSON() ([]byte, error) {
} }
func (t DateTime) Type() core.Type { func (t DateTime) Type() core.Type {
return core.DateTimeType return types.DateTime
} }
func (t DateTime) String() string { func (t DateTime) String() string {
return t.Time.String() return t.Time.String()
} }
func (t DateTime) Compare(other core.Value) int { func (t DateTime) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == types.DateTime {
case core.DateTimeType:
other := other.(DateTime) other := other.(DateTime)
if t.After(other.Time) { if t.After(other.Time) {
@ -80,13 +80,9 @@ func (t DateTime) Compare(other core.Value) int {
} }
return 0 return 0
default:
if other.Type() > core.DateTimeType {
return -1
} }
return 1 return types.Compare(types.DateTime, other.Type())
}
} }
func (t DateTime) Unwrap() interface{} { func (t DateTime) Unwrap() interface{} {

View File

@ -9,11 +9,12 @@ import (
"strconv" "strconv"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type Float float64 type Float float64
var ZeroFloat = Float(0.0) const ZeroFloat = Float(0.0)
func NewFloat(input float64) Float { func NewFloat(input float64) Float {
return Float(input) return Float(input)
@ -75,18 +76,18 @@ func (t Float) MarshalJSON() ([]byte, error) {
} }
func (t Float) Type() core.Type { func (t Float) Type() core.Type {
return core.FloatType return types.Float
} }
func (t Float) String() string { func (t Float) String() string {
return fmt.Sprintf("%f", t) 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) raw := float64(t)
switch other.Type() { if otherType == types.Float {
case core.FloatType:
f := other.Unwrap().(float64) f := other.Unwrap().(float64)
if raw == f { if raw == f {
@ -98,7 +99,9 @@ func (t Float) Compare(other core.Value) int {
} }
return +1 return +1
case core.IntType: }
if otherType == types.Int {
i := other.Unwrap().(int) i := other.Unwrap().(int)
f := float64(i) f := float64(i)
@ -111,11 +114,9 @@ func (t Float) Compare(other core.Value) int {
} }
return +1 return +1
case core.BooleanType, core.NoneType:
return 1
default:
return -1
} }
return types.Compare(types.Float, otherType)
} }
func (t Float) Unwrap() interface{} { func (t Float) Unwrap() interface{} {

View File

@ -1,6 +1,7 @@
package values package values
import ( import (
"context"
"encoding/binary" "encoding/binary"
"encoding/json" "encoding/json"
"hash/fnv" "hash/fnv"
@ -9,9 +10,10 @@ import (
"time" "time"
"github.com/MontFerret/ferret/pkg/runtime/core" "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 { if byPath == nil || len(byPath) == 0 {
return None, nil return None, nil
} }
@ -27,32 +29,32 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) {
segmentType := segment.Type() segmentType := segment.Type()
switch result.Type() { switch result.Type() {
case core.ObjectType: case types.Object:
obj := result.(*Object) obj := result.(*Object)
if segmentType != core.StringType { if segmentType != types.String {
return nil, core.TypeError(segmentType, core.StringType) return nil, core.TypeError(segmentType, types.String)
} }
result, _ = obj.Get(segment.(String)) result, _ = obj.Get(segment.(String))
break break
case core.ArrayType: case types.Array:
arr := result.(*Array) arr := result.(*Array)
if segmentType != core.IntType { if segmentType != types.Int {
return nil, core.TypeError(segmentType, core.IntType) return nil, core.TypeError(segmentType, types.Int)
} }
result = arr.Get(segment.(Int)) result = arr.Get(segment.(Int))
break break
case core.HTMLElementType, core.HTMLDocumentType: case types.HTMLElement, types.HTMLDocument:
el := result.(HTMLNode) el := result.(HTMLNode)
if segmentType == core.IntType { if segmentType == types.Int {
result = el.GetChildNode(segment.(Int)) result = el.GetChildNode(segment.(Int))
} else if segmentType == core.StringType { } else if segmentType == types.String {
strSegment := segment.(String) strSegment := segment.(String)
switch strSegment { switch strSegment {
@ -73,7 +75,7 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) {
case "length": case "length":
result = el.Length() result = el.Length()
case "url": case "url":
if result.Type() == core.HTMLDocumentType { if result.Type() == types.HTMLDocument {
doc, ok := result.(HTMLDocument) doc, ok := result.(HTMLDocument)
if ok { if ok {
@ -88,22 +90,22 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) {
return None, err return None, err
} }
} else { } else {
return nil, core.TypeError(segmentType, core.IntType, core.StringType) return nil, core.TypeError(segmentType, types.Int, types.String)
} }
default: default:
getter, ok := result.(core.Getter) getter, ok := result.(core.Getter)
if ok { if ok {
return getter.GetIn(byPath[i:]) return getter.GetIn(ctx, byPath[i:])
} }
return None, core.TypeError( return None, core.TypeError(
from.Type(), from.Type(),
core.ArrayType, types.Array,
core.ObjectType, types.Object,
core.HTMLDocumentType, types.HTMLDocument,
core.HTMLElementType, types.HTMLElement,
) )
} }
} }
@ -111,7 +113,7 @@ func GetIn(from core.Value, byPath []core.Value) (core.Value, error) {
return result, nil 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 { if byPath == nil || len(byPath) == 0 {
return nil return nil
} }
@ -126,11 +128,11 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error {
segmentType := segment.Type() segmentType := segment.Type()
switch parent.Type() { switch parent.Type() {
case core.ObjectType: case types.Object:
parent := parent.(*Object) parent := parent.(*Object)
if segmentType != core.StringType { if segmentType != types.String {
return core.TypeError(segmentType, core.StringType) return core.TypeError(segmentType, types.String)
} }
if isTarget == false { if isTarget == false {
@ -140,9 +142,9 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error {
} }
break break
case core.ArrayType: case types.Array:
if segmentType != core.IntType { if segmentType != types.Int {
return core.TypeError(segmentType, core.IntType) return core.TypeError(segmentType, types.Int)
} }
parent := parent.(*Array) parent := parent.(*Array)
@ -160,19 +162,19 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error {
setter, ok := parent.(core.Setter) setter, ok := parent.(core.Setter)
if ok { if ok {
return setter.SetIn(byPath[idx:], value) return setter.SetIn(ctx, byPath[idx:], value)
} }
// redefine parent // redefine parent
isArray := segmentType == core.IntType isArray := segmentType == types.Int
// it's not an index // it's not an index
if isArray == false { if isArray == false {
obj := NewObject() obj := NewObject()
parent = obj parent = obj
if segmentType != core.StringType { if segmentType != types.String {
return core.TypeError(segmentType, core.StringType) return core.TypeError(segmentType, types.String)
} }
if isTarget { if isTarget {
@ -190,7 +192,7 @@ func SetIn(to core.Value, byPath []core.Value, value core.Value) error {
} }
// set new parent // 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 return err
} }
@ -302,9 +304,9 @@ func Unmarshal(value json.RawMessage) (core.Value, error) {
func IsCloneable(value core.Value) Boolean { func IsCloneable(value core.Value) Boolean {
switch value.Type() { switch value.Type() {
case core.ArrayType: case types.Array:
return NewBoolean(true) return NewBoolean(true)
case core.ObjectType: case types.Object:
return NewBoolean(true) return NewBoolean(true)
default: default:
return NewBoolean(false) return NewBoolean(false)
@ -313,15 +315,15 @@ func IsCloneable(value core.Value) Boolean {
func ToBoolean(input core.Value) core.Value { func ToBoolean(input core.Value) core.Value {
switch input.Type() { switch input.Type() {
case core.BooleanType: case types.Boolean:
return input return input
case core.NoneType: case types.None:
return False return False
case core.StringType: case types.String:
return NewBoolean(input.String() != "") return NewBoolean(input.String() != "")
case core.IntType: case types.Int:
return NewBoolean(input.(Int) != 0) return NewBoolean(input.(Int) != 0)
case core.FloatType: case types.Float:
return NewBoolean(input.(Float) != 0) return NewBoolean(input.(Float) != 0)
default: default:
return True return True
@ -330,15 +332,15 @@ func ToBoolean(input core.Value) core.Value {
func ToArray(input core.Value) core.Value { func ToArray(input core.Value) core.Value {
switch input.Type() { switch input.Type() {
case core.BooleanType, case types.Boolean,
core.IntType, types.Int,
core.FloatType, types.Float,
core.StringType, types.String,
core.DateTimeType: types.DateTime:
return NewArrayWith(input) return NewArrayWith(input)
case core.HTMLElementType, case types.HTMLElement,
core.HTMLDocumentType: types.HTMLDocument:
val := input.(HTMLNode) val := input.(HTMLNode)
attrs := val.GetAttributes() attrs := val.GetAttributes()
@ -357,9 +359,9 @@ func ToArray(input core.Value) core.Value {
}) })
return obj return obj
case core.ArrayType: case types.Array:
return input.Copy() return input.Copy()
case core.ObjectType: case types.Object:
obj, ok := input.(*Object) obj, ok := input.(*Object)
if !ok { if !ok {

View File

@ -1,6 +1,7 @@
package values_test package values_test
import ( import (
"context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"testing" "testing"
@ -8,39 +9,41 @@ import (
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
) )
type CustomType struct { var CustomType = core.NewType("custom")
type CustomValue struct {
properties map[core.Value]core.Value properties map[core.Value]core.Value
} }
func (t *CustomType) MarshalJSON() ([]byte, error) { func (t *CustomValue) MarshalJSON() ([]byte, error) {
return nil, core.ErrNotImplemented return nil, core.ErrNotImplemented
} }
func (t *CustomType) Type() core.Type { func (t *CustomValue) Type() core.Type {
return core.CustomType return CustomType
} }
func (t *CustomType) String() string { func (t *CustomValue) String() string {
return "" return ""
} }
func (t *CustomType) Compare(other core.Value) int { func (t *CustomValue) Compare(other core.Value) int64 {
return other.Compare(t) * -1 return other.Compare(t) * -1
} }
func (t *CustomType) Unwrap() interface{} { func (t *CustomValue) Unwrap() interface{} {
return t return t
} }
func (t *CustomType) Hash() uint64 { func (t *CustomValue) Hash() uint64 {
return 0 return 0
} }
func (t *CustomType) Copy() core.Value { func (t *CustomValue) Copy() core.Value {
return values.None 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 { if path == nil || len(path) == 0 {
return values.None, nil return values.None, nil
} }
@ -56,10 +59,10 @@ func (t *CustomType) GetIn(path []core.Value) (core.Value, error) {
return propValue, nil 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 { if path == nil || len(path) == 0 {
return nil return nil
} }
@ -77,17 +80,17 @@ func (t *CustomType) SetIn(path []core.Value, value core.Value) error {
return nil return nil
} }
return values.SetIn(propValue, path[1:], value) return values.SetIn(ctx, propValue, path[1:], value)
} }
func TestHelpers(t *testing.T) { func TestHelpers(t *testing.T) {
Convey("Helpers", t, func() { Convey("Helpers", t, func() {
Convey("Getter", func() { Convey("Getter", func() {
Convey("It should get a value by a given path", func() { Convey("It should get a value by a given path", func() {
ct := &CustomType{ ct := &CustomValue{
properties: map[core.Value]core.Value{ properties: map[core.Value]core.Value{
values.NewString("foo"): values.NewInt(1), values.NewString("foo"): values.NewInt(1),
values.NewString("bar"): &CustomType{ values.NewString("bar"): &CustomValue{
properties: map[core.Value]core.Value{ properties: map[core.Value]core.Value{
values.NewString("qaz"): values.NewInt(2), 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"), values.NewString("foo"),
}) })
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(foo, ShouldEqual, values.NewInt(1)) 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("bar"),
values.NewString("qaz"), values.NewString("qaz"),
}) })
@ -114,10 +119,10 @@ func TestHelpers(t *testing.T) {
Convey("Setter", func() { Convey("Setter", func() {
Convey("It should get a value by a given path", func() { Convey("It should get a value by a given path", func() {
ct := &CustomType{ ct := &CustomValue{
properties: map[core.Value]core.Value{ properties: map[core.Value]core.Value{
values.NewString("foo"): values.NewInt(1), values.NewString("foo"): values.NewInt(1),
values.NewString("bar"): &CustomType{ values.NewString("bar"): &CustomValue{
properties: map[core.Value]core.Value{ properties: map[core.Value]core.Value{
values.NewString("qaz"): values.NewInt(2), 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.NewString("foo"),
}, values.NewInt(2)) }, values.NewInt(2))
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(ct.properties[values.NewString("foo")], ShouldEqual, values.NewInt(2)) 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("bar"),
values.NewString("qaz"), values.NewString("qaz"),
}, values.NewString("foobar")) }, values.NewString("foobar"))
So(err, ShouldBeNil) So(err, ShouldBeNil)
qaz, err := values.GetIn(ct, []core.Value{ qaz, err := values.GetIn(ctx, ct, []core.Value{
values.NewString("bar"), values.NewString("bar"),
values.NewString("qaz"), values.NewString("qaz"),
}) })

View File

@ -7,11 +7,12 @@ import (
"strconv" "strconv"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type Int int64 type Int int64
var ZeroInt = Int(0) const ZeroInt = Int(0)
func NewInt(input int) Int { func NewInt(input int) Int {
return Int(int64(input)) return Int(int64(input))
@ -65,16 +66,17 @@ func (t Int) MarshalJSON() ([]byte, error) {
} }
func (t Int) Type() core.Type { func (t Int) Type() core.Type {
return core.IntType return types.Int
} }
func (t Int) String() string { func (t Int) String() string {
return strconv.Itoa(int(t)) return strconv.Itoa(int(t))
} }
func (t Int) Compare(other core.Value) int { func (t Int) Compare(other core.Value) int64 {
switch other.Type() { otherType := other.Type()
case core.IntType:
if otherType == types.Int {
i := other.(Int) i := other.(Int)
if t == i { if t == i {
@ -86,7 +88,9 @@ func (t Int) Compare(other core.Value) int {
} }
return +1 return +1
case core.FloatType: }
if otherType == types.Float {
f := other.(Float) f := other.(Float)
f2 := Float(t) f2 := Float(t)
@ -99,11 +103,9 @@ func (t Int) Compare(other core.Value) int {
} }
return +1 return +1
case core.BooleanType, core.NoneType:
return 1
default:
return -1
} }
return types.Compare(types.Int, otherType)
} }
func (t Int) Unwrap() interface{} { func (t Int) Unwrap() interface{} {

View File

@ -2,6 +2,7 @@ package values
import ( import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type none struct{} type none struct{}
@ -13,20 +14,19 @@ func (t *none) MarshalJSON() ([]byte, error) {
} }
func (t *none) Type() core.Type { func (t *none) Type() core.Type {
return core.NoneType return types.None
} }
func (t *none) String() string { func (t *none) String() string {
return "" return ""
} }
func (t *none) Compare(other core.Value) int { func (t *none) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == types.None {
case core.NoneType:
return 0 return 0
default:
return -1
} }
return -1
} }
func (t *none) Unwrap() interface{} { func (t *none) Unwrap() interface{} {

View File

@ -7,14 +7,17 @@ import (
"sort" "sort"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type ( type (
ObjectPredicate = func(value core.Value, key string) bool ObjectPredicate = func(value core.Value, key string) bool
ObjectProperty struct { ObjectProperty struct {
key string key string
value core.Value value core.Value
} }
Object struct { Object struct {
value map[string]core.Value value map[string]core.Value
} }
@ -43,7 +46,7 @@ func (t *Object) MarshalJSON() ([]byte, error) {
} }
func (t *Object) Type() core.Type { func (t *Object) Type() core.Type {
return core.ObjectType return types.Object
} }
func (t *Object) String() string { func (t *Object) String() string {
@ -59,22 +62,23 @@ func (t *Object) String() string {
// Compare compares the source object with other core.Value // Compare compares the source object with other core.Value
// The behavior of the Compare is similar // The behavior of the Compare is similar
// to the comparison of objects in ArangoDB // to the comparison of objects in ArangoDB
func (t *Object) Compare(other core.Value) int { func (t *Object) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == t.Type() {
case core.ObjectType:
other := other.(*Object) other := other.(*Object)
if t.Length() == 0 && other.Length() == 0 { if t.Length() == 0 && other.Length() == 0 {
return 0 return 0
} }
if t.Length() < other.Length() { if t.Length() < other.Length() {
return -1 return -1
} }
if t.Length() > other.Length() { if t.Length() > other.Length() {
return 1 return 1
} }
var res = 0 var res int64
sortedT := sort.StringSlice(t.Keys()) sortedT := sort.StringSlice(t.Keys())
sortedT.Sort() sortedT.Sort()
@ -92,6 +96,7 @@ func (t *Object) Compare(other core.Value) int {
tVal, _ = t.Get(NewString(tKey)) tVal, _ = t.Get(NewString(tKey))
otherVal, _ = other.Get(NewString(tKey)) otherVal, _ = other.Get(NewString(tKey))
res = tVal.Compare(otherVal) res = tVal.Compare(otherVal)
continue continue
} }
@ -105,9 +110,9 @@ func (t *Object) Compare(other core.Value) int {
} }
return res return res
default:
return 1
} }
return types.Compare(types.Object, other.Type())
} }
func (t *Object) Unwrap() interface{} { func (t *Object) Unwrap() interface{} {
@ -201,10 +206,6 @@ func (t *Object) Get(key String) (core.Value, Boolean) {
return None, NewBoolean(found) 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) { func (t *Object) Set(key String, value core.Value) {
if value != nil { if value != nil {
t.value[string(key)] = value t.value[string(key)] = value
@ -217,20 +218,20 @@ func (t *Object) Remove(key String) {
delete(t.value, string(key)) 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 { func (t *Object) Clone() core.Cloneable {
cloned := NewObject() cloned := NewObject()
var value core.Value var value core.Value
var keyString String var keyString String
for key := range t.value { for key := range t.value {
keyString = NewString(key) keyString = NewString(key)
value, _ = t.Get(keyString) 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) cloned.Set(keyString, value)
} }

View File

@ -1,6 +1,7 @@
package values_test package values_test
import ( import (
"github.com/MontFerret/ferret/pkg/runtime/values/types"
"testing" "testing"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
@ -63,7 +64,7 @@ func TestObject(t *testing.T) {
Convey("Should return type", func() { Convey("Should return type", func() {
obj := values.NewObject() obj := values.NewObject()
So(obj.Type(), ShouldEqual, core.ObjectType) So(obj.Type().Equals(types.Object), ShouldBeTrue)
}) })
}) })

View File

@ -7,12 +7,15 @@ import (
"strings" "strings"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type String string type String string
var EmptyString = String("") const (
var SpaceString = String(" ") EmptyString = String("")
SpaceString = String(" ")
)
func NewString(input string) String { func NewString(input string) String {
if input == "" { if input == "" {
@ -69,24 +72,19 @@ func (t String) MarshalJSON() ([]byte, error) {
} }
func (t String) Type() core.Type { func (t String) Type() core.Type {
return core.StringType return types.String
} }
func (t String) String() string { func (t String) String() string {
return string(t) return string(t)
} }
func (t String) Compare(other core.Value) int { func (t String) Compare(other core.Value) int64 {
switch other.Type() { if other.Type() == types.String {
case core.StringType: return int64(strings.Compare(string(t), other.Unwrap().(string)))
return strings.Compare(string(t), other.Unwrap().(string))
default:
if other.Type() > core.DateTimeType {
return -1
} }
return 1 return types.Compare(types.String, other.Type())
}
} }
func (t String) Unwrap() interface{} { func (t String) Unwrap() interface{} {

View 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
}

View 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)
}
}
})
})
}

View 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")
)

View 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)
}
})
}

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -30,7 +31,7 @@ func Append(_ context.Context, args ...core.Value) (core.Value, error) {
unique := values.False unique := values.False
if len(args) > 2 { if len(args) > 2 {
err = core.ValidateType(args[2], core.BooleanType) err = core.ValidateType(args[2], types.Boolean)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// First returns a first element from a given array. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, nil return values.None, nil

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -32,7 +33,7 @@ func Flatten(_ context.Context, args ...core.Value) (core.Value, error) {
level := 1 level := 1
if len(args) > 1 { if len(args) > 1 {
err = core.ValidateType(args[1], core.IntType) err = core.ValidateType(args[1], types.Int)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -49,7 +50,7 @@ func Flatten(_ context.Context, args ...core.Value) (core.Value, error) {
currentLevel++ currentLevel++
input.ForEach(func(value core.Value, idx int) bool { 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) result.Push(value)
} else { } else {
unwrap(value.(*values.Array)) unwrap(value.(*values.Array))

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Intersection return the intersection of all arrays specified. // 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) capacity := len(args)
for _, i := range args { for _, i := range args {
err := core.ValidateType(i, core.ArrayType) err := core.ValidateType(i, types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Last returns the last element of an array. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, nil return values.None, nil

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Minus return the difference of all arrays specified. // 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) capacity := values.NewInt(0)
for idx, i := range args { for idx, i := range args {
err := core.ValidateType(i, core.ArrayType) err := core.ValidateType(i, types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], core.IntType) err = core.ValidateType(args[1], types.Int)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Pop returns a new array without last element. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -29,7 +30,7 @@ func Position(_ context.Context, args ...core.Value) (core.Value, error) {
retIdx := false retIdx := false
if len(args) > 2 { if len(args) > 2 {
err = core.ValidateType(args[2], core.BooleanType) err = core.ValidateType(args[2], types.Boolean)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Push create a new array with appended value. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -30,7 +31,7 @@ func Push(_ context.Context, args ...core.Value) (core.Value, error) {
uniq := false uniq := false
if len(args) > 2 { if len(args) > 2 {
err = core.ValidateType(args[2], core.BooleanType) err = core.ValidateType(args[2], types.Boolean)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], core.IntType) err = core.ValidateType(args[1], types.Int)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -31,7 +32,7 @@ func RemoveValue(_ context.Context, args ...core.Value) (core.Value, error) {
limit := -1 limit := -1
if len(args) > 2 { if len(args) > 2 {
err = core.ValidateType(args[2], core.IntType) err = core.ValidateType(args[2], types.Int)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], core.ArrayType) err = core.ValidateType(args[1], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Reverse return a new array with its elements reversed. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Shift returns a new array without the first element. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Slice returns a new sliced array. // Slice returns a new sliced array.
@ -19,13 +20,13 @@ func Slice(_ context.Context, args ...core.Value) (core.Value, error) {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], core.IntType) err = core.ValidateType(args[1], types.Int)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -36,7 +37,7 @@ func Slice(_ context.Context, args ...core.Value) (core.Value, error) {
length := values.NewInt(int(arr.Length())) length := values.NewInt(int(arr.Length()))
if len(args) > 2 { if len(args) > 2 {
if args[2].Type() == core.IntType { if args[2].Type() == types.Int {
arg2 := args[2].(values.Int) arg2 := args[2].(values.Int)
if arg2 > 0 { if arg2 > 0 {

View File

@ -2,8 +2,10 @@ package arrays
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Sorted sorts all elements in anyArray. // Sorted sorts all elements in anyArray.
@ -17,7 +19,7 @@ func Sorted(_ context.Context, args ...core.Value) (core.Value, error) {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// SortedUnique sorts all elements in anyArray. // SortedUnique sorts all elements in anyArray.
@ -19,7 +20,7 @@ func SortedUnique(_ context.Context, args ...core.Value) (core.Value, error) {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Union returns the union of all passed arrays. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err 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)) result := values.NewArray(len(args) * int(firstArrLen))
for _, arg := range args { for _, arg := range args {
err := core.ValidateType(arg, core.ArrayType) err := core.ValidateType(arg, types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -2,8 +2,10 @@ package arrays
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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) { 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -24,7 +26,7 @@ func UnionDistinct(_ context.Context, args ...core.Value) (core.Value, error) {
hashes := make(map[uint64]bool) hashes := make(map[uint64]bool)
for _, arg := range args { for _, arg := range args {
err := core.ValidateType(arg, core.ArrayType) err := core.ValidateType(arg, types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Unique returns all unique elements from a given array. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Unshift prepends value to a given array. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.ArrayType) err = core.ValidateType(args[0], types.Array)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -31,7 +32,7 @@ func Unshift(_ context.Context, args ...core.Value) (core.Value, error) {
uniq := values.False uniq := values.False
if len(args) > 2 { if len(args) > 2 {
err = core.ValidateType(args[2], core.BooleanType) err = core.ValidateType(args[2], types.Boolean)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -2,9 +2,11 @@ package collections
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/collections" "github.com/MontFerret/ferret/pkg/runtime/collections"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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) { 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] value := inputs[0]
err = core.ValidateType(
value, c, ok := value.(collections.Collection)
core.StringType,
core.ArrayType, if !ok {
core.ObjectType, return values.None, core.TypeError(value.Type(),
core.HTMLElementType, types.String,
core.HTMLDocumentType, types.Array,
core.BinaryType, 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
} }

View File

@ -5,12 +5,13 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
var ( var (
sliceDateTime = []core.Type{core.DateTimeType} sliceDateTime = []core.Type{types.DateTime}
sliceIntType = []core.Type{core.IntType} sliceIntType = []core.Type{types.Int}
sliceStringType = []core.Type{core.StringType} sliceStringType = []core.Type{types.String}
emptyDateTime values.DateTime emptyDateTime values.DateTime
emptyInt values.Int emptyInt values.Int

View File

@ -1,12 +1,12 @@
package datetime package datetime
import ( import (
"github.com/pkg/errors"
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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") rangeEnd := values.NewString("millisecond")
if len(args) == 4 { 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 return values.None, err
} }
rangeEnd = args[3].(values.String) rangeEnd = args[3].(values.String)

View File

@ -6,6 +6,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Date convert RFC3339 date time string to DateTime object. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.StringType) err = core.ValidateType(args[0], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateDay returns the day of date as a number. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -3,9 +3,9 @@ package datetime
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/core" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -3,9 +3,9 @@ package datetime
import ( import (
"context" "context"
"github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/core" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -6,6 +6,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
var daysCount = map[time.Month]int{ var daysCount = map[time.Month]int{
@ -32,7 +33,7 @@ func DateDaysInMonth(_ context.Context, args ...core.Value) (core.Value, error)
return values.None, err return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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) isFloat := values.NewBoolean(false)
if len(args) == 4 { if len(args) == 4 {
err = core.ValidateType(args[3], core.BooleanType) err = core.ValidateType(args[3], types.Boolean)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateFormat format date according to the given format string. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], core.StringType) err = core.ValidateType(args[1], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -31,24 +31,28 @@ func (tc *testCase) Do(t *testing.T, fn core.Function) {
So(err, ShouldBeNil) So(err, ShouldBeNil)
} }
So(actual.Type(), ShouldEqual, expected.Type()) So(actual.Type().Equals(expected.Type()), ShouldBeTrue)
So(actual.Compare(expected), ShouldEqual, 0) So(actual.Compare(expected), ShouldEqual, 0)
}) })
} }
func mustDefaultLayoutDt(timeString string) values.DateTime { func mustDefaultLayoutDt(timeString string) values.DateTime {
dt, err := defaultLayoutDt(timeString) dt, err := defaultLayoutDt(timeString)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return dt return dt
} }
func mustLayoutDt(layout, value string) values.DateTime { func mustLayoutDt(layout, value string) values.DateTime {
dt, err := layoutDt(layout, value) dt, err := layoutDt(layout, value)
if err != nil { if err != nil {
panic(err) panic(err)
} }
return dt return dt
} }
@ -58,8 +62,10 @@ func defaultLayoutDt(timeString string) (values.DateTime, error) {
func layoutDt(layout, value string) (values.DateTime, error) { func layoutDt(layout, value string) (values.DateTime, error) {
t, err := time.Parse(layout, value) t, err := time.Parse(layout, value)
if err != nil { if err != nil {
return values.DateTime{}, err return values.DateTime{}, err
} }
return values.NewDateTime(t), nil return values.NewDateTime(t), nil
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateHour returns the hour of date as a number. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateMillisecond returns the millisecond of date as a number. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateMinute returns the minute of date as a number. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateMonth returns the month of date as a number. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -6,6 +6,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateQuarter returns which quarter date belongs to. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateSecond returns the second of date as a number. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// DateYear returns the year extracted from the given date. // 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 return values.None, err
} }
err = core.ValidateType(args[0], core.DateTimeType) err = core.ValidateType(args[0], types.DateTime)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Click dispatches click event on a given element // 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 { if len(args) == 1 {
arg1 := args[0] arg1 := args[0]
err := core.ValidateType(arg1, core.HTMLElementType) err := core.ValidateType(arg1, types.HTMLElement)
if err != nil { if err != nil {
return values.False, err return values.False, err
@ -40,7 +41,7 @@ func Click(_ context.Context, args ...core.Value) (core.Value, error) {
arg1 := args[0] arg1 := args[0]
selector := args[1].String() selector := args[1].String()
err = core.ValidateType(arg1, core.HTMLDocumentType) err = core.ValidateType(arg1, types.HTMLDocument)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// ClickAll dispatches click event on all matched element // 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] arg1 := args[0]
selector := args[1].String() selector := args[1].String()
err = core.ValidateType(arg1, core.HTMLDocumentType) err = core.ValidateType(arg1, types.HTMLDocument)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -2,10 +2,12 @@ package html
import ( import (
"context" "context"
"time"
"github.com/MontFerret/ferret/pkg/drivers" "github.com/MontFerret/ferret/pkg/drivers"
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"time" "github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
type DocumentLoadParams struct { type DocumentLoadParams struct {
@ -29,7 +31,7 @@ func Document(ctx context.Context, args ...core.Value) (core.Value, error) {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[0], core.StringType) err = core.ValidateType(args[0], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err
@ -83,11 +85,11 @@ func newDefaultDocLoadParams() DocumentLoadParams {
func newDocLoadParams(arg core.Value) (DocumentLoadParams, error) { func newDocLoadParams(arg core.Value) (DocumentLoadParams, error) {
res := newDefaultDocLoadParams() 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 return res, err
} }
if arg.Type() == core.BooleanType { if arg.Type() == types.Boolean {
res.Dynamic = arg.(values.Boolean) res.Dynamic = arg.(values.Boolean)
return res, nil return res, nil
@ -98,7 +100,7 @@ func newDocLoadParams(arg core.Value) (DocumentLoadParams, error) {
isDynamic, exists := obj.Get(values.NewString("dynamic")) isDynamic, exists := obj.Get(values.NewString("dynamic"))
if exists { if exists {
if err := core.ValidateType(isDynamic, core.BooleanType); err != nil { if err := core.ValidateType(isDynamic, types.Boolean); err != nil {
return res, err return res, err
} }
@ -108,7 +110,7 @@ func newDocLoadParams(arg core.Value) (DocumentLoadParams, error) {
timeout, exists := obj.Get(values.NewString("timeout")) timeout, exists := obj.Get(values.NewString("timeout"))
if exists { if exists {
if err := core.ValidateType(timeout, core.IntType); err != nil { if err := core.ValidateType(timeout, types.Int); err != nil {
return res, err return res, err
} }

View File

@ -7,6 +7,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Download a resource from the given URL. // Download a resource from the given URL.
@ -20,7 +21,7 @@ func Download(_ context.Context, args ...core.Value) (core.Value, error) {
} }
arg1 := args[0] arg1 := args[0]
err = core.ValidateType(arg1, core.StringType) err = core.ValidateType(arg1, types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "github.com/MontFerret/ferret/pkg/runtime/values"
"github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// Element finds an element by a given CSS selector. // 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 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 { if err != nil {
return nil, values.EmptyString, err return nil, values.EmptyString, err
} }
err = core.ValidateType(args[1], core.StringType) err = core.ValidateType(args[1], types.String)
if err != nil { if err != nil {
return nil, values.EmptyString, err return nil, values.EmptyString, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 // document or element
err = core.ValidateType(args[0], core.HTMLDocumentType, core.HTMLElementType) err = core.ValidateType(args[0], types.HTMLDocument, types.HTMLElement)
if err != nil { if err != nil {
return values.None, err return values.None, err
} }
if len(args) == 2 { if len(args) == 2 {
err = core.ValidateType(args[1], core.StringType) err = core.ValidateType(args[1], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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 // 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 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 { if err != nil {
return values.None, err return values.None, err
@ -30,7 +31,7 @@ func InnerHTML(_ context.Context, args ...core.Value) (core.Value, error) {
return node.InnerHTML(), nil return node.InnerHTML(), nil
} }
err = core.ValidateType(args[1], core.StringType) err = core.ValidateType(args[1], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 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 { if err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], core.StringType) err = core.ValidateType(args[1], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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 // 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 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 { if err != nil {
return values.None, err return values.None, err
@ -30,7 +31,7 @@ func InnerText(_ context.Context, args ...core.Value) (core.Value, error) {
return node.InnerText(), nil return node.InnerText(), nil
} }
err = core.ValidateType(args[1], core.StringType) err = core.ValidateType(args[1], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err

View File

@ -5,6 +5,7 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/core" "github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values" "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. // 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 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 { if err != nil {
return values.None, err return values.None, err
} }
err = core.ValidateType(args[1], core.StringType) err = core.ValidateType(args[1], types.String)
if err != nil { if err != nil {
return values.None, err return values.None, err

Some files were not shown because too many files have changed in this diff Show More