: ASSERT ( n -- ) IF ABORT" Array index < 0" THEN ;
: ASSERT2 ( n -- ) IF ABORT" Array index >= lim" THEN ;
: X4 ( n -- n ) DUP + DUP + ;

: (I) ( n arr -- @elem )
 SWAP DUP ( arr n n )
 0 < ASSERT ( arr n )
 SWAP DUP @ >R ( n arr | @arr )
 SWAP DUP R> >= ASSERT2 ( arr n )
 1 + X4 + ;

: ARRAY ( name ( sz -- )
 CREATE
 DUP ,
 DUP + ALLOT
 DOES> (I) ;

: (I2) ( i j arr -- @elem )
 DUP @ SWAP ( i j @arr arr )
 >R >R SWAP ( j i | arr @arr )
 DUP 0  <  ASSERT ( i < 0 ) ( j i | arr @arr )
 DUP R> >= ASSERT ( i >= sz ) ( j i | arr )
 SWAP DUP R> ( i j j arr )
 DUP 2 + @ SWAP >R ( i j j arr[1] | arr )
 DUP >R ( i j j arr[1] | arr arr[1] )
 >= ASSERT ( i j | arr arr[1] )
 DUP 0 < ASSERT ( i j | arr arr[1] )
 SWAP R> * + X4 R> + ;
 
: ARRAY2 ( name ( i j -- )
 CREATE
 >R DUP ,
 R> DUP ,
 SWAP 1
 DO DUP ALLOT LOOP
 DROP
 DOES> (I2) ;