PageRenderTime 52ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/src/flisp/system.lsp

https://github.com/lcw/julia
Lisp | 1015 lines | 858 code | 122 blank | 35 comment | 1 complexity | 6a1ca944d1a4e263a5324d7688102884 MD5 | raw file
Possible License(s): MIT
  1. ; -*- scheme -*-
  2. ; femtoLisp standard library
  3. ; by Jeff Bezanson (C) 2009
  4. ; Distributed under the BSD License
  5. (define (void) #t) ; the unspecified value
  6. (define *builtins*
  7. (vector
  8. 0 0 0 0 0 0 0 0 0 0 0 0
  9. (lambda (x y) (eq? x y)) (lambda (x y) (eqv? x y))
  10. (lambda (x y) (equal? x y)) (lambda (x) (atom? x))
  11. (lambda (x) (not x)) (lambda (x) (null? x))
  12. (lambda (x) (boolean? x)) (lambda (x) (symbol? x))
  13. (lambda (x) (number? x)) (lambda (x) (bound? x))
  14. (lambda (x) (pair? x)) (lambda (x) (builtin? x))
  15. (lambda (x) (vector? x)) (lambda (x) (fixnum? x))
  16. (lambda (x) (function? x)) (lambda (x y) (cons x y))
  17. (lambda rest (apply list rest)) (lambda (x) (car x))
  18. (lambda (x) (cdr x)) (lambda (x y) (set-car! x y))
  19. (lambda (x y) (set-cdr! x y)) (lambda rest (apply apply rest))
  20. (lambda rest (apply + rest)) (lambda rest (apply - rest))
  21. (lambda rest (apply * rest)) (lambda rest (apply / rest))
  22. (lambda rest (apply div0 rest)) (lambda (x y) (= x y))
  23. (lambda (x y) (< x y)) (lambda (x y) (compare x y))
  24. (lambda rest (apply vector rest)) (lambda (x y) (aref x y))
  25. (lambda (x y z) (aset! x y z))))
  26. (if (not (bound? '*syntax-environment*))
  27. (define *syntax-environment* (table)))
  28. (define (set-syntax! s v) (put! *syntax-environment* s v))
  29. (define (symbol-syntax s) (get *syntax-environment* s #f))
  30. (define-macro (define-macro form . body)
  31. `(set-syntax! ',(car form)
  32. (lambda ,(cdr form) ,@body)))
  33. (define-macro (letrec binds . body)
  34. `((lambda ,(map car binds)
  35. ,.(map (lambda (b) `(set! ,@b)) binds)
  36. ,@body)
  37. ,.(map (lambda (x) (void)) binds)))
  38. (define-macro (let binds . body)
  39. (let ((lname #f))
  40. (if (symbol? binds)
  41. (begin (set! lname binds)
  42. (set! binds (car body))
  43. (set! body (cdr body))))
  44. (let ((thelambda
  45. `(lambda ,(map (lambda (c) (if (pair? c) (car c) c))
  46. binds)
  47. ,@body))
  48. (theargs
  49. (map (lambda (c) (if (pair? c) (cadr c) (void))) binds)))
  50. (cons (if lname
  51. `(letrec ((,lname ,thelambda)) ,lname)
  52. thelambda)
  53. theargs))))
  54. (define-macro (cond . clauses)
  55. (define (cond-clauses->if lst)
  56. (if (atom? lst)
  57. #f
  58. (let ((clause (car lst)))
  59. (if (or (eq? (car clause) 'else)
  60. (eq? (car clause) #t))
  61. (if (null? (cdr clause))
  62. (car clause)
  63. (cons 'begin (cdr clause)))
  64. (if (null? (cdr clause))
  65. ; test by itself
  66. (list 'or
  67. (car clause)
  68. (cond-clauses->if (cdr lst)))
  69. ; test => expression
  70. (if (eq? (cadr clause) '=>)
  71. (if (1arg-lambda? (caddr clause))
  72. ; test => (lambda (x) ...)
  73. (let ((var (caadr (caddr clause))))
  74. `(let ((,var ,(car clause)))
  75. (if ,var ,(cons 'begin (cddr (caddr clause)))
  76. ,(cond-clauses->if (cdr lst)))))
  77. ; test => proc
  78. (let ((b (gensym)))
  79. `(let ((,b ,(car clause)))
  80. (if ,b
  81. (,(caddr clause) ,b)
  82. ,(cond-clauses->if (cdr lst))))))
  83. (list 'if
  84. (car clause)
  85. (cons 'begin (cdr clause))
  86. (cond-clauses->if (cdr lst)))))))))
  87. (cond-clauses->if clauses))
  88. ; standard procedures ---------------------------------------------------------
  89. (define (member item lst)
  90. (cond ((atom? lst) #f)
  91. ((equal? (car lst) item) lst)
  92. (#t (member item (cdr lst)))))
  93. (define (memv item lst)
  94. (cond ((atom? lst) #f)
  95. ((eqv? (car lst) item) lst)
  96. (#t (memv item (cdr lst)))))
  97. (define (assoc item lst)
  98. (cond ((atom? lst) #f)
  99. ((equal? (caar lst) item) (car lst))
  100. (#t (assoc item (cdr lst)))))
  101. (define (assv item lst)
  102. (cond ((atom? lst) #f)
  103. ((eqv? (caar lst) item) (car lst))
  104. (#t (assv item (cdr lst)))))
  105. (define (> a b) (< b a))
  106. (define (<= a b) (or (< a b) (= a b)))
  107. (define (>= a b) (or (< b a) (= a b)))
  108. (define (negative? x) (< x 0))
  109. (define (zero? x) (= x 0))
  110. (define (positive? x) (> x 0))
  111. (define (even? x) (= (logand x 1) 0))
  112. (define (odd? x) (not (even? x)))
  113. (define (identity x) x)
  114. (define (1+ n) (+ n 1))
  115. (define (1- n) (- n 1))
  116. (define (mod0 x y) (- x (* (div0 x y) y)))
  117. (define (div x y) (+ (div0 x y)
  118. (or (and (< x 0)
  119. (or (and (< y 0) 1)
  120. -1))
  121. 0)))
  122. (define (mod x y) (- x (* (div x y) y)))
  123. (define (abs x) (if (< x 0) (- x) x))
  124. (define (max x0 . xs)
  125. (if (null? xs) x0
  126. (foldl (lambda (a b) (if (< a b) b a)) x0 xs)))
  127. (define (min x0 . xs)
  128. (if (null? xs) x0
  129. (foldl (lambda (a b) (if (< a b) a b)) x0 xs)))
  130. (define (char? x) (eq? (typeof x) 'wchar))
  131. (define (array? x) (or (vector? x)
  132. (let ((t (typeof x)))
  133. (and (pair? t) (eq? (car t) 'array)))))
  134. (define (closure? x) (and (function? x) (not (builtin? x))))
  135. (define (caar x) (car (car x)))
  136. (define (cadr x) (car (cdr x)))
  137. (define (cdar x) (cdr (car x)))
  138. (define (cddr x) (cdr (cdr x)))
  139. (define (caaar x) (car (car (car x))))
  140. (define (caadr x) (car (car (cdr x))))
  141. (define (cadar x) (car (cdr (car x))))
  142. (define (caddr x) (car (cdr (cdr x))))
  143. (define (cdaar x) (cdr (car (car x))))
  144. (define (cdadr x) (cdr (car (cdr x))))
  145. (define (cddar x) (cdr (cdr (car x))))
  146. (define (cdddr x) (cdr (cdr (cdr x))))
  147. (define (caaaar x) (car (car (car (car x)))))
  148. (define (caaadr x) (car (car (car (cdr x)))))
  149. (define (caadar x) (car (car (cdr (car x)))))
  150. (define (caaddr x) (car (car (cdr (cdr x)))))
  151. (define (cadaar x) (car (cdr (car (car x)))))
  152. (define (cadadr x) (car (cdr (car (cdr x)))))
  153. (define (caddar x) (car (cdr (cdr (car x)))))
  154. (define (cadddr x) (car (cdr (cdr (cdr x)))))
  155. (define (cdaaar x) (cdr (car (car (car x)))))
  156. (define (cdaadr x) (cdr (car (car (cdr x)))))
  157. (define (cdadar x) (cdr (car (cdr (car x)))))
  158. (define (cdaddr x) (cdr (car (cdr (cdr x)))))
  159. (define (cddaar x) (cdr (cdr (car (car x)))))
  160. (define (cddadr x) (cdr (cdr (car (cdr x)))))
  161. (define (cdddar x) (cdr (cdr (cdr (car x)))))
  162. (define (cddddr x) (cdr (cdr (cdr (cdr x)))))
  163. (let ((*values* (list '*values*)))
  164. (set! values
  165. (lambda vs
  166. (if (and (pair? vs) (null? (cdr vs)))
  167. (car vs)
  168. (cons *values* vs))))
  169. (set! call-with-values
  170. (lambda (producer consumer)
  171. (let ((res (producer)))
  172. (if (and (pair? res) (eq? *values* (car res)))
  173. (apply consumer (cdr res))
  174. (consumer res))))))
  175. ; list utilities --------------------------------------------------------------
  176. (define (every pred lst)
  177. (or (atom? lst)
  178. (and (pred (car lst))
  179. (every pred (cdr lst)))))
  180. (define (any pred lst)
  181. (and (pair? lst)
  182. (or (pred (car lst))
  183. (any pred (cdr lst)))))
  184. (define (list? a) (or (null? a) (and (pair? a) (list? (cdr a)))))
  185. (define (list-tail lst n)
  186. (if (<= n 0) lst
  187. (list-tail (cdr lst) (- n 1))))
  188. (define (list-head lst n)
  189. (if (<= n 0) ()
  190. (cons (car lst)
  191. (list-head (cdr lst) (- n 1)))))
  192. (define (list-ref lst n)
  193. (car (list-tail lst n)))
  194. ; bounded length test
  195. ; use this instead of (= (length lst) n), since it avoids unnecessary
  196. ; work and always terminates.
  197. (define (length= lst n)
  198. (cond ((< n 0) #f)
  199. ((= n 0) (atom? lst))
  200. ((atom? lst) (= n 0))
  201. (else (length= (cdr lst) (- n 1)))))
  202. (define (length> lst n)
  203. (cond ((< n 0) lst)
  204. ((= n 0) (and (pair? lst) lst))
  205. ((atom? lst) (< n 0))
  206. (else (length> (cdr lst) (- n 1)))))
  207. (define (last-pair l)
  208. (if (atom? (cdr l))
  209. l
  210. (last-pair (cdr l))))
  211. (define (lastcdr l)
  212. (if (atom? l)
  213. l
  214. (cdr (last-pair l))))
  215. (define (to-proper l)
  216. (cond ((null? l) l)
  217. ((atom? l) (list l))
  218. (else (cons (car l) (to-proper (cdr l))))))
  219. (define (map! f lst)
  220. (prog1 lst
  221. (while (pair? lst)
  222. (set-car! lst (f (car lst)))
  223. (set! lst (cdr lst)))))
  224. (define (filter pred lst)
  225. (define (filter- f lst acc)
  226. (cdr
  227. (prog1 acc
  228. (while (pair? lst)
  229. (begin (if (pred (car lst))
  230. (set! acc
  231. (cdr (set-cdr! acc (cons (car lst) ())))))
  232. (set! lst (cdr lst)))))))
  233. (filter- pred lst (list ())))
  234. (define (separate pred lst)
  235. (define (separate- pred lst yes no)
  236. (let ((vals
  237. (prog1
  238. (cons yes no)
  239. (while (pair? lst)
  240. (begin (if (pred (car lst))
  241. (set! yes
  242. (cdr (set-cdr! yes (cons (car lst) ()))))
  243. (set! no
  244. (cdr (set-cdr! no (cons (car lst) ())))))
  245. (set! lst (cdr lst)))))))
  246. (values (cdr (car vals)) (cdr (cdr vals)))))
  247. (separate- pred lst (list ()) (list ())))
  248. (define (count f l)
  249. (define (count- f l n)
  250. (if (null? l)
  251. n
  252. (count- f (cdr l) (if (f (car l))
  253. (+ n 1)
  254. n))))
  255. (count- f l 0))
  256. (define (foldr f zero lst)
  257. (if (null? lst) zero
  258. (f (car lst) (foldr f zero (cdr lst)))))
  259. (define (foldl f zero lst)
  260. (if (null? lst) zero
  261. (foldl f (f (car lst) zero) (cdr lst))))
  262. (define (reverse- zero lst)
  263. (if (null? lst) zero
  264. (reverse- (cons (car lst) zero) (cdr lst))))
  265. (define (reverse lst) (reverse- () lst))
  266. (define (reverse!- prev l)
  267. (while (pair? l)
  268. (set! l (prog1 (cdr l)
  269. (set-cdr! l (prog1 prev
  270. (set! prev l))))))
  271. prev)
  272. (define (reverse! l) (reverse!- () l))
  273. (define (delete-duplicates lst)
  274. (if (atom? lst)
  275. lst
  276. (let ((elt (car lst))
  277. (tail (cdr lst)))
  278. (if (member elt tail)
  279. (delete-duplicates tail)
  280. (cons elt
  281. (delete-duplicates tail))))))
  282. ; backquote -------------------------------------------------------------------
  283. (define (revappend l1 l2) (reverse- l2 l1))
  284. (define (nreconc l1 l2) (reverse!- l2 l1))
  285. (define (self-evaluating? x)
  286. (or (and (atom? x)
  287. (not (symbol? x)))
  288. (and (constant? x)
  289. (symbol? x)
  290. (eq x (top-level-value x)))))
  291. (define-macro (quasiquote x) (bq-process x))
  292. (define (bq-process x)
  293. (define (splice-form? x)
  294. (or (and (pair? x) (or (eq? (car x) 'unquote-splicing)
  295. (eq? (car x) 'unquote-nsplicing)))
  296. (eq? x 'unquote)))
  297. ; bracket without splicing
  298. (define (bq-bracket1 x)
  299. (if (and (pair? x) (eq? (car x) 'unquote))
  300. (cadr x)
  301. (bq-process x)))
  302. (cond ((self-evaluating? x)
  303. (if (vector? x)
  304. (let ((body (bq-process (vector->list x))))
  305. (if (eq? (car body) 'list)
  306. (cons vector (cdr body))
  307. (list apply vector body)))
  308. x))
  309. ((atom? x) (list 'quote x))
  310. ((eq? (car x) 'quasiquote) (bq-process (bq-process (cadr x))))
  311. ((eq? (car x) 'unquote) (cadr x))
  312. ((not (any splice-form? x))
  313. (let ((lc (lastcdr x))
  314. (forms (map bq-bracket1 x)))
  315. (if (null? lc)
  316. (cons 'list forms)
  317. (if (null? (cdr forms))
  318. (list cons (car forms) (bq-process lc))
  319. (nconc (cons 'list* forms) (list (bq-process lc)))))))
  320. (#t (let ((p x) (q ()))
  321. (while (and (pair? p)
  322. (not (eq? (car p) 'unquote)))
  323. (set! q (cons (bq-bracket (car p)) q))
  324. (set! p (cdr p)))
  325. (let ((forms
  326. (cond ((pair? p) (nreconc q (list (cadr p))))
  327. ((null? p) (reverse! q))
  328. (#t (nreconc q (list (bq-process p)))))))
  329. (if (null? (cdr forms))
  330. (car forms)
  331. (if (and (length= forms 2)
  332. (length= (car forms) 2)
  333. (eq? list (caar forms)))
  334. (list cons (cadar forms) (cadr forms))
  335. (cons 'nconc forms))))))))
  336. (define (bq-bracket x)
  337. (cond ((atom? x) (list list (bq-process x)))
  338. ((eq? (car x) 'unquote) (list list (cadr x)))
  339. ((eq? (car x) 'unquote-splicing) (list 'copy-list (cadr x)))
  340. ((eq? (car x) 'unquote-nsplicing) (cadr x))
  341. (#t (list list (bq-process x)))))
  342. ; standard macros -------------------------------------------------------------
  343. (define (quote-value v)
  344. (if (self-evaluating? v)
  345. v
  346. (list 'quote v)))
  347. (define-macro (let* binds . body)
  348. (if (atom? binds) `((lambda () ,@body))
  349. `((lambda (,(caar binds))
  350. ,@(if (pair? (cdr binds))
  351. `((let* ,(cdr binds) ,@body))
  352. body))
  353. ,(cadar binds))))
  354. (define-macro (when c . body) (list 'if c (cons 'begin body) #f))
  355. (define-macro (unless c . body) (list 'if c #f (cons 'begin body)))
  356. (define-macro (case key . clauses)
  357. (define (vals->cond key v)
  358. (cond ((eq? v 'else) 'else)
  359. ((null? v) #f)
  360. ((symbol? v) `(eq? ,key ,(quote-value v)))
  361. ((atom? v) `(eqv? ,key ,(quote-value v)))
  362. ((null? (cdr v)) `(eqv? ,key ,(quote-value (car v))))
  363. ((every symbol? v)
  364. `(memq ,key ',v))
  365. (else `(memv ,key ',v))))
  366. (let ((g (gensym)))
  367. `(let ((,g ,key))
  368. (cond ,.(map (lambda (clause)
  369. (cons (vals->cond g (car clause))
  370. (cdr clause)))
  371. clauses)))))
  372. (define-macro (do vars test-spec . commands)
  373. (let ((loop (gensym))
  374. (test-expr (car test-spec))
  375. (vars (map car vars))
  376. (inits (map cadr vars))
  377. (steps (map (lambda (x)
  378. (if (pair? (cddr x))
  379. (caddr x)
  380. (car x)))
  381. vars)))
  382. `(letrec ((,loop (lambda ,vars
  383. (if ,test-expr
  384. (begin
  385. ,@(cdr test-spec))
  386. (begin
  387. ,@commands
  388. (,loop ,.steps))))))
  389. (,loop ,.inits))))
  390. ; SRFI 8
  391. (define-macro (receive formals expr . body)
  392. `(call-with-values (lambda () ,expr)
  393. (lambda ,formals ,@body)))
  394. (define-macro (dotimes var . body)
  395. (let ((v (car var))
  396. (cnt (cadr var)))
  397. `(for 0 (- ,cnt 1)
  398. (lambda (,v) ,@body))))
  399. (define (map-int f n)
  400. (if (<= n 0)
  401. ()
  402. (let ((first (cons (f 0) ()))
  403. (acc ()))
  404. (set! acc first)
  405. (for 1 (- n 1)
  406. (lambda (i)
  407. (begin (set-cdr! acc (cons (f i) ()))
  408. (set! acc (cdr acc)))))
  409. first)))
  410. (define (iota n) (map-int identity n))
  411. (define (for-each f l . lsts)
  412. (define (for-each-n f lsts)
  413. (if (pair? (car lsts))
  414. (begin (apply f (map car lsts))
  415. (for-each-n f (map cdr lsts)))))
  416. (if (null? lsts)
  417. (while (pair? l)
  418. (begin (f (car l))
  419. (set! l (cdr l))))
  420. (for-each-n f (cons l lsts)))
  421. #t)
  422. (define-macro (with-bindings binds . body)
  423. (let ((vars (map car binds))
  424. (vals (map cadr binds))
  425. (olds (map (lambda (x) (gensym)) binds)))
  426. `(let ,(map list olds vars)
  427. ,@(map (lambda (v val) `(set! ,v ,val)) vars vals)
  428. (unwind-protect
  429. (begin ,@body)
  430. (begin ,@(map (lambda (v old) `(set! ,v ,old)) vars olds))))))
  431. ; exceptions ------------------------------------------------------------------
  432. (define (error . args) (raise (cons 'error args)))
  433. (define-macro (throw tag value) `(raise (list 'thrown-value ,tag ,value)))
  434. (define-macro (catch tag expr)
  435. (let ((e (gensym)))
  436. `(trycatch ,expr
  437. (lambda (,e) (if (and (pair? ,e)
  438. (eq (car ,e) 'thrown-value)
  439. (eq (cadr ,e) ,tag))
  440. (caddr ,e)
  441. (raise ,e))))))
  442. (define-macro (unwind-protect expr finally)
  443. (let ((e (gensym))
  444. (thk (gensym)))
  445. `(let ((,thk (lambda () ,finally)))
  446. (prog1 (trycatch ,expr
  447. (lambda (,e) (begin (,thk) (raise ,e))))
  448. (,thk)))))
  449. ; debugging utilities ---------------------------------------------------------
  450. (define-macro (assert expr) `(if ,expr #t (raise '(assert-failed ,expr))))
  451. #;(define traced?
  452. (letrec ((sample-traced-lambda (lambda args (begin (write (cons 'x args))
  453. (newline)
  454. (apply #.apply args)))))
  455. (lambda (f)
  456. (and (closure? f)
  457. (equal? (function:code f)
  458. (function:code sample-traced-lambda))))))
  459. #;(define (trace sym)
  460. (let* ((func (top-level-value sym))
  461. (args (gensym)))
  462. (if (not (traced? func))
  463. (set-top-level-value! sym
  464. (eval
  465. `(lambda ,args
  466. (begin (write (cons ',sym ,args))
  467. (newline)
  468. (apply ',func ,args)))))))
  469. 'ok)
  470. #;(define (untrace sym)
  471. (let ((func (top-level-value sym)))
  472. (if (traced? func)
  473. (set-top-level-value! sym
  474. (aref (function:vals func) 2)))))
  475. (define-macro (time expr)
  476. (let ((t0 (gensym)))
  477. `(let ((,t0 (time.now)))
  478. (prog1
  479. ,expr
  480. (princ "Elapsed time: " (- (time.now) ,t0) " seconds\n")))))
  481. ; text I/O --------------------------------------------------------------------
  482. (define (print . args) (for-each write args))
  483. (define (princ . args)
  484. (with-bindings ((*print-readably* #f))
  485. (for-each write args)))
  486. (define (newline (port *output-stream*))
  487. (io.write port *linefeed*)
  488. #t)
  489. (define (io.readline s) (io.readuntil s #\linefeed))
  490. ; call f on a stream until the stream runs out of data
  491. (define (read-all-of f s)
  492. (let loop ((lines ())
  493. (curr (f s)))
  494. (if (io.eof? s)
  495. (reverse! lines)
  496. (loop (cons curr lines) (f s)))))
  497. (define (io.readlines s) (read-all-of io.readline s))
  498. (define (read-all s) (read-all-of read s))
  499. (define (io.readall s)
  500. (let ((b (buffer)))
  501. (io.copy b s)
  502. (let ((str (io.tostring! b)))
  503. (if (and (equal? str "") (io.eof? s))
  504. (eof-object)
  505. str))))
  506. (define-macro (with-output-to stream . body)
  507. `(with-bindings ((*output-stream* ,stream))
  508. ,@body))
  509. (define-macro (with-input-from stream . body)
  510. `(with-bindings ((*input-stream* ,stream))
  511. ,@body))
  512. ; vector functions ------------------------------------------------------------
  513. (define (list->vector l) (apply vector l))
  514. (define (vector->list v)
  515. (let ((n (length v))
  516. (l ()))
  517. (for 1 n
  518. (lambda (i)
  519. (set! l (cons (aref v (- n i)) l))))
  520. l))
  521. (define (vector.map f v)
  522. (let* ((n (length v))
  523. (nv (vector.alloc n)))
  524. (for 0 (- n 1)
  525. (lambda (i)
  526. (aset! nv i (f (aref v i)))))
  527. nv))
  528. ; table functions -------------------------------------------------------------
  529. (define (table.pairs t)
  530. (table.foldl (lambda (k v z) (cons (cons k v) z))
  531. () t))
  532. (define (table.keys t)
  533. (table.foldl (lambda (k v z) (cons k z))
  534. () t))
  535. (define (table.values t)
  536. (table.foldl (lambda (k v z) (cons v z))
  537. () t))
  538. #;(define (table.clone t)
  539. (let ((nt (table)))
  540. (table.foldl (lambda (k v z) (put! nt k v))
  541. () t)
  542. nt))
  543. #;(define (table.invert t)
  544. (let ((nt (table)))
  545. (table.foldl (lambda (k v z) (put! nt v k))
  546. () t)
  547. nt))
  548. (define (table.foreach f t)
  549. (table.foldl (lambda (k v z) (begin (f k v) #t)) () t))
  550. ; string functions ------------------------------------------------------------
  551. (define (string.tail s n) (string.sub s (string.inc s 0 n)))
  552. (define *whitespace*
  553. (string.encode #array(wchar 9 10 11 12 13 32 133 160 5760 6158 8192
  554. 8193 8194 8195 8196 8197 8198 8199 8200
  555. 8201 8202 8232 8233 8239 8287 12288)))
  556. (define (string.trim s at-start at-end)
  557. (define (trim-start s chars i L)
  558. (if (and (< i L)
  559. (string.find chars (string.char s i)))
  560. (trim-start s chars (string.inc s i) L)
  561. i))
  562. (define (trim-end s chars i)
  563. (if (and (> i 0)
  564. (string.find chars (string.char s (string.dec s i))))
  565. (trim-end s chars (string.dec s i))
  566. i))
  567. (let ((L (length s)))
  568. (string.sub s
  569. (trim-start s at-start 0 L)
  570. (trim-end s at-end L))))
  571. (define (string.map f s)
  572. (let ((b (buffer))
  573. (n (length s)))
  574. (let ((i 0))
  575. (while (< i n)
  576. (begin (io.putc b (f (string.char s i)))
  577. (set! i (string.inc s i)))))
  578. (io.tostring! b)))
  579. (define (string.rep s k)
  580. (cond ((< k 4)
  581. (cond ((<= k 0) "")
  582. ((= k 1) (string s))
  583. ((= k 2) (string s s))
  584. (else (string s s s))))
  585. ((odd? k) (string s (string.rep s (- k 1))))
  586. (else (string.rep (string s s) (/ k 2)))))
  587. (define (string.lpad s n c) (string (string.rep c (- n (string.count s))) s))
  588. (define (string.rpad s n c) (string s (string.rep c (- n (string.count s)))))
  589. (define (print-to-string v)
  590. (let ((b (buffer)))
  591. (write v b)
  592. (io.tostring! b)))
  593. (define (string.join strlist sep)
  594. (if (null? strlist) ""
  595. (let ((b (buffer)))
  596. (io.write b (car strlist))
  597. (for-each (lambda (s) (begin (io.write b sep)
  598. (io.write b s)))
  599. (cdr strlist))
  600. (io.tostring! b))))
  601. ; toplevel --------------------------------------------------------------------
  602. (define (macrocall? e) (and (symbol? (car e))
  603. (symbol-syntax (car e))))
  604. (define (macroexpand-1 e)
  605. (if (atom? e) e
  606. (let ((f (macrocall? e)))
  607. (if f (apply f (cdr e))
  608. e))))
  609. (define (expand e)
  610. ; symbol resolves to toplevel; i.e. has no shadowing definition
  611. (define (top? s env) (not (or (bound? s) (assq s env))))
  612. (define (splice-begin body)
  613. (cond ((atom? body) body)
  614. ((equal? body '((begin)))
  615. body)
  616. ((and (pair? (car body))
  617. (eq? (caar body) 'begin))
  618. (append (splice-begin (cdar body)) (splice-begin (cdr body))))
  619. (else
  620. (cons (car body) (splice-begin (cdr body))))))
  621. (define *expanded* (list '*expanded*))
  622. (define (expand-body body env)
  623. (if (atom? body) body
  624. (let* ((body (if (top? 'begin env)
  625. (splice-begin body)
  626. body))
  627. (def? (top? 'define env))
  628. (dvars (if def? (get-defined-vars body) ()))
  629. (env (nconc (map list dvars) env)))
  630. (if (not def?)
  631. (map (lambda (x) (expand-in x env)) body)
  632. (let* ((ex-nondefs ; expand non-definitions
  633. (let loop ((body body))
  634. (cond ((atom? body) body)
  635. ((and (pair? (car body))
  636. (eq? 'define (caar body)))
  637. (cons (car body) (loop (cdr body))))
  638. (else
  639. (let ((form (expand-in (car body) env)))
  640. (set! env (nconc
  641. (map list (get-defined-vars form))
  642. env))
  643. (cons
  644. (cons *expanded* form)
  645. (loop (cdr body))))))))
  646. (body ex-nondefs))
  647. (while (pair? body) ; now expand deferred definitions
  648. (if (not (eq? *expanded* (caar body)))
  649. (set-car! body (expand-in (car body) env))
  650. (set-car! body (cdar body)))
  651. (set! body (cdr body)))
  652. ex-nondefs)))))
  653. (define (expand-lambda-list l env)
  654. (if (atom? l) l
  655. (cons (if (and (pair? (car l)) (pair? (cdr (car l))))
  656. (list (caar l) (expand-in (cadar l) env))
  657. (car l))
  658. (expand-lambda-list (cdr l) env))))
  659. (define (l-vars l)
  660. (cond ((atom? l) (list l))
  661. ((pair? (car l)) (cons (caar l) (l-vars (cdr l))))
  662. (else (cons (car l) (l-vars (cdr l))))))
  663. (define (expand-lambda e env)
  664. (let ((formals (cadr e))
  665. (name (lastcdr e))
  666. (body (cddr e))
  667. (vars (l-vars (cadr e))))
  668. (let ((env (nconc (map list vars) env)))
  669. `(lambda ,(expand-lambda-list formals env)
  670. ,.(expand-body body env)
  671. . ,name))))
  672. (define (expand-define e env)
  673. (if (or (null? (cdr e)) (atom? (cadr e)))
  674. (if (null? (cddr e))
  675. e
  676. `(define ,(cadr e) ,(expand-in (caddr e) env)))
  677. (let ((formals (cdadr e))
  678. (name (caadr e))
  679. (body (cddr e))
  680. (vars (l-vars (cdadr e))))
  681. (let ((env (nconc (map list vars) env)))
  682. `(define ,(cons name (expand-lambda-list formals env))
  683. ,.(expand-body body env))))))
  684. (define (expand-let-syntax e env)
  685. (let ((binds (cadr e)))
  686. (cons 'begin
  687. (expand-body (cddr e)
  688. (nconc
  689. (map (lambda (bind)
  690. (list (car bind)
  691. ((compile-thunk
  692. (expand-in (cadr bind) env)))
  693. env))
  694. binds)
  695. env)))))
  696. ; given let-syntax definition environment (menv) and environment
  697. ; at the point of the macro use (lenv), return the environment to
  698. ; expand the macro use in. TODO
  699. (define (local-expansion-env menv lenv) menv)
  700. (define (expand-in e env)
  701. (if (atom? e) e
  702. (let* ((head (car e))
  703. (bnd (assq head env))
  704. (default (lambda ()
  705. (let loop ((e e))
  706. (if (atom? e) e
  707. (cons (if (atom? (car e))
  708. (car e)
  709. (expand-in (car e) env))
  710. (loop (cdr e))))))))
  711. (cond ((and bnd (pair? (cdr bnd))) ; local macro
  712. (expand-in (apply (cadr bnd) (cdr e))
  713. (local-expansion-env (caddr bnd) env)))
  714. ((or bnd ; bound lexical or toplevel var
  715. (not (symbol? head))
  716. (bound? head))
  717. (default))
  718. ((macrocall? e) => (lambda (f)
  719. (expand-in (apply f (cdr e)) env)))
  720. ((eq? head 'quote) e)
  721. ((eq? head 'lambda) (expand-lambda e env))
  722. ((eq? head 'define) (expand-define e env))
  723. ((eq? head 'let-syntax) (expand-let-syntax e env))
  724. (else (default))))))
  725. (expand-in e ()))
  726. (define (eval x) ((compile-thunk (expand x))))
  727. (define (load-process x) (eval x))
  728. (define (load filename)
  729. (let ((F (file filename :read)))
  730. (trycatch
  731. (let next (prev E v)
  732. (if (not (io.eof? F))
  733. (next (read F)
  734. prev
  735. (load-process E))
  736. (begin (io.close F)
  737. ; evaluate last form in almost-tail position
  738. (load-process E))))
  739. (lambda (e)
  740. (begin
  741. (io.close F)
  742. (raise `(load-error ,filename ,e)))))))
  743. (define *banner* (string.tail "
  744. ; _
  745. ; |_ _ _ |_ _ | . _ _
  746. ; | (-||||_(_)|__|_)|_)
  747. ;-------------------|----------------------------------------------------------
  748. " 1))
  749. (define (repl)
  750. (define (prompt)
  751. (princ "> ") (io.flush *output-stream*)
  752. (let ((v (trycatch (read)
  753. (lambda (e) (begin (io.discardbuffer *input-stream*)
  754. (raise e))))))
  755. (and (not (io.eof? *input-stream*))
  756. (let ((V (load-process v)))
  757. (print V)
  758. (set! that V)
  759. #t))))
  760. (define (reploop)
  761. (when (trycatch (and (prompt) (newline))
  762. (lambda (e)
  763. (top-level-exception-handler e)
  764. #t))
  765. (begin (newline)
  766. (reploop))))
  767. (reploop)
  768. (newline))
  769. (define (top-level-exception-handler e)
  770. (with-output-to *stderr*
  771. (print-exception e)
  772. (print-stack-trace (stacktrace))))
  773. (define (print-stack-trace st)
  774. (define (find-in-f f tgt path)
  775. (let ((path (cons (function:name f) path)))
  776. (if (eq? (function:code f) (function:code tgt))
  777. (throw 'ffound path)
  778. (let ((v (function:vals f)))
  779. (for 0 (1- (length v))
  780. (lambda (i) (if (closure? (aref v i))
  781. (find-in-f (aref v i) tgt path))))))))
  782. (define (fn-name f e)
  783. (let ((p (catch 'ffound
  784. (begin
  785. (for-each (lambda (topfun)
  786. (find-in-f topfun f ()))
  787. e)
  788. #f))))
  789. (if p
  790. (symbol (string.join (map string (reverse! p)) "/"))
  791. 'lambda)))
  792. (let ((st (reverse! (list-tail st (if *interactive* 5 4))))
  793. (e (filter closure? (map (lambda (s) (and (bound? s)
  794. (top-level-value s)))
  795. (environment))))
  796. (n 0))
  797. (for-each
  798. (lambda (f)
  799. (princ "#" n " ")
  800. (print (cons (fn-name (aref f 0) e)
  801. (cdr (vector->list f))))
  802. (newline)
  803. (set! n (+ n 1)))
  804. st)))
  805. (define (print-exception e)
  806. (cond ((and (pair? e)
  807. (eq? (car e) 'type-error)
  808. (length= e 4))
  809. (princ "type error: " (cadr e) ": expected " (caddr e) ", got ")
  810. (print (cadddr e)))
  811. ((and (pair? e)
  812. (eq? (car e) 'bounds-error)
  813. (length= e 4))
  814. (princ (cadr e) ": index " (cadddr e) " out of bounds for ")
  815. (print (caddr e)))
  816. ((and (pair? e)
  817. (eq? (car e) 'unbound-error)
  818. (pair? (cdr e)))
  819. (princ "eval: variable " (cadr e) " has no value"))
  820. ((and (pair? e)
  821. (eq? (car e) 'error))
  822. (princ "error: ")
  823. (apply princ (cdr e)))
  824. ((and (pair? e)
  825. (eq? (car e) 'load-error))
  826. (print-exception (caddr e))
  827. (princ "in file " (cadr e)))
  828. ((and (list? e)
  829. (length= e 2))
  830. (print (car e))
  831. (princ ": ")
  832. (let ((msg (cadr e)))
  833. ((if (or (string? msg) (symbol? msg))
  834. princ print)
  835. msg)))
  836. (else (princ "*** Unhandled exception: ")
  837. (print e)))
  838. (princ *linefeed*))
  839. (define (simple-sort l)
  840. (if (or (null? l) (null? (cdr l))) l
  841. (let ((piv (car l)))
  842. (receive (less grtr)
  843. (separate (lambda (x) (< x piv)) (cdr l))
  844. (nconc (simple-sort less)
  845. (list piv)
  846. (simple-sort grtr))))))
  847. (define (make-system-image fname)
  848. (let ((f (file fname :write :create :truncate))
  849. (excludes '(*linefeed* *directory-separator* *argv* that
  850. *print-pretty* *print-width* *print-readably*
  851. *print-level* *print-length* *os-name*)))
  852. (with-bindings ((*print-pretty* #t)
  853. (*print-readably* #t))
  854. (let ((syms
  855. (filter (lambda (s)
  856. (and (bound? s)
  857. (not (constant? s))
  858. (or (not (builtin? (top-level-value s)))
  859. (not (equal? (string s) ; alias of builtin
  860. (string (top-level-value s)))))
  861. (not (memq s excludes))
  862. (not (iostream? (top-level-value s)))))
  863. (simple-sort (environment)))))
  864. (write (apply nconc (map list syms (map top-level-value syms))) f)
  865. (io.write f *linefeed*))
  866. (io.close f))))
  867. ; initialize globals that need to be set at load time
  868. (define (__init_globals)
  869. (if (or (eq? *os-name* 'win32)
  870. (eq? *os-name* 'win64)
  871. (eq? *os-name* 'windows))
  872. (begin (set! *directory-separator* "\\")
  873. (set! *linefeed* "\r\n"))
  874. (begin (set! *directory-separator* "/")
  875. (set! *linefeed* "\n")))
  876. (set! *output-stream* *stdout*)
  877. (set! *input-stream* *stdin*)
  878. (set! *error-stream* *stderr*))
  879. (define (__script fname)
  880. (trycatch (load fname)
  881. (lambda (e) (begin (top-level-exception-handler e)
  882. (exit 1)))))
  883. (define (__start argv)
  884. (__init_globals)
  885. (if (pair? (cdr argv))
  886. (begin (set! *argv* (cdr argv))
  887. (set! *interactive* #f)
  888. (__script (cadr argv)))
  889. (begin (set! *argv* argv)
  890. (set! *interactive* #t)
  891. (princ *banner*)
  892. (repl)))
  893. (exit 0))