Skip to content

Commit c3dbf57

Browse files
authored
Merge pull request #3987 from onflow/supun/second-value-assignment
[Compiler] Compile second value assignment
2 parents 4dd91ca + 41c0c3d commit c3dbf57

File tree

11 files changed

+585
-58
lines changed

11 files changed

+585
-58
lines changed

bbq/compiler/compiler.go

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,15 @@ func (c *Compiler[_, _]) VisitIfStatement(statement *ast.IfStatement) (_ struct{
10621062
varDeclTypes := c.DesugaredElaboration.VariableDeclarationTypes(test)
10631063
c.emitTransfer(varDeclTypes.TargetType)
10641064

1065+
// Before declaring the variable, evaluate and assign the second value.
1066+
if test.SecondValue != nil {
1067+
c.compileAssignment(
1068+
test.Value,
1069+
test.SecondValue,
1070+
varDeclTypes.ValueType,
1071+
)
1072+
}
1073+
10651074
// Declare the variable *after* unwrapping the optional,
10661075
// in a new scope
10671076
c.currentFunction.locals.PushNewWithCurrent()
@@ -1295,23 +1304,31 @@ func (c *Compiler[_, _]) VisitVariableDeclaration(declaration *ast.VariableDecla
12951304
// If so, use the corresponding elaboration.
12961305
c.compilePotentiallyInheritedCode(declaration, func() {
12971306

1298-
// TODO: second value
1299-
13001307
name := declaration.Identifier.Identifier
1301-
// TODO: This can be nil only for synthetic-result variable
1302-
// Any better way to handle this?
1308+
1309+
// Value can be nil only for synthetic-result variable.
13031310
if declaration.Value == nil {
13041311
c.currentFunction.declareLocal(name)
1305-
} else {
1306-
// Compile the value expression *before* declaring the variable
1307-
c.compileExpression(declaration.Value)
1312+
return
1313+
}
13081314

1309-
varDeclTypes := c.DesugaredElaboration.VariableDeclarationTypes(declaration)
1310-
c.emitTransfer(varDeclTypes.TargetType)
1315+
// Compile the value expression *before* declaring the variable.
1316+
c.compileExpression(declaration.Value)
13111317

1312-
// Declare the variable *after* compiling the value expression
1313-
c.emitDeclareLocal(name)
1318+
varDeclTypes := c.DesugaredElaboration.VariableDeclarationTypes(declaration)
1319+
c.emitTransfer(varDeclTypes.TargetType)
1320+
1321+
// Before declaring the variable, evaluate and assign the second value.
1322+
if declaration.SecondValue != nil {
1323+
c.compileAssignment(
1324+
declaration.Value,
1325+
declaration.SecondValue,
1326+
varDeclTypes.ValueType,
1327+
)
13141328
}
1329+
1330+
// Declare the variable *after* compiling the value expressions.
1331+
c.emitDeclareLocal(name)
13151332
})
13161333

13171334
return
@@ -1361,22 +1378,30 @@ func (c *Compiler[_, _]) emitDeclareLocal(name string) *local {
13611378
}
13621379

13631380
func (c *Compiler[_, _]) VisitAssignmentStatement(statement *ast.AssignmentStatement) (_ struct{}) {
1381+
assignmentTypes := c.DesugaredElaboration.AssignmentStatementTypes(statement)
1382+
c.compileAssignment(
1383+
statement.Target,
1384+
statement.Value,
1385+
assignmentTypes.TargetType,
1386+
)
1387+
return
1388+
}
13641389

1365-
switch target := statement.Target.(type) {
1390+
func (c *Compiler[_, _]) compileAssignment(
1391+
target ast.Expression,
1392+
value ast.Expression,
1393+
targetType sema.Type,
1394+
) {
1395+
switch target := target.(type) {
13661396
case *ast.IdentifierExpression:
1367-
c.compileExpression(statement.Value)
1368-
assignmentTypes := c.DesugaredElaboration.AssignmentStatementTypes(statement)
1369-
c.emitTransfer(assignmentTypes.TargetType)
1370-
1397+
c.compileExpression(value)
1398+
c.emitTransfer(targetType)
13711399
c.emitVariableStore(target.Identifier.Identifier)
13721400

13731401
case *ast.MemberExpression:
13741402
c.compileExpression(target.Expression)
1375-
1376-
c.compileExpression(statement.Value)
1377-
assignmentTypes := c.DesugaredElaboration.AssignmentStatementTypes(statement)
1378-
c.emitTransfer(assignmentTypes.TargetType)
1379-
1403+
c.compileExpression(value)
1404+
c.emitTransfer(targetType)
13801405
constant := c.addStringConst(target.Identifier.Identifier)
13811406
c.emit(opcode.InstructionSetField{
13821407
FieldName: constant.index,
@@ -1385,18 +1410,14 @@ func (c *Compiler[_, _]) VisitAssignmentStatement(statement *ast.AssignmentState
13851410
case *ast.IndexExpression:
13861411
c.compileExpression(target.TargetExpression)
13871412
c.compileExpression(target.IndexingExpression)
1388-
1389-
c.compileExpression(statement.Value)
1390-
assignmentTypes := c.DesugaredElaboration.AssignmentStatementTypes(statement)
1391-
c.emitTransfer(assignmentTypes.TargetType)
1392-
1413+
c.compileExpression(value)
1414+
c.emitTransfer(targetType)
13931415
c.emit(opcode.InstructionSetIndex{})
13941416

13951417
default:
13961418
// TODO:
13971419
panic(errors.NewUnreachableError())
13981420
}
1399-
return
14001421
}
14011422

14021423
func (c *Compiler[_, _]) VisitSwapStatement(_ *ast.SwapStatement) (_ struct{}) {
@@ -2003,11 +2024,16 @@ func (c *Compiler[_, _]) VisitMemberExpression(expression *ast.MemberExpression)
20032024
// and leave the value on stack.
20042025
// i.e: the target/parent is already loaded.
20052026

2006-
// TODO: remove member if `isNestedResourceMove`
2007-
// See `Interpreter.memberExpressionGetterSetter` for the reference implementation.
2008-
c.emit(opcode.InstructionGetField{
2009-
FieldName: constant.index,
2010-
})
2027+
isNestedResourceMove := c.DesugaredElaboration.IsNestedResourceMoveExpression(expression)
2028+
if isNestedResourceMove {
2029+
c.emit(opcode.InstructionRemoveField{
2030+
FieldName: constant.index,
2031+
})
2032+
} else {
2033+
c.emit(opcode.InstructionGetField{
2034+
FieldName: constant.index,
2035+
})
2036+
}
20112037

20122038
// Return a reference, if the member is accessed via a reference.
20132039
// This is pre-computed at the checker.
@@ -2027,7 +2053,13 @@ func (c *Compiler[_, _]) VisitMemberExpression(expression *ast.MemberExpression)
20272053
func (c *Compiler[_, _]) VisitIndexExpression(expression *ast.IndexExpression) (_ struct{}) {
20282054
c.compileExpression(expression.TargetExpression)
20292055
c.compileExpression(expression.IndexingExpression)
2030-
c.emit(opcode.InstructionGetIndex{})
2056+
2057+
isNestedResourceMove := c.DesugaredElaboration.IsNestedResourceMoveExpression(expression)
2058+
if isNestedResourceMove {
2059+
c.emit(opcode.InstructionRemoveIndex{})
2060+
} else {
2061+
c.emit(opcode.InstructionGetIndex{})
2062+
}
20312063

20322064
indexExpressionTypes, ok := c.DesugaredElaboration.IndexExpressionTypes(expression)
20332065
if !ok {

0 commit comments

Comments
 (0)