Advertisement
Guest User

Untitled

a guest
Dec 24th, 2011
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.18 KB | None | 0 0
  1. ######################################################
  2. ##
  3. ## Pair:
  4. ##
  5. ## An implementation of Lisp-style cons-pairs for
  6. ## Forth, based around a mark-and-sweep garbage
  7. ## collection system, and list manipulation utility
  8. ## words.
  9. ##
  10. ## This system uses two high-order bits to identify
  11. ## pointers to pairs for list traversal and garbage
  12. ## collection purposes. The constant 'true' and
  13. ## any fully-opaque or fully-transparent colors will
  14. ## not be falsely identified as a pair, but caution
  15. ## should be taken with having other potential
  16. ## collisions on the stacks or in managed memory
  17. ## during list operations.
  18. ##
  19. ## John Earnest
  20. ##
  21. ######################################################
  22.  
  23. :include "Print.fs"
  24.  
  25. :const nil -2147483648
  26. :const pair-mask 0x60000000
  27. :const pair-flag 0x40000000
  28. :const pair-hole 0x20000000
  29.  
  30. : nil? ( val -- flag )
  31. nil xor -if true else false then
  32. ;
  33.  
  34. : pair? ( addr -- flag )
  35. dup pair-flag and swap
  36. not pair-hole and or
  37. pair-mask xor
  38. if false else true then
  39. ;
  40.  
  41. : atom? ( addr -- flag )
  42. dup nil? not swap pair? not and
  43. ;
  44.  
  45. : .reach pair-mask not and ;
  46. : .first pair-mask not and 1 + ;
  47. : .rest pair-mask not and 2 + ;
  48.  
  49. : raw? ( addr -- flag )
  50. dup pair? if .rest @ atom?
  51. else drop false then
  52. ;
  53.  
  54. ######################################################
  55. ##
  56. ## Garbage Collector:
  57. ##
  58. ## Scans the data and return stacks as well as
  59. ## a specially declared region of 'managed memory'
  60. ## to find pair pointers. Can handle cyclic references.
  61. ##
  62. ## Garbage collection will occur automatically when
  63. ## pair operations need to allocate a pair and no
  64. ## heap cells are free. Only gc-init and free-cells
  65. ## are meant to be called explicitly.
  66. ##
  67. ######################################################
  68.  
  69. :const heap-size 500
  70. :array heap 1500 0
  71.  
  72. :proto managed-begin
  73. :proto managed-end
  74.  
  75. :var data-min
  76. :var data-max
  77. :var return-min
  78. :var return-max
  79.  
  80. : gc-init ( -- )
  81. DP @ data-min !
  82. RP @ 1 - return-min !
  83. ;
  84.  
  85. : free-cells ( -- count )
  86. 0 heap-size 1 - for
  87. i 3 * heap + @ -if 1 + then
  88. next
  89. ;
  90.  
  91. : walk ( pair* -- )
  92. dup .reach @ if drop exit then
  93. dup .reach true swap !
  94. dup .first @ dup pair? if walk else drop then
  95. .rest @ dup pair? if walk else drop then
  96. ;
  97.  
  98. : scan ( min max -- )
  99. over -
  100. for
  101. dup i + @ dup pair? if walk
  102. else drop then
  103. next
  104. drop
  105. ;
  106.  
  107. : collect ( -- )
  108. #"collecting garbage..." typeln
  109. DP @ data-max !
  110. RP @ return-max !
  111. free-cells
  112. heap-size 1 - for 0 i 3 * heap + ! next
  113. data-min @ data-max @ scan
  114. return-min @ return-max @ scan
  115. ' managed-begin ' managed-end scan
  116. free-cells swap - 1 <
  117. if "failed to free space." typeln halt then
  118. ;
  119.  
  120. : new-pair ( -- pair* )
  121. heap-size 1 - for
  122. i 3 * heap + dup @ -if
  123. pair-flag or
  124. 1 over .reach ! rdrop exit
  125. then
  126. drop
  127. next
  128. collect new-pair
  129. ;
  130.  
  131. ######################################################
  132. ##
  133. ## Pair Operations:
  134. ##
  135. ## Equivalent to cons, car, cdr, set-car! and set-cdr!,
  136. ## respectively, except with names that make sense.
  137. ##
  138. ######################################################
  139.  
  140. : pair ( first rest -- pair* )
  141. new-pair >r
  142. i .rest ! i .first ! r>
  143. ;
  144.  
  145. : first ( pair* -- first )
  146. .first @
  147. ;
  148.  
  149. : rest ( pair* -- rest )
  150. .rest @
  151. ;
  152.  
  153. : first! ( value pair* -- )
  154. .first !
  155. ;
  156.  
  157. : rest! ( value pair* -- )
  158. .rest !
  159. ;
  160.  
  161. : split ( pair* -- first rest )
  162. dup .first @ swap .rest @
  163. ;
  164.  
  165. : -split ( pair* -- rest first )
  166. dup .rest @ swap .first @
  167. ;
  168.  
  169. ######################################################
  170. ##
  171. ## List utilities:
  172. ##
  173. ## These are mostly recursive, so if you
  174. ## intend to use them for more than toy examples
  175. ## it would be a good idea to crank up the size
  176. ## of the data and return stacks.
  177. ##
  178. ######################################################
  179.  
  180. : list-build ( nil ... -- pair* )
  181. nil loop
  182. pair over nil?
  183. until
  184. swap drop
  185. ;
  186.  
  187. : [.atom] ( val -- )
  188. dup nil? if drop "nil " type else . then
  189. ;
  190.  
  191. : list-print ( pair* -- )
  192. dup pair? -if [.atom] exit then
  193. "[ " type
  194. dup raw? if
  195. -split [.atom] ". " type .
  196. else
  197. loop
  198. -split
  199. dup pair? if list-print else [.atom] then
  200. dup raw? if list-print break then
  201. dup nil? if drop break then
  202. again
  203. then
  204. "] " type
  205. ;
  206.  
  207. : list-join ( first* second* -- pair* )
  208. over nil? if swap drop exit then
  209. >r split r> list-join pair
  210. ;
  211.  
  212. : list-flatten ( pair* -- pair* )
  213. dup nil? if exit then
  214. dup raw? if nil pair exit then
  215. dup atom? if nil pair exit then
  216. split >r list-flatten
  217. r> list-flatten list-join
  218. ;
  219.  
  220. : list-reverse ( pair* -- pair* )
  221. dup nil? if exit then
  222. split list-reverse swap nil pair list-join
  223. ;
  224.  
  225. : list-length ( pair* -- count )
  226. 1 swap rest dup nil? if drop exit then
  227. list-length +
  228. ;
  229.  
  230. : list-nth ( pair* n -- value )
  231. over nil? if "bad list index!" typeln halt then
  232. dup -if drop first exit then
  233. 1 - swap rest swap list-nth
  234. ;
  235.  
  236. : list-last ( pair* -- value )
  237. dup rest nil? if first exit then
  238. rest list-last
  239. ;
  240.  
  241. : list-butlast ( pair* -- pair* )
  242. dup rest nil? if drop nil exit then
  243. split list-butlast pair
  244. ;
  245.  
  246. : list-equal? ( pair* pair* -- flag )
  247. over nil? over nil? or
  248. if over nil? over nil? and >r 2drop r> exit then
  249. over first over first xor if 2drop false exit then
  250. rest swap rest list-equal?
  251. ;
  252.  
  253. : list-apply ( pair* func* -- )
  254. over nil? if 2drop exit then
  255. >r -split i exec r> list-apply
  256. ;
  257.  
  258. : list-map ( pair* func* -- pair* )
  259. over nil? if drop exit then
  260. >r -split i exec swap r>
  261. list-map pair
  262. ;
  263.  
  264. : list-reduce ( pair* start bin-op* -- end )
  265. >r over nil? if swap r> 2drop exit then
  266. >r -split r> i exec r> list-reduce
  267. ;
  268.  
  269. : list-filter ( pair* pred* -- pair* )
  270. over nil? if drop exit then
  271. over first over exec
  272. if >r split r> list-filter pair
  273. else >r rest r> list-filter then
  274. ;
  275.  
  276. : list-zip ( a* b* -- pair* )
  277. over nil? over nil? or if 2drop nil exit then
  278. over first over first pair
  279. swap rest >r swap rest r>
  280. list-zip pair
  281. ;
  282.  
  283. : list-zipwith ( pair* n -- pair* )
  284. over nil? if drop exit then
  285. >r -split i pair swap r>
  286. list-zipwith pair
  287. ;
  288.  
  289. : list-cross ( a* b* -- pair* )
  290. dup nil? if swap drop exit then
  291. -split >r over r> list-zipwith
  292. swap >r swap r>
  293. list-cross pair
  294. ;
  295.  
  296. ######################################################
  297. ##
  298. ## Tests and examples
  299. ##
  300. ######################################################
  301.  
  302. # a little sugar for mitigating
  303. # any remaining Lisp envy:
  304. : [ nil ;
  305. : ] list-build ;
  306. : . list-print ;
  307.  
  308. # managed memory- any persistent storage
  309. # which might reference a pair must be wrapped
  310. # in these markers.
  311. : managed-begin ;
  312.  
  313. :var A
  314. :var B
  315.  
  316. : managed-end ;
  317.  
  318. : main
  319. # this routine must be called before
  320. # using any list-manipulation operations-
  321. # it caches the base positions of the stacks
  322. # so they can be scanned later.
  323. gc-init
  324.  
  325. 666 # stack 'canary'
  326.  
  327. 1 2 pair pair? .
  328. nil pair? .
  329. true pair? .
  330. false pair? . cr
  331.  
  332. [ 1 [ 2 3 ] 4 5 pair 6 ] . cr
  333. 77 33 44 nil pair pair pair . cr
  334. 5 4 3 pair pair . cr
  335. nil 1 pair . cr
  336. [ 1 2 3 [ 4 5 6 ] 7 [ 8 [ 9 10 ] ] ] . cr
  337. [ 3 4 5 ] A !
  338. [ 5 4 3 ] B !
  339. [ A @ B @ A @ B @ ] . cr
  340.  
  341. [ 9 8 7 ] [ 6 5 4 ] list-join . cr
  342.  
  343. [ 9 8 7 6 5 ] list-flatten . cr
  344. [ 9 [ [ 8 ] 7 ] 6 5 ] list-flatten . cr
  345. [ 1 2 pair 3 4 pair ] list-flatten . cr
  346.  
  347. [ 1 2 3 4 5 ] list-reverse . cr
  348.  
  349. [ 1 ] list-length .
  350. [ 1 2 ] list-length .
  351. [ 1 2 3 ] list-length . cr
  352.  
  353. [ 4 5 6 ]
  354. dup 0 list-nth .
  355. dup 1 list-nth .
  356. 2 list-nth . cr
  357.  
  358. [ 23 45 99 ] list-last . cr
  359. [ 23 45 99 ] list-butlast . cr
  360.  
  361. [ 1 2 3 ] [ 1 2 ] list-equal? .
  362. [ 1 2 3 ] [ 1 5 3 ] list-equal? .
  363. [ 1 2 3 ] [ 1 2 3 ] list-equal? . cr
  364.  
  365. [ 1 1 2 3 5 8 13 ] { . ", " type } list-apply cr
  366. [ 1 2 3 4 ] { 3 * } list-map . cr
  367. [ 1 2 3 4 ] 0 { + } list-reduce . cr
  368.  
  369. [ 5 4 3 2 1 ] { drop true } list-filter . cr
  370. [ 5 4 3 2 1 ] { drop false } list-filter . cr
  371. [ 1 2 3 4 5 ] { 2 mod } list-filter . cr
  372. [ 1 2 3 4 5 ] { 1 + 2 mod } list-filter . cr
  373.  
  374. [ 1 2 3 ] [ 4 5 6 ] list-zip . cr
  375. [ 1 2 ] [ 3 4 5 6 ] list-zip . cr
  376. [ 9 8 7 ] 88 list-zipwith . cr
  377. [ 1 2 3 ] [ 4 5 ] list-cross . cr
  378.  
  379. . cr # print the canary
  380.  
  381. halt
  382. ;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement