Skip to content

Commit

Permalink
Feature/variables optimization (#673)
Browse files Browse the repository at this point in the history
* Added optimization to FOR loops by disabling allocation if RETURN statement returns NONE

* Added support of ignoring expression results in variable declaration using '_' as a variable name
  • Loading branch information
ziflex authored Sep 20, 2021
1 parent 0c4a18c commit b3c19bf
Show file tree
Hide file tree
Showing 21 changed files with 1,280 additions and 970 deletions.
17 changes: 17 additions & 0 deletions pkg/compiler/compiler_for_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ func TestFor(t *testing.T) {
So(string(out), ShouldEqual, "[1,2,3]")
})

Convey("Should not allocate memory if NONE is a return statement", t, func() {
c := compiler.New()

p, err := c.Compile(`
FOR i IN 0..100
RETURN NONE
`)

So(err, ShouldBeNil)
So(p, ShouldHaveSameTypeAs, &runtime.Program{})

out, err := p.Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, "[]")
})

Convey("Should compile FOR i, k IN [1, 2, 3] RETURN k", t, func() {
c := compiler.New()

Expand Down
37 changes: 37 additions & 0 deletions pkg/compiler/compiler_let_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,4 +337,41 @@ func TestLet(t *testing.T) {
So(err, ShouldBeNil)
So(string(out), ShouldEqual, `false`)
})

Convey("Should use ignorable variable name", t, func() {
out, err := newCompilerWithObservable().MustCompile(`
LET _ = (FOR i IN 1..100 RETURN NONE)
RETURN TRUE
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, `true`)
})

Convey("Should allow to declare a variable name using _", t, func() {
c := compiler.New()

out, err := c.MustCompile(`
LET _ = (FOR i IN 1..100 RETURN NONE)
LET _ = (FOR i IN 1..100 RETURN NONE)
RETURN TRUE
`).Run(context.Background())

So(err, ShouldBeNil)
So(string(out), ShouldEqual, `true`)
})

Convey("Should not allow to use ignorable variable name", t, func() {
c := compiler.New()

_, err := c.Compile(`
LET _ = (FOR i IN 1..100 RETURN NONE)
RETURN _
`)

So(err, ShouldNotBeNil)
})
}
4 changes: 4 additions & 0 deletions pkg/compiler/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func (s *scope) HasVariable(name string) bool {
}

func (s *scope) SetVariable(name string) error {
if name == core.IgnorableVariable {
return nil
}

_, exists := s.vars[name]

if exists {
Expand Down
18 changes: 17 additions & 1 deletion pkg/compiler/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
if !isWhileLoop {
srcCtx := ctx.ForExpressionSource().(*fql.ForExpressionSourceContext)
srcExp, err := v.doVisitForExpressionSource(srcCtx, scope)

if err != nil {
return nil, err
}
Expand All @@ -266,6 +267,7 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
} else {
whileExpCtx := ctx.Expression().(*fql.ExpressionContext)
conditionExp, err := v.doVisitExpression(whileExpCtx, scope)

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -315,6 +317,7 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
valVarName,
keyVarName,
)

if err != nil {
return nil, err
}
Expand All @@ -325,6 +328,7 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
statementCtx.(*fql.ForExpressionStatementContext),
forInScope,
)

if err != nil {
return nil, err
}
Expand All @@ -336,12 +340,14 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
var spread bool
var distinct bool
var predicate core.Expression
var passThrough bool
forRetCtx := ctx.ForExpressionReturn().(*fql.ForExpressionReturnContext)
returnCtx := forRetCtx.ReturnExpression()

if returnCtx != nil {
returnCtx := returnCtx.(*fql.ReturnExpressionContext)
returnExp, err := v.doVisitReturnExpression(returnCtx, forInScope)

if err != nil {
return nil, err
}
Expand All @@ -353,9 +359,13 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
}

predicate = returnExp

ret := returnExp.(*expressions.ReturnExpression)
passThrough = literals.IsNone(ret.Predicate())
} else {
forInCtx := forRetCtx.ForExpression().(*fql.ForExpressionContext)
forInExp, err := v.doVisitForExpression(forInCtx, forInScope)

if err != nil {
return nil, err
}
Expand All @@ -371,7 +381,9 @@ func (v *visitor) doVisitForExpression(ctx *fql.ForExpressionContext, scope *sco
predicate,
distinct,
spread,
passThrough,
)

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1130,8 +1142,12 @@ func (v *visitor) doVisitVariable(ctx *fql.VariableContext, scope *scope) (core.
func (v *visitor) doVisitVariableDeclaration(ctx *fql.VariableDeclarationContext, scope *scope) (core.Expression, error) {
var init core.Expression
var err error
name := core.IgnorableVariable

if id := ctx.Identifier(); id != nil {
name = id.GetText()
}

name := ctx.Identifier().GetText()
err = scope.SetVariable(name)

if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion pkg/parser/antlr/FqlLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ While: 'WHILE';
// Literals
Param: '@';
Identifier: Letter+ (Symbols (Identifier)*)* (Digit (Identifier)*)*;
IgnoreIdentifier: Underscore;
StringLiteral: SQString | DQSring | BacktickString | TickString;
IntegerLiteral: [0-9]+;
FloatLiteral
Expand All @@ -111,7 +112,8 @@ fragment ExponentPart
fragment Letter
: 'A'..'Z' | 'a'..'z'
;
fragment Symbols: '_';
fragment Symbols: Underscore;
fragment Underscore: '_';
fragment Digit
: '0'..'9'
;
Expand Down
11 changes: 6 additions & 5 deletions pkg/parser/antlr/FqlLexer.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ Do=61
While=62
Param=63
Identifier=64
StringLiteral=65
IntegerLiteral=66
FloatLiteral=67
NamespaceSegment=68
UnknownIdentifier=69
IgnoreIdentifier=65
StringLiteral=66
IntegerLiteral=67
FloatLiteral=68
NamespaceSegment=69
UnknownIdentifier=70
':'=5
';'=6
'.'=7
Expand Down
1 change: 1 addition & 0 deletions pkg/parser/antlr/FqlParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ bodyExpression

variableDeclaration
: Let Identifier Assign expression
| Let IgnoreIdentifier Assign expression
;

returnExpression
Expand Down
6 changes: 5 additions & 1 deletion pkg/parser/fql/FqlLexer.interp

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions pkg/parser/fql/FqlLexer.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ Do=61
While=62
Param=63
Identifier=64
StringLiteral=65
IntegerLiteral=66
FloatLiteral=67
NamespaceSegment=68
UnknownIdentifier=69
IgnoreIdentifier=65
StringLiteral=66
IntegerLiteral=67
FloatLiteral=68
NamespaceSegment=69
UnknownIdentifier=70
':'=5
';'=6
'.'=7
Expand Down
4 changes: 3 additions & 1 deletion pkg/parser/fql/FqlParser.interp

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions pkg/parser/fql/FqlParser.tokens
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ Do=61
While=62
Param=63
Identifier=64
StringLiteral=65
IntegerLiteral=66
FloatLiteral=67
NamespaceSegment=68
UnknownIdentifier=69
IgnoreIdentifier=65
StringLiteral=66
IntegerLiteral=67
FloatLiteral=68
NamespaceSegment=69
UnknownIdentifier=70
':'=5
';'=6
'.'=7
Expand Down
Loading

0 comments on commit b3c19bf

Please sign in to comment.