ref: 6ec69f537598e81cbb678ba5387c55c9274249e5
parent: 943c0d71d15c972ee730b417f0e47ef1f689efe6
author: JeffBezanson <[email protected]>
date: Wed Jun 10 20:34:50 EDT 2009
optimizations to map and case several optimizations to the compiler itself, mostly involving emit and encode-byte-code experimental, very basic profiling utility
--- a/femtolisp/compiler.lsp
+++ b/femtolisp/compiler.lsp
@@ -60,35 +60,38 @@
(prog1 nconst
(aset! b 2 (+ nconst 1)))))))
(define (emit e inst . args)
- (if (memq inst '(:loadv :loadg :setg))
- (set! args (list (bcode:indexfor e (car args)))))
- (let ((longform
- (assq inst '((:loadv :loadv.l) (:loadg :loadg.l) (:setg :setg.l)
- (:loada :loada.l) (:seta :seta.l)))))
- (if (and longform
- (> (car args) 255))
- (set! inst (cadr longform))))
- (let ((longform
- (assq inst '((:loadc :loadc.l) (:setc :setc.l)))))
- (if (and longform
- (or (> (car args) 255)
- (> (cadr args) 255)))
- (set! inst (cadr longform))))
- (if (eq? inst :loada)
- (cond ((equal? args '(0))
- (set! inst :loada0)
- (set! args ()))
- ((equal? args '(1))
- (set! inst :loada1)
- (set! args ()))))
- (if (eq? inst :loadc)
- (cond ((equal? args '(0 0))
- (set! inst :loadc00)
- (set! args ()))
- ((equal? args '(0 1))
- (set! inst :loadc01)
- (set! args ()))))
- (aset! e 0 (nreconc (cons inst args) (aref e 0)))
+ (if (null? args)
+ (aset! e 0 (cons inst (aref e 0)))
+ (begin
+ (if (memq inst '(:loadv :loadg :setg))
+ (set! args (list (bcode:indexfor e (car args)))))
+ (let ((longform
+ (assq inst '((:loadv :loadv.l) (:loadg :loadg.l) (:setg :setg.l)
+ (:loada :loada.l) (:seta :seta.l)))))
+ (if (and longform
+ (> (car args) 255))
+ (set! inst (cadr longform))))
+ (let ((longform
+ (assq inst '((:loadc :loadc.l) (:setc :setc.l)))))
+ (if (and longform
+ (or (> (car args) 255)
+ (> (cadr args) 255)))
+ (set! inst (cadr longform))))
+ (if (eq? inst :loada)
+ (cond ((equal? args '(0))
+ (set! inst :loada0)
+ (set! args ()))
+ ((equal? args '(1))
+ (set! inst :loada1)
+ (set! args ()))))
+ (if (eq? inst :loadc)
+ (cond ((equal? args '(0 0))
+ (set! inst :loadc00)
+ (set! args ()))
+ ((equal? args '(0 1))
+ (set! inst :loadc01)
+ (set! args ()))))
+ (aset! e 0 (nreconc (cons inst args) (aref e 0)))))
e)
(define (make-label e) (gensym))
@@ -99,8 +102,11 @@
(define (encode-byte-code e)
(let* ((cl (reverse! e))
(v (list->vector cl))
- (long? (>= (+ (length v)
- (* 3 (count (lambda (i)
+ (long? (>= (+ (length v) ; 1 byte for each entry, plus...
+ ; at most half the entries in this vector can be
+ ; instructions accepting 32-bit arguments
+ (* 3 (div0 (length v) 2))
+ #;(* 3 (count (lambda (i)
(memq i '(:loadv.l :loadg.l :setg.l
:loada.l :seta.l :loadc.l
:setc.l :jmp :brt :brf
@@ -112,7 +118,8 @@
(label-to-loc (table))
(fixup-to-label (table))
(bcode (buffer))
- (vi #f))
+ (vi #f)
+ (nxt #f))
(while (< i n)
(begin
(set! vi (aref v i))
@@ -123,46 +130,44 @@
(io.write bcode
(byte
(get Instructions
- (if (and long?
- (memq vi '(:jmp :brt :brf)))
+ (if long?
(case vi
(:jmp :jmp.l)
(:brt :brt.l)
- (:brf :brf.l))
+ (:brf :brf.l)
+ (else vi))
vi))))
(set! i (+ i 1))
- (if (< i n)
- (let ((nxt (aref v i)))
- (case vi
- ((:loadv.l :loadg.l :setg.l :loada.l :seta.l :largc
- :lvargc)
- (io.write bcode (uint32 nxt))
- (set! i (+ i 1)))
-
- ((:loada :seta :call :tcall :loadv :loadg :setg
- :list :+ :- :* :/ :vector :argc :vargc :loadi8
- :apply :tapply)
- (io.write bcode (uint8 nxt))
- (set! i (+ i 1)))
-
- ((:loadc :setc) ; 2 uint8 args
- (io.write bcode (uint8 nxt))
- (set! i (+ i 1))
- (io.write bcode (uint8 (aref v i)))
- (set! i (+ i 1)))
+ (set! nxt (if (< i n) (aref v i) #f))
+ (cond ((memq vi '(:jmp :brf :brt))
+ (put! fixup-to-label (sizeof bcode) nxt)
+ (io.write bcode ((if long? uint32 uint16) 0))
+ (set! i (+ i 1)))
+ ((number? nxt)
+ (case vi
+ ((:loadv.l :loadg.l :setg.l :loada.l :seta.l
+ :largc :lvargc)
+ (io.write bcode (uint32 nxt))
+ (set! i (+ i 1)))
+
+ ((:loadc :setc) ; 2 uint8 args
+ (io.write bcode (uint8 nxt))
+ (set! i (+ i 1))
+ (io.write bcode (uint8 (aref v i)))
+ (set! i (+ i 1)))
+
+ ((:loadc.l :setc.l) ; 2 uint32 args
+ (io.write bcode (uint32 nxt))
+ (set! i (+ i 1))
+ (io.write bcode (uint32 (aref v i)))
+ (set! i (+ i 1)))
+
+ (else
+ ; other number arguments are always uint8
+ (io.write bcode (uint8 nxt))
+ (set! i (+ i 1)))))
+ (else #f))))))
- ((:loadc.l :setc.l) ; 2 uint32 args
- (io.write bcode (uint32 nxt))
- (set! i (+ i 1))
- (io.write bcode (uint32 (aref v i)))
- (set! i (+ i 1)))
-
- ((:jmp :brf :brt)
- (put! fixup-to-label (sizeof bcode) nxt)
- (io.write bcode ((if long? uint32 uint16) 0))
- (set! i (+ i 1)))
-
- (else #f))))))))
(table.foreach
(lambda (addr labl)
(begin (io.seek bcode addr)
--- a/femtolisp/flisp.boot
+++ b/femtolisp/flisp.boot
@@ -105,7 +105,7 @@
map!
#function("r2\x7f^\x7fF6I02\x7f~\x7fM31O2\x7fNm15402;" [])
map
-#function("r2\x7f?690\x7f;~\x7fM31e0~\x7fN32K;" [map])
+#function("r2c0__L1u43;" [#function("v\x7fm02^\x81F6Q02\x7f\x80\x81M31_KPNm12\x81No015602~N;" [])])
make-system-image
#function("r1c0e1~e2e3e434c5e6u44;" [#function("v^k02c1c2qu42;" [*print-pretty* #function("vc0qc1qt~302;" [#function("r0e0c1qe2e3e430313142;" [for-each #function("r1~E16h02e0~31@16h02e1~31G@16h02e2~i1132@16h02e3e1~3131@6\x950e4i10~322e5i10c6322e4i10e1~31322e5i10c642;^;" [constant? top-level-value memq iostream? io.print io.write "\n"]) reverse! simple-sort environment]) #function("r1\x80302e0~41;" [raise])]) #function("r0e0\x80312i02k1;" [io.close *print-pretty*])]) file :write :create :truncate (*linefeed* *directory-separator* *argv* that *print-pretty* *print-width* *print-readably*) *print-pretty*])
make-label
@@ -181,15 +181,15 @@
error
#function("s0e0c1~K41;" [raise error])
encode-byte-code
-#function("r1c0e1~31u42;" [#function("vc0e1~31u42;" [#function("vc0e1e2~31b3e3c4q\x8032T2yc532u42;" [#function("vc0e1\x8031`e230e230e330^u47;" [#function("v^\x7f~X6\xb102i10\x7f[m52g5e0<6f0e1g2i10\x7fay[e2g431332\x7fb2ym15\xae0e3g4e4e5e6\x8016~02e7g5c8326\x8b0c9g5u325\x8d0g53231322\x7faym12\x7f~X6\xad0c:i10\x7f[u325\xae0^5202e;c<qg3322e=g441;" [:label put! sizeof io.write byte get Instructions memq (:jmp :brt :brf) #function("v~e0=6;0e1;~e2=6E0e3;~e4=6O0e5;^;" [:jmp :jmp.l :brt :brt.l :brf :brf.l]) #function("vc0i05u42;" [#function("ve0~c1326Q0e2i14e3\x8031322i11ayo11;e0~c4326q0e2i14e5\x8031322i11ayo11;e0~c6326\xad0e2i14e5\x8031322i11ayo112e2i14e5i30i11[31322i11ayo11;e0~c7326\xe90e2i14e3\x8031322i11ayo112e2i14e3i30i11[31322i11ayo11;e0~c8326$0e9i13e:i1431\x80332e2i14i206\x130e35\x150e;`31322i11ayo11;^;" [memv (:loadv.l :loadg.l :setg.l :loada.l :seta.l :largc :lvargc) io.write uint32 (:loada :seta :call :tcall :loadv :loadg :setg :list :+ :- :* :/ :vector :argc :vargc :loadi8 :apply :tapply) uint8 (:loadc :setc) (:loadc.l :setc.l) (:jmp :brf :brt) put! sizeof uint16])]) table.foreach #function("r2e0i04~322e1i04i106K0e25M0e3e4i02\x7f323142;" [io.seek io.write uint32 uint16 get]) io.tostring!]) length table buffer]) >= length count #function("r1e0~c142;" [memq (:loadv.l :loadg.l :setg.l :loada.l :seta.l :loadc.l :setc.l :jmp :brt :brf :largc :lvargc)]) 65536]) list->vector]) reverse!])
+#function("r1c0e1~31u42;" [#function("vc0e1~31u42;" [#function("vc0e1e2~31b3e2~31b2VT2yc332u42;" [#function("vc0e1\x8031`e230e230e330^^u48;" [#function("v^\x7f~X6\xea02i10\x7f[m52g5e0<6f0e1g2i10\x7fay[e2g431332\x7fb2ym15\xe70e3g4e4e5e6\x806~0c7g5u325\x800g53231322\x7faym12\x7f~X6\x9b0i10\x7f[5\x9c0^m62e8g5c9326\xd60e1g3e2g431g6332e3g4\x806\xc60e:5\xc80e;`31322\x7faym15\xe70g6D6\xe60c<g5u325\xe70^5202e=c>qg3322e?g441;" [:label put! sizeof io.write byte get Instructions #function("v~e0<6;0e1;~e2<6E0e3;~e4<6O0e5;i05;" [:jmp :jmp.l :brt :brt.l :brf :brf.l]) memq (:jmp :brf :brt) uint32 uint16 #function("ve0~c1326Q0e2i04e3i0631322\x81ayo01;e0~c4326\x890e2i04e5i0631322\x81ayo012e2i04e5i20\x81[31322\x81ayo01;e0~c6326\xc10e2i04e3i0631322\x81ayo012e2i04e3i20\x81[31322\x81ayo01;e2i04e5i0631322\x81ayo01;" [memq (:loadv.l :loadg.l :setg.l :loada.l :seta.l :largc :lvargc) io.write uint32 (:loadc :setc) uint8 (:loadc.l :setc.l)]) table.foreach #function("r2e0i04~322e1i04i106K0e25M0e3e4i02\x7f323142;" [io.seek io.write uint32 uint16 get]) io.tostring!]) length table buffer]) >= length 65536]) list->vector]) reverse!])
emit
-#function("s2e0\x7fc1326K0e2~g2M32L1m25L0^2c3e4\x7fc532u322c6e4\x7fc732u322\x7fe8<6\x980g2c9>6\x810e:m12_m25\x950g2c;>6\x940e<m12_m25\x950^5\x990^2\x7fe=<6\xcb0g2c>>6\xb40e?m12_m25\xc80g2c@>6\xc70eAm12_m25\xc80^5\xcc0^2~`eB\x7fg2K~`[32\\2~;" [memq (:loadv :loadg :setg) bcode:indexfor #function("v~16A02e0i02Mc1326M0e2~31o01;^;" [> 255 cadr]) assq ((:loadv :loadv.l) (:loadg :loadg.l) (:setg :setg.l) (:loada :loada.l) (:seta :seta.l)) #function("v~16S02e0i02Mc13217S02e0e2i0231c1326_0e2~31o01;^;" [> 255 cadr]) ((:loadc :loadc.l) (:setc :setc.l)) :loada (0) :loada0 (1) :loada1 :loadc (0 0) :loadc00 (0 1) :loadc01 nreconc])
+#function("s2g2A6C0~`\x7f~`[K\\5\xec0e0\x7fc1326\\0e2~g2M32L1m25]0^2c3e4\x7fc532u322c6e4\x7fc732u322\x7fe8<6\xa90g2c9>6\x920e:m12_m25\xa60g2c;>6\xa50e<m12_m25\xa60^5\xaa0^2\x7fe=<6\xdc0g2c>>6\xc50e?m12_m25\xd90g2c@>6\xd80eAm12_m25\xd90^5\xdd0^2~`eB\x7fg2K~`[32\\2~;" [memq (:loadv :loadg :setg) bcode:indexfor #function("v~16A02e0i02Mc1326M0e2~31o01;^;" [> 255 cadr]) assq ((:loadv :loadv.l) (:loadg :loadg.l) (:setg :setg.l) (:loada :loada.l) (:seta :seta.l)) #function("v~16S02e0i02Mc13217S02e0e2i0231c1326_0e2~31o01;^;" [> 255 cadr]) ((:loadc :loadc.l) (:setc :setc.l)) :loada (0) :loada0 (1) :loada1 :loadc (0 0) :loadc00 (0 1) :loadc01 nreconc])
div
#function("r2~\x7fV~`X16M02\x7f`X16F02a17M02b/17S02`y;" [])
display
#function("r1e0~312];" [princ])
disassemble
-#function("s1\x7fA6H0e0~`322e1302];5I0^2c2\x7fMe3~31e4~31u44;" [disassemble newline #function("vc0^u42;" [#function("vc0qm02c1`e2\x8131u43;" [#function("r1~J16<02~G@6Q0e0c1312e2~i10ay42;e3~41;" [princ "\n" disassemble print]) #function("v^~\x7fX6K02c0e1c2q^e333u32520;" [#function("ve0\x80`326A0e1305B0^2`i20azc2qw2e3e4\x8031c5e6e7~31a32c8342\x80ayo002c9~u42;" [> newline #function("r1e0c141;" [princ "\t"]) princ hex5 ": " string.tail string "\t" #function("ve0~c1326Y0i20i32e2i31i1032[312i10b4yo10;e0~c3326}0i20i32i31i10[[312i10ayo10;e0~c4326\xa00e5e6i31i10[31312i10ayo10;e0~c7326\xc70e5e6e2i31i103231312i10b4yo10;e0~c8326\x050e5e6i31i10[31c9322i10ayo102e5e6i31i10[31312i10ayo10;e0~c:326K1e5e6e2i31i103231c9322i10b4yo102e5e6e2i31i103231312i10b4yo10;e0~c;326t1e5c<e=e>i31i103231322i10b2yo10;e0~c?326\x9d1e5c<e=e2i31i103231322i10b4yo10;^;" [memv (:loadv.l :loadg.l :setg.l) ref-uint32-LE (:loadv :loadg :setg) (:loada :seta :call :tcall :list :+ :- :* :/ :vector :argc :vargc :loadi8 :apply :tapply) princ number->string (:loada.l :seta.l :largc :lvargc) (:loadc :setc) " " (:loadc.l :setc.l) (:jmp :brf :brt) "@" hex5 ref-uint16-LE (:jmp.l :brf.l :brt.l)])]) table.foldl #function("r3g217F02\x7fi21\x80[<16F02~;" []) Instructions]) length])]) function:code function:vals])
+#function("s1\x7fA6H0e0~`322e1302];5I0^2c2\x7fMe3~31e4~31u44;" [disassemble newline #function("vc0^u42;" [#function("vc0qm02c1`e2\x8131u43;" [#function("r1~J16<02~G@6Q0e0c1312e2~i10ay42;e3~41;" [princ "\n" disassemble print]) #function("v^~\x7fX6K02c0e1c2q^e333u32520;" [#function("ve0\x80`326A0e1305B0^2`i20azc2qw2e3e4\x8031c5e6e7~31a32c8342\x80ayo002c9~u42;" [> newline #function("r1e0c141;" [princ "\t"]) princ hex5 ": " string.tail string "\t" #function("ve0~c1326Y0i20i32e2i31i1032[312i10b4yo10;e0~c3326}0i20i32i31i10[[312i10ayo10;e0~c4326\xa00e5e6i31i10[31312i10ayo10;e0~c7326\xc70e5e6e2i31i103231312i10b4yo10;e0~c8326\x050e5e6i31i10[31c9322i10ayo102e5e6i31i10[31312i10ayo10;e0~c:326K1e5e6e2i31i103231c9322i10b4yo102e5e6e2i31i103231312i10b4yo10;e0~c;326t1e5c<e=e>i31i103231322i10b2yo10;e0~c?326\x9d1e5c<e=e2i31i103231322i10b4yo10;^;" [memq (:loadv.l :loadg.l :setg.l) ref-uint32-LE (:loadv :loadg :setg) (:loada :seta :call :tcall :list :+ :- :* :/ :vector :argc :vargc :loadi8 :apply :tapply) princ number->string (:loada.l :seta.l :largc :lvargc) (:loadc :setc) " " (:loadc.l :setc.l) (:jmp :brf :brt) "@" hex5 ref-uint16-LE (:jmp.l :brf.l :brt.l)])]) table.foldl #function("r3g217F02\x7fi21\x80[<16F02~;" []) Instructions]) length])]) function:code function:vals])
delete-duplicates
#function("r1~?690~;c0~M~Nu43;" [#function("ve0~\x7f326@0e1\x7f41;~e1\x7f31K;" [member delete-duplicates])])
count
@@ -203,7 +203,7 @@
compile-thunk
#function("r1e0c1_~L341;" [compile lambda])
compile-sym
-#function("r4c0e1g2\x7f`]34u42;" [#function("vc0~Mu42;" [#function("v~c0=6J0e1i10i13`[e2\x803143;~c3=6h0e1i10i13a[e2\x8031e4\x803144;e1i10i13b2[i1243;" [arg emit cadr closed caddr])]) lookup-sym])
+#function("r4c0e1g2\x7f`]34u42;" [#function("vc0~Mu42;" [#function("v~c0<6J0e1i10i13`[e2\x803143;~c3<6h0e1i10i13a[e2\x8031e4\x803144;e1i10i13b2[i1243;" [arg emit cadr closed caddr])]) lookup-sym])
compile-short-circuit
#function("r6g3?6C0e0~\x7fg2g444;g3N?6V0e0~\x7fg2g3M44;c1e2~31u42;" [compile-in #function("ve0\x80\x81^i03M342e1\x80e2322e1\x80i05~332e1\x80e3322e4\x80\x81i02i03Ni04i05362e5\x80~42;" [compile-in emit :dup :pop compile-short-circuit mark-label]) make-label])
compile-prog1
@@ -213,7 +213,7 @@
compile-let
#function("r4c0g3Mg3Nu43;" [#function("ve0\x7fe1e2~3131326F0^5Q0e3e4c5~32312e6\x80e7e8\x81~]33332c9e:\x80\x81\x7f33u42;" [length= length cadr error string "apply: incorrect number of arguments to " emit :loadv compile-f #function("ve0i10e1322e0i10i126K0e25M0e3a~y43;" [emit :copyenv :tcall :call]) compile-arglist])])
compile-in
-#function("r4g3C6C0e0~\x7fg3c144;g3?6\xb10g3`<6X0e2~e342;g3a<6g0e2~e442;g3]<6v0e2~e542;g3^<6\x850e2~e642;g3_<6\x940e2~e742;e8g3316\xa70e2~e9g343;e2~e:g343;c;g3Mu42;" [compile-sym [:loada :loadc :loadg] emit :load0 :load1 :loadt :loadf :loadnil fits-i8 :loadi8 :loadv #function("v~c0=6G0e1\x80e2e3i033143;~c4=6[0e5\x80\x81i02i0344;~c6=6p0e7\x80\x81i02i03N44;~c8=6\x810e9\x80\x81i0343;~c:=6\xa00e1\x80e2e;\x81i0332332e1\x80e<42;~c==6\xb50e>\x80\x81i02i03N44;~c?=6\xca0e@\x80\x81i02i03N44;~cA=6\xe90eB\x80\x81e3i0331c6eCi0331K44;~cD=6\x0c0eE\x80\x81e3i0331eFi0331eGi033145;~cH=6*0eI\x80\x81]e3i0331342e1\x80eJ42;~cK=6P1eI\x80\x81^eFi0331342eL\x80\x81e3i0331cM44;~cN=6\x9b1eI\x80\x81^c:_e3i0331L3342eOeFi0331316}1^5\x831ePcQ312eI\x80\x81^eFi0331342e1\x80eR42;eS\x80\x81i02i0344;" [quote emit :loadv cadr if compile-if begin compile-begin prog1 compile-prog1 lambda compile-f :closure and compile-and or compile-or while compile-while cddr for compile-for caddr cadddr return compile-in :ret set! compile-sym [:seta :setc :setg] trycatch 1arg-lambda? error "trycatch: second form must be a 1-argument lambda" :trycatch compile-app])])
+#function("r4g3C6C0e0~\x7fg3c144;g3?6\xb10g3`<6X0e2~e342;g3a<6g0e2~e442;g3]<6v0e2~e542;g3^<6\x850e2~e642;g3_<6\x940e2~e742;e8g3316\xa70e2~e9g343;e2~e:g343;c;g3Mu42;" [compile-sym [:loada :loadc :loadg] emit :load0 :load1 :loadt :loadf :loadnil fits-i8 :loadi8 :loadv #function("v~c0<6G0e1\x80e2e3i033143;~c4<6[0e5\x80\x81i02i0344;~c6<6p0e7\x80\x81i02i03N44;~c8<6\x810e9\x80\x81i0343;~c:<6\xa00e1\x80e2e;\x81i0332332e1\x80e<42;~c=<6\xb50e>\x80\x81i02i03N44;~c?<6\xca0e@\x80\x81i02i03N44;~cA<6\xe90eB\x80\x81e3i0331c6eCi0331K44;~cD<6\x0c0eE\x80\x81e3i0331eFi0331eGi033145;~cH<6*0eI\x80\x81]e3i0331342e1\x80eJ42;~cK<6P1eI\x80\x81^eFi0331342eL\x80\x81e3i0331cM44;~cN<6\x9b1eI\x80\x81^c:_e3i0331L3342eOeFi0331316}1^5\x831ePcQ312eI\x80\x81^eFi0331342e1\x80eR42;eS\x80\x81i02i0344;" [quote emit :loadv cadr if compile-if begin compile-begin prog1 compile-prog1 lambda compile-f :closure and compile-and or compile-or while compile-while cddr for compile-for caddr cadddr return compile-in :ret set! compile-sym [:seta :setc :setg] trycatch 1arg-lambda? error "trycatch: second form must be a 1-argument lambda" :trycatch compile-app])])
compile-if
#function("r4c0e1~31e1~31e2g331e3g331e4g331F6]0e5g3315^0^u46;" [#function("vg2]<6D0e0\x80\x81i02g344;g2^<6W0e0\x80\x81i02g444;e0\x80\x81^g2342e1\x80e2~332e0\x80\x81i02g3342i026\x860e1\x80e3325\x8e0e1\x80e4\x7f332e5\x80~322e0\x80\x81i02g4342e5\x80\x7f42;" [compile-in emit :brf :ret :jmp mark-label]) make-label cadr caddr cdddr cadddr])
compile-for
@@ -221,7 +221,7 @@
compile-f
#function("s2c0e130e2\x7f31u43;" [#function("vi02A@6C0e0~e1325\x970e2\x7fe3326j0e0~e4\x7f31A6^0e55`0e6e7\x7f31335\x970e4\x7f31A6\x820e0~e8e7\x7f31335\x970e0~e9\x7f?6\x900`5\x950e7\x7f31332e:~e;\x7f31\x80K]e<\x8131342e0~e=322e>e?e@~3131eA~3142;" [emit :let length> MAX_ARGS lastcdr :largc :lvargc length :argc :vargc compile-in to-proper caddr :ret function encode-byte-code bcode:code const-to-idx-vec]) make-code-emitter cadr])
compile-call
-#function("r4c0g3Mu42;" [#function("vc0~C16]02e1~\x8132@16]02~E16]02e2~3116]02e3~31G6h0e3~315i0~u42;" [#function("vc0~G16?02e1~31u42;" [#function("v~@6E0e0i20i21^\x80345F0^2c1e2i20i21i23N33u42;" [compile-in #function("v\x806C0c0e1e2\x80^33u42;e3i30i326S0e45U0e5~43;" [#function("v~16A02e0i43N~32@6O0e1i20~325P0^2c2i10u42;" [length= argc-error #function("v~e0=6X0i10`W6J0e1i50e242;e1i50i20i1043;~e3=6\x920i10`W6q0e1i50e442;i10b2W6\x840e1i50e542;e1i50i20i1043;~e6=6\xdd0i10`W6\xaa0e7i30a42;i10aW6\xbc0e1i50e842;i10b2W6\xcf0e1i50e942;e1i50i20i1043;~e:=6\x040i10`W6\xf60e1i50e;42;e1i50i20i1043;~e<=6*0i10`W6\x1c0e7i30a42;e1i50i20i1043;~e==6S1i10`W6E1e1i50e>c?43;e1i50i20i1043;~e@=6\x851i10b2X6m1e7i30b242;e1i50i526}1eA5\x7f1e@i1043;e1i50i2042;" [:list emit :loadnil :+ :load0 :add2 :- argc-error :neg :sub2 :* :load1 :/ :vector :loadv [] :apply :tapply])]) get arg-counts emit :tcall :call]) compile-arglist]) builtin->instruction]) in-env? constant? top-level-value])])
+#function("r4c0g3Mu42;" [#function("vc0~C16]02e1~\x8132@16]02~E16]02e2~3116]02e3~31G6h0e3~315i0~u42;" [#function("vc0~G16?02e1~31u42;" [#function("v~@6E0e0i20i21^\x80345F0^2c1e2i20i21i23N33u42;" [compile-in #function("v\x806C0c0e1e2\x80^33u42;e3i30i326S0e45U0e5~43;" [#function("v~16A02e0i43N~32@6O0e1i20~325P0^2c2i10u42;" [length= argc-error #function("v~e0<6X0i10`W6J0e1i50e242;e1i50i20i1043;~e3<6\x920i10`W6q0e1i50e442;i10b2W6\x840e1i50e542;e1i50i20i1043;~e6<6\xdd0i10`W6\xaa0e7i30a42;i10aW6\xbc0e1i50e842;i10b2W6\xcf0e1i50e942;e1i50i20i1043;~e:<6\x040i10`W6\xf60e1i50e;42;e1i50i20i1043;~e<<6*0i10`W6\x1c0e7i30a42;e1i50i20i1043;~e=<6S1i10`W6E1e1i50e>c?43;e1i50i20i1043;~e@<6\x851i10b2X6m1e7i30b242;e1i50i526}1eA5\x7f1e@i1043;e1i50i2042;" [:list emit :loadnil :+ :load0 :add2 :- argc-error :neg :sub2 :* :load1 :/ :vector :loadv [] :apply :tapply])]) get arg-counts emit :tcall :call]) compile-arglist]) builtin->instruction]) in-env? constant? top-level-value])])
compile-begin
#function("r4g3?6B0e0~\x7fg2^44;g3N?6U0e0~\x7fg2g3M44;e0~\x7f^g3M342e1~e2322e3~\x7fg2g3N44;" [compile-in emit :pop compile-begin])
compile-arglist
@@ -319,6 +319,6 @@
*whitespace*
"\t\n\v\f\r \u0085 \u2028\u2029 "
*syntax-environment*
-#table(define #function("s1~C6?0c0~\x7fML3;c0~Mc1~N\x7fKKL3;" [set! lambda]) letrec #function("s1c0e1e2~32e3e1c4q~32\x7f32KKe1c5q~32K;" [lambda map car nconc #function("r1c0~K;" [set!]) #function("r1^;" [])]) backquote #function("r1e0~41;" [bq-process]) assert #function("r1c0~]c1c2c3~L2L2L2L4;" [if raise quote assert-failed]) label #function("r2c0~L1c1~\x7fL3L3^L2;" [lambda set!]) do #function("s2c0e130\x7fMe2e3~32e2e4~32e2c5q~32u46;" [#function("vc0~c1g2c2\x7fe3c4L1e5\x81N3132e3c4L1e5i0231e3~L1e5g43132L133L4L3L2L1e3~L1e5g33132L3;" [letrec lambda if nconc begin copy-list]) gensym map car cadr #function("r1e0~31F6A0e1~41;~M;" [cddr caddr])]) when #function("s1c0~c1\x7fK^L4;" [if begin]) unwind-protect #function("r2c0e130e130u43;" [#function("vc0\x7fc1_\x81L3L2L1c2c3\x80c1~L1c4\x7fL1c5~L2L3L3L3\x7fL1L3L3;" [let lambda prog1 trycatch begin raise]) gensym]) dotimes #function("s1c0~Me1~31u43;" [#function("vc0`c1\x7faL3e2c3L1~L1L1e4\x813133L4;" [for - nconc lambda copy-list]) cadr]) define-macro #function("s1c0c1~ML2c2~N\x7fKKL3;" [set-syntax! quote lambda]) unless #function("s1c0~^c1\x7fKL4;" [if begin]) let #function("s1c0^u42;" [#function("v\x80C6H0\x80m02\x81Mo002\x81No015I0^2c0c1e2c3q\x8032\x81KKe2c4q\x8032u43;" [#function("v\x806>0c0\x80~L35?0~\x7fK;" [label]) lambda map #function("r1~F6:0~M;~;" []) #function("r1~F6=0e0~41;^;" [cadr])])]) cond #function("s0c0^u42;" [#function("vc0qm02~\x8041;" [#function("r1~?690^;c0~Mu42;" [#function("v~Mc0<17?02~M]<6Q0~NA6K0~M;c1~NK;~NA6e0c2~Mi10\x80N31L3;c3~Mc1~NKi10\x80N31L4;" [else begin or if])])])]) throw #function("r2c0c1c2c3L2~\x7fL4L2;" [raise list quote thrown-value]) time #function("r1c0e130u42;" [#function("vc0~c1L1L2L1c2\x80c3c4c5c1L1~L3c6L4L3L3;" [let time.now prog1 princ "Elapsed time: " - " seconds\n"]) gensym]) let* #function("s1~?6J0e0c1L1_L1e2\x7f3133L1;e0c1L1e3~31L1L1e2~NF6w0e0c4L1~NL1e2\x7f3133L15x0\x7f3133e5~31L2;" [nconc lambda copy-list caar let* cadar]) case #function("s1c0^u42;" [#function("vc0qm02c1e230u42;" [#function("r2\x7fc0<6<0c0;\x7fA6C0^;\x7f?6S0c1~e2\x7f31L3;\x7fNA6e0c1~e2\x7fM31L3;c3~c4\x7fL2L3;" [else eqv? quote-value memv quote]) #function("vc0~i10L2L1e1c2L1e3e4c5qi11323132L3;" [let nconc cond copy-list map #function("r1i10\x80~M32~NK;" [])]) gensym])]) catch #function("r2c0e130u42;" [#function("vc0\x81c1~L1c2c3c4~L2c5c6~L2c7c8L2L3c5c9~L2\x80L3L4c:~L2c;~L2L4L3L3;" [trycatch lambda if and pair? eq car quote thrown-value cadr caddr raise]) gensym]))
+#table(define #function("s1~C6?0c0~\x7fML3;c0~Mc1~N\x7fKKL3;" [set! lambda]) letrec #function("s1c0e1e2~32e3e1c4q~32\x7f32KKe1c5q~32K;" [lambda map car nconc #function("r1c0~K;" [set!]) #function("r1^;" [])]) backquote #function("r1e0~41;" [bq-process]) assert #function("r1c0~]c1c2c3~L2L2L2L4;" [if raise quote assert-failed]) label #function("r2c0~L1c1~\x7fL3L3^L2;" [lambda set!]) do #function("s2c0e130\x7fMe2e3~32e2e4~32e2c5q~32u46;" [#function("vc0~c1g2c2\x7fe3c4L1e5\x81N3132e3c4L1e5i0231e3~L1e5g43132L133L4L3L2L1e3~L1e5g33132L3;" [letrec lambda if nconc begin copy-list]) gensym map car cadr #function("r1e0~31F6A0e1~41;~M;" [cddr caddr])]) when #function("s1c0~c1\x7fK^L4;" [if begin]) unwind-protect #function("r2c0e130e130u43;" [#function("vc0\x7fc1_\x81L3L2L1c2c3\x80c1~L1c4\x7fL1c5~L2L3L3L3\x7fL1L3L3;" [let lambda prog1 trycatch begin raise]) gensym]) dotimes #function("s1c0~Me1~31u43;" [#function("vc0`c1\x7faL3e2c3L1~L1L1e4\x813133L4;" [for - nconc lambda copy-list]) cadr]) define-macro #function("s1c0c1~ML2c2~N\x7fKKL3;" [set-syntax! quote lambda]) unless #function("s1c0~^c1\x7fKL4;" [if begin]) let #function("s1c0^u42;" [#function("v\x80C6H0\x80m02\x81Mo002\x81No015I0^2c0c1e2c3q\x8032\x81KKe2c4q\x8032u43;" [#function("v\x806>0c0\x80~L35?0~\x7fK;" [label]) lambda map #function("r1~F6:0~M;~;" []) #function("r1~F6=0e0~41;^;" [cadr])])]) cond #function("s0c0^u42;" [#function("vc0qm02~\x8041;" [#function("r1~?690^;c0~Mu42;" [#function("v~Mc0<17?02~M]<6Q0~NA6K0~M;c1~NK;~NA6e0c2~Mi10\x80N31L3;c3~Mc1~NKi10\x80N31L4;" [else begin or if])])])]) throw #function("r2c0c1c2c3L2~\x7fL4L2;" [raise list quote thrown-value]) time #function("r1c0e130u42;" [#function("vc0~c1L1L2L1c2\x80c3c4c5c1L1~L3c6L4L3L3;" [let time.now prog1 princ "Elapsed time: " - " seconds\n"]) gensym]) let* #function("s1~?6J0e0c1L1_L1e2\x7f3133L1;e0c1L1e3~31L1L1e2~NF6w0e0c4L1~NL1e2\x7f3133L15x0\x7f3133e5~31L2;" [nconc lambda copy-list caar let* cadar]) case #function("s1c0^u42;" [#function("vc0qm02c1e230u42;" [#function("r2\x7fc0<6<0c0;\x7fA6C0^;\x7fC6S0c1~e2\x7f31L3;\x7f?6c0c3~e2\x7f31L3;\x7fNA6u0c3~e2\x7fM31L3;e4e5\x7f326\x8a0c6~c7\x7fL2L3;c8~c7\x7fL2L3;" [else eq? quote-value eqv? every symbol? memq quote memv]) #function("vc0~i10L2L1e1c2L1e3e4c5qi11323132L3;" [let nconc cond copy-list map #function("r1i10\x80~M32~NK;" [])]) gensym])]) catch #function("r2c0e130u42;" [#function("vc0\x81c1~L1c2c3c4~L2c5c6~L2c7c8L2L3c5c9~L2\x80L3L4c:~L2c;~L2L4L3L3;" [trycatch lambda if and pair? eq car quote thrown-value cadr caddr raise]) gensym]))
*banner*
"; _\n; |_ _ _ |_ _ | . _ _\n; | (-||||_(_)|__|_)|_)\n;-------------------|----------------------------------------------------------\n\n"
--- a/femtolisp/flisp.c
+++ b/femtolisp/flisp.c
@@ -799,7 +799,7 @@
#endif
/*
- stack on entry: <func> <args...>
+ stack on entry: <func> <up to MAX_ARGS args...> <arglist if nargs>MAX_ARGS>
caller's responsibility:
- put the stack in this state
- provide arg count
@@ -819,7 +819,7 @@
uint8_t *code;
// temporary variables (not necessary to preserve across calls)
- uint32_t op;
+ uint8_t op;
symbol_t *sym;
static cons_t *c;
static value_t *pv;
@@ -935,9 +935,10 @@
v = apply_cl(n);
}
else {
- op = uintval(func);
- if (op > OP_ASET)
+ i = uintval(func);
+ if (i > OP_ASET)
type_error("apply", "function", func);
+ op = (uint8_t)i;
s = builtin_arg_counts[op];
if (s >= 0)
argcount(builtin_names[op], n, s);
--- a/femtolisp/system.lsp
+++ b/femtolisp/system.lsp
@@ -21,8 +21,15 @@
(define (symbol-syntax s) (get *syntax-environment* s #f))
(define (map f lst)
- (if (atom? lst) lst
- (cons (f (car lst)) (map f (cdr lst)))))
+ ((lambda (first acc)
+ (begin
+ (set! first acc)
+ (while (pair? lst)
+ (begin (set! acc
+ (cdr (set-cdr! acc (cons (f (car lst)) ()))))
+ (set! lst (cdr lst))))
+ (cdr first)))
+ () (list ())))
(define-macro (label name fn)
(list (list 'lambda (list name) (list 'set! name fn)) #f))
@@ -362,8 +369,11 @@
(define (vals->cond key v)
(cond ((eq? v 'else) 'else)
((null? v) #f)
+ ((symbol? v) `(eq? ,key ,(quote-value v)))
((atom? v) `(eqv? ,key ,(quote-value v)))
((null? (cdr v)) `(eqv? ,key ,(quote-value (car v))))
+ ((every symbol? v)
+ `(memq ,key ',v))
(else `(memv ,key ',v))))
(let ((g (gensym)))
`(let ((,g ,key))
--- a/femtolisp/test.lsp
+++ b/femtolisp/test.lsp
@@ -226,3 +226,35 @@
(sub h n (string.inc h i) (cons i lst))
(reverse! lst))))
(sub haystack needle (if (null? offs) 0 (car offs)) ()))
+
+(let ((*profiles* (table)))
+ (set! profile
+ (lambda (s)
+ (let ((f (top-level-value s)))
+ (set-top-level-value! s
+ (lambda args
+ (define tt (get *profiles* s 0))
+ (define t0 (time.now))
+ (define v (apply f args))
+ (put! *profiles* s (+ tt (- (time.now) t0)))
+ v)))))
+ (set! show-profiles
+ (lambda ()
+ (define (swapad c) (cons (cdr c) (car c)))
+ (for-each (lambda (p)
+ (princ (cdr p) "\t\t" (car p))
+ (newline))
+ (simple-sort (map swapad (table.pairs *profiles*)))))))
+
+#;(for-each profile
+ '(emit encode-byte-code const-to-idx-vec
+ index-of lookup-sym in-env?
+ compile-sym compile-if compile-begin
+ list-partition just-compile-args
+ compile-arglist
+ compile-app compile-let compile-call
+ compile-in compile compile-f
+ map length> length= count filter append
+ lastcdr to-proper reverse reverse! list->vector
+ table.foreach list-head list-tail assq memq assoc member
+ assv memv nreconc bq-process))
--- a/femtolisp/torture.scm
+++ b/femtolisp/torture.scm
@@ -1,19 +1,24 @@
+(define ones (map (lambda (x) 1) (iota 1000000)))
+
+(display (apply + ones))
+(newline)
+
(define (big n)
(if (<= n 0)
0
`(+ 1 1 1 1 1 1 1 1 1 1 ,(big (- n 1)))))
-(define nst `(display ,(big 100000)))
+(define nst (big 100000))
(display (eval nst))
(newline)
+(define longg (cons '+ ones))
+(display (eval longg))
+(newline)
+
(define (f x)
(begin (display x)
(newline)
(f (+ x 1))
0))
-
-(define longg (cons '+ (map (lambda (x) 1) (iota 1000000))))
-(display (eval longg))
-(newline)