shithub: femtolisp

Download patch

ref: 2e9a8c21ccb52cd4726e7c6a0c92cabf1d0e26f8
parent: caf7f15f44bf0db2fa3fa9268e57216424d2b31b
author: JeffBezanson <jeff.bezanson@gmail.com>
date: Wed May 5 01:31:46 EDT 2010

porting over some improvements: now fl_applyn can handle any function
  (lambda wrappers for opcodes)
faster separate


--- a/femtolisp/flisp.boot
+++ b/femtolisp/flisp.boot
@@ -1,32 +1,67 @@
 (*banner* ";  _\n; |_ _ _ |_ _ |  . _ _\n; | (-||||_(_)|__|_)|_)\n;-------------------|----------------------------------------------------------\n\n"
+	  *builtins* [0 0 0 0 0 0 0 0 0 0 0 0 #fn("7000r2|}<;" [])
+		      #fn("7000r2|}=;" [])
+		      #fn("7000r2|}>;" [])
+		      #fn("6000r1|?;" [])
+		      #fn("6000r1|@;" [])
+		      #fn("6000r1|A;" [])
+		      #fn("6000r1|B;" [])
+		      #fn("6000r1|C;" [])
+		      #fn("6000r1|D;" [])
+		      #fn("6000r1|E;" [])
+		      #fn("6000r1|F;" [])
+		      #fn("6000r1|G;" [])
+		      #fn("6000r1|H;" [])
+		      #fn("6000r1|I;" [])
+		      #fn("6000r1|J;" [])
+		      #fn("7000r2|}K;" [])
+		      #fn("9000s0c0|v2;" [#.list])
+		      #fn("6000r1|M;" [])
+		      #fn("6000r1|N;" [])
+		      #fn("7000r2|}O;" [])
+		      #fn("7000r2|}P;" [])
+		      #fn("9000s0c0|v2;" [#.apply])
+		      #fn("9000s0c0|v2;" [#.+])
+		      #fn("9000s0c0|v2;" [#.-])
+		      #fn("9000s0c0|v2;" [#.*])
+		      #fn("9000s0c0|v2;" [#./])
+		      #fn("9000s0c0|v2;" [#.div0])
+		      #fn("7000r2|}W;" [])
+		      #fn("7000r2|}X;" [])
+		      #fn("7000r2|}Y;" [])
+		      #fn("9000s0c0|v2;" [#.vector])
+		      #fn("7000r2|}[;" [])
+		      #fn("8000r3|}g2\\;" [])]
 	  *interactive* #f *syntax-environment*
-	  #table(letrec #fn(">000s1e0c1L1e2c3|32L1e2c4|32e5}3134e2c6|32K;" [nconc
-  lambda map #.car #fn("8000r1c0e1|31K;" [set! copy-list]) copy-list #fn("6000r1e040;" [void])])  quasiquote #fn("7000r1e0|41;" [bq-process])  when #fn("<000s1c0|c1}K^L4;" [if
-  begin])  dotimes #fn(";000s1c0q|M|\x8442;" [#fn("=000r2c0`c1}aL3e2c3L1|L1L1e4\x7f3133L4;" [for
+	  #table(with-bindings #fn(">000s1c0qe1c2|32e1e3|32e1c4|3243;" [#fn("A000r3e0c1L1e2c3g2|33L1e4e2c5|}3331c6c7e4\x7f31Kc7e4e2c8|g23331KL3L144;" [nconc
+  let map #.list copy-list #fn("8000r2c0|}L3;" [set!]) unwind-protect begin #fn("8000r2c0|}L3;" [set!])])
+  map #.car cadr #fn("6000r1e040;" [gensym])])  letrec #fn(">000s1e0c1L1e2c3|32L1e2c4|32e5}3134e2c6|32K;" [nconc
+  lambda map #.car #fn("8000r1c0e1|31K;" [set! copy-list]) copy-list #fn("6000r1e040;" [void])])  assert #fn("<000r1c0|]c1c2c3|L2L2L2L4;" [if
+  raise quote assert-failed])  label #fn(":000r2c0|L1c1|}L3L3^L2;" [lambda set!])  do #fn("A000s2c0qe130}Me2c3|32e2e4|32e2c5|3245;" [#fn("A000r5c0|c1g2c2}c3e4\x7fN31Ke5c3L1e4i0231|g4KL133L4L3L2L1|g3KL3;" [letrec
+  lambda if begin copy-list nconc]) gensym map #.car cadr #fn("7000r1e0|31F680e1|41;|M;" [cddr
+  caddr])])  quasiquote #fn("7000r1e0|41;" [bq-process])  when #fn("<000s1c0|c1}K^L4;" [if
+  begin])  with-input-from #fn("=000s1e0c1L1c2|L2L1L1e3}3143;" [nconc
+								with-bindings
+								*input-stream*
+								copy-list])  dotimes #fn(";000s1c0q|M|\x8442;" [#fn("=000r2c0`c1}aL3e2c3L1|L1L1e4\x7f3133L4;" [for
   - nconc lambda copy-list])])  unwind-protect #fn("8000r2c0qe130e13042;" [#fn("@000r2c0}c1_\x7fL3L2L1c2c3~c1|L1c4}L1c5|L2L3L3L3}L1L3L3;" [let
   lambda prog1 trycatch begin raise]) gensym])  define-macro #fn("?000s1c0c1|ML2e2c3L1|NL1e4}3133L3;" [set-syntax!
   quote nconc lambda copy-list])  receive #fn("@000s2c0c1_}L3e2c1L1|L1e3g23133L3;" [call-with-values
