├── .gitignore ├── .replit ├── README.md ├── deps.edn ├── reference ├── guide.txt ├── repl-demo.gif └── source.bel ├── resources ├── bel.ebnf └── core.bel ├── src └── bel_clojure │ ├── core.clj │ ├── evaluator.clj │ ├── model.clj │ └── reader.clj └── test └── bel_clojure ├── core_test.clj ├── evaluator_test.clj ├── model_test.clj └── reader_test.clj /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .lsp 3 | .cpcache 4 | .nrepl-port 5 | .clj-kondo 6 | .DS_Store -------------------------------------------------------------------------------- /.replit: -------------------------------------------------------------------------------- 1 | language = "bash" 2 | run = "clj -m bel-clojure.core" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bel-clojure: super-alpha 2 | 3 |

4 | 5 |

6 | 7 | This is my hack to run PG’s Bel in Clojure. Want to try it out? 8 | 9 | First, Make sure you have [Clojure](https://clojure.org/guides/getting_started#_clojure_installer_and_cli_tools) installed. After that: 10 | 11 | ```bash 12 | clj -X:repl 13 | ``` 14 | 15 | ## Tests 16 | 17 | ``` 18 | clj -X:test 19 | ``` 20 | 21 | ## Some Examples 22 | 23 | This is PG's `examples`, recreated on this interpreter. You can note what's implemented, and the slight differences. 24 | 25 | ```clojure 26 | > 27 | (cons 'a 'b '(c d e)) 28 | > (a b c d e) 29 | (cons \h "ello") 30 | > (h e l l o) 31 | (2 '(a b c)) 32 | > b 33 | (set w '(a (b c) d (e f))) 34 | > nil 35 | (find pair w) 36 | > (b c) 37 | (pop (find pair w)) 38 | > b 39 | w 40 | > (a (c) d (e f)) 41 | (dedup:sort < "abracadabra") 42 | > (a b c d r) 43 | (map (upon 2 3) (list + - * /)) 44 | > (5 -1 6 2/3) 45 | (let x 'a 46 | (cons x 'b)) 47 | > (a . b) 48 | (with (x 1 y 2) 49 | (+ x y)) 50 | > 3 51 | (let ((x y) . z) '((a b) c) 52 | (list x y z)) 53 | > (a b (c)) 54 | ((fn (x) (cons x 'b)) 'a) 55 | > (a . b) 56 | ((fn (x|symbol) (cons x 'b)) 'a) 57 | > (a . b) 58 | ((fn (x|int) (cons x 'b)) 'a) 59 | > (err (quote mistype)) 60 | ((fn (f x|f) (cons x 'b)) sym 'a) 61 | > (a . b) 62 | ((macro (v) `(set ,v 7)) x) 63 | > nil 64 | x 65 | > 7 66 | (apply or '(t nil)) 67 | > t 68 | (best (of > len) '((a b) (a b c d) (a) (a b c))) 69 | > (a b c d) 70 | (do (thread (do (join 'a 'b))) 71 | (thread (do (join 'a 'b) (join 'b 'd)))) 72 | > (b . d) 73 | (do (thread (do (join 'a 'b))) 74 | (thread 75 | (atomic (do (join 'a 'b) (join 'b 'd))))) 76 | > (a . b) 77 | ``` 78 | 79 | ## Notes 80 | 81 | To make the interpreter tolerably fast, **I tweaked the source in a few ways** 82 | 83 | 1. I represent the environment as a map, rather than a list 84 | 2. I leaked java’s numbers, strings, and characters into Bel 85 | 3. I moved some logic out of the source and into the interpreter 86 | 87 | This isn't done yet. **There's a few big todos remaining** 88 | 89 | 1. Streams. I didn’t implement streams yet. I think the best plan would be to leak Java streams, and I wanted to think about it. 90 | 2. Performance tuning. I made some tweaks, but there's a lot of low-hanging fruit still. 91 | 92 | This has been a lot of fun to write. I hope it’s as fun for you to play with it. 93 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {:paths ["src" "resources"] 2 | :deps {org.clojure/clojure {:mvn/version "1.10.3"} 3 | instaparse/instaparse {:mvn/version "1.4.10"}} 4 | :aliases {:repl {:main-opts ["-m" "bel-clojure.core"] 5 | :exec-fn bel-clojure.core/-main} 6 | :test {:extra-deps {io.github.cognitect-labs/test-runner 7 | {:git/url "https://github.com/cognitect-labs/test-runner.git" 8 | :sha "9e35c979860c75555adaff7600070c60004a0f44"}} 9 | :main-opts ["-m" "cognitect.test-runner"] 10 | :exec-fn cognitect.test-runner.api/test 11 | :extra-paths ["test"]} 12 | 13 | :nREPL 14 | {:extra-paths ["test"] 15 | :extra-deps 16 | {nrepl/nrepl {:mvn/version "0.8.3"}}}}} 17 | -------------------------------------------------------------------------------- /reference/repl-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stopachka/bel-clojure/2e5ab2e90bb3489de96a16e8cf31c86db6cb03b6/reference/repl-demo.gif -------------------------------------------------------------------------------- /reference/source.bel: -------------------------------------------------------------------------------- 1 | ; Bel in Bel. 9 October 2019, 9:14 GMT 2 | 3 | 4 | (def no (x) 5 | (id x nil)) 6 | 7 | (def atom (x) 8 | (no (id (type x) 'pair))) 9 | 10 | (def all (f xs) 11 | (if (no xs) t 12 | (f (car xs)) (all f (cdr xs)) 13 | nil)) 14 | 15 | (def some (f xs) 16 | (if (no xs) nil 17 | (f (car xs)) xs 18 | (some f (cdr xs)))) 19 | 20 | (def reduce (f xs) 21 | (if (no (cdr xs)) 22 | (car xs) 23 | (f (car xs) (reduce f (cdr xs))))) 24 | 25 | (def cons args 26 | (reduce join args)) 27 | 28 | (def append args 29 | (if (no (cdr args)) (car args) 30 | (no (car args)) (apply append (cdr args)) 31 | (cons (car (car args)) 32 | (apply append (cdr (car args)) 33 | (cdr args))))) 34 | 35 | (def snoc args 36 | (append (car args) (cdr args))) 37 | 38 | (def list args 39 | (append args nil)) 40 | 41 | (def map (f . ls) 42 | (if (no ls) nil 43 | (some no ls) nil 44 | (no (cdr ls)) (cons (f (car (car ls))) 45 | (map f (cdr (car ls)))) 46 | (cons (apply f (map car ls)) 47 | (apply map f (map cdr ls))))) 48 | 49 | (mac fn (parms . body) 50 | (if (no (cdr body)) 51 | `(list 'lit 'clo scope ',parms ',(car body)) 52 | `(list 'lit 'clo scope ',parms '(do ,@body)))) 53 | 54 | (set vmark (join)) 55 | 56 | (def uvar () 57 | (list vmark)) 58 | 59 | (mac do args 60 | (reduce (fn (x y) 61 | (list (list 'fn (uvar) y) x)) 62 | args)) 63 | 64 | (mac let (parms val . body) 65 | `((fn (,parms) ,@body) ,val)) 66 | 67 | (mac macro args 68 | `(list 'lit 'mac (fn ,@args))) 69 | 70 | (mac def (n . rest) 71 | `(set ,n (fn ,@rest))) 72 | 73 | (mac mac (n . rest) 74 | `(set ,n (macro ,@rest))) 75 | 76 | (mac or args 77 | (if (no args) 78 | nil 79 | (let v (uvar) 80 | `(let ,v ,(car args) 81 | (if ,v ,v (or ,@(cdr args))))))) 82 | 83 | (mac and args 84 | (reduce (fn es (cons 'if es)) 85 | (or args '(t)))) 86 | 87 | (def = args 88 | (if (no (cdr args)) t 89 | (some atom args) (all [id _ (car args)] (cdr args)) 90 | (and (apply = (map car args)) 91 | (apply = (map cdr args))))) 92 | 93 | (def symbol (x) (= (type x) 'symbol)) 94 | 95 | (def pair (x) (= (type x) 'pair)) 96 | 97 | (def char (x) (= (type x) 'char)) 98 | 99 | (def stream (x) (= (type x) 'stream)) 100 | 101 | (def proper (x) 102 | (or (no x) 103 | (and (pair x) (proper (cdr x))))) 104 | 105 | (def string (x) 106 | (and (proper x) (all char x))) 107 | 108 | (def mem (x ys (o f =)) 109 | (some [f _ x] ys)) 110 | 111 | (def in (x . ys) 112 | (mem x ys)) 113 | 114 | (def cadr (x) (car (cdr x))) 115 | 116 | (def cddr (x) (cdr (cdr x))) 117 | 118 | (def caddr (x) (car (cddr x))) 119 | 120 | (mac case (expr . args) 121 | (if (no (cdr args)) 122 | (car args) 123 | (let v (uvar) 124 | `(let ,v ,expr 125 | (if (= ,v ',(car args)) 126 | ,(cadr args) 127 | (case ,v ,@(cddr args))))))) 128 | 129 | (mac iflet (var . args) 130 | (if (no (cdr args)) 131 | (car args) 132 | (let v (uvar) 133 | `(let ,v ,(car args) 134 | (if ,v 135 | (let ,var ,v ,(cadr args)) 136 | (iflet ,var ,@(cddr args))))))) 137 | 138 | (mac aif args 139 | `(iflet it ,@args)) 140 | 141 | (def find (f xs) 142 | (aif (some f xs) (car it))) 143 | 144 | (def begins (xs pat (o f =)) 145 | (if (no pat) t 146 | (atom xs) nil 147 | (f (car xs) (car pat)) (begins (cdr xs) (cdr pat) f) 148 | nil)) 149 | 150 | (def caris (x y (o f =)) 151 | (begins x (list y) f)) 152 | 153 | (def hug (xs (o f list)) 154 | (if (no xs) nil 155 | (no (cdr xs)) (list (f (car xs))) 156 | (cons (f (car xs) (cadr xs)) 157 | (hug (cddr xs) f)))) 158 | 159 | (mac with (parms . body) 160 | (let ps (hug parms) 161 | `((fn ,(map car ps) ,@body) 162 | ,@(map cadr ps)))) 163 | 164 | (def keep (f xs) 165 | (if (no xs) nil 166 | (f (car xs)) (cons (car xs) (keep f (cdr xs))) 167 | (keep f (cdr xs)))) 168 | 169 | (def rem (x ys (o f =)) 170 | (keep [no (f _ x)] ys)) 171 | 172 | (def get (k kvs (o f =)) 173 | (find [f (car _) k] kvs)) 174 | 175 | (def put (k v kvs (o f =)) 176 | (cons (cons k v) 177 | (rem k kvs (fn (x y) (f (car x) y))))) 178 | 179 | (def rev (xs) 180 | (if (no xs) 181 | nil 182 | (snoc (rev (cdr xs)) (car xs)))) 183 | 184 | (def snap (xs ys (o acc)) 185 | (if (no xs) 186 | (list acc ys) 187 | (snap (cdr xs) (cdr ys) (snoc acc (car ys))))) 188 | 189 | (def udrop (xs ys) 190 | (cadr (snap xs ys))) 191 | 192 | (def idfn (x) 193 | x) 194 | 195 | (def is (x) 196 | [= _ x]) 197 | 198 | (mac eif (var (o expr) (o fail) (o ok)) 199 | (with (v (uvar) 200 | w (uvar) 201 | c (uvar)) 202 | `(let ,v (join) 203 | (let ,w (ccc (fn (,c) 204 | (dyn err [,c (cons ,v _)] ,expr))) 205 | (if (caris ,w ,v id) 206 | (let ,var (cdr ,w) ,fail) 207 | (let ,var ,w ,ok)))))) 208 | 209 | (mac onerr (e1 e2) 210 | (let v (uvar) 211 | `(eif ,v ,e2 ,e1 ,v))) 212 | 213 | (mac safe (expr) 214 | `(onerr nil ,expr)) 215 | 216 | (def literal (e) 217 | (or (in e t nil o apply) 218 | (in (type e) 'char 'stream) 219 | (caris e 'lit) 220 | (string e))) 221 | 222 | (def variable (e) 223 | (if (atom e) 224 | (no (literal e)) 225 | (id (car e) vmark))) 226 | 227 | (def isa (name) 228 | [begins _ `(lit ,name) id]) 229 | 230 | (def bel (e (o g globe)) 231 | (ev (list (list e nil)) 232 | nil 233 | (list nil g))) 234 | 235 | (def mev (s r (p g)) 236 | (if (no s) 237 | (if p 238 | (sched p g) 239 | (car r)) 240 | (sched (if (cdr (binding 'lock s)) 241 | (cons (list s r) p) 242 | (snoc p (list s r))) 243 | g))) 244 | 245 | (def sched (((s r) . p) g) 246 | (ev s r (list p g))) 247 | 248 | (def ev (((e a) . s) r m) 249 | (aif (literal e) (mev s (cons e r) m) 250 | (variable e) (vref e a s r m) 251 | (no (proper e)) (sigerr 'malformed s r m) 252 | (get (car e) forms id) ((cdr it) (cdr e) a s r m) 253 | (evcall e a s r m))) 254 | 255 | (def vref (v a s r m) 256 | (let g (cadr m) 257 | (if (inwhere s) 258 | (aif (or (lookup v a s g) 259 | (and (car (inwhere s)) 260 | (let cell (cons v nil) 261 | (xdr g (cons cell (cdr g))) 262 | cell))) 263 | (mev (cdr s) (cons (list it 'd) r) m) 264 | (sigerr 'unbound s r m)) 265 | (aif (lookup v a s g) 266 | (mev s (cons (cdr it) r) m) 267 | (sigerr (list 'unboundb v) s r m))))) 268 | 269 | (set smark (join)) 270 | 271 | (def inwhere (s) 272 | (let e (car (car s)) 273 | (and (begins e (list smark 'loc)) 274 | (cddr e)))) 275 | 276 | (def lookup (e a s g) 277 | (or (binding e s) 278 | (get e a id) 279 | (get e g id) 280 | (case e 281 | scope (cons e a) 282 | globe (cons e g)))) 283 | 284 | (def binding (v s) 285 | (get v 286 | (map caddr (keep [begins _ (list smark 'bind) id] 287 | (map car s))) 288 | id)) 289 | 290 | (def sigerr (msg s r m) 291 | (aif (binding 'err s) 292 | (applyf (cdr it) (list msg) nil s r m) 293 | (err 'no-err))) 294 | 295 | (mac fu args 296 | `(list (list smark 'fut (fn ,@args)) nil)) 297 | 298 | (def evmark (e a s r m) 299 | (case (car e) 300 | fut ((cadr e) s r m) 301 | bind (mev s r m) 302 | loc (sigerr 'unfindable s r m) 303 | prot (mev (cons (list (cadr e) a) 304 | (fu (s r m) (mev s (cdr r) m)) 305 | s) 306 | r 307 | m) 308 | (sigerr 'unknown-mark s r m))) 309 | 310 | (set forms (list (cons smark evmark))) 311 | 312 | (mac form (name parms . body) 313 | `(set forms (put ',name ,(formfn parms body) forms))) 314 | 315 | (def formfn (parms body) 316 | (with (v (uvar) 317 | w (uvar) 318 | ps (parameters (car parms))) 319 | `(fn ,v 320 | (eif ,w (apply (fn ,(car parms) (list ,@ps)) 321 | (car ,v)) 322 | (apply sigerr 'bad-form (cddr ,v)) 323 | (let ,ps ,w 324 | (let ,(cdr parms) (cdr ,v) ,@body)))))) 325 | 326 | (def parameters (p) 327 | (if (no p) nil 328 | (variable p) (list p) 329 | (atom p) (err 'bad-parm) 330 | (in (car p) t o) (parameters (cadr p)) 331 | (append (parameters (car p)) 332 | (parameters (cdr p))))) 333 | 334 | (form quote ((e) a s r m) 335 | (mev s (cons e r) m)) 336 | 337 | (form if (es a s r m) 338 | (if (no es) 339 | (mev s (cons nil r) m) 340 | (mev (cons (list (car es) a) 341 | (if (cdr es) 342 | (cons (fu (s r m) 343 | (if2 (cdr es) a s r m)) 344 | s) 345 | s)) 346 | r 347 | m))) 348 | 349 | (def if2 (es a s r m) 350 | (mev (cons (list (if (car r) 351 | (car es) 352 | (cons 'if (cdr es))) 353 | a) 354 | s) 355 | (cdr r) 356 | m)) 357 | 358 | (form where ((e (o new)) a s r m) 359 | (mev (cons (list e a) 360 | (list (list smark 'loc new) nil) 361 | s) 362 | r 363 | m)) 364 | 365 | (form dyn ((v e1 e2) a s r m) 366 | (if (variable v) 367 | (mev (cons (list e1 a) 368 | (fu (s r m) (dyn2 v e2 a s r m)) 369 | s) 370 | r 371 | m) 372 | (sigerr 'cannot-bind s r m))) 373 | 374 | (def dyn2 (v e2 a s r m) 375 | (mev (cons (list e2 a) 376 | (list (list smark 'bind (cons v (car r))) 377 | nil) 378 | s) 379 | (cdr r) 380 | m)) 381 | 382 | (form after ((e1 e2) a s r m) 383 | (mev (cons (list e1 a) 384 | (list (list smark 'prot e2) a) 385 | s) 386 | r 387 | m)) 388 | 389 | (form ccc ((f) a s r m) 390 | (mev (cons (list (list f (list 'lit 'cont s r)) 391 | a) 392 | s) 393 | r 394 | m)) 395 | 396 | (form thread ((e) a s r (p g)) 397 | (mev s 398 | (cons nil r) 399 | (list (cons (list (list (list e a)) 400 | nil) 401 | p) 402 | g))) 403 | 404 | (def evcall (e a s r m) 405 | (mev (cons (list (car e) a) 406 | (fu (s r m) 407 | (evcall2 (cdr e) a s r m)) 408 | s) 409 | r 410 | m)) 411 | 412 | (def evcall2 (es a s (op . r) m) 413 | (if ((isa 'mac) op) 414 | (applym op es a s r m) 415 | (mev (append (map [list _ a] es) 416 | (cons (fu (s r m) 417 | (let (args r2) (snap es r) 418 | (applyf op (rev args) a s r2 m))) 419 | s)) 420 | r 421 | m))) 422 | 423 | (def applym (mac args a s r m) 424 | (applyf (caddr mac) 425 | args 426 | a 427 | (cons (fu (s r m) 428 | (mev (cons (list (car r) a) s) 429 | (cdr r) 430 | m)) 431 | s) 432 | r 433 | m)) 434 | 435 | (def applyf (f args a s r m) 436 | (if (= f apply) (applyf (car args) (reduce join (cdr args)) a s r m) 437 | (caris f 'lit) (if (proper f) 438 | (applylit f args a s r m) 439 | (sigerr 'bad-lit s r m)) 440 | (sigerr 'cannot-apply s r m))) 441 | 442 | (def applylit (f args a s r m) 443 | (aif (and (inwhere s) (find [(car _) f] locfns)) 444 | ((cadr it) f args a s r m) 445 | (let (tag . rest) (cdr f) 446 | (case tag 447 | prim (applyprim (car rest) args s r m) 448 | clo (let ((o env) (o parms) (o body) . extra) rest 449 | (if (and (okenv env) (okparms parms)) 450 | (applyclo parms args env body s r m) 451 | (sigerr 'bad-clo s r m))) 452 | mac (applym f (map [list 'quote _] args) a s r m) 453 | cont (let ((o s2) (o r2) . extra) rest 454 | (if (and (okstack s2) (proper r2)) 455 | (applycont s2 r2 args s r m) 456 | (sigerr 'bad-cont s r m))) 457 | (aif (get tag virfns) 458 | (let e ((cdr it) f (map [list 'quote _] args)) 459 | (mev (cons (list e a) s) r m)) 460 | (sigerr 'unapplyable s r m)))))) 461 | 462 | (set virfns nil) 463 | 464 | (mac vir (tag . rest) 465 | `(set virfns (put ',tag (fn ,@rest) virfns))) 466 | 467 | (set locfns nil) 468 | 469 | (mac loc (test . rest) 470 | `(set locfns (cons (list ,test (fn ,@rest)) locfns))) 471 | 472 | (loc (is car) (f args a s r m) 473 | (mev (cdr s) (cons (list (car args) 'a) r) m)) 474 | 475 | (loc (is cdr) (f args a s r m) 476 | (mev (cdr s) (cons (list (car args) 'd) r) m)) 477 | 478 | (def okenv (a) 479 | (and (proper a) (all pair a))) 480 | 481 | (def okstack (s) 482 | (and (proper s) 483 | (all [and (proper _) (cdr _) (okenv (cadr _))] 484 | s))) 485 | 486 | (def okparms (p) 487 | (if (no p) t 488 | (variable p) t 489 | (atom p) nil 490 | (caris p t) (oktoparm p) 491 | (and (if (caris (car p) o) 492 | (oktoparm (car p)) 493 | (okparms (car p))) 494 | (okparms (cdr p))))) 495 | 496 | (def oktoparm ((tag (o var) (o e) . extra)) 497 | (and (okparms var) (or (= tag o) e) (no extra))) 498 | 499 | (set prims '((id join xar xdr wrb ops) 500 | (car cdr type sym nom rdb cls stat sys) 501 | (coin))) 502 | 503 | (def applyprim (f args s r m) 504 | (aif (some [mem f _] prims) 505 | (if (udrop (cdr it) args) 506 | (sigerr 'overargs s r m) 507 | (with (a (car args) 508 | b (cadr args)) 509 | (eif v (case f 510 | id (id a b) 511 | join (join a b) 512 | car (car a) 513 | cdr (cdr a) 514 | type (type a) 515 | xar (xar a b) 516 | xdr (xdr a b) 517 | sym (sym a) 518 | nom (nom a) 519 | wrb (wrb a b) 520 | rdb (rdb a) 521 | ops (ops a b) 522 | cls (cls a) 523 | stat (stat a) 524 | coin (coin) 525 | sys (sys a)) 526 | (sigerr v s r m) 527 | (mev s (cons v r) m)))) 528 | (sigerr 'unknown-prim s r m))) 529 | 530 | (def applyclo (parms args env body s r m) 531 | (mev (cons (fu (s r m) 532 | (pass parms args env s r m)) 533 | (fu (s r m) 534 | (mev (cons (list body (car r)) s) 535 | (cdr r) 536 | m)) 537 | s) 538 | r 539 | m)) 540 | 541 | (def pass (pat arg env s r m) 542 | (let ret [mev s (cons _ r) m] 543 | (if (no pat) (if arg 544 | (sigerr 'overargs s r m) 545 | (ret env)) 546 | (literal pat) (sigerr 'literal-parm s r m) 547 | (variable pat) (ret (cons (cons pat arg) env)) 548 | (caris pat t) (typecheck (cdr pat) arg env s r m) 549 | (caris pat o) (pass (cadr pat) arg env s r m) 550 | (destructure pat arg env s r m)))) 551 | 552 | (def typecheck ((var f) arg env s r m) 553 | (mev (cons (list (list f (list 'quote arg)) env) 554 | (fu (s r m) 555 | (if (car r) 556 | (pass var arg env s (cdr r) m) 557 | (sigerr 'mistype s r m))) 558 | s) 559 | r 560 | m)) 561 | 562 | (def destructure ((p . ps) arg env s r m) 563 | (if (no arg) (if (caris p o) 564 | (mev (cons (list (caddr p) env) 565 | (fu (s r m) 566 | (pass (cadr p) (car r) env s (cdr r) m)) 567 | (fu (s r m) 568 | (pass ps nil (car r) s (cdr r) m)) 569 | s) 570 | r 571 | m) 572 | (sigerr 'underargs s r m)) 573 | (atom arg) (sigerr 'atom-arg s r m) 574 | (mev (cons (fu (s r m) 575 | (pass p (car arg) env s r m)) 576 | (fu (s r m) 577 | (pass ps (cdr arg) (car r) s (cdr r) m)) 578 | s) 579 | r 580 | m))) 581 | 582 | (def applycont (s2 r2 args s r m) 583 | (if (or (no args) (cdr args)) 584 | (sigerr 'wrong-no-args s r m) 585 | (mev (append (keep [and (protected _) (no (mem _ s2 id))] 586 | s) 587 | s2) 588 | (cons (car args) r2) 589 | m))) 590 | 591 | (def protected (x) 592 | (some [begins (car x) (list smark _) id] 593 | '(bind prot))) 594 | 595 | (def function (x) 596 | (find [(isa _) x] '(prim clo))) 597 | 598 | (def con (x) 599 | (fn args x)) 600 | 601 | (def compose fs 602 | (reduce (fn (f g) 603 | (fn args (f (apply g args)))) 604 | (or fs (list idfn)))) 605 | 606 | (def combine (op) 607 | (fn fs 608 | (reduce (fn (f g) 609 | (fn args 610 | (op (apply f args) (apply g args)))) 611 | (or fs (list (con (op))))))) 612 | 613 | (set cand (combine and) 614 | cor (combine or)) 615 | 616 | (def foldl (f base . args) 617 | (if (or (no args) (some no args)) 618 | base 619 | (apply foldl f 620 | (apply f (snoc (map car args) base)) 621 | (map cdr args)))) 622 | 623 | (def foldr (f base . args) 624 | (if (or (no args) (some no args)) 625 | base 626 | (apply f (snoc (map car args) 627 | (apply foldr f base (map cdr args)))))) 628 | 629 | (def of (f g) 630 | (fn args (apply f (map g args)))) 631 | 632 | (def upon args 633 | [apply _ args]) 634 | 635 | (def pairwise (f xs) 636 | (or (no (cdr xs)) 637 | (and (f (car xs) (cadr xs)) 638 | (pairwise f (cdr xs))))) 639 | 640 | (def fuse (f . args) 641 | (apply append (apply map f args))) 642 | 643 | (mac letu (v . body) 644 | (if ((cor variable atom) v) 645 | `(let ,v (uvar) ,@body) 646 | `(with ,(fuse [list _ '(uvar)] v) 647 | ,@body))) 648 | 649 | (mac pcase (expr . args) 650 | (if (no (cdr args)) 651 | (car args) 652 | (letu v 653 | `(let ,v ,expr 654 | (if (,(car args) ,v) 655 | ,(cadr args) 656 | (pcase ,v ,@(cddr args))))))) 657 | 658 | (def match (x pat) 659 | (if (= pat t) t 660 | (function pat) (pat x) 661 | (or (atom x) (atom pat)) (= x pat) 662 | (and (match (car x) (car pat)) 663 | (match (cdr x) (cdr pat))))) 664 | 665 | (def split (f xs (o acc)) 666 | (if ((cor atom f:car) xs) 667 | (list acc xs) 668 | (split f (cdr xs) (snoc acc (car xs))))) 669 | 670 | (mac when (expr . body) 671 | `(if ,expr (do ,@body))) 672 | 673 | (mac unless (expr . body) 674 | `(when (no ,expr) ,@body)) 675 | 676 | (set i0 nil 677 | i1 '(t) 678 | i2 '(t t) 679 | i10 '(t t t t t t t t t t) 680 | i16 '(t t t t t t t t t t t t t t t t)) 681 | 682 | (set i< udrop) 683 | 684 | (def i+ args 685 | (apply append args)) 686 | 687 | (def i- (x y) 688 | (if (no x) (list '- y) 689 | (no y) (list '+ x) 690 | (i- (cdr x) (cdr y)))) 691 | 692 | (def i* args 693 | (foldr (fn (x y) (fuse (con x) y)) 694 | i1 695 | args)) 696 | 697 | (def i/ (x y (o q)) 698 | (if (no x) (list q nil) 699 | (i< x y) (list q x) 700 | (i/ (udrop y x) y (i+ q i1)))) 701 | 702 | (def i^ (x y) 703 | (foldr i* i1 (map (con x) y))) 704 | 705 | (def r+ ((xn xd) (yn yd)) 706 | (list (i+ (i* xn yd) (i* yn xd)) 707 | (i* xd yd))) 708 | 709 | (def r- ((xn xd) (yn yd)) 710 | (let (s n) (i- (i* xn yd) (i* yn xd)) 711 | (list s n (i* xd yd)))) 712 | 713 | (def r* ((xn xd) (yn yd)) 714 | (list (i* xn yn) (i* xd yd))) 715 | 716 | (def r/ ((xn xd) (yn yd)) 717 | (list (i* xn yd) (i* xd yn))) 718 | 719 | (set srzero (list '+ i0 i1) 720 | srone (list '+ i1 i1)) 721 | 722 | (def sr+ ((xs . xr) (ys . yr)) 723 | (if (= xs '-) 724 | (if (= ys '-) 725 | (cons '- (r+ xr yr)) 726 | (r- yr xr)) 727 | (if (= ys '-) 728 | (r- xr yr) 729 | (cons '+ (r+ xr yr))))) 730 | 731 | (def sr- (x y) 732 | (sr+ x (srinv y))) 733 | 734 | (def srinv ((s n d)) 735 | (list (if (and (= s '+) (~= n i0)) '- '+) 736 | n 737 | d)) 738 | 739 | (def sr* ((xs . xr) (ys . yr)) 740 | (cons (if (= xs '-) 741 | (case ys - '+ '-) 742 | ys) 743 | (r* xr yr))) 744 | 745 | (def sr/ (x y) 746 | (sr* x (srrecip y))) 747 | 748 | (def srrecip ((s (t n [~= _ i0]) d)) 749 | (list s d n)) 750 | 751 | (def sr< ((xs xn xd) (ys yn yd)) 752 | (if (= xs '+) 753 | (if (= ys '+) 754 | (i< (i* xn yd) (i* yn xd)) 755 | nil) 756 | (if (= ys '+) 757 | (~= xn yn i0) 758 | (i< (i* yn xd) (i* xn yd))))) 759 | 760 | (set srnum cadr 761 | srden caddr) 762 | 763 | (def c+ ((xr xi) (yr yi)) 764 | (list (sr+ xr yr) (sr+ xi yi))) 765 | 766 | (def c* ((xr xi) (yr yi)) 767 | (list (sr- (sr* xr yr) (sr* xi yi)) 768 | (sr+ (sr* xi yr) (sr* xr yi)))) 769 | 770 | (def litnum (r (o i srzero)) 771 | (list 'lit 'num r i)) 772 | 773 | (def number (x) 774 | (let r (fn (y) 775 | (match y (list [in _ '+ '-] proper proper))) 776 | (match x `(lit num ,r ,r)))) 777 | 778 | (set numr car:cddr 779 | numi cadr:cddr) 780 | 781 | (set rpart litnum:numr 782 | ipart litnum:numi) 783 | 784 | (def real (x) 785 | (and (number x) (= (numi x) srzero))) 786 | 787 | (def inv (x) 788 | (litnum (srinv:numr x) (srinv:numi x))) 789 | 790 | (def abs (x) 791 | (litnum (cons '+ (cdr (numr x))))) 792 | 793 | (def simplify ((s n d)) 794 | (if (= n i0) (list '+ n i1) 795 | (= n d) (list s i1 i1) 796 | (let g (apply i* ((of common factor) n d)) 797 | (list s (car:i/ n g) (car:i/ d g))))) 798 | 799 | (def factor (x (o d i2)) 800 | (if (i< x d) 801 | nil 802 | (let (q r) (i/ x d) 803 | (if (= r i0) 804 | (cons d (factor q d)) 805 | (factor x (i+ d i1)))))) 806 | 807 | (def common (xs ys) 808 | (if (in nil xs ys) 809 | nil 810 | (let (a b) (split (is (car xs)) ys) 811 | (if b 812 | (cons (car xs) 813 | (common (cdr xs) (append a (cdr b)))) 814 | (common (cdr xs) ys))))) 815 | 816 | (set buildnum (of litnum simplify)) 817 | 818 | (def recip (x) 819 | (with (r (numr x) 820 | i (numi x)) 821 | (let d (sr+ (sr* r r) (sr* i i)) 822 | (buildnum (sr/ r d) 823 | (sr/ (srinv i) d))))) 824 | 825 | (def + ns 826 | (foldr (fn (x y) 827 | (apply buildnum ((of c+ cddr) x y))) 828 | 0 829 | ns)) 830 | 831 | (def - ns 832 | (if (no ns) 0 833 | (no (cdr ns)) (inv (car ns)) 834 | (+ (car ns) (inv (apply + (cdr ns)))))) 835 | 836 | (def * ns 837 | (foldr (fn (x y) 838 | (apply buildnum ((of c* cddr) x y))) 839 | 1 840 | ns)) 841 | 842 | (def / ns 843 | (if (no ns) 844 | 1 845 | (* (car ns) (recip (apply * (cdr ns)))))) 846 | 847 | (def inc (n) (+ n 1)) 848 | 849 | (def dec (n) (- n 1)) 850 | 851 | (def pos (x ys (o f =)) 852 | (if (no ys) nil 853 | (f (car ys) x) 1 854 | (aif (pos x (cdr ys) f) (+ it 1)))) 855 | 856 | (def len (xs) 857 | (if (no xs) 0 (inc:len:cdr xs))) 858 | 859 | (def charn (c) 860 | (dec:pos c chars caris)) 861 | 862 | (def < args 863 | (pairwise bin< args)) 864 | 865 | (def > args 866 | (apply < (rev args))) 867 | 868 | (def list< (x y) 869 | (if (no x) y 870 | (no y) nil 871 | (or (< (car x) (car y)) 872 | (and (= (car x) (car y)) 873 | (< (cdr x) (cdr y)))))) 874 | 875 | (def bin< args 876 | (aif (all no args) nil 877 | (find [all (car _) args] comfns) (apply (cdr it) args) 878 | (err 'incomparable))) 879 | 880 | (set comfns nil) 881 | 882 | (def com (f g) 883 | (set comfns (put f g comfns))) 884 | 885 | (com real (of sr< numr)) 886 | 887 | (com char (of < charn)) 888 | 889 | (com string list<) 890 | 891 | (com symbol (of list< nom)) 892 | 893 | (def int (n) 894 | (and (real n) (= (srden:numr n) i1))) 895 | 896 | (def whole (n) 897 | (and (int n) (~< n 0))) 898 | 899 | (def pint (n) 900 | (and (int n) (> n 0))) 901 | 902 | (def yc (f) 903 | ([_ _] [f (fn a (apply (_ _) a))])) 904 | 905 | (mac rfn (name . rest) 906 | `(yc (fn (,name) (fn ,@rest)))) 907 | 908 | (mac afn args 909 | `(rfn self ,@args)) 910 | 911 | (def wait (f) 912 | ((afn (v) (if v v (self (f)))) 913 | (f))) 914 | 915 | (def runs (f xs (o fon (and xs (f (car xs))))) 916 | (if (no xs) 917 | nil 918 | (let (as bs) (split (if fon ~f f) xs) 919 | (cons as (runs f bs (no fon)))))) 920 | 921 | (def whitec (c) 922 | (in c \sp \lf \tab \cr)) 923 | 924 | (def tokens (xs (o break whitec)) 925 | (let f (if (function break) break (is break)) 926 | (keep ~f:car (runs f xs)))) 927 | 928 | (def dups (xs (o f =)) 929 | (if (no xs) nil 930 | (mem (car xs) (cdr xs) f) (cons (car xs) 931 | (dups (rem (car xs) (cdr xs) f) f)) 932 | (dups (cdr xs) f))) 933 | 934 | (set simple (cor atom number)) 935 | 936 | (mac do1 args 937 | (letu v 938 | `(let ,v ,(car args) 939 | ,@(cdr args) 940 | ,v))) 941 | 942 | (def gets (v kvs (o f =)) 943 | (find [f (cdr _) v] kvs)) 944 | 945 | (def consif (x y) 946 | (if x (cons x y) y)) 947 | 948 | (mac check (x f (o alt)) 949 | (letu v 950 | `(let ,v ,x 951 | (if (,f ,v) ,v ,alt)))) 952 | 953 | (mac withs (parms . body) 954 | (if (no parms) 955 | `(do ,@body) 956 | `(let ,(car parms) ,(cadr parms) 957 | (withs ,(cddr parms) ,@body)))) 958 | 959 | (mac bind (var expr . body) 960 | `(dyn ,var ,expr (do ,@body))) 961 | 962 | (mac atomic body 963 | `(bind lock t ,@body)) 964 | 965 | (def tail (f xs) 966 | (if (no xs) nil 967 | (f xs) xs 968 | (tail f (cdr xs)))) 969 | 970 | (set dock rev:cdr:rev) 971 | 972 | (def lastcdr (xs) 973 | (if (no (cdr xs)) 974 | xs 975 | (lastcdr (cdr xs)))) 976 | 977 | (set last car:lastcdr) 978 | 979 | (def newq () 980 | (list nil)) 981 | 982 | (def enq (x q) 983 | (atomic (xar q (snoc (car q) x))) 984 | q) 985 | 986 | (def deq (q) 987 | (atomic (do1 (car (car q)) 988 | (xar q (cdr (car q)))))) 989 | 990 | (mac set args 991 | (cons 'do 992 | (map (fn ((p (o e t))) 993 | (letu v 994 | `(atomic (let ,v ,e 995 | (let (cell loc) (where ,p t) 996 | ((case loc a xar d xdr) cell ,v)))))) 997 | (hug args)))) 998 | 999 | (mac zap (op place . args) 1000 | (letu (vo vc vl va) 1001 | `(atomic (with (,vo ,op 1002 | (,vc ,vl) (where ,place) 1003 | ,va (list ,@args)) 1004 | (case ,vl 1005 | a (xar ,vc (apply ,vo (car ,vc) ,va)) 1006 | d (xdr ,vc (apply ,vo (cdr ,vc) ,va)) 1007 | (err 'bad-place)))))) 1008 | 1009 | (mac ++ (place (o n 1)) 1010 | `(zap + ,place ,n)) 1011 | 1012 | (mac -- (place (o n 1)) 1013 | `(zap - ,place ,n)) 1014 | 1015 | (mac push (x place) 1016 | (letu v 1017 | `(let ,v ,x 1018 | (zap [cons ,v _] ,place)))) 1019 | 1020 | (mac pull (x place . rest) 1021 | (letu v 1022 | `(let ,v ,x 1023 | (zap [rem ,v _ ,@rest] ,place)))) 1024 | 1025 | (set cbuf '((nil))) 1026 | 1027 | (def open args 1028 | (let s (apply ops args) 1029 | (push (list s) cbuf) 1030 | s)) 1031 | 1032 | (def close (s) 1033 | (pull s cbuf caris) 1034 | (cls s)) 1035 | 1036 | (def peek ((o s ins)) 1037 | (if ((cor no stream) s) 1038 | (let c (wait (fn () 1039 | (atomic (let p (get s cbuf) 1040 | (or (cdr p) 1041 | (aif (bitc s) (xdr p it) nil)))))) 1042 | (if (= c 'eof) nil c)) 1043 | (car (car s)))) 1044 | 1045 | (def rdc ((o s ins)) 1046 | (if ((cor no stream) s) 1047 | (let c (wait (fn () 1048 | (atomic (let p (get s cbuf) 1049 | (aif (cdr p) 1050 | (do (xdr p nil) it) 1051 | (bitc s)))))) 1052 | (if (= c 'eof) nil c)) 1053 | (deq s))) 1054 | 1055 | (set bbuf nil) 1056 | 1057 | (def bitc ((o s ins)) 1058 | (let bits (get s bbuf) 1059 | (aif (gets (rev (cdr bits)) chars) 1060 | (do (pull s bbuf caris) 1061 | (car it)) 1062 | (let b (rdb s) 1063 | (if (in b nil 'eof) 1064 | b 1065 | (do (if bits 1066 | (push b (cdr bits)) 1067 | (push (list s b) bbuf)) 1068 | (bitc s))))))) 1069 | 1070 | (def digit (c (o base i10)) 1071 | (mem c (udrop (udrop base i16) "fedcba9876543210"))) 1072 | 1073 | (set breakc (cor no whitec (is \;) [get _ syntax])) 1074 | 1075 | (def signc (c) 1076 | (in c \+ \-)) 1077 | 1078 | (def intrac (c) 1079 | (in c \. \!)) 1080 | 1081 | (set source (cor no stream (cand pair string:car))) 1082 | 1083 | (def read ((o s|source ins) (o (t base [<= 2 _ 16]) 10) (o eof)) 1084 | (car (rdex s (srnum:numr base) eof))) 1085 | 1086 | (def saferead ((o s ins) (o alt) (o base 10)) 1087 | (onerr alt (read s base alt))) 1088 | 1089 | (def rdex ((o s ins) (o base i10) (o eof) (o share)) 1090 | (eatwhite s) 1091 | (let c (rdc s) 1092 | (aif (no c) (list eof share) 1093 | (get c syntax) ((cdr it) s base share) 1094 | (list (rdword s c base) share)))) 1095 | 1096 | (def eatwhite (s) 1097 | (pcase (peek s) 1098 | whitec (do (rdc s) 1099 | (eatwhite s)) 1100 | (is \;) (do (charstil s (is \lf)) 1101 | (eatwhite s)))) 1102 | 1103 | (def charstil (s f) 1104 | (if ((cor no f) (peek s)) 1105 | nil 1106 | (cons (rdc s) (charstil s f)))) 1107 | 1108 | (set syntax nil) 1109 | 1110 | (mac syn (c . rest) 1111 | `(set syntax (put ,c (fn ,@rest) syntax))) 1112 | 1113 | (syn \( (s base share) 1114 | (rdlist s \) base share)) 1115 | 1116 | (syn \) args 1117 | (err 'unexpected-terminator)) 1118 | 1119 | (syn \[ (s base share) 1120 | (let (e newshare) (rdlist s \] base share) 1121 | (list (list 'fn '(_) e) newshare))) 1122 | 1123 | (syn \] args 1124 | (err 'unexpected-terminator)) 1125 | 1126 | (def rdlist (s term base share (o acc)) 1127 | (eatwhite s) 1128 | (pcase (peek s) 1129 | no (err 'unterminated-list) 1130 | (is \.) (do (rdc s) (rddot s term base share acc)) 1131 | (is term) (do (rdc s) (list acc share)) 1132 | (let (e newshare) (rdex s base nil share) 1133 | (rdlist s term base newshare (snoc acc e))))) 1134 | 1135 | (def rddot (s term base share acc) 1136 | (pcase (peek s) 1137 | no (err 'unterminated-list) 1138 | breakc (if (no acc) 1139 | (err 'missing-car) 1140 | (let (e newshare) (hard-rdex s base share 'missing-cdr) 1141 | (if (car (rdlist s term base share)) 1142 | (err 'duplicate-cdr) 1143 | (list (apply cons (snoc acc e)) 1144 | newshare)))) 1145 | (rdlist s term base share (snoc acc (rdword s \. base))))) 1146 | 1147 | (def hard-rdex (s base share msg) 1148 | (let eof (join) 1149 | (let v (rdex s base eof share) 1150 | (if (id (car v) eof) (err msg) v)))) 1151 | 1152 | (set namecs '((bel . \bel) (tab . \tab) (lf . \lf) (cr . \cr) (sp . \sp))) 1153 | 1154 | (syn \\ (s base share) 1155 | (list (pcase (peek s) 1156 | no (err 'escape-without-char) 1157 | breakc (rdc s) 1158 | (let cs (charstil s breakc) 1159 | (if (cdr cs) 1160 | (aif (get (sym cs) namecs) 1161 | (cdr it) 1162 | (err 'unknown-named-char)) 1163 | (car cs)))) 1164 | share)) 1165 | 1166 | (syn \' (s base share) 1167 | (rdwrap s 'quote base share)) 1168 | 1169 | (syn \` (s base share) 1170 | (rdwrap s 'bquote base share)) 1171 | 1172 | (syn \, (s base share) 1173 | (case (peek s) 1174 | \@ (do (rdc s) 1175 | (rdwrap s 'comma-at base share)) 1176 | (rdwrap s 'comma base share))) 1177 | 1178 | (def rdwrap (s token base share) 1179 | (let (e newshare) (hard-rdex s base share 'missing-expression) 1180 | (list (list token e) newshare))) 1181 | 1182 | (syn \" (s base share) 1183 | (list (rddelim s \") share)) 1184 | 1185 | (syn \¦ (s base share) 1186 | (list (sym (rddelim s \¦)) share)) 1187 | 1188 | (def rddelim (s d (o esc)) 1189 | (let c (rdc s) 1190 | (if (no c) (err 'missing-delimiter) 1191 | esc (cons c (rddelim s d)) 1192 | (= c \\) (rddelim s d t) 1193 | (= c d) nil 1194 | (cons c (rddelim s d))))) 1195 | 1196 | (syn \# (s base share) 1197 | (let name (charstil s ~digit) 1198 | (if (= (peek s) \=) 1199 | (do (rdc s) 1200 | (rdtarget s base name (join) share)) 1201 | (aif (get name share) 1202 | (list (cdr it) share) 1203 | (err 'unknown-label))))) 1204 | 1205 | (def rdtarget (s base name cell oldshare) 1206 | (withs (share (cons (cons name cell) oldshare) 1207 | (e newshare) (hard-rdex s base share 'missing-target)) 1208 | (if (simple e) 1209 | (err 'bad-target) 1210 | (do (xar cell (car e)) 1211 | (xdr cell (cdr e)) 1212 | (list cell newshare))))) 1213 | 1214 | (def rdword (s c base) 1215 | (parseword (cons c (charstil s breakc)) base)) 1216 | 1217 | (def parseword (cs base) 1218 | (or (parsenum cs base) 1219 | (if (= cs ".") (err 'unexpected-dot) 1220 | (mem \| cs) (parset cs base) 1221 | (some intrac cs) (parseslist (runs intrac cs) base) 1222 | (parsecom cs base)))) 1223 | 1224 | (def parsenum (cs base) 1225 | (if (validi cs base) 1226 | (buildnum srzero (parsei cs base)) 1227 | (let sign (check (car cs) signc) 1228 | (let (ds es) (split signc (if sign (cdr cs) cs)) 1229 | (and (validr ds base) 1230 | (or (no es) (validi es base)) 1231 | (buildnum (parsesr (consif sign ds) base) 1232 | (if (no es) srzero (parsei es base)))))))) 1233 | 1234 | (def validi (cs base) 1235 | (and (signc (car cs)) 1236 | (= (last cs) \i) 1237 | (let digs (cdr (dock cs)) 1238 | (or (no digs) (validr digs base))))) 1239 | 1240 | (def validr (cs base) 1241 | (or (validd cs base) 1242 | (let (n d) (split (is \/) cs) 1243 | (and (validd n base) 1244 | (validd (cdr d) base))))) 1245 | 1246 | (def validd (cs base) 1247 | (and (all (cor [digit _ base] (is \.)) cs) 1248 | (some [digit _ base] cs) 1249 | (~cdr (keep (is \.) cs)))) 1250 | 1251 | (def parsei (cs base) 1252 | (if (cddr cs) 1253 | (parsesr (dock cs) base) 1254 | (if (caris cs \+) 1255 | srone 1256 | (srinv srone)))) 1257 | 1258 | (def parsesr (cs base) 1259 | (withs (sign (if (signc (car cs)) (sym (list (car cs)))) 1260 | (n d) (split (is \/) (if sign (cdr cs) cs))) 1261 | (simplify (cons (or sign '+) 1262 | (r/ (parsed n base) 1263 | (if d 1264 | (let rd (parsed (cdr d) base) 1265 | (if (caris rd i0) 1266 | (err 'zero-denominator) 1267 | rd)) 1268 | (list i1 i1))))))) 1269 | 1270 | (def parsed (cs base) 1271 | (let (i f) (split (is \.) cs) 1272 | (if (cdr f) 1273 | (list (parseint (rev (append i (cdr f))) base) 1274 | (i^ base 1275 | (apply i+ (map (con i1) (cdr f))))) 1276 | (list (parseint (rev i) base) i1)))) 1277 | 1278 | (def parseint (ds base) 1279 | (if ds 1280 | (i+ (charint (car ds)) 1281 | (i* base (parseint (cdr ds) base))) 1282 | i0)) 1283 | 1284 | (def charint (c) 1285 | (map (con t) (mem c "fedcba987654321"))) 1286 | 1287 | (def parset (cs base) 1288 | (if (cdr (keep (is \|) cs)) 1289 | (err 'multiple-bars) 1290 | (let vt (tokens cs \|) 1291 | (if (= (len vt) 2) 1292 | (cons t (map [parseword _ base] vt)) 1293 | (err 'bad-tspec))))) 1294 | 1295 | (def parseslist (rs base) 1296 | (if (intrac (car (last rs))) 1297 | (err 'final-intrasymbol) 1298 | (map (fn ((cs ds)) 1299 | (if (cdr cs) (err 'double-intrasymbol) 1300 | (caris cs \!) (list 'quote (parsecom ds base)) 1301 | (parsecom ds base))) 1302 | (hug (if (intrac (car (car rs))) 1303 | (cons "." "upon" rs) 1304 | (cons "." rs)))))) 1305 | 1306 | (def parsecom (cs base) 1307 | (if (mem \: cs) 1308 | (cons 'compose (map [parseno _ base] (tokens cs \:))) 1309 | (parseno cs base))) 1310 | 1311 | (def parseno (cs base) 1312 | (if (caris cs \~) 1313 | (if (cdr cs) 1314 | (list 'compose 'no (parseno (cdr cs) base)) 1315 | 'no) 1316 | (or (parsenum cs base) (sym cs)))) 1317 | 1318 | (mac bquote (e) 1319 | (let (sub change) (bqex e nil) 1320 | (if change sub (list 'quote e)))) 1321 | 1322 | (def bqex (e n) 1323 | (if (no e) (list nil nil) 1324 | (atom e) (list (list 'quote e) nil) 1325 | (case (car e) 1326 | bquote (bqthru e (list n) 'bquote) 1327 | comma (if (no n) 1328 | (list (cadr e) t) 1329 | (bqthru e (car n) 'comma)) 1330 | comma-at (if (no n) 1331 | (list (list 'splice (cadr e)) t) 1332 | (bqthru e (car n) 'comma-at)) 1333 | (bqexpair e n)))) 1334 | 1335 | (def bqthru (e n op) 1336 | (let (sub change) (bqex (cadr e) n) 1337 | (if change 1338 | (list (if (caris sub 'splice) 1339 | `(cons ',op ,(cadr sub)) 1340 | `(list ',op ,sub)) 1341 | t) 1342 | (list (list 'quote e) nil)))) 1343 | 1344 | (def bqexpair (e n) 1345 | (with ((a achange) (bqex (car e) n) 1346 | (d dchange) (bqex (cdr e) n)) 1347 | (if (or achange dchange) 1348 | (list (if (caris d 'splice) 1349 | (if (caris a 'splice) 1350 | `(apply append (spa ,(cadr a)) (spd ,(cadr d))) 1351 | `(apply cons ,a (spd ,(cadr d)))) 1352 | (caris a 'splice) 1353 | `(append (spa ,(cadr a)) ,d) 1354 | `(cons ,a ,d)) 1355 | t) 1356 | (list (list 'quote e) nil)))) 1357 | 1358 | (def spa (x) 1359 | (if (and x (atom x)) 1360 | (err 'splice-atom) 1361 | x)) 1362 | 1363 | (def spd (x) 1364 | (pcase x 1365 | no (err 'splice-empty-cdr) 1366 | atom (err 'splice-atom) 1367 | cdr (err 'splice-multiple-cdrs) 1368 | x)) 1369 | 1370 | (mac comma args 1371 | '(err 'comma-outside-backquote)) 1372 | 1373 | (mac comma-at args 1374 | '(err 'comma-at-outside-backquote)) 1375 | 1376 | (mac splice args 1377 | '(err 'comma-at-outside-list)) 1378 | 1379 | (def print (x (o s outs) (o names (namedups x)) (o hist)) 1380 | (aif (simple x) (do (prsimple x s) hist) 1381 | (ustring x names) (prstring x s names hist) 1382 | (get x names id) (do (prc \# s) 1383 | (print (cdr it) s) 1384 | (if (mem x hist id) 1385 | hist 1386 | (do (prc \= s) 1387 | (if (ustring (cdr x) names) 1388 | (prstring x s names (cons x hist)) 1389 | (prpair x s names (cons x hist)))))) 1390 | (prpair x s names hist))) 1391 | 1392 | (def namedups (x (o n 0)) 1393 | (map [cons _ (++ n)] (dups (cells x) id))) 1394 | 1395 | (def cells (x (o seen)) 1396 | (if (simple x) seen 1397 | (mem x seen id) (snoc seen x) 1398 | (cells (cdr x) 1399 | (cells (car x) (snoc seen x))))) 1400 | 1401 | (def prc (c (o s outs)) 1402 | (if (atom s) 1403 | (aif (get c chars) 1404 | (map [wrb _ s] (cdr it)) 1405 | (err 'unknown char)) 1406 | (enq c s)) 1407 | c) 1408 | 1409 | (def ustring (x names) 1410 | (and x (string x) (~tail [get _ names id] x))) 1411 | 1412 | (def prstring (x s names hist) 1413 | (prc \" s) 1414 | (presc x \" s) 1415 | (prc \" s) 1416 | hist) 1417 | 1418 | (def presc (cs esc s) 1419 | (map (fn (c) 1420 | (if (in c esc \\) (prc \\ s)) 1421 | (prc c s)) 1422 | cs)) 1423 | 1424 | (def prsimple (x s) 1425 | (pcase x 1426 | symbol (prsymbol x s) 1427 | char (do (prc \\ s) (prc x s)) 1428 | stream (map [prc _ s] "") 1429 | number (prnum (numr x) (numi x) s) 1430 | (err 'cannot-print))) 1431 | 1432 | (def prsymbol (x s) 1433 | (let cs (nom x) 1434 | (let odd (~= (saferead (list cs)) x) 1435 | (if odd (prc \¦ s)) 1436 | (presc cs \¦ s) 1437 | (if odd (prc \¦ s))))) 1438 | 1439 | (def prnum (r i s) 1440 | (unless (and (= r srzero) (~= i srzero)) 1441 | (if (caris r '-) (prc \- s)) 1442 | (map [prc _ s] (rrep (cdr r)))) 1443 | (unless (= i srzero) 1444 | (print (car i) s) 1445 | (unless (apply = (cdr i)) 1446 | (map [prc _ s] (rrep (cdr i)))) 1447 | (prc \i s))) 1448 | 1449 | (def rrep ((n d) (o base i10)) 1450 | (append (irep n base) 1451 | (if (= d i1) nil (cons \/ (irep d base))))) 1452 | 1453 | (def irep (x base) 1454 | (if (i< x base) 1455 | (list (intchar x)) 1456 | (let (q r) (i/ x base) 1457 | (snoc (irep q base) (intchar r))))) 1458 | 1459 | (def intchar (x) 1460 | (car (udrop x "0123456789abcdef"))) 1461 | 1462 | (def prpair (x s names hist) 1463 | (prc \( s) 1464 | (do1 (prelts x s names hist) 1465 | (prc \) s))) 1466 | 1467 | (def prelts ((x . rest) s names hist) 1468 | (let newhist (print x s names hist) 1469 | (if (or (and rest (simple rest)) 1470 | (ustring rest names) 1471 | (get rest names id)) 1472 | (do (map [prc _ s] " . ") 1473 | (print rest s names newhist)) 1474 | (if rest 1475 | (do (prc \sp s) 1476 | (prelts rest s names newhist)) 1477 | newhist)))) 1478 | 1479 | (def prn args 1480 | (map [do (print _) (prc \sp)] args) 1481 | (prc \lf) 1482 | (last args)) 1483 | 1484 | (def pr args 1485 | (map prnice args)) 1486 | 1487 | (def prnice (x (o s outs)) 1488 | (pcase x 1489 | char (prc x s) 1490 | string (map [prc _ s] x) 1491 | (print x s nil)) 1492 | x) 1493 | 1494 | (def drop (n|whole xs) 1495 | (if (= n 0) 1496 | xs 1497 | (drop (- n 1) (cdr xs)))) 1498 | 1499 | (def nth (n|pint xs|pair) 1500 | (if (= n 1) 1501 | (car xs) 1502 | (nth (- n 1) (cdr xs)))) 1503 | 1504 | (vir num (f args) 1505 | `(nth ,f ,@args)) 1506 | 1507 | (def nchar (n) 1508 | (car ((+ n 1) chars))) 1509 | 1510 | (def first (n|whole xs) 1511 | (if (or (= n 0) (no xs)) 1512 | nil 1513 | (cons (car xs) 1514 | (first (- n 1) (cdr xs))))) 1515 | 1516 | (mac catch body 1517 | (letu v 1518 | `(ccc (fn (,v) (bind throw ,v ,@body))))) 1519 | 1520 | (def cut (xs (o start 1) (o end (len xs))) 1521 | (first (- (+ end 1 (if (< end 0) (len xs) 0)) 1522 | start) 1523 | (drop (- start 1) xs))) 1524 | 1525 | (mac whenlet (var expr . body) 1526 | `(iflet ,var ,expr (do ,@body))) 1527 | 1528 | (mac awhen args 1529 | `(whenlet it ,@args)) 1530 | 1531 | (mac each (var expr . body) 1532 | `(map (fn (,var) ,@body) ,expr)) 1533 | 1534 | (def flip (f) 1535 | (fn args (apply f (rev args)))) 1536 | 1537 | (def part (f . args) 1538 | (fn rest 1539 | (apply f (append args rest)))) 1540 | 1541 | (def trap (f . args) 1542 | (flip (apply part (flip f) (rev args)))) 1543 | 1544 | (def only (f) 1545 | (fn args 1546 | (if (car args) (apply f args)))) 1547 | 1548 | (def >= args 1549 | (pairwise ~bin< args)) 1550 | 1551 | (def <= args 1552 | (apply >= (rev args))) 1553 | 1554 | (def floor (x|real) 1555 | (let (s n d) (numr x) 1556 | (let (f m) (i/ n d) 1557 | (litnum (list s 1558 | (i+ f (if (or (= s '+) (= m i0)) 1559 | i0 1560 | i1)) 1561 | i1))))) 1562 | 1563 | (set ceil -:floor:-) 1564 | 1565 | (def mod (x y) 1566 | (* (- (/ x y) (floor (/ x y))) 1567 | y)) 1568 | 1569 | (mac whilet (var expr . body) 1570 | (letu (vf vp) 1571 | `((rfn ,vf (,vp) 1572 | (whenlet ,var ,vp ,@body (,vf ,expr))) 1573 | ,expr))) 1574 | 1575 | (mac loop (var init update test . body) 1576 | (letu v 1577 | `((rfn ,v (,var) 1578 | (when ,test ,@body (,v ,update))) 1579 | ,init))) 1580 | 1581 | (mac while (expr . body) 1582 | (letu v 1583 | `(loop ,v ,expr ,expr ,v ,@body))) 1584 | 1585 | (mac til (var expr test . body) 1586 | `(loop ,var ,expr ,expr (no ,test) 1587 | ,@body)) 1588 | 1589 | (mac for (var init max . body) 1590 | (letu (vi vm) 1591 | `(with (,vi ,init 1592 | ,vm ,max) 1593 | (loop ,var ,vi (+ ,var 1) (<= ,var ,vm) 1594 | ,@body)))) 1595 | 1596 | (mac repeat (n . body) 1597 | `(for ,(uvar) 1 ,n ,@body)) 1598 | 1599 | (mac poll (expr f) 1600 | (letu (vr ve vf) 1601 | `((rfn ,vr (,ve ,vf) 1602 | (if (,vf ,ve) ,ve (,vr ,expr ,vf))) 1603 | ,expr 1604 | ,f))) 1605 | 1606 | (mac accum (var . body) 1607 | (letu v 1608 | `(withs (,v nil 1609 | ,var [push _ ,v]) 1610 | ,@body 1611 | (rev ,v)))) 1612 | 1613 | (mac nof (n expr) 1614 | (letu v 1615 | `(accum ,v (repeat ,n (,v ,expr))))) 1616 | 1617 | (mac drain (expr (o f 'no)) 1618 | (letu v 1619 | `(accum ,v 1620 | (poll ,expr (cor ,f (compose no ,v)))))) 1621 | 1622 | (def ^w (x y|whole) 1623 | (apply * (nof y x))) 1624 | 1625 | (def clog2 (n) 1626 | (if (<= n 2) 1 (inc:clog2 (/ n 2)))) 1627 | 1628 | (def randlen (n) 1629 | (read (list (nof n (if (coin) \0 \1))) 1630 | 2)) 1631 | 1632 | (def rand (n|pint) 1633 | (poll (randlen (clog2 n)) [< _ n])) 1634 | 1635 | (mac wipe args 1636 | `(set ,@(fuse [list _ nil] args))) 1637 | 1638 | (mac pop (place) 1639 | `(let (cell loc) (where ,place) 1640 | (let xs ((case loc a car d cdr) cell) 1641 | ((case loc a xar d xdr) cell (cdr xs)) 1642 | (car xs)))) 1643 | 1644 | (mac clean (f place) 1645 | (letu v 1646 | `(let ,v (compose no ,f) 1647 | (zap [keep ,v _] ,place)))) 1648 | 1649 | (mac swap places 1650 | (let vs (map [nof 3 (uvar)] places) 1651 | `(atomic (withs ,(fuse (fn (place (cell loc val)) 1652 | (list (list cell loc) 1653 | `(where ,place) 1654 | val 1655 | `((case ,loc a car d cdr) ,cell))) 1656 | places 1657 | vs) 1658 | ,@(map (fn ((cellx locx valx) (celly locy valy)) 1659 | `((case ,locx a xar d xdr) ,cellx ,valy)) 1660 | vs 1661 | (snoc (cdr vs) (car vs))))))) 1662 | 1663 | (def adjoin (x ys (o f =)) 1664 | (if (mem x ys f) ys (cons x ys))) 1665 | 1666 | (mac pushnew (x place (o f '=)) 1667 | (letu v 1668 | `(let ,v ,x 1669 | (zap [adjoin ,v _ ,f] ,place)))) 1670 | 1671 | (def dedup (xs (o f =)) 1672 | (rev (foldl (trap adjoin f) nil xs))) 1673 | 1674 | (def insert (f x ys) 1675 | (if (no ys) (list x) 1676 | (f x (car ys)) (cons x ys) 1677 | (cons (car ys) (insert f x (cdr ys))))) 1678 | 1679 | (def sort (f xs) 1680 | (foldr (part insert f) nil (rev xs))) 1681 | 1682 | (set best car:sort) 1683 | 1684 | (def max args 1685 | (best > args)) 1686 | 1687 | (def min args 1688 | (best < args)) 1689 | 1690 | (def even (n) 1691 | (int (/ n 2))) 1692 | 1693 | (set odd (cand int ~even)) 1694 | 1695 | (def round (n) 1696 | (let r (fn (n) 1697 | (withs (f (floor n) 1698 | d (- n f)) 1699 | (if (or (> d 1/2) (and (= d 1/2) (odd f))) 1700 | (ceil n) 1701 | f))) 1702 | (if (< n 0) (-:r:- n) (r n)))) 1703 | 1704 | (mac withfile (var name dir . body) 1705 | `(let ,var (open ,name ,dir) 1706 | (after (do ,@body) (close ,var)))) 1707 | 1708 | (mac from (name . body) 1709 | (letu v 1710 | `(withfile ,v ,name 'in 1711 | (bind ins ,v ,@body)))) 1712 | 1713 | (mac to (name . body) 1714 | (letu v 1715 | `(withfile ,v ,name 'out 1716 | (bind outs ,v ,@body)))) 1717 | 1718 | (def readall ((o s ins) (o base 10)) 1719 | (let eof (join) 1720 | (drain (read s base eof) [id _ eof]))) 1721 | 1722 | (def load (name) 1723 | (let eof (join) 1724 | (withfile s name 'in 1725 | (til e (read s 10 eof) (id e eof) 1726 | (bel e))))) 1727 | 1728 | (mac record body 1729 | (letu v 1730 | `(let ,v (newq) 1731 | (bind outs ,v ,@body) 1732 | (car ,v)))) 1733 | 1734 | (def prs args 1735 | (record (apply pr args))) 1736 | 1737 | (def array (dims (o default)) 1738 | (if (no dims) 1739 | default 1740 | `(lit arr ,@(nof (car dims) 1741 | (array (cdr dims) default))))) 1742 | 1743 | (vir arr (f args) 1744 | `(aref ,f ,@args)) 1745 | 1746 | (def aref (a|isa!arr n . ns) 1747 | (if (no ns) 1748 | (n (cddr a)) 1749 | (apply aref (n (cddr a)) ns))) 1750 | 1751 | (def table ((o kvs)) 1752 | `(lit tab ,@kvs)) 1753 | 1754 | (vir tab (f args) 1755 | `(tabref ,f ,@args)) 1756 | 1757 | (def tabref (tab key (o default)) 1758 | (aif (get key (cddr tab)) 1759 | (cdr it) 1760 | default)) 1761 | 1762 | (loc isa!tab (f args a s r m) 1763 | (let e `(list (tabloc ,f ,@(map [list 'quote _] args)) 'd) 1764 | (mev (cons (list e a) (cdr s)) r m))) 1765 | 1766 | (def tabloc (tab key) 1767 | (or (get key (cddr tab)) 1768 | (let kv (cons key nil) 1769 | (push kv (cddr tab)) 1770 | kv))) 1771 | 1772 | (def tabrem (tab key (o f =)) 1773 | (clean [caris _ key f] (cddr tab))) 1774 | 1775 | (set templates (table)) 1776 | 1777 | (mac tem (name . fields) 1778 | `(set (templates ',name) 1779 | (list ,@(map (fn ((k v)) `(cons ',k (fn () ,v))) 1780 | (hug fields))))) 1781 | 1782 | (mac make (name . args) 1783 | `(inst ',name 1784 | (list ,@(map (fn ((k v)) `(cons ',k ,v)) 1785 | (hug args))))) 1786 | 1787 | (def inst (name kvs) 1788 | (aif templates.name 1789 | (table (map (fn ((k . f)) 1790 | (cons k 1791 | (aif (get k kvs) (cdr it) (f)))) 1792 | it)) 1793 | (err 'no-template))) 1794 | 1795 | (def readas (name (o s ins)) 1796 | (withs (eof (join) 1797 | v (read s 10 eof)) 1798 | (if (id v eof) nil 1799 | (isa!tab v) (inst name (cddr v)) 1800 | (err 'inst-nontable)))) 1801 | -------------------------------------------------------------------------------- /resources/bel.ebnf: -------------------------------------------------------------------------------- 1 | sexp = string | list | abbrev_fn | quote | backquote | comma | splice | char | symbol | dot | number | comp_sym 2 | list = lparen sexp? ( sexp)* rparen 3 | abbrev_fn = <'['> sexp? ( sexp)* <']'> 4 | comp_sym = symbol (comp_id* symbol)* | (comp_id* symbol) (comp_id* symbol)* 5 | comp_id = (':' | '!' | '.' | '~' | ':' | '|') 6 | = <'('> 7 | = <')'> 8 | string = <'"'> any_char* <'"'> 9 | char = <'\\'> name 10 | symbol = name 11 | dot = #'\.' 12 | quote = <'\''> sexp 13 | backquote = <'`'> sexp 14 | comma = <','> sexp 15 | splice = <',@'> sexp 16 | name = #'[a-zA-Z\-*+_=>\/<\^][a-zA-Z0-9\-*+_=>\/<\^\?]*' 17 | number = #'[+-]?[0-9][0-9]*[.]?[0-9]*' 18 | any_char = #'.' | space 19 | space = #'\s' 20 | whitespace = #'\s+' 21 | -------------------------------------------------------------------------------- /resources/core.bel: -------------------------------------------------------------------------------- 1 | ; Bel in Bel. 9 October 2019, 9:14 GMT 2 | 3 | ; stopa-edit 4 | ; Writing a poor man's def, to let PG's code run, 5 | ; before he defines it 6 | 7 | (set 8 | def 9 | (lit 10 | mac 11 | (lit 12 | clo nil (n p e) 13 | (join 'set 14 | (join 15 | n 16 | (join 17 | (join 18 | 'lit (join 'clo (join nil (join p (join e nil))))) 19 | nil)))))) 20 | 21 | ; /stopa-edit 22 | 23 | (def no (x) 24 | (id x nil)) 25 | 26 | ; stopa-edit 27 | ; string is a separate type in this implementation 28 | 29 | (def atom (x) 30 | (if (no (id (type x) 'pair)) 31 | (if (no (id (type x) 'string)) t))) 32 | 33 | ; /stopa-edit 34 | 35 | (def all (f xs) 36 | (if (no xs) t 37 | (f (car xs)) (all f (cdr xs)) 38 | nil)) 39 | 40 | (def some (f xs) 41 | (if (no xs) nil 42 | (f (car xs)) xs 43 | (some f (cdr xs)))) 44 | 45 | (def reduce (f xs) 46 | (if (no (cdr xs)) 47 | (car xs) 48 | (f (car xs) (reduce f (cdr xs))))) 49 | 50 | (def cons args 51 | (reduce join args)) 52 | 53 | (def append args 54 | (if (no (cdr args)) (car args) 55 | (no (car args)) (apply append (cdr args)) 56 | (cons (car (car args)) 57 | (apply append (cdr (car args)) 58 | (cdr args))))) 59 | 60 | 61 | 62 | (def snoc args 63 | (append (car args) (cdr args))) 64 | 65 | (def list args 66 | (append args nil)) 67 | 68 | (def map (f . ls) 69 | (if (no ls) nil 70 | (some no ls) nil 71 | (no (cdr ls)) (cons (f (car (car ls))) 72 | (map f (cdr (car ls)))) 73 | (cons (apply f (map car ls)) 74 | (apply map f (map cdr ls))))) 75 | 76 | ; stopa-edit 77 | ; poor man's mac, to support mac until PG defines it 78 | 79 | (set 80 | mac 81 | (lit 82 | mac 83 | (lit 84 | clo nil (n p e) 85 | (join 'set 86 | (join 87 | n 88 | (join 89 | (join 90 | 'lit 91 | (join 92 | 'mac 93 | (join 94 | (join 95 | 'lit (join 'clo (join nil (join p (join e nil))))) 96 | nil))) 97 | nil)))))) 98 | 99 | ; /stopa-edit 100 | 101 | (mac fn (parms . body) 102 | (if (no (cdr body)) 103 | `(list 'lit 'clo scope ',parms ',(car body)) 104 | `(list 'lit 'clo scope ',parms '(do ,@body)))) 105 | 106 | (mac do args 107 | (reduce (fn (x y) 108 | (list (list 'fn (uvar) y) x)) 109 | args)) 110 | 111 | (mac let (parms val . body) 112 | `((fn (,parms) ,@body) ,val)) 113 | 114 | (mac macro args 115 | `(list 'lit 'mac (fn ,@args))) 116 | 117 | (mac def (n . rest) 118 | `(set ,n (fn ,@rest))) 119 | 120 | (mac mac (n . rest) 121 | `(set ,n (macro ,@rest))) 122 | 123 | (mac or args 124 | (if (no args) 125 | nil 126 | (let v (uvar) 127 | `(let ,v ,(car args) 128 | (if ,v ,v (or ,@(cdr args))))))) 129 | 130 | (mac and args 131 | (reduce (fn es (cons 'if es)) 132 | (or args '(t)))) 133 | 134 | (def = args 135 | (if (no (cdr args)) t 136 | (some atom args) (all [id _ (car args)] (cdr args)) 137 | (and (apply = (map car args)) 138 | (apply = (map cdr args))))) 139 | 140 | ; stopa-edit 141 | ; Added number + string as primitive types. Letting 142 | ; these seep in from Clojure 143 | 144 | (def symbol (x) (= (type x) 'symbol)) 145 | 146 | (def pair (x) (= (type x) 'pair)) 147 | 148 | (def char (x) (= (type x) 'char)) 149 | 150 | (def number (x) (= (type x) 'number)) 151 | 152 | (def string (x) (= (type x) 'string)) 153 | 154 | ; /stopa-edit 155 | 156 | (def proper (x) 157 | (or (no x) 158 | (and (pair x) (proper (cdr x))))) 159 | 160 | (def mem (x ys (o f =)) 161 | (some [f _ x] ys)) 162 | 163 | (def in (x . ys) 164 | (mem x ys)) 165 | 166 | (def cadr (x) (car (cdr x))) 167 | 168 | (def cddr (x) (cdr (cdr x))) 169 | 170 | (def caddr (x) (car (cddr x))) 171 | 172 | (mac case (expr . args) 173 | (if (no (cdr args)) 174 | (car args) 175 | (let v (uvar) 176 | `(let ,v ,expr 177 | (if (= ,v ',(car args)) 178 | ,(cadr args) 179 | (case ,v ,@(cddr args))))))) 180 | 181 | (mac iflet (var . args) 182 | (if (no (cdr args)) 183 | (car args) 184 | (let v (uvar) 185 | `(let ,v ,(car args) 186 | (if ,v 187 | (let ,var ,v ,(cadr args)) 188 | (iflet ,var ,@(cddr args))))))) 189 | 190 | (mac aif args 191 | `(iflet it ,@args)) 192 | 193 | (def find (f xs) 194 | (aif (some f xs) (car it))) 195 | 196 | (def begins (xs pat (o f =)) 197 | (if (no pat) t 198 | (atom xs) nil 199 | (f (car xs) (car pat)) (begins (cdr xs) (cdr pat) f) 200 | nil)) 201 | 202 | (def caris (x y (o f =)) 203 | (begins x (list y) f)) 204 | 205 | (def hug (xs (o f list)) 206 | (if (no xs) nil 207 | (no (cdr xs)) (list (f (car xs))) 208 | (cons (f (car xs) (cadr xs)) 209 | (hug (cddr xs) f)))) 210 | 211 | (mac with (parms . body) 212 | (let ps (hug parms) 213 | `((fn ,(map car ps) ,@body) 214 | ,@(map cadr ps)))) 215 | 216 | (def keep (f xs) 217 | (if (no xs) nil 218 | (f (car xs)) (cons (car xs) (keep f (cdr xs))) 219 | (keep f (cdr xs)))) 220 | 221 | (def rem (x ys (o f =)) 222 | (keep [no (f _ x)] ys)) 223 | 224 | (def get (k kvs (o f =)) 225 | (find [f (car _) k] kvs)) 226 | 227 | (def put (k v kvs (o f =)) 228 | (cons (cons k v) 229 | (rem k kvs (fn (x y) (f (car x) y))))) 230 | 231 | (def rev (xs) 232 | (if (no xs) 233 | nil 234 | (snoc (rev (cdr xs)) (car xs)))) 235 | 236 | (def snap (xs ys (o acc)) 237 | (if (no xs) 238 | (list acc ys) 239 | (snap (cdr xs) (cdr ys) (snoc acc (car ys))))) 240 | 241 | (def udrop (xs ys) 242 | (cadr (snap xs ys))) 243 | 244 | (def idfn (x) 245 | x) 246 | 247 | (def is (x) 248 | [= _ x]) 249 | 250 | (mac eif (var (o expr) (o fail) (o ok)) 251 | (with (v (uvar) 252 | w (uvar) 253 | c (uvar)) 254 | `(let ,v (join) 255 | (let ,w (ccc (fn (,c) 256 | (dyn err [,c (cons ,v _)] ,expr))) 257 | (if (caris ,w ,v id) 258 | (let ,var (cdr ,w) ,fail) 259 | (let ,var ,w ,ok)))))) 260 | 261 | 262 | (mac onerr (e1 e2) 263 | (let v (uvar) 264 | `(eif ,v ,e2 ,e1 ,v))) 265 | 266 | (mac safe (expr) 267 | `(onerr nil ,expr)) 268 | 269 | (def literal (e) 270 | (or (in e t nil o apply) 271 | (in (type e) 'char 'stream) 272 | (caris e 'lit) 273 | (string e))) 274 | 275 | (def variable (e) 276 | (and (atom e) (no (literal e)))) 277 | 278 | (def isa (name) 279 | [begins _ `(lit ,name) id]) 280 | 281 | (def function (x) 282 | (find [(isa _) x] '(prim clo))) 283 | 284 | (def con (x) 285 | (fn args x)) 286 | 287 | (def compose fs 288 | (reduce (fn (f g) 289 | (fn args (f (apply g args)))) 290 | (or fs (list idfn)))) 291 | 292 | (def combine (op) 293 | (fn fs 294 | (reduce (fn (f g) 295 | (fn args 296 | (op (apply f args) (apply g args)))) 297 | (or fs (list (con (op))))))) 298 | 299 | (set cand (combine and) 300 | cor (combine or)) 301 | 302 | (def foldl (f base . args) 303 | (if (or (no args) (some no args)) 304 | base 305 | (apply foldl f 306 | (apply f (snoc (map car args) base)) 307 | (map cdr args)))) 308 | 309 | (def foldr (f base . args) 310 | (if (or (no args) (some no args)) 311 | base 312 | (apply f (snoc (map car args) 313 | (apply foldr f base (map cdr args)))))) 314 | 315 | (def of (f g) 316 | (fn args (apply f (map g args)))) 317 | 318 | (def upon args 319 | [apply _ args]) 320 | 321 | (def pairwise (f xs) 322 | (or (no (cdr xs)) 323 | (and (f (car xs) (cadr xs)) 324 | (pairwise f (cdr xs))))) 325 | 326 | (def fuse (f . args) 327 | (apply append (apply map f args))) 328 | 329 | (mac letu (v . body) 330 | (if ((cor variable atom) v) 331 | `(let ,v (uvar) ,@body) 332 | `(with ,(fuse [list _ '(uvar)] v) 333 | ,@body))) 334 | 335 | (mac pcase (expr . args) 336 | (if (no (cdr args)) 337 | (car args) 338 | (letu v 339 | `(let ,v ,expr 340 | (if (,(car args) ,v) 341 | ,(cadr args) 342 | (pcase ,v ,@(cddr args))))))) 343 | 344 | (def match (x pat) 345 | (if (= pat t) t 346 | (function pat) (pat x) 347 | (or (atom x) (atom pat)) (= x pat) 348 | (and (match (car x) (car pat)) 349 | (match (cdr x) (cdr pat))))) 350 | 351 | (def split (f xs (o acc)) 352 | (if ((cor atom f:car) xs) 353 | (list acc xs) 354 | (split f (cdr xs) (snoc acc (car xs))))) 355 | 356 | (mac when (expr . body) 357 | `(if ,expr (do ,@body))) 358 | 359 | (mac unless (expr . body) 360 | `(when (no ,expr) ,@body)) 361 | 362 | (def inc (n) (+ n 1)) 363 | 364 | (def dec (n) (- n 1)) 365 | 366 | (def pos (x ys (o f =)) 367 | (if (no ys) nil 368 | (f (car ys) x) 1 369 | (aif (pos x (cdr ys) f) (+ it 1)))) 370 | 371 | (def len (xs) 372 | (if (no xs) 0 (inc:len:cdr xs))) 373 | 374 | ; stopa-edit 375 | 376 | (def charn (c) 377 | (hash c)) 378 | 379 | ; stopa-edit 380 | 381 | (def < args 382 | (pairwise bin< args)) 383 | 384 | (def > args 385 | (apply < (rev args))) 386 | 387 | (def list< (x y) 388 | (if (no x) y 389 | (no y) nil 390 | (or (< (car x) (car y)) 391 | (and (= (car x) (car y)) 392 | (< (cdr x) (cdr y)))))) 393 | 394 | (def pint (n) 395 | (and (int n) (> n 0))) 396 | 397 | (def yc (f) 398 | ([_ _] [f (fn a (apply (_ _) a))])) 399 | 400 | (mac rfn (name . rest) 401 | `(yc (fn (,name) (fn ,@rest)))) 402 | 403 | (mac afn args 404 | `(rfn self ,@args)) 405 | 406 | (def wait (f) 407 | ((afn (v) (if v v (self (f)))) 408 | (f))) 409 | 410 | (def runs (f xs (o fon (and xs (f (car xs))))) 411 | (if (no xs) 412 | nil 413 | (let (as bs) (split (if fon ~f f) xs) 414 | (cons as (runs f bs (no fon)))))) 415 | 416 | (def whitec (c) 417 | (in c \space \n \tab \r)) 418 | 419 | (def tokens (xs (o break whitec)) 420 | (let f (if (function break) break (is break)) 421 | (keep ~f:car (runs f xs)))) 422 | 423 | (def dups (xs (o f =)) 424 | (if (no xs) nil 425 | (mem (car xs) (cdr xs) f) (cons (car xs) 426 | (dups (rem (car xs) (cdr xs) f) f)) 427 | (dups (cdr xs) f))) 428 | 429 | (set simple (cor atom number)) 430 | 431 | (mac do1 args 432 | (letu v 433 | `(let ,v ,(car args) 434 | ,@(cdr args) 435 | ,v))) 436 | 437 | (def gets (v kvs (o f =)) 438 | (find [f (cdr _) v] kvs)) 439 | 440 | (def consif (x y) 441 | (if x (cons x y) y)) 442 | 443 | (mac check (x f (o alt)) 444 | (letu v 445 | `(let ,v ,x 446 | (if (,f ,v) ,v ,alt)))) 447 | 448 | (mac withs (parms . body) 449 | (if (no parms) 450 | `(do ,@body) 451 | `(let ,(car parms) ,(cadr parms) 452 | (withs ,(cddr parms) ,@body)))) 453 | 454 | (mac bind (var expr . body) 455 | `(dyn ,var ,expr (do ,@body))) 456 | 457 | (mac atomic body 458 | `(bind lock t ,@body)) 459 | 460 | (def tail (f xs) 461 | (if (no xs) nil 462 | (f xs) xs 463 | (tail f (cdr xs)))) 464 | 465 | (set dock rev:cdr:rev) 466 | 467 | (def lastcdr (xs) 468 | (if (no (cdr xs)) 469 | xs 470 | (lastcdr (cdr xs)))) 471 | 472 | (set last car:lastcdr) 473 | 474 | (def newq () 475 | (list nil)) 476 | 477 | (def enq (x q) 478 | (atomic (xar q (snoc (car q) x))) 479 | q) 480 | 481 | (def deq (q) 482 | (atomic (do1 (car (car q)) 483 | (xar q (cdr (car q)))))) 484 | 485 | (mac zap (op place . args) 486 | (letu (vo vc vl va) 487 | `(atomic (with (,vo ,op 488 | (,vc ,vl) (where ,place) 489 | ,va (list ,@args)) 490 | (case ,vl 491 | a (xar ,vc (apply ,vo (car ,vc) ,va)) 492 | d (xdr ,vc (apply ,vo (cdr ,vc) ,va)) 493 | (err 'bad-place)))))) 494 | 495 | (mac ++ (place (o n 1)) 496 | `(zap + ,place ,n)) 497 | 498 | (mac -- (place (o n 1)) 499 | `(zap - ,place ,n)) 500 | 501 | (mac push (x place) 502 | (letu v 503 | `(let ,v ,x 504 | (zap [cons ,v _] ,place)))) 505 | 506 | (mac pull (x place . rest) 507 | (letu v 508 | `(let ,v ,x 509 | (zap [rem ,v _ ,@rest] ,place)))) 510 | 511 | (def drop (n xs) 512 | (if (= n 0) 513 | xs 514 | (drop (- n 1) (cdr xs)))) 515 | 516 | (def nth (n|pint xs|pair) 517 | (if (= n 1) 518 | (car xs) 519 | (nth (- n 1) (cdr xs)))) 520 | 521 | 522 | (def first (n xs) 523 | (if (or (= n 0) (no xs)) 524 | nil 525 | (cons (car xs) 526 | (first (- n 1) (cdr xs))))) 527 | 528 | (mac catch body 529 | (letu v 530 | `(ccc (fn (,v) (bind throw ,v ,@body))))) 531 | 532 | (def cut (xs (o start 1) (o end (len xs))) 533 | (first (- (+ end 1 (if (< end 0) (len xs) 0)) 534 | start) 535 | (drop (- start 1) xs))) 536 | 537 | (mac whenlet (var expr . body) 538 | `(iflet ,var ,expr (do ,@body))) 539 | 540 | (mac awhen args 541 | `(whenlet it ,@args)) 542 | 543 | (mac each (var expr . body) 544 | `(map (fn (,var) ,@body) ,expr)) 545 | 546 | (def flip (f) 547 | (fn args (apply f (rev args)))) 548 | 549 | (def part (f . args) 550 | (fn rest 551 | (apply f (append args rest)))) 552 | 553 | (def trap (f . args) 554 | (flip (apply part (flip f) (rev args)))) 555 | 556 | (def only (f) 557 | (fn args 558 | (if (car args) (apply f args)))) 559 | 560 | (def >= args 561 | (pairwise ~bin< args)) 562 | 563 | (def <= args 564 | (apply >= (rev args))) 565 | 566 | (mac whilet (var expr . body) 567 | (letu (vf vp) 568 | `((rfn ,vf (,vp) 569 | (whenlet ,var ,vp ,@body (,vf ,expr))) 570 | ,expr))) 571 | 572 | (mac loop (var init update test . body) 573 | (letu v 574 | `((rfn ,v (,var) 575 | (when ,test ,@body (,v ,update))) 576 | ,init))) 577 | 578 | (mac while (expr . body) 579 | (letu v 580 | `(loop ,v ,expr ,expr ,v ,@body))) 581 | 582 | (mac til (var expr test . body) 583 | `(loop ,var ,expr ,expr (no ,test) 584 | ,@body)) 585 | 586 | (mac for (var init max . body) 587 | (letu (vi vm) 588 | `(with (,vi ,init 589 | ,vm ,max) 590 | (loop ,var ,vi (+ ,var 1) (<= ,var ,vm) 591 | ,@body)))) 592 | 593 | (mac repeat (n . body) 594 | `(for ,(uvar) 1 ,n ,@body)) 595 | 596 | (mac poll (expr f) 597 | (letu (vr ve vf) 598 | `((rfn ,vr (,ve ,vf) 599 | (if (,vf ,ve) ,ve (,vr ,expr ,vf))) 600 | ,expr 601 | ,f))) 602 | 603 | (mac accum (var . body) 604 | (letu v 605 | `(withs (,v nil 606 | ,var [push _ ,v]) 607 | ,@body 608 | (rev ,v)))) 609 | 610 | (mac nof (n expr) 611 | (letu v 612 | `(accum ,v (repeat ,n (,v ,expr))))) 613 | 614 | (mac drain (expr (o f 'no)) 615 | (letu v 616 | `(accum ,v 617 | (poll ,expr (cor ,f (compose no ,v)))))) 618 | 619 | (mac wipe args 620 | `(set ,@(fuse [list _ nil] args))) 621 | 622 | (mac pop (place) 623 | `(let (cell loc) (where ,place) 624 | (let xs ((case loc a car d cdr) cell) 625 | ((case loc a xar d xdr) cell (cdr xs)) 626 | (car xs)))) 627 | 628 | (mac clean (f place) 629 | (letu v 630 | `(let ,v (compose no ,f) 631 | (zap [keep ,v _] ,place)))) 632 | 633 | (mac swap places 634 | (let vs (map [nof 3 (uvar)] places) 635 | `(atomic (withs ,(fuse (fn (place (cell loc val)) 636 | (list (list cell loc) 637 | `(where ,place) 638 | val 639 | `((case ,loc a car d cdr) ,cell))) 640 | places 641 | vs) 642 | ,@(map (fn ((cellx locx valx) (celly locy valy)) 643 | `((case ,locx a xar d xdr) ,cellx ,valy)) 644 | vs 645 | (snoc (cdr vs) (car vs))))))) 646 | 647 | (def adjoin (x ys (o f =)) 648 | (if (mem x ys f) ys (cons x ys))) 649 | 650 | (mac pushnew (x place (o f '=)) 651 | (letu v 652 | `(let ,v ,x 653 | (zap [adjoin ,v _ ,f] ,place)))) 654 | 655 | (def dedup (xs (o f =)) 656 | (rev (foldl (trap adjoin f) nil xs))) 657 | 658 | (def insert (f x ys) 659 | (if (no ys) (list x) 660 | (f x (car ys)) (cons x ys) 661 | (cons (car ys) (insert f x (cdr ys))))) 662 | 663 | (def sort (f xs) 664 | (foldr (part insert f) nil (rev xs))) 665 | 666 | (set best car:sort) 667 | 668 | (def max args 669 | (best > args)) 670 | 671 | (def min args 672 | (best < args)) 673 | 674 | -------------------------------------------------------------------------------- /src/bel_clojure/core.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.core 2 | (:require 3 | [clojure.java.io :as io] 4 | [clojure.string :as cstring] 5 | [bel-clojure.evaluator :as e] 6 | [bel-clojure.reader :as r])) 7 | 8 | ;; --------- 9 | ;; Bootstrap 10 | 11 | (defn source-str->parts [source-str] 12 | (->> (cstring/split source-str #"\n") 13 | (partition-by cstring/blank?) 14 | (map (fn [xs] (cstring/join "\n" xs))) 15 | (remove (fn [s] (cstring/starts-with? s ";"))) 16 | (remove cstring/blank?))) 17 | 18 | (defn bootstrap-env [] 19 | (let [env (e/env)] 20 | (e/eval-all env (source-str->parts (slurp (io/resource "core.bel")))) 21 | env)) 22 | 23 | ;; ---- 24 | ;; REPL 25 | 26 | (defn read-form 27 | ([] (read-form [])) 28 | ([ret] 29 | (let [x (read-line) 30 | new-ret (conj ret x)] 31 | (try 32 | (let [v (r/parse (cstring/join "\n" new-ret))] 33 | (assert (not (:index v))) 34 | v) 35 | (catch Throwable _e 36 | (read-form new-ret)))))) 37 | 38 | (defn repl [env] 39 | (println 40 | (str "🦁 Welcome to Bel\n" 41 | " Write some code, and press enter\n" 42 | " (id t t)\n" 43 | " (cons 'a 'b '(c d e))\n" 44 | ">")) 45 | (loop [] 46 | (let [form (read-form)] 47 | (println "> " 48 | (r/bel->pretty 49 | (e/eval-single 50 | env form))) 51 | (recur)))) 52 | 53 | (defn -main [& _args] 54 | (println " Loading core.bel...") 55 | (repl (bootstrap-env))) 56 | -------------------------------------------------------------------------------- /src/bel_clojure/evaluator.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.evaluator 2 | (:refer-clojure :exclude [eval]) 3 | (:require 4 | [bel-clojure.model :as m] 5 | [bel-clojure.reader :as r])) 6 | 7 | ;; ---- 8 | ;; Misc 9 | 10 | (defn stack-pop [x] (list (peek x) (pop x))) 11 | 12 | (defn stack-pop-2 [x] 13 | (list (list (peek (pop x)) (peek x)) 14 | (pop (pop x)))) 15 | 16 | (defn stack-pop-until-breakpoint [breakpoint x] 17 | (loop [peeks () 18 | pops x] 19 | (cond 20 | (empty? pops) (list peeks pops) 21 | (= (peek pops) breakpoint) (list peeks (pop pops)) 22 | :else 23 | (recur 24 | (conj peeks (peek pops)) 25 | (pop pops))))) 26 | 27 | ;; ------ 28 | ;; where 29 | 30 | (defn in-where? [es] 31 | (= (second (peek es)) [:where])) 32 | 33 | (defn b-where [es rs env x] 34 | [(conj es 35 | [env [:where]] 36 | [env x]) 37 | rs]) 38 | 39 | ;; -------- 40 | ;; variable 41 | 42 | (defn env-pair [sym v] 43 | (assert (m/bel-variable? sym) 44 | (format "expected left-side to be a variable= %s" sym)) 45 | (m/p sym v)) 46 | 47 | (defn not-bel-nil [x] 48 | (when-not (= x m/bel-nil) x)) 49 | 50 | (defn v-pair [{:keys [dyn scope globe]} form] 51 | (let [v (->> [dyn scope globe] 52 | (some (fn [x] 53 | (not-bel-nil (m/map-get x form)))))] 54 | (assert v 55 | (format "expected value for variable = %s" form)) 56 | v)) 57 | 58 | (defn eval-variable [es rs env form] 59 | (cond 60 | (= m/bel-globe form) 61 | [es (conj rs (:globe env))] 62 | 63 | (= m/bel-scope form) 64 | [es (conj rs (:scope env))] 65 | 66 | :else 67 | (let [vp (v-pair env form)] 68 | (if (in-where? es) 69 | [(pop es) 70 | (conj rs 71 | (m/p vp (m/p m/bel-d m/bel-nil)))] 72 | [es 73 | (conj rs (m/cdr vp))])))) 74 | 75 | ;; ---------- 76 | ;; thread 77 | 78 | (declare env) 79 | 80 | (defn b-thread [es rs {:keys [globe] :as env1} form] 81 | [(conj 82 | es 83 | [env1 [:start-thread (assoc (env) :globe globe) form]]) 84 | rs]) 85 | 86 | ;; ---- 87 | ;; dyn 88 | 89 | (defn eval-dyn-2 [es rs env [_ variable after]] 90 | (let [[ev rest-rs] (stack-pop rs) 91 | {:keys [dyn]} env] 92 | [(conj es 93 | [(assoc env 94 | :dyn 95 | (m/map-assoc dyn variable (env-pair variable ev))) 96 | after]) 97 | rest-rs])) 98 | 99 | (defn b-dyn [es rs env variable arg after] 100 | [(conj 101 | es 102 | [env [:dyn-2 variable after]] 103 | [env arg]) 104 | rs]) 105 | 106 | ;; ---- 107 | ;; ccc 108 | 109 | (defn eval-cont [_es _rs _env litv args-head] 110 | (let [[f] litv 111 | [es rs] (f)] 112 | [es (conj rs (m/car args-head))])) 113 | 114 | (defn eval-ccc-2 [es rs env _form] 115 | (let [[f-evaled rest-rs] (stack-pop rs)] 116 | [(conj 117 | es 118 | [env 119 | (m/p 120 | f-evaled 121 | (m/p 122 | (m/seq->p [m/bel-lit m/bel-cont (fn [] [es rest-rs])]) 123 | m/bel-nil))]) 124 | rest-rs])) 125 | 126 | (defn b-ccc [es rs env f] 127 | [(conj 128 | es 129 | [env [:ccc-2]] 130 | [env f]) 131 | rs]) 132 | 133 | ;; --- 134 | ;; err 135 | 136 | (defn b-err [_es _rs _env e] 137 | [[] [(m/p m/bel-lit (m/p 'error (m/p e m/bel-nil) ))]]) 138 | 139 | ;; ----- 140 | ;; debug 141 | 142 | (defn b-debug 143 | [x] (println "[DEBUG] " (r/bel->pretty x))) 144 | 145 | ;; ---- 146 | ;; uvar 147 | 148 | (def b-uvar gensym) 149 | 150 | ;; ---- 151 | ;; bin< 152 | 153 | (declare bel-compare) 154 | 155 | (defn base-compare 156 | [a b] (compare a b)) 157 | 158 | (defn list-compare 159 | [a b] 160 | (let [c1 (m/car a) 161 | c2 (m/car b) 162 | v (bel-compare c1 c2)] 163 | (cond 164 | (not= 0 v) v 165 | (not= m/bel-nil (m/cdr a)) (bel-compare (m/cdr a) (m/cdr b)) 166 | :else v))) 167 | 168 | (defn bel-compare [a b] 169 | (let [f (condp = (m/type a) 170 | 'pair list-compare 171 | base-compare)] 172 | (f a b))) 173 | 174 | (defn b-bin< [& xs] 175 | (m/clj-bool->bel (neg? (apply bel-compare xs)))) 176 | 177 | ;; ---- 178 | ;; math 179 | 180 | (defn wrap-math-fn [f] 181 | (fn [& xs] 182 | (let [v (apply f xs)] 183 | (if 184 | (number? v) v 185 | (m/clj-bool->bel v))))) 186 | 187 | (def math-name->fn 188 | {"+" (wrap-math-fn +) 189 | "-" (wrap-math-fn -) 190 | "*" (wrap-math-fn *) 191 | "/" (wrap-math-fn /) 192 | "int" (wrap-math-fn int?) 193 | "num<" (wrap-math-fn <) 194 | "abs" (wrap-math-fn #(Math/abs %)) 195 | "hash" (wrap-math-fn #(.hashCode %))}) 196 | 197 | ;; ------------ 198 | ;; simple-prims 199 | 200 | (def prim-name->fn 201 | (merge 202 | {"id" #'m/id 203 | "car" #'m/car 204 | "cdr" #'m/cdr 205 | "join" #'m/join 206 | "type" #'m/type 207 | "xar" #'m/xar 208 | "xdr" #'m/xdr 209 | "sym" #'m/sym 210 | "nom" #'m/nom 211 | "coin" #'m/coin 212 | "debug" #'b-debug 213 | "uvar" #'b-uvar 214 | "bin<" #'b-bin< 215 | "map-assoc" #'m/map-assoc} 216 | math-name->fn)) 217 | 218 | ;; ------------- 219 | ;; special-prims 220 | 221 | (def special-prim-name->fn 222 | {"dyn" #'b-dyn 223 | "ccc" #'b-ccc 224 | "where" #'b-where 225 | "err" #'b-err 226 | "thread" #'b-thread}) 227 | 228 | ;; --- 229 | ;; Env 230 | 231 | (defn bel-globe [] 232 | (let [m (m/mut-map)] 233 | (->> (merge prim-name->fn special-prim-name->fn) 234 | (map (fn [[k]] 235 | (let [sym-k (symbol (name k))] 236 | (m/map-put 237 | m 238 | sym-k 239 | (m/p 240 | sym-k 241 | (m/seq->p [m/bel-lit m/bel-prim sym-k])))))) 242 | doall) 243 | m)) 244 | 245 | (defn env 246 | ([] (env (bel-globe))) 247 | ([g] 248 | {:globe g 249 | :scope m/bel-nil 250 | :dyn m/bel-nil})) 251 | 252 | ;; ------------ 253 | ;; eval-if 254 | 255 | (defn eval-if-2 [es rs env [_ [consequent-form r]]] 256 | (let [[evaled-test-form rest-rs] (stack-pop rs)] 257 | [(conj es 258 | (cond 259 | (not= m/bel-nil evaled-test-form) 260 | [env consequent-form] 261 | 262 | (= m/bel-nil r) 263 | [env r] 264 | 265 | (= m/bel-nil (m/cdr r)) 266 | [env (m/car r)] 267 | :else 268 | [env 269 | (m/p m/bel-if r)])) 270 | rest-rs])) 271 | 272 | (defn eval-if-1 [es rs env [test-form r]] 273 | [(conj es 274 | [env [:if-2 r]] 275 | [env test-form]) 276 | rs]) 277 | 278 | ;; ------------ 279 | ;; eval-set 280 | 281 | (defn eval-set-2 [es rs {:keys [globe] :as _env} form] 282 | (let [[_ sym] form 283 | [evaled-v rest-rs] (stack-pop rs)] 284 | (m/map-put 285 | globe 286 | sym 287 | (env-pair sym evaled-v)) 288 | [es rest-rs])) 289 | 290 | (defn eval-set-1 [es rs env form] 291 | (let [[sym after-sym] form 292 | _ (assert (not= m/bel-nil after-sym) 293 | "Set sym needs a value") 294 | [v after-v] after-sym 295 | es' (if (not= after-v m/bel-nil) 296 | (conj es [env (m/p m/bel-set after-v)]) 297 | es)] 298 | [(conj es' 299 | [env [:set-2 sym]] 300 | [env v]) 301 | rs])) 302 | 303 | ;; eval-application 304 | ;; -------------------- 305 | 306 | (defn lit-type [[_lit [t]]] t) 307 | 308 | (defn lit-v [[_lit [_t v]]] v) 309 | 310 | (defn assert-lit [[lit :as form]] 311 | (assert (= m/bel-lit lit) 312 | (format 313 | "expected lit expression got form = %s" form)) 314 | form) 315 | 316 | ;; ------------- 317 | ;; eval-prim 318 | 319 | (defn bel-nil-args [f args] 320 | (let [arglist (->> f meta :arglists first) 321 | niled-args (if arglist 322 | (map-indexed (fn [i _] (nth args i m/bel-nil)) arglist) 323 | args)] 324 | niled-args)) 325 | 326 | (defn eval-prim-simple [es rs env [_ n simple-f]] 327 | (let [[evaled-args rest-rs] (stack-pop rs) 328 | args (m/p->seq evaled-args)] 329 | (try 330 | (if (in-where? es) 331 | [(pop es) 332 | (conj rs 333 | (m/p 334 | (m/car evaled-args) 335 | (m/p 336 | (condp = n 337 | "car" m/bel-a 338 | "cdr" m/bel-d 339 | (throw (Exception. "unexpected use of where"))) 340 | m/bel-nil)))] 341 | 342 | [es 343 | (conj rest-rs 344 | (apply simple-f 345 | (bel-nil-args simple-f args)))]) 346 | (catch Throwable e 347 | [(conj es [env (m/p 348 | m/bel-err-sym 349 | (m/p e m/bel-nil))]) 350 | rest-rs])))) 351 | 352 | (defn eval-prim [es rs env litv args-head] 353 | (let [n (name (m/car litv)) 354 | simple-f (prim-name->fn n) 355 | special-f (special-prim-name->fn n)] 356 | (if simple-f 357 | [(conj es 358 | [env [:eval-prim-simple n simple-f]] 359 | [env [:eval-many-1 args-head]]) 360 | rs] 361 | (apply special-f 362 | (bel-nil-args 363 | special-f 364 | (concat [es rs env] 365 | (m/p->seq args-head))))))) 366 | 367 | ;; ----------- 368 | ;; assign-vars 369 | 370 | (defn assign-vars-typecheck-2 [es rs env [_ variable arg]] 371 | (let [[check rest-rs] (stack-pop rs)] 372 | (if (= m/bel-nil check) 373 | [(conj es 374 | [env (m/p 375 | m/bel-err-sym 376 | (m/p (m/quoted-p 'mistype) 377 | m/bel-nil))]) 378 | rs] 379 | [(conj es 380 | [env 381 | [:assign-vars-1 382 | (m/bel-typecheck-var variable) 383 | arg]]) 384 | rest-rs]))) 385 | 386 | (defn assign-vars-typecheck-1 [es rs env [_ variable arg]] 387 | (let [[evaled-f rest-rs] (stack-pop rs)] 388 | [(conj es 389 | [env [:assign-vars-typecheck-2 variable arg]] 390 | [env (m/p 391 | evaled-f 392 | (m/p (m/quoted-p arg) 393 | m/bel-nil))]) 394 | rest-rs])) 395 | 396 | (defn assign-vars-optional-arg [es rs env [_ variable]] 397 | (let [[arg-evaled rest-rs] (stack-pop rs)] 398 | [(conj es 399 | [env [:assign-vars-1 variable arg-evaled]]) 400 | rest-rs])) 401 | 402 | (defn assign-vars-rest [es rs env [_ var-head arg-head]] 403 | (let [[scope rest-rs] (stack-pop rs)] 404 | [(conj es 405 | [(assoc env :scope scope) 406 | [:assign-vars-1 var-head arg-head]]) 407 | rest-rs])) 408 | 409 | (defn assign-vars-1 [es rs {:keys [scope] :as env} [_ var-head arg-head]] 410 | (cond 411 | (every? (partial = m/bel-nil) [var-head arg-head]) 412 | [es (conj rs scope)] 413 | 414 | (m/bel-variable? var-head) 415 | [es (conj rs 416 | (m/map-assoc 417 | scope 418 | var-head 419 | (env-pair 420 | var-head 421 | arg-head)))] 422 | 423 | (m/bel-optional? var-head) 424 | (if (= m/bel-nil arg-head) 425 | [(conj es 426 | [env [:assign-vars-optional-arg 427 | (m/bel-optional-var var-head)]] 428 | [env (m/bel-optional-arg var-head)]) 429 | 430 | rs] 431 | [(conj es 432 | [env [:assign-vars-1 433 | (m/bel-optional-var var-head) arg-head]]) 434 | rs]) 435 | (m/bel-typecheck? var-head) 436 | [(conj es 437 | [env [:assign-vars-typecheck-1 var-head arg-head]] 438 | [env (m/bel-typecheck-f var-head)]) 439 | rs] 440 | :else 441 | [(conj es 442 | [env [:assign-vars-rest 443 | (m/cdr var-head) (m/cdr arg-head)]] 444 | [env [:assign-vars-1 445 | (m/car var-head) (m/car arg-head)]]) 446 | rs])) 447 | 448 | ;; ------------ 449 | ;; eval-clo 450 | 451 | (defn eval-clo-2 [es rs env [_ body-head]] 452 | (let [[scope rest-rs] (stack-pop rs)] 453 | [(conj es 454 | [(assoc env :scope scope) body-head]) 455 | rest-rs])) 456 | 457 | (defn clo-expression-stack [env litv args-head] 458 | (let [[scope [args-sym-head [body-head]]] litv] 459 | [[env [:eval-clo-2 body-head]] 460 | [(assoc env :scope scope) 461 | [:assign-vars-1 args-sym-head args-head]]])) 462 | 463 | (defn eval-clo [es rs env litv args-head] 464 | [(apply conj (concat [es] (clo-expression-stack env litv args-head))) 465 | rs]) 466 | 467 | ;; ------------ 468 | ;; eval-mac 469 | 470 | (defn eval-mac-2 [es rs env _form] 471 | (let [[code rest-rs] (stack-pop rs)] 472 | [(conj es [env code]) 473 | rest-rs])) 474 | 475 | (defn eval-mac-1 [es rs env litv args-head] 476 | (let [[[_ [_ clo]]] litv] 477 | [(apply conj 478 | (concat [es 479 | [env [:eval-mac-2]]] 480 | (clo-expression-stack env clo args-head))) 481 | rs])) 482 | 483 | ;; ------------ 484 | ;; eval-lit 485 | 486 | (defn eval-lit-1 [es rs env [_ evaled-lit]] 487 | (let [[args-head rest-rs] (stack-pop rs) 488 | litv (lit-v evaled-lit)] 489 | (condp = (lit-type evaled-lit) 490 | m/bel-prim 491 | (eval-prim es rest-rs env litv args-head) 492 | m/bel-clo 493 | (eval-clo es rest-rs env litv args-head) 494 | m/bel-mac 495 | (eval-mac-1 es rest-rs env litv args-head) 496 | m/bel-cont 497 | (eval-cont es rest-rs env litv args-head)))) 498 | 499 | ;; -------------- 500 | ;; eval-many 501 | 502 | (defn eval-many-2 [es rs _env _form] 503 | (let [[top-ps rest-rs] (stack-pop-until-breakpoint :eval-many-breakpoint rs) 504 | evaled-pairs (m/seq->p (reverse top-ps))] 505 | [es (conj rest-rs evaled-pairs)])) 506 | 507 | (defn eval-many-1 [es rs env [_ args-head]] 508 | (let [pairs-to-eval (m/p->seq args-head)] 509 | [(apply 510 | conj 511 | (concat 512 | [es [env [:eval-many-2]]] 513 | (map (fn [p] [env p]) pairs-to-eval))) 514 | (conj rs :eval-many-breakpoint)])) 515 | 516 | ;; -------------------- 517 | ;; eval-application 518 | 519 | (defn eval-application-2 [es rs env [_ args-head]] 520 | (let [[evaled rest-rs] (stack-pop rs)] 521 | (if (m/number? evaled) 522 | [(conj es 523 | [env [:eval-lit-1 (m/cdr (v-pair env 'nth))]] 524 | [env [:eval-many-1 (m/p evaled args-head)]]) 525 | rest-rs] 526 | (let [evaled-lit (assert-lit evaled) 527 | es' (conj es [env [:eval-lit-1 evaled-lit]])] 528 | (if (#{m/bel-mac m/bel-prim} 529 | (lit-type evaled-lit)) 530 | [es' (conj rest-rs args-head)] 531 | [(conj es' 532 | [env [:eval-many-1 args-head]]) 533 | rest-rs]))))) 534 | 535 | (defn eval-application-1 [es rs env [f args-head :as _form]] 536 | [(conj es 537 | [env [:application-2 args-head]] 538 | [env f]) 539 | rs]) 540 | 541 | ;; eval-apply 542 | ;; ------------- 543 | 544 | (defn apply-head->args-head [x] 545 | (let [xs (m/p->seq x) 546 | but-last (drop-last xs) 547 | l (last xs) 548 | ls (if (m/pair? l) 549 | (m/p->seq l) 550 | [l])] 551 | (->> (concat but-last ls) 552 | (map m/quoted-p) 553 | m/seq->p))) 554 | 555 | (defn eval-apply-2 [es rs env [_ f]] 556 | (let [[evaled-apply-head rest-rs] (stack-pop rs)] 557 | [(conj 558 | es 559 | [env (m/p 560 | f (apply-head->args-head evaled-apply-head))]) 561 | rest-rs])) 562 | 563 | (defn eval-apply-1 [es rs env [f apply-head :as _form]] 564 | [(conj 565 | es 566 | [env [:eval-apply-2 f]] 567 | [env [:eval-many-1 apply-head]]) 568 | rs]) 569 | 570 | ;; ------------- 571 | ;; eval-pair 572 | 573 | (defn eval-pair [es rs env [l r :as form]] 574 | (cond 575 | (= m/bel-quote l) [es (conj rs (m/car r))] 576 | (= m/bel-set l) (eval-set-1 es rs env r) 577 | (= m/bel-if l) (eval-if-1 es rs env r) 578 | (= m/bel-apply l) (eval-apply-1 es rs env r) 579 | :else (eval-application-1 es rs env form))) 580 | 581 | ;; ------------------ 582 | ;; eval-backquote 583 | 584 | (defn eval-bq-comma-1 [es rs _env _form] 585 | (let [[[r-evaled h-evaled] rest-rs] (stack-pop-2 rs)] 586 | [es 587 | (conj 588 | rest-rs 589 | (m/p 590 | h-evaled 591 | r-evaled))])) 592 | 593 | (defn eval-bq-splice-1 [es rs _env _form] 594 | (let [[[r-evaled h-evaled] rest-rs] (stack-pop-2 rs)] 595 | [es 596 | (conj 597 | rest-rs 598 | (m/p-append 599 | h-evaled 600 | r-evaled))])) 601 | 602 | (defn eval-bq-pair-1 [es rs _env _form] 603 | (let [[[r-evaled h-evaled] rest-rs] (stack-pop-2 rs)] 604 | [es 605 | (conj 606 | rest-rs 607 | (m/p 608 | h-evaled 609 | r-evaled))])) 610 | 611 | (defn eval-bq-rest-1 [es rs _env [_ h]] 612 | (let [[r-evaled rest-rs] (stack-pop rs)] 613 | [es 614 | (conj 615 | rest-rs 616 | (m/p 617 | h 618 | r-evaled))])) 619 | 620 | (defn eval-backquote [es rs env [_ form]] 621 | (let [t (m/type form)] 622 | (cond 623 | (= t 'comma) 624 | [(conj es [env (second form)]) 625 | rs] 626 | 627 | (not= t 'pair) 628 | [es (conj rs form)] 629 | 630 | :else 631 | (let [[h r] form 632 | h-t (m/type h)] 633 | (cond 634 | (= h-t 'comma) 635 | [(conj 636 | es 637 | [env [:eval-bq-comma-1]] 638 | [env (second h)] 639 | [env [:backquote r]]) 640 | rs] 641 | (= h-t 'splice) 642 | [(conj 643 | es 644 | [env [:eval-bq-splice-1]] 645 | [env (second h)] 646 | [env [:backquote r]]) 647 | rs] 648 | (= h-t 'pair) 649 | [(conj es 650 | [env [:eval-bq-pair-1]] 651 | [env [:backquote h]] 652 | [env [:backquote r]]) 653 | rs] 654 | :else 655 | [(conj es 656 | [env [:eval-bq-rest-1 h]] 657 | [env [:backquote r]]) 658 | rs]))))) 659 | 660 | ;; -------- 661 | ;; eval 662 | 663 | (defn literal? [form] 664 | (or (#{'clj-err 'char 'number} (m/type-nilable form)) 665 | (#{m/bel-nil m/bel-t m/bel-o m/bel-apply} form) 666 | (and (m/pair? form) (#{m/bel-lit} (m/car form))) 667 | (m/string? form))) 668 | 669 | (def step->fn 670 | {:set-2 eval-set-2 671 | :if-2 eval-if-2 672 | :application-2 eval-application-2 673 | :eval-many-1 eval-many-1 674 | :eval-many-2 eval-many-2 675 | :eval-lit-1 eval-lit-1 676 | :eval-prim-simple eval-prim-simple 677 | :eval-mac-2 eval-mac-2 678 | :assign-vars-1 assign-vars-1 679 | :assign-vars-optional-arg assign-vars-optional-arg 680 | :assign-vars-typecheck-1 assign-vars-typecheck-1 681 | :assign-vars-typecheck-2 assign-vars-typecheck-2 682 | :assign-vars-rest assign-vars-rest 683 | :eval-clo-2 eval-clo-2 684 | :dyn-2 eval-dyn-2 685 | :ccc-2 eval-ccc-2 686 | :backquote eval-backquote 687 | :eval-bq-comma-1 eval-bq-comma-1 688 | :eval-bq-splice-1 eval-bq-splice-1 689 | :eval-bq-pair-1 eval-bq-pair-1 690 | :eval-bq-rest-1 eval-bq-rest-1 691 | :eval-apply-2 eval-apply-2}) 692 | 693 | (defn eval-step [es rs] 694 | (let [[top rest-es] (stack-pop es) 695 | [env form] top] 696 | (cond 697 | (literal? form) 698 | [rest-es (conj rs form)] 699 | 700 | (m/bel-variable? form) 701 | (eval-variable rest-es rs env form) 702 | 703 | (m/pair? form) 704 | (eval-pair rest-es rs env form) 705 | 706 | :else 707 | (let [f (step->fn (first form))] 708 | (f rest-es rs env form))))) 709 | 710 | (defn debug-loop [tid es rs] 711 | (println "---start--") 712 | (println "tid:" tid) 713 | (println "in:") 714 | (doall (map (comp println r/bel->pretty second) es)) 715 | (println "out:") 716 | (doall (map println rs)) 717 | (println "---end---")) 718 | 719 | (defn start-thread-command? [form] 720 | (and (seqable? form) (= :start-thread (first form)))) 721 | 722 | (defn start-thread-command->thread [[_ env form]] 723 | [(gensym) (list [env form]) ()]) 724 | 725 | (defn locking? [es] 726 | (let [lock (some-> es peek first :dyn (get 'lock))] 727 | (and lock (not= lock m/bel-nil)))) 728 | 729 | (defn eval [threads] 730 | (loop [threads threads] 731 | (let [[top-thread & rest-threads] threads 732 | [tid es rs] top-thread 733 | [_ top-form] (peek es)] 734 | (cond 735 | (empty? es) 736 | (if (empty? rest-threads) 737 | (or (peek rs) m/bel-nil) 738 | (recur rest-threads)) 739 | 740 | (start-thread-command? top-form) 741 | (recur 742 | (into [(start-thread-command->thread top-form) 743 | [tid (pop es) rs]] 744 | rest-threads)) 745 | :else 746 | (let [[es' rs'] (eval-step es rs) 747 | thread' [tid es' rs']] 748 | (recur 749 | (if (locking? es') 750 | (into [thread'] rest-threads) 751 | (into (vec rest-threads) [thread'])))))))) 752 | 753 | (defn eval-single [env form] 754 | (eval [[(gensym) (list [env form]) ()]])) 755 | 756 | (defn eval-all 757 | [env strs] 758 | (mapv (fn [s] 759 | (eval-single env (r/parse s))) strs)) 760 | -------------------------------------------------------------------------------- /src/bel_clojure/model.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.model 2 | (:refer-clojure :rename {type clj-type 3 | symbol? clj-symbol? 4 | string? clj-string? 5 | char? clj-char? 6 | number? clj-number?}) 7 | (:import 8 | (java.util ArrayList))) 9 | 10 | ;; ---- 11 | ;; Misc 12 | 13 | (defn first-and-only [xs msg] 14 | (assert (= (count xs) 1) msg) 15 | (first xs)) 16 | 17 | ;; ------------- 18 | ;; Primitive Types 19 | 20 | (def string? clj-string?) 21 | (def char? clj-char?) 22 | (def symbol? clj-symbol?) 23 | (def number? clj-number?) 24 | (def pair? (comp (partial = java.util.ArrayList) clj-type)) 25 | (def mut-map? (comp (partial = java.util.HashMap) clj-type)) 26 | (def imm-map? (comp (partial = clojure.lang.PersistentArrayMap) clj-type)) 27 | (def clj-err? (partial instance? Throwable)) 28 | 29 | (defn type-nilable [x] 30 | (cond 31 | (symbol? x) 'symbol 32 | (string? x) 'string 33 | (char? x) 'char 34 | (number? x) 'number 35 | (pair? x) 'pair 36 | (mut-map? x) 'mut-map 37 | (imm-map? x) 'imm-map 38 | (clj-err? x) 'clj-err 39 | :else 40 | (let [v (and (seqable? x) (first x))] 41 | (when (#{:splice :comma :backquote} v) 42 | (symbol (name v)))))) 43 | 44 | (defn type [x] 45 | (let [v (type-nilable x)] 46 | (assert v (format "Unsupported type for form = %s" x)) 47 | v)) 48 | 49 | ;; --------- 50 | ;; Pair Cons 51 | 52 | (defn p 53 | ([a b] 54 | (ArrayList. [a b]))) 55 | 56 | ;; --------- 57 | ;; Constants 58 | 59 | (def bel-quote 'quote) 60 | (def bel-nil (symbol "nil")) 61 | (def bel-t 't) 62 | (def bel-err-sym 'err) 63 | (def bel-dot [:dot "."]) 64 | (def bel-lit 'lit) 65 | (def bel-prim 'prim) 66 | (def bel-o 'o) 67 | (def bel-a 'a) 68 | (def bel-d 'd) 69 | (def bel-apply 'apply) 70 | (def bel-set 'set) 71 | (def bel-clo 'clo) 72 | (def bel-mac 'mac) 73 | (def bel-globe 'globe) 74 | (def bel-scope 'scope) 75 | (def bel-if 'if) 76 | (def bel-cont 'cont) 77 | 78 | ;; ------------- 79 | ;; Pair Helpers 80 | 81 | (defn quoted-p [a] 82 | (p bel-quote (p a bel-nil))) 83 | 84 | (defn seq->p 85 | [xs] 86 | (let [[x n & after-n] xs 87 | after-x (rest xs)] 88 | (if (empty? xs) 89 | bel-nil 90 | (p 91 | x 92 | (if (= bel-dot n) 93 | (first-and-only after-n "dotted list _must_ have 1 exp after the dot") 94 | (seq->p after-x)))))) 95 | 96 | (defn id [a b] 97 | (let [id-f (if (pair? a) identical? =)] 98 | (if (id-f a b) bel-t bel-nil))) 99 | 100 | (defn join [a b] 101 | (p a 102 | (if (string? b) (seq->p b) b))) 103 | 104 | (defn car [form] 105 | (cond 106 | (= bel-nil form) form 107 | 108 | (string? form) (first form) 109 | 110 | (not (pair? form)) 111 | (throw (Exception. (format "expected pair, got = %s" form))) 112 | 113 | :else 114 | (first form))) 115 | 116 | (defn cdr [form] 117 | (cond 118 | (= bel-nil form) form 119 | 120 | (string? form) (seq->p (rest form)) 121 | 122 | (not (pair? form)) 123 | (throw (Exception. (format "expected pair, got = %s" form))) 124 | 125 | :else 126 | (last form))) 127 | 128 | (defn p->seq [form] 129 | (if (= bel-nil form) 130 | () 131 | (cons 132 | (car form) 133 | (let [r (cdr form)] 134 | (cond 135 | (pair? r) (p->seq r) 136 | (= bel-nil r) [] 137 | :else [r]))))) 138 | 139 | (defn xar [form y] 140 | (.set form 0 y) 141 | form) 142 | 143 | (defn xdr [form y] 144 | (.set form 1 y) 145 | form) 146 | 147 | (def sym symbol) 148 | 149 | (def nom name) 150 | 151 | (defn coin [] (rand-nth [bel-t bel-nil])) 152 | 153 | (defn p-append [a b] 154 | (cond 155 | (= bel-nil a) b 156 | (= bel-nil (cdr a)) (p (car a) b) 157 | :else 158 | (p 159 | (car a) 160 | (p-append (cdr a) b)))) 161 | 162 | ;; --------- 163 | ;; Variable 164 | 165 | (def bel-variable? symbol?) 166 | 167 | ;; --------- 168 | ;; Optional 169 | 170 | (defn bel-optional? [[h]] 171 | (= bel-o h)) 172 | 173 | (defn bel-optional-var [[_h [variable]]] variable) 174 | 175 | (defn bel-optional-arg [[_h [_variable r]]] (car r)) 176 | 177 | ;; --------- 178 | ;; Typecheck 179 | 180 | (defn bel-typecheck? [[h]] 181 | (= bel-t h)) 182 | 183 | (defn bel-typecheck-var [[_h [variable]]] variable) 184 | 185 | (defn bel-typecheck-f [[_h [_variable r]]] (car r)) 186 | 187 | ;; ------- 188 | ;; Interop 189 | 190 | (defn clj-bool->bel [x] (if x bel-t bel-nil)) 191 | 192 | ;; ---- 193 | ;; Maps 194 | 195 | (defn map-get [m k] 196 | (if (= m bel-nil) 197 | bel-nil 198 | (or (.get m k) bel-nil))) 199 | 200 | (defn map-assoc [m k v] 201 | (let [m' (if (= bel-nil m) {} m)] 202 | (assoc m' k v))) 203 | 204 | (defn map-dissoc [m k] 205 | (if (= bel-nil m) bel-nil 206 | (let [m' (dissoc m k)] 207 | (if (empty? m') bel-nil m')))) 208 | 209 | (defn mut-map [] 210 | (java.util.HashMap.)) 211 | 212 | (defn map-put [m k v] 213 | (.put m k v)) 214 | 215 | (defn map-delete [m k] 216 | (.remove m k)) 217 | -------------------------------------------------------------------------------- /src/bel_clojure/reader.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.reader 2 | (:require 3 | [clojure.java.io :as io] 4 | [instaparse.core :as insta] 5 | [clojure.walk :as walk] 6 | [clojure.string :as cstring] 7 | [clojure.edn :as edn] 8 | [bel-clojure.model :as m])) 9 | 10 | (defn form-transform 11 | [k f] 12 | (fn [x] 13 | (if (and 14 | (coll? x) 15 | (= (first x) k)) 16 | (f x) 17 | x))) 18 | 19 | ;; ------- 20 | ;; unwrap 21 | 22 | (def unwrap-sexp (form-transform :sexp second)) 23 | 24 | (def unwrap-space (form-transform :space second)) 25 | 26 | (def unwrap-name (form-transform :name second)) 27 | 28 | ;; ---- 29 | ;; list 30 | 31 | (def list->pair 32 | (form-transform 33 | :list 34 | (fn [[_t & children]] 35 | (m/seq->p children)))) 36 | 37 | ;; ------- 38 | ;; string 39 | 40 | (def transform-string 41 | (form-transform 42 | :string 43 | (fn [[_t & children]] 44 | (cstring/join (map second children))))) 45 | 46 | ;; ----- 47 | ;; quote 48 | 49 | (def quote->pair 50 | (form-transform :quote 51 | (fn [[_ exp]] 52 | (m/quoted-p exp)))) 53 | 54 | ;; ---------- 55 | ;; abbrev-fn 56 | 57 | (def abbrev-fn->pair 58 | (form-transform :abbrev_fn 59 | (fn [[_ & xs]] 60 | (m/p 61 | 'fn 62 | (m/p 63 | (m/p '_ m/bel-nil) 64 | (m/p 65 | (m/seq->p xs) 66 | m/bel-nil)))))) 67 | 68 | ;; ---------- 69 | ;; abbrev-sym 70 | 71 | (declare handle-abbrev-sym) 72 | 73 | (defn handle-bar [left-xs right-xs] 74 | (m/p 't (m/p 75 | (handle-abbrev-sym left-xs) 76 | (m/p 77 | (handle-abbrev-sym right-xs) 78 | m/bel-nil)))) 79 | 80 | (defn handle-dot [left-xs right-xs] 81 | (m/p (if (seq left-xs) 82 | (handle-abbrev-sym left-xs) 83 | 'upon) 84 | (m/p (handle-abbrev-sym right-xs) m/bel-nil))) 85 | 86 | (defn handle-excl [left-xs right-xs] 87 | (m/p (if (seq left-xs) 88 | (handle-abbrev-sym left-xs) 89 | 'upon) 90 | (m/p (m/quoted-p (handle-abbrev-sym right-xs)) 91 | m/bel-nil))) 92 | 93 | (defn handle-no [left-xs [r & right-xs]] 94 | (handle-abbrev-sym 95 | (concat left-xs 96 | [(m/p 97 | 'compose 98 | (m/p 99 | 'no 100 | (m/p r m/bel-nil)))] 101 | right-xs))) 102 | 103 | (defn handle-col [left-xs right-xs] 104 | (m/p 105 | 'compose 106 | (->> (concat left-xs right-xs) 107 | (remove (fn [x] (and (seqable? x) (= (first x) :comp_id)))) 108 | m/seq->p))) 109 | 110 | (defn handle-abbrev-sym [x] 111 | (if 112 | (or (m/pair? x) (m/symbol? x)) 113 | x 114 | (let [[id f] (->> [["|" handle-bar] 115 | ["." handle-dot] 116 | ["!" handle-excl] 117 | ["~" handle-no] 118 | [":" handle-col]] 119 | (filter (fn [[id]] 120 | (some (partial = [:comp_id id]) x))) 121 | first) 122 | [before-id [_ & after-id]] 123 | (split-with (partial not= [:comp_id id]) x)] 124 | (if f 125 | (f before-id after-id) 126 | (first x))))) 127 | 128 | (def abbrev-sym->pair 129 | (form-transform :comp_sym 130 | (fn [[_ & xs]] 131 | (handle-abbrev-sym xs)))) 132 | 133 | ;; ------ 134 | ;; number 135 | 136 | (def transform-number 137 | (form-transform :number 138 | (fn [[_ v]] (edn/read-string v)))) 139 | 140 | ;; ------ 141 | ;; symbol 142 | 143 | (def transform-symbol 144 | (form-transform :symbol (fn [[_ v]] (symbol v)))) 145 | 146 | ;; ------ 147 | ;; char 148 | 149 | (def transform-char 150 | (form-transform :char (fn [[_ x]] 151 | (edn/read-string (str "\\" x))))) 152 | 153 | ;; ----- 154 | ;; bel-parse 155 | 156 | (def parse-string (-> "bel.ebnf" io/resource insta/parser)) 157 | 158 | (def unwrap-abbrev-sym-pt (form-transform :abbrev_sym_pt second)) 159 | 160 | (def parse-postwalk 161 | (comp 162 | list->pair 163 | transform-string 164 | quote->pair 165 | transform-symbol 166 | unwrap-name 167 | unwrap-sexp 168 | unwrap-abbrev-sym-pt 169 | unwrap-space 170 | abbrev-fn->pair 171 | abbrev-sym->pair 172 | transform-number 173 | transform-char)) 174 | 175 | (def parse 176 | (comp (partial walk/postwalk parse-postwalk) parse-string cstring/trim)) 177 | 178 | ;; ---------------- 179 | ;; bel->pretty 180 | 181 | (defn bel->pretty [form] 182 | (condp = (m/type-nilable form) 183 | 'symbol (if (= m/bel-nil form) nil form) 184 | 'backquote (list 'bq (bel->pretty (second form))) 185 | 'comma (list 'cm (bel->pretty (second form))) 186 | 'splice (list 'spl (bel->pretty (second form))) 187 | 'err (list 'err (bel->pretty (second form))) 188 | 'char form 189 | 'number form 190 | 'string form 191 | 'pair 192 | (let [[a b] form] 193 | (concat [(bel->pretty a)] 194 | (cond 195 | (= m/bel-nil b) nil 196 | (m/pair? b) (bel->pretty b) 197 | :else ['. (bel->pretty b)]))) 198 | form)) 199 | -------------------------------------------------------------------------------- /test/bel_clojure/core_test.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.core-test 2 | (:require 3 | [bel-clojure.reader :as r] 4 | [bel-clojure.evaluator :as e] 5 | [bel-clojure.core :refer :all] 6 | [clojure.test :refer :all])) 7 | 8 | (def env (delay (bootstrap-env))) 9 | 10 | (defn ev [& strs] 11 | (println ">" strs) 12 | (r/bel->pretty (last (e/eval-all @env strs)))) 13 | 14 | (deftest core-test 15 | (is (= (ev "(no nil)") 't)) 16 | (is (= (ev "(atom \\a)") 't)) 17 | (is (= (ev "(atom '(a))") nil)) 18 | (is (= (ev "(atom \"foo\")") nil)) 19 | (is (= (ev "(all atom '(a b))") 't)) 20 | (is (= (ev "(all atom '(a (b c) d))") nil)) 21 | (is (= (ev "(some atom '((a b) (c d)))") nil)) 22 | (is (= (ev "(some atom '((a b) c (d e)))") '(c (d e)))) 23 | (is (= (ev "(reduce join '(a b c))") '(a b . c))) 24 | (is (= (ev "(cons 'a 'b 'c '(d e f))") 25 | '(a b c d e f))) 26 | (is (= (ev "(append '(a b c) '(d e f))") 27 | '(a b c d e f))) 28 | (is (= (ev "(append '(a) nil '(b c) '(d e f))") 29 | '(a b c d e f))) 30 | (is (= (ev "(snoc '(a b c) 'd 'e)") 31 | '(a b c d e))) 32 | (is (= (ev "(list 'a 'b)") 33 | '(a b))) 34 | (is (= (ev "(map car '((a b) (c d) (e f)))") 35 | '(a c e))) 36 | (is (= (ev "(map cons '(a b c) '(d e f))") 37 | '((a . d) (b . e) (c . f)))) 38 | (is (= (ev "(symbol 'a)") 39 | 't)) 40 | (is (= (ev "(let (x . y) '(a b c) y)") 41 | '(b c))) 42 | (is (= (ev "((macro (v) `(set ,v 'a)) x)" 43 | "x") 44 | 'a)) 45 | (is (= (ev "(apply or '(nil a nil b))") 46 | 'a)) 47 | (is (= (ev "(proper '(a . b))") 48 | nil)) 49 | (is (= (ev "(proper '(a b))") 50 | 't)) 51 | (is (= (ev "(string \"foo\")") 52 | 't)) 53 | (is (= (ev "(mem \\a \"foobar\")") 54 | '(\a \r))) 55 | (is (= (ev "(let (x (o (y . z) '(a . b))) '(f) (list x y z))") 56 | '(f a b))) 57 | (is (= (ev "(begins '(a b c d e) '(a b))") 58 | 't)) 59 | (is (= (ev "(= '(a b) '(a b))") 't)) 60 | (is (= (ev "(case '+ + 'plus - 'minus 'unknown)") 'plus)) 61 | (is (= (ev "(iflet x nil 'foo '(a b c) (car x) 'bar)") 'a)) 62 | (is (= (ev "(find [= (car _) \\a] '(\"pear\" \"apple\" \"grape\"))") 63 | "apple")) 64 | (is (= (ev "(caris '(a b) 'a)") 't)) 65 | (is (= (ev "(hug '(a b c d e))") '((a b) (c d) (e)))) 66 | (is (= (ev "(with (x 'a y 'b) (cons x y))") '(a . b))) 67 | (is (= (ev "(rem \\a \"abracadabra\")") 68 | '(\b \r \c \d \b \r))) 69 | (is (= (ev "(set x '((a . d) (b . e) (c . f)))" 70 | "(get 'a x)") 71 | '(a . d))) 72 | (is (= (ev "(set x '((a . d) (b . e) (c . f)))" 73 | "(put 'z 'y x)") 74 | '((z . y) (a . d) (b . e) (c . f)))) 75 | (is (= (ev "(rev \"able\")") 76 | '(\e \l \b \a))) 77 | (is (= (ev "(snap '(a b) '(c d e f g))") '((c d) (e f g)))) 78 | (is (= (ev "(udrop '(a b) '(c d e f g))") '(e f g))) 79 | (is (= (ev "(map idfn '(a b c))") '(a b c))) 80 | (is (= (ev "((is 'a) 'a)") 't)) 81 | (is (= (ev "(eif x (car 'a) 'oops x)") 'oops)) 82 | (is (= (ev "(onerr 'oops (car 'a))") 'oops)) 83 | (is (= (ev "(safe (car 'a))") nil)) 84 | (is (= (ev "(safe (car '(a b)))") 'a)) 85 | (is (= (ev "(map literal (list nil \"foo\" car))") '((nil o apply) t t))) 86 | (is (= (ev "(map variable (list 'x (uvar) t))") '(t t nil))) 87 | (is (= (ev "((isa 'clo) map)") 't)) 88 | (is (= (ev "(def consa (xs|pair) (cons 'a xs))" 89 | "(consa 'z)") 90 | '(lit error (quote mistype)))) 91 | (is (= (ev "(def consa (xs|pair) (cons 'a xs))" 92 | "(consa '(a b))") 93 | '(a a b))) 94 | (is (= (ev "(def foo ((o (t (x . y) [caris _ 'a]) '(a . b))) x)" 95 | "(foo '(b b))") 96 | '(lit error (quote mistype)))) 97 | (is (= (ev "(def foo ((o (t (x . y) [caris _ 'a]) '(a . b))) x)" 98 | "(foo)") 99 | 'a)) 100 | (is (= (ev "((fn (x (o y x)) y) 'a)") 'a)) 101 | (is (= (ev "((fn (f x|f) x) pair 'a)") 102 | '(lit error (quote mistype)))) 103 | (is (= (ev "(map function (list car append 'foo))") '(prim clo nil))) 104 | (is (= (ev "(map (con 'yo) '(a b c))") '(yo yo yo))) 105 | (is (= (ev "(car:cdr '(a b c))") 'b)) 106 | (is (= (ev "(map ~cdr '((a) (a b c) (a b)))") 107 | '(t nil nil))) 108 | (is (= (ev "(map ((combine and) car cdr) '((a . nil) (a . b) (nil . b)))") 109 | '(nil b nil))) 110 | (is (= (ev "((cand pair cdr) '(a b))") '(b))) 111 | (is (= (ev "((cor char pair) 'a)") nil)) 112 | (is (= (ev "(foldl cons nil '(a b))") '(b a))) 113 | (is (= (ev "(foldr cons nil '(a b))") '(a b))) 114 | (is (= (ev "(map (upon '(a b c)) (list car cadr cdr))") 115 | '(a b (b c)))) 116 | (is (= (ev "(fuse [list 'a _] '(b c d))") 117 | '(a b a c a d))) 118 | (is (= (ev "(match '(a (b) c d) (list 'a pair 'c t))") 't)) 119 | (is (= (ev "(split (is \\a) \"frantic\")") 120 | '((\f \r) (\a \n \t \i \c)))) 121 | (is (= (ev "(inc 2)") 3)) 122 | (is (= (ev "(len '(a b c))") 3)) 123 | (is (= (ev "(pos \\s \"ask\")") 2)) 124 | (is (= (ev "(> 3 2)") 't)) 125 | (is (= (ev "(< \"apple\" \"apply\")") 't)) 126 | (is (= (ev "((afn (x) 127 | (if (no x) 0 (inc:self:cdr x))) '(a b c))") 128 | 3)) 129 | (is (= (ev "(pint 1)") 't)) 130 | (is (= (ev "(runs pint '(1 1 0 0 0 1 1 1 0))") 131 | '((1 1) (0 0 0) (1 1 1) (0)))) 132 | (is (= (ev "(tokens \"the age of the essay\")") 133 | '((\t \h \e) (\a \g \e) (\o \f) (\t \h \e) (\e \s \s \a \y)))) 134 | (is (= (ev "(dups \"abracadabra\")") 135 | '(\a \b \r))) 136 | (is (= (ev "(consif (cadr '(a)) '(x y))") '(x y))) 137 | (is (= (ev "(let x 'a (withs (x 'b y x) y))") 'b)) 138 | (is (= (ev "(tail [caris _ \\-] \"non-nil\")") '(\- \n \i \l))) 139 | (is (= (ev "(dock '(a b c))") '(a b))) 140 | (is (= (ev "(lastcdr '(a b c))") '(c))) 141 | (is (= (ev "(last '(a b c))") 'c)) 142 | (is (= (ev "(set x (newq))" "(enq 'a x)" "(enq 'b x)") 143 | '((a b)))) 144 | (is (= (ev "(set x (newq))" "(enq 'a x)" "(enq 'b x)" "(deq x)") 145 | 'a)) 146 | (is (= (ev "(set x (newq))" "(enq 'a x)" "(enq 'b x)" "(deq x)" "x") 147 | '((b)))) 148 | (is (= (ev "(let x '(a b c) (zap cdr x) x)") '(b c))) 149 | (is (= (ev "(let x '(a b c) (push 'z x) (pull 'c x) x)") '(z a b))) 150 | (is (= (ev "(let x 'nil (push 'a x) (push 'b x) x)") '(b a))) 151 | (is (= (ev "(drop 2 '(a b c d e))") '(c d e))) 152 | (is (= (ev "(nth 2 '(a b c d e))") 'b)) 153 | (is (= (ev "(first 2 '(a b c de))") '(a b))) 154 | (is (= (ev "(catch (throw 'a) (/ 1 0))") 'a)) 155 | (is (= (ev "(cut \"foobar\" 2 4)") '(\o \o \b))) 156 | (is (= (ev "(cut \"foobar\" 2 -1)") '(\o \o \b \a))) 157 | (is (= (ev "((flip -) 1 10)") 9)) 158 | (is (= (ev "((part cons 'a) 'b)") '(a . b))) 159 | (is (= (ev "((trap cons 'a) 'b)") '(b . a))) 160 | (is (= (ev "(let x nil 161 | (set find only.car:some) 162 | (find [= (car _) \\a] '(\"pear\" \"apple\" \"grape\")))") 163 | "apple")) 164 | (is (= (ev "(let z nil 165 | (let x '(a b c) (whilet y (pop x) (push y z)) x) z)") 166 | '(c b a))) 167 | (is (= (ev "(let z nil 168 | (loop x 1 (+ x 1) (< x 5) (push x z)) 169 | z)") 170 | '(4 3 2 1))) 171 | (is (= (ev "(let z nil 172 | (for x 1 5 (push x z)) 173 | z)") 174 | '(5 4 3 2 1))) 175 | (is (= (ev "(let x '(a b c d e) (poll (pop x) is!c) x)") '(d e))) 176 | (is (= (ev "(let x '(a b c) (pop (cdr x)) x)") '(a c))) 177 | (is (= (ev "(let (x y z) '(a b c) (swap x y z) (list x y z))") '(b c a))) 178 | (is (= (ev "(adjoin 'a '(a b c))") '(a b c))) 179 | (is (= (ev "(adjoin 'z '(a b c))") '(z a b c))) 180 | (is (= (ev "(dedup \"abracadabra\")") 181 | '(\a \b \r \c \d))) 182 | (is (= (ev "(insert < 3 '(1 2 4 5))") '(1 2 3 4 5))) 183 | (is (= (ev "(sort < '(5 1 3 2 4))") '(1 2 3 4 5))) 184 | (is (= (ev "(best > '(1 2 4 5))") 5)) 185 | (is (= (ev "(best (of > len) '((a) (b c) (d e) (f)))") '(b c))) 186 | (is (= (ev "(do (thread (do (join 'a 'b))) 187 | (thread (do (join 'a 'b) (join 'b 'd))))") 188 | '(b . d))) 189 | (is (= (ev "(do (thread (do (join 'a 'b))) 190 | (thread 191 | (atomic (do (join 'a 'b) (join 'b 'd)))))") 192 | '(a . b))) 193 | (is (= (ev "(2 '(a b c))") 'b))) 194 | -------------------------------------------------------------------------------- /test/bel_clojure/evaluator_test.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.evaluator-test 2 | (:refer-clojure :exclude [eval]) 3 | (:require 4 | [bel-clojure.reader :as r] 5 | [clojure.test :refer :all] 6 | [bel-clojure.evaluator :refer :all])) 7 | 8 | (defn ev-all [env strs] 9 | (mapv r/bel->pretty (eval-all env strs))) 10 | 11 | (defn ev [& strs] 12 | (last (ev-all (env) strs))) 13 | 14 | (deftest test-evaluator 15 | (is (= (ev "nil") nil)) 16 | (is (= (ev "\\b") \b)) 17 | (is (= (ev "\"foo\"") "foo")) 18 | (is (= (ev "'foo") 'foo)) 19 | (is (= (ev "(type globe)") 'mut-map)) 20 | (is (= (ev "(type scope)") 'symbol)) 21 | (is (= (ev "(lit (foo bar baz))") '(lit (foo bar baz)))) 22 | (is (= (ev "car") '(lit prim car))) 23 | (is (= (ev "(set a 'b c 'd)" "c") 'd)) 24 | (is (= (ev "(if t 'a 'b)") 'a)) 25 | (is (= (ev "(if nil 'a 'b)") 'b)) 26 | (is (= (ev "(if nil 'a nil 'b 'c)") 'c)) 27 | (is (= (ev "(car '(a b))") 'a)) 28 | (is (= (ev "(id t nil)") nil)) 29 | (is (= (ev "(id t t)") 't)) 30 | (is (= (ev "(id t)") nil)) 31 | (is (= (ev "(id)") 't)) 32 | (is (= (ev "((lit clo nil (x) (id x t)) t)") 33 | 't)) 34 | (is (= (ev "((lit clo nil (x) (id x t)) nil)") 35 | nil)) 36 | (is (= (ev "(apply join '(a b))") 37 | '(a . b))) 38 | (is (= (ev "(apply join 'a '(b))") 39 | '(a . b))) 40 | (is (= (ev "((lit clo nil (x (o y)) y) 'a)") 41 | nil)) 42 | (is (= (ev "((lit clo nil (x (o y 'b)) y) 'a)") 43 | 'b)) 44 | (is (= (ev 45 | ;; see source.bel 46 | "(set def (lit mac (lit clo nil (n p e) (join 'set (join n (join (join 'lit (join 'clo (join nil (join p (join e nil))))) nil))))))" 47 | "(def no (x) (id x nil))" 48 | "(no nil)") 49 | 't)) 50 | (is (= (ev "(set a 'foo b '(bar baz))" "`(foo ',a ,@b)") 51 | '(foo (quote foo) bar baz))) 52 | (is (= (ev "(set x 'a)" "`(x ,x y)") 53 | '(x a y))) 54 | (is (= (ev "(set x 'a)" "`(x ,x y ,(id 'a 'a))") 55 | '(x a y t))) 56 | (is (= (ev "(set y '(c d))" "`(a b ,@y e f)") 57 | '(a b c d e f))) 58 | (is (= (take-last 2 (ev-all (env) 59 | ["(set x 'a)" 60 | "x" 61 | "(dyn x 'z (join x 'b))" 62 | "x"])) 63 | '((z . b) a))) 64 | (is (= (take-last 2 (ev-all (env) 65 | ["(join 'a (ccc (lit clo nil (c) (set cont c))))" 66 | "(cont 'b)" 67 | "(cont 'c)"])) 68 | '((a . b) (a . c)))) 69 | (is (= (ev "(err \"something\")") 70 | '(lit error "something"))) 71 | (is (= (take 2 (ev "(car 'a)")) '(lit error))) 72 | (is (= (ev 73 | "(dyn err (lit clo nil (x) 'hello) (car 'a))") 74 | 'hello)) 75 | (is (= (ev "((lit clo nil ((t x (lit clo nil (x) (id t x)))) 'hello) t)") 76 | 'hello)) 77 | (is (= (ev 78 | "((lit clo nil ((t x (lit clo nil (x) (id t x)))) 'hello) nil)") 79 | '(lit error (quote mistype)))) 80 | (is (= (ev "1") 1)) 81 | (is (= (ev "(+ 1 2.0)") 3.0)) 82 | (is (= (ev "(num< 2 3)") 't)) 83 | (is (= (ev "(abs -4)") 4)) 84 | (is (= (ev "(+ 0.05 (/ 19 20))") 1.0)) 85 | (is (= (ev "(int 1)") 't)) 86 | (is (number? (ev "(hash \\b)"))) 87 | (is (= (ev "(set x 'a)" "(where x)") 88 | '((x . a) d))) 89 | (is (= (ev "(where (car '(a b)))") 90 | '((a b) a))) 91 | (is (= (ev "(where (cdr '(a b)))") 92 | '((a b) d)))) 93 | -------------------------------------------------------------------------------- /test/bel_clojure/model_test.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.model-test 2 | (:refer-clojure :exclude [eval char? string? number? symbol? type]) 3 | (:require 4 | [bel-clojure.reader :as r] 5 | [clojure.test :refer :all] 6 | [bel-clojure.model :refer :all])) 7 | 8 | (defn pretty-f [f & args] 9 | (r/bel->pretty (apply f (map r/parse args)))) 10 | 11 | (deftest test-model 12 | (is (= (pretty-f id "a" "a") 't)) 13 | (is (= (pretty-f id "a" "b") nil)) 14 | (is (= (pretty-f id "(a)" "(a)") nil)) 15 | (is (= (pretty-f join "a" "b") '(a . b))) 16 | (is (= (pretty-f car "(a b c)") 'a)) 17 | (is (= (pretty-f car "nil") nil)) 18 | (is (= (pretty-f car "\"foo\"") \f)) 19 | (is (= (pretty-f cdr "(a . b)") 'b)) 20 | (is (= (pretty-f cdr "(a b)") '(b))) 21 | (is (= (pretty-f cdr "nil") nil)) 22 | (is (= (pretty-f cdr "\"foo\"") '(\o \o))) 23 | (is (= (pretty-f type "a") 'symbol)) 24 | (is (= (pretty-f type "(a b)") 'pair)) 25 | (is (= (pretty-f type "\\a") 'char)) 26 | (is (= (pretty-f type "\"a\"") 'string)) 27 | (let [p (r/parse "(a . b)") 28 | c (r/parse "c")] 29 | (xar p c) 30 | (is (= (car p) c))) 31 | (let [p (r/parse "(a . b)") 32 | c (r/parse "c")] 33 | (xdr p c) 34 | (is (= (cdr p) c))) 35 | (is (= (pretty-f sym "\"foo\"") 'foo)) 36 | (is (= (pretty-f nom "foo") "foo")) 37 | (is (= (map-assoc bel-nil 'foo 1) {'foo 1})) 38 | (is (= (map-dissoc bel-nil {'foo 1}) bel-nil))) 39 | -------------------------------------------------------------------------------- /test/bel_clojure/reader_test.clj: -------------------------------------------------------------------------------- 1 | (ns bel-clojure.reader-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [bel-clojure.reader :refer :all])) 5 | 6 | (defn pretty-parse [x] (bel->pretty (parse x))) 7 | 8 | (deftest test-reader 9 | (is (= (pretty-parse "\"str\"") "str")) 10 | (is (= (pretty-parse "\"hello world\"") "hello world")) 11 | (is (= (pretty-parse "(a b c)") '(a b c))) 12 | (is (= (pretty-parse "_") '_)) 13 | (is (= (pretty-parse "'+") '(quote +))) 14 | (is (= (pretty-parse "\\b") \b)) 15 | (is (= (pretty-parse "(a . b)") 16 | '(a . b))) 17 | (is (= (pretty-parse "(a b . c)") 18 | '(a b . c))) 19 | (is (= (pretty-parse "()") nil)) 20 | (is (= (pretty-parse "`(foo ,a ,@b)") 21 | '(bq (foo (cm a) (spl b))))) 22 | (is (= (pretty-parse "=") '=)) 23 | (is (= (pretty-parse ">=") '>=)) 24 | (is (= (pretty-parse "[id _ (car args)]") 25 | '(fn (_) (id _ (car args))))) 26 | (is (= (pretty-parse "(mac e1)") 27 | '(mac e1))) 28 | (is (= (pretty-parse "e1") 29 | 'e1)) 30 | (is (= (pretty-parse "~cdr") 31 | '(compose no cdr))) 32 | (is (= (pretty-parse "car:cdr") 33 | '(compose car cdr))) 34 | (is (= (pretty-parse "car:cdr:cdr") 35 | '(compose car cdr cdr))) 36 | (is (= (pretty-parse "c|isa!cont") 37 | '(t c (isa (quote cont))))) 38 | (is (= (pretty-parse "!a") 39 | '(upon (quote a)))) 40 | (is (= '(compose no f) 41 | (pretty-parse "~f"))) 42 | (is (= (pretty-parse "x|~f:g!a") 43 | '(t x ((compose (compose no f) g) (quote a))))) 44 | (is (= (pretty-parse "~f:car") 45 | '(compose (compose no f) car))) 46 | (is (= (pretty-parse "car:i/") 47 | (list 'compose 'car (symbol "i/")))) 48 | (is (= (pretty-parse "i*") 'i*)) 49 | (is (= (pretty-parse "i<") 'i<)) 50 | (is (= (pretty-parse "i^") (symbol "i^"))) 51 | (is (= (pretty-parse "a|b") '(t a b))) 52 | (is (= (pretty-parse "1") 1)) 53 | (is (= (pretty-parse "1.05") 1.05)) 54 | (is (= (pretty-parse "-1.05") -1.05)) 55 | (is (= (pretty-parse "+0.05") 0.05)) 56 | (is (= (pretty-parse "int?") 'int?))) 57 | --------------------------------------------------------------------------------