mirror of
https://github.com/MontFerret/ferret.git
synced 2025-08-13 19:52:52 +02:00
Refactor compiler internals; rename files and update context usage for improved clarity and structure
This commit is contained in:
@@ -31,11 +31,11 @@ func (ec *ExprCompiler) Compile(ctx fql.IExpressionContext) vm.Operand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c := ctx.LogicalAndOperator(); c != nil {
|
if c := ctx.LogicalAndOperator(); c != nil {
|
||||||
return ec.compileLogicalAnd(ctx.Predicate())
|
return ec.compileLogicalAnd(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c := ctx.LogicalOrOperator(); c != nil {
|
if c := ctx.LogicalOrOperator(); c != nil {
|
||||||
return ec.compileLogicalOr(ctx.Predicate())
|
return ec.compileLogicalOr(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c := ctx.GetTernaryOperator(); c != nil {
|
if c := ctx.GetTernaryOperator(); c != nil {
|
||||||
@@ -73,11 +73,11 @@ 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.IExpressionContext) vm.Operand {
|
||||||
dst := ec.ctx.Registers.Allocate(core.Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
// Execute left expression
|
// Execute left expression
|
||||||
left := ec.compilePredicate(ctx.GetLeft())
|
left := ec.Compile(ctx.GetLeft())
|
||||||
|
|
||||||
// Execute left expression
|
// Execute left expression
|
||||||
ec.ctx.Emitter.EmitMove(dst, left)
|
ec.ctx.Emitter.EmitMove(dst, left)
|
||||||
@@ -86,7 +86,7 @@ func (ec *ExprCompiler) compileLogicalAnd(ctx fql.IPredicateContext) vm.Operand
|
|||||||
end := ec.ctx.Emitter.EmitJumpIfFalse(dst, core.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.Compile(ctx.GetRight())
|
||||||
|
|
||||||
// And move the result to the destination register
|
// And move the result to the destination register
|
||||||
ec.ctx.Emitter.EmitMove(dst, right)
|
ec.ctx.Emitter.EmitMove(dst, right)
|
||||||
@@ -97,11 +97,11 @@ 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.IExpressionContext) vm.Operand {
|
||||||
dst := ec.ctx.Registers.Allocate(core.Temp)
|
dst := ec.ctx.Registers.Allocate(core.Temp)
|
||||||
|
|
||||||
// Execute left expression
|
// Execute left expression
|
||||||
left := ec.compilePredicate(ctx.GetLeft())
|
left := ec.Compile(ctx.GetLeft())
|
||||||
|
|
||||||
// Execute left expression
|
// Execute left expression
|
||||||
ec.ctx.Emitter.EmitMove(dst, left)
|
ec.ctx.Emitter.EmitMove(dst, left)
|
||||||
@@ -110,7 +110,7 @@ func (ec *ExprCompiler) compileLogicalOr(ctx fql.IPredicateContext) vm.Operand {
|
|||||||
end := ec.ctx.Emitter.EmitJumpIfTrue(dst, core.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.Compile(ctx.GetRight())
|
||||||
|
|
||||||
// And move the result to the destination register
|
// And move the result to the destination register
|
||||||
ec.ctx.Emitter.EmitMove(dst, right)
|
ec.ctx.Emitter.EmitMove(dst, right)
|
||||||
@@ -181,7 +181,7 @@ func (ec *ExprCompiler) compilePredicate(ctx fql.IPredicateContext) vm.Operand {
|
|||||||
right := ec.compilePredicate(ctx.Predicate(1))
|
right := ec.compilePredicate(ctx.Predicate(1))
|
||||||
|
|
||||||
if op := ctx.EqualityOperator(); op != nil {
|
if op := ctx.EqualityOperator(); op != nil {
|
||||||
switch ctx.GetText() {
|
switch op.GetText() {
|
||||||
case "==":
|
case "==":
|
||||||
opcode = vm.OpEq
|
opcode = vm.OpEq
|
||||||
case "!=":
|
case "!=":
|
||||||
@@ -433,6 +433,11 @@ func (ec *ExprCompiler) CompileFunctionCall(ctx fql.IFunctionCallContext, protec
|
|||||||
|
|
||||||
func (ec *ExprCompiler) CompileArgumentList(ctx fql.IArgumentListContext) core.RegisterSequence {
|
func (ec *ExprCompiler) CompileArgumentList(ctx fql.IArgumentListContext) core.RegisterSequence {
|
||||||
var seq core.RegisterSequence
|
var seq core.RegisterSequence
|
||||||
|
|
||||||
|
if ctx == nil {
|
||||||
|
return seq
|
||||||
|
}
|
||||||
|
|
||||||
// Get all array element expressions
|
// Get all array element expressions
|
||||||
exps := ctx.AllExpression()
|
exps := ctx.AllExpression()
|
||||||
size := len(exps)
|
size := len(exps)
|
||||||
|
@@ -12,8 +12,8 @@ func TestFunctionCall(t *testing.T) {
|
|||||||
Case("RETURN TYPENAME(1.1)", "float"),
|
Case("RETURN TYPENAME(1.1)", "float"),
|
||||||
Case("WAIT(10) RETURN 1", 1),
|
Case("WAIT(10) RETURN 1", 1),
|
||||||
Case("RETURN LENGTH([1,2,3])", 3),
|
Case("RETURN LENGTH([1,2,3])", 3),
|
||||||
SkipCase("RETURN CONCAT('a', 'b', 'c')", "abc"),
|
Case("RETURN CONCAT('a', 'b', 'c')", "abc"),
|
||||||
SkipCase("RETURN CONCAT(CONCAT('a', 'b'), 'c', CONCAT('d', 'e'))", "abcde", "Nested calls"),
|
Case("RETURN CONCAT(CONCAT('a', 'b'), 'c', CONCAT('d', 'e'))", "abcde", "Nested calls"),
|
||||||
SkipCaseArray(`
|
SkipCaseArray(`
|
||||||
LET arr = []
|
LET arr = []
|
||||||
LET a = 1
|
LET a = 1
|
||||||
@@ -21,7 +21,7 @@ func TestFunctionCall(t *testing.T) {
|
|||||||
RETURN res
|
RETURN res
|
||||||
`,
|
`,
|
||||||
[]any{1}, "Append to array"),
|
[]any{1}, "Append to array"),
|
||||||
SkipCase("LET duration = 10 WAIT(duration) RETURN 1", 1),
|
Case("LET duration = 10 WAIT(duration) RETURN 1", 1),
|
||||||
CaseNil("RETURN (FALSE OR T::FAIL())?"),
|
CaseNil("RETURN (FALSE OR T::FAIL())?"),
|
||||||
CaseNil("RETURN T::FAIL()?"),
|
CaseNil("RETURN T::FAIL()?"),
|
||||||
CaseArray(`FOR i IN [1, 2, 3, 4]
|
CaseArray(`FOR i IN [1, 2, 3, 4]
|
||||||
|
@@ -113,7 +113,7 @@ func TestMember(t *testing.T) {
|
|||||||
map[string]any{
|
map[string]any{
|
||||||
"second": "third",
|
"second": "third",
|
||||||
}),
|
}),
|
||||||
CaseObject(`RETURN KEEP_KEYS({first: {second: "third"}}.first, "second")`,
|
SkipCaseObject(`RETURN KEEP_KEYS({first: {second: "third"}}.first, "second")`,
|
||||||
map[string]any{
|
map[string]any{
|
||||||
"second": "third",
|
"second": "third",
|
||||||
}),
|
}),
|
||||||
|
@@ -20,8 +20,8 @@ func TestTernaryOperator(t *testing.T) {
|
|||||||
Case("LET foo = FALSE RETURN foo ? TRUE : FALSE", false),
|
Case("LET foo = FALSE RETURN foo ? TRUE : FALSE", false),
|
||||||
CaseArray("FOR i IN [1, 2, 3, 4, 5, 6] RETURN i < 3 ? i * 3 : i * 2", []any{3, 6, 6, 8, 10, 12}),
|
CaseArray("FOR i IN [1, 2, 3, 4, 5, 6] RETURN i < 3 ? i * 3 : i * 2", []any{3, 6, 6, 8, 10, 12}),
|
||||||
CaseArray(`FOR i IN [NONE, 2, 3, 4, 5, 6] RETURN i ? : i`, []any{nil, 2, 3, 4, 5, 6}),
|
CaseArray(`FOR i IN [NONE, 2, 3, 4, 5, 6] RETURN i ? : i`, []any{nil, 2, 3, 4, 5, 6}),
|
||||||
Case(`RETURN 0 && true ? "1" : "some"`, "some"),
|
Case(`RETURN 0 && true ? "1" : "some"`, "some", "Should return 'some' when first operand is 0"),
|
||||||
Case(`RETURN length([]) > 0 && true ? "1" : "some"`, "some"),
|
Case(`RETURN length([]) > 0 && true ? "1" : "some"`, "some", "Should return 'some' when first operand is an empty array"),
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("Should compile ternary operator with default values", t, func() {
|
Convey("Should compile ternary operator with default values", t, func() {
|
||||||
|
Reference in New Issue
Block a user