syntax = "proto2";
package org.jetbrains.kotlin.backend.common.serialization.proto;

// Changes to this proto are tracked by KotlinAbiVersion version. See KotlinAbiVersion KDoc.

option java_multiple_files = true;
option java_outer_classname = "KotlinIr";
option optimize_for = LITE_RUNTIME;

/* ------ Top Level --------------------------------------------- */

message FileEntry {
  required string name = 1;
  repeated int32 line_start_offset = 2 [packed=true];
  optional int32 first_relevant_line_index = 3 [default = 0];
}

message IrFile {
  repeated int32 declaration_id = 1 [packed=true];
  optional FileEntry file_entry = 2; // Required: either `file_entry` or `file_entry_id` is present.
  optional int32 file_entry_id = 7;  // Required: either `file_entry` or `file_entry_id` is present.
  repeated int32 fq_name = 3 [packed=true];
  repeated IrConstructorCall annotation = 4;
  repeated int64 explicitly_exported_to_compiler = 5 [packed=true];
  repeated int32 preprocessed_inline_functions = 8 [packed=true];

  // WARNING: Don't occupy index 6 which was previously used for storing expect/actual table.
  // repeated Actual actual = 6;
}

/* ------ IdSignature -------------------------------------------- */

message CommonIdSignature {
  repeated int32 package_fq_name = 1 [packed=true];
  repeated int32 declaration_fq_name = 2 [packed = true];
  optional int64 member_uniq_id = 3;
  optional int64 flags = 4 [default = 0];
  optional int32 debug_info = 5;
}

message AccessorIdSignature {
  required int32 property_signature = 1;
  required int32 name = 2;
  required int64 accessor_hash_id = 3;
  optional int64 flags = 4 [default = 0];
  optional int32 debug_info = 5;
}

message FileLocalIdSignature {
  required int32 container = 1;
  required int64 local_id = 2;

  // WARNING: Don't occupy index 3 which was previously used for storing local signature description.
  //optional int32 debug_info = 3;
}

message CompositeSignature {
  required int32 container_sig = 1;
  required int32 inner_sig = 2;
}

message LocalSignature {
  repeated int32 local_fq_name = 1 [packed=true];
  optional int64 local_hash = 2;

  // WARNING: Don't occupy index 3 which was previously used for storing local signature description.
  //optional int32 debug_info = 3;
}

message FileSignature {}

message IdSignature {
  oneof idSig {
    CommonIdSignature public_sig = 1;
    FileLocalIdSignature private_sig = 2;
    AccessorIdSignature accessor_sig = 3;
    int32 scoped_local_sig = 4;
    CompositeSignature composite_sig = 5;
    LocalSignature local_sig = 6;
    FileSignature file_sig = 7;
  }
}

/* ------ IrTypes --------------------------------------------- */

// Note: IrTypeArgument [63..2 - IrType index | 1..0 - Variance]
// If x...xxx00 -> *

message IrSimpleTypeLegacy {
  repeated IrConstructorCall annotation = 1;
  required int64 classifier = 2;
  required bool has_question_mark = 3;
  repeated int64 argument = 4 [packed=true]; // 0 - STAR, otherwise [63..2 - IrType index | 1..0 - Variance]
  optional IrTypeAbbreviation abbreviation = 5;
}

enum IrSimpleTypeNullability {
  MARKED_NULLABLE = 0;
  NOT_SPECIFIED = 1;
  DEFINITELY_NOT_NULL = 2;
}

message IrSimpleType {
  repeated IrConstructorCall annotation = 1;
  required int64 classifier = 2;
  optional IrSimpleTypeNullability nullability = 3 [default=NOT_SPECIFIED];
  repeated int64 argument = 4 [packed=true]; // 0 - STAR, otherwise [63..2 - IrType index | 1..0 - Variance]
  optional IrTypeAbbreviation abbreviation = 5;
}

message IrTypeAbbreviation {
  repeated IrConstructorCall annotation = 1;
  required int64 type_alias = 2;
  required bool has_question_mark = 3;
  repeated int64 argument = 4 [packed=true]; // 0 - STAR, otherwise [63..2 - IrType index | 1..0 - Variance]
}

