Skip to content

Commit

Permalink
FOR LOOP impl
Browse files Browse the repository at this point in the history
  • Loading branch information
ziflex committed Nov 1, 2024
1 parent cdafe80 commit 72d8863
Show file tree
Hide file tree
Showing 120 changed files with 1,233 additions and 638 deletions.
3 changes: 2 additions & 1 deletion e2e/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ import (
"strings"
"time"

"github.com/MontFerret/ferret/pkg/logging"

"github.com/rs/zerolog"

"github.com/MontFerret/ferret"
"github.com/MontFerret/ferret/pkg/drivers/cdp"
"github.com/MontFerret/ferret/pkg/drivers/http"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/logging"
)

type (
Expand Down
15 changes: 0 additions & 15 deletions pkg/compiler/allocator.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ type (
IsAllocated bool
LastUse int // Instruction number of last use
NextUse int // Instruction number of next use
VarName string // Associated variable name, if any
Type RegisterType // Type of variable stored
Lifetime *RegisterLifetime // Lifetime information
}
Expand Down Expand Up @@ -52,20 +51,6 @@ func NewRegisterAllocator() *RegisterAllocator {
}
}

func (ra *RegisterAllocator) AllocateVar(name string) runtime.Operand {
// Allocate register
reg := ra.Allocate(Var)

// Update register status
ra.registers[reg].VarName = name

return reg
}

func (ra *RegisterAllocator) AllocateTemp() runtime.Operand {
return ra.Allocate(Temp)
}