-  lambda nconc copy-list])  unless #fn("=000s1c0|^c1}KL4;" [if begin])  let* #fn("A000s1|?6E0e0c1L1_L1e2}3133L1;e0c1L1e3|31L1L1e2|NF6H0e0c4L1|NL1e2}3133L1530}3133e5|31L2;" [nconc
-  lambda copy-list caar let* cadar])  case #fn(":000s1c0q]41;" [#fn("7000r1c0m02c1qe23041;" [#fn("9000r2}c0\x8250c0;}\x8540^;}C6=0c1|e2}31L3;}?6=0c3|e2}31L3;}N\x85>0c3|e2}M31L3;e4c5}326=0c6|c7}L2L3;c8|c7}L2L3;" [else
-  eq? quote-value eqv? every #.symbol? memq quote memv] vals->cond)
-  #fn(";000r1c0|i10L2L1c1e2c3qi1132KL3;" [let cond map #fn("8000r1i10~|M32|NK;" [])])
-  gensym])])  catch #fn("7000r2c0qe13041;" [#fn("@000r1c0\x7fc1|L1c2c3c4|L2c5c6|L2c7c8L2L3c5c9|L2~L3L4c:|L2c;|L2L4L3L3;" [trycatch
-  lambda if and pair? eq car quote thrown-value cadr caddr raise]) gensym])  assert #fn("<000r1c0|]c1c2c3|L2L2L2L4;" [if
-  raise quote assert-failed])  label #fn(":000r2c0|L1c1|}L3L3^L2;" [lambda set!])  do #fn("A000s2c0qe130}Me2c3|32e2e4|32e2c5|3245;" [#fn("A000r5c0|c1g2c2}c3e4\x7fN31Ke5c3L1e4i0231|g4KL133L4L3L2L1|g3KL3;" [letrec
-  lambda if begin copy-list nconc]) gensym map #.car cadr #fn("7000r1e0|31F680e1|41;|M;" [cddr
-  caddr])])  with-input-from #fn("=000s1e0c1L1c2|L2L1L1e3}3143;" [nconc
-								  with-bindings
-								  *input-stream*
-								  copy-list])  let #fn(":000s1c0q^41;" [#fn("<000r1~C6D0~m02\x7fMo002\x7fNo01530]2c0qe1c2L1e3c4~32L1e5\x7f3133e3c6~3242;" [#fn("8000r2~6;0c0~|L3530|}K;" [label])
+  lambda nconc copy-list])  unless #fn("=000s1c0|^c1}KL4;" [if begin])  let #fn(":000s1c0q^41;" [#fn("<000r1~C6D0~m02\x7fMo002\x7fNo01530]2c0qe1c2L1e3c4~32L1e5\x7f3133e3c6~3242;" [#fn("8000r2~6;0c0~|L3530|}K;" [label])
   nconc lambda map #fn("6000r1|F650|M;|;" []) copy-list #fn("6000r1|F650|\x84;e040;" [void])])])  cond #fn("9000s0c0q]41;" [#fn("7000r1c0qm02|~41;" [#fn("7000r1|?640^;c0q|M41;" [#fn(":000r1|Mc0<17702|M]<6@0|N\x8550|M;c1|NK;|N\x85@0c2|Mi10~N31L3;|\x84c3\x82W0e4e5|31316A0c6qe7e5|313141;c8qe93041;c:|Mc1|NKi10~N31L4;" [else
   begin or => 1arg-lambda? caddr #fn("=000r1c0|~ML2L1c1|c2e3e4~3131Ki20i10N31L4L3;" [let
   if begin cddr caddr]) caadr #fn("<000r1c0|~ML2L1c1|e2~31|L2i20i10N31L4L3;" [let
   if caddr]) gensym if])] cond-clauses->if)])])  throw #fn(":000r2c0c1c2c3L2|}L4L2;" [raise
   list quote thrown-value])  time #fn("7000r1c0qe13041;" [#fn(">000r1c0|c1L1L2L1c2~c3c4c5c1L1|L3c6L4L3L3;" [let