message IrDynamicType {
  repeated IrConstructorCall annotation = 1;
}

message IrDefinitelyNotNullType {
  // In fact that is an `IntersectionType` so let represent it as it. In future it could be easy to support general case
  repeated int32 types = 1 [packed=true];
}

message IrType {
  oneof kind {
    IrSimpleTypeLegacy legacySimple = 1;
    IrDynamicType dynamic = 2;
    IrDefinitelyNotNullType dnn = 4;
    IrSimpleType simple = 5;

    // WARNING: Don't occupy index 3 which was previously used for storing IrErrorType.
    // IrErrorType error = 3;
  }
}

/* ------ IrExpressions --------------------------------------------- */


message IrBreak {
  required int32 loop_id = 1;
  optional int32 label = 2;
}

message IrBlock {
  repeated IrStatement statement = 1;
  optional int32 origin_name = 2;
}

message IrReturnableBlock {
  required int64 symbol = 1;
  required IrBlock base = 2;
}

message IrInlinedFunctionBlock {
  optional int64 inlined_function_symbol = 1;
  optional FileEntry inlined_function_file_entry = 2; // Required: either `inlined_function_file_entry` or `inlined_function_file_entry_id` is present.
  required IrBlock base = 3;
  required int32 inlined_function_start_offset = 4;
  required int32 inlined_function_end_offset = 5;
  optional int32 inlined_function_file_entry_id = 6;  // Required: either `inlined_function_file_entry` or `inlined_function_file_entry_id` is present.
}

message MemberAccessCommon {
  // Value argument serialization scheme after 2.2.0
  repeated NullableIrExpression argument = 6;

  // Value argument serialization scheme before 2.2.0
  optional IrExpression dispatch_receiver = 1;
  optional IrExpression extension_receiver = 2;
  repeated NullableIrExpression regular_argument = 3;

  repeated int32 type_argument = 4 [packed=true];

  // Previously used fields:
  //repeated NullableIrExpression context_argument = 5;
}

message IrCall {
  required int64 symbol = 1;
  required MemberAccessCommon member_access = 2;
  optional int64 super = 3;
  optional int32 origin_name = 4;
}

message IrConstructorCall {
  required int64 symbol = 1;
  required int32 constructor_type_arguments_count = 2;
  required MemberAccessCommon member_access = 3;
  optional int32 origin_name = 4;
}

message IrFunctionReference {
  required int64 symbol = 1;
  optional int32 origin_name = 2;
  required MemberAccessCommon member_access = 3;
  optional int64 reflection_target_symbol = 4;
}

message IrLocalDelegatedPropertyReference {
  required int64 delegate = 1;
  optional int64 getter = 2;
  optional int64 setter = 3;
  required int64 symbol = 4;
  optional int32 origin_name = 5;
}

message IrPropertyReference {
  optional int64 field = 1;
  optional int64 getter = 2;
  optional int64 setter = 3;
  optional int32 origin_name = 4;
  required MemberAccessCommon member_access = 5;
  required int64 symbol = 6;
}

message IrRichFunctionReference {
  repeated IrExpression bound_values = 1;
  optional int64 reflection_target_symbol = 2;
  required int64 overridden_function_symbol = 3;
  required IrFunction invoke_function = 4;
  optional int64 flags = 5 [default = 0];
  optional int32 origin_name = 6;
}

message IrRichPropertyReference {
  repeated IrExpression bound_values = 1;
  optional int64 reflection_target_symbol = 2;
  required IrFunction getter_function = 3;
  optional IrFunction setter_function = 4;
  optional int32 origin_name = 5;
}

message IrComposite {
  repeated IrStatement statement = 1;
  optional int32 origin_name = 2;
}

message IrClassReference {
  required int64 class_symbol = 1;
  required int32 class_type = 2;
}

