Skip to content

Commit

Permalink
Implemented function calls with supressed error propagation
Browse files Browse the repository at this point in the history
  • Loading branch information
ziflex committed Mar 28, 2024
1 parent 70649e1 commit 474d985
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 50 deletions.
63 changes: 26 additions & 37 deletions pkg/compiler/compiler_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,43 @@ import (

func TestFunctionCall(t *testing.T) {
RunUseCases(t, []UseCase{
//{
// "RETURN TYPENAME(1)",
// "int",
// nil,
//},
//{
// "WAIT(10) RETURN 1",
// 1,
// nil,
//},
//{
// "LET duration = 10 WAIT(duration) RETURN 1",
// 1,
// nil,
//},
{
"RETURN TYPENAME(1)",
"int",
"RETURN (FALSE OR T::FAIL())?",
nil,
},
{
"WAIT(10) RETURN 1",
1,
nil,
},
{
"LET duration = 10 WAIT(duration) RETURN 1",
1,
"RETURN T::FAIL()?",
nil,
nil,
},
//{
// "RETURN (FALSE OR T::FAIL())?",
// nil,
// nil,
//},
//{
// "RETURN ERROR()?",
// nil,
// nil,
// `FOR i IN [1, 2, 3, 4]
// LET duration = 10
//
// WAIT(duration)
//
// RETURN i * 2`,
// []int{2, 4, 6, 8},
// ShouldEqualJSON,
//},
})

//
//Convey("Should compile function call inside FOR IN statement", t, func() {
// c := compiler.New()
//
// p, err := c.Compile(`
// FOR i IN [1, 2, 3, 4]
// LET duration = 10
//
// WAIT(duration)
//
// RETURN i * 2
// `)
//
// So(err, ShouldBeNil)
//
// out, err := p.Run(context.Background())
//
// So(err, ShouldBeNil)
//
// So(string(out), ShouldEqual, `[2,4,6,8]`)
//})
//
//Convey("Should handle errors when ? is used", t, func() {
// c := compiler.New()
Expand Down
38 changes: 31 additions & 7 deletions pkg/compiler/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ func (v *visitor) VisitFunctionCallExpression(ctx *fql.FunctionCallExpressionCon

name += call.FunctionName().GetText()

//regularCall := ctx.ErrorOperator() == nil
isNonOptional := ctx.ErrorOperator() == nil

v.emit(runtime.OpConstant, v.addConstant(values.String(name)))

Expand All @@ -310,17 +310,41 @@ func (v *visitor) VisitFunctionCallExpression(ctx *fql.FunctionCallExpressionCon

switch size {
case 0:
v.emit(runtime.OpCall, 0)
if isNonOptional {
v.emit(runtime.OpCall, 0)
} else {
v.emit(runtime.OpCallOptional, 0)
}
case 1:
v.emit(runtime.OpCall1, 1)
if isNonOptional {
v.emit(runtime.OpCall1, 1)
} else {
v.emit(runtime.OpCall1Optional, 1)
}
case 2:
v.emit(runtime.OpCall2, 2)
if isNonOptional {
v.emit(runtime.OpCall2, 2)
} else {
v.emit(runtime.OpCall2Optional, 2)
}
case 3:
v.emit(runtime.OpCall3, 3)
if isNonOptional {
v.emit(runtime.OpCall3, 3)
} else {
v.emit(runtime.OpCall3Optional, 3)
}
case 4:
v.emit(runtime.OpCall4, 4)
if isNonOptional {
v.emit(runtime.OpCall4, 4)
} else {
v.emit(runtime.OpCall4Optional, 4)
}
default:
v.emit(runtime.OpCallN, size)
if isNonOptional {
v.emit(runtime.OpCallN, size)
} else {
v.emit(runtime.OpCallNOptional, size)
}
}

return nil
Expand Down
6 changes: 6 additions & 0 deletions pkg/runtime/opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,17 @@ const (
OpRegexpPositive
OpRegexpNegative
OpCall
OpCallOptional
OpCall1
OpCall1Optional
OpCall2
OpCall2Optional
OpCall3
OpCall3Optional
OpCall4
OpCall4Optional
OpCallN
OpCallNOptional
OpPush
OpPop
OpPopClose
Expand Down
24 changes: 18 additions & 6 deletions pkg/runtime/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,40 +283,46 @@ loop:
reg := program.Constants[arg].(*values.Regexp)
stack.Push(!reg.Match(stack.Pop()))

case OpCall:
case OpCall, OpCallOptional:
fnName := stack.Pop().String()
res, err := vm.env.GetFunction(fnName)(ctx)

if err == nil {
stack.Push(res)
} else if op == OpCallOptional {
stack.Push(values.None)
} else {
return nil, err
}

case OpCall1:
case OpCall1, OpCall1Optional:
arg := stack.Pop()
fnName := stack.Pop().String()
res, err := vm.env.GetFunction(fnName)(ctx, arg)

if err == nil {
stack.Push(res)
} else if op == OpCall1Optional {
stack.Push(values.None)
} else {
return nil, err
}

case OpCall2:
case OpCall2, OpCall2Optional:
arg2 := stack.Pop()
arg1 := stack.Pop()
fnName := stack.Pop().String()
res, err := vm.env.GetFunction(fnName)(ctx, arg1, arg2)

if err == nil {
stack.Push(res)
} else if op == OpCall2Optional {
stack.Push(values.None)
} else {
return nil, err
}

case OpCall3:
case OpCall3, OpCall3Optional:
arg3 := stack.Pop()
arg2 := stack.Pop()
arg1 := stack.Pop()
Expand All @@ -325,11 +331,13 @@ loop:

if err == nil {
stack.Push(res)
} else if op == OpCall3Optional {
stack.Push(values.None)
} else {
return nil, err
}

case OpCall4:
case OpCall4, OpCall4Optional:
arg4 := stack.Pop()
arg3 := stack.Pop()
arg2 := stack.Pop()
Expand All @@ -339,10 +347,12 @@ loop:

if err == nil {
stack.Push(res)
} else if op == OpCall4Optional {
stack.Push(values.None)
} else {
return nil, err
}
case OpCallN:
case OpCallN, OpCallNOptional:
// pop arguments from the stack
// and push them to the arguments array
// in reverse order because stack is LIFO and arguments array is FIFO
Expand All @@ -361,6 +371,8 @@ loop:

if err == nil {
stack.Push(res)
} else if op == OpCallNOptional {
stack.Push(values.None)
} else {
return nil, err
}
Expand Down

0 comments on commit 474d985

Please sign in to comment.