// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'bytecode_serialization.dart' show BufferedWriter, BufferedReader;

/*

In kernel binary, try blocks are encoded in the following way
(using notation from pkg/kernel/binary.md):

// Offset of a bytecode instruction.
type BytecodeOffset = UInt;

type TryBlock {
  UInt outerTryIndexPlus1;
  BytecodeOffset startPC; // Inclusive.
  BytecodeOffset endPC; // Exclusive.
  BytecodeOffset handlerPC;
  Byte flags (needsStackTrace, isSynthetic);
  List<ConstantIndex> types;
}

type ExceptionsTable {
  // Ordered by startPC, then by nesting (outer precedes inner).
  // Try blocks are properly nested. It means there are no partially
  // overlapping try blocks - each pair of try block regions either
  // has no intersection or one try block region encloses another.
  List<TryBlock> tryBlocks;
}

*/

class TryBlock {
  static const int flagNeedsStackTrace = 1 << 0;
  static const int flagIsSynthetic = 1 << 1;

  final int tryIndex;
  final int outerTryIndex;
  final int startPC;
  int endPC = -1;
  int handlerPC = -1;
  int flags = 0;
  List<int> types = <int>[];

  TryBlock._(this.tryIndex, this.outerTryIndex, this.startPC);

  bool get needsStackTrace => (flags & flagNeedsStackTrace) != 0;

  void set needsStackTrace(bool value) {
    flags = (flags & ~flagNeedsStackTrace) | (value ? flagNeedsStackTrace : 0);
  }

  bool get isSynthetic => (flags & flagIsSynthetic) != 0;

  void set isSynthetic(bool value) {
    flags = (flags & ~flagIsSynthetic) | (value ? flagIsSynthetic : 0);
  }

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(outerTryIndex + 1);
    writer.writePackedUInt30(startPC);
    writer.writePackedUInt30(endPC);
    writer.writePackedUInt30(handlerPC);
    writer.writeByte(flags);
    writer.writePackedUInt30(types.length);
    types.forEach(writer.writePackedUInt30);
  }

  factory TryBlock.read(BufferedReader reader, int tryIndex) {
    final outerTryIndex = reader.readPackedUInt30() - 1;
    final startPC = reader.readPackedUInt30();
    final tryBlock = new TryBlock._(tryIndex, outerTryIndex, startPC);

    tryBlock.endPC = reader.readPackedUInt30();
    tryBlock.handlerPC = reader.readPackedUInt30();
    tryBlock.flags = reader.readByte();
    tryBlock.types = new List<int>.generate(
        reader.readPackedUInt30(), (_) => reader.readPackedUInt30());

    return tryBlock;
  }

  @override
  String toString() => 'try-index $tryIndex, outer $outerTryIndex, '
      'start $startPC, end $endPC, handler $handlerPC, '
      '${needsStackTrace ? 'needs-stack-trace, ' : ''}'
      '${isSynthetic ? 'synthetic, ' : ''}'
      'types ${types.map((t) => 'CP#$t').toList()}';
}

class ExceptionsTable {
  List<TryBlock> blocks = <TryBlock>[];

  ExceptionsTable();

  TryBlock enterTryBlock(int startPC) {
    assert(blocks.isEmpty || blocks.last.startPC <= startPC);
    final tryBlock =
        new TryBlock._(blocks.length, _outerTryBlockIndex(startPC), startPC);
    blocks.add(tryBlock);
    return tryBlock;
  }

  int _outerTryBlockIndex(int startPC) {
    for (int i = blocks.length - 1; i >= 0; --i) {
      final tryBlock = blocks[i];
      if (tryBlock.endPC < 0 || tryBlock.endPC > startPC) {
        return i;
      }
    }
    return -1;
  }

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(blocks.length);
    blocks.forEach((b) => b.write(writer));
  }

  ExceptionsTable.read(BufferedReader reader)
      : blocks = new List<TryBlock>.generate(reader.readPackedUInt30(),
            (int index) => new TryBlock.read(reader, index));

  @override
  String toString() {
    if (blocks.isEmpty) {
      return '';
    }
    StringBuffer sb = new StringBuffer();
    sb.writeln('ExceptionsTable {');
    for (var tryBlock in blocks) {
      sb.writeln('  $tryBlock');
    }
    sb.writeln('}');
    return sb.toString();
  }
}