message IrConst {
  oneof value {
    bool null = 1;
    bool boolean = 2;
    int32 char = 3;
    int32 byte = 4;
    int32 short = 5;
    int32 int = 6;
    int64 long = 7;
    fixed32 float_bits = 8;  // float/double is stored via fixed 32/64 bit value to avoid raw bit conversion
    fixed64 double_bits = 9;
    int32 string = 10;
  }
}

message IrContinue {
  required int32 loop_id = 1;
  optional int32 label = 2;
}

message IrDelegatingConstructorCall {
  required int64 symbol = 1;
  required MemberAccessCommon member_access = 2;
}

message IrDoWhile {
  required Loop loop = 1;
}

message IrEnumConstructorCall {
  required int64 symbol = 1;
  required MemberAccessCommon member_access = 2;
}

message IrGetClass {
  required IrExpression argument = 1;
}

message IrGetEnumValue {
  required int64 symbol = 1;
}

message FieldAccessCommon {
  required int64 symbol = 1;
  optional int64 super = 2;
  optional IrExpression receiver = 3;
}

message IrGetField {
  required FieldAccessCommon field_access = 1;
  optional int32 origin_name = 2;
}

message IrGetValue {
  required int64 symbol = 1;
  optional int32 origin_name = 2;
}

message IrGetObject {
  required int64 symbol = 1;
}

message IrInstanceInitializerCall {
  required int64 symbol = 1;
}

message Loop {
  required int32 loop_id = 1;
  required IrExpression condition = 2;
  optional int32 label = 3;
  optional IrExpression body = 4;
  optional int32 origin_name = 5;
}

message IrReturn {
  required int64 return_target = 1;
  required IrExpression value = 2;
}

message IrSetField {
  required FieldAccessCommon field_access = 1;
  required IrExpression value = 2;
  optional int32 origin_name = 3;
}

message IrSetValue {
  required int64 symbol = 1;
  required IrExpression value = 2;
  optional int32 origin_name = 3;
}

message IrSpreadElement {
  required IrExpression expression = 1;
  required int64 coordinates = 2;
}

message IrStringConcat {
  repeated IrExpression argument = 1;
}

message IrThrow {
  required IrExpression value = 1;
}

message IrTry {
  required IrExpression result = 1;
  repeated IrStatement catch = 2;
  optional IrExpression finally = 3;
}

message IrTypeOp {
  required IrTypeOperator operator = 1;
  required int32 operand = 2;
  required IrExpression argument = 3;
}

message IrVararg {
  required int32 element_type = 1;
  repeated IrVarargElement element = 2;
}

message IrVarargElement {
  oneof vararg_element {
    IrExpression expression = 1;
    IrSpreadElement spread_element = 2;
  }
}

message IrWhen {
  repeated IrStatement branch = 1;
  optional int32 origin_name = 2;
}

message IrWhile {
  required Loop loop = 1;
}

message IrFunctionExpression {
  required IrFunction function = 1;
  required int32 origin_name = 2;
}

message IrErrorExpression {
  required int32 description = 1;
}

message IrErrorCallExpression {
  required int32 description = 1;
  optional IrExpression receiver = 2;
  repeated IrExpression value_argument = 3;
}

/* ------ Dynamic expression --------------------------------------------- */

message IrDynamicMemberExpression {
  required int32 member_name = 1;
  required IrExpression receiver = 2;
}

message IrDynamicOperatorExpression {
  enum IrDynamicOperator {
    UNARY_PLUS = 1;
    UNARY_MINUS = 2;
    EXCL = 3;
    PREFIX_INCREMENT = 4;
    POSTFIX_INCREMENT = 5;
    PREFIX_DECREMENT = 6;
    POSTFIX_DECREMENT = 7;

    BINARY_PLUS = 8;
    BINARY_MINUS = 9;
    MUL = 10;
    DIV = 11;
    MOD = 12;
    GT = 13;
    LT = 14;
    GE = 15;
    LE = 16;
    EQEQ = 17;
    EXCLEQ = 18;
    EQEQEQ = 19;
    EXCLEQEQ = 20;
    ANDAND = 21;
    OROR = 22;

    EQ = 23;
    PLUSEQ = 24;
    MINUSEQ = 25;
    MULEQ = 26;
    DIVEQ = 27;
    MODEQ = 28;

    ARRAY_ACCESS = 29;
    INVOKE = 30;
  }
  required IrDynamicOperator operator = 1;
  required IrExpression receiver = 2;
  repeated IrExpression argument = 3;
}

