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))
29 ;;; Code compress/decompression
32 (define (code-pack code)
34 ((inst (? integer? n))
36 (let ((abbrev (string->symbol (format #f "~A:~A" inst n))))
37 (if (instruction? abbrev) (list abbrev) code)))
39 (let ((double (string->symbol (format #f "~A*2" inst))))
40 (if (instruction? double)
41 (list double (quotient n 256) (modulo n 256))
42 (apply error "Index out of range:" code))))
46 (define (code-unpack code)
47 (let ((inst (symbol->string (car code))))
49 ((string-match "^([^:]*):([0-9]+)$" inst) =>
51 (cons* (string->symbol (match:substring data 1))
52 (string->number (match:substring data 2))
61 (define (object->code x)
62 (cond ((eq? x #t) `(make-true))
63 ((eq? x #f) `(make-false))
64 ((null? x) `(make-eol))
66 (cond ((and (<= -128 x) (< x 128))
67 `(make-int8 ,(modulo x 256)))
68 ((and (<= -32768 x) (< x 32768))
69 (let ((n (if (< x 0) (+ x 65536) x)))
70 `(make-int16 ,(quotient n 256) ,(modulo n 256))))
72 ((char? x) `(make-char8 ,(char->integer x)))
75 (define (code->object code)
78 (('make-false) #f) ;; FIXME: Same as the `else' case!
81 (if (< n 128) n (- n 256)))
83 (let ((n (+ (* n1 256) n2)))
84 (if (< n 32768) n (- n 65536))))
88 (('load-symbol s) (string->symbol s))
89 (('load-keyword s) (symbol->keyword (string->symbol s)))
92 (define (code->bytes code)
93 (let* ((inst (car code))
95 (head (make-string 1 (integer->char (instruction->opcode inst))))
96 (len (instruction-length inst)))
98 ;; Variable-length code
99 (let ((str (car rest)))
100 (string-append head (encode-length (string-length str)) str)))
101 ((= len (length rest))
103 (string-append head (list->string (map integer->char rest))))
105 (error "Invalid code:" code)))))
107 (define-public (make-byte-decoder bytes)
108 (let ((addr 0) (size (string-length bytes)))
110 (let ((byte (char->integer (string-ref bytes addr))))
111 (set! addr (1+ addr))
116 (inst (opcode->instruction (pop)))
117 (n (instruction-length inst))
120 (let* ((end (+ (decode-length pop) addr))
121 (str (substring bytes addr end)))
126 (l '() (cons (pop) l)))
127 ((= n 0) (cons* inst (reverse! l)))))))
133 ;;; Variable-length code
136 (define (encode-length len)
137 (define C integer->char)
139 (cond ((< len 254) (list (C len)))
141 (list (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)