mirror of
https://github.com/MontFerret/ferret.git
synced 2025-08-13 19:52:52 +02:00
Refactor compiler structure; move internal packages to core and update references
This commit is contained in:
@@ -2,6 +2,7 @@ package compiler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
goruntime "runtime"
|
goruntime "runtime"
|
||||||
|
|
||||||
"github.com/MontFerret/ferret/pkg/compiler/internal"
|
"github.com/MontFerret/ferret/pkg/compiler/internal"
|
||||||
@@ -37,7 +38,7 @@ func New(setters ...Option) *Compiler {
|
|||||||
|
|
||||||
func (c *Compiler) Compile(query string) (program *vm.Program, err error) {
|
func (c *Compiler) Compile(query string) (program *vm.Program, err error) {
|
||||||
if query == "" {
|
if query == "" {
|
||||||
return nil, internal.ErrEmptyQuery
|
return nil, core.ErrEmptyQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
|
import "github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
|
|
||||||
// FuncContext encapsulates the context and state required for compiling and managing functions during code processing.
|
// FuncContext encapsulates the context and state required for compiling and managing functions during code processing.
|
||||||
type FuncContext struct {
|
type FuncContext struct {
|
||||||
Emitter *Emitter
|
Emitter *core.Emitter
|
||||||
Registers *RegisterAllocator
|
Registers *core.RegisterAllocator
|
||||||
Symbols *SymbolTable
|
Symbols *core.SymbolTable
|
||||||
Loops *LoopTable
|
Loops *core.LoopTable
|
||||||
CatchTable *CatchStack
|
CatchTable *core.CatchStack
|
||||||
|
|
||||||
ExprCompiler *ExprCompiler
|
ExprCompiler *ExprCompiler
|
||||||
LiteralCompiler *LiteralCompiler
|
LiteralCompiler *LiteralCompiler
|
||||||
@@ -19,14 +21,14 @@ type FuncContext struct {
|
|||||||
// NewFuncContext initializes and returns a new instance of FuncContext, setting up all required components for compilation.
|
// NewFuncContext initializes and returns a new instance of FuncContext, setting up all required components for compilation.
|
||||||
func NewFuncContext() *FuncContext {
|
func NewFuncContext() *FuncContext {
|
||||||
ctx := &FuncContext{
|
ctx := &FuncContext{
|
||||||
Emitter: NewEmitter(),
|
Emitter: core.NewEmitter(),
|
||||||
Registers: NewRegisterAllocator(),
|
Registers: core.NewRegisterAllocator(),
|
||||||
Symbols: nil, // set later
|
Symbols: nil, // set later
|
||||||
Loops: nil, // set later
|
Loops: nil, // set later
|
||||||
CatchTable: NewCatchStack(),
|
CatchTable: core.NewCatchStack(),
|
||||||
}
|
}
|
||||||
ctx.Symbols = NewSymbolTable(ctx.Registers)
|
ctx.Symbols = core.NewSymbolTable(ctx.Registers)
|
||||||
ctx.Loops = NewLoopTable(ctx.Registers)
|
ctx.Loops = core.NewLoopTable(ctx.Registers)
|
||||||
|
|
||||||
ctx.ExprCompiler = NewExprCompiler(ctx)
|
ctx.ExprCompiler = NewExprCompiler(ctx)
|
||||||
ctx.LiteralCompiler = NewLiteralCompiler(ctx)
|
ctx.LiteralCompiler = NewLiteralCompiler(ctx)
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/MontFerret/ferret/pkg/runtime"
|
"github.com/MontFerret/ferret/pkg/runtime"
|
8
pkg/compiler/internal/core/constants.go
Normal file
8
pkg/compiler/internal/core/constants.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package core
|
||||||
|
|
||||||
|
const (
|
||||||
|
JumpPlaceholder = -1
|
||||||
|
UndefinedVariable = -1
|
||||||
|
IgnorePseudoVariable = "_"
|
||||||
|
PseudoVariable = "CURRENT"
|
||||||
|
)
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
import "github.com/pkg/errors"
|
||||||
|
|
@@ -1,6 +1,8 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import "github.com/MontFerret/ferret/pkg/vm"
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
|
)
|
||||||
|
|
||||||
type LoopType int
|
type LoopType int
|
||||||
|
|
||||||
@@ -76,5 +78,5 @@ func (l *Loop) EmitFinalization(emitter *Emitter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *Loop) canBindVar(name string) bool {
|
func (l *Loop) canBindVar(name string) bool {
|
||||||
return name != "" && name != ignorePseudoVariable
|
return name != "" && name != IgnorePseudoVariable
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@@ -1,4 +1,4 @@
|
|||||||
package internal
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@@ -1,4 +1,4 @@
|
|||||||
package internal_test
|
package core_test
|
||||||
|
|
||||||
import "testing"
|
import "testing"
|
||||||
|
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
"github.com/MontFerret/ferret/pkg/parser/fql"
|
"github.com/MontFerret/ferret/pkg/parser/fql"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime"
|
"github.com/MontFerret/ferret/pkg/runtime"
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
@@ -44,13 +45,13 @@ func (ec *ExprCompiler) Compile(ctx fql.IExpressionContext) vm.Operand {
|
|||||||
return ec.compilePredicate(c)
|
return ec.compilePredicate(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Free temporary registers if needed
|
// TODO: Free temporary registers if needed
|
||||||
func (ec *ExprCompiler) compileUnary(ctx fql.IUnaryOperatorContext, parent fql.IExpressionContext) vm.Operand {
|
func (ec *ExprCompiler) compileUnary(ctx fql.IUnaryOperatorContext, parent fql.IExpressionContext) vm.Operand {
|
||||||
src := ec.Compile(parent.GetRight())
|
src := ec.Compile(parent.GetRight())
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
var op vm.Opcode
|
var op vm.Opcode
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ func (ec *ExprCompiler) compileUnary(ctx fql.IUnaryOperatorContext, parent fql.I
|
|||||||
} else if ctx.Plus() != nil {
|
} else if ctx.Plus() != nil {
|
||||||
op = vm.OpFlipPositive
|
op = vm.OpFlipPositive
|
||||||
} else {
|
} else {
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do not overwrite the source register
|
// We do not overwrite the source register
|
||||||
@@ -72,7 +73,7 @@ func (ec *ExprCompiler) compileUnary(ctx fql.IUnaryOperatorContext, parent fql.I
|
|||||||
|
|
||||||
// TODO: Free temporary registers if needed
|
// TODO: Free temporary registers if needed
|
||||||
func (ec *ExprCompiler) compileLogicalAnd(ctx fql.IPredicateContext) vm.Operand {
|
func (ec *ExprCompiler) compileLogicalAnd(ctx fql.IPredicateContext) vm.Operand {
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
// Execute left expression
|
// Execute left expression
|
||||||
left := ec.compilePredicate(ctx.GetLeft())
|
left := ec.compilePredicate(ctx.GetLeft())
|
||||||
@@ -81,7 +82,7 @@ func (ec *ExprCompiler) compileLogicalAnd(ctx fql.IPredicateContext) vm.Operand
|
|||||||
ec.ctx.Emitter.EmitMove(dst, left)
|
ec.ctx.Emitter.EmitMove(dst, left)
|
||||||
|
|
||||||
// Test if left is false and jump to the end
|
// Test if left is false and jump to the end
|
||||||
end := ec.ctx.Emitter.EmitJumpIfFalse(dst, jumpPlaceholder)
|
end := ec.ctx.Emitter.EmitJumpIfFalse(dst, core.JumpPlaceholder)
|
||||||
|
|
||||||
// If left is true, execute right expression
|
// If left is true, execute right expression
|
||||||
right := ec.compilePredicate(ctx.GetRight())
|
right := ec.compilePredicate(ctx.GetRight())
|
||||||
@@ -96,7 +97,7 @@ func (ec *ExprCompiler) compileLogicalAnd(ctx fql.IPredicateContext) vm.Operand
|
|||||||
|
|
||||||
// TODO: Free temporary registers if needed
|
// TODO: Free temporary registers if needed
|
||||||
func (ec *ExprCompiler) compileLogicalOr(ctx fql.IPredicateContext) vm.Operand {
|
func (ec *ExprCompiler) compileLogicalOr(ctx fql.IPredicateContext) vm.Operand {
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
// Execute left expression
|
// Execute left expression
|
||||||
left := ec.compilePredicate(ctx.GetLeft())
|
left := ec.compilePredicate(ctx.GetLeft())
|
||||||
@@ -105,7 +106,7 @@ func (ec *ExprCompiler) compileLogicalOr(ctx fql.IPredicateContext) vm.Operand {
|
|||||||
ec.ctx.Emitter.EmitMove(dst, left)
|
ec.ctx.Emitter.EmitMove(dst, left)
|
||||||
|
|
||||||
// Test if left is true and jump to the end
|
// Test if left is true and jump to the end
|
||||||
end := ec.ctx.Emitter.EmitJumpIfTrue(dst, jumpPlaceholder)
|
end := ec.ctx.Emitter.EmitJumpIfTrue(dst, core.JumpPlaceholder)
|
||||||
|
|
||||||
// If left is false, execute right expression
|
// If left is false, execute right expression
|
||||||
right := ec.compilePredicate(ctx.GetRight())
|
right := ec.compilePredicate(ctx.GetRight())
|
||||||
@@ -120,14 +121,14 @@ func (ec *ExprCompiler) compileLogicalOr(ctx fql.IPredicateContext) vm.Operand {
|
|||||||
|
|
||||||
// TODO: Free temporary registers if needed
|
// TODO: Free temporary registers if needed
|
||||||
func (ec *ExprCompiler) compileTernary(ctx fql.IExpressionContext) vm.Operand {
|
func (ec *ExprCompiler) compileTernary(ctx fql.IExpressionContext) vm.Operand {
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
// Compile condition and put result in dst
|
// Compile condition and put result in dst
|
||||||
condReg := ec.Compile(ctx.GetCondition())
|
condReg := ec.Compile(ctx.GetCondition())
|
||||||
ec.ctx.Emitter.EmitMove(dst, condReg)
|
ec.ctx.Emitter.EmitMove(dst, condReg)
|
||||||
|
|
||||||
// Jump to 'false' branch if condition is false
|
// Jump to 'false' branch if condition is false
|
||||||
otherwise := ec.ctx.Emitter.EmitJumpIfFalse(dst, jumpPlaceholder)
|
otherwise := ec.ctx.Emitter.EmitJumpIfFalse(dst, core.JumpPlaceholder)
|
||||||
|
|
||||||
// True branch
|
// True branch
|
||||||
if onTrue := ctx.GetOnTrue(); onTrue != nil {
|
if onTrue := ctx.GetOnTrue(); onTrue != nil {
|
||||||
@@ -137,7 +138,7 @@ func (ec *ExprCompiler) compileTernary(ctx fql.IExpressionContext) vm.Operand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Jump over false branch
|
// Jump over false branch
|
||||||
end := ec.ctx.Emitter.EmitJump(jumpPlaceholder)
|
end := ec.ctx.Emitter.EmitJump(core.JumpPlaceholder)
|
||||||
ec.ctx.Emitter.PatchJumpNext(otherwise)
|
ec.ctx.Emitter.PatchJumpNext(otherwise)
|
||||||
|
|
||||||
// False branch
|
// False branch
|
||||||
@@ -174,7 +175,7 @@ func (ec *ExprCompiler) compilePredicate(ctx fql.IPredicateContext) vm.Operand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var opcode vm.Opcode
|
var opcode vm.Opcode
|
||||||
dest := ec.ctx.Registers.Allocate(Temp)
|
dest := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
left := ec.compilePredicate(ctx.Predicate(0))
|
left := ec.compilePredicate(ctx.Predicate(0))
|
||||||
right := ec.compilePredicate(ctx.Predicate(1))
|
right := ec.compilePredicate(ctx.Predicate(1))
|
||||||
|
|
||||||
@@ -193,7 +194,7 @@ func (ec *ExprCompiler) compilePredicate(ctx fql.IPredicateContext) vm.Operand {
|
|||||||
case "<=":
|
case "<=":
|
||||||
opcode = vm.OpLte
|
opcode = vm.OpLte
|
||||||
default:
|
default:
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
} else if op := ctx.ArrayOperator(); op != nil {
|
} else if op := ctx.ArrayOperator(); op != nil {
|
||||||
// TODO: Implement me
|
// TODO: Implement me
|
||||||
@@ -233,7 +234,7 @@ func (ec *ExprCompiler) compileAtom(ctx fql.IExpressionAtomContext) vm.Operand {
|
|||||||
case "%":
|
case "%":
|
||||||
opcode = vm.OpMod
|
opcode = vm.OpMod
|
||||||
default:
|
default:
|
||||||
panic(runtime.Error(ErrUnexpectedToken, op.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, op.GetText()))
|
||||||
}
|
}
|
||||||
} else if op := ctx.AdditiveOperator(); op != nil {
|
} else if op := ctx.AdditiveOperator(); op != nil {
|
||||||
isSet = true
|
isSet = true
|
||||||
@@ -244,7 +245,7 @@ func (ec *ExprCompiler) compileAtom(ctx fql.IExpressionAtomContext) vm.Operand {
|
|||||||
case "-":
|
case "-":
|
||||||
opcode = vm.OpSub
|
opcode = vm.OpSub
|
||||||
default:
|
default:
|
||||||
panic(runtime.Error(ErrUnexpectedToken, op.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, op.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if op := ctx.RegexpOperator(); op != nil {
|
} else if op := ctx.RegexpOperator(); op != nil {
|
||||||
@@ -256,14 +257,14 @@ func (ec *ExprCompiler) compileAtom(ctx fql.IExpressionAtomContext) vm.Operand {
|
|||||||
case "!~":
|
case "!~":
|
||||||
opcode = vm.OpRegexpNegative
|
opcode = vm.OpRegexpNegative
|
||||||
default:
|
default:
|
||||||
panic(runtime.Error(ErrUnexpectedToken, op.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, op.GetText()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSet {
|
if isSet {
|
||||||
regLeft := ec.compileAtom(ctx.ExpressionAtom(0))
|
regLeft := ec.compileAtom(ctx.ExpressionAtom(0))
|
||||||
regRight := ec.compileAtom(ctx.ExpressionAtom(1))
|
regRight := ec.compileAtom(ctx.ExpressionAtom(1))
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
if opcode == vm.OpRegexpPositive || opcode == vm.OpRegexpNegative {
|
if opcode == vm.OpRegexpPositive || opcode == vm.OpRegexpNegative {
|
||||||
if regRight.IsConstant() {
|
if regRight.IsConstant() {
|
||||||
@@ -299,7 +300,7 @@ func (ec *ExprCompiler) compileAtom(ctx fql.IExpressionAtomContext) vm.Operand {
|
|||||||
return ec.Compile(c)
|
return ec.Compile(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *ExprCompiler) CompileMemberExpression(ctx fql.IMemberExpressionContext) vm.Operand {
|
func (ec *ExprCompiler) CompileMemberExpression(ctx fql.IMemberExpressionContext) vm.Operand {
|
||||||
@@ -334,7 +335,7 @@ func (ec *ExprCompiler) CompileMemberExpression(ctx fql.IMemberExpressionContext
|
|||||||
src2 = ec.ctx.LiteralCompiler.CompileComputedPropertyName(c)
|
src2 = ec.ctx.LiteralCompiler.CompileComputedPropertyName(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst = ec.ctx.Registers.Allocate(Temp)
|
dst = ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
// TODO: Replace with EmitLoadKey
|
// TODO: Replace with EmitLoadKey
|
||||||
if p.ErrorOperator() != nil {
|
if p.ErrorOperator() != nil {
|
||||||
@@ -354,14 +355,14 @@ func (ec *ExprCompiler) CompileVariable(ctx fql.IVariableContext) vm.Operand {
|
|||||||
op, _, found := ec.ctx.Symbols.Resolve(ctx.GetText())
|
op, _, found := ec.ctx.Symbols.Resolve(ctx.GetText())
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
panic(runtime.Error(ErrVariableNotFound, ctx.GetText()))
|
panic(runtime.Error(core.ErrVariableNotFound, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if op.IsRegister() {
|
if op.IsRegister() {
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
reg := ec.ctx.Registers.Allocate(Temp)
|
reg := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
ec.ctx.Emitter.EmitLoadGlobal(reg, op)
|
ec.ctx.Emitter.EmitLoadGlobal(reg, op)
|
||||||
|
|
||||||
return reg
|
return reg
|
||||||
@@ -388,7 +389,7 @@ func (ec *ExprCompiler) CompileFunctionCall(ctx fql.IFunctionCallContext, protec
|
|||||||
|
|
||||||
switch name {
|
switch name {
|
||||||
case runtimeLength:
|
case runtimeLength:
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
if seq == nil || len(seq) != 1 {
|
if seq == nil || len(seq) != 1 {
|
||||||
panic(runtime.Error(runtime.ErrInvalidArgument, runtimeLength+": expected 1 argument"))
|
panic(runtime.Error(runtime.ErrInvalidArgument, runtimeLength+": expected 1 argument"))
|
||||||
@@ -398,7 +399,7 @@ func (ec *ExprCompiler) CompileFunctionCall(ctx fql.IFunctionCallContext, protec
|
|||||||
|
|
||||||
return dst
|
return dst
|
||||||
case runtimeTypename:
|
case runtimeTypename:
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
if seq == nil || len(seq) != 1 {
|
if seq == nil || len(seq) != 1 {
|
||||||
panic(runtime.Error(runtime.ErrInvalidArgument, runtimeTypename+": expected 1 argument"))
|
panic(runtime.Error(runtime.ErrInvalidArgument, runtimeTypename+": expected 1 argument"))
|
||||||
@@ -416,7 +417,7 @@ func (ec *ExprCompiler) CompileFunctionCall(ctx fql.IFunctionCallContext, protec
|
|||||||
|
|
||||||
return seq[0]
|
return seq[0]
|
||||||
default:
|
default:
|
||||||
dest := ec.ctx.Registers.Allocate(Temp)
|
dest := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
ec.ctx.Emitter.EmitLoadConst(dest, ec.ctx.Symbols.AddConstant(name))
|
ec.ctx.Emitter.EmitLoadConst(dest, ec.ctx.Symbols.AddConstant(name))
|
||||||
|
|
||||||
if !protected {
|
if !protected {
|
||||||
@@ -429,8 +430,8 @@ func (ec *ExprCompiler) CompileFunctionCall(ctx fql.IFunctionCallContext, protec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *ExprCompiler) CompileArgumentList(ctx fql.IArgumentListContext) RegisterSequence {
|
func (ec *ExprCompiler) CompileArgumentList(ctx fql.IArgumentListContext) core.RegisterSequence {
|
||||||
var seq RegisterSequence
|
var seq core.RegisterSequence
|
||||||
// Get all array element expressions
|
// Get all array element expressions
|
||||||
exps := ctx.AllExpression()
|
exps := ctx.AllExpression()
|
||||||
size := len(exps)
|
size := len(exps)
|
||||||
@@ -458,7 +459,7 @@ func (ec *ExprCompiler) CompileArgumentList(ctx fql.IArgumentListContext) Regist
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ec *ExprCompiler) CompileRangeOperator(ctx fql.IRangeOperatorContext) vm.Operand {
|
func (ec *ExprCompiler) CompileRangeOperator(ctx fql.IRangeOperatorContext) vm.Operand {
|
||||||
dst := ec.ctx.Registers.Allocate(Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
start := ec.compileRangeOperand(ctx.GetLeft())
|
start := ec.compileRangeOperand(ctx.GetLeft())
|
||||||
end := ec.compileRangeOperand(ctx.GetRight())
|
end := ec.compileRangeOperand(ctx.GetRight())
|
||||||
|
|
||||||
@@ -480,7 +481,7 @@ func (ec *ExprCompiler) compileRangeOperand(ctx fql.IRangeOperandContext) vm.Ope
|
|||||||
return ec.ctx.LiteralCompiler.CompileIntegerLiteral(c)
|
return ec.ctx.LiteralCompiler.CompileIntegerLiteral(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *ExprCompiler) functionName(ctx fql.IFunctionCallContext) runtime.String {
|
func (ec *ExprCompiler) functionName(ctx fql.IFunctionCallContext) runtime.String {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
"github.com/antlr4-go/antlr/v4"
|
"github.com/antlr4-go/antlr/v4"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -11,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func loadConstant(ctx *FuncContext, value runtime.Value) vm.Operand {
|
func loadConstant(ctx *FuncContext, value runtime.Value) vm.Operand {
|
||||||
reg := ctx.Registers.Allocate(Temp)
|
reg := ctx.Registers.Allocate(core.Temp)
|
||||||
ctx.Emitter.EmitLoadConst(reg, ctx.Symbols.AddConstant(value))
|
ctx.Emitter.EmitLoadConst(reg, ctx.Symbols.AddConstant(value))
|
||||||
return reg
|
return reg
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
"github.com/MontFerret/ferret/pkg/parser/fql"
|
"github.com/MontFerret/ferret/pkg/parser/fql"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime"
|
"github.com/MontFerret/ferret/pkg/runtime"
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
@@ -36,7 +37,7 @@ func (lc *LiteralCompiler) Compile(ctx fql.ILiteralContext) vm.Operand {
|
|||||||
return lc.CompileNoneLiteral(c)
|
return lc.CompileNoneLiteral(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LiteralCompiler) CompileStringLiteral(ctx fql.IStringLiteralContext) vm.Operand {
|
func (lc *LiteralCompiler) CompileStringLiteral(ctx fql.IStringLiteralContext) vm.Operand {
|
||||||
@@ -109,7 +110,7 @@ func (lc *LiteralCompiler) CompileFloatLiteral(ctx fql.IFloatLiteralContext) vm.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LiteralCompiler) CompileBooleanLiteral(ctx fql.IBooleanLiteralContext) vm.Operand {
|
func (lc *LiteralCompiler) CompileBooleanLiteral(ctx fql.IBooleanLiteralContext) vm.Operand {
|
||||||
reg := lc.ctx.Registers.Allocate(Temp)
|
reg := lc.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
switch strings.ToLower(ctx.GetText()) {
|
switch strings.ToLower(ctx.GetText()) {
|
||||||
case "true":
|
case "true":
|
||||||
@@ -117,14 +118,14 @@ func (lc *LiteralCompiler) CompileBooleanLiteral(ctx fql.IBooleanLiteralContext)
|
|||||||
case "false":
|
case "false":
|
||||||
lc.ctx.Emitter.EmitBoolean(reg, false)
|
lc.ctx.Emitter.EmitBoolean(reg, false)
|
||||||
default:
|
default:
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return reg
|
return reg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LiteralCompiler) CompileNoneLiteral(_ fql.INoneLiteralContext) vm.Operand {
|
func (lc *LiteralCompiler) CompileNoneLiteral(_ fql.INoneLiteralContext) vm.Operand {
|
||||||
reg := lc.ctx.Registers.Allocate(Temp)
|
reg := lc.ctx.Registers.Allocate(core.Temp)
|
||||||
lc.ctx.Emitter.EmitA(vm.OpLoadNone, reg)
|
lc.ctx.Emitter.EmitA(vm.OpLoadNone, reg)
|
||||||
|
|
||||||
return reg
|
return reg
|
||||||
@@ -132,7 +133,7 @@ func (lc *LiteralCompiler) CompileNoneLiteral(_ fql.INoneLiteralContext) vm.Oper
|
|||||||
|
|
||||||
func (lc *LiteralCompiler) CompileArrayLiteral(ctx fql.IArrayLiteralContext) vm.Operand {
|
func (lc *LiteralCompiler) CompileArrayLiteral(ctx fql.IArrayLiteralContext) vm.Operand {
|
||||||
// Allocate destination register for the array
|
// Allocate destination register for the array
|
||||||
destReg := lc.ctx.Registers.Allocate(Temp)
|
destReg := lc.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
if list := ctx.ArgumentList(); list != nil {
|
if list := ctx.ArgumentList(); list != nil {
|
||||||
// Get all array element expressions
|
// Get all array element expressions
|
||||||
@@ -174,7 +175,7 @@ func (lc *LiteralCompiler) CompileArrayLiteral(ctx fql.IArrayLiteralContext) vm.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LiteralCompiler) CompileObjectLiteral(ctx fql.IObjectLiteralContext) vm.Operand {
|
func (lc *LiteralCompiler) CompileObjectLiteral(ctx fql.IObjectLiteralContext) vm.Operand {
|
||||||
dst := lc.ctx.Registers.Allocate(Temp)
|
dst := lc.ctx.Registers.Allocate(core.Temp)
|
||||||
assignments := ctx.AllPropertyAssignment()
|
assignments := ctx.AllPropertyAssignment()
|
||||||
size := len(assignments)
|
size := len(assignments)
|
||||||
|
|
||||||
@@ -232,7 +233,7 @@ func (lc *LiteralCompiler) CompilePropertyName(ctx fql.IPropertyNameContext) vm.
|
|||||||
} else if word := ctx.UnsafeReservedWord(); word != nil {
|
} else if word := ctx.UnsafeReservedWord(); word != nil {
|
||||||
name = word.GetText()
|
name = word.GetText()
|
||||||
} else {
|
} else {
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return loadConstant(lc.ctx, runtime.NewString(name))
|
return loadConstant(lc.ctx, runtime.NewString(name))
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
"github.com/MontFerret/ferret/pkg/parser/fql"
|
"github.com/MontFerret/ferret/pkg/parser/fql"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime"
|
"github.com/MontFerret/ferret/pkg/runtime"
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
@@ -18,23 +19,23 @@ func NewLoopCompiler(ctx *FuncContext) *LoopCompiler {
|
|||||||
func (lc *LoopCompiler) Compile(ctx fql.IForExpressionContext) vm.Operand {
|
func (lc *LoopCompiler) Compile(ctx fql.IForExpressionContext) vm.Operand {
|
||||||
var distinct bool
|
var distinct bool
|
||||||
var returnRuleCtx antlr.RuleContext
|
var returnRuleCtx antlr.RuleContext
|
||||||
var loopType LoopType
|
var loopType core.LoopType
|
||||||
returnCtx := ctx.ForExpressionReturn()
|
returnCtx := ctx.ForExpressionReturn()
|
||||||
|
|
||||||
if c := returnCtx.ReturnExpression(); c != nil {
|
if c := returnCtx.ReturnExpression(); c != nil {
|
||||||
returnRuleCtx = c
|
returnRuleCtx = c
|
||||||
distinct = c.Distinct() != nil
|
distinct = c.Distinct() != nil
|
||||||
loopType = NormalLoop
|
loopType = core.NormalLoop
|
||||||
} else if c := returnCtx.ForExpression(); c != nil {
|
} else if c := returnCtx.ForExpression(); c != nil {
|
||||||
returnRuleCtx = c
|
returnRuleCtx = c
|
||||||
loopType = PassThroughLoop
|
loopType = core.PassThroughLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
loop := lc.ctx.Loops.NewLoop(loopType, ForLoop, distinct)
|
loop := lc.ctx.Loops.NewLoop(loopType, core.ForLoop, distinct)
|
||||||
lc.ctx.Symbols.EnterScope()
|
lc.ctx.Symbols.EnterScope()
|
||||||
lc.ctx.Loops.Push(loop)
|
lc.ctx.Loops.Push(loop)
|
||||||
|
|
||||||
if loop.Kind == ForLoop {
|
if loop.Kind == core.ForLoop {
|
||||||
loop.Src = lc.CompileForExpressionSource(ctx.ForExpressionSource())
|
loop.Src = lc.CompileForExpressionSource(ctx.ForExpressionSource())
|
||||||
|
|
||||||
if val := ctx.GetValueVariable(); val != nil {
|
if val := ctx.GetValueVariable(); val != nil {
|
||||||
@@ -63,7 +64,7 @@ func (lc *LoopCompiler) Compile(ctx fql.IForExpressionContext) vm.Operand {
|
|||||||
loop = lc.ctx.Loops.Current()
|
loop = lc.ctx.Loops.Current()
|
||||||
|
|
||||||
// RETURN
|
// RETURN
|
||||||
if loop.Type != PassThroughLoop {
|
if loop.Type != core.PassThroughLoop {
|
||||||
c := returnRuleCtx.(*fql.ReturnExpressionContext)
|
c := returnRuleCtx.(*fql.ReturnExpressionContext)
|
||||||
expReg := lc.ctx.ExprCompiler.Compile(c.Expression())
|
expReg := lc.ctx.ExprCompiler.Compile(c.Expression())
|
||||||
|
|
||||||
@@ -111,7 +112,7 @@ func (lc *LoopCompiler) CompileForExpressionSource(ctx fql.IForExpressionSourceC
|
|||||||
return lc.ctx.LiteralCompiler.CompileObjectLiteral(c)
|
return lc.ctx.LiteralCompiler.CompileObjectLiteral(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LoopCompiler) CompileForExpressionStatement(ctx fql.IForExpressionStatementContext) {
|
func (lc *LoopCompiler) CompileForExpressionStatement(ctx fql.IForExpressionStatementContext) {
|
||||||
@@ -168,17 +169,17 @@ func (lc *LoopCompiler) CompileLimitClauseValue(ctx fql.ILimitClauseValueContext
|
|||||||
return lc.ctx.ExprCompiler.CompileFunctionCallExpression(c)
|
return lc.ctx.ExprCompiler.CompileFunctionCallExpression(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LoopCompiler) CompileLimit(src vm.Operand) {
|
func (lc *LoopCompiler) CompileLimit(src vm.Operand) {
|
||||||
state := lc.ctx.Registers.Allocate(State)
|
state := lc.ctx.Registers.Allocate(core.State)
|
||||||
lc.ctx.Emitter.EmitABx(vm.OpIterLimit, state, src, lc.ctx.Loops.Current().Jump)
|
lc.ctx.Emitter.EmitABx(vm.OpIterLimit, state, src, lc.ctx.Loops.Current().Jump)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LoopCompiler) CompileOffset(src vm.Operand) {
|
func (lc *LoopCompiler) CompileOffset(src vm.Operand) {
|
||||||
state := lc.ctx.Registers.Allocate(State)
|
state := lc.ctx.Registers.Allocate(core.State)
|
||||||
lc.ctx.Emitter.EmitABx(vm.OpIterSkip, state, src, lc.ctx.Loops.Current().Jump)
|
lc.ctx.Emitter.EmitABx(vm.OpIterSkip, state, src, lc.ctx.Loops.Current().Jump)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +195,7 @@ func (lc *LoopCompiler) CompileSortClause(ctx fql.ISortClauseContext) {
|
|||||||
// And wrap each loop element by a KeyValuePair
|
// And wrap each loop element by a KeyValuePair
|
||||||
// Where a key is either a single value or a list of values
|
// Where a key is either a single value or a list of values
|
||||||
// These KeyValuePairs are then added to the dataset
|
// These KeyValuePairs are then added to the dataset
|
||||||
kvKeyReg := lc.ctx.Registers.Allocate(Temp)
|
kvKeyReg := lc.ctx.Registers.Allocate(core.Temp)
|
||||||
clauses := ctx.AllSortClauseExpression()
|
clauses := ctx.AllSortClauseExpression()
|
||||||
var directions []runtime.SortDirection
|
var directions []runtime.SortDirection
|
||||||
isSortMany := len(clauses) > 1
|
isSortMany := len(clauses) > 1
|
||||||
@@ -214,7 +215,7 @@ func (lc *LoopCompiler) CompileSortClause(ctx fql.ISortClauseContext) {
|
|||||||
// TODO: Free Registers
|
// TODO: Free Registers
|
||||||
}
|
}
|
||||||
|
|
||||||
arrReg := lc.ctx.Registers.Allocate(Temp)
|
arrReg := lc.ctx.Registers.Allocate(core.Temp)
|
||||||
lc.ctx.Emitter.EmitAs(vm.OpList, arrReg, keyRegs)
|
lc.ctx.Emitter.EmitAs(vm.OpList, arrReg, keyRegs)
|
||||||
lc.ctx.Emitter.EmitAB(vm.OpMove, kvKeyReg, arrReg) // TODO: Free Registers
|
lc.ctx.Emitter.EmitAB(vm.OpMove, kvKeyReg, arrReg) // TODO: Free Registers
|
||||||
} else {
|
} else {
|
||||||
@@ -229,7 +230,7 @@ func (lc *LoopCompiler) CompileSortClause(ctx fql.ISortClauseContext) {
|
|||||||
kvValReg = loop.Value
|
kvValReg = loop.Value
|
||||||
} else {
|
} else {
|
||||||
// If so, we need to load it from the iterator
|
// If so, we need to load it from the iterator
|
||||||
kvValReg = lc.ctx.Registers.Allocate(Temp)
|
kvValReg = lc.ctx.Registers.Allocate(core.Temp)
|
||||||
loop.EmitValue(kvKeyReg, lc.ctx.Emitter)
|
loop.EmitValue(kvKeyReg, lc.ctx.Emitter)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,18 +259,18 @@ func (lc *LoopCompiler) CompileCollectClause(ctx fql.ICollectClauseContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// emitIterValue emits an instruction to get the value from the iterator
|
// emitIterValue emits an instruction to get the value from the iterator
|
||||||
func (lc *LoopCompiler) emitLoopBegin(loop *Loop) {
|
func (lc *LoopCompiler) emitLoopBegin(loop *core.Loop) {
|
||||||
if loop.Allocate {
|
if loop.Allocate {
|
||||||
lc.ctx.Emitter.EmitAb(vm.OpDataSet, loop.Result, loop.Distinct)
|
lc.ctx.Emitter.EmitAb(vm.OpDataSet, loop.Result, loop.Distinct)
|
||||||
loop.ResultPos = lc.ctx.Emitter.Size() - 1
|
loop.ResultPos = lc.ctx.Emitter.Size() - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
loop.Iterator = lc.ctx.Registers.Allocate(State)
|
loop.Iterator = lc.ctx.Registers.Allocate(core.State)
|
||||||
|
|
||||||
if loop.Kind == ForLoop {
|
if loop.Kind == core.ForLoop {
|
||||||
lc.ctx.Emitter.EmitAB(vm.OpIter, loop.Iterator, loop.Src)
|
lc.ctx.Emitter.EmitAB(vm.OpIter, loop.Iterator, loop.Src)
|
||||||
// jumpPlaceholder is a placeholder for the exit jump position
|
// core.JumpPlaceholder is a placeholder for the exit jump position
|
||||||
loop.Jump = lc.ctx.Emitter.EmitJumpc(vm.OpIterNext, jumpPlaceholder, loop.Iterator)
|
loop.Jump = lc.ctx.Emitter.EmitJumpc(vm.OpIterNext, core.JumpPlaceholder, loop.Iterator)
|
||||||
|
|
||||||
if loop.Value != vm.NoopOperand {
|
if loop.Value != vm.NoopOperand {
|
||||||
lc.ctx.Emitter.EmitAB(vm.OpIterValue, loop.Value, loop.Iterator)
|
lc.ctx.Emitter.EmitAB(vm.OpIterValue, loop.Value, loop.Iterator)
|
||||||
@@ -285,7 +286,7 @@ func (lc *LoopCompiler) emitLoopBegin(loop *Loop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// emitPatchLoop replaces the source of the loop with a modified dataset
|
// emitPatchLoop replaces the source of the loop with a modified dataset
|
||||||
func (lc *LoopCompiler) emitPatchLoop(loop *Loop) {
|
func (lc *LoopCompiler) emitPatchLoop(loop *core.Loop) {
|
||||||
// Replace source with sorted array
|
// Replace source with sorted array
|
||||||
lc.ctx.Emitter.EmitAB(vm.OpMove, loop.Src, loop.Result)
|
lc.ctx.Emitter.EmitAB(vm.OpMove, loop.Src, loop.Result)
|
||||||
|
|
||||||
@@ -296,24 +297,24 @@ func (lc *LoopCompiler) emitPatchLoop(loop *Loop) {
|
|||||||
lc.emitLoopBegin(loop)
|
lc.emitLoopBegin(loop)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LoopCompiler) emitLoopEnd(loop *Loop) vm.Operand {
|
func (lc *LoopCompiler) emitLoopEnd(loop *core.Loop) vm.Operand {
|
||||||
lc.ctx.Emitter.EmitJump(loop.Jump - loop.JumpOffset)
|
lc.ctx.Emitter.EmitJump(loop.Jump - loop.JumpOffset)
|
||||||
|
|
||||||
// TODO: Do not allocate for pass-through Loops
|
// TODO: Do not allocate for pass-through Loops
|
||||||
dst := lc.ctx.Registers.Allocate(Temp)
|
dst := lc.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
if loop.Allocate {
|
if loop.Allocate {
|
||||||
// TODO: Reuse the dsReg register
|
// TODO: Reuse the dsReg register
|
||||||
lc.ctx.Emitter.EmitA(vm.OpClose, loop.Iterator)
|
lc.ctx.Emitter.EmitA(vm.OpClose, loop.Iterator)
|
||||||
lc.ctx.Emitter.EmitAB(vm.OpMove, dst, loop.Result)
|
lc.ctx.Emitter.EmitAB(vm.OpMove, dst, loop.Result)
|
||||||
|
|
||||||
if loop.Kind == ForLoop {
|
if loop.Kind == core.ForLoop {
|
||||||
lc.ctx.Emitter.PatchJump(loop.Jump)
|
lc.ctx.Emitter.PatchJump(loop.Jump)
|
||||||
} else {
|
} else {
|
||||||
lc.ctx.Emitter.PatchJumpAB(loop.Jump)
|
lc.ctx.Emitter.PatchJumpAB(loop.Jump)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if loop.Kind == ForLoop {
|
if loop.Kind == core.ForLoop {
|
||||||
lc.ctx.Emitter.PatchJumpNext(loop.Jump)
|
lc.ctx.Emitter.PatchJumpNext(loop.Jump)
|
||||||
} else {
|
} else {
|
||||||
lc.ctx.Emitter.PatchJumpNextAB(loop.Jump)
|
lc.ctx.Emitter.PatchJumpNextAB(loop.Jump)
|
||||||
@@ -323,14 +324,14 @@ func (lc *LoopCompiler) emitLoopEnd(loop *Loop) vm.Operand {
|
|||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lc *LoopCompiler) loopKind(ctx *fql.ForExpressionContext) LoopKind {
|
func (lc *LoopCompiler) loopKind(ctx *fql.ForExpressionContext) core.LoopKind {
|
||||||
if ctx.While() == nil {
|
if ctx.While() == nil {
|
||||||
return ForLoop
|
return core.ForLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Do() == nil {
|
if ctx.Do() == nil {
|
||||||
return WhileLoop
|
return core.WhileLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
return DoWhileLoop
|
return core.DoWhileLoop
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
"github.com/MontFerret/ferret/pkg/parser/fql"
|
"github.com/MontFerret/ferret/pkg/parser/fql"
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
)
|
)
|
||||||
@@ -19,6 +20,8 @@ func (sc *StmtCompiler) Compile(ctx fql.IBodyContext) {
|
|||||||
for _, statement := range ctx.AllBodyStatement() {
|
for _, statement := range ctx.AllBodyStatement() {
|
||||||
sc.CompileBodyStatement(statement)
|
sc.CompileBodyStatement(statement)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc.CompileBodyExpression(ctx.BodyExpression())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *StmtCompiler) CompileBodyStatement(ctx fql.IBodyStatementContext) {
|
func (sc *StmtCompiler) CompileBodyStatement(ctx fql.IBodyStatementContext) {
|
||||||
@@ -54,7 +57,7 @@ func (sc *StmtCompiler) CompileBodyExpression(ctx fql.IBodyExpressionContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sc *StmtCompiler) CompileVariableDeclaration(ctx fql.IVariableDeclarationContext) vm.Operand {
|
func (sc *StmtCompiler) CompileVariableDeclaration(ctx fql.IVariableDeclarationContext) vm.Operand {
|
||||||
name := ignorePseudoVariable
|
name := core.IgnorePseudoVariable
|
||||||
|
|
||||||
if id := ctx.Identifier(); id != nil {
|
if id := ctx.Identifier(); id != nil {
|
||||||
name = id.GetText()
|
name = id.GetText()
|
||||||
@@ -64,12 +67,12 @@ func (sc *StmtCompiler) CompileVariableDeclaration(ctx fql.IVariableDeclarationC
|
|||||||
|
|
||||||
src := sc.ctx.ExprCompiler.Compile(ctx.Expression())
|
src := sc.ctx.ExprCompiler.Compile(ctx.Expression())
|
||||||
|
|
||||||
if name != ignorePseudoVariable {
|
if name != core.IgnorePseudoVariable {
|
||||||
var dest vm.Operand
|
var dest vm.Operand
|
||||||
|
|
||||||
if src.IsConstant() {
|
if src.IsConstant() {
|
||||||
dest = sc.ctx.Symbols.DeclareGlobal(name)
|
dest = sc.ctx.Symbols.DeclareGlobal(name)
|
||||||
tmp := sc.ctx.Registers.Allocate(Temp)
|
tmp := sc.ctx.Registers.Allocate(core.Temp)
|
||||||
sc.ctx.Emitter.EmitAB(vm.OpLoadConst, tmp, src)
|
sc.ctx.Emitter.EmitAB(vm.OpLoadConst, tmp, src)
|
||||||
sc.ctx.Emitter.EmitAB(vm.OpStoreGlobal, dest, tmp)
|
sc.ctx.Emitter.EmitAB(vm.OpStoreGlobal, dest, tmp)
|
||||||
} else if sc.ctx.Symbols.Scope() == 0 {
|
} else if sc.ctx.Symbols.Scope() == 0 {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
"github.com/MontFerret/ferret/pkg/parser/fql"
|
"github.com/MontFerret/ferret/pkg/parser/fql"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -10,20 +11,13 @@ type Visitor struct {
|
|||||||
|
|
||||||
Err error
|
Err error
|
||||||
Src string
|
Src string
|
||||||
Emitter *Emitter
|
Emitter *core.Emitter
|
||||||
Registers *RegisterAllocator
|
Registers *core.RegisterAllocator
|
||||||
Symbols *SymbolTable
|
Symbols *core.SymbolTable
|
||||||
Loops *LoopTable
|
Loops *core.LoopTable
|
||||||
CatchTable *CatchStack
|
CatchTable *core.CatchStack
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
jumpPlaceholder = -1
|
|
||||||
undefinedVariable = -1
|
|
||||||
ignorePseudoVariable = "_"
|
|
||||||
pseudoVariable = "CURRENT"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewVisitor(src string) *Visitor {
|
func NewVisitor(src string) *Visitor {
|
||||||
v := new(Visitor)
|
v := new(Visitor)
|
||||||
v.BaseFqlParserVisitor = new(fql.BaseFqlParserVisitor)
|
v.BaseFqlParserVisitor = new(fql.BaseFqlParserVisitor)
|
||||||
@@ -44,13 +38,7 @@ func (v *Visitor) VisitProgram(ctx *fql.ProgramContext) interface{} {
|
|||||||
v.VisitHead(head.(*fql.HeadContext))
|
v.VisitHead(head.(*fql.HeadContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Body().Accept(v)
|
v.ctx.StmtCompiler.Compile(ctx.Body())
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *Visitor) VisitBody(ctx *fql.BodyContext) interface{} {
|
|
||||||
v.ctx.StmtCompiler.Compile(ctx)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/compiler/internal/core"
|
||||||
"github.com/MontFerret/ferret/pkg/parser/fql"
|
"github.com/MontFerret/ferret/pkg/parser/fql"
|
||||||
"github.com/MontFerret/ferret/pkg/runtime"
|
"github.com/MontFerret/ferret/pkg/runtime"
|
||||||
"github.com/MontFerret/ferret/pkg/vm"
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
@@ -34,7 +35,7 @@ func (wc *WaitCompiler) Compile(ctx fql.IWaitForExpressionContext) vm.Operand {
|
|||||||
timeoutReg = wc.CompileTimeoutClauseContext(timeout)
|
timeoutReg = wc.CompileTimeoutClauseContext(timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
streamReg := wc.ctx.Registers.Allocate(Temp)
|
streamReg := wc.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
// We move the source object to the stream register in order to re-use it in OpStream
|
// We move the source object to the stream register in order to re-use it in OpStream
|
||||||
wc.ctx.Emitter.EmitMove(streamReg, srcReg)
|
wc.ctx.Emitter.EmitMove(streamReg, srcReg)
|
||||||
@@ -44,10 +45,10 @@ func (wc *WaitCompiler) Compile(ctx fql.IWaitForExpressionContext) vm.Operand {
|
|||||||
var valReg vm.Operand
|
var valReg vm.Operand
|
||||||
|
|
||||||
// Now we start iterating over the stream
|
// Now we start iterating over the stream
|
||||||
jumpToNext := wc.ctx.Emitter.EmitJumpc(vm.OpIterNext, jumpPlaceholder, streamReg)
|
jumpToNext := wc.ctx.Emitter.EmitJumpc(vm.OpIterNext, core.JumpPlaceholder, streamReg)
|
||||||
|
|
||||||
if filter := ctx.FilterClause(); filter != nil {
|
if filter := ctx.FilterClause(); filter != nil {
|
||||||
valReg = wc.ctx.Symbols.DeclareLocal(pseudoVariable)
|
valReg = wc.ctx.Symbols.DeclareLocal(core.PseudoVariable)
|
||||||
wc.ctx.Emitter.EmitAB(vm.OpIterValue, valReg, streamReg)
|
wc.ctx.Emitter.EmitAB(vm.OpIterValue, valReg, streamReg)
|
||||||
|
|
||||||
wc.ctx.ExprCompiler.Compile(filter.Expression())
|
wc.ctx.ExprCompiler.Compile(filter.Expression())
|
||||||
@@ -86,7 +87,7 @@ func (wc *WaitCompiler) CompileWaitForEventName(ctx fql.IWaitForEventNameContext
|
|||||||
return wc.ctx.ExprCompiler.CompileFunctionCallExpression(c)
|
return wc.ctx.ExprCompiler.CompileFunctionCallExpression(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc *WaitCompiler) CompileWaitForEventSource(ctx fql.IWaitForEventSourceContext) vm.Operand {
|
func (wc *WaitCompiler) CompileWaitForEventSource(ctx fql.IWaitForEventSourceContext) vm.Operand {
|
||||||
@@ -102,7 +103,7 @@ func (wc *WaitCompiler) CompileWaitForEventSource(ctx fql.IWaitForEventSourceCon
|
|||||||
return wc.ctx.ExprCompiler.CompileFunctionCallExpression(c)
|
return wc.ctx.ExprCompiler.CompileFunctionCallExpression(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc *WaitCompiler) CompileOptionsClause(ctx fql.IOptionsClauseContext) vm.Operand {
|
func (wc *WaitCompiler) CompileOptionsClause(ctx fql.IOptionsClauseContext) vm.Operand {
|
||||||
@@ -110,7 +111,7 @@ func (wc *WaitCompiler) CompileOptionsClause(ctx fql.IOptionsClauseContext) vm.O
|
|||||||
return wc.ctx.LiteralCompiler.CompileObjectLiteral(c)
|
return wc.ctx.LiteralCompiler.CompileObjectLiteral(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (wc *WaitCompiler) CompileTimeoutClauseContext(ctx fql.ITimeoutClauseContext) vm.Operand {
|
func (wc *WaitCompiler) CompileTimeoutClauseContext(ctx fql.ITimeoutClauseContext) vm.Operand {
|
||||||
@@ -134,5 +135,5 @@ func (wc *WaitCompiler) CompileTimeoutClauseContext(ctx fql.ITimeoutClauseContex
|
|||||||
return wc.ctx.ExprCompiler.CompileFunctionCall(c, false)
|
return wc.ctx.ExprCompiler.CompileFunctionCall(c, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(runtime.Error(ErrUnexpectedToken, ctx.GetText()))
|
panic(runtime.Error(core.ErrUnexpectedToken, ctx.GetText()))
|
||||||
}
|
}
|
||||||
|
@@ -1,30 +1,35 @@
|
|||||||
package vm_test
|
package vm_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/MontFerret/ferret/pkg/runtime"
|
||||||
|
"github.com/MontFerret/ferret/pkg/vm"
|
||||||
. "github.com/MontFerret/ferret/test/integration/base"
|
. "github.com/MontFerret/ferret/test/integration/base"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRange(t *testing.T) {
|
func TestRange(t *testing.T) {
|
||||||
RunUseCases(t, []UseCase{
|
RunUseCases(t, []UseCase{
|
||||||
CaseArray("RETURN 1..10", []any{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}),
|
SkipCaseArray("RETURN 1..10", []any{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "Should return a range from 1 to 10"),
|
||||||
CaseArray("RETURN 10..1", []any{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}),
|
SkipCaseArray("RETURN 10..1", []any{10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, "Should return a range from 10 to 1"),
|
||||||
CaseArray(
|
SkipCaseArray(
|
||||||
`
|
`
|
||||||
LET start = 1
|
LET start = 1
|
||||||
LET end = 10
|
LET end = 10
|
||||||
RETURN start..end
|
RETURN start..end
|
||||||
`,
|
`,
|
||||||
[]any{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
[]any{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
||||||
|
"Should be able to use variables in range",
|
||||||
),
|
),
|
||||||
//{
|
CaseArray(`
|
||||||
// `
|
LET start = @start
|
||||||
//LET start = @start
|
LET end = @end
|
||||||
//LET end = @end
|
RETURN start..end
|
||||||
//RETURN start..end
|
`,
|
||||||
//`,
|
[]any{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
||||||
// []any{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
|
"Should be able to use parameters in range",
|
||||||
// ShouldEqualJSON,
|
),
|
||||||
//},
|
}, vm.WithParams(map[string]runtime.Value{
|
||||||
})
|
"start": runtime.NewInt(1),
|
||||||
|
"end": runtime.NewInt(10),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user