#include <perms.h>

//          Edinburgh IMP77 Compiler - Version 8.4
//
//     1  %begin

int main(int argc, char **argv) { /*%begin*/
  _imp_initialise(argc, argv);

  //     2
  //     3    %recordformat small rec fm(%integer i, %real r)

  struct SMALLRECFM {
    union {
      struct {
        int I;
        float R;
      };
    };
  };

  //     4    %recordformat big rec fm(%integer i, %real r, %string(255) s)

  struct BIGRECFM {
    union {
      struct {
        int I;
        float R;
        _imp_string255 S;
      };
    };
  };

  //     5
  //     6    %record (small rec fm) small rec, small rec 2

  struct SMALLRECFM SMALLREC;
  struct SMALLRECFM SMALLREC2;

  //     7    %record (big rec fm) big rec

  struct BIGRECFM BIGREC;

  //     8
  //     9    %record (small rec fm) %name small ptr

  struct SMALLRECFM *SMALLPTR;

  //    10
  //    11    small rec_i = 123 ; small rec_r = 234.56

  SMALLREC.I = 123;
  SMALLREC.R = 234.56;

  //    12    big rec_i = 123 ; big rec_r = 234.56 ; big rec_s = "A String"

  BIGREC.I = 123;
  BIGREC.R = 234.56;

  /* clang-format off */
_imp_strncpy(/*?*/&BIGREC.S, ({__typeof__(_imp_string255) tmp;/*B*/ tmp = _imp_str_literal("A String"); (void *)&tmp;}), /*max:*/255);

  /* clang-format on */

  //    13
  //    14  ! regular record assignments. These work OK.
  //    15
  //    16    small ptr == small rec 2

  SMALLPTR = (struct SMALLRECFM *)/*?*/ &SMALLREC2;

  //    17
  //    18    small ptr = small rec

  *SMALLPTR = SMALLREC;

  //    19
  //    20    small rec = small ptr

  SMALLREC = *SMALLPTR;

  //    21
  //    22    small rec <- small ptr

  SMALLREC = /*jam transfer*/ *SMALLPTR;

  //    23
  //    24  ! These generate bad code:
  //    25
  //    26  ! RECORD() on RHS
  //    27
  //    28    small ptr == RECORD(ADDR(big rec))

  SMALLPTR = (struct SMALLRECFM *)_imp_RECORD(_imp_ADDR(/*?*/ &BIGREC));

  //    29
  //    30    small ptr == RECORD(ADDR(small rec))

  SMALLPTR = (struct SMALLRECFM *)_imp_RECORD(_imp_ADDR(/*?*/ &SMALLREC));

  //    31
  //    32    small rec 2 = RECORD(ADDR(big rec))

  SMALLREC2 = *_imp_RECORD(_imp_ADDR(/*?*/ &BIGREC));

  //    33
  //    34    small rec 2 <- RECORD(ADDR(big rec))

  SMALLREC2 = /*jam transfer*/ *_imp_RECORD(_imp_ADDR(/*?*/ &BIGREC));

  //    35
  //    36    small ptr = RECORD(ADDR(big rec))

  *SMALLPTR = *_imp_RECORD(_imp_ADDR(/*?*/ &BIGREC));

  //    37
  //    38    small ptr <- RECORD(ADDR(big rec))

  *SMALLPTR = /*jam transfer*/ *_imp_RECORD(_imp_ADDR(/*?*/ &BIGREC));

  //    39
  //    40  ! RECORD() on LHS
  //    41
  //    42    RECORD(ADDR(big rec)) = small rec

  *_imp_RECORD(_imp_ADDR(/*?*/ &BIGREC)) = SMALLREC;

  //    43
  //    44    RECORD(ADDR(big rec)) <- small rec

  *_imp_RECORD(_imp_ADDR(/*?*/ &BIGREC)) = /*jam transfer*/ SMALLREC;

  //    45
  //    46    RECORD(ADDR(small rec)) = big rec

  *_imp_RECORD(_imp_ADDR(/*?*/ &SMALLREC)) = BIGREC;

  //    47
  //    48    RECORD(ADDR(small rec)) <- big rec

  *_imp_RECORD(_imp_ADDR(/*?*/ &SMALLREC)) = /*jam transfer*/ BIGREC;

  //    49
  //    50
  //    51  %endofprogram

  _imp_stop(0);
  return 0;
end_0:;
}