visitForStmt method

  1. @override
Uint8List visitForStmt(
  1. ForStmt stmt
)
override

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();
}