// Allocate assigns a register based on variable type
func (ra *RegisterAllocator) Allocate(regType RegisterType) runtime.Operand {
// Try to find a free register first
Expand Down
249 changes: 125 additions & 124 deletions pkg/compiler/compiler_exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ package compiler_test
import (
"context"
"fmt"
"testing"

"github.com/MontFerret/ferret/pkg/compiler"
"github.com/MontFerret/ferret/pkg/runtime"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"testing"

. "github.com/smartystreets/goconvey/convey"
)
Expand Down Expand Up @@ -159,7 +160,7 @@ func TestVariables(t *testing.T) {
//Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 RETURN i) RETURN i", t, func() {
// c := compiler.New()
// counter := -1
// c.RegisterFunction("COUNTER", func(ctx context.visitor, args ...core.Value) (core.Value, error) {
// c.RegisterFunction("COUNTER", func(ctx context.visitor, args ...core.Second) (core.Second, error) {
// counter++
//
// return values.NewInt(counter), nil
Expand All @@ -182,7 +183,7 @@ func TestVariables(t *testing.T) {
//Convey("Should compile LET i = (FOR i WHILE COUNTER() < 5 T::FAIL() RETURN i)? RETURN i == NONE", t, func() {
// c := compiler.New()
// counter := -1
// c.RegisterFunction("COUNTER", func(ctx context.visitor, args ...core.Value) (core.Value, error) {
// c.RegisterFunction("COUNTER", func(ctx context.visitor, args ...core.Second) (core.Second, error) {
// counter++
//
// return values.NewInt(counter), nil
Expand Down Expand Up @@ -382,7 +383,7 @@ func TestLogicalOperators(t *testing.T) {
//
//Convey("ERROR()? || 'boo' should return 'boo'", t, func() {
// c := compiler.New()
// c.RegisterFunction("ERROR", func(ctx context.visitor, args ...core.Value) (core.Value, error) {
// c.RegisterFunction("ERROR", func(ctx context.visitor, args ...core.Second) (core.Second, error) {
// return nil, errors.New("test")
// })
//
Expand All @@ -400,7 +401,7 @@ func TestLogicalOperators(t *testing.T) {
//
//Convey("!ERROR()? && TRUE should return false", t, func() {
// c := compiler.New()
// c.RegisterFunction("ERROR", func(ctx context.visitor, args ...core.Value) (core.Value, error) {
// c.RegisterFunction("ERROR", func(ctx context.visitor, args ...core.Second) (core.Second, error) {
// return nil, errors.New("test")
// })
//
Expand Down Expand Up @@ -1055,7 +1056,7 @@ func TestMember(t *testing.T) {
//
// Convey("When function returns error", func() {
// c := compiler.New()
// c.RegisterFunction("ERROR", func(ctx context.visitor, args ...core.Value) (core.Value, error) {
// c.RegisterFunction("ERROR", func(ctx context.visitor, args ...core.Second) (core.Second, error) {
// return nil, core.ErrNotImplemented
// })
//
Expand Down Expand Up @@ -1125,124 +1126,124 @@ func TestFor(t *testing.T) {
[]any{1, 2, 3, 4, 5},
ShouldEqualJSON,
},
{
`FOR i IN 1..5
LET x = i
PRINT(x)
RETURN i
`,
[]any{1, 2, 3, 4, 5},
ShouldEqualJSON,
},
{
`FOR val, counter IN 1..5
LET x = val
PRINT(counter)
LET y = counter
RETURN [x, y]
`,
[]any{[]any{1, 0}, []any{2, 1}, []any{3, 2}, []any{4, 3}, []any{5, 4}},
ShouldEqualJSON,
},
{
`FOR i IN [] RETURN i
`,
[]any{},
ShouldEqualJSON,
},
{
`FOR i IN [1, 2, 3] RETURN i
`,
[]any{1, 2, 3},
ShouldEqualJSON,
},

{
`FOR i, k IN [1, 2, 3] RETURN k`,
[]any{0, 1, 2},
ShouldEqualJSON,
},
{
`FOR i IN ['foo', 'bar', 'qaz'] RETURN i`,
[]any{"foo", "bar", "qaz"},
ShouldEqualJSON,
},
{
`FOR i IN {a: 'bar', b: 'foo', c: 'qaz'} RETURN i`,
[]any{"foo", "bar", "qaz"},
ShouldHaveSameItems,
},
{
`FOR i, k IN {a: 'foo', b: 'bar', c: 'qaz'} RETURN k`,
[]any{"a", "b", "c"},
ShouldHaveSameItems,
},
{
`FOR i IN [{name: 'foo'}, {name: 'bar'}, {name: 'qaz'}] RETURN i.name`,
[]any{"foo", "bar", "qaz"},
ShouldHaveSameItems,
},
{
`FOR i IN { items: [{name: 'foo'}, {name: 'bar'}, {name: 'qaz'}] }.items RETURN i.name`,
[]any{"foo", "bar", "qaz"},
ShouldHaveSameItems,
},
{
`FOR prop IN ["a"]
FOR val IN [1, 2, 3]
RETURN {[prop]: val}`,
[]any{map[string]any{"a": 1}, map[string]any{"a": 2}, map[string]any{"a": 3}},
ShouldEqualJSON,
},
{
`FOR val IN 1..3
FOR prop IN ["a"]
RETURN {[prop]: val}`,
[]any{map[string]any{"a": 1}, map[string]any{"a": 2}, map[string]any{"a": 3}},
ShouldEqualJSON,
},
{
`FOR prop IN ["a"]
FOR val IN 1..3
RETURN {[prop]: val}`,
[]any{map[string]any{"a": 1}, map[string]any{"a": 2}, map[string]any{"a": 3}},
ShouldEqualJSON,
},
{
`FOR prop IN ["a"]
FOR val IN [1, 2, 3]
FOR val2 IN [1, 2, 3]
RETURN { [prop]: [val, val2] }`,
[]any{map[string]any{"a": []int{1, 1}}, map[string]any{"a": []int{1, 2}}, map[string]any{"a": []int{1, 3}}, map[string]any{"a": []int{2, 1}}, map[string]any{"a": []int{2, 2}}, map[string]any{"a": []int{2, 3}}, map[string]any{"a": []int{3, 1}}, map[string]any{"a": []int{3, 2}}, map[string]any{"a": []int{3, 3}}},
ShouldEqualJSON,
},
{
`FOR val IN [1, 2, 3]
RETURN (
FOR prop IN ["a", "b", "c"]
RETURN { [prop]: val }
)`,
[]any{[]any{map[string]any{"a": 1}, map[string]any{"b": 1}, map[string]any{"c": 1}}, []any{map[string]any{"a": 2}, map[string]any{"b": 2}, map[string]any{"c": 2}}, []any{map[string]any{"a": 3}, map[string]any{"b": 3}, map[string]any{"c": 3}}},
ShouldEqualJSON,
},
{
`FOR val IN [1, 2, 3]
LET sub = (
FOR prop IN ["a", "b", "c"]
RETURN { [prop]: val }
)
RETURN sub`,
[]any{[]any{map[string]any{"a": 1}, map[string]any{"b": 1}, map[string]any{"c": 1}}, []any{map[string]any{"a": 2}, map[string]any{"b": 2}, map[string]any{"c": 2}}, []any{map[string]any{"a": 3}, map[string]any{"b": 3}, map[string]any{"c": 3}}},
ShouldEqualJSON,
},
{
`FOR i IN [ 1, 2, 3, 4, 1, 3 ]
RETURN DISTINCT i
`,
[]any{1, 2, 3, 4},
ShouldEqualJSON,
},
//{
// `FOR i IN 1..5
// LET x = i
// PRINT(x)
// RETURN i
// `,
// []any{1, 2, 3, 4, 5},
// ShouldEqualJSON,
//},
//{
// `FOR val, counter IN 1..5
// LET x = val
// PRINT(counter)
// LET y = counter
// RETURN [x, y]
//`,
// []any{[]any{1, 0}, []any{2, 1}, []any{3, 2}, []any{4, 3}, []any{5, 4}},
// ShouldEqualJSON,
//},
//{
// `FOR i IN [] RETURN i
//`,
// []any{},
// ShouldEqualJSON,
//},
//{
// `FOR i IN [1, 2, 3] RETURN i
//`,
// []any{1, 2, 3},
// ShouldEqualJSON,
//},
//
//{
// `FOR i, k IN [1, 2, 3] RETURN k`,
// []any{0, 1, 2},
// ShouldEqualJSON,
//},
//{
// `FOR i IN ['foo', 'bar', 'qaz'] RETURN i`,
// []any{"foo", "bar", "qaz"},
// ShouldEqualJSON,
//},
//{
// `FOR i IN {a: 'bar', b: 'foo', c: 'qaz'} RETURN i`,
// []any{"foo", "bar", "qaz"},
// ShouldHaveSameItems,
//},
//{
// `FOR i, k IN {a: 'foo', b: 'bar', c: 'qaz'} RETURN k`,
// []any{"a", "b", "c"},
// ShouldHaveSameItems,
//},
//{
// `FOR i IN [{name: 'foo'}, {name: 'bar'}, {name: 'qaz'}] RETURN i.name`,
// []any{"foo", "bar", "qaz"},
// ShouldHaveSameItems,
//},
//{
// `FOR i IN { items: [{name: 'foo'}, {name: 'bar'}, {name: 'qaz'}] }.items RETURN i.name`,
// []any{"foo", "bar", "qaz"},
// ShouldHaveSameItems,
//},
//{
// `FOR prop IN ["a"]
// FOR val IN [1, 2, 3]
// RETURN {[prop]: val}`,
// []any{map[string]any{"a": 1}, map[string]any{"a": 2}, map[string]any{"a": 3}},
// ShouldEqualJSON,
//},
//{
// `FOR val IN 1..3
// FOR prop IN ["a"]
// RETURN {[prop]: val}`,
// []any{map[string]any{"a": 1}, map[string]any{"a": 2}, map[string]any{"a": 3}},
// ShouldEqualJSON,
//},
//{
// `FOR prop IN ["a"]
// FOR val IN 1..3
// RETURN {[prop]: val}`,
// []any{map[string]any{"a": 1}, map[string]any{"a": 2}, map[string]any{"a": 3}},
// ShouldEqualJSON,
//},
//{
// `FOR prop IN ["a"]
// FOR val IN [1, 2, 3]
// FOR val2 IN [1, 2, 3]
// RETURN { [prop]: [val, val2] }`,
// []any{map[string]any{"a": []int{1, 1}}, map[string]any{"a": []int{1, 2}}, map[string]any{"a": []int{1, 3}}, map[string]any{"a": []int{2, 1}}, map[string]any{"a": []int{2, 2}}, map[string]any{"a": []int{2, 3}}, map[string]any{"a": []int{3, 1}}, map[string]any{"a": []int{3, 2}}, map[string]any{"a": []int{3, 3}}},
// ShouldEqualJSON,
//},
//{
// `FOR val IN [1, 2, 3]
// RETURN (
// FOR prop IN ["a", "b", "c"]
// RETURN { [prop]: val }
// )`,
// []any{[]any{map[string]any{"a": 1}, map[string]any{"b": 1}, map[string]any{"c": 1}}, []any{map[string]any{"a": 2}, map[string]any{"b": 2}, map[string]any{"c": 2}}, []any{map[string]any{"a": 3}, map[string]any{"b": 3}, map[string]any{"c": 3}}},
// ShouldEqualJSON,
//},
//{
// `FOR val IN [1, 2, 3]
// LET sub = (
// FOR prop IN ["a", "b", "c"]
// RETURN { [prop]: val }
// )
//
// RETURN sub`,
// []any{[]any{map[string]any{"a": 1}, map[string]any{"b": 1}, map[string]any{"c": 1}}, []any{map[string]any{"a": 2}, map[string]any{"b": 2}, map[string]any{"c": 2}}, []any{map[string]any{"a": 3}, map[string]any{"b": 3}, map[string]any{"c": 3}}},
// ShouldEqualJSON,
//},
//{
// `FOR i IN [ 1, 2, 3, 4, 1, 3 ]
// RETURN DISTINCT i
//`,
// []any{1, 2, 3, 4},
// ShouldEqualJSON,
//},
})
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/compiler/compiler_setup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import (
"context"
j "encoding/json"
"fmt"
"github.com/MontFerret/ferret/pkg/runtime/core"
"strings"
"testing"

"github.com/MontFerret/ferret/pkg/runtime/core"

. "github.com/smartystreets/goconvey/convey"

"github.com/MontFerret/ferret/pkg/compiler"
Expand Down
3 changes: 2 additions & 1 deletion pkg/compiler/compiler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package compiler_test

import (
"fmt"
"testing"

"github.com/MontFerret/ferret/pkg/runtime"
"github.com/MontFerret/ferret/pkg/runtime/core"
"github.com/MontFerret/ferret/pkg/runtime/values"
"testing"
)

func Disassembly(instr []string, opcodes ...runtime.Opcode) string {
Expand Down
Loading

0 comments on commit 72d8863

Please sign in to comment.