1 ;;; Guile VM code converters
3 ;; Copyright (C) 2001 Free Software Foundation, Inc.
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation; either version 2, or (at your option)
10 ;; This program is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;; GNU General Public License for more details.
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this program; see the file COPYING. If not, write to
17 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 ;; Boston, MA 02111-1307, USA.
22 (define-module (system vm conv)
23 :use-module (system vm core)
24 :use-module (ice-9 match)
25 :use-module (ice-9 regex)
26 :use-module (srfi srfi-4)
27 :export (code-pack code-unpack object->code code->object code->bytes
31 ;;; Code compress/decompression
34 (define (code-pack code)
36 ((inst (? integer? n))
38 (let ((abbrev (string->symbol (format #f "~A:~A" inst n))))
39 (if (instruction? abbrev) (list abbrev) code)))
43 (define (code-unpack code)
44 (let ((inst (symbol->string (car code))))
46 ((string-match "^([^:]*):([0-9]+)$" inst) =>
48 (cons* (string->symbol (match:substring data 1))
49 (string->number (match:substring data 2))
58 (define (object->code x)
59 (cond ((eq? x #t) `(make-true))
60 ((eq? x #f) `(make-false))
61 ((null? x) `(make-eol))
62 ((and (integer? x) (exact? x))
63 (cond ((and (<= -128 x) (< x 128))
64 `(make-int8 ,(modulo x 256)))
65 ((and (<= -32768 x) (< x 32768))
66 (let ((n (if (< x 0) (+ x 65536) x)))
67 `(make-int16 ,(quotient n 256) ,(modulo n 256))))
69 ((char? x) `(make-char8 ,(char->integer x)))
72 (define (code->object code)
75 (('make-false) #f) ;; FIXME: Same as the `else' case!
78 (if (< n 128) n (- n 256)))
80 (let ((n (+ (* n1 256) n2)))
81 (if (< n 32768) n (- n 65536))))
85 (('load-symbol s) (string->symbol s))
86 (('load-keyword s) (make-keyword-from-dash-symbol (string->symbol s)))
89 (define (code->bytes code)
90 (let* ((code (code-pack code))
93 (len (instruction-length inst))
94 (head (instruction->opcode inst)))
96 ;; Variable-length code
97 ;; Typical instructions are `link' and `load-program'.
98 (let* ((str (car rest))
99 (str-len (u8vector-length str))
100 (encoded-len (encode-length str-len))
101 (encoded-len-len (u8vector-length encoded-len)))
103 (append (cons head (u8vector->list encoded-len))
104 (u8vector->list str)))))
105 ((= len (length rest))
107 (apply u8vector (cons head rest)))
109 (error "Invalid code:" code)))))
111 ; (let ((c->b code->bytes))
112 ; ;; XXX: Debugging output
115 ; (format #t "code->bytes: ~a~%" code)
116 ; (let ((result (c->b code)))
117 ; (format #t "code->bytes: returned ~a~%" result)
121 (define (make-byte-decoder bytes)
122 (let ((addr 0) (size (u8vector-length bytes)))
124 (let ((byte (char->integer (u8vector-ref bytes addr))))
125 (set! addr (1+ addr))
130 (inst (opcode->instruction (pop)))
131 (n (instruction-length inst))
134 (let* ((end (+ (decode-length pop) addr))
136 (list-tail (u8vector->list
143 (l '() (cons (pop) l)))
144 ((= n 0) (cons* inst (reverse! l)))))))
150 ;;; Variable-length interface
153 ;; NOTE: decoded in vm_fetch_length in vm.c as well.
155 (define (encode-length len)
156 (cond ((< len 254) (u8vector len))
158 (u8vector 254 (quotient len 256) (modulo len 256)))
159 ((< len most-positive-fixnum)
161 (quotient len (* 256 256 256))
162 (modulo (quotient len (* 256 256)) 256)
163 (modulo (quotient len 256) 256)
165 (else (error "Too long code length:" len))))
167 (define (decode-length pop)
169 (cond ((< len 254) len)
170 ((= len 254) (+ (* (pop) 256) (pop)))
171 (else (+ (* (pop) 256 256 256)