1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-02 13:00:26 +02:00
guile/module/language/assembly.scm
Michael Gran 904a78f11d Add 32-bit characters
This adds the 32-bit standalone characters.  Strings are still
8-bit.  Characters larger than 8-bit can only be entered or
displayed in octal format at this point.  At this point, the
terminal's display encoding is expected to be Latin-1.

        * module/language/assembly/compile-bytecode.scm (write-bytecode):
        add 32-bit char

        * module/language/assembly.scm (object->assembly): add 32-bit char
        (assembly->object): add 32-bit char

        * libguile/vm-i-system.c (make-char32): new op

        * libguile/print.c (iprin1): print 32-bit char

        * libguile/numbers.h: add type scm_t_wchar

        * libguile/numbers.c: add type scm_t_wchar

        * libguile/chars.h: new type scm_t_wchar
        (SCM_CODEPOINT_MAX): new
        (SCM_IS_UNICODE_CHAR): new
        (SCM_MAKE_CHAR): operate on 32-bit char

        * libguile/chars.c: comparison operators now use Unicode
        codepoints
        (scm_c_upcase): now receives and returns scm_t_wchar
        (scm_c_downcase): now receives and returns scm_t_wchar
2009-07-29 06:38:32 -07:00

171 lines
5.4 KiB
Scheme
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; Guile Virtual Machine Assembly
;; Copyright (C) 2001, 2009 Free Software Foundation, Inc.
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;;; Code:
(define-module (language assembly)
#:use-module (rnrs bytevector)
#:use-module (system base pmatch)
#:use-module (system vm instruction)
#:use-module ((srfi srfi-1) #:select (fold))
#:export (byte-length
addr+ align-program align-code align-block
assembly-pack assembly-unpack
object->assembly assembly->object))
;; nargs, nrest, nlocs, len, metalen, padding
(define *program-header-len* (+ 1 1 2 4 4 4))
;; lengths are encoded in 3 bytes
(define *len-len* 3)
(define (byte-length assembly)
(pmatch assembly
(,label (guard (not (pair? label)))
0)
((load-unsigned-integer ,str)
(+ 1 *len-len* (string-length str)))
((load-integer ,str)
(+ 1 *len-len* (string-length str)))
((load-number ,str)
(+ 1 *len-len* (string-length str)))
((load-string ,str)
(+ 1 *len-len* (string-length str)))
((load-symbol ,str)
(+ 1 *len-len* (string-length str)))
((load-keyword ,str)
(+ 1 *len-len* (string-length str)))
((load-array ,bv)
(+ 1 *len-len* (bytevector-length bv)))
((define ,str)
(+ 1 *len-len* (string-length str)))
((load-program ,nargs ,nrest ,nlocs ,labels ,len ,meta . ,code)
(+ 1 *program-header-len* len (if meta (1- (byte-length meta)) 0)))
((,inst . _) (guard (>= (instruction-length inst) 0))
(+ 1 (instruction-length inst)))
(else (error "unknown instruction" assembly))))
(define *program-alignment* 8)
(define *block-alignment* 8)
(define (addr+ addr code)
(fold (lambda (x len) (+ (byte-length x) len))
addr
code))
(define (code-alignment addr alignment header-len)
(make-list (modulo (- alignment
(modulo (+ addr header-len) alignment))
alignment)
'(nop)))
(define (align-block addr)
(code-alignment addr *block-alignment* 0))
(define (align-code code addr alignment header-len)
`(,@(code-alignment addr alignment header-len)
,code))
(define (align-program prog addr)
(align-code prog addr *program-alignment* 1))
;;;
;;; Code compress/decompression
;;;
(define *abbreviations*
'(((make-int8 0) . (make-int8:0))
((make-int8 1) . (make-int8:1))))
(define *expansions*
(map (lambda (x) (cons (cdr x) (car x))) *abbreviations*))
(define (assembly-pack code)
(or (assoc-ref *abbreviations* code)
code))
(define (assembly-unpack code)
(or (assoc-ref *expansions* code)
code))
;;;
;;; Encoder/decoder
;;;
(define (object->assembly x)
(cond ((eq? x #t) `(make-true))
((eq? x #f) `(make-false))
((null? x) `(make-eol))
((and (integer? x) (exact? x))
(cond ((and (<= -128 x) (< x 128))
(assembly-pack `(make-int8 ,(modulo x 256))))
((and (<= -32768 x) (< x 32768))
(let ((n (if (< x 0) (+ x 65536) x)))
`(make-int16 ,(quotient n 256) ,(modulo n 256))))
((and (<= 0 x #xffffffffffffffff))
`(make-uint64 ,@(bytevector->u8-list
(let ((bv (make-bytevector 8)))
(bytevector-u64-set! bv 0 x (endianness big))
bv))))
((and (<= 0 (+ x #x8000000000000000) #x7fffffffffffffff))
`(make-int64 ,@(bytevector->u8-list
(let ((bv (make-bytevector 8)))
(bytevector-s64-set! bv 0 x (endianness big))
bv))))
(else #f)))
((char? x)
(cond ((<= (char->integer x) #xff)
`(make-char8 ,(char->integer x)))
(else
`(make-char32 ,(char->integer x)))))
(else #f)))
(define (assembly->object code)
(pmatch code
((make-true) #t)
((make-false) #f) ;; FIXME: Same as the `else' case!
((make-eol) '())
((make-int8 ,n)
(if (< n 128) n (- n 256)))
((make-int16 ,n1 ,n2)
(let ((n (+ (* n1 256) n2)))
(if (< n 32768) n (- n 65536))))
((make-uint64 ,n1 ,n2 ,n3 ,n4 ,n5 ,n6 ,n7 ,n8)
(bytevector-u64-ref
(u8-list->bytevector (list n1 n2 n3 n4 n5 n6 n7 n8))
0
(endianness big)))
((make-int64 ,n1 ,n2 ,n3 ,n4 ,n5 ,n6 ,n7 ,n8)
(bytevector-s64-ref
(u8-list->bytevector (list n1 n2 n3 n4 n5 n6 n7 n8))
0
(endianness big)))
((make-char8 ,n)
(integer->char n))
((make-char32 ,n1 ,n2 ,n3 ,n4)
(integer->char (+ (* n1 #x1000000)
(* n2 #x10000)
(* n3 #x100)
n4)))
((load-string ,s) s)
((load-symbol ,s) (string->symbol s))
((load-keyword ,s) (symbol->keyword (string->symbol s)))
(else #f)))