-  time.now prog1 princ "Elapsed time: " - " seconds\n"]) gensym])  with-output-to #fn("=000s1e0c1L1c2|L2L1L1e3}3143;" [nconc
-  with-bindings *output-stream* copy-list])  with-bindings #fn(">000s1c0qe1c2|32e1e3|32e1c4|3243;" [#fn("A000r3e0c1L1e2c3g2|33L1e4e2c5|}3331c6c7e4\x7f31Kc7e4e2c8|g23331KL3L144;" [nconc
-  let map #.list copy-list #fn("8000r2c0|}L3;" [set!]) unwind-protect begin #fn("8000r2c0|}L3;" [set!])])
-  map #.car cadr #fn("6000r1e040;" [gensym])]))
+  time.now prog1 princ "Elapsed time: " - " seconds\n"]) gensym])  let* #fn("A000s1|?6E0e0c1L1_L1e2}3133L1;e0c1L1e3|31L1L1e2|NF6H0e0c4L1|NL1e2}3133L1530}3133e5|31L2;" [nconc
+  lambda copy-list caar let* cadar])  case #fn(":000s1c0q]41;" [#fn("7000r1c0m02c1qe23041;" [#fn("9000r2}c0\x8250c0;}\x8540^;}C6=0c1|e2}31L3;}?6=0c3|e2}31L3;}N\x85>0c3|e2}M31L3;e4c5}326=0c6|c7}L2L3;c8|c7}L2L3;" [else
+  eq? quote-value eqv? every #.symbol? memq quote memv] vals->cond)
+  #fn(";000r1c0|i10L2L1c1e2c3qi1132KL3;" [let cond map #fn("8000r1i10~|M32|NK;" [])])
+  gensym])])  with-output-to #fn("=000s1e0c1L1c2|L2L1L1e3}3143;" [nconc
+								  with-bindings
+								  *output-stream*
+								  copy-list])  catch #fn("7000r2c0qe13041;" [#fn("@000r1c0\x7fc1|L1c2c3c4|L2c5c6|L2c7c8L2L3c5c9|L2~L3L4c:|L2c;|L2L4L3L3;" [trycatch
+  lambda if and pair? eq car quote thrown-value cadr caddr raise]) gensym]))
 	  *whitespace* "\t\n\v\f\r \u0085  ᠎           \u2028\u2029   " 1+
 	  #fn("7000r1|aw;" [] 1+) 1- #fn("7000r1|ax;" [] 1-) 1arg-lambda?
 	  #fn("8000r1|F16T02|Mc0<16J02|NF16B02|\x84F16:02e1|\x84a42;" [lambda