// TODO: we need an extension mechanism to accomodate new
// IR operators in upcoming releases.
message IrOperation {
  oneof operation {
    IrBlock block = 1;
    IrBreak break = 2;
    IrCall call = 3;
    IrClassReference class_reference = 4;
    IrComposite composite = 5;
    IrConst const = 6;
    IrContinue continue = 7;
    IrDelegatingConstructorCall delegating_constructor_call = 8;
    IrDoWhile do_while = 9;
    IrEnumConstructorCall enum_constructor_call = 10;
    IrFunctionReference function_reference = 11;
    IrGetClass get_class = 12;
    IrGetEnumValue get_enum_value = 13;
    IrGetField get_field = 14;
    IrGetObject get_object = 15;
    IrGetValue get_value = 16;
    IrInstanceInitializerCall instance_initializer_call = 17;
    IrPropertyReference property_reference = 18;
    IrReturn return = 19;
    IrSetField set_field = 20;
    IrSetValue set_value = 21;
    IrStringConcat string_concat = 22;
    IrThrow throw = 23;
    IrTry try = 24;
    IrTypeOp type_op = 25;
    IrVararg vararg = 26;
    IrWhen when = 27;
    IrWhile while = 28;
    IrDynamicMemberExpression dynamic_member = 29;
    IrDynamicOperatorExpression dynamic_operator = 30;
    IrLocalDelegatedPropertyReference local_delegated_property_reference = 31;
    IrConstructorCall constructor_call = 32;
    IrFunctionExpression function_expression = 33;
    // Error code
    IrErrorExpression error_expression = 34;
    IrErrorCallExpression error_call_expression = 35;
    // Operations again
    IrReturnableBlock returnable_block = 36;
    IrInlinedFunctionBlock inlined_function_block = 37;
    IrRichFunctionReference rich_function_reference = 38;
    IrRichPropertyReference rich_property_reference = 39;
  }
}

enum IrTypeOperator {
  CAST = 1;
  IMPLICIT_CAST = 2;
  IMPLICIT_NOTNULL = 3;
  IMPLICIT_COERCION_TO_UNIT = 4;
  IMPLICIT_INTEGER_COERCION = 5;
  SAFE_CAST = 6;
  INSTANCEOF = 7;
  NOT_INSTANCEOF = 8;
  SAM_CONVERSION = 9;
  IMPLICIT_DYNAMIC_CAST = 10;
  REINTERPRET_CAST = 11;
}


message IrExpression {
  required IrOperation operation = 1;
  required int32 type = 2;
  required int64 coordinates = 3;
}

message NullableIrExpression {
  optional IrExpression expression = 1;
}

/* ------ Declarations --------------------------------------------- */

message IrDeclarationBase {
  required int64 symbol = 1;
  required int32 origin_name = 2;
  required int64 coordinates = 3;
  optional int64 flags = 4 [default = 0];
  repeated IrConstructorCall annotation = 5;
}

message IrFunctionBase {
  required IrDeclarationBase base = 1;
  required int64 name_type = 2;
  repeated IrTypeParameter type_parameter = 3;
  optional IrValueParameter dispatch_receiver = 4;
  repeated IrValueParameter context_parameter = 9;
  optional IrValueParameter extension_receiver = 5;
  repeated IrValueParameter regular_parameter = 6;
  optional int32 body = 7;
  //optional int32 context_receiver_parameters_count = 8;
}

message IrFunction {
  required IrFunctionBase base = 1;
  repeated int64 overridden = 2 [packed=true]; // TODO: supposed to be deleted
  //optional UniqId corresponding_property = 7;
}

message IrConstructor {
  required IrFunctionBase base = 1;
}

message IrField {
  required IrDeclarationBase base = 1;
  required int64 name_type = 2;
  optional int32 initializer = 3;
}

