Skip to content

Commit

Permalink
add array variable assignment (#867)
Browse files Browse the repository at this point in the history
  • Loading branch information
brennanjl authored Jun 25, 2024
1 parent af55d9c commit 4ea9379
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 29 deletions.
10 changes: 10 additions & 0 deletions internal/engine/integration/procedure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,16 @@ func Test_Procedures(t *testing.T) {
}`,
outputs: [][]any{{false}},
},
{
name: "array",
procedure: `procedure assign_array() public view returns (ints int[]) {
$arr int[] := [1, 2, 3];
$arr[2] := 4;
return $arr;
}`,
outputs: [][]any{{[]any{int64(1), int64(4), int64(3)}}},
},
}

for _, test := range tests {
Expand Down
18 changes: 12 additions & 6 deletions parse/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -2234,12 +2234,18 @@ func (p *procedureAnalyzer) VisitProcedureStmtAssignment(p0 *ProcedureStmtAssign
return zeroProcedureReturn()
}

_, ok = p.variables[p0.Variable.String()]
if !ok {
// if it does not exist, we can declare it here.
p.variables[p0.Variable.String()] = dt
p.markDeclared(p0.Variable, p0.Variable.String(), dt)
return zeroProcedureReturn()
// the variable can be either an ExpressionVariable or an ExpressionArrayAccess
// If it is an ExpressionVariable, we need to declare it

exprVar, ok := p0.Variable.(*ExpressionVariable)
if ok {
_, ok = p.variables[exprVar.String()]
if !ok {
// if it does not exist, we can declare it here.
p.variables[exprVar.String()] = dt
p.markDeclared(p0.Variable, exprVar.String(), dt)
return zeroProcedureReturn()
}
}

// the type can be inferred from the value.
Expand Down
13 changes: 10 additions & 3 deletions parse/antlr.go
Original file line number Diff line number Diff line change
Expand Up @@ -2018,10 +2018,17 @@ func (s *schemaVisitor) VisitVariable_or_underscore(ctx *gen.Variable_or_undersc
}

func (s *schemaVisitor) VisitStmt_variable_assignment(ctx *gen.Stmt_variable_assignmentContext) any {
stmt := &ProcedureStmtAssign{
Variable: varFromTerminalNode(ctx.VARIABLE()),
Value: ctx.Procedure_expr().Accept(s).(Expression),
stmt := &ProcedureStmtAssign{}

stmt.Variable = ctx.Procedure_expr(0).Accept(s).(Expression)
// this can either be a variable or an array access
switch v := stmt.Variable.(type) {
case *ExpressionVariable, *ExpressionArrayAccess:
// ok
default:
s.errs.RuleErr(ctx.Procedure_expr(0), ErrSyntax, "cannot assign to %T", v)
}
stmt.Value = ctx.Procedure_expr(1).Accept(s).(Expression)

if ctx.Type_() != nil {
stmt.Type = ctx.Type_().Accept(s).(*types.DataType)
Expand Down
2 changes: 1 addition & 1 deletion parse/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ func (p *ProcedureStmtDeclaration) Accept(v Visitor) any {
type ProcedureStmtAssign struct {
baseProcedureStmt
// Variable is the variable that is being assigned.
Variable *ExpressionVariable
Variable Expression
// Type is the type of the variable.
// It can be nil if the variable is not being assigned,
// or if the type should be inferred.
Expand Down
53 changes: 35 additions & 18 deletions parse/gen/kuneiform_parser.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion parse/grammar/KuneiformParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ proc_statement:
VARIABLE type SCOL # stmt_variable_declaration
// stmt_procedure_call must go above stmt_variable_assignment due to lexer ambiguity
| ((variable_or_underscore) (COMMA (variable_or_underscore))* ASSIGN)? procedure_function_call SCOL # stmt_procedure_call
| VARIABLE type? ASSIGN procedure_expr SCOL # stmt_variable_assignment
| procedure_expr type? ASSIGN procedure_expr SCOL # stmt_variable_assignment
| FOR receiver=VARIABLE IN (range|target_variable=variable|sql_statement) LBRACE proc_statement* RBRACE # stmt_for_loop
| IF if_then_block (ELSEIF if_then_block)* (ELSE LBRACE proc_statement* RBRACE)? # stmt_if
| sql_statement SCOL # stmt_sql
Expand Down

0 comments on commit 4ea9379

Please sign in to comment.