runPrompt function

void runPrompt()

Implementation

void runPrompt() {
  print("Dart Simple Python Subset REPL");
  print("Enter Python code. Use Ctrl+D or 'exit()' to quit.");
  String currentBlock = "";

  while (true) {
    stdout.write(currentBlock.isEmpty ? '>>> ' : '... ');
    String? line = stdin.readLineSync();

    // Handle Ctrl+D (EOF) or exit command
    if (line == null || line.trim() == 'exit()') {
      break;
    }

    // --- Block Completion Logic ---
    bool runTheBlock = false;
    if (currentBlock.isEmpty && line.trim().isEmpty) continue;

    // Append the new line (with newline char for lexer consistency)
    currentBlock += '$line\n';
    String trimmedLine = line.trim();

    // Finish block with empty line
    if (trimmedLine.isEmpty && currentBlock.trim().isNotEmpty) {
      try {
        Lexer tempLexer = Lexer(currentBlock);
        tempLexer.scanTokens(); // scan to fill indentStack

        // no indentation?
        if (tempLexer.indentStack.length <= 1) {
          runTheBlock = checkOpenBrackets(currentBlock) == 0;
        }
      } catch (e) {
        // Lexer error => try to run the code to show the error
        runTheBlock = true;
      }
    } else if (currentBlock.trim().isNotEmpty) {
      // Current line is not empty. Block will be executed when
      // - no open brackets
      // - last line doesnt end with ":"
      // - last relevant line (ignoring comment) is not indented
      List<String> lines = currentBlock.trimRight().split('\n');
      String lastRelevantLine = '';
      for (int i = lines.length - 1; i >= 0; i--) {
        String l = lines[i].trim();
        if (l.isNotEmpty && !l.startsWith('#')) {
          lastRelevantLine = l;
          break;
        }
      }

      if (checkOpenBrackets(currentBlock) > 0) {
        runTheBlock = false; // unclosed brackets -> need more input
      } else if (lastRelevantLine.endsWith(':')) {
        runTheBlock = false; // if, for, while... -> need more input
      } else {
        // Block might be ok for execution. However, Wait for empty line to confirm - unless there
        // is only a single line in the block
        if (lines.where((l) => l.trim().isNotEmpty).length == 1) {
          runTheBlock = true;
        } else {
          runTheBlock = false;
        }
      }
    }

    if (runTheBlock) {
      run(currentBlock, isRepl: true);
      // reset for next input
      currentBlock = "";
      hadError = false;
      hadRuntimeError = false;
    }
  }
  print("\nExiting REPL.");
}