message IrLocalDelegatedProperty {
  required IrDeclarationBase base = 1;
  required int64 name_type = 2;
  optional IrVariable delegate = 3;
  optional IrFunction getter = 4;
  optional IrFunction setter = 5;
}

message IrProperty {
  required IrDeclarationBase base = 1;
  required int32 name = 2;
  optional IrField backing_field = 3;
  optional IrFunction getter = 4;
  optional IrFunction setter = 5;
}

message IrVariable {
  required IrDeclarationBase base = 1;
  required int64 name_type = 2;
  optional IrExpression initializer = 3;
}

message IrValueParameter {
  required IrDeclarationBase base = 1;
  required int64 name_type = 2;
  optional int32 vararg_element_type = 3;
  optional int32 default_value = 4;
}

message IrTypeParameter {
  required IrDeclarationBase base = 1;
  required int32 name = 2;
  repeated int32 super_type = 3 [packed=true];
}

message IrClass {
  required IrDeclarationBase base = 1;
  required int32 name = 2;
  optional IrValueParameter this_receiver = 3;
  repeated IrTypeParameter type_parameter = 4;
  repeated IrDeclaration declaration = 5;
  repeated int32 super_type = 6 [packed=true];
  optional IrInlineClassRepresentation inline_class_representation = 7;
  optional IrMultiFieldValueClassRepresentation multi_field_value_class_representation = 9;
  repeated int64 sealed_subclass = 8 [packed=true];
}

message IrTypeAlias {
  required IrDeclarationBase base = 1;
  required int64 name_type = 2;
  repeated IrTypeParameter type_parameter = 3;
}

message IrEnumEntry {
  required IrDeclarationBase base = 1;
  required int32 name = 2;
  optional int32 initializer = 3;
  optional IrClass corresponding_class = 4;
}

message IrAnonymousInit {
  required IrDeclarationBase base = 1;
  required int32 body = 2;
}

// TODO: we need an extension mechanism to accomodate new
// IR operators in upcoming releases.

message IrDeclaration {
  oneof declarator {
    IrAnonymousInit ir_anonymous_init = 1;
    IrClass ir_class = 2;
    IrConstructor ir_constructor = 3;
    IrEnumEntry ir_enum_entry = 4;
    IrField ir_field = 5;
    IrFunction ir_function = 6;
    IrProperty ir_property = 7;
    IrTypeParameter ir_type_parameter = 8;
    IrVariable ir_variable = 9;
    IrValueParameter ir_value_parameter = 10;
    IrLocalDelegatedProperty ir_local_delegated_property = 11;
    IrTypeAlias ir_type_alias = 12;

    // WARNING: Don't occupy index 13 which was previously used for storing IrErrorDeclaration.
    // IrErrorDeclaration ir_error_declaration = 13;
  }
}

/* ------- IrStatements --------------------------------------------- */

message IrBranch {
  required IrExpression condition = 1;
  required IrExpression result = 2;
}

message IrBlockBody {
  repeated IrStatement statement = 1;
}

message IrCatch {
  required IrVariable catch_parameter = 1;
  required IrExpression result = 2;
}

enum IrSyntheticBodyKind {
  ENUM_VALUES = 1;
  ENUM_VALUEOF = 2;
  ENUM_ENTRIES = 3;
}

message IrSyntheticBody {
  required IrSyntheticBodyKind kind = 1;
}

// Let's try to map IrElement as well as IrStatement to IrStatement.
message IrStatement {
  required int64 coordinates = 1;
  oneof statement {
    IrDeclaration declaration = 2;
    IrExpression expression = 3;
    IrBlockBody block_body = 4;
    IrBranch branch = 5;
    IrCatch catch = 6;
    IrSyntheticBody synthetic_body = 7;
  }
}

message IrInlineClassRepresentation {
  required int32 underlying_property_name = 1;
  required int32 underlying_property_type = 2;
}

message IrMultiFieldValueClassRepresentation {
  repeated int32 underlying_property_name = 1 [packed=true];
  repeated int32 underlying_property_type = 2 [packed=true];
}
