
fragment type U8;     size U8 1;     atom suffix U8     _u8;
fragment type U16;    size U16 2;    atom suffix U16    _u16;
fragment type U32;    size U32 4;    atom suffix U32    _u32;
fragment type U64;    size U64 8;    atom suffix U64    _u64;
fragment type I8;     size I8 1;     atom suffix I8     _i8;
fragment type I16;    size I16 2;    atom suffix I16    _i16;
fragment type I32;    size I32 4;    atom suffix I32    _i32;
fragment type I64;    size I64 8;    atom suffix I64    _i64;
fragment type ASCII;  size ASCII 1;  atom suffix ASCII  _c;
fragment type String; size String 8; atom suffix String _s;

#[] := λ(: l Array<Sized<8>,?>)(: li U64). (: (
#   (mov( l R15 ))
#   (mov( r R14 ))
#   (shl( 3_u64 R14 ))
#   (add( R14 R15 ))
#   (mov( R15 0_u64 RAX ))
#   (as RAX x)
#) x);
#[] := λ(: l Array<Sized<4>,?>)(: li U64). (: (
#   (mov( l R15 ))
#   (mov( r R14 ))
#   (shl( 2_u64 R14 ))
#   (add( R14 R15 ))
#   (mov( R15 0_u64 RAX ))
#   (as RAX x)
#) x);
#[] := λ(: l Array<Sized<2>,?>)(: li U64). (: (
#   (mov( l R15 ))
#   (mov( r R14 ))
#   (shl( 1_u64 R14 ))
#   (add( R14 R15 ))
#   (mov( R15 0_u64 RAX ))
#   (as RAX x)
#) x);
#[] := λ(: l Array<Sized<1>,?>)(: li U64). (: (
#   (mov( l R15 ))
#   (mov( r R14 ))
#   (add( R14 R15 ))
#   (mov( R15 0_u64 RAX ))
#   (as RAX x)
#) x);

