visitForStmt method
Implementation
@override
Uint8List visitForStmt(ForStmt stmt) {
final bytesBuilder = BytesBuilder();
bytesBuilder.add(_lineInfo(stmt.line, stmt.column));
bytesBuilder.addByte(HTOpCode.codeBlock);
bytesBuilder.add(_parseIdentifier(Semantic.forStmtInit));
late Uint8List condition;
Uint8List? increment;
ASTNode? capturedDecl;
final newSymbolMap = <String, String>{};
_markedSymbolsList.add(newSymbolMap);
if (stmt.init != null) {
final userDecl = stmt.init as VarDecl;
final markedId = '${_lexicon.internalPrefix}${userDecl.id.id}';
newSymbolMap[userDecl.id.id] = markedId;
Uint8List? initializer;
if (userDecl.initializer != null) {
initializer = compileAST(userDecl.initializer!, endOfExec: true);
}
final initDecl = _assembleVarDeclStmt(
markedId, userDecl.line, userDecl.column,
initializer: initializer, isMutable: userDecl.isMutable);
bytesBuilder.add(initDecl);
// 这里是为了实现将变量声明移动到for循环语句块内部的效果
final capturedInit = IdentifierExpr(markedId);
capturedDecl = VarDecl(userDecl.id, initializer: capturedInit);
}
if (stmt.condition != null) {
condition = compileAST(stmt.condition!);
} else {
final boolExpr = ASTLiteralBoolean(true);
condition = visitBooleanExpr(boolExpr);
}
if (stmt.increment != null) {
increment = compileAST(stmt.increment!);
}
if (capturedDecl != null) {
stmt.loop.statements.insert(0, capturedDecl);
}
final loop = visitBlockStmt(stmt.loop);
final continueLength = condition.length + loop.length + 1;
final breakLength = continueLength + (increment?.length ?? 0) + 3;
bytesBuilder.addByte(HTOpCode.loopPoint);
bytesBuilder.add(_uint16(continueLength));
bytesBuilder.add(_uint16(breakLength));
bytesBuilder.add(condition);
bytesBuilder.addByte(HTOpCode.whileStmt);
bytesBuilder.add(loop);
if (increment != null) {
bytesBuilder.add(increment);
}
bytesBuilder.addByte(HTOpCode.skip);
bytesBuilder.add(_int16(-breakLength));
_markedSymbolsList.removeLast();
bytesBuilder.addByte(HTOpCode.endOfCodeBlock);
return bytesBuilder.toBytes();
}