Skip to content

Commit

Permalink
add dates to semantic walker
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacov committed Feb 21, 2020
1 parent 7e6506a commit 0eab940
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 1 deletion.
72 changes: 72 additions & 0 deletions v5/pkg/walkers/semantics/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"regexp"
"strings"
"time"

"github.com/yaacov/tree-search-language/v5/pkg/tsl"
)
Expand Down Expand Up @@ -145,6 +146,13 @@ func runSemantics(n tsl.Node, eval EvalFunc) (bool, error) {
if r.Func == tsl.ArrayOp {
return handleNumberArrayOp(n, eval)
}
case tsl.DateOp:
if r.Func == tsl.DateOp {
return handleDateOp(n, eval)
}
if r.Func == tsl.ArrayOp {
return handleDateArrayOp(n, eval)
}
case tsl.BooleanOp:
if r.Func == tsl.BooleanOp {
return handleBooleanOp(n, eval)
Expand Down Expand Up @@ -210,6 +218,11 @@ func evalIdentNode(node tsl.Node, eval EvalFunc) (tsl.Node, error) {
Func: tsl.BooleanOp,
Left: v,
}
case time.Time:
n = tsl.Node{
Func: tsl.DateOp,
Left: v,
}
case float32:
n = tsl.Node{
Func: tsl.NumberOp,
Expand Down Expand Up @@ -417,6 +430,31 @@ func handleNumberOp(n tsl.Node, eval EvalFunc) (bool, error) {
return false, tsl.UnexpectedLiteralError{Literal: n.Func}
}

func handleDateOp(n tsl.Node, eval EvalFunc) (bool, error) {
l := n.Left.(tsl.Node)
r := n.Right.(tsl.Node)

left := l.Left.(time.Time)
right := r.Left.(time.Time)

switch n.Func {
case tsl.EqOp:
return left == right, nil
case tsl.NotEqOp:
return left != right, nil
case tsl.LtOp:
return right.Before(left), nil
case tsl.LteOp:
return !right.After(left), nil
case tsl.GtOp:
return left.Before(right), nil
case tsl.GteOp:
return !left.After(right), nil
}

return false, tsl.UnexpectedLiteralError{Literal: n.Func}
}

func handleBooleanOp(n tsl.Node, eval EvalFunc) (bool, error) {
l := n.Left.(tsl.Node)
r := n.Right.(tsl.Node)
Expand Down Expand Up @@ -500,6 +538,40 @@ func handleNumberArrayOp(n tsl.Node, eval EvalFunc) (bool, error) {
return false, tsl.UnexpectedLiteralError{Literal: n.Func}
}

func handleDateArrayOp(n tsl.Node, eval EvalFunc) (bool, error) {
l := n.Left.(tsl.Node)
r := n.Right.(tsl.Node)

left := l.Left.(time.Time)
right := r.Right.([]tsl.Node)

switch n.Func {
case tsl.BetweenOp:
begin := right[0].Left.(time.Time)
end := right[1].Left.(time.Time)

return !left.Before(begin) && left.Before(end), nil
case tsl.NotBetweenOp:
begin := right[0].Left.(time.Time)
end := right[1].Left.(time.Time)
return left.Before(begin) || !left.Before(end), nil
case tsl.InOp:
b := false
for _, node := range right {
b = b || left == node.Left.(time.Time)
}
return b, nil
case tsl.NotInOp:
b := true
for _, node := range right {
b = b && left != node.Left.(time.Time)
}
return b, nil
}

return false, tsl.UnexpectedLiteralError{Literal: n.Func}
}

func handleLogicalOp(n tsl.Node, eval EvalFunc) (bool, error) {
l := n.Left.(tsl.Node)
r := n.Right.(tsl.Node)
Expand Down
10 changes: 9 additions & 1 deletion v5/pkg/walkers/semantics/walk_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package semantics

import (
"testing"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
Expand All @@ -32,12 +33,14 @@ func TestWalk(t *testing.T) {

var _ = Describe("Walk", func() {
// This is the record that we will use for all the tests:
date, _ := time.Parse(time.RFC3339, "2020-01-01T00:00:00Z")
record := map[string]interface{}{
"title": "A good book",
"author": "Joe",
"spec.pages": 14,
"spec.rating": 5,
"loaned": true,
"date": date,
}

// This is the evaluation function that we will use to extract fields from the record:
Expand Down Expand Up @@ -75,6 +78,11 @@ var _ = Describe("Walk", func() {

// Booleans
Entry("booleans", "spec.pages < 20 and loaned = true", true),
Entry("booleans", "spec.pages < 20 and loaned != true", false),
Entry("booleans false", "spec.pages < 20 and loaned != true", false),

// dates
Entry("dates", "date = 2020-01-01T00:00:00Z", true),
Entry("dates", "date < 2020-01-02T00:00:00Z", false),
Entry("dates", "date between 2019-12-30T00:00:00Z and 2020-01-02T00:00:00Z", true),
)
})

0 comments on commit 0eab940

Please sign in to comment.