# some list words # these should use only return stack recursion: # move the control stuff to RS and leave the data stack free # for unbalanced words to mess up # in addition to that, they should not use the abort stack, which woul # allow them to be used in coroutines (or anything that survives # context switches) # SEMANTICS: both are serial: they can use the data stack for # accumulation: if map/for-each are called with ( ..stuff.. lst xt ), # the corresponding xt is called with ( ..stuf.. el ) # these are just pre/post loop macros moving stuff to RS to execute # the XT with a clean DS.. local variables would be nice here.. # DS RS # ( ptr xt -- xt ) ( -- xt ptr ) : pre-map postpone dup postpone >r postpone swap postpone >r ; immediate # DS RS # ( -- ptr+ xt ) ( xt ptr -- ) : post-map postpone r> postpone follow postpone r> ; immediate : map-rest # ( ptr xt -- ) over if pre-map r @> swap execute r ! post-map pass map-rest then 2drop ; : for-each-rest # ( ptr xt -- ) over if pre-map r @> swap execute post-map pass for-each-rest then 2drop ; # : @map swap head swap map-next ;; # : @for-each swap head swap for-each-next ;; : map swap >r rsp head swap map-rest r> ; "( list xt -- list)\t" "Process each element in list using xt : ( el -- el )" concat doc : for-each swap >r rsp head swap for-each-rest rdrop ; "( list xt -- )\t" "Similar to map, but xt is a consumer : ( el -- )" concat doc : do-list-var find execute @ ; : list-var@ ['] do-list-var map ; "(list -- list)\tDeref a list of symbol values." doc : split >r rsp pop r> swap ; "( list -- rest first )\tSplit off first element." doc : unsplit swap >r rsp push r> ; "( rest first -- list)\tUndo split: push element on list." doc : cons >r rsp push r> ; : uncons >r rsp pop r> ; : unsplit swap >r rsp push r> ; "( rest first -- list )\tJoin an element to a list." doc # used for recursion over lists in this form: # : x split? if ... pass x then ; : split? list:size if split -1 else drop 0 then ; : list list:pack list:reverse ; # FIXME 'pack' is not very natural to use, use list instead : swoncat swap concat ; : unlist list:reverse list:unpack ;; # i'm not sure about this # cycle is here pop followed by queue. it cycles a variable.. # should it also cycle a list on tos?? that's why list:cycle is provided # DISABLED # : cycle >r r pop r> queue ; # : list:cycle >r rtop cycle r> ; # stacks : xchg >r r @> swap r> ! ; # PARAMETERS # a parameter is a (variable value) pair and is used for dynamic # variable storage. it is not a dictionary, but a datastructure used # to implement shallow binding. # swap a variable : @swap dup >r @> swap r> ! ; "( value variable -- value )\tSwap the value of a variable." doc # same, but exchange an assoc list item, where the key = cell : swap-parameter unpack dup >r @swap r> 2 pack ; # make a variable/value list from a set of symbols, with empty containers : names>parameters { interpret undef 2 list } map ; # parameter swapping : swap-parameters ' swap-parameter map ; : @swap-parameters >r r @> swap-parameters r> ! ;