fragment [] := λ(: l LocalVariable+Array<x+Sized<1>,?>)(: r LocalVariable+U64). (: (
   (.program (
      \t 'mov \s (.expression l) \[ '%rbp \] , \s '%r15 \n
      \t 'mov \s (.expression r) \[ '%rbp \] , \s '%r14 \n
      \t 'add \s '%r14 , \s '%r15 \n
      \t 'mov \s '0 \[ '%r15 \] , \s '%r15b \n
   ))
   (.expression( 'r15b ))
) x+Reg8);


fragment [] := λ(: l LocalVariable+Array<x,?>)(: r GlobalVariable+U64). (: (
   (.program (
      \t 'mov \s '$ (.expression l) , \s '%r15 \n
      \t 'mov \s '$ (.expression r) , \s '%r14 \n
      \t 'mov \s '0 \[ '%r14 \] , \s '%r14 \n
      \t 'shl \s '$3 , \s '%r14 \n
      \t 'add \s '%r14 , \s '%r15 \n
      \t 'mov \s '0 \[ '%r15 \] , \s '%r15 \n
   ))
   (.expression( 'r15 ))
) x+Reg64);

fragment [] := λ(: l GlobalVariable+Array<x,?>)(: r GlobalVariable+U64). (: (
   (.program (
      \t 'mov \s '$ (.expression l) , \s '%r15 \n
      \t 'mov \s '$ (.expression r) , \s '%r14 \n
      \t 'mov \s '0 \[ '%r14 \] , \s '%r14 \n
      \t 'shl \s '$3 , \s '%r14 \n
      \t 'add \s '%r14 , \s '%r15 \n
      \t 'mov \s '0 \[ '%r15 \] , \s '%r15 \n
   ))
   (.expression( 'r15 ))
) x+Reg64);
fragment [] := λ(: l GlobalVariable+Array<x,?>)(: r LocalVariable+U64). (: (
   (.program (
      \t 'mov \s '$ (.expression l) , \s '%r15 \n
      \t 'mov \s (.expression r) \[ '%rbp \] , \s '%r14 \n
      \t 'shl \s '$3 , \s '%r14 \n
      \t 'add \s '%r14 , \s '%r15 \n
      \t 'mov \s '0 \[ '%r15 \] , \s '%r15 \n
   ))
   (.expression( 'r15 ))
) x+Reg64);
fragment [] := λ(: l GlobalVariable+Array<x,?>)(: r Constant+U64). (: (
   (.program (
      \t 'mov \s '$ (.expression l) , \s '%r15 \n
      \t 'mov \s '$ (.expression r) , \s '%r14 \n
      \t 'shl \s '$3 , \s '%r14 \n
      \t 'add \s '%r14 , \s '%r15 \n
      \t 'mov \s '0 \[ '%r15 \] , \s '%r15 \n
   ))
   (.expression( 'r15 ))
) x+Reg64);

fragment > := λ(: l GlobalVariable+U64)(: r Constant+U64). (: (
   (.program (
      \t 'mov \s '$ (.expression l) , \s '%r15 \n
      \t 'mov \s '0 \[ '%r15 \] , \s '%r15 \n
      \t 'cmp \s '$ (.expression r) , '%r15 \n
   ))
   (.expression( 'ja ))
) BranchConditional);
fragment > := λ(: l LocalVariable+U64)(: r Constant+U64). (: (
   (.program (
      \t 'mov \s (.expression l) \[ '%rbp \] , \s '%r15 \n
      \t 'cmp \s '$ (.expression r) , '%r15 \n
   ))
   (.expression( 'ja ))
) BranchConditional);

< := λ(: l U64)(: r U64). (: (tail(
   (gensym-label end)
   (mov( 1_u64 RAX ))
   (mov( l R8 ))
   (mov( r R9 ))
   (cmp( R9 R8 ))
   (jb end)
   (mov( 0_u64 RAX ))
   (label end)
   (as RAX U64)
)) U64);

+ := λ(: l U64)(: r U64). (: (tail(
   (mov( l R8 ))
   (mov( r RAX ))
   (add( R8 RAX ))
   (as RAX U64)
)) U64);

- := λ(: l U64)(: r U64). (: (tail(
   (mov( r R8 ))
   (mov( l RAX ))
   (sub( R8 RAX ))
   (as RAX U64)
)) U64);

fragment branchtrue := λ(: _ Nil). (: (
   (.expression( 'jmp ))
) BranchConditional);
fragment branchfalse := λ(: _ Nil). (: (
   (.program( \t 'cmp \s '%rsp, \s '%rsp \n ))
   (.expression( 'jne ))
) BranchConditional);

!= := λ(: l U8)(: r U8). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14B ))
   (mov( r R15B ))
   (cmp( R14B R15B ))
   (je end-false)
   (jmp end-true)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);

== := λ(: l U8)(: r U8). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14B ))
   (mov( r R15B ))
   (cmp( R14B R15B ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);
== := λ(: l U16)(: r U16). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14W ))
   (mov( r R15W ))
   (cmp( R14W R15W ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);
== := λ(: l U32)(: r U32). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14D ))
   (mov( r R15D ))
   (cmp( R14D R15D ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);
== := λ(: l U64)(: r U64). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14 ))
   (mov( r R15 ))
   (cmp( R14 R15 ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);


== := λ(: l I8)(: r I8). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14B ))
   (mov( r R15B ))
   (cmp( R14B R15B ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);
== := λ(: l I16)(: r I16). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14W ))
   (mov( r R15W ))
   (cmp( R14W R15W ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);
== := λ(: l I32)(: r I32). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14D ))
   (mov( r R15D ))
   (cmp( R14D R15D ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);
== := λ(: l I64)(: r I64). (: (tail(
   (push R14)
   (push R15)
   (gensym-label end-true)
   (gensym-label end-false)
   (gensym-label end)
   (mov( l R14 ))
   (mov( r R15 ))
   (cmp( R14 R15 ))
   (je end-true)
   (jmp end-false)
   (label end-true)
   (mov( 1_u64 RAX ))
   (jmp end)
   (label end-false)
   (mov( 0_u64 RAX ))
   (jmp end)
   (label end)
   (pop R15)
   (pop R14)
   (as RAX U64)
)) U64);

