import type { Stack , StackContext } from "./api.js" ; import { $ , $n } from "./safe.js" ; const __xsp = ( id ) => ( ctx ) => ( ctx [ 0 ] . push ( ctx [ id ] . length ) , ctx ) ; const __dup = ( id ) => __copy ( id , id ) ; const __dup2 = ( id ) => ( ctx ) => { const stack = ctx [ id ] ; let n = stack . length - 2 ; $n ( n , 0 ) ; stack . push ( stack [ n ] , stack [ n + 1 ] ) ; return ctx ; } ; const __dup3 = ( id ) => ( ctx ) => { const stack = ctx [ id ] ; let n = stack . length - 3 ; $n ( n , 0 ) ; stack . push ( stack [ n ] , stack [ n + 1 ] , stack [ n + 2 ] ) ; return ctx ; } ; const __drop = ( id , n = 1 ) => ( ctx ) => ( $ ( ctx [ id ] , 1 ) , ( ctx [ id ] . length -= n ) , ctx ) ; const __swap = ( i ) => ( ctx ) => { const stack = ctx [ i ] ; const n = stack . length - 2 ; $n ( n , 0 ) ; const a = stack [ n ] ; stack [ n ] = stack [ n + 1 ] ; stack [ n + 1 ] = a ; return ctx ; } ; const __swap2 = ( i ) => ( ctx ) => { const stack = ctx [ i ] ; let n = stack . length - 1 ; $n ( n , 3 ) ; let a = stack [ n ] ; stack [ n ] = stack [ n - 2 ] ; stack [ n - 2 ] = a ; n -- ; a = stack [ n ] ; stack [ n ] = stack [ n - 2 ] ; stack [ n - 2 ] = a ; return ctx ; } ; const __over = ( id ) => ( ctx ) => { const stack = ctx [ id ] ; const n = stack . length - 2 ; $n ( n , 0 ) ; stack . push ( stack [ n ] ) ; return ctx ; } ; const __move = ( src , dest ) => ( ctx ) => ( $ ( ctx [ src ] , 1 ) , ctx [ dest ] . push ( ctx [ src ] . pop ( ) ) , ctx ) ; const __move2 = ( a , b ) => ( ctx ) => { const src = ctx [ a ] ; $ ( src , 2 ) ; const v = src . pop ( ) ; ctx [ b ] . push ( src . pop ( ) , v ) ; return ctx ; } ; const __copy = ( src , dest ) => ( ctx ) => ( $ ( ctx [ src ] , 1 ) , ctx [ dest ] . push ( tos ( ctx [ src ] ) ) , ctx ) ; const __copy2 = ( a , b ) => ( ctx ) => { const src = ctx [ a ] ; const n = src . length - 2 ; $n ( n , 0 ) ; ctx [ b ] . push ( src [ n ] , src [ n + 1 ] ) ; return ctx ; } ; const __incdec = ( id , n ) => ( ctx ) => ( $ ( ctx [ id ] , 1 ) , ( ctx [ id ] [ ctx [ id ] . length - 1 ] += n ) , ctx ) ; param stack export const tos = ( stack ) => stack [ stack . length - 1 ] ; /**
 * Utility word w/ no stack nor side effect.
 */ export const nop = ( ctx ) => ctx ; param ctx export const dsp = __xsp ( 0 ) ; param ctx export const pick = ( ctx ) => { const stack = ctx [ 0 ] ; let n = stack . length - 1 ; $n ( n , 0 ) ; $n ( ( n -= stack . pop ( ) + 1 ) , 0 ) ; stack . push ( stack [ n ] ) ; return ctx ; } ; param ctx export const drop = __drop ( 0 ) ; param ctx export const drop2 = __drop ( 0 , 2 ) ; /**
 * If TOS is truthy then drop it:
 *
 * ( x -- )
 *
 * Else, no effect:
 *
 * ( x -- x )
 */ export const dropif = ( ctx ) => ( $ ( ctx [ 0 ] , 1 ) , tos ( ctx [ 0 ] ) && ctx [ 0 ] . length -- , ctx ) ; param args export const defPush = ( ... args ) => ( ctx ) => ( ctx [ 0 ] . push ( ... args ) , ctx ) ; param ctx export const dup = __dup ( 0 ) ; param ctx export const dup2 = __dup2 ( 0 ) ; param ctx export const dup3 = __dup3 ( 0 ) ; param ctx export const dupif = ( ctx ) => { $ ( ctx [ 0 ] , 1 ) ; const x = tos ( ctx [ 0 ] ) ; x && ctx [ 0 ] . push ( x ) ; return ctx ; } ; param ctx export const swap = __swap ( 0 ) ; param ctx export const swap2 = __swap2 ( 0 ) ; param ctx export const nip = ( ctx ) => { const stack = ctx [ 0 ] ; const n = stack . length - 2 ; $n ( n , 0 ) ; stack [ n ] = stack . pop ( ) ; return ctx ; } ; param ctx export const tuck = ( ctx ) => { $ ( ctx [ 0 ] , 2 ) ; const stack = ctx [ 0 ] ; const a = stack . pop ( ) ; stack . push ( a , stack . pop ( ) , a ) ; return ctx ; } ; param ctx export const rot = ( ctx ) => { const stack = ctx [ 0 ] ; const n = stack . length - 1 ; $n ( n , 2 ) ; const c = stack [ n - 2 ] ; stack [ n - 2 ] = stack [ n - 1 ] ; stack [ n - 1 ] = stack [ n ] ; stack [ n ] = c ; return ctx ; } ; param ctx export const invrot = ( ctx ) => { const stack = ctx [ 0 ] ; const n = stack . length - 1 ; $n ( n , 2 ) ; const c = stack [ n ] ; stack [ n ] = stack [ n - 1 ] ; stack [ n - 1 ] = stack [ n - 2 ] ; stack [ n - 2 ] = c ; return ctx ; } ; param ctx export const over = __over ( 0 ) ; param ctx export const inc = __incdec ( 0 , 1 ) ; param ctx export const dec = __incdec ( 0 , - 1 ) ; param ctx export const rsp = __xsp ( 1 ) ; param ctx export const rdup = __dup ( 1 ) ; param ctx export const rdup2 = __dup2 ( 1 ) ; param ctx export const rdup3 = __dup3 ( 1 ) ; param ctx export const rdrop = __drop ( 1 ) ; param ctx export const rdrop2 = __drop ( 1 , 2 ) ; export const movdr = __move ( 0 , 1 ) ; export const movrd = __move ( 1 , 0 ) ; export const cpdr = __copy ( 0 , 1 ) ; export const cprd = __copy ( 1 , 0 ) ; export const movdr2 = __move2 ( 0 , 1 ) ; export const movrd2 = __move2 ( 1 , 0 ) ; export const cpdr2 = __copy2 ( 0 , 1 ) ; export const cprd2 = __copy2 ( 1 , 0 ) ; param ctx export const rswap = __swap ( 1 ) ; param ctx export const rswap2 = __swap2 ( 1 ) ; param ctx export const rover = __over ( 1 ) ; /**
 * Like  inc , but applies to r-stack TOS.
 *
 *  param ctx export const rinc = __incdec ( 1 , 1 ) ; /**
 * Like  dec , but applies to r-stack TOS.
 *
 *  param ctx export const rdec = __incdec ( 1 , - 1 ) ;