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 :export (code-pack code-unpack object->code code->object code->bytes
30 ;;; Code compress/decompression
33 (define (code-pack code)
35 ((inst (? integer? n))
37 (let ((abbrev (string->symbol (format #f "~A:~A" inst n))))
38 (if (instruction? abbrev) (list abbrev) code)))
40 (let ((double (string->symbol (format #f "~A*2" inst))))
41 (if (instruction? double)
42 (list double (quotient n 256) (modulo n 256))
43 (apply error "Index out of range:" code))))
47 (define (code-unpack code)
48 (let ((inst (symbol->string (car code))))
50 ((string-match "^([^:]*):([0-9]+)$" inst) =>
52 (cons* (string->symbol (match:substring data 1))
53 (string->number (match:substring data 2))
62 (define (object->code x)
63 (cond ((eq? x #t) `(make-true))
64 ((eq? x #f) `(make-false))
65 ((null? x) `(make-eol))
66 ((and (integer? x) (exact? x))
67 (cond ((and (<= -128 x) (< x 128))
68 `(make-int8 ,(modulo x 256)))
69 ((and (<= -32768 x) (< x 32768))
70 (let ((n (if (< x 0) (+ x 65536) x)))
71 `(make-int16 ,(quotient n 256) ,(modulo n 256))))
73 ((char? x) `(make-char8 ,(char->integer x)))
76 (define (code->object code)
79 (('make-false) #f) ;; FIXME: Same as the `else' case!
82 (if (< n 128) n (- n 256)))
84 (let ((n (+ (* n1 256) n2)))
85 (if (< n 32768) n (- n 65536))))
89 (('load-symbol s) (string->symbol s))
90 (('load-keyword s) (symbol->keyword (string->symbol s)))
93 (define (code->bytes code)
94 (let* ((inst (car code))
96 (head (make-string 1 (integer->char (instruction->opcode inst))))
97 (len (instruction-length inst)))
99 ;; Variable-length code
100 (let ((str (car rest)))
101 (string-append head (encode-length (string-length str)) str)))
102 ((= len (length rest))
104 (string-append head (list->string (map integer->char rest))))
106 (error "Invalid code:" code)))))
108 (define (make-byte-decoder bytes)
109 (let ((addr 0) (size (string-length bytes)))
111 (let ((byte (char->integer (string-ref bytes addr))))
112 (set! addr (1+ addr))
117 (inst (opcode->instruction (pop)))
118 (n (instruction-length inst))
121 (let* ((end (+ (decode-length pop) addr))
122 (str (substring bytes addr end)))
127 (l '() (cons (pop) l)))
128 ((= n 0) (cons* inst (reverse! l)))))))
134 ;;; Variable-length code
137 (define (encode-length len)
138 (define C integer->char)
139 (cond ((< len 254) (string (C len)))
141 (string (C 254) (C (quotient len 256)) (C (modulo len 256))))
142 ((< len most-positive-fixnum)
144 (C (quotient len (* 256 256 256)))
145 (C (modulo (quotient len (* 256 256)) 256))
146 (C (modulo (quotient len 256) 256))
147 (C (modulo len 256))))
148 (else (error "Too long code length:" len))))
150 (define (decode-length pop)
152 (cond ((< len 254) len)
153 ((= len 254) (+ (* (pop) 256) (pop)))
154 (else (+ (* (pop) 256 256 256)