@@ -274,10 +309,12 @@
 						    *print-readably*
 						    *print-level*
 						    *print-length* *os-name*)] make-system-image)
-	  map #fn("<000s2c0q]]42;" [#fn("9000r2c0m02c1qm12i02\x85;0|~\x7f_L143;}~\x7fi02K42;" [#fn("9000r3g2]}F6H02g2|}M31_KPNm22}Nm15\x17/2N;" [] map1)
-  #fn("<000r2}M\x8540_;|~c0}_L133Q2\x7f|~c1}_L13332K;" [#.car #.cdr] mapn)])] map)
-	  map! #fn("9000r2}]}F6B02}|}M31O2}Nm15\x1d/2;" [] map!) map-int
-	  #fn("8000r2e0}`32640_;c1q|`31_K_42;" [<= #fn(":000r2|m12a\x7faxc0qu2|;" [#fn("8000r1\x7fi10|31_KP2\x7fNo01;" [])])] map-int)
+	  map #fn("=000s2g2\x85<0e0|}_L143;e1|}g2K42;" [map1 mapn] map) map!
+	  #fn("9000r2}]}F6B02}|}M31O2}Nm15\x1d/2;" [] map!) map-int #fn("8000r2e0}`32640_;c1q|`31_K_42;" [<=
+  #fn(":000r2|m12a\x7faxc0qu2|;" [#fn("8000r1\x7fi10|31_KP2\x7fNo01;" [])])] map-int)
+	  map1 #fn("9000r3g2]}F6H02g2|}M31_KPNm22}Nm15\x17/2N;" [] map1) mapn
+	  #fn("<000r2}M\x8540_;|e0c1}_L133Q2e2|e0c3}_L13332K;" [map1 #.car mapn
+								#.cdr] mapn)
 	  mark-label #fn("9000r2e0|c1}43;" [emit label] mark-label) max
 	  #fn("<000s1}\x8540|;e0c1|}43;" [foldl #fn("7000r2|}X640};|;" [])] max)
 	  member #fn("8000r2}?640^;}M|>640};e0|}N42;" [member] member) memv
@@ -338,8 +375,7 @@
 	  #fn("9000r1e0c1_|43;" [foldl #.cons] reverse) reverse! #fn("7000r1c0q_41;" [#fn("9000r1]~F6C02~N~|~m02P2o005\x1c/2|;" [])] reverse!)
 	  self-evaluating? #fn("8000r1|?16602|C@17K02e0|3116A02|C16:02|e1|31<;" [constant?
   top-level-value] self-evaluating?)
-	  separate #fn("7000r2c0q]41;" [#fn(":000r1c0qm02|~\x7f__44;" [#fn(";000r4}\x85C0e0e1g231e1g33142;|}M316@0~|}N}Mg2Kg344;~|}Ng2}Mg3K44;" [values
-  reverse] separate-)])] separate)
+	  separate #fn("7000r2c0q]41;" [#fn(":000r1c0m02|~\x7f_L1_L144;" [#fn(";000r4c0g2g3K]}F6Z02|}M316?0g2}M_KPNm25<0g3}M_KPNm32}Nm15\x05/241;" [#fn("8000r1e0|MN|NN42;" [values])] separate-)])] separate)
 	  set-syntax! #fn("9000r2e0e1|}43;" [put! *syntax-environment*] set-syntax!)
 	  simple-sort #fn("7000r1|A17602|NA640|;c0q|M41;" [#fn("8000r1e0c1qc2q42;" [call-with-values
   #fn("8000r0e0c1qi10N42;" [separate #fn("7000r1|~X;" [])])
