*** empty log message ***
[bpt/guile.git] / module / system / vm / assemble.scm
index 1e9e2d6..fb87058 100644 (file)
@@ -20,6 +20,7 @@
 ;;; Code:
 
 (define-module (system vm assemble)
+  :use-syntax (system base syntax)
   :use-module (system il glil)
   :use-module (system vm core)
   :use-module (system vm conv)
 ;;; Types
 ;;;
 
-(define-structure (<vm-asm> venv glil body))
-(define-structure (venv parent nexts closure?))
-(define-structure (vmod id))
-(define-structure (vlink module name))
-(define-structure (bytespec nargs nrest nlocs nexts bytes objs closure?))
+(define-record (<vm-asm> venv glil body))
+(define-record (<venv> parent nexts closure?))
+(define-record (<vmod> id))
+(define-record (<vlink> module name))
+(define-record (<bytespec> vars bytes meta objs closure?))
 
 \f
 ;;;
 
 (define (preprocess x e)
   (match x
-    (($ <glil-asm> nargs nrest nlocs nexts body)
-     (let* ((venv (make-venv e nexts #f))
+    (($ <glil-asm> vars body)
+     (let* ((venv (<venv> :parent e :nexts vars.nexts :closure? #f))
            (body (map (lambda (x) (preprocess x venv)) body)))
-       (make-<vm-asm> venv x body)))
+       (<vm-asm> :venv venv :glil x :body body)))
     (($ <glil-external> op depth index)
      (do ((d depth (1- d))
-         (e e (venv-parent e)))
+         (e e e.parent))
         ((= d 0))
-       (set-venv-closure?! e #t))
+       (set! e.closure? #t))
      x)
     (else x)))
 
 
 (define (codegen glil toplevel)
   (match glil
-    (($ <vm-asm> venv ($ <glil-asm> nargs nrest nlocs nexts _) body)
+    (($ <vm-asm> venv ($ <glil-asm> vars _) body)
      (let ((stack '())
+          (bind-alist '())
+          (source-alist '())
           (label-alist '())
           (object-alist '()))
        (define (push-code! code)
                                  (set! object-alist (acons x i object-alist))
                                  i)))))
                  (push-code! `(object-ref ,i))))))
+       (define (current-address)
+        (define (byte-length x)
+          (cond ((string? x) (string-length x))
+                (else 3)))
+        (apply + (map byte-length stack)))
        (define (generate-code x)
         (match x
           (($ <vm-asm> venv)
            (push-object! (codegen x #f))
-           (if (venv-closure? venv) (push-code! `(make-closure))))
+           (if venv.closure? (push-code! `(make-closure))))
+
+          (($ <glil-bind> binds)
+           (let ((binds (map (lambda (v)
+                               (case (cadr v)
+                                 ((argument) (list (car v) #f (caddr v)))
+                                 ((local) (list (car v) #f
+                                                (+ vars.nargs (caddr v))))
+                                 ((external) (list (car v) #t (caddr v)))))
+                             binds)))
+             (set! bind-alist (acons (current-address) binds bind-alist))))
+
+          (($ <glil-unbind>)
+           (set! bind-alist (acons (current-address) #f bind-alist)))
+
+          (($ <glil-source> loc)
+           (set! source-alist (acons (current-address) loc source-alist)))
 
           (($ <glil-void>)
            (push-code! '(void)))
 
           (($ <glil-local> op index)
            (if (eq? op 'ref)
-               (push-code! `(local-ref ,(+ nargs index)))
-               (push-code! `(local-set ,(+ nargs index)))))
+               (push-code! `(local-ref ,(+ vars.nargs index)))
+               (push-code! `(local-set ,(+ vars.nargs index)))))
 
           (($ <glil-external> op depth index)
-           (do ((e venv (venv-parent e))
+           (do ((e venv e.parent)
                 (d depth (1- d))
-                (n 0 (+ n (venv-nexts e))))
+                (n 0 (+ n e.nexts)))
                ((= d 0)
                 (if (eq? op 'ref)
                     (push-code! `(external-ref ,(+ n index)))
                     (push-code! `(external-set ,(+ n index)))))))
 
           (($ <glil-module> op module name)
-           (push-object! (make-vlink #f name)) ;; FIXME: (make-vmod module)
+           (push-object! (<vlink> :module #f :name name))
            (if (eq? op 'ref)
                (push-code! '(variable-ref))
                (push-code! '(variable-set))))
 
           (($ <glil-label> label)
-           (define (byte-length x)
-             (cond ((string? x) (string-length x))
-                   (else 3)))
-           (let ((addr (apply + (map byte-length stack))))
-             (set! label-alist (assq-set! label-alist label addr))))
+           (set! label-alist (assq-set! label-alist label (current-address))))
 
           (($ <glil-branch> inst label)
            (set! stack (cons (list inst label) stack)))
        (for-each generate-code body)
        (let ((bytes (stack->bytes (reverse! stack) label-alist)))
         (if toplevel
-            (bytecode->objcode bytes nlocs nexts)
-            (let ((objs (map car (reverse! object-alist))))
-              (make-bytespec nargs nrest nlocs nexts bytes objs
-                             (venv-closure? venv)))))))))
+            (bytecode->objcode bytes vars.nlocs vars.nexts)
+            (<bytespec> :vars vars :bytes bytes
+                        :meta (if (and (null? bind-alist)
+                                       (null? source-alist))
+                                #f
+                                (cons (reverse! bind-alist)
+                                      (reverse! source-alist)))
+                        :objs (let ((objs (map car (reverse! object-alist))))
+                                (if (null? objs) #f (list->vector objs)))
+                        :closure? venv.closure?)))))))
 
 (define (object-assoc x alist)
-  (if (vlink? x) (assoc x alist) (assq x alist)))
+  (match x
+    (($ <vlink>) (assoc x alist))
+    (else        (assq x alist))))
 
 (define (stack->bytes stack label-alist)
   (let loop ((result '()) (stack stack) (addr 0))
   (let dump! ((x x))
     (cond
      ((object->code x) => push-code!)
-     ((bytespec? x)
+     (else
       (match x
-       (($ bytespec nargs nrest nlocs nexts bytes objs closure?)
+       (($ <bytespec> vars bytes meta objs closure?)
         ;; dump parameters
-        (cond
-         ((and (< nargs 4) (< nlocs 8) (< nexts 4))
-          ;; 8-bit representation
-          (let ((x (+ (* nargs 64) (* nrest 32) (* nlocs 4) nexts)))
-            (push-code! `(make-int8 ,x))))
-         ((and (< nargs 16) (< nlocs 128) (< nexts 16))
-          ;; 16-bit representation
-          (let ((x (+ (* nargs 4096) (* nrest 2048) (* nlocs 16) nexts)))
-            (push-code! `(make-int16 ,(quotient x 256) ,(modulo x 256)))))
-         (else
-          ;; Other cases
-          (push-code! (object->code nargs))
-          (push-code! (object->code nrest))
-          (push-code! (object->code nlocs))
-          (push-code! (object->code nexts))
-          (push-code! (object->code #f))))
+        (let ((nargs vars.nargs) (nrest vars.nrest)
+              (nlocs vars.nlocs) (nexts vars.nexts))
+          (cond
+            ((and (< nargs 4) (< nlocs 8) (< nexts 4))
+             ;; 8-bit representation
+             (let ((x (+ (* nargs 64) (* nrest 32) (* nlocs 4) nexts)))
+               (push-code! `(make-int8 ,x))))
+            ((and (< nargs 16) (< nlocs 128) (< nexts 16))
+             ;; 16-bit representation
+             (let ((x (+ (* nargs 4096) (* nrest 2048) (* nlocs 16) nexts)))
+               (push-code! `(make-int16 ,(quotient x 256) ,(modulo x 256)))))
+            (else
+             ;; Other cases
+             (push-code! (object->code nargs))
+             (push-code! (object->code nrest))
+             (push-code! (object->code nlocs))
+             (push-code! (object->code nexts))
+             (push-code! (object->code #f)))))
         ;; dump object table
-        (cond ((not (null? objs))
-               (for-each dump! objs)
-               (push-code! `(vector ,(length objs)))))
+        (if objs (dump! objs))
+        ;; dump meta data
+        (if meta (dump! meta))
         ;; dump bytecode
-        (push-code! `(load-program ,bytes)))))
-     ((vlink? x)
-      ;;; (dump! (vlink-module x))  ;; FIXME: no module support now
-      (push-code! `(link ,(symbol->string (vlink-name x)))))
-     ((vmod? x)
-      (push-code! `(load-module ,(vmod-id x))))
-     ((and (integer? x) (exact? x))
-      (let ((str (do ((n x (quotient n 256))
-                     (l '() (cons (modulo n 256) l)))
-                    ((= n 0)
-                     (list->string (map integer->char l))))))
-       (push-code! `(load-integer ,str))))
-     ((number? x)
-      (push-code! `(load-number ,(number->string x))))
-     ((string? x)
-      (push-code! `(load-string ,x)))
-     ((symbol? x)
-      (push-code! `(load-symbol ,(symbol->string x))))
-     ((keyword? x)
-      (push-code! `(load-keyword ,(symbol->string (keyword-dash-symbol x)))))
-     ((list? x)
-      (for-each dump! x)
-      (push-code! `(list ,(length x))))
-     ((pair? x)
-      (dump! (car x))
-      (dump! (cdr x))
-      (push-code! `(cons)))
-     ((vector? x)
-      (for-each dump! (vector->list x))
-      (push-code! `(vector ,(vector-length x))))
-     (else
-      (error "Cannot dump:" x)))))
+        (push-code! `(load-program ,bytes)))
+       (($ <vlink> module name)
+        ;; FIXME: dump module
+        (push-code! `(link ,(symbol->string name))))
+       (($ <vmod> id)
+        (push-code! `(load-module ,id)))
+       ((and ($ integer) ($ exact))
+        (let ((str (do ((n x (quotient n 256))
+                        (l '() (cons (modulo n 256) l)))
+                       ((= n 0)
+                        (list->string (map integer->char l))))))
+          (push-code! `(load-integer ,str))))
+       (($ number)
+        (push-code! `(load-number ,(number->string x))))
+       (($ string)
+        (push-code! `(load-string ,x)))
+       (($ symbol)
+        (push-code! `(load-symbol ,(symbol->string x))))
+       (($ keyword)
+        (push-code! `(load-keyword
+                      ,(symbol->string (keyword-dash-symbol x)))))
+       (($ list)
+        (for-each dump! x)
+        (push-code! `(list ,(length x))))
+       (($ pair)
+        (dump! (car x))
+        (dump! (cdr x))
+        (push-code! `(cons)))
+       (($ vector)
+        (for-each dump! (vector->list x))
+        (push-code! `(vector ,(vector-length x))))
+       (else
+        (error "Cannot dump:" x)))))))