@@ -1062,6 +1062,15 @@ func (c *Compiler[_, _]) VisitIfStatement(statement *ast.IfStatement) (_ struct{
1062
1062
varDeclTypes := c .DesugaredElaboration .VariableDeclarationTypes (test )
1063
1063
c .emitTransfer (varDeclTypes .TargetType )
1064
1064
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
+
1065
1074
// Declare the variable *after* unwrapping the optional,
1066
1075
// in a new scope
1067
1076
c .currentFunction .locals .PushNewWithCurrent ()
@@ -1295,23 +1304,31 @@ func (c *Compiler[_, _]) VisitVariableDeclaration(declaration *ast.VariableDecla
1295
1304
// If so, use the corresponding elaboration.
1296
1305
c .compilePotentiallyInheritedCode (declaration , func () {
1297
1306
1298
- // TODO: second value
1299
-
1300
1307
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.
1303
1310
if declaration .Value == nil {
1304
1311
c .currentFunction .declareLocal (name )
1305
- } else {
1306
- // Compile the value expression *before* declaring the variable
1307
- c .compileExpression (declaration .Value )
1312
+ return
1313
+ }
1308
1314
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 )
1311
1317
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
+ )
1314
1328
}
1329
+
1330
+ // Declare the variable *after* compiling the value expressions.
1331
+ c .emitDeclareLocal (name )
1315
1332
})
1316
1333
1317
1334
return
@@ -1361,22 +1378,30 @@ func (c *Compiler[_, _]) emitDeclareLocal(name string) *local {
1361
1378
}
1362
1379
1363
1380
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
+ }
1364
1389
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 ) {
1366
1396
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 )
1371
1399
c .emitVariableStore (target .Identifier .Identifier )
1372
1400
1373
1401
case * ast.MemberExpression :
1374
1402
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 )
1380
1405
constant := c .addStringConst (target .Identifier .Identifier )
1381
1406
c .emit (opcode.InstructionSetField {
1382
1407
FieldName : constant .index ,
@@ -1385,18 +1410,14 @@ func (c *Compiler[_, _]) VisitAssignmentStatement(statement *ast.AssignmentState
1385
1410
case * ast.IndexExpression :
1386
1411
c .compileExpression (target .TargetExpression )
1387
1412
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 )
1393
1415
c .emit (opcode.InstructionSetIndex {})
1394
1416
1395
1417
default :
1396
1418
// TODO:
1397
1419
panic (errors .NewUnreachableError ())
1398
1420
}
1399
- return
1400
1421
}
1401
1422
1402
1423
func (c * Compiler [_ , _ ]) VisitSwapStatement (_ * ast.SwapStatement ) (_ struct {}) {
@@ -2003,11 +2024,16 @@ func (c *Compiler[_, _]) VisitMemberExpression(expression *ast.MemberExpression)
2003
2024
// and leave the value on stack.
2004
2025
// i.e: the target/parent is already loaded.
2005
2026
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
+ }
2011
2037
2012
2038
// Return a reference, if the member is accessed via a reference.
2013
2039
// This is pre-computed at the checker.
@@ -2027,7 +2053,13 @@ func (c *Compiler[_, _]) VisitMemberExpression(expression *ast.MemberExpression)
2027
2053
func (c * Compiler [_ , _ ]) VisitIndexExpression (expression * ast.IndexExpression ) (_ struct {}) {
2028
2054
c .compileExpression (expression .TargetExpression )
2029
2055
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
+ }
2031
2063
2032
2064
indexExpressionTypes , ok := c .DesugaredElaboration .IndexExpressionTypes (expression )
2033
2065
if ! ok {
0 commit comments