summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLĂ©onard Oest O'Leary <lool4516@gmail.com>2023-05-23 13:41:37 -0400
committerGitHub <noreply@github.com>2023-05-23 13:41:37 -0400
commit13090a80b0db51f0fdecc4c4322bdd3eb2f1e9c3 (patch)
tree53f4114b6b824245559aca7baddb4ec533c07d7c
parent8bc271983f075d002d4ea1dfbc4f44d7736a4961 (diff)
parent6364a8ddc5410d848f444b44cdedd66c4f45d0a7 (diff)
Merge pull request #47 from udem-dlteam/leo-ard/new-encoding
Leo ard/new encoding
-rw-r--r--src/host/js/makefile2
-rw-r--r--src/host/js/rvm.js43
-rw-r--r--src/lib/max.scm2
-rw-r--r--src/makefile4
-rwxr-xr-xsrc/rsc.scm1041
5 files changed, 762 insertions, 330 deletions
diff --git a/src/host/js/makefile b/src/host/js/makefile
index f725a27..40ca8d2 100644
--- a/src/host/js/makefile
+++ b/src/host/js/makefile
@@ -1,4 +1,4 @@
HOST = js
HOST_INTERPRETER = $${JS_HOST_INTERPRETER:-node}
-RSC_MUST_TEST_FEATURES = -f+ js/node
+RSC_MUST_TEST_FEATURES = -f+ js/node; -f+ js/node -e skip
include ../../makefile-common.mk
diff --git a/src/host/js/rvm.js b/src/host/js/rvm.js
index 12482d6..ba187a2 100644
--- a/src/host/js/rvm.js
+++ b/src/host/js/rvm.js
@@ -130,9 +130,50 @@ symtbl = [[0,[accum,n,3],2],symtbl,0];
symbol_ref = (n) => list_tail(symtbl,n)[0];
list_tail = (x,i) => i ? list_tail(x[1],i-1) : x;
+inst_tail = (x,i) => i ? inst_tail(x[2],i-1) : x;
// decode the instruction graph
+if(false){ // @@(feature pipeline-compiler)@@
+
+// @@(feature encoding/skip
+stack = 0;
+
+while (1) {
+ x = get_code();
+ n = x;
+ d = 0;
+ op = -1;
+ while ((d=[20,20,0,10,11,4,9][++op])+(5>op)*2<n) n -= d+(4<op?1:3);
+ //console.log("code : ", x, " arg : ", n, "d : ", d, "op : ", op)
+ if (x>90) {
+ op=5;
+ n = pop();
+ }
+ else {
+ if (!op) stack = [0,stack,0];
+ n = n>=d ? (n==d ? get_int(0) : symbol_ref(get_int(n-d-1))) : op<3 ? symbol_ref(n) : n;
+ if (5<op){
+ //console.log("SKIP ", n)
+ //show_stack()
+ stack = [inst_tail(stack[0], n), stack, 0];
+ continue;
+ } // skip instruction
+ if (4<op) {
+ n = [[n,0,pop()],0,1];
+ if (!stack) break;
+ op=4;
+ }
+ }
+ stack[0] = [op?op-1:0,n,stack[0]];
+}
+// )@@
+
+} // @@(feature pipeline-compiler)@@
+
+
+
+// @@(feature encoding/original
stack = 0;
while (1) {
@@ -154,6 +195,7 @@ while (1) {
}
stack[0] = [op?op-1:0,n,stack[0]];
}
+// )@@
set_global = (x) => { symtbl[0][0] = x; symtbl = symtbl[1]; };
@@ -165,6 +207,7 @@ set_global(NIL);
// RVM core
pc = n[0][2];
+
stack = [0,0,[5,0,0]]; // primordial continuation (executes halt instr.)
push = (x) => ((stack = [x,stack,0]), true);
diff --git a/src/lib/max.scm b/src/lib/max.scm
index 58dfc37..c4e8c7b 100644
--- a/src/lib/max.scm
+++ b/src/lib/max.scm
@@ -1013,7 +1013,7 @@
(define (fold func base lst)
(if (pair? lst)
(fold func (func (car lst) base) (cdr lst))
- acc))
+ base))
(define (error msg info)
(display msg)
diff --git a/src/makefile b/src/makefile
index 6105fd7..22e5d3d 100644
--- a/src/makefile
+++ b/src/makefile
@@ -13,6 +13,10 @@ build-all:
cd host/$$host; $(MAKE) build-all; cd ../..; \
done
+tests/*: all
+ TEST_FILTER="$@" $(MAKE) check
+
+
check:
@if [ "$$HOST" = "" ]; then \
for host in $(HOSTS); do \
diff --git a/src/rsc.scm b/src/rsc.scm
index 74c2fdd..79abb04 100755
--- a/src/rsc.scm
+++ b/src/rsc.scm
@@ -91,7 +91,11 @@
(lambda (port) (read-line port #f)))))
(del-file tmpin)
(del-file tmpout)
- out))))
+ out)))
+
+ (define list1 list)
+ (define list2 list)
+ (define list3 list))
(else
@@ -552,13 +556,14 @@
(define (field2-set! o x) (vector-set! o 2 x) o)
(define (procedure2? o) (instance? o procedure-type))
- (define (make-procedure code env) (rib code env procedure-type))
- (define (procedure-code proc) (field0 proc))
- (define (procedure-env proc) (field1 proc))))
+ (define (make-procedure code env) (c-rib code env procedure-type))
+ (define (procedure-code proc) (c-rib-oper proc))
+ (define (procedure-env proc) (c-rib-opnd proc))
+
+ ))
+
+
-(define (oper pc) (field0 pc))
-(define (opnd pc) (field1 pc))
-(define (next pc) (field2 pc))
;;;----------------------------------------------------------------------------
@@ -592,25 +597,215 @@
(improper-list->list (cdr lst1) (cons (car lst1) lst2))
(reverse (cons lst1 lst2))))
-
+
+;; ====== hashable ribs (or c-ribs, for code ribs) =====
+
+(cond-expand
+
+ (ribbit
+
+ (define c-rib rib)
+ (define c-rib-oper field0)
+ (define c-rib-opnd field1)
+ (define c-rib-next field2)
+ (define c-rib-hash error)
+
+ (define c-rib-oper-set! field0-set!)
+ (define c-rib-opnd-set! field1-set!)
+ (define c-rib-next-set! field2-set!))
+
+ (else
+
+ (define hash-table-c-ribs (make-table))
+
+ (define (make-c-rib field0 field1 field2 hash)
+ (rib field0 (rib field1 hash 0) field2))
+
+ (define (c-rib-oper c-rib) (field0 c-rib))
+ (define (c-rib-opnd c-rib) (field0 (field1 c-rib)))
+ (define (c-rib-next c-rib) (field2 c-rib))
+ (define (c-rib-hash c-rib) (field1 (field1 c-rib)))
+
+ (define (c-rib-oper-set! c-rib v) (field0-set! c-rib v))
+ (define (c-rib-opnd-set! c-rib v) (field0-set! (field1 c-rib) v))
+ (define (c-rib-next-set! c-rib v) (field2-set! c-rib v))
+
+ ;; Creates a rib that is unique and hashable
+ (define (c-rib field0 field1 field2)
+ (let* ((hash-table hash-table-c-ribs)
+ (hash (hash-c-rib field0 field1 field2))
+ (hash-list (table-ref hash-table hash #f))
+ (c-rib-ref (make-c-rib field0 field1 field2 hash)))
+ (if hash-list
+ (let search ((search-iter hash-list))
+ (if (pair? search-iter)
+ (if (c-rib-eq? c-rib-ref (car search-iter))
+ (car search-iter)
+ (search (cdr search-iter)))
+ (begin
+ (table-set! hash-table hash (cons c-rib-ref hash-list))
+ c-rib-ref)))
+ (begin
+ (table-set! hash-table hash (cons c-rib-ref '()))
+ c-rib-ref))))
+
+ ;; Hash combine (taken from Gambit Scheme) https://github.com/gambit/gambit/blob/master/lib/_system%23.scm
+ ;; The FNV1a hash algorithm is adapted to hash values, in
+ ;; particular the hashing constants are used (see
+ ;; https://tools.ietf.org/html/draft-eastlake-fnv-12). Because the
+ ;; hash function result is a fixnum and it needs to give the same
+ ;; result on 32 bit and 64 bit architectures, the constants are
+ ;; adapted to fit in a 32 bit fixnum.
+
+ ;; FNV1a 32 bit constants
+ (define fnv1a-prime-32bits 16777619)
+ (define max-fixnum 4294967296)
+
+
+ (define (hash-combine a b)
+ (modulo
+ (* fnv1a-prime-32bits
+ (+ a b))
+ max-fixnum))
+
+ (define (hash-string str)
+ (fold hash-combine 0 (map char->integer (string->list str))))
+
+ (define (c-rib-eq? c-rib1 c-rib2)
+ (let ((op1 (c-rib-oper c-rib1))
+ (op2 (c-rib-oper c-rib2))
+ (opnd1 (c-rib-opnd c-rib1))
+ (opnd2 (c-rib-opnd c-rib2))
+ (next1 (c-rib-next c-rib1))
+ (next2 (c-rib-next c-rib2))
+ (hash1 (c-rib-hash c-rib1))
+ (hash2 (c-rib-hash c-rib2)))
+
+ (and
+ (or (not hash1) ;; check if hashes are =. If not, we skip
+ (not hash2)
+ (eqv? hash1 hash2))
+
+ (or
+ (eqv? op1 op2) ;;test operand
+ (and (rib? op1) (rib? op2) (c-rib-eq? op1 op2)))
+
+ (or ;; test opnd
+ (eqv? opnd1 opnd2)
+ (and (rib? opnd1) (rib? opnd2) (c-rib-eq? opnd1 opnd2)))
+ (or ;; test next
+ (eqv? next1 next2)
+ (and (rib? next1) (rib? next2) (c-rib-eq? next1 next2))))))
+
+ (define table-hash-size 512)
+
+
+ (define (hash-c-rib field0 field1 field2)
+
+ ;; This is a really simple hashing function. I tested it on the 50-repl test and I got good results
+ ;; having at most 6 elements hashed to the same value with a 512 hash table size. Most hashes had one
+ ;; or two elements inside it.
+
+ (define (op->hash op)
+ (cond
+ ((eq? op jump/call-op) 0)
+ ((eq? op set-op) 1)
+ ((eq? op get-op) 2)
+ ((eq? op const-op) 3)
+ ((eq? op if-op) 4)
+ ((number? op) (+ (abs op) 4))
+ ((rib? op) (c-rib-hash op))
+
+ (else (error "Cannot hash the following instruction : " op))))
+
+ (define (opnd->hash opnd)
+ (cond
+ ((symbol? opnd)
+ (hash-string (symbol->string opnd)))
+ ((number? opnd)
+ (abs opnd))
+ ((rib? opnd)
+ (c-rib-hash opnd))
+ ((eq? '() opnd)
+ 4)
+ ((eq? #f opnd)
+ 5)
+ ((eq? #t opnd)
+ 6)
+ ((string? opnd)
+ (hash-string opnd))
+ ((list? opnd)
+ (fold + 0 (map opnd->hash opnd)))
+ (else (error "Cannot hash the following opnd in a c-rib" opnd))))
+
+ (define (next->hash next)
+ (cond
+ ((number? next)
+ 0)
+ ((rib? next)
+ (c-rib-hash next))
+ (else
+ (error "Cannot hash the next of the following c-rib" next))))
+
+ ;(pp 'rib)
+ ;(pp field0)
+ ;(pp field1)
+
+ ;(pp field2)
+ (modulo (hash-combine
+ (hash-combine
+ (opnd->hash field1)
+ (op->hash field0))
+ (next->hash field2))
+ table-hash-size))
+
+
+
+ ;; helper function to display the hash table
+ (define (display-c-rib c-rib)
+
+ (define (display-obj obj)
+ (if (rib? obj)
+ (string-append
+ "%"
+ (number->string (c-rib-hash obj))
+ "%")
+ (object->string obj)))
+
+ (let ((op (c-rib-oper c-rib))
+ (opnd (c-rib-opnd c-rib))
+ (next (c-rib-next c-rib)))
+ (string-append
+ "["
+ (display-obj op)
+ " "
+ (display-obj opnd)
+ " "
+ (display-obj next)
+ "]")))))
+
+
+
+
+
+
(define (comp ctx expr cont)
- ;(pp (list 'comp (ctx-cte ctx) expr cont))
(cond ((symbol? expr)
(let ((v (lookup expr (ctx-cte ctx) 0)))
(if (eqv? v expr) ;; global?
(let ((g (live? expr (ctx-live ctx))))
(if (and g (constant? g)) ;; constant propagated?
- (rib const-op (cadr (cadr g)) cont)
- (rib get-op v cont)))
- (rib get-op v cont))))
+ (c-rib const-op (cadr (cadr g)) cont)
+ (c-rib get-op v cont)))
+ (c-rib get-op v cont))))
((pair? expr)
(let ((first (car expr)))
(cond ((eqv? first 'quote)
- (rib const-op (cadr expr) cont))
+ (c-rib const-op (cadr expr) cont))
((eqv? first 'set!)
(let ((var (cadr expr)))
@@ -635,7 +830,7 @@
((eqv? first 'if)
(let ((cont-false (comp ctx (cadddr expr) cont)))
(let ((cont-true (comp ctx (caddr expr) cont)))
- (let ((cont-test (rib if-op cont-true cont-false)))
+ (let ((cont-test (c-rib if-op cont-true cont-false)))
(comp ctx (cadr expr) cont-test)))))
((eqv? first 'lambda)
@@ -649,18 +844,18 @@
(if variadic
(improper-list->list params '())
params)))
- (rib const-op
+ (c-rib const-op
(make-procedure
- (rib (+ (* 2 nb-params) (if variadic 1 0))
- 0
- (comp-begin (ctx-cte-set
- ctx
- (extend params
- (cons #f
- (cons #f
- (ctx-cte ctx)))))
- (cddr expr)
- tail))
+ (c-rib (+ (* 2 nb-params) (if variadic 1 0))
+ 0
+ (comp-begin (ctx-cte-set
+ ctx
+ (extend params
+ (cons #f
+ (cons #f
+ (ctx-cte ctx)))))
+ (cddr expr)
+ tail))
'())
(if (null? (ctx-cte ctx))
cont
@@ -705,15 +900,15 @@
(else
;; self-evaluating
- (rib const-op expr cont))))
+ (c-rib const-op expr cont))))
(define (gen-call v cont)
(if (eqv? cont tail)
- (rib jump/call-op v 0) ;; jump
- (rib jump/call-op v cont))) ;; call
+ (c-rib jump/call-op v 0) ;; jump
+ (c-rib jump/call-op v cont))) ;; call
(define (gen-assign ctx v cont)
- (rib set-op v (gen-noop ctx cont)))
+ (c-rib set-op v (gen-noop ctx cont)))
@@ -721,27 +916,27 @@
(let* ((arity-check (memq 'arity-check (ctx-live-features ctx)))
(call-rib
(if arity-check
- (and (rib? cont) (field2 cont))
+ (and (rib? cont) (c-rib-next cont))
(and (rib? cont) cont)))
(call-rib-ok?
(and call-rib
- (eqv? (field0 call-rib) jump/call-op) ;; call?
- (eqv? (field1 call-rib) name)
- (rib? (field2 call-rib)))))
+ (eqv? (c-rib-oper call-rib) jump/call-op) ;; call?
+ (eqv? (c-rib-opnd call-rib) name)
+ (rib? (c-rib-next call-rib)))))
(if arity-check
(and call-rib-ok?
(rib? cont)
- (eqv? (field0 cont) const-op)
- (not (rib? (field1 cont)))) ;; push a number
+ (eqv? (c-rib-oper cont) const-op)
+ (not (rib? (c-rib-opnd cont)))) ;; push a number
call-rib-ok?)))
(define (gen-noop ctx cont)
(if (is-call? ctx 'arg1 cont)
(if (memq 'arity-check (ctx-live-features ctx))
- (field2 (field2 cont)) ;; remove const and pop
- (field2 cont)) ;; remove pop
- (rib const-op 0 cont))) ;; add dummy value for set!
+ (c-rib-next (c-rib-next cont)) ;; remove const and pop
+ (c-rib-next cont)) ;; remove pop
+ (c-rib const-op 0 cont))) ;; add dummy value for set!
(define (comp-bind ctx vars exprs body cont)
(comp-bind* ctx vars exprs ctx body cont))
@@ -764,7 +959,7 @@
(define (add-nb-args ctx nb-args tail)
(if (memq 'arity-check (ctx-live-features ctx))
- (rib const-op
+ (c-rib const-op
nb-args
tail)
tail))
@@ -775,7 +970,7 @@
(add-nb-args
ctx
2
- (rib jump/call-op ;; call
+ (c-rib jump/call-op ;; call
(use-symbol ctx 'arg2)
cont))))
@@ -790,7 +985,7 @@
(add-nb-args
ctx
2
- (rib jump/call-op ;; call
+ (c-rib jump/call-op ;; call
(use-symbol ctx 'arg1)
(comp-begin ctx (cdr exprs) cont)))
cont)))
@@ -817,7 +1012,7 @@
(cons (car vars) (extend (cdr vars) cte))
cte))
-(define tail (rib jump/call-op 'id 0)) ;; jump
+(define tail (c-rib jump/call-op 'id 0)) ;; jump
;;;----------------------------------------------------------------------------
@@ -906,7 +1101,7 @@
(cons 'begin
(append to-add
- (cdr expansion)))))
+ (cons expansion '())))))
(define (detect-features live)
(fold (lambda (x acc)
@@ -975,16 +1170,38 @@
return
0
(make-procedure
- (rib 2 ;; 0 parameters
- 0
- (comp ctx
- expansion
- tail))
+ (c-rib 2 ;; 0 parameters
+ 0
+ (comp ctx
+ expansion
+ tail))
'()))
(vector-set! return 1 exports)
(vector-set! return 2 primitives)
(vector-set! return 3 live-features)
(vector-set! return 4 features)
+
+
+ ;(pp
+ ; (list-sort
+ ; (lambda (x y) (< (car x) (car y)))
+ ; (map (lambda (pair)
+ ; (cons (car pair) (map display-c-rib (cdr pair)))) (table->list hash-table-c-ribs))))
+
+ (if (>= verbosity 3)
+ (begin
+ (display "*** Code expansion: \n")
+ (pp expansion)))
+
+ (if (>= verbosity 3)
+ (begin
+ (display "*** hash-consing table: \n")
+ (pp
+ (list-sort
+ (lambda (x y) (< (car x) (car y)))
+ (map (lambda (pair)
+ (list (car pair) (length (cdr pair)))) (table->list hash-table-c-ribs))))))
+
(if (>= verbosity 2)
(begin
(display "*** RVM code:\n")
@@ -1509,42 +1726,143 @@
;; RVM code encoding.
+;; New encoding, for each instruction. Each instruction is taken separately 'int' et 'sym' and 'const' :
+;; - Number of short encodings
+;; - Number of long encodings
+;; New instruction 'skip'.
+;;
+;; + lonely instruction (if)
+
+;; Old encoding :
+;; - Assumes 3 long encoding for each pair of intruction. Each pair of instruction has a priority
+;; either 'int' or 'sym'. Depending on the priority, the short encoding will be for the 'int'
+;; or 'sym' variant. The 'const' and 'if' is special.
+;; - 'if' has only one code. It pops the two values on top of the stack and creates the if. Its a merge.
+;; - 'const' also has the 'proc' variante. This variante allows to push a rib directly.
+
+
+(define (calculate-start encoding-table)
+ (define counter 0)
+
+ (map
+ (lambda (lst)
+ (let* ((sym (car lst))
+ (size (cadr lst))
+ (return-val (list3 sym size counter)))
+ (set! counter (+ counter size))
+ return-val))
+ encoding-table))
+
+
+(define encoding-original-92
+ (calculate-start
+ '(
+ ;; jump
+ ((jump sym short) 20)
+ ((jump int long) 1)
+ ((jump sym long) 2)
+
+ ((jump int short) 0)
-(define eb 92) ;; encoding base (strings have 92 characters that are not escaped and not space)
-;;(define eb 256)
-(define eb/2 (quotient eb 2))
-
-(define get-int-short 10) ;; 0 <= N <= 9 are encoded with 1 byte
-(define const-int-short 11) ;; 0 <= N <= 10 are encoded with 1 byte
-(define const-proc-short 4) ;; 0 <= N <= 3 are encoded with 1 byte
-(define jump-sym-short 20) ;; 0 <= N <= 19 are encoded with 1 byte
-
-(define call-sym-short (- eb ;; use rest to encode calls to globals
- (+ const-int-short
- (+ const-proc-short
- (+ get-int-short
- (+ jump-sym-short
- 17))))))
-
-(define jump-start 0)
-(define jump-int-start (+ jump-start jump-sym-short))
-(define jump-sym-start (+ jump-int-start 1))
-(define call-start (+ jump-sym-start 2))
-(define call-int-start (+ call-start call-sym-short))
-(define call-sym-start (+ call-int-start 1))
-(define set-start (+ call-sym-start 2))
-(define set-int-start (+ set-start 0))
-(define set-sym-start (+ set-int-start 1))
-(define get-start (+ set-sym-start 2))
-(define get-int-start (+ get-start get-int-short))
-(define get-sym-start (+ get-int-start 1))
-(define const-start (+ get-sym-start 2))
-(define const-int-start (+ const-start const-int-short))
-(define const-sym-start (+ const-int-start 1))
-(define const-proc-start (+ const-sym-start 2))
-(define if-start (+ const-proc-start (+ const-proc-short 1)))
-
-(define (encode proc exports primitives live-features)
+ ;; call
+ ((call sym short) 30)
+ ((call int long) 1)
+ ((call sym long) 2)
+
+ ((call int short) 0)
+
+ ;; set
+ ((set int long) 1)
+ ((set sym long) 2)
+
+ ((set sym short) 0)
+ ((set int short) 0)
+
+ ;; get
+ ((get int short) 10)
+ ((get int long) 1)
+ ((get sym long) 2)
+
+ ((get sym short) 0)
+
+ ;; const
+ ((const int short) 11)
+ ((const int long) 1)
+ ((const sym long) 2)
+
+ ((const proc short) 4)
+ ((const proc long) 1)
+
+ ((const sym short) 0)
+
+ (if 1))))
+
+
+(define encoding-skip-92
+ (calculate-start
+ '(
+ ;; jump
+ ((jump sym short) 20)
+ ((jump int long) 1)
+ ((jump sym long) 2)
+
+ ((jump int short) 0)
+
+ ;; call
+ ((call sym short) 20)
+ ((call int long) 1)
+ ((call sym long) 2)
+
+ ((call int short) 0)
+
+ ;; set
+ ((set int long) 1)
+ ((set sym long) 2)
+
+ ((set sym short) 0)
+ ((set int short) 0)
+
+ ;; get
+ ((get int short) 10)
+ ((get int long) 1)
+ ((get sym long) 2)
+
+ ((get sym short) 0)
+
+ ;; const
+ ((const int short) 11)
+ ((const int long) 1)
+ ((const sym long) 2)
+
+ ((const proc short) 4)
+ ((const proc long) 1)
+
+ ((const sym short) 0)
+
+ ((skip int short) 9)
+ ((skip int long) 1)
+
+ (if 1)
+
+ )))
+
+;(pp encoding-skip-92)
+
+(define (encoding-inst-size encoding entry)
+ (cadr (encoding-inst-get encoding entry)))
+
+(define (encoding-inst-start encoding entry)
+ (caddr (encoding-inst-get encoding entry)))
+
+(define (encoding-inst-get encoding entry)
+ (assoc entry encoding))
+
+(define (encoding-size encoding)
+ (fold + 0 (map cadr encoding)))
+
+(define (encode proc exports primitives live-features encoding)
+
+ (define eb/2 (quotient (encoding-size encoding) 2))
(define syms (make-table))
@@ -1552,68 +1870,68 @@
(define (add-nb-args nb-args tail)
(if (and live-features (memq 'arity-check live-features))
- (rib const-op
- nb-args
- tail)
+ (c-rib const-op
+ nb-args
+ tail)
tail))
(define (build-constant o tail)
(cond ((or (memv o '(#f #t ()))
(assq o built-constants))
(let ((v (constant-global-var o)))
- (rib get-op
- (scan-opnd v 1)
- tail)))
+ (c-rib get-op
+ (scan-opnd v 1)
+ tail)))
((symbol? o)
- (rib const-op
- (scan-opnd o 2)
- tail))
+ (c-rib const-op
+ (scan-opnd o 2)
+ tail))
((number? o)
(if (< o 0)
- (rib const-op
- 0
- (rib const-op
- (- 0 o)
- (add-nb-args
- 2
- (rib jump/call-op
- (scan-opnd '- 0)
- tail))))
- (rib const-op
- o
- tail)))
+ (c-rib const-op
+ 0
+ (c-rib const-op
+ (- 0 o)
+ (add-nb-args
+ 2
+ (c-rib jump/call-op
+ (scan-opnd '- 0)
+ tail))))
+ (c-rib const-op
+ o
+ tail)))
((pair? o)
(build-constant (car o)
(build-constant (cdr o)
- (rib const-op
- pair-type
- (add-nb-args
- 3
- (rib jump/call-op
- (scan-opnd 'rib 0)
- tail))))))
+ (c-rib const-op
+ pair-type
+ (add-nb-args
+ 3
+ (c-rib jump/call-op
+ (scan-opnd 'rib 0)
+ tail))))))
((string? o)
(let ((chars (map char->integer (string->list o))))
(build-constant chars
(build-constant (length chars)
- (rib const-op
- string-type
- (add-nb-args
- 3
- (rib jump/call-op
- (scan-opnd 'rib 0)
- tail)))))))
+ (c-rib const-op
+ string-type
+ (add-nb-args
+ 3
+ (c-rib jump/call-op
+ (scan-opnd 'rib 0)
+ tail)))))))
((vector? o)
(let ((elems (vector->list o)))
(build-constant elems
(build-constant (length elems)
- (rib const-op
- vector-type
- (add-nb-args
- 3
- (rib jump/call-op
- (scan-opnd 'rib 0)
- tail)))))))
+ (c-rib const-op
+ vector-type
+ (add-nb-args
+ 3
+ (c-rib jump/call-op
+ (scan-opnd 'rib 0)
+ tail)))))))
(else
(error "can't build constant" o))))
@@ -1628,19 +1946,19 @@
(define (prim-code sym tail)
(let ((index (cadr (assq sym primitives))))
(if (number? index) ;; if not a number, the primitive is already set in code as (set! p (rib index 0 1))
- (rib const-op
- index
- (rib const-op
- 0
- (rib const-op
- procedure-type
- (add-nb-args
- 3
- (rib jump/call-op
- (scan-opnd 'rib 0)
- (rib set-op
- (scan-opnd sym 3)
- tail))))))
+ (c-rib const-op
+ index
+ (c-rib const-op
+ 0
+ (c-rib const-op
+ procedure-type
+ (add-nb-args
+ 3
+ (c-rib jump/call-op
+ (scan-opnd 'rib 0)
+ (c-rib set-op
+ (scan-opnd sym 3)
+ tail))))))
tail)))
(let loop ((lst (cdr primitives)) ;; skip rib primitive that is predefined
@@ -1660,7 +1978,7 @@
(define (append-code code tail)
(if (eqv? code 0)
tail
- (rib (field0 code) (field1 code) (append-code (field2 code) tail))))
+ (c-rib (c-rib-oper code) (c-rib-opnd code) (append-code (c-rib-next code) tail))))
(define (add-init-constants tail)
(let loop ((lst built-constants) (tail tail))
@@ -1670,15 +1988,21 @@
(v (cadr x))
(code (cddr x)))
(loop (cdr lst)
- (append-code code (rib set-op v tail))))
+ (append-code code (c-rib set-op v tail))))
tail)))
- (define (add-init-code! proc)
- (let ((code (field0 proc)))
- (field2-set! code
- (add-init-primitives
- (add-init-constants
- (field2 code))))))
+ (define (add-init-code proc)
+ (let* ((code (c-rib-oper proc))
+ (new-code (add-init-primitives
+ (add-init-constants
+ (c-rib-next code)))))
+
+ (c-rib (c-rib
+ (c-rib-oper code)
+ (c-rib-opnd code)
+ new-code)
+ (c-rib-opnd proc)
+ (c-rib-next proc))))
(define constant-counter 0)
@@ -1706,7 +2030,7 @@
sym)
(define (scan-proc proc)
- (scan (next (procedure-code proc))))
+ (scan (c-rib-next (procedure-code proc))))
(define (scan-opnd o pos)
(scan-opnd-aux o pos)
@@ -1732,11 +2056,11 @@
(if (rib? code)
(begin
(scan-instr code)
- (scan (next code)))))
+ (scan (c-rib-next code)))))
(define (scan-instr code)
- (let ((op (oper code))
- (o (opnd code)))
+ (let ((op (c-rib-oper code))
+ (o (c-rib-opnd code)))
(cond ((eqv? op if-op)
(scan o))
((eqv? op jump/call-op)
@@ -1749,8 +2073,8 @@
(and (number? o) (>= o 0)))
(scan-opnd o 2) ;; 2 = const
(let ((v (constant-global-var o)))
- (field0-set! code get-op)
- (field1-set! code v)
+ (c-rib-oper-set! code get-op)
+ (c-rib-opnd-set! code v)
(scan-opnd v 1)))) ;; 1 = get
((eqv? op set-op)
(scan-opnd o 3))))) ;; 3 = set
@@ -1777,122 +2101,143 @@
(let ((r (- n (* q eb/2))))
(let ((t (cons (if (eqv? stream end) r (+ r eb/2)) stream)))
(if (= q 0)
- t
- (encode-n-aux q t end))))))
-
- (define (enc-proc proc stream)
- (let ((code (procedure-code proc)))
- (let ((nparams (field0 code)))
- (enc (next code)
- (if (< nparams
- const-proc-short)
- (cons (+ const-proc-start
- nparams)
- stream)
- (encode-long1 (+ const-proc-start
- const-proc-short)
- nparams
- stream))))))
-
-
- (define (enc code stream)
- (if (rib? code)
- (let ((op (oper code)))
- (cond ((eqv? op jump/call-op)
- (if (eqv? 0 (next code)) ;; jump?
-
- (let ((o (opnd code)))
- (cond ((number? o)
- (encode-long1 jump-int-start
- o
- stream))
- ((symbol? o)
- (let ((x (encode-sym o)))
- (if (< x jump-sym-short)
- (cons (+ jump-start x)
- stream)
- (encode-long2 jump-sym-start
- x
- stream))))
- (else
- (error "can't encode jump" o))))
-
- (enc (next code)
- (let ((o (opnd code)))
- (cond ((number? o)
- (encode-long1 call-int-start
- o
- stream))
- ((symbol? o)
- (let ((x (encode-sym o)))
- (if (< x call-sym-short)
- (cons (+ call-start x)
- stream)
- (encode-long2 call-sym-start
- x
- stream))))
- (else
- (error "can't encode call" o)))))))
-
- ((eqv? op set-op)
- (enc (next code)
- (let ((o (opnd code)))
- (cond ((number? o)
- (encode-long1 set-int-start
- o
- stream))
- ((symbol? o)
- (encode-long2 set-sym-start
- (encode-sym o)
- stream))
- (else
- (error "can't encode set" o))))))
-
- ((eqv? op get-op)
- (enc (next code)
- (let ((o (opnd code)))
- (cond ((number? o)
- (if (< o get-int-short)
- (cons (+ get-start o)
- stream)
- (encode-long1 get-int-start
- o
- stream)))
- ((symbol? o)
- (encode-long2 get-sym-start
- (encode-sym o)
- stream))
- (else
- (error "can't encode get" o))))))
-
- ((eqv? op const-op)
- (enc (next code)
- (let ((o (opnd code)))
- (cond ((number? o)
- (if (< o const-int-short)
- (cons (+ const-start o)
- stream)
- (encode-long1 const-int-start
- o
- stream)))
- ((symbol? o)
- (encode-long2 const-sym-start
- (encode-sym o)
- stream))
- ((procedure2? o)
- (enc-proc o stream))
- (else
- (error "can't encode const" o))))))
-
- ((eqv? op if-op)
- (enc (next code)
- (enc (opnd code)
- (cons if-start
- stream))))
+ t
+ (encode-n-aux q t end))))))
+
+ (define (sublist-eq? left right result)
+ (if (and (pair? left)
+ (pair? right)
+ (eqv? (c-rib-oper (car left))
+ (c-rib-oper (car right)))
+ (eqv? (c-rib-opnd (car left))
+ (c-rib-opnd (car right))))
+ (sublist-eq? (cdr left) (cdr right) (cons (car left) result))
+ (reverse result)))
+
+ (define (enc-inst arg op-sym arg-sym encoding-table stream)
+ (let* ((short-key (list3 op-sym arg-sym 'short))
+ (long-key (list3 op-sym arg-sym 'long))
+ (short-size (encoding-inst-size encoding-table short-key))
+ (long-size (encoding-inst-size encoding-table long-key))
+ (short-start (encoding-inst-start encoding-table short-key))
+ (long-start (encoding-inst-start encoding-table long-key)))
+
+ (if (< arg short-size)
+ (cons (+ short-start arg)
+ stream)
+ (cond
+ ((eqv? long-size 1)
+ (encode-long1 long-start arg stream))
+ ((eqv? long-size 2)
+ (encode-long2 long-start arg stream))
+ (else
+ (error "Invalid long size, should be at least one and less than 2" long-size))))))
+
+ (define (encode-to-stream proc encoding)
+ (enc-proc proc encoding #f '()))
+
+ (define (enc-proc arg encoding limit stream)
+ (let ((code (procedure-code arg)))
+ (let ((nparams (c-rib-oper code)))
+ (if (or (eq? limit #f) (> limit 0))
+ (enc (c-rib-next code)
+ encoding
+ (and limit (- limit 1))
+ (enc-inst nparams 'const 'proc encoding stream))
+ steam))))
+
+ (define (reverse-code code tail)
+ (if (rib? (c-rib-next code))
+ (reverse-code (c-rib-next code) (cons code tail))
+ (cons code tail)))
+
+ (define (enc code encoding limit stream)
+ (cond
+ ((not (rib? code)) (error "Rib expected, got :" code))
+ ((and limit (<= limit 0)) stream)
+ (else
+ (let* ((op (c-rib-oper code))
+ (arg (c-rib-opnd code))
+ (next-op (c-rib-next code))
+ (op-sym
+ (cond ((eqv? op jump/call-op)
+ (if (eqv? 0 next-op)
+ 'jump
+ 'call))
+ ((eqv? op set-op)
+ 'set)
+ ((eqv? op get-op)
+ 'get)
+ ((eqv? op const-op)
+ 'const)
+ (else
+ 'special)))
+ (arg-sym
+ (cond ((eqv? 'special op-sym)
+ 'special)
+ ((number? arg)
+ 'int)
+ ((symbol? arg)
+ 'sym)
+ ((and (procedure2? arg) (eqv? 'const op-sym))
+ 'proc)
+ (else
+ (error (string-append "can't encode " (symbol->string op-sym))
+ code)))))
+ (cond
+ ((and (eq? op-sym 'const) ;; special case for encoding procedures
+ (eq? arg-sym 'proc))
+ (enc next-op encoding (and limit (- limit 1)) (enc-proc arg encoding #f stream)))
+ ((not (eq? 'special op-sym)) ;; "normal" encoding
+ (let ((encoded-inst
+ (enc-inst
+ (if (eq? arg-sym 'sym)
+ (encode-sym arg)
+ arg)
+ op-sym
+ arg-sym
+ encoding
+ stream)))
+ (if (eq? 'jump op-sym)
+ encoded-inst
+ (enc next-op
+ encoding
+ (and limit (- limit 1))
+ encoded-inst))))
+ ((eqv? op if-op) ;; special case for if
+ (if (encoding-inst-get encoding '(skip int long)) ;; if optimization
+ (let* ((enc-next (enc (c-rib-next code) encoding (and limit (- limit 1)) '()))
+ (rev-next (reverse-code (c-rib-next code) '()))
+ (rev-opnd (reverse-code (c-rib-opnd code) '()))
+ (sublist (sublist-eq? rev-next rev-opnd '()))
+ (sublist-length (length sublist))
+ (opnd-different-length (- (length rev-opnd) sublist-length))
+ (next-different-length (- (length rev-next) sublist-length))
+ (tail (cons (encoding-inst-start encoding 'if) stream)))
+ (append enc-next
+ (if (pair? sublist)
+ (enc-inst next-different-length
+ 'skip
+ 'int
+ encoding
+ (enc (c-rib-opnd code)
+ encoding
+ opnd-different-length
+ tail))
+ (enc (c-rib-opnd code)
+ encoding
+ #f
+ tail))))
- (else
- (error "unknown op" op))))
- (error "rib expected" '())))
+ (enc (c-rib-next code)
+ encoding
+ (and limit (- limit 1))
+ (enc (c-rib-opnd code)
+ encoding
+ #f
+ (cons (encoding-inst-start encoding 'if) stream)))))
+ (else
+ (error "Cannot encode instruction" code)))))))
(define (ordering sym-descr)
(let ((sym (car sym-descr)))
@@ -1906,16 +2251,16 @@
(scan-proc proc)
- (add-init-code! proc)
+ (let ((proc (add-init-code proc)))
- (let ((lst
- (list-sort
- (lambda (a b)
- (< (ordering b) (ordering a)))
- (table->list syms))))
+ (let ((lst
+ (list-sort
+ (lambda (a b)
+ (< (ordering b) (ordering a)))
+ (table->list syms))))
- (let loop1 ((i 0) (lst lst) (symbols '()))
- (if (and (pair? lst) (< i call-sym-short))
+ (let loop1 ((i 0) (lst lst) (symbols '()))
+ (if (and (pair? lst) (< i (encoding-inst-start encoding '(call sym short))))
(let ((s (car lst)))
(let ((sym (car s)))
(let ((descr (cdr s)))
@@ -1925,49 +2270,49 @@
(loop1 (+ i 1) (cdr lst) (cons symbol symbols)))))))
(let loop2 ((i i) (lst2 lst) (symbols symbols))
(if (pair? lst2)
- (let ((s (car lst2)))
- (let ((sym (car s)))
- (let ((x (assq sym exports)))
- (if x
- (let ((symbol (cdr x)))
+ (let ((s (car lst2)))
+ (let ((sym (car s)))
+ (let ((x (assq sym exports)))
+ (if x
+ (let ((symbol (cdr x)))
+ (let ((descr (cdr s)))
+ (field0-set! descr i)
+ (loop2 (+ i 1) (cdr lst2) (cons symbol symbols))))
+ (loop2 i (cdr lst2) symbols)))))
+ (let loop3 ((i i) (lst3 lst) (symbols symbols))
+ (if (pair? lst3)
+ (let ((s (car lst3)))
+ (let ((sym (car s)))
+ (let ((x (assq sym exports)))
+ (if x
+ (loop3 i (cdr lst3) symbols)
+ (let ((symbol (str->uninterned-symbol "")))
(let ((descr (cdr s)))
(field0-set! descr i)
- (loop2 (+ i 1) (cdr lst2) (cons symbol symbols))))
- (loop2 i (cdr lst2) symbols)))))
- (let loop3 ((i i) (lst3 lst) (symbols symbols))
- (if (pair? lst3)
- (let ((s (car lst3)))
- (let ((sym (car s)))
- (let ((x (assq sym exports)))
- (if x
- (loop3 i (cdr lst3) symbols)
- (let ((symbol (str->uninterned-symbol "")))
- (let ((descr (cdr s)))
- (field0-set! descr i)
- (loop3 (+ i 1) (cdr lst3) (cons symbol symbols))))))))
- (let loop4 ((symbols* symbols))
- (if (and (pair? symbols*)
- (string=? (symbol->str (car symbols*)) ""))
- (loop4 (cdr symbols*))
-
- (let ((stream
- (enc-proc proc '())))
- (string-append
- (stream->string
- (encode-n (- (length symbols)
- (length symbols*))
- '()))
- (string-append
- (string-concatenate
- (map (lambda (s)
- (let ((str (symbol->str s)))
- (list->string
- (reverse (string->list str)))))
- symbols*)
- ",")
- (string-append
- ";"
- (stream->string stream)))))))))))))))
+ (loop3 (+ i 1) (cdr lst3) (cons symbol symbols))))))))
+ (let loop4 ((symbols* symbols))
+ (if (and (pair? symbols*)
+ (string=? (symbol->str (car symbols*)) ""))
+ (loop4 (cdr symbols*))
+
+ (let ((stream (encode-to-stream proc encoding)))
+ ;(pp (cons 'stream stream))
+ (string-append
+ (stream->string
+ (encode-n (- (length symbols)
+ (length symbols*))
+ '()))
+ (string-append
+ (string-concatenate
+ (map (lambda (s)
+ (let ((str (symbol->str s)))
+ (list->string
+ (reverse (string->list str)))))
+ symbols*)
+ ",")
+ (string-append
+ ";"
+ (stream->string stream))))))))))))))))
(define (stream->string stream)
(list->string
@@ -2378,7 +2723,7 @@
(let ((file-content (call-with-input-file path (lambda (port) (read-line port #f)))))
(if (eof-object? file-content) "" file-content)))
-(define (generate-code target verbosity input-path rvm-path minify? host-file proc-exports-and-features) ;features-enabled features-disabled source-vm
+(define (generate-code target verbosity input-path rvm-path minify? host-file encodings proc-exports-and-features) ;features-enabled features-disabled source-vm
(let* ((proc
(vector-ref proc-exports-and-features 0))
(exports
@@ -2390,13 +2735,19 @@
(features
(vector-ref proc-exports-and-features 4))
(encode (lambda (bits)
- (let ((input (string-append
- (if (eqv? bits 92)
- (encode proc exports primitives live-features)
- (error "Cannot encode program with this number of bits" bits))
- (if input-path
- (string-from-file input-path)
- "")) ))
+ (let ((input
+ (string-append
+ (if (assoc bits encodings)
+ (encode
+ proc
+ exports
+ primitives
+ live-features
+ (cadr (assoc bits encodings)))
+ (error "Encoding is not defined for this number of bits : " bits))
+ (if input-path
+ (string-from-file input-path)
+ "")) ))
(if (>= verbosity 1)
(begin
(display "*** RVM code length: ")
@@ -2487,6 +2838,8 @@
#f ;; rvm-path
#f ;; minify?
#f ;; host-file
+ (list1
+ (list2 92 encoding-original-92))
(compile-program
0 ;; verbosity
#f ;; parsed-vm
@@ -2516,7 +2869,7 @@
primitives
features-enabled
features-disabled
- )
+ encoding-name)
;; This version of the compiler reads the program and runtime library
;; source code from files and it supports various options. It can
@@ -2533,7 +2886,32 @@
(if (equal? _target "rvm")
#f
(parse-host-file
- (string->list* vm-source)))))
+ (string->list* vm-source))))
+
+ (encodings (cond
+ ((string=? "original" encoding-name)
+ (list
+ (list 92 encoding-original-92)))
+ ((string=? "skip" encoding-name)
+ (list
+ (list 92 encoding-skip-92)))
+ (else
+ (error "Cannot find encoding :" encoding-name))))
+
+ (features-enabled (cons (string->symbol (string-append "encoding/" encoding-name))
+ features-enabled)))
+
+ ;; Verify that the encoding is on the right number
+ ;; of codes
+ (for-each
+ (lambda (pair)
+ (if (not (eqv? (encoding-size (cadr pair)) (car pair)))
+ (error
+ (string-append
+ "Encoding is not on " (car pair) " but on " (encoding-size (cadr pair)))
+ (cadr pair))))
+ encodings)
+
(set! target _target)
(write-target-code
@@ -2545,6 +2923,7 @@
rvm-path
minify?
host-file
+ encodings
(compile-program
verbosity
host-file
@@ -2567,7 +2946,8 @@
(primitives #f)
(features-enabled '())
(features-disabled '())
- (rvm-path #f))
+ (rvm-path #f)
+ (encoding-name "original"))
(let loop ((args (cdr args)))
(if (pair? args)
@@ -2591,6 +2971,9 @@
((and (pair? rest) (member arg '("-p" "--primitives")))
(set! primitives (read (open-input-string (car rest))))
(loop (cdr rest)))
+ ((and (pair? rest) (member arg '("-e" "--encoding")))
+ (set! encoding-name (car rest))
+ (loop (cdr rest)))
((and (pair? rest) (member arg '("-r" "--rvm")))
(set! rvm-path (car rest))
(loop (cdr rest)))
@@ -2650,7 +3033,9 @@
verbosity
primitives
features-enabled
- features-disabled)))))
+ features-disabled
+ encoding-name
+ )))))
(parse-cmd-line (cmd-line))