PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/arc.arc

http://github.com/alimoeeny/arc
Unknown | 1918 lines | 1534 code | 384 blank | 0 comment | 0 complexity | 1621970a85d0ee1da21ed634d460914b MD5 | raw file
  1. ; Main Arc lib. Ported to Scheme version Jul 06.
  2. ; don't like names of conswhen and consif
  3. ; need better way of generating strings; too many calls to string
  4. ; maybe strings with escape char for evaluation
  5. ; make foo~bar equiv of foo:~bar (in expand-ssyntax)
  6. ; add sigs of ops defined in ac.scm
  7. ; get hold of error types within arc
  8. ; does macex have to be defined in scheme instead of using def below?
  9. ; write disp, read, write in arc
  10. ; could I get all of macros up into arc.arc?
  11. ; warn when shadow a global name
  12. ; some simple regexp/parsing plan
  13. ; compromises in this implementation:
  14. ; no objs in code
  15. ; (mac testlit args (listtab args)) breaks when called
  16. ; separate string type
  17. ; (= (cdr (cdr str)) "foo") couldn't work because no way to get str tail
  18. ; not sure this is a mistake; strings may be subtly different from
  19. ; lists of chars
  20. (assign current-load-file* "arc.arc")
  21. (assign source-file* (table))
  22. (assign source* (table))
  23. (assign help* (table))
  24. (assign do (annotate 'mac
  25. (fn args `((fn () ,@args)))))
  26. (sref sig 'args 'do)
  27. (sref source-file* current-load-file* 'do)
  28. (assign safeset (annotate 'mac
  29. (fn (var val)
  30. `(do (if (bound ',var)
  31. (do (disp "*** redefining " (stderr))
  32. (disp ',var (stderr))
  33. (disp #\newline (stderr))))
  34. (assign ,var ,val)))))
  35. (sref sig '(var val) 'safeset)
  36. (sref source-file* current-load-file* 'safeset)
  37. (assign docify-body (fn (body)
  38. (if (if (is (type car.body) 'string) cdr.body) body
  39. (cons nil body))))
  40. (sref sig '(body) 'docify-body)
  41. (sref source-file* current-load-file* 'docify-body)
  42. (assign def (annotate 'mac
  43. (fn (name parms . body)
  44. ((fn ((doc . body))
  45. `(do (sref sig ',parms ',name)
  46. (sref help* ',doc ',name)
  47. (sref source-file* current-load-file* ',name)
  48. (sref source* '(def ,name ,parms ,@body) ',name)
  49. (safeset ,name (fn ,parms ,@body))))
  50. (docify-body body)))))
  51. (sref sig '(name parms . body) 'def)
  52. (sref source-file* current-load-file* 'def)
  53. (def caar (xs) (car:car xs))
  54. (def cadr (xs) (car:cdr xs))
  55. (def cddr (xs) (cdr:cdr xs))
  56. (def cdar (xs) (cdr:car xs))
  57. (def cadar (xs) (car:cdar xs))
  58. (def no (x) (is x nil))
  59. (def acons (x) (is (type x) 'cons))
  60. (def atom (x) (no (acons x)))
  61. ; Can return to this def once Rtm gets ac to make all rest args
  62. ; nil-terminated lists.
  63. ; (def list args args)
  64. (def copylist (xs)
  65. (if (no xs)
  66. nil
  67. (cons (car xs) (copylist (cdr xs)))))
  68. (def list args (copylist args))
  69. (def idfn (x) x)
  70. ; Maybe later make this internal. Useful to let xs be a fn?
  71. (def map1 (f xs)
  72. (if (no xs)
  73. nil
  74. (cons (f (car xs)) (map1 f (cdr xs)))))
  75. (def pair (xs (o f list))
  76. (if (no xs)
  77. nil
  78. (no (cdr xs))
  79. (list (list (car xs)))
  80. (cons (f (car xs) (cadr xs))
  81. (pair (cddr xs) f))))
  82. (assign mac (annotate 'mac
  83. (fn (name parms . body)
  84. ((fn ((doc . body))
  85. `(do (sref sig ',parms ',name)
  86. (sref help* ',doc ',name)
  87. (sref source-file* current-load-file* ',name)
  88. (sref source* '(mac ,name ,parms ,@body) ',name)
  89. (safeset ,name (annotate 'mac (fn ,parms ,@body)))))
  90. (docify-body body)))))
  91. (sref sig '(name parms . body) 'mac)
  92. (sref source-file* current-load-file* 'mac)
  93. (mac make-br-fn (body) `(fn (_) ,body))
  94. (mac and args
  95. (if args
  96. (if (cdr args)
  97. `(if ,(car args) (and ,@(cdr args)))
  98. (car args))
  99. 't))
  100. (def assoc (key al)
  101. (if (atom al)
  102. nil
  103. (and (acons (car al)) (is (caar al) key))
  104. (car al)
  105. (assoc key (cdr al))))
  106. (def alref (al key) (cadr (assoc key al)))
  107. (mac with (parms . body)
  108. `((fn ,(map1 car (pair parms))
  109. ,@body)
  110. ,@(map1 cadr (pair parms))))
  111. (mac let (var val . body)
  112. `(with (,var ,val) ,@body))
  113. (mac withs (parms . body)
  114. (if (no parms)
  115. `(do ,@body)
  116. `(let ,(car parms) ,(cadr parms)
  117. (withs ,(cddr parms) ,@body))))
  118. ; Rtm prefers to overload + to do this
  119. (def join args
  120. (if (no args)
  121. nil
  122. (let a (car args)
  123. (if (no a)
  124. (apply join (cdr args))
  125. (cons (car a) (apply join (cdr a) (cdr args)))))))
  126. ; Need rfn for use in macro expansions.
  127. (mac rfn (name parms . body)
  128. `(let ,name nil
  129. (assign ,name (fn ,parms ,@body))))
  130. (mac afn (parms . body)
  131. `(let self nil
  132. (assign self (fn ,parms ,@body))))
  133. ; Ac expands x:y:z into (compose x y z), ~x into (complement x)
  134. ; Only used when the call to compose doesn't occur in functional position.
  135. ; Composes in functional position are transformed away by ac.
  136. (mac compose args
  137. (let g (uniq)
  138. `(fn ,g
  139. ,((afn (fs)
  140. (if (cdr fs)
  141. (list (car fs) (self (cdr fs)))
  142. `(apply ,(if (car fs) (car fs) 'idfn) ,g)))
  143. args))))
  144. ; Ditto: complement in functional position optimized by ac.
  145. (mac complement (f)
  146. (let g (uniq)
  147. `(fn ,g (no (apply ,f ,g)))))
  148. (def rev (xs)
  149. ((afn (xs acc)
  150. (if (no xs)
  151. acc
  152. (self (cdr xs) (cons (car xs) acc))))
  153. xs nil))
  154. (def isnt (x y) (no (is x y)))
  155. (mac w/uniq (names . body)
  156. (if (acons names)
  157. `(with ,(apply + nil (map1 (fn (n) (list n '(uniq)))
  158. names))
  159. ,@body)
  160. `(let ,names (uniq) ,@body)))
  161. (mac or args
  162. (and args
  163. (w/uniq g
  164. `(let ,g ,(car args)
  165. (if ,g ,g (or ,@(cdr args)))))))
  166. (def alist (x) (or (no x) (is (type x) 'cons)))
  167. (mac in (x . choices)
  168. (w/uniq g
  169. `(let ,g ,x
  170. (or ,@(map1 (fn (c) `(is ,g ,c)) choices)))))
  171. ; bootstrapping version; overloaded later as a generic function
  172. (def iso (x y)
  173. (or (is x y)
  174. (and (acons x)
  175. (acons y)
  176. (iso (car x) (car y))
  177. (iso (cdr x) (cdr y)))))
  178. (mac when (test . body)
  179. `(if ,test (do ,@body)))
  180. (mac unless (test . body)
  181. `(if (no ,test) (do ,@body)))
  182. (mac while (test . body)
  183. (w/uniq (gf gp)
  184. `((rfn ,gf (,gp)
  185. (when ,gp ,@body (,gf ,test)))
  186. ,test)))
  187. (def empty (seq)
  188. (or (no seq)
  189. (and (or (is (type seq) 'string) (is (type seq) 'table))
  190. (is (len seq) 0))))
  191. (def reclist (f xs)
  192. (and xs (or (f xs) (reclist f (cdr xs)))))
  193. (def recstring (test s (o start 0))
  194. ((afn (i)
  195. (and (< i (len s))
  196. (or (test i)
  197. (self (+ i 1)))))
  198. start))
  199. (def testify (x)
  200. (if (isa x 'fn) x [is _ x]))
  201. ; Like keep, seems like some shouldn't testify. But find should,
  202. ; and all probably should.
  203. (def some (test seq)
  204. (let f (testify test)
  205. (if (alist seq)
  206. (reclist f:car seq)
  207. (recstring f:seq seq))))
  208. (def all (test seq)
  209. (~some (complement (testify test)) seq))
  210. (def mem (test seq)
  211. (let f (testify test)
  212. (reclist [if (f:car _) _] seq)))
  213. (def find (test seq)
  214. (let f (testify test)
  215. (if (alist seq)
  216. (reclist [if (f:car _) (car _)] seq)
  217. (recstring [if (f:seq _) (seq _)] seq))))
  218. (def isa (x y) (is (type x) y))
  219. ; Possible to write map without map1, but makes News 3x slower.
  220. ;(def map (f . seqs)
  221. ; (if (some1 no seqs)
  222. ; nil
  223. ; (no (cdr seqs))
  224. ; (let s1 (car seqs)
  225. ; (cons (f (car s1))
  226. ; (map f (cdr s1))))
  227. ; (cons (apply f (map car seqs))
  228. ; (apply map f (map cdr seqs)))))
  229. (def map (f . seqs)
  230. (if (some [isa _ 'string] seqs)
  231. (withs (n (apply min (map len seqs))
  232. new (newstring n))
  233. ((afn (i)
  234. (if (is i n)
  235. new
  236. (do (sref new (apply f (map [_ i] seqs)) i)
  237. (self (+ i 1)))))
  238. 0))
  239. (no (cdr seqs))
  240. (map1 f (car seqs))
  241. ((afn (seqs)
  242. (if (some no seqs)
  243. nil
  244. (cons (apply f (map1 car seqs))
  245. (self (map1 cdr seqs)))))
  246. seqs)))
  247. (def mappend (f . args)
  248. (apply + nil (apply map f args)))
  249. (def firstn (n xs)
  250. (if (no n) xs
  251. (and (> n 0) xs) (cons (car xs) (firstn (- n 1) (cdr xs)))
  252. nil))
  253. (def nthcdr (n xs)
  254. (if (no n) xs
  255. (> n 0) (nthcdr (- n 1) (cdr xs))
  256. xs))
  257. ; Generalization of pair: (tuples x) = (pair x)
  258. (def tuples (xs (o n 2))
  259. (if (no xs)
  260. nil
  261. (cons (firstn n xs)
  262. (tuples (nthcdr n xs) n))))
  263. ; If ok to do with =, why not with def? But see if use it.
  264. (mac defs args
  265. `(do ,@(map [cons 'def _] (tuples args 3))))
  266. (def caris (x val)
  267. (and (acons x) (is (car x) val)))
  268. (def warn (msg . args)
  269. (disp (+ "Warning: " msg ". "))
  270. (map [do (write _) (disp " ")] args)
  271. (disp #\newline))
  272. (mac atomic body
  273. `(atomic-invoke (fn () ,@body)))
  274. (mac atlet args
  275. `(atomic (let ,@args)))
  276. (mac atwith args
  277. `(atomic (with ,@args)))
  278. (mac atwiths args
  279. `(atomic (withs ,@args)))
  280. ; setforms returns (vars get set) for a place based on car of an expr
  281. ; vars is a list of gensyms alternating with expressions whose vals they
  282. ; should be bound to, suitable for use as first arg to withs
  283. ; get is an expression returning the current value in the place
  284. ; set is an expression representing a function of one argument
  285. ; that stores a new value in the place
  286. ; A bit gross that it works based on the *name* in the car, but maybe
  287. ; wrong to worry. Macros live in expression land.
  288. ; seems meaningful to e.g. (push 1 (pop x)) if (car x) is a cons.
  289. ; can't in cl though. could I define a setter for push or pop?
  290. (assign setter (table))
  291. (mac defset (name parms . body)
  292. (w/uniq gexpr
  293. `(sref setter
  294. (fn (,gexpr)
  295. (let ,parms (cdr ,gexpr)
  296. ,@body))
  297. ',name)))
  298. (defset car (x)
  299. (w/uniq g
  300. (list (list g x)
  301. `(car ,g)
  302. `(fn (val) (scar ,g val)))))
  303. (defset cdr (x)
  304. (w/uniq g
  305. (list (list g x)
  306. `(cdr ,g)
  307. `(fn (val) (scdr ,g val)))))
  308. (defset caar (x)
  309. (w/uniq g
  310. (list (list g x)
  311. `(caar ,g)
  312. `(fn (val) (scar (car ,g) val)))))
  313. (defset cadr (x)
  314. (w/uniq g
  315. (list (list g x)
  316. `(cadr ,g)
  317. `(fn (val) (scar (cdr ,g) val)))))
  318. (defset cddr (x)
  319. (w/uniq g
  320. (list (list g x)
  321. `(cddr ,g)
  322. `(fn (val) (scdr (cdr ,g) val)))))
  323. ; Note: if expr0 macroexpands into any expression whose car doesn't
  324. ; have a setter, setforms assumes it's a data structure in functional
  325. ; position. Such bugs will be seen only when the code is executed, when
  326. ; sref complains it can't set a reference to a function.
  327. (def setforms (expr0)
  328. (let expr (macex expr0)
  329. (if (isa expr 'sym)
  330. (if (ssyntax expr)
  331. (setforms (ssexpand expr))
  332. (w/uniq (g h)
  333. (list (list g expr)
  334. g
  335. `(fn (,h) (assign ,expr ,h)))))
  336. ; make it also work for uncompressed calls to compose
  337. (and (acons expr) (metafn (car expr)))
  338. (setforms (expand-metafn-call (ssexpand (car expr)) (cdr expr)))
  339. (and (acons expr) (acons (car expr)) (is (caar expr) 'get))
  340. (setforms (list (cadr expr) (cadr (car expr))))
  341. (let f (setter (car expr))
  342. (if f
  343. (f expr)
  344. ; assumed to be data structure in fn position
  345. (do (when (caris (car expr) 'fn)
  346. (warn "Inverting what looks like a function call"
  347. expr0 expr))
  348. (w/uniq (g h)
  349. (let argsyms (map [uniq] (cdr expr))
  350. (list (+ (list g (car expr))
  351. (mappend list argsyms (cdr expr)))
  352. `(,g ,@argsyms)
  353. `(fn (,h) (sref ,g ,h ,(car argsyms))))))))))))
  354. (def metafn (x)
  355. (or (ssyntax x)
  356. (and (acons x) (in (car x) 'compose 'complement))))
  357. (def expand-metafn-call (f args)
  358. (if (is (car f) 'compose)
  359. ((afn (fs)
  360. (if (caris (car fs) 'compose) ; nested compose
  361. (self (join (cdr (car fs)) (cdr fs)))
  362. (cdr fs)
  363. (list (car fs) (self (cdr fs)))
  364. (cons (car fs) args)))
  365. (cdr f))
  366. (is (car f) 'no)
  367. (err "Can't invert " (cons f args))
  368. (cons f args)))
  369. (def expand= (place val)
  370. (if (and (isa place 'sym) (~ssyntax place))
  371. `(assign ,place ,val)
  372. (let (vars prev setter) (setforms place)
  373. (w/uniq g
  374. `(atwith ,(+ vars (list g val))
  375. (,setter ,g))))))
  376. (def expand=list (terms)
  377. `(do ,@(map (fn ((p v)) (expand= p v)) ; [apply expand= _]
  378. (pair terms))))
  379. (mac = args
  380. (expand=list args))
  381. (mac loop (start test update . body)
  382. (w/uniq (gfn gparm)
  383. `(do ,start
  384. ((rfn ,gfn (,gparm)
  385. (if ,gparm
  386. (do ,@body ,update (,gfn ,test))))
  387. ,test))))
  388. (mac for (v init max . body)
  389. (w/uniq (gi gm)
  390. `(with (,v nil ,gi ,init ,gm (+ ,max 1))
  391. (loop (assign ,v ,gi) (< ,v ,gm) (assign ,v (+ ,v 1))
  392. ,@body))))
  393. (mac down (v init min . body)
  394. (w/uniq (gi gm)
  395. `(with (,v nil ,gi ,init ,gm (- ,min 1))
  396. (loop (assign ,v ,gi) (> ,v ,gm) (assign ,v (- ,v 1))
  397. ,@body))))
  398. (mac repeat (n . body)
  399. `(for ,(uniq) 1 ,n ,@body))
  400. ; could bind index instead of gensym
  401. (def walk (seq func)
  402. (if alist.seq
  403. ((afn (l)
  404. (when (acons l)
  405. (func (car l))
  406. (self (cdr l)))) seq)
  407. (isa seq 'table)
  408. (maptable (fn (k v) (func (list k v))) seq)
  409. ; else
  410. (for i 0 (- (len seq) 1)
  411. (func (seq i)))))
  412. (mac each (var expr . body)
  413. `(walk ,expr (fn (,var) ,@body)))
  414. ; ; old definition of 'each. possibly faster, but not extendable.
  415. ; (mac each (var expr . body)
  416. ; (w/uniq (gseq gf gv)
  417. ; `(let ,gseq ,expr
  418. ; (if (alist ,gseq)
  419. ; ((rfn ,gf (,gv)
  420. ; (when (acons ,gv)
  421. ; (let ,var (car ,gv) ,@body)
  422. ; (,gf (cdr ,gv))))
  423. ; ,gseq)
  424. ; (isa ,gseq 'table)
  425. ; (maptable (fn ,var ,@body)
  426. ; ,gseq)
  427. ; (for ,gv 0 (- (len ,gseq) 1)
  428. ; (let ,var (,gseq ,gv) ,@body))))))
  429. ; (nthcdr x y) = (cut y x).
  430. (def cut (seq start (o end))
  431. (let end (if (no end) (len seq)
  432. (< end 0) (+ (len seq) end)
  433. end)
  434. (if (isa seq 'string)
  435. (let s2 (newstring (- end start))
  436. (for i 0 (- end start 1)
  437. (= (s2 i) (seq (+ start i))))
  438. s2)
  439. (firstn (- end start) (nthcdr start seq)))))
  440. (mac whilet (var test . body)
  441. (w/uniq (gf gp)
  442. `((rfn ,gf (,gp)
  443. (let ,var ,gp
  444. (when ,var ,@body (,gf ,test))))
  445. ,test)))
  446. (def last (xs)
  447. (if (cdr xs)
  448. (last (cdr xs))
  449. (car xs)))
  450. (def rem (test seq)
  451. (let f (testify test)
  452. (if (alist seq)
  453. ((afn (s)
  454. (if (no s) nil
  455. (f (car s)) (self (cdr s))
  456. (cons (car s) (self (cdr s)))))
  457. seq)
  458. (coerce (rem test (coerce seq 'cons)) 'string))))
  459. ; Seems like keep doesn't need to testify-- would be better to
  460. ; be able to use tables as fns. But rem does need to, because
  461. ; often want to rem a table from a list. So maybe the right answer
  462. ; is to make keep the more primitive, not rem.
  463. (def keep (test seq)
  464. (rem (complement (testify test)) seq))
  465. ;(def trues (f seq)
  466. ; (rem nil (map f seq)))
  467. (def trues (f xs)
  468. (and xs
  469. (let fx (f (car xs))
  470. (if fx
  471. (cons fx (trues f (cdr xs)))
  472. (trues f (cdr xs))))))
  473. (mac do1 args
  474. (w/uniq g
  475. `(let ,g ,(car args)
  476. ,@(cdr args)
  477. ,g)))
  478. ; Would like to write a faster case based on table generated by a macro,
  479. ; but can't insert objects into expansions in Mzscheme.
  480. (mac caselet (var expr . args)
  481. (let ex (afn (args)
  482. (if (no (cdr args))
  483. (car args)
  484. `(if (is ,var ',(car args))
  485. ,(cadr args)
  486. ,(self (cddr args)))))
  487. `(let ,var ,expr ,(ex args))))
  488. (mac case (expr . args)
  489. `(caselet ,(uniq) ,expr ,@args))
  490. (mac push (x place)
  491. (w/uniq gx
  492. (let (binds val setter) (setforms place)
  493. `(let ,gx ,x
  494. (atwiths ,binds
  495. (,setter (cons ,gx ,val)))))))
  496. (mac swap (place1 place2)
  497. (w/uniq (g1 g2)
  498. (with ((binds1 val1 setter1) (setforms place1)
  499. (binds2 val2 setter2) (setforms place2))
  500. `(atwiths ,(+ binds1 (list g1 val1) binds2 (list g2 val2))
  501. (,setter1 ,g2)
  502. (,setter2 ,g1)))))
  503. (mac rotate places
  504. (with (vars (map [uniq] places)
  505. forms (map setforms places))
  506. `(atwiths ,(mappend (fn (g (binds val setter))
  507. (+ binds (list g val)))
  508. vars
  509. forms)
  510. ,@(map (fn (g (binds val setter))
  511. (list setter g))
  512. (+ (cdr vars) (list (car vars)))
  513. forms))))
  514. (mac pop (place)
  515. (w/uniq g
  516. (let (binds val setter) (setforms place)
  517. `(atwiths ,(+ binds (list g val))
  518. (do1 (car ,g)
  519. (,setter (cdr ,g)))))))
  520. (def adjoin (x xs (o test iso))
  521. (if (some [test x _] xs)
  522. xs
  523. (cons x xs)))
  524. (mac pushnew (x place . args)
  525. (w/uniq gx
  526. (let (binds val setter) (setforms place)
  527. `(atwiths ,(+ (list gx x) binds)
  528. (,setter (adjoin ,gx ,val ,@args))))))
  529. (mac pull (test place)
  530. (w/uniq g
  531. (let (binds val setter) (setforms place)
  532. `(atwiths ,(+ (list g test) binds)
  533. (,setter (rem ,g ,val))))))
  534. (mac togglemem (x place . args)
  535. (w/uniq gx
  536. (let (binds val setter) (setforms place)
  537. `(atwiths ,(+ (list gx x) binds)
  538. (,setter (if (mem ,gx ,val)
  539. (rem ,gx ,val)
  540. (adjoin ,gx ,val ,@args)))))))
  541. (mac ++ (place (o i 1))
  542. (if (isa place 'sym)
  543. `(= ,place (+ ,place ,i))
  544. (w/uniq gi
  545. (let (binds val setter) (setforms place)
  546. `(atwiths ,(+ binds (list gi i))
  547. (,setter (+ ,val ,gi)))))))
  548. (mac -- (place (o i 1))
  549. (if (isa place 'sym)
  550. `(= ,place (- ,place ,i))
  551. (w/uniq gi
  552. (let (binds val setter) (setforms place)
  553. `(atwiths ,(+ binds (list gi i))
  554. (,setter (- ,val ,gi)))))))
  555. ; E.g. (++ x) equiv to (zap + x 1)
  556. (mac zap (op place . args)
  557. (with (gop (uniq)
  558. gargs (map [uniq] args)
  559. mix (afn seqs
  560. (if (some no seqs)
  561. nil
  562. (+ (map car seqs)
  563. (apply self (map cdr seqs))))))
  564. (let (binds val setter) (setforms place)
  565. `(atwiths ,(+ binds (list gop op) (mix gargs args))
  566. (,setter (,gop ,val ,@gargs))))))
  567. ; Can't simply mod pr to print strings represented as lists of chars,
  568. ; because empty string will get printed as nil. Would need to rep strings
  569. ; as lists of chars annotated with 'string, and modify car and cdr to get
  570. ; the rep of these. That would also require hacking the reader.
  571. (def pr args
  572. (map1 disp args)
  573. (car args))
  574. (def prt args
  575. (map1 [if _ (disp _)] args)
  576. (car args))
  577. (def prn args
  578. (do1 (apply pr args)
  579. (pr #\newline))) ; writec doesn't implicitly flush
  580. (mac wipe args
  581. `(do ,@(map (fn (a) `(= ,a nil)) args)))
  582. (mac set args
  583. `(do ,@(map (fn (a) `(= ,a t)) args)))
  584. ; Destructuring means ambiguity: are pat vars bound in else? (no)
  585. (mac iflet (var expr then . rest)
  586. (w/uniq gv
  587. `(let ,gv ,expr
  588. (if ,gv (let ,var ,gv ,then) ,@rest))))
  589. (mac whenlet (var expr . body)
  590. `(iflet ,var ,expr (do ,@body)))
  591. (mac aif (expr . body)
  592. `(let it ,expr
  593. (if it
  594. ,@(if (cddr body)
  595. `(,(car body) (aif ,@(cdr body)))
  596. body))))
  597. (mac awhen (expr . body)
  598. `(let it ,expr (if it (do ,@body))))
  599. (mac aand args
  600. (if (no args)
  601. 't
  602. (no (cdr args))
  603. (car args)
  604. `(let it ,(car args) (and it (aand ,@(cdr args))))))
  605. (mac accum (accfn . body)
  606. (w/uniq gacc
  607. `(withs (,gacc nil ,accfn [push _ ,gacc])
  608. ,@body
  609. (rev ,gacc))))
  610. ; Repeatedly evaluates its body till it returns nil, then returns vals.
  611. (mac drain (expr (o eof nil))
  612. (w/uniq (gacc gdone gres)
  613. `(with (,gacc nil ,gdone nil)
  614. (while (no ,gdone)
  615. (let ,gres ,expr
  616. (if (is ,gres ,eof)
  617. (= ,gdone t)
  618. (push ,gres ,gacc))))
  619. (rev ,gacc))))
  620. ; For the common C idiom while x = snarfdata != stopval.
  621. ; Rename this if use it often.
  622. (mac whiler (var expr endval . body)
  623. (w/uniq gf
  624. `(withs (,var nil ,gf (testify ,endval))
  625. (while (no (,gf (= ,var ,expr)))
  626. ,@body))))
  627. ;(def macex (e)
  628. ; (if (atom e)
  629. ; e
  630. ; (let op (and (atom (car e)) (eval (car e)))
  631. ; (if (isa op 'mac)
  632. ; (apply (rep op) (cdr e))
  633. ; e))))
  634. (def consif (x y) (if x (cons x y) y))
  635. (def string args
  636. (apply + "" (map [coerce _ 'string] args)))
  637. (def flat x
  638. ((afn (x acc)
  639. (if (no x) acc
  640. (atom x) (cons x acc)
  641. (self (car x) (self (cdr x) acc))))
  642. x nil))
  643. (mac check (x test (o alt))
  644. (w/uniq gx
  645. `(let ,gx ,x
  646. (if (,test ,gx) ,gx ,alt))))
  647. (def pos (test seq (o start 0))
  648. (let f (testify test)
  649. (if (alist seq)
  650. ((afn (seq n)
  651. (if (no seq)
  652. nil
  653. (f (car seq))
  654. n
  655. (self (cdr seq) (+ n 1))))
  656. (nthcdr start seq)
  657. start)
  658. (recstring [if (f (seq _)) _] seq start))))
  659. (def even (n) (is (mod n 2) 0))
  660. (def odd (n) (no (even n)))
  661. (mac after (x . ys)
  662. `(protect (fn () ,x) (fn () ,@ys)))
  663. (let expander
  664. (fn (f var name body)
  665. `(let ,var (,f ,name)
  666. (after (do ,@body) (close ,var))))
  667. (mac w/infile (var name . body)
  668. (expander 'infile var name body))
  669. (mac w/outfile (var name . body)
  670. (expander 'outfile var name body))
  671. (mac w/instring (var str . body)
  672. (expander 'instring var str body))
  673. (mac w/socket (var port . body)
  674. (expander 'open-socket var port body))
  675. )
  676. (mac w/outstring (var . body)
  677. `(let ,var (outstring) ,@body))
  678. ; what happens to a file opened for append if arc is killed in
  679. ; the middle of a write?
  680. (mac w/appendfile (var name . body)
  681. `(let ,var (outfile ,name 'append)
  682. (after (do ,@body) (close ,var))))
  683. ; rename this simply "to"? - prob not; rarely use
  684. (mac w/stdout (str . body)
  685. `(call-w/stdout ,str (fn () ,@body)))
  686. (mac w/stdin (str . body)
  687. `(call-w/stdin ,str (fn () ,@body)))
  688. (mac tostring body
  689. (w/uniq gv
  690. `(w/outstring ,gv
  691. (w/stdout ,gv ,@body)
  692. (inside ,gv))))
  693. (mac fromstring (str . body)
  694. (w/uniq gv
  695. `(w/instring ,gv ,str
  696. (w/stdin ,gv ,@body))))
  697. (def readstring1 (s (o eof nil)) (w/instring i s (read i eof)))
  698. (def read ((o x (stdin)) (o eof nil))
  699. (if (isa x 'string) (readstring1 x eof) (sread x eof)))
  700. ; inconsistency between names of readfile[1] and writefile
  701. (def readfile (name) (w/infile s name (drain (read s))))
  702. (def readfile1 (name) (w/infile s name (read s)))
  703. (def readall (src (o eof nil))
  704. ((afn (i)
  705. (let x (read i eof)
  706. (if (is x eof)
  707. nil
  708. (cons x (self i)))))
  709. (if (isa src 'string) (instring src) src)))
  710. (def allchars (str)
  711. (tostring (whiler c (readc str nil) no
  712. (writec c))))
  713. (def filechars (name)
  714. (w/infile s name (allchars s)))
  715. (def writefile (val file)
  716. (let tmpfile (+ file ".tmp")
  717. (w/outfile o tmpfile (write val o))
  718. (mvfile tmpfile file))
  719. val)
  720. (= ac-denil ($ ac-denil))
  721. (= ac-global-name ($ ac-global-name))
  722. (= ac-niltree ($ ac-niltree))
  723. ; for when we can't use assign
  724. (mac ac-set-global (name val)
  725. (w/uniq (gname v)
  726. `(with (,gname (ac-global-name ,name)
  727. ,v ,val)
  728. ($ (namespace-set-variable-value! ,gname ,v))
  729. nil)))
  730. (= scheme-f (read "#f"))
  731. (= scheme-t (read "#t"))
  732. (= redef =)
  733. (= defined-variables* (table))
  734. (redef ac-defined-var?
  735. (fn (name)
  736. (if defined-variables*.name scheme-t scheme-f)))
  737. (mac defvar (name impl)
  738. `(do (ac-set-global ',name ,impl)
  739. (set (defined-variables* ',name))
  740. nil))
  741. (mac defvar-impl (name)
  742. (let gname (ac-global-name name)
  743. `($ ,gname)))
  744. (mac undefvar (name)
  745. `(do (wipe (defined-variables* ',name))
  746. (ac-set-global ',name nil)))
  747. (mac parameterize(var val . body)
  748. (w/uniq f
  749. `(let ,f (fn() ,@body)
  750. (parameterize-sub ,var ,val ,f))))
  751. (def thread-cell(var (o inherit))
  752. ($:make-thread-cell ,var ,(if inherit scheme-t scheme-f)))
  753. (mac thread-local(name val)
  754. (w/uniq storage
  755. `(defvar ,name
  756. (let ,storage (thread-cell ,val)
  757. (fn args
  758. (if args
  759. (ac-niltree:$:thread-cell-set! ,storage (car args))
  760. (ac-niltree:$:thread-cell-ref ,storage)))))))
  761. (def sym (x) (coerce x 'sym))
  762. (def int (x (o b 10)) (coerce x 'int b))
  763. (def stringify(sym)
  764. (coerce sym 'string))
  765. (def symize args
  766. (coerce (apply + args) 'sym))
  767. (def globalize l
  768. (symize l "*"))
  769. (mac rand-choice exprs
  770. `(case (rand ,(len exprs))
  771. ,@(let key -1
  772. (mappend [list (++ key) _]
  773. exprs))))
  774. (mac n-of (n expr)
  775. (w/uniq ga
  776. `(let ,ga nil
  777. (repeat ,n (push ,expr ,ga))
  778. (rev ,ga))))
  779. ; rejects bytes >= 248 lest digits be overrepresented
  780. (def rand-string (n)
  781. (let c "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  782. (with (nc 62 s (newstring n) i 0)
  783. (w/infile str "/dev/urandom"
  784. (while (< i n)
  785. (let x (readb str)
  786. (unless (> x 247)
  787. (= (s i) (c (mod x nc)))
  788. (++ i)))))
  789. s)))
  790. (mac forlen (var s . body)
  791. `(for ,var 0 (- (len ,s) 1) ,@body))
  792. (mac on (var s . body)
  793. (if (is var 'index)
  794. (err "Can't use index as first arg to on.")
  795. (w/uniq gs
  796. `(let ,gs ,s
  797. (forlen index ,gs
  798. (let ,var (,gs index)
  799. ,@body))))))
  800. (def best (f seq)
  801. (if (no seq)
  802. nil
  803. (let wins (car seq)
  804. (each elt (cdr seq)
  805. (if (f elt wins) (= wins elt)))
  806. wins)))
  807. (def max args (best > args))
  808. (def min args (best < args))
  809. ; (mac max2 (x y)
  810. ; (w/uniq (a b)
  811. ; `(with (,a ,x ,b ,y) (if (> ,a ,b) ,a ,b))))
  812. (def most (f seq)
  813. (unless (no seq)
  814. (withs (wins (car seq) topscore (f wins))
  815. (each elt (cdr seq)
  816. (let score (f elt)
  817. (if (> score topscore) (= wins elt topscore score))))
  818. wins)))
  819. ; Insert so that list remains sorted. Don't really want to expose
  820. ; these but seem to have to because can't include a fn obj in a
  821. ; macroexpansion.
  822. (def insert-sorted (test elt seq)
  823. (if (no seq)
  824. (list elt)
  825. (test elt (car seq))
  826. (cons elt seq)
  827. (cons (car seq) (insert-sorted test elt (cdr seq)))))
  828. (mac insort (test elt seq)
  829. `(zap [insert-sorted ,test ,elt _] ,seq))
  830. (def reinsert-sorted (test elt seq)
  831. (if (no seq)
  832. (list elt)
  833. (is elt (car seq))
  834. (reinsert-sorted test elt (cdr seq))
  835. (test elt (car seq))
  836. (cons elt (rem elt seq))
  837. (cons (car seq) (reinsert-sorted test elt (cdr seq)))))
  838. (mac insortnew (test elt seq)
  839. `(zap [reinsert-sorted ,test ,elt _] ,seq))
  840. ; Could make this look at the sig of f and return a fn that took the
  841. ; right no of args and didn't have to call apply (or list if 1 arg).
  842. (def memo (f)
  843. (with (cache (table) nilcache (table))
  844. (fn args
  845. (or (cache args)
  846. (and (no (nilcache args))
  847. (aif (apply f args)
  848. (= (cache args) it)
  849. (do (set (nilcache args))
  850. nil)))))))
  851. (mac defmemo (name parms . body)
  852. `(safeset ,name (memo (fn ,parms ,@body))))
  853. (def <= args
  854. (or (no args)
  855. (no (cdr args))
  856. (and (no (> (car args) (cadr args)))
  857. (apply <= (cdr args)))))
  858. (def >= args
  859. (or (no args)
  860. (no (cdr args))
  861. (and (no (< (car args) (cadr args)))
  862. (apply >= (cdr args)))))
  863. (def whitec (c)
  864. (in c #\space #\newline #\tab #\return))
  865. (def nonwhite (c) (no (whitec c)))
  866. (def letter (c) (or (<= #\a c #\z) (<= #\A c #\Z)))
  867. (def digit (c) (<= #\0 c #\9))
  868. (def alphadig (c) (or (letter c) (digit c)))
  869. (def punc (c)
  870. (in c #\. #\, #\; #\: #\! #\?))
  871. ; a version of readline that accepts both lf and crlf endings
  872. ; adapted from Andrew Wilcox's code (http://awwx.ws/readline) by Michael
  873. ; Arntzenius <daekharel@gmail.com>
  874. (def readline ((o str (stdin)))
  875. (awhen (readc str)
  876. (tostring
  877. ((afn (c)
  878. (if (is c #\return) (when (is peekc.str #\newline) readc.str)
  879. (is c #\newline) nil
  880. (do (writec c)
  881. (aif readc.str self.it))))
  882. it))))
  883. ; Don't currently use this but suspect some code could.
  884. (mac summing (sumfn . body)
  885. (w/uniq (gc gt)
  886. `(let ,gc 0
  887. (let ,sumfn (fn (,gt) (if ,gt (++ ,gc)))
  888. ,@body)
  889. ,gc)))
  890. (def sum (f xs)
  891. (let n 0
  892. (each x xs (++ n (f x)))
  893. n))
  894. (def treewise (f base tree)
  895. (if (atom tree)
  896. (base tree)
  897. (f (treewise f base (car tree))
  898. (treewise f base (cdr tree)))))
  899. (def carif (x) (if (atom x) x (car x)))
  900. ; Could prob be generalized beyond printing.
  901. (def prall (elts (o init "") (o sep ", "))
  902. (when elts
  903. (pr init (car elts))
  904. (map [pr sep _] (cdr elts))
  905. elts))
  906. (def prs args
  907. (prall args "" #\space))
  908. (def tree-subst (old new tree)
  909. (if (is tree old)
  910. new
  911. (atom tree)
  912. tree
  913. (cons (tree-subst old new (car tree))
  914. (tree-subst old new (cdr tree)))))
  915. (def ontree (f tree)
  916. (f tree)
  917. (unless (atom tree)
  918. (ontree f (car tree))
  919. (ontree f (cdr tree))))
  920. (def dotted (x)
  921. (if (atom x)
  922. nil
  923. (and (cdr x) (or (atom (cdr x))
  924. (dotted (cdr x))))))
  925. (def fill-table (table data)
  926. (each (k v) (pair data) (= (table k) v))
  927. table)
  928. (def keys (h)
  929. (accum a (each (k v) h (a k))))
  930. (def vals (h)
  931. (accum a (each (k v) h (a v))))
  932. ; These two should really be done by coerce. Wrap coerce?
  933. (def tablist (h)
  934. (accum a (maptable (fn args (a args)) h)))
  935. (def listtab (al)
  936. (let h (table)
  937. (map (fn ((k v)) (= (h k) v))
  938. al)
  939. h))
  940. (mac obj args
  941. `(listtab (list ,@(map (fn ((k v))
  942. `(list ',k ,v))
  943. (pair args)))))
  944. (def load-table (file (o eof))
  945. (w/infile i file (read-table i eof)))
  946. (def read-table ((o i (stdin)) (o eof))
  947. (let e (read i eof)
  948. (if (alist e) (listtab e) e)))
  949. (def load-tables (file)
  950. (w/infile i file
  951. (w/uniq eof
  952. (drain (read-table i eof) eof))))
  953. (def save-table (h file)
  954. (writefile (tablist h) file))
  955. (def write-table (h (o o (stdout)))
  956. (write (tablist h) o))
  957. (def copy (x . args)
  958. (let x2 (case (type x)
  959. sym x
  960. cons (copylist x) ; (apply (fn args args) x)
  961. string (let new (newstring (len x))
  962. (forlen i x
  963. (= (new i) (x i)))
  964. new)
  965. table (let new (table)
  966. (each (k v) x
  967. (= (new k) v))
  968. new)
  969. (err "Can't copy " x))
  970. (map (fn ((k v)) (= (x2 k) v))
  971. (pair args))
  972. x2))
  973. (def shr (n m)
  974. (shl n (- m)))
  975. (def abs (n)
  976. (if (< n 0) (- n) n))
  977. ; The problem with returning a list instead of multiple values is that
  978. ; you can't act as if the fn didn't return multiple vals in cases where
  979. ; you only want the first. Not a big problem.
  980. (def round (n)
  981. (withs (base (trunc n) rem (abs (- n base)))
  982. (if (> rem 1/2) ((if (> n 0) + -) base 1)
  983. (< rem 1/2) base
  984. (odd base) ((if (> n 0) + -) base 1)
  985. base)))
  986. (def roundup (n)
  987. (withs (base (trunc n) rem (abs (- n base)))
  988. (if (>= rem 1/2)
  989. ((if (> n 0) + -) base 1)
  990. base)))
  991. (def nearest (n quantum)
  992. (* (roundup (/ n quantum)) quantum))
  993. (def avg (ns) (/ (apply + ns) (len ns)))
  994. (def med (ns (o test >))
  995. ((sort test ns) (round (/ (len ns) 2))))
  996. ; Use mergesort on assumption that mostly sorting mostly sorted lists
  997. ; benchmark: (let td (n-of 10000 (rand 100)) (time (sort < td)) 1)
  998. (def sort (test seq)
  999. (if (alist seq)
  1000. (mergesort test (copy seq))
  1001. (coerce (mergesort test (coerce seq 'cons)) (type seq))))
  1002. ; Destructive stable merge-sort, adapted from slib and improved
  1003. ; by Eli Barzilay for MzLib; re-written in Arc.
  1004. (def mergesort (less? lst)
  1005. (with (n (len lst))
  1006. (if (<= n 1) lst
  1007. ; ; check if the list is already sorted
  1008. ; ; (which can be a common case, eg, directory lists).
  1009. ; (let loop ([last (car lst)] [next (cdr lst)])
  1010. ; (or (null? next)
  1011. ; (and (not (less? (car next) last))
  1012. ; (loop (car next) (cdr next)))))
  1013. ; lst
  1014. ((afn (n)
  1015. (if (> n 2)
  1016. ; needs to evaluate L->R
  1017. (withs (j (/ (if (even n) n (- n 1)) 2) ; faster than round
  1018. a (self j)
  1019. b (self (- n j)))
  1020. (merge less? a b))
  1021. ; the following case just inlines the length 2 case,
  1022. ; it can be removed (and use the above case for n>1)
  1023. ; and the code still works, except a little slower
  1024. (is n 2)
  1025. (with (x (car lst) y (cadr lst) p lst)
  1026. (= lst (cddr lst))
  1027. (when (less? y x) (scar p y) (scar (cdr p) x))
  1028. (scdr (cdr p) nil)
  1029. p)
  1030. (is n 1)
  1031. (with (p lst)
  1032. (= lst (cdr lst))
  1033. (scdr p nil)
  1034. p)
  1035. nil))
  1036. n))))
  1037. ; Also by Eli.
  1038. (def merge (less? x y)
  1039. (if (no x) y
  1040. (no y) x
  1041. (let lup nil
  1042. (assign lup
  1043. (fn (r x y r-x?) ; r-x? for optimization -- is r connected to x?
  1044. (if (less? (car y) (car x))
  1045. (do (if r-x? (scdr r y))
  1046. (if (cdr y) (lup y x (cdr y) nil) (scdr y x)))
  1047. ; (car x) <= (car y)
  1048. (do (if (no r-x?) (scdr r x))
  1049. (if (cdr x) (lup x (cdr x) y t) (scdr x y))))))
  1050. (if (less? (car y) (car x))
  1051. (do (if (cdr y) (lup y x (cdr y) nil) (scdr y x))
  1052. y)
  1053. ; (car x) <= (car y)
  1054. (do (if (cdr x) (lup x (cdr x) y t) (scdr x y))
  1055. x)))))
  1056. (def bestn (n f seq)
  1057. (firstn n (sort f seq)))
  1058. (def split (seq pos)
  1059. (list (cut seq 0 pos) (cut seq pos)))
  1060. (mac time (expr)
  1061. (w/uniq (t1 t2)
  1062. `(let ,t1 (msec)
  1063. (do1 ,expr
  1064. (let ,t2 (msec)
  1065. (prn "time: " (- ,t2 ,t1) " msec."))))))
  1066. (mac jtime (expr)
  1067. `(do1 'ok (time ,expr)))
  1068. (mac time10 (expr)
  1069. `(time (repeat 10 ,expr)))
  1070. (def union (f xs ys)
  1071. (+ xs (rem (fn (y) (some [f _ y] xs))
  1072. ys)))
  1073. (= templates* (table))
  1074. (mac deftem (tem . fields)
  1075. (withs (name (carif tem) includes (if (acons tem) (cdr tem)))
  1076. `(= (templates* ',name)
  1077. (+ (mappend templates* ',(rev includes))
  1078. (list ,@(map (fn ((k v)) `(list ',k (fn () ,v)))
  1079. (pair fields)))))))
  1080. (mac addtem (name . fields)
  1081. `(= (templates* ',name)
  1082. (union (fn (x y) (is (car x) (car y)))
  1083. (list ,@(map (fn ((k v)) `(list ',k (fn () ,v)))
  1084. (pair fields)))
  1085. (templates* ',name))))
  1086. (def inst (tem . args)
  1087. (let x (table)
  1088. (each (k v) (if (acons tem) tem (templates* tem))
  1089. (unless (no v) (= (x k) (v))))
  1090. (each (k v) (pair args)
  1091. (= (x k) v))
  1092. x))
  1093. ; To write something to be read by temread, (write (tablist x))
  1094. (def temread (tem (o str (stdin)))
  1095. (templatize tem (read str)))
  1096. ; Converts alist to inst; ugly; maybe should make this part of coerce.
  1097. ; Note: discards fields not defined by the template.
  1098. (def templatize (tem raw)
  1099. (with (x (inst tem) fields (if (acons tem) tem (templates* tem)))
  1100. (each (k v) raw
  1101. (when (assoc k fields)
  1102. (= (x k) v)))
  1103. x))
  1104. (def temload (tem file)
  1105. (w/infile i file (temread tem i)))
  1106. (def temloadall (tem file)
  1107. (map (fn (pairs) (templatize tem pairs))
  1108. (w/infile in file (readall in))))
  1109. (def number (n) (in (type n) 'int 'num))
  1110. (def since (t1) (- (seconds) t1))
  1111. (def minutes-since (t1) (/ (since t1) 60))
  1112. (def hours-since (t1) (/ (since t1) 3600))
  1113. (def days-since (t1) (/ (since t1) 86400))
  1114. ; could use a version for fns of 1 arg at least
  1115. (def cache (timef valf)
  1116. (with (cached nil gentime nil)
  1117. (fn ()
  1118. (unless (and cached (< (since gentime) (timef)))
  1119. (= cached (valf)
  1120. gentime (seconds)))
  1121. cached)))
  1122. (mac defcache (name lasts . body)
  1123. `(safeset ,name (cache (fn () ,lasts)
  1124. (fn () ,@body))))
  1125. (mac errsafe (expr)
  1126. `(on-err (fn (c) nil)
  1127. (fn () ,expr)))
  1128. (def saferead (arg) (errsafe:read arg))
  1129. (def safe-load-table (filename)
  1130. (or (errsafe:load-table filename)
  1131. (table)))
  1132. (def ensure-dir (path)
  1133. (unless (dir-exists path)
  1134. (system (string "mkdir -p " path))))
  1135. (def date ((o s (seconds)))
  1136. (rev (nthcdr 3 (timedate s))))
  1137. (def datestring ((o s (seconds)))
  1138. (let (y m d) (date s)
  1139. (string y "-" (if (< m 10) "0") m "-" (if (< d 10) "0") d)))
  1140. (def count (test x)
  1141. (with (n 0 testf (testify test))
  1142. (each elt x
  1143. (if (testf elt) (++ n)))
  1144. n))
  1145. (def ellipsize (str (o limit 80))
  1146. (if (<= (len str) limit)
  1147. str
  1148. (+ (cut str 0 limit) "...")))
  1149. (def rand-elt (seq)
  1150. (seq (rand (len seq))))
  1151. (mac until (test . body)
  1152. `(while (no ,test) ,@body))
  1153. (def before (x y seq (o i 0))
  1154. (with (xp (pos x seq i) yp (pos y seq i))
  1155. (and xp (or (no yp) (< xp yp)))))
  1156. (def orf fns
  1157. (fn args
  1158. ((afn (fs)
  1159. (and fs (or (apply (car fs) args) (self (cdr fs)))))
  1160. fns)))
  1161. (def andf fns
  1162. (fn args
  1163. ((afn (fs)
  1164. (if (no fs) t
  1165. (no (cdr fs)) (apply (car fs) args)
  1166. (and (apply (car fs) args) (self (cdr fs)))))
  1167. fns)))
  1168. (def atend (i s)
  1169. (> i (- (len s) 2)))
  1170. (def multiple (x y)
  1171. (is 0 (mod x y)))
  1172. (mac nor args `(no (or ,@args)))
  1173. (mac nand args `(no (and ,@args)))
  1174. ; Consider making the default sort fn take compare's two args (when do
  1175. ; you ever have to sort mere lists of numbers?) and rename current sort
  1176. ; as prim-sort or something.
  1177. ; Could simply modify e.g. > so that (> len) returned the same thing
  1178. ; as (compare > len).
  1179. (def compare (comparer scorer)
  1180. (fn (x y) (comparer (scorer x) (scorer y))))
  1181. ; Cleaner thus, but may only ever need in 2 arg case.
  1182. ;(def compare (comparer scorer)
  1183. ; (fn args (apply comparer map scorer args)))
  1184. ; (def only (f g . args) (aif (apply g args) (f it)))
  1185. (def only (f)
  1186. (fn args (if (car args) (apply f args))))
  1187. (mac conswhen (f x y)
  1188. (w/uniq (gf gx)
  1189. `(with (,gf ,f ,gx ,x)
  1190. (if (,gf ,gx) (cons ,gx ,y) ,y))))
  1191. ; Could combine with firstn if put f arg last, default to (fn (x) t).
  1192. (def retrieve (n f xs)
  1193. (if (no n) (keep f xs)
  1194. (or (<= n 0) (no xs)) nil
  1195. (f (car xs)) (cons (car xs) (retrieve (- n 1) f (cdr xs)))
  1196. (retrieve n f (cdr xs))))
  1197. (def dedup (xs)
  1198. (with (h (table) acc nil)
  1199. (each x xs
  1200. (unless (h x)
  1201. (push x acc)
  1202. (set (h x))))
  1203. (rev acc)))
  1204. (def single (x) (and (acons x) (no (cdr x))))
  1205. (def intersperse (x ys)
  1206. (and ys (cons (car ys)
  1207. (mappend [list x _] (cdr ys)))))
  1208. (def counts (seq (o c (table)))
  1209. (if (no seq)
  1210. c
  1211. (do (++ (c (car seq) 0))
  1212. (counts (cdr seq) c))))
  1213. (def tree-counts (tree (o c (table)))
  1214. (counts (flat tree) c))
  1215. (def commonest (seq)
  1216. (with (winner nil n 0)
  1217. (each (k v) (counts seq)
  1218. (when (> v n) (= winner k n v)))
  1219. (list winner n)))
  1220. (def reduce (f xs)
  1221. (if (cddr xs)
  1222. (reduce f (cons (f (car xs) (cadr xs)) (cddr xs)))
  1223. (apply f xs)))
  1224. (def rreduce (f xs)
  1225. (if (cddr xs)
  1226. (f (car xs) (rreduce f (cdr xs)))
  1227. (apply f xs)))
  1228. (let argsym (uniq)
  1229. (def parse-format (str)
  1230. (accum a
  1231. (with (chars nil i -1)
  1232. (w/instring s str
  1233. (whilet c (readc s)
  1234. (case c
  1235. #\# (do (a (coerce (rev chars) 'string))
  1236. (wipe chars)
  1237. (a (read s)))
  1238. #\~ (do (a (coerce (rev chars) 'string))
  1239. (wipe chars)
  1240. (readc s)
  1241. (a (list argsym (++ i))))
  1242. (push c chars))))
  1243. (when chars
  1244. (a (coerce (rev chars) 'string))))))
  1245. (mac prf (str . args)
  1246. `(let ,argsym (list ,@args)
  1247. (pr ,@(parse-format str))))
  1248. )
  1249. (wipe load-file-stack*)
  1250. (def load (file)
  1251. (push current-load-file* load-file-stack*)
  1252. (= current-load-file* file)
  1253. (after (w/infile f file
  1254. (w/uniq eof
  1255. (whiler e (read f eof) eof
  1256. (eval e))))
  1257. (= current-load-file* (pop load-file-stack*))))
  1258. (def positive (x)
  1259. (and (number x) (> x 0)))
  1260. (mac w/table (var . body)
  1261. `(let ,var (table) ,@body ,var))
  1262. (def ero args
  1263. (w/stdout (stderr)
  1264. (each a args
  1265. (write a)
  1266. (writec #\space))
  1267. (writec #\newline))
  1268. (car args))
  1269. (def queue () (list nil nil 0))
  1270. ; Despite call to atomic, once had some sign this wasn't thread-safe.
  1271. ; Keep an eye on it.
  1272. (def enq (obj q)
  1273. (atomic
  1274. (++ (q 2))
  1275. (if (no (car q))
  1276. (= (cadr q) (= (car q) (list obj)))
  1277. (= (cdr (cadr q)) (list obj)
  1278. (cadr q) (cdr (cadr q))))
  1279. (car q)))
  1280. (def deq (q)
  1281. (atomic (unless (is (q 2) 0) (-- (q 2)))
  1282. (pop (car q))))
  1283. ; Should redef len to do this, and make queues lists annotated queue.
  1284. (def qlen (q) (q 2))
  1285. (def qlist (q) (car q))
  1286. (def enq-limit (val q (o limit 1000))
  1287. (atomic
  1288. (unless (< (qlen q) limit)
  1289. (deq q))
  1290. (enq val q)))
  1291. (def median (ns)
  1292. ((sort > ns) (trunc (/ (len ns) 2))))
  1293. (mac noisy-each (n var val . body)
  1294. (w/uniq (gn gc)
  1295. `(with (,gn ,n ,gc 0)
  1296. (each ,var ,val
  1297. (when (multiple (++ ,gc) ,gn)
  1298. (pr ".")
  1299. (flushout)
  1300. )
  1301. ,@body)
  1302. (prn)
  1303. (flushout))))
  1304. (mac point (name . body)
  1305. (w/uniq (g p)
  1306. `(ccc (fn (,g)
  1307. (let ,name (fn ((o ,p)) (,g ,p))
  1308. ,@body)))))
  1309. (mac catch body
  1310. `(point throw ,@body))
  1311. (def downcase (x)
  1312. (let downc (fn (c)
  1313. (let n (coerce c 'int)
  1314. (if (or (< 64 n 91) (< 191 n 215) (< 215 n 223))
  1315. (coerce (+ n 32) 'char)
  1316. c)))
  1317. (case (type x)
  1318. string (map downc x)
  1319. char (downc x)
  1320. sym (if x (sym (map downc (coerce x 'string))))
  1321. (err "Can't downcase" x))))
  1322. (def upcase (x)
  1323. (let upc (fn (c)
  1324. (let n (coerce c 'int)
  1325. (if (or (< 96 n 123) (< 223 n 247) (< 247 n 255))
  1326. (coerce (- n 32) 'char)
  1327. c)))
  1328. (case (type x)
  1329. string (map upc x)
  1330. char (upc x)
  1331. ; it's arguable whether (upcase nil) should be nil or NIL, but pg has
  1332. ; chosen NIL, so in the name of compatibility:
  1333. sym (if x (sym (map upc (coerce x 'string))) 'NIL)
  1334. (err "Can't upcase" x))))
  1335. (def inc (x (o n 1))
  1336. (coerce (+ (coerce x 'int) n) (type x)))
  1337. (def range (start end)
  1338. (if (> start end)
  1339. nil
  1340. (cons start (range (inc start) end))))
  1341. (def mismatch (s1 s2)
  1342. (catch
  1343. (on c s1
  1344. (when (isnt c (s2 index))
  1345. (throw index)))))
  1346. (def memtable (ks)
  1347. (let h (table)
  1348. (each k ks (set (h k)))
  1349. h))
  1350. (= bar* " | ")
  1351. (mac w/bars body
  1352. (w/uniq (out needbars)
  1353. `(let ,needbars nil
  1354. (do ,@(map (fn (e)
  1355. `(let ,out (tostring ,e)
  1356. (unless (is ,out "")
  1357. (if ,needbars
  1358. (pr bar* ,out)
  1359. (do (set ,needbars)
  1360. (pr ,out))))))
  1361. body)))))
  1362. (def len< (x n) (< (len x) n))
  1363. (def len> (x n) (> (len x) n))
  1364. (mac thread body
  1365. `(new-thread (fn () ,@body)))
  1366. (def kill-thread(th)
  1367. (atomic ($:kill-thread th)))
  1368. (def break-thread(th)
  1369. (atomic ($:break-thread th)))
  1370. (def thread-send(thd v)
  1371. (ac-niltree:$:thread-send thd v))
  1372. (def thread-receive()
  1373. (ac-niltree:$:thread-receive))
  1374. (def thread-try-receive()
  1375. (ac-niltree:$:thread-try-receive))
  1376. (def thread-rewind-receive args
  1377. (ac-niltree:$:thread-rewind-receive (ac-denil ,args)))
  1378. (mac trav (x . fs)
  1379. (w/uniq g
  1380. `((afn (,g)
  1381. (when ,g
  1382. ,@(map [list _ g] fs)))
  1383. ,x)))
  1384. (mac or= (place expr)
  1385. (let (binds val setter) (setforms place)
  1386. `(atwiths ,binds
  1387. (or ,val (,setter ,expr)))))
  1388. (= vtables* (table))
  1389. (mac defgeneric(name args . body)
  1390. `(do
  1391. (or= (vtables* ',name) (table))
  1392. (def ,name allargs
  1393. (aif (aand (vtables* ',name) (it (type car.allargs)))
  1394. (apply it allargs)
  1395. (aif (pickles* (type car.allargs))
  1396. (apply ,name (map it allargs))
  1397. (let ,args allargs
  1398. ,@body))))))
  1399. (mac defmethod(name args type . body)
  1400. `(= ((vtables* ',name) ',type)
  1401. (fn ,args
  1402. ,@body)))
  1403. (= pickles* (table))
  1404. (mac pickle(type f)
  1405. `(= (pickles* ',type)
  1406. ,f))
  1407. ; Could take n args, but have never once needed that.
  1408. (defgeneric iso(x y)
  1409. (is x y))
  1410. (defmethod iso(x y) cons
  1411. (and (acons x)
  1412. (acons y)
  1413. (iso car.x car.y)
  1414. (iso cdr.x cdr.y)))
  1415. (defmethod iso(x y) table
  1416. (and (isa x 'table)
  1417. (isa y 'table)
  1418. (is (len keys.x) (len keys.y))
  1419. (all
  1420. (fn((k v))
  1421. (iso y.k v))
  1422. tablist.x)))
  1423. (= hooks* (table))
  1424. (def hook (name . args)
  1425. (aif (hooks* name) (apply it args)))
  1426. (mac defhook (name . rest)
  1427. `(= (hooks* ',name) (fn ,@rest)))
  1428. (mac out (expr) `(pr ,(tostring (eval expr))))
  1429. ; if renamed this would be more natural for (map [_ user] pagefns*)
  1430. (def get (index) [_ index])
  1431. (= savers* (table))
  1432. (mac fromdisk (var file init load save)
  1433. (w/uniq (gf gv)
  1434. `(unless (bound ',var)
  1435. (do1 (= ,var (iflet ,gf (file-exists ,file)
  1436. (,load ,gf)
  1437. ,init))
  1438. (= (savers* ',var) (fn (,gv) (,save ,gv ,file)))))))
  1439. (mac diskvar (var file)
  1440. `(fromdisk ,var ,file nil readfile1 writefile))
  1441. (mac disktable (var file)
  1442. `(fromdisk ,var ,file (table) load-table save-table))
  1443. (mac todisk (var (o expr var))
  1444. `((savers* ',var)
  1445. ,(if (is var expr) var `(= ,var ,expr))))
  1446. (mac evtil (expr test)
  1447. (w/uniq gv
  1448. `(let ,gv ,expr
  1449. (while (no (,test ,gv))
  1450. (= ,gv ,expr))
  1451. ,gv)))
  1452. (def rand-key (h)
  1453. (if (empty h)
  1454. nil
  1455. (let n (rand (len h))
  1456. (catch
  1457. (each (k v) h
  1458. (when (is (-- n) -1)
  1459. (throw k)))))))
  1460. (def ratio (test xs)
  1461. (if (empty xs)
  1462. 0
  1463. (/ (count test xs) (len xs))))
  1464. (mac ret (var val . body)
  1465. `(let ,var ,val ,@body ,var))
  1466. (def butlast (x)
  1467. (cut x 0 (- (len x) 1)))
  1468. (mac between (var expr within . body)
  1469. (w/uniq first
  1470. `(let ,first t
  1471. (each ,var ,expr
  1472. (if ,first
  1473. (wipe ,first)
  1474. ,within)
  1475. ,@body))))
  1476. (mac tofile (name . body)
  1477. (w/uniq str `(w/outfile ,str ,name (w/stdout ,str ,@body))))
  1478. (mac ontofile (name . body)
  1479. (w/uniq str `(w/appendfile ,str ,name (w/stdout ,str ,@body))))
  1480. (mac fromfile (name . body)
  1481. (w/uniq str `(w/infile ,str ,name (w/stdin ,str ,@body))))
  1482. (def cars (xs) (map car xs))
  1483. (def cdrs (xs) (map cdr xs))
  1484. (mac mapeach (var lst . body)
  1485. `(map (fn (,var) ,@body) ,lst))
  1486. (wipe current-load-file*)
  1487. (load "help/arc.arc")
  1488. ; any logical reason I can't say (push x (if foo y z)) ?
  1489. ; eval would have to always ret 2 things, the val and where it came from
  1490. ; idea: implicit tables of tables; setf empty field, becomes table
  1491. ; or should setf on a table just take n args?
  1492. ; idea: use constants in functional position for currying?
  1493. ; (1 foo) would mean (fn args (apply foo 1 args))
  1494. ; another solution would be to declare certain symbols curryable, and
  1495. ; if > was, >_10 would mean [> _ 10]
  1496. ; or just say what the hell and make _ ssyntax for currying
  1497. ; idea: make >10 ssyntax for [> _ 10]
  1498. ; solution to the "problem" of improper lists: allow any atom as a list
  1499. ; terminator, not just nil. means list recursion should terminate on
  1500. ; atom rather than nil, (def empty (x) (or (atom x) (is x "")))
  1501. ; table should be able to take an optional initial-value. handle in sref.
  1502. ; warn about code of form (if (= )) -- probably mean is
  1503. ; warn when a fn has a parm that's already defined as a macro.
  1504. ; (def foo (after) (after))
  1505. ; idea: a fn (nothing) that returns a special gensym which is ignored
  1506. ; by map, so can use map in cases when don't want all the vals
  1507. ; idea: anaph macro so instead of (aand x y) say (anaph and x y)
  1508. ; idea: foo.bar!baz as an abbrev for (foo bar 'baz)
  1509. ; or something a bit more semantic?
  1510. ; could uniq be (def uniq () (annotate 'symbol (list 'u))) again?
  1511. ; idea: use x- for (car x) and -x for (cdr x) (but what about math -?)
  1512. ; idea: get rid of strings and just use symbols
  1513. ; could a string be (#\a #\b . "") ?
  1514. ; better err msg when , outside of a bq
  1515. ; idea: parameter (p foo) means in body foo is (pair arg)
  1516. ; idea: make ('string x) equiv to (coerce x 'string) ? or isa?
  1517. ; quoted atoms in car valuable unused semantic space
  1518. ; idea: if (defun foo (x y) ...), make (foo 1) return (fn (y) (foo 1 y))
  1519. ; probably would lead to lots of errors when call with missing args
  1520. ; but would be really dense with . notation, (foo.1 2)
  1521. ; or use special ssyntax for currying: (foo@1 2)
  1522. ; remember, can also double; could use foo::bar to mean something
  1523. ; wild idea: inline defs for repetitive code
  1524. ; same args as fn you're in
  1525. ; variant of compose where first fn only applied to first arg?
  1526. ; (> (len x) y) means (>+len x y)
  1527. ; use ssyntax underscore for a var?
  1528. ; foo_bar means [foo _ bar]
  1529. ; what does foo:_:bar mean?
  1530. ; matchcase
  1531. ; idea: atable that binds it to table, assumes input is a list
  1532. ; crazy that finding the top 100 nos takes so long:
  1533. ; (let bb (n-of 1000 (rand 50)) (time10 (bestn 100 > bb)))
  1534. ; time: 2237 msec. -> now down to 850 msec