--- a/femtolisp/flisp.c
+++ b/femtolisp/flisp.c
@@ -93,7 +93,7 @@
 value_t IOError, ParseError, TypeError, ArgError, UnboundError, MemoryError;
 value_t DivideError, BoundsError, Error, KeyError, EnumerationError;
 value_t printwidthsym, printreadablysym, printprettysym, printlengthsym;
-value_t printlevelsym;
+value_t printlevelsym, builtins_table_sym;
 
 static value_t NIL, LAMBDA, IF, TRYCATCH;
 static value_t BACKQUOTE, COMMA, COMMAAT, COMMADOT, FUNCTION;
@@ -627,6 +627,11 @@
     else if (isfunction(f)) {
         v = apply_cl(n);
     }
+    else if (isbuiltin(f)) {
+        value_t tab = symbol_value(builtins_table_sym);
+        Stack[SP-n-1] = vector_elt(tab, uintval(f));
+        v = apply_cl(n);
+    }
     else {
         type_error("apply", "function", f);
     }
@@ -1728,7 +1733,10 @@
             else {
                 PUSH(Stack[bp]); // env has already been captured; share
             }
-            pv = alloc_words(4);
+            if (curheap > lim-2)
+                gc(0);
+            pv = (value_t*)curheap;
+            curheap += (4*sizeof(value_t));
             e = Stack[SP-2];  // closure to copy
             assert(isfunction(e));
             pv[0] = ((value_t*)ptr(e))[0];
@@ -2206,6 +2214,7 @@
     set(printwidthsym=symbol("*print-width*"), fixnum(SCR_WIDTH));
     set(printlengthsym=symbol("*print-length*"), FL_F);
     set(printlevelsym=symbol("*print-level*"), FL_F);
+    builtins_table_sym = symbol("*builtins*");
     fl_lasterror = NIL;
     i = 0;
     for (i=OP_EQ; i <= OP_ASET; i++) {
--- a/femtolisp/flisp.h
+++ b/femtolisp/flisp.h
@@ -332,6 +332,7 @@
 int fl_isnumber(value_t v);
 int fl_isgensym(value_t v);
 int fl_isiostream(value_t v);
+ios_t *fl_toiostream(value_t v, char *fname);
 value_t cvalue_compare(value_t a, value_t b);
 int numeric_compare(value_t a, value_t b, int eq, int eqnans, char *fname);
 
--- a/femtolisp/iostream.c
+++ b/femtolisp/iostream.c
@@ -70,6 +70,11 @@
     return value2c(ios_t*, v);
 }
 
+ios_t *fl_toiostream(value_t v, char *fname)
+{
+    return toiostream(v, fname);
+}
+
 value_t fl_file(value_t *args, uint32_t nargs)
 {
     if (nargs < 1)
@@ -333,7 +338,9 @@
     if (dest.buf != data) {
         // outgrew initial space
         cv->data = dest.buf;
+#ifndef BOEHM_GC
         cv_autorelease(cv);
+#endif
     }
     ((char*)cv->data)[n] = '\0';
     if (n == 0 && ios_eof(src))
@@ -378,7 +385,9 @@
         char *b = ios_takebuf(st, &n); n--;
         b[n] = '\0';
         str = cvalue_from_ref(stringtype, b, n, FL_NIL);
+#ifndef BOEHM_GC
         cv_autorelease((cvalue_t*)ptr(str));
+#endif
     }
     return str;
 }
--- a/femtolisp/read.c
+++ b/femtolisp/read.c
@@ -11,7 +11,7 @@
 // exceptions are '.', which is an ordinary symbol character
 // unless it's the only character in the symbol, and '#', which is
 // an ordinary symbol character unless it's the first character.
-static int symchar(char c)
+static inline int symchar(char c)
 {
     static char *special = "()[]'\";`,\\| \f\n\r\t\v";
     return !strchr(special, c);
--- a/femtolisp/system.lsp
+++ b/femtolisp/system.lsp
@@ -5,6 +5,27 @@
 
 (define (void) #t)  ; the unspecified value
 
+(define *builtins*
+  (vector
+   0 0 0 0 0 0 0 0 0 0 0 0
+   (lambda (x y) (eq? x y))          (lambda (x y) (eqv? x y))
+   (lambda (x y) (equal? x y))       (lambda (x) (atom? x))
+   (lambda (x) (not x))              (lambda (x) (null? x))
+   (lambda (x) (boolean? x))         (lambda (x) (symbol? x))
+   (lambda (x) (number? x))          (lambda (x) (bound? x))
+   (lambda (x) (pair? x))            (lambda (x) (builtin? x))
+   (lambda (x) (vector? x))          (lambda (x) (fixnum? x))
+   (lambda (x) (function? x))        (lambda (x y) (cons x y))
+   (lambda rest (apply list rest))   (lambda (x) (car x))
+   (lambda (x) (cdr x))              (lambda (x y) (set-car! x y))
+   (lambda (x y) (set-cdr! x y))     (lambda rest (apply apply rest))
+   (lambda rest (apply + rest))      (lambda rest (apply - rest))
+   (lambda rest (apply * rest))      (lambda rest (apply / rest))
+   (lambda rest (apply div0 rest))   (lambda (x y) (= x y))
+   (lambda (x y) (< x y))            (lambda (x y) (compare x y))
+   (lambda rest (apply vector rest)) (lambda (x y) (aref x y))
+   (lambda (x y z) (aset! x y z))))
+
 (if (not (bound? '*syntax-environment*))
     (define *syntax-environment* (table)))
 
@@ -18,19 +39,21 @@
 (define-macro (label name fn)
   `((lambda (,name) (set! ,name ,fn)) #f))
 
+(define (map1 f lst acc)
+  (cdr
+   (prog1 acc
+	  (while (pair? lst)
+		 (begin (set! acc
+			      (cdr (set-cdr! acc (cons (f (car lst)) ()))))
+			(set! lst (cdr lst)))))))
+
+(define (mapn f lsts)
+  (if (null? (car lsts))
+      ()
+      (cons (apply f (map1 car lsts (list ())))
+	    (mapn  f (map1 cdr lsts (list ()))))))
+
 (define (map f lst . lsts)
-  (define (map1 f lst acc)
-    (cdr
-     (prog1 acc
-      (while (pair? lst)
-	     (begin (set! acc
-			  (cdr (set-cdr! acc (cons (f (car lst)) ()))))
-		    (set! lst (cdr lst)))))))
-  (define (mapn f lsts)
-    (if (null? (car lsts))
-	()
-	(cons (apply f (map1 car lsts (list ())))
-	      (mapn  f (map1 cdr lsts (list ()))))))
   (if (null? lsts)
       (map1 f lst (list ()))
       (mapn f (cons lst lsts))))
@@ -265,12 +288,18 @@
 
 (define (separate pred lst)
   (define (separate- pred lst yes no)
-    (cond ((null? lst) (values (reverse yes) (reverse no)))
-	  ((pred (car lst))
-	   (separate- pred (cdr lst) (cons (car lst) yes) no))
-	  (else
-	   (separate- pred (cdr lst) yes (cons (car lst) no)))))
-  (separate- pred lst () ()))
+    (let ((vals
+	   (prog1
+	    (cons yes no)
+	    (while (pair? lst)
+		   (begin (if (pred (car lst))
+			      (set! yes
+				    (cdr (set-cdr! yes (cons (car lst) ()))))
+			      (set! no
+				    (cdr (set-cdr! no  (cons (car lst) ())))))
+			  (set! lst (cdr lst)))))))
+      (values (cdr (car vals)) (cdr (cdr vals)))))
+  (separate- pred lst (list ()) (list ())))
 
 (define (count f l)
   (define (count- f l n)