~ chicken-core (chicken-5) 67b43481415918b74e09639d6058d40dd7d9f586
commit 67b43481415918b74e09639d6058d40dd7d9f586 Author: felix <felix@call-with-current-continuation.org> AuthorDate: Sun Nov 22 12:37:35 2009 +0100 Commit: felix <felix@call-with-current-continuation.org> CommitDate: Thu Dec 3 17:15:40 2009 +0100 replaced silex with feeley's compiler diff --git a/distribution/manifest b/distribution/manifest index 128ff8ff..e0efa5d0 100644 --- a/distribution/manifest +++ b/distribution/manifest @@ -199,7 +199,8 @@ tests/re-tests.txt tests/lolevel-tests.scm tests/feeley-dynwind.scm tests/compiler-syntax-tests.scm -tests/silex.scm +tests/compiler.scm +tests/fft.scm tweaks.scm utils.scm apply-hack.x86.S diff --git a/tests/compiler.scm b/tests/compiler.scm new file mode 100644 index 00000000..8a63a77e --- /dev/null +++ b/tests/compiler.scm @@ -0,0 +1,11725 @@ +(define compiler-iters 300) + +(define (fatal-error . args) + (for-each display args) + (newline) + (exit 1)) + + (define (call-with-output-file/truncate filename proc) + (call-with-output-file filename proc)) + +(define (run-bench name count ok? run) + (let loop ((i count) (result '(undefined))) + (if (< 0 i) + (loop (- i 1) (run)) + result))) + +(define (run-benchmark name count ok? run-maker . args) + (newline) + (let* ((run (apply run-maker args)) + (result (run-bench name count ok? run))) + (if (not (ok? result)) + (begin + (display "*** wrong result ***") + (newline) + (display "*** got: ") + (pp result) + (newline)))) + (exit 0)) +;(define integer->char ascii->char) +;(define char->integer char->ascii) + +(define open-input-file* open-input-file) +(define (pp-expression expr port) (write expr port) (newline port)) +(define (write-returning-len obj port) (write obj port) 1) +(define (display-returning-len obj port) (display obj port) 1) +(define (write-word w port) + (write-char (integer->char (quotient w 256)) port) + (write-char (integer->char (modulo w 256)) port)) +(define char-nul (integer->char 0)) +(define char-tab (integer->char 9)) +(define char-newline (integer->char 10)) +(define character-encoding char->integer) +(define max-character-encoding 255) +(define (fatal-err msg arg) (fatal-error msg arg)) +(define (scheme-global-var name) name) +(define (scheme-global-var-ref var) (scheme-global-eval var fatal-err)) +(define (scheme-global-var-set! var val) + (scheme-global-eval (list 'set! var (list 'quote val)) fatal-err)) +(define (scheme-global-eval expr err) `(eval ,expr)) ;; eval not needed for test +(define (pinpoint-error filename line char) #t) +(define file-path-sep #\:) +(define file-ext-sep #\.) +(define (path-absolute? x) + (and (> (string-length x) 0) + (let ((c (string-ref x 0))) (or (char=? c #\/) (char=? c #\~))))) +(define (file-path x) + (let loop1 ((i (string-length x))) + (if (and (> i 0) (not (char=? (string-ref x (- i 1)) file-path-sep))) + (loop1 (- i 1)) + (let ((result (make-string i))) + (let loop2 ((j (- i 1))) + (if (< j 0) + result + (begin + (string-set! result j (string-ref x j)) + (loop2 (- j 1))))))))) +(define (file-name x) + (let loop1 ((i (string-length x))) + (if (and (> i 0) (not (char=? (string-ref x (- i 1)) file-path-sep))) + (loop1 (- i 1)) + (let ((result (make-string (- (string-length x) i)))) + (let loop2 ((j (- (string-length x) 1))) + (if (< j i) + result + (begin + (string-set! result (- j i) (string-ref x j)) + (loop2 (- j 1))))))))) +(define (file-ext x) + (let loop1 ((i (string-length x))) + (if (or (= i 0) (char=? (string-ref x (- i 1)) file-path-sep)) + #f + (if (not (char=? (string-ref x (- i 1)) file-ext-sep)) + (loop1 (- i 1)) + (let ((result (make-string (- (string-length x) i)))) + (let loop2 ((j (- (string-length x) 1))) + (if (< j i) + result + (begin + (string-set! result (- j i) (string-ref x j)) + (loop2 (- j 1)))))))))) +(define (file-root x) + (let loop1 ((i (string-length x))) + (if (or (= i 0) (char=? (string-ref x (- i 1)) file-path-sep)) + x + (if (not (char=? (string-ref x (- i 1)) file-ext-sep)) + (loop1 (- i 1)) + (let ((result (make-string (- i 1)))) + (let loop2 ((j (- i 2))) + (if (< j 0) + result + (begin + (string-set! result j (string-ref x j)) + (loop2 (- j 1)))))))))) +(define (make-counter next limit limit-error) + (lambda () + (if (< next limit) + (let ((result next)) (set! next (+ next 1)) result) + (limit-error)))) +(define (pos-in-list x l) + (let loop ((l l) (i 0)) + (cond ((not (pair? l)) #f) + ((eq? (car l) x) i) + (else (loop (cdr l) (+ i 1)))))) +(define (string-pos-in-list x l) + (let loop ((l l) (i 0)) + (cond ((not (pair? l)) #f) + ((string=? (car l) x) i) + (else (loop (cdr l) (+ i 1)))))) +(define (nth-after l n) + (let loop ((l l) (n n)) (if (> n 0) (loop (cdr l) (- n 1)) l))) +(define (pair-up l1 l2) + (define (pair l1 l2) + (if (pair? l1) + (cons (cons (car l1) (car l2)) (pair (cdr l1) (cdr l2))) + '())) + (pair l1 l2)) +(define (my-last-pair l) + (let loop ((l l)) (if (pair? (cdr l)) (loop (cdr l)) l))) +(define (sort-list l <?) + (define (mergesort l) + (define (merge l1 l2) + (cond ((null? l1) l2) + ((null? l2) l1) + (else + (let ((e1 (car l1)) (e2 (car l2))) + (if (<? e1 e2) + (cons e1 (merge (cdr l1) l2)) + (cons e2 (merge l1 (cdr l2)))))))) + (define (split l) + (if (or (null? l) (null? (cdr l))) l (cons (car l) (split (cddr l))))) + (if (or (null? l) (null? (cdr l))) + l + (let* ((l1 (mergesort (split l))) (l2 (mergesort (split (cdr l))))) + (merge l1 l2)))) + (mergesort l)) +(define (lst->vector l) + (let* ((n (length l)) (v (make-vector n))) + (let loop ((l l) (i 0)) + (if (pair? l) + (begin (vector-set! v i (car l)) (loop (cdr l) (+ i 1))) + v)))) +(define (vector->lst v) + (let loop ((l '()) (i (- (vector-length v) 1))) + (if (< i 0) l (loop (cons (vector-ref v i) l) (- i 1))))) +(define (lst->string l) + (let* ((n (length l)) (s (make-string n))) + (let loop ((l l) (i 0)) + (if (pair? l) + (begin (string-set! s i (car l)) (loop (cdr l) (+ i 1))) + s)))) +(define (string->lst s) + (let loop ((l '()) (i (- (string-length s) 1))) + (if (< i 0) l (loop (cons (string-ref s i) l) (- i 1))))) +(define (with-exception-handling proc) + (let ((old-exception-handler throw-to-exception-handler)) + (let ((val (call-with-current-continuation + (lambda (cont) + (set! throw-to-exception-handler cont) + (proc))))) + (set! throw-to-exception-handler old-exception-handler) + val))) +(define (throw-to-exception-handler val) + (fatal-err "Internal error, no exception handler at this point" val)) +(define (compiler-error msg . args) + (newline) + (display "*** ERROR -- ") + (display msg) + (for-each (lambda (x) (display " ") (write x)) args) + (newline) + (compiler-abort)) +(define (compiler-user-error loc msg . args) + (newline) + (display "*** ERROR -- In ") + (locat-show loc) + (newline) + (display "*** ") + (display msg) + (for-each (lambda (x) (display " ") (write x)) args) + (newline) + (compiler-abort)) +(define (compiler-internal-error msg . args) + (newline) + (display "*** ERROR -- Compiler internal error detected") + (newline) + (display "*** in procedure ") + (display msg) + (for-each (lambda (x) (display " ") (write x)) args) + (newline) + (compiler-abort)) +(define (compiler-limitation-error msg . args) + (newline) + (display "*** ERROR -- Compiler limit reached") + (newline) + (display "*** ") + (display msg) + (for-each (lambda (x) (display " ") (write x)) args) + (newline) + (compiler-abort)) +(define (compiler-abort) (throw-to-exception-handler #f)) +(define (make-gnode label edges) (vector label edges)) +(define (gnode-label x) (vector-ref x 0)) +(define (gnode-edges x) (vector-ref x 1)) +(define (transitive-closure graph) + (define changed? #f) + (define (closure edges) + (list->set + (set-union + edges + (apply set-union + (map (lambda (label) (gnode-edges (gnode-find label graph))) + (set->list edges)))))) + (let ((new-graph + (set-map (lambda (x) + (let ((new-edges (closure (gnode-edges x)))) + (if (not (set-equal? new-edges (gnode-edges x))) + (set! changed? #t)) + (make-gnode (gnode-label x) new-edges))) + graph))) + (if changed? (transitive-closure new-graph) new-graph))) +(define (gnode-find label graph) + (define (find label l) + (cond ((null? l) #f) + ((eq? (gnode-label (car l)) label) (car l)) + (else (find label (cdr l))))) + (find label (set->list graph))) +(define (topological-sort graph) + (if (set-empty? graph) + '() + (let ((to-remove (or (remove-no-edges graph) (remove-cycle graph)))) + (let ((labels (set-map gnode-label to-remove))) + (cons labels + (topological-sort + (set-map (lambda (x) + (make-gnode + (gnode-label x) + (set-difference (gnode-edges x) labels))) + (set-difference graph to-remove)))))))) +(define (remove-no-edges graph) + (let ((nodes-with-no-edges + (set-keep (lambda (x) (set-empty? (gnode-edges x))) graph))) + (if (set-empty? nodes-with-no-edges) #f nodes-with-no-edges))) +(define (remove-cycle graph) + (define (remove l) + (let ((edges (gnode-edges (car l)))) + (define (equal-edges? x) (set-equal? (gnode-edges x) edges)) + (define (member-edges? x) (set-member? (gnode-label x) edges)) + (if (set-member? (gnode-label (car l)) edges) + (let ((edge-graph (set-keep member-edges? graph))) + (if (set-every? equal-edges? edge-graph) + edge-graph + (remove (cdr l)))) + (remove (cdr l))))) + (remove (set->list graph))) +(define (list->set list) list) +(define (set->list set) set) +(define (set-empty) '()) +(define (set-empty? set) (null? set)) +(define (set-member? x set) (memq x set)) +(define (set-singleton x) (list x)) +(define (set-adjoin set x) (if (memq x set) set (cons x set))) +(define (set-remove set x) + (cond ((null? set) '()) + ((eq? (car set) x) (cdr set)) + (else (cons (car set) (set-remove (cdr set) x))))) +(define (set-equal? s1 s2) + (cond ((null? s1) (null? s2)) + ((memq (car s1) s2) (set-equal? (cdr s1) (set-remove s2 (car s1)))) + (else #f))) +(define (set-difference set . other-sets) + (define (difference s1 s2) + (cond ((null? s1) '()) + ((memq (car s1) s2) (difference (cdr s1) s2)) + (else (cons (car s1) (difference (cdr s1) s2))))) + (n-ary difference set other-sets)) +(define (set-union . sets) + (define (union s1 s2) + (cond ((null? s1) s2) + ((memq (car s1) s2) (union (cdr s1) s2)) + (else (cons (car s1) (union (cdr s1) s2))))) + (n-ary union '() sets)) +(define (set-intersection set . other-sets) + (define (intersection s1 s2) + (cond ((null? s1) '()) + ((memq (car s1) s2) (cons (car s1) (intersection (cdr s1) s2))) + (else (intersection (cdr s1) s2)))) + (n-ary intersection set other-sets)) +(define (n-ary function first rest) + (if (null? rest) + first + (n-ary function (function first (car rest)) (cdr rest)))) +(define (set-keep keep? set) + (cond ((null? set) '()) + ((keep? (car set)) (cons (car set) (set-keep keep? (cdr set)))) + (else (set-keep keep? (cdr set))))) +(define (set-every? pred? set) + (or (null? set) (and (pred? (car set)) (set-every? pred? (cdr set))))) +(define (set-map proc set) + (if (null? set) '() (cons (proc (car set)) (set-map proc (cdr set))))) +(define (list->queue list) + (cons list (if (pair? list) (my-last-pair list) '()))) +(define (queue->list queue) (car queue)) +(define (queue-empty) (cons '() '())) +(define (queue-empty? queue) (null? (car queue))) +(define (queue-get! queue) + (if (null? (car queue)) + (compiler-internal-error "queue-get!, queue is empty") + (let ((x (caar queue))) + (set-car! queue (cdar queue)) + (if (null? (car queue)) (set-cdr! queue '())) + x))) +(define (queue-put! queue x) + (let ((entry (cons x '()))) + (if (null? (car queue)) + (set-car! queue entry) + (set-cdr! (cdr queue) entry)) + (set-cdr! queue entry) + x)) +(define (string->canonical-symbol str) + (let ((len (string-length str))) + (let loop ((str str) (s (make-string len)) (i (- len 1))) + (if (>= i 0) + (begin + (string-set! s i (char-downcase (string-ref str i))) + (loop str s (- i 1))) + (string->symbol s))))) +(define quote-sym (string->canonical-symbol "QUOTE")) +(define quasiquote-sym (string->canonical-symbol "QUASIQUOTE")) +(define unquote-sym (string->canonical-symbol "UNQUOTE")) +(define unquote-splicing-sym (string->canonical-symbol "UNQUOTE-SPLICING")) +(define lambda-sym (string->canonical-symbol "LAMBDA")) +(define if-sym (string->canonical-symbol "IF")) +(define set!-sym (string->canonical-symbol "SET!")) +(define cond-sym (string->canonical-symbol "COND")) +(define =>-sym (string->canonical-symbol "=>")) +(define else-sym (string->canonical-symbol "ELSE")) +(define and-sym (string->canonical-symbol "AND")) +(define or-sym (string->canonical-symbol "OR")) +(define case-sym (string->canonical-symbol "CASE")) +(define let-sym (string->canonical-symbol "LET")) +(define let*-sym (string->canonical-symbol "LET*")) +(define letrec-sym (string->canonical-symbol "LETREC")) +(define begin-sym (string->canonical-symbol "BEGIN")) +(define do-sym (string->canonical-symbol "DO")) +(define define-sym (string->canonical-symbol "DEFINE")) +(define delay-sym (string->canonical-symbol "DELAY")) +(define future-sym (string->canonical-symbol "FUTURE")) +(define **define-macro-sym (string->canonical-symbol "DEFINE-MACRO")) +(define **declare-sym (string->canonical-symbol "DECLARE")) +(define **include-sym (string->canonical-symbol "INCLUDE")) +(define not-sym (string->canonical-symbol "NOT")) +(define **c-declaration-sym (string->canonical-symbol "C-DECLARATION")) +(define **c-init-sym (string->canonical-symbol "C-INIT")) +(define **c-procedure-sym (string->canonical-symbol "C-PROCEDURE")) +(define void-sym (string->canonical-symbol "VOID")) +(define char-sym (string->canonical-symbol "CHAR")) +(define signed-char-sym (string->canonical-symbol "SIGNED-CHAR")) +(define unsigned-char-sym (string->canonical-symbol "UNSIGNED-CHAR")) +(define short-sym (string->canonical-symbol "SHORT")) +(define unsigned-short-sym (string->canonical-symbol "UNSIGNED-SHORT")) +(define int-sym (string->canonical-symbol "INT")) +(define unsigned-int-sym (string->canonical-symbol "UNSIGNED-INT")) +(define long-sym (string->canonical-symbol "LONG")) +(define unsigned-long-sym (string->canonical-symbol "UNSIGNED-LONG")) +(define float-sym (string->canonical-symbol "FLOAT")) +(define double-sym (string->canonical-symbol "DOUBLE")) +(define pointer-sym (string->canonical-symbol "POINTER")) +(define boolean-sym (string->canonical-symbol "BOOLEAN")) +(define string-sym (string->canonical-symbol "STRING")) +(define scheme-object-sym (string->canonical-symbol "SCHEME-OBJECT")) +(define c-id-prefix "___") +(define false-object (if (eq? '() #f) (string->symbol "#f") #f)) +(define (false-object? obj) (eq? obj false-object)) +(define undef-object (string->symbol "#[undefined]")) +(define (undef-object? obj) (eq? obj undef-object)) +(define (symbol-object? obj) + (and (not (false-object? obj)) (not (undef-object? obj)) (symbol? obj))) +(define scm-file-exts '("scm" #f)) +(define compiler-version "2.2.2") +(define (open-sf filename) + (define (open-err) (compiler-error "Can't find file" filename)) + (if (not (file-ext filename)) + (let loop ((exts scm-file-exts)) + (if (pair? exts) + (let* ((ext (car exts)) + (full-name + (if ext (string-append filename "." ext) filename)) + (port (open-input-file* full-name))) + (if port (vector port full-name 0 1 0) (loop (cdr exts)))) + (open-err))) + (let ((port (open-input-file* filename))) + (if port (vector port filename 0 1 0) (open-err))))) +(define (close-sf sf) (close-input-port (vector-ref sf 0))) +(define (sf-read-char sf) + (let ((c (read-char (vector-ref sf 0)))) + (cond ((eof-object? c)) + ((char=? c char-newline) + (vector-set! sf 3 (+ (vector-ref sf 3) 1)) + (vector-set! sf 4 0)) + (else (vector-set! sf 4 (+ (vector-ref sf 4) 1)))) + c)) +(define (sf-peek-char sf) (peek-char (vector-ref sf 0))) +(define (sf-read-error sf msg . args) + (apply compiler-user-error + (cons (sf->locat sf) + (cons (string-append "Read error -- " msg) args)))) +(define (sf->locat sf) + (vector 'file + (vector-ref sf 1) + (vector-ref sf 2) + (vector-ref sf 3) + (vector-ref sf 4))) +(define (expr->locat expr source) (vector 'expr expr source)) +(define (locat-show loc) + (if loc + (case (vector-ref loc 0) + ((file) + (if (pinpoint-error + (vector-ref loc 1) + (vector-ref loc 3) + (vector-ref loc 4)) + (begin + (display "file \"") + (display (vector-ref loc 1)) + (display "\", line ") + (display (vector-ref loc 3)) + (display ", character ") + (display (vector-ref loc 4))))) + ((expr) + (display "expression ") + (write (vector-ref loc 1)) + (if (vector-ref loc 2) + (begin + (display " ") + (locat-show (source-locat (vector-ref loc 2)))))) + (else (compiler-internal-error "locat-show, unknown location tag"))) + (display "unknown location"))) +(define (locat-filename loc) + (if loc + (case (vector-ref loc 0) + ((file) (vector-ref loc 1)) + ((expr) + (let ((source (vector-ref loc 2))) + (if source (locat-filename (source-locat source)) ""))) + (else + (compiler-internal-error "locat-filename, unknown location tag"))) + "")) +(define (make-source code locat) (vector code locat)) +(define (source-code x) (vector-ref x 0)) +(define (source-code-set! x y) (vector-set! x 0 y) x) +(define (source-locat x) (vector-ref x 1)) +(define (expression->source expr source) + (define (expr->source x) + (make-source + (cond ((pair? x) (list->source x)) + ((vector? x) (vector->source x)) + ((symbol-object? x) (string->canonical-symbol (symbol->string x))) + (else x)) + (expr->locat x source))) + (define (list->source l) + (cond ((pair? l) (cons (expr->source (car l)) (list->source (cdr l)))) + ((null? l) '()) + (else (expr->source l)))) + (define (vector->source v) + (let* ((len (vector-length v)) (x (make-vector len))) + (let loop ((i (- len 1))) + (if (>= i 0) + (begin + (vector-set! x i (expr->source (vector-ref v i))) + (loop (- i 1))))) + x)) + (expr->source expr)) +(define (source->expression source) + (define (list->expression l) + (cond ((pair? l) + (cons (source->expression (car l)) (list->expression (cdr l)))) + ((null? l) '()) + (else (source->expression l)))) + (define (vector->expression v) + (let* ((len (vector-length v)) (x (make-vector len))) + (let loop ((i (- len 1))) + (if (>= i 0) + (begin + (vector-set! x i (source->expression (vector-ref v i))) + (loop (- i 1))))) + x)) + (let ((code (source-code source))) + (cond ((pair? code) (list->expression code)) + ((vector? code) (vector->expression code)) + (else code)))) +(define (file->sources filename info-port) + (if info-port + (begin + (display "(reading \"" info-port) + (display filename info-port) + (display "\"" info-port))) + (let ((sf (open-sf filename))) + (define (read-sources) + (let ((source (read-source sf))) + (if (not (eof-object? source)) + (begin + (if info-port (display "." info-port)) + (cons source (read-sources))) + '()))) + (let ((sources (read-sources))) + (if info-port (display ")" info-port)) + (close-sf sf) + sources))) +(define (file->sources* filename info-port loc) + (file->sources + (if (path-absolute? filename) + filename + (string-append (file-path (locat-filename loc)) filename)) + info-port)) +(define (read-source sf) + (define (read-char*) + (let ((c (sf-read-char sf))) + (if (eof-object? c) + (sf-read-error sf "Premature end of file encountered") + c))) + (define (read-non-whitespace-char) + (let ((c (read-char*))) + (cond ((< 0 (vector-ref read-table (char->integer c))) + (read-non-whitespace-char)) + ((char=? c #\;) + (let loop () + (if (not (char=? (read-char*) char-newline)) + (loop) + (read-non-whitespace-char)))) + (else c)))) + (define (delimiter? c) + (or (eof-object? c) (not (= (vector-ref read-table (char->integer c)) 0)))) + (define (read-list first) + (let ((result (cons first '()))) + (let loop ((end result)) + (let ((c (read-non-whitespace-char))) + (cond ((char=? c #\))) + ((and (char=? c #\.) (delimiter? (sf-peek-char sf))) + (let ((x (read-source sf))) + (if (char=? (read-non-whitespace-char) #\)) + (set-cdr! end x) + (sf-read-error sf "')' expected")))) + (else + (let ((tail (cons (rd* c) '()))) + (set-cdr! end tail) + (loop tail)))))) + result)) + (define (read-vector) + (define (loop i) + (let ((c (read-non-whitespace-char))) + (if (char=? c #\)) + (make-vector i '()) + (let* ((x (rd* c)) (v (loop (+ i 1)))) (vector-set! v i x) v)))) + (loop 0)) + (define (read-string) + (define (loop i) + (let ((c (read-char*))) + (cond ((char=? c #\") (make-string i #\space)) + ((char=? c #\\) + (let* ((c (read-char*)) (s (loop (+ i 1)))) + (string-set! s i c) + s)) + (else (let ((s (loop (+ i 1)))) (string-set! s i c) s))))) + (loop 0)) + (define (read-symbol/number-string i) + (if (delimiter? (sf-peek-char sf)) + (make-string i #\space) + (let* ((c (sf-read-char sf)) (s (read-symbol/number-string (+ i 1)))) + (string-set! s i (char-downcase c)) + s))) + (define (read-symbol/number c) + (let ((s (read-symbol/number-string 1))) + (string-set! s 0 (char-downcase c)) + (or (string->number s 10) (string->canonical-symbol s)))) + (define (read-prefixed-number c) + (let ((s (read-symbol/number-string 2))) + (string-set! s 0 #\#) + (string-set! s 1 c) + (string->number s 10))) + (define (read-special-symbol) + (let ((s (read-symbol/number-string 2))) + (string-set! s 0 #\#) + (string-set! s 1 #\#) + (string->canonical-symbol s))) + (define (rd c) + (cond ((eof-object? c) c) + ((< 0 (vector-ref read-table (char->integer c))) + (rd (sf-read-char sf))) + ((char=? c #\;) + (let loop () + (let ((c (sf-read-char sf))) + (cond ((eof-object? c) c) + ((char=? c char-newline) (rd (sf-read-char sf))) + (else (loop)))))) + (else (rd* c)))) + (define (rd* c) + (let ((source (make-source #f (sf->locat sf)))) + (source-code-set! + source + (cond ((char=? c #\() + (let ((x (read-non-whitespace-char))) + (if (char=? x #\)) '() (read-list (rd* x))))) + ((char=? c #\#) + (let ((c (char-downcase (sf-read-char sf)))) + (cond ((char=? c #\() (read-vector)) + ((char=? c #\f) false-object) + ((char=? c #\t) #t) + ((char=? c #\\) + (let ((c (read-char*))) + (if (or (not (char-alphabetic? c)) + (delimiter? (sf-peek-char sf))) + c + (let ((name (read-symbol/number c))) + (let ((x (assq name named-char-table))) + (if x + (cdr x) + (sf-read-error + sf + "Unknown character name" + name))))))) + ((char=? c #\#) (read-special-symbol)) + (else + (let ((num (read-prefixed-number c))) + (or num + (sf-read-error + sf + "Unknown '#' read macro" + c))))))) + ((char=? c #\") (read-string)) + ((char=? c #\') + (list (make-source quote-sym (sf->locat sf)) (read-source sf))) + ((char=? c #\`) + (list (make-source quasiquote-sym (sf->locat sf)) + (read-source sf))) + ((char=? c #\,) + (if (char=? (sf-peek-char sf) #\@) + (let ((x (make-source unquote-splicing-sym (sf->locat sf)))) + (sf-read-char sf) + (list x (read-source sf))) + (list (make-source unquote-sym (sf->locat sf)) + (read-source sf)))) + ((char=? c #\)) (sf-read-error sf "Misplaced ')'")) + ((or (char=? c #\[) (char=? c #\]) (char=? c #\{) (char=? c #\})) + (sf-read-error sf "Illegal character" c)) + (else + (if (char=? c #\.) + (if (delimiter? (sf-peek-char sf)) + (sf-read-error sf "Misplaced '.'"))) + (read-symbol/number c)))))) + (rd (sf-read-char sf))) +(define named-char-table + (list (cons (string->canonical-symbol "NUL") char-nul) + (cons (string->canonical-symbol "TAB") char-tab) + (cons (string->canonical-symbol "NEWLINE") char-newline) + (cons (string->canonical-symbol "SPACE") #\space))) +(define read-table + (let ((rt (make-vector (+ max-character-encoding 1) 0))) + (vector-set! rt (char->integer char-tab) 1) + (vector-set! rt (char->integer char-newline) 1) + (vector-set! rt (char->integer #\space) 1) + (vector-set! rt (char->integer #\;) -1) + (vector-set! rt (char->integer #\() -1) + (vector-set! rt (char->integer #\)) -1) + (vector-set! rt (char->integer #\") -1) + (vector-set! rt (char->integer #\') -1) + (vector-set! rt (char->integer #\`) -1) + rt)) +(define (make-var name bound refs sets source) + (vector var-tag name bound refs sets source #f)) +(define (var? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) var-tag))) +(define (var-name x) (vector-ref x 1)) +(define (var-bound x) (vector-ref x 2)) +(define (var-refs x) (vector-ref x 3)) +(define (var-sets x) (vector-ref x 4)) +(define (var-source x) (vector-ref x 5)) +(define (var-info x) (vector-ref x 6)) +(define (var-name-set! x y) (vector-set! x 1 y)) +(define (var-bound-set! x y) (vector-set! x 2 y)) +(define (var-refs-set! x y) (vector-set! x 3 y)) +(define (var-sets-set! x y) (vector-set! x 4 y)) +(define (var-source-set! x y) (vector-set! x 5 y)) +(define (var-info-set! x y) (vector-set! x 6 y)) +(define var-tag (list 'var-tag)) +(define (var-copy var) + (make-var (var-name var) #t (set-empty) (set-empty) (var-source var))) +(define (make-temp-var name) (make-var name #t (set-empty) (set-empty) #f)) +(define (temp-var? var) (eq? (var-bound var) #t)) +(define ret-var (make-temp-var 'ret)) +(define ret-var-set (set-singleton ret-var)) +(define closure-env-var (make-temp-var 'closure-env)) +(define empty-var (make-temp-var #f)) +(define make-global-environment #f) +(set! make-global-environment (lambda () (env-frame #f '()))) +(define (env-frame env vars) (vector (cons vars #f) '() '() env)) +(define (env-new-var! env name source) + (let* ((glob (not (env-parent-ref env))) + (var (make-var name (not glob) (set-empty) (set-empty) source))) + (env-vars-set! env (cons var (env-vars-ref env))) + var)) +(define (env-macro env name def) + (let ((name* (if (full-name? name) + name + (let ((prefix (env-namespace-prefix env name))) + (if prefix (make-full-name prefix name) name))))) + (vector (vector-ref env 0) + (cons (cons name* def) (env-macros-ref env)) + (env-decls-ref env) + (env-parent-ref env)))) +(define (env-declare env decl) + (vector (vector-ref env 0) + (env-macros-ref env) + (cons decl (env-decls-ref env)) + (env-parent-ref env))) +(define (env-vars-ref env) (car (vector-ref env 0))) +(define (env-vars-set! env vars) (set-car! (vector-ref env 0) vars)) +(define (env-macros-ref env) (vector-ref env 1)) +(define (env-decls-ref env) (vector-ref env 2)) +(define (env-parent-ref env) (vector-ref env 3)) +(define (env-namespace-prefix env name) + (let loop ((decls (env-decls-ref env))) + (if (pair? decls) + (let ((decl (car decls))) + (if (eq? (car decl) namespace-sym) + (let ((syms (cddr decl))) + (if (or (null? syms) (memq name syms)) + (cadr decl) + (loop (cdr decls)))) + (loop (cdr decls)))) + #f))) +(define (env-lookup env name stop-at-first-frame? proc) + (define (search env name full?) + (if full? + (search* env name full?) + (let ((prefix (env-namespace-prefix env name))) + (if prefix + (search* env (make-full-name prefix name) #t) + (search* env name full?))))) + (define (search* env name full?) + (define (search-macros macros) + (if (pair? macros) + (let ((m (car macros))) + (if (eq? (car m) name) + (proc env name (cdr m)) + (search-macros (cdr macros)))) + (search-vars (env-vars-ref env)))) + (define (search-vars vars) + (if (pair? vars) + (let ((v (car vars))) + (if (eq? (var-name v) name) + (proc env name v) + (search-vars (cdr vars)))) + (let ((env* (env-parent-ref env))) + (if (or stop-at-first-frame? (not env*)) + (proc env name #f) + (search env* name full?))))) + (search-macros (env-macros-ref env))) + (search env name (full-name? name))) +(define (valid-prefix? str) + (let ((l (string-length str))) + (or (= l 0) (and (>= l 2) (char=? (string-ref str (- l 1)) #\#))))) +(define (full-name? sym) + (let ((str (symbol->string sym))) + (let loop ((i (- (string-length str) 1))) + (if (< i 0) #f (if (char=? (string-ref str i) #\#) #t (loop (- i 1))))))) +(define (make-full-name prefix sym) + (if (= (string-length prefix) 0) + sym + (string->canonical-symbol (string-append prefix (symbol->string sym))))) +(define (env-lookup-var env name source) + (env-lookup + env + name + #f + (lambda (env name x) + (if x + (if (var? x) + x + (compiler-internal-error + "env-lookup-var, name is that of a macro" + name)) + (env-new-var! env name source))))) +(define (env-define-var env name source) + (env-lookup + env + name + #t + (lambda (env name x) + (if x + (if (var? x) + (pt-syntax-error source "Duplicate definition of a variable") + (compiler-internal-error + "env-define-var, name is that of a macro" + name)) + (env-new-var! env name source))))) +(define (env-lookup-global-var env name) + (let ((env* (env-global-env env))) + (define (search-vars vars) + (if (pair? vars) + (let ((v (car vars))) + (if (eq? (var-name v) name) v (search-vars (cdr vars)))) + (env-new-var! env* name #f))) + (search-vars (env-vars-ref env*)))) +(define (env-global-variables env) (env-vars-ref (env-global-env env))) +(define (env-global-env env) + (let loop ((env env)) + (let ((env* (env-parent-ref env))) (if env* (loop env*) env)))) +(define (env-lookup-macro env name) + (env-lookup + env + name + #f + (lambda (env name x) (if (or (not x) (var? x)) #f x)))) +(define (env-declarations env) env) +(define flag-declarations '()) +(define parameterized-declarations '()) +(define boolean-declarations '()) +(define namable-declarations '()) +(define namable-boolean-declarations '()) +(define namable-string-declarations '()) +(define (define-flag-decl name type) + (set! flag-declarations (cons (cons name type) flag-declarations)) + '()) +(define (define-parameterized-decl name) + (set! parameterized-declarations (cons name parameterized-declarations)) + '()) +(define (define-boolean-decl name) + (set! boolean-declarations (cons name boolean-declarations)) + '()) +(define (define-namable-decl name type) + (set! namable-declarations (cons (cons name type) namable-declarations)) + '()) +(define (define-namable-boolean-decl name) + (set! namable-boolean-declarations (cons name namable-boolean-declarations)) + '()) +(define (define-namable-string-decl name) + (set! namable-string-declarations (cons name namable-string-declarations)) + '()) +(define (flag-decl source type val) (list type val)) +(define (parameterized-decl source id parm) (list id parm)) +(define (boolean-decl source id pos) (list id pos)) +(define (namable-decl source type val names) (cons type (cons val names))) +(define (namable-boolean-decl source id pos names) (cons id (cons pos names))) +(define (namable-string-decl source id str names) + (if (and (eq? id namespace-sym) (not (valid-prefix? str))) + (pt-syntax-error source "Illegal namespace")) + (cons id (cons str names))) +(define (declaration-value name element default decls) + (if (not decls) + default + (let loop ((l (env-decls-ref decls))) + (if (pair? l) + (let ((d (car l))) + (if (and (eq? (car d) name) + (or (null? (cddr d)) (memq element (cddr d)))) + (cadr d) + (loop (cdr l)))) + (declaration-value name element default (env-parent-ref decls)))))) +(define namespace-sym (string->canonical-symbol "NAMESPACE")) +(define-namable-string-decl namespace-sym) +(define (node-parent x) (vector-ref x 1)) +(define (node-children x) (vector-ref x 2)) +(define (node-fv x) (vector-ref x 3)) +(define (node-decl x) (vector-ref x 4)) +(define (node-source x) (vector-ref x 5)) +(define (node-parent-set! x y) (vector-set! x 1 y)) +(define (node-fv-set! x y) (vector-set! x 3 y)) +(define (node-decl-set! x y) (vector-set! x 4 y)) +(define (node-source-set! x y) (vector-set! x 5 y)) +(define (node-children-set! x y) + (vector-set! x 2 y) + (for-each (lambda (child) (node-parent-set! child x)) y) + (node-fv-invalidate! x)) +(define (node-fv-invalidate! x) + (let loop ((node x)) + (if node (begin (node-fv-set! node #t) (loop (node-parent node)))))) +(define (make-cst parent children fv decl source val) + (vector cst-tag parent children fv decl source val)) +(define (cst? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) cst-tag))) +(define (cst-val x) (vector-ref x 6)) +(define (cst-val-set! x y) (vector-set! x 6 y)) +(define cst-tag (list 'cst-tag)) +(define (make-ref parent children fv decl source var) + (vector ref-tag parent children fv decl source var)) +(define (ref? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) ref-tag))) +(define (ref-var x) (vector-ref x 6)) +(define (ref-var-set! x y) (vector-set! x 6 y)) +(define ref-tag (list 'ref-tag)) +(define (make-set parent children fv decl source var) + (vector set-tag parent children fv decl source var)) +(define (set? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) set-tag))) +(define (set-var x) (vector-ref x 6)) +(define (set-var-set! x y) (vector-set! x 6 y)) +(define set-tag (list 'set-tag)) +(define (make-def parent children fv decl source var) + (vector def-tag parent children fv decl source var)) +(define (def? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) def-tag))) +(define (def-var x) (vector-ref x 6)) +(define (def-var-set! x y) (vector-set! x 6 y)) +(define def-tag (list 'def-tag)) +(define (make-tst parent children fv decl source) + (vector tst-tag parent children fv decl source)) +(define (tst? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) tst-tag))) +(define tst-tag (list 'tst-tag)) +(define (make-conj parent children fv decl source) + (vector conj-tag parent children fv decl source)) +(define (conj? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) conj-tag))) +(define conj-tag (list 'conj-tag)) +(define (make-disj parent children fv decl source) + (vector disj-tag parent children fv decl source)) +(define (disj? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) disj-tag))) +(define disj-tag (list 'disj-tag)) +(define (make-prc parent children fv decl source name min rest parms) + (vector prc-tag parent children fv decl source name min rest parms)) +(define (prc? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) prc-tag))) +(define (prc-name x) (vector-ref x 6)) +(define (prc-min x) (vector-ref x 7)) +(define (prc-rest x) (vector-ref x 8)) +(define (prc-parms x) (vector-ref x 9)) +(define (prc-name-set! x y) (vector-set! x 6 y)) +(define (prc-min-set! x y) (vector-set! x 7 y)) +(define (prc-rest-set! x y) (vector-set! x 8 y)) +(define (prc-parms-set! x y) (vector-set! x 9 y)) +(define prc-tag (list 'prc-tag)) +(define (make-app parent children fv decl source) + (vector app-tag parent children fv decl source)) +(define (app? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) app-tag))) +(define app-tag (list 'app-tag)) +(define (make-fut parent children fv decl source) + (vector fut-tag parent children fv decl source)) +(define (fut? x) + (and (vector? x) (> (vector-length x) 0) (eq? (vector-ref x 0) fut-tag))) +(define fut-tag (list 'fut-tag)) +(define (new-cst source decl val) (make-cst #f '() #t decl source val)) +(define (new-ref source decl var) + (let ((node (make-ref #f '() #t decl source var))) + (var-refs-set! var (set-adjoin (var-refs var) node)) + node)) +(define (new-ref-extended-bindings source name env) + (new-ref source + (add-extended-bindings (env-declarations env)) + (env-lookup-global-var env name))) +(define (new-set source decl var val) + (let ((node (make-set #f (list val) #t decl source var))) + (var-sets-set! var (set-adjoin (var-sets var) node)) + (node-parent-set! val node) + node)) +(define (set-val x) + (if (set? x) + (car (node-children x)) + (compiler-internal-error "set-val, 'set' node expected" x))) +(define (new-def source decl var val) + (let ((node (make-def #f (list val) #t decl source var))) + (var-sets-set! var (set-adjoin (var-sets var) node)) + (node-parent-set! val node) + node)) +(define (def-val x) + (if (def? x) + (car (node-children x)) + (compiler-internal-error "def-val, 'def' node expected" x))) +(define (new-tst source decl pre con alt) + (let ((node (make-tst #f (list pre con alt) #t decl source))) + (node-parent-set! pre node) + (node-parent-set! con node) + (node-parent-set! alt node) + node)) +(define (tst-pre x) + (if (tst? x) + (car (node-children x)) + (compiler-internal-error "tst-pre, 'tst' node expected" x))) +(define (tst-con x) + (if (tst? x) + (cadr (node-children x)) + (compiler-internal-error "tst-con, 'tst' node expected" x))) +(define (tst-alt x) + (if (tst? x) + (caddr (node-children x)) + (compiler-internal-error "tst-alt, 'tst' node expected" x))) +(define (new-conj source decl pre alt) + (let ((node (make-conj #f (list pre alt) #t decl source))) + (node-parent-set! pre node) + (node-parent-set! alt node) + node)) +(define (conj-pre x) + (if (conj? x) + (car (node-children x)) + (compiler-internal-error "conj-pre, 'conj' node expected" x))) +(define (conj-alt x) + (if (conj? x) + (cadr (node-children x)) + (compiler-internal-error "conj-alt, 'conj' node expected" x))) +(define (new-disj source decl pre alt) + (let ((node (make-disj #f (list pre alt) #t decl source))) + (node-parent-set! pre node) + (node-parent-set! alt node) + node)) +(define (disj-pre x) + (if (disj? x) + (car (node-children x)) + (compiler-internal-error "disj-pre, 'disj' node expected" x))) +(define (disj-alt x) + (if (disj? x) + (cadr (node-children x)) + (compiler-internal-error "disj-alt, 'disj' node expected" x))) +(define (new-prc source decl name min rest parms body) + (let ((node (make-prc #f (list body) #t decl source name min rest parms))) + (for-each (lambda (x) (var-bound-set! x node)) parms) + (node-parent-set! body node) + node)) +(define (prc-body x) + (if (prc? x) + (car (node-children x)) + (compiler-internal-error "prc-body, 'proc' node expected" x))) +(define (new-call source decl oper args) + (let ((node (make-app #f (cons oper args) #t decl source))) + (node-parent-set! oper node) + (for-each (lambda (x) (node-parent-set! x node)) args) + node)) +(define (new-call* source decl oper args) + (if *ptree-port* + (if (ref? oper) + (let ((var (ref-var oper))) + (if (global? var) + (let ((proc (standard-procedure + (var-name var) + (node-decl oper)))) + (if (and proc + (not (nb-args-conforms? + (length args) + (standard-procedure-call-pattern proc)))) + (begin + (display "*** WARNING -- \"" *ptree-port*) + (display (var-name var) *ptree-port*) + (display "\" is called with " *ptree-port*) + (display (length args) *ptree-port*) + (display " argument(s)." *ptree-port*) + (newline *ptree-port*)))))))) + (new-call source decl oper args)) +(define (app-oper x) + (if (app? x) + (car (node-children x)) + (compiler-internal-error "app-oper, 'call' node expected" x))) +(define (app-args x) + (if (app? x) + (cdr (node-children x)) + (compiler-internal-error "app-args, 'call' node expected" x))) +(define (oper-pos? node) + (let ((parent (node-parent node))) + (if parent (and (app? parent) (eq? (app-oper parent) node)) #f))) +(define (new-fut source decl val) + (let ((node (make-fut #f (list val) #t decl source))) + (node-parent-set! val node) + node)) +(define (fut-val x) + (if (fut? x) + (car (node-children x)) + (compiler-internal-error "fut-val, 'fut' node expected" x))) +(define (new-disj-call source decl pre oper alt) + (new-call* + source + decl + (let* ((parms (new-temps source '(temp))) (temp (car parms))) + (new-prc source + decl + #f + 1 + #f + parms + (new-tst source + decl + (new-ref source decl temp) + (new-call* + source + decl + oper + (list (new-ref source decl temp))) + alt))) + (list pre))) +(define (new-seq source decl before after) + (new-call* + source + decl + (new-prc source decl #f 1 #f (new-temps source '(temp)) after) + (list before))) +(define (new-let ptree proc vars vals body) + (if (pair? vars) + (new-call + (node-source ptree) + (node-decl ptree) + (new-prc (node-source proc) + (node-decl proc) + (prc-name proc) + (length vars) + #f + (reverse vars) + body) + (reverse vals)) + body)) +(define (new-temps source names) + (if (null? names) + '() + (cons (make-var (car names) #t (set-empty) (set-empty) source) + (new-temps source (cdr names))))) +(define (new-variables vars) + (if (null? vars) + '() + (cons (make-var + (source-code (car vars)) + #t + (set-empty) + (set-empty) + (car vars)) + (new-variables (cdr vars))))) +(define (set-prc-names! vars vals) + (let loop ((vars vars) (vals vals)) + (if (not (null? vars)) + (let ((var (car vars)) (val (car vals))) + (if (prc? val) (prc-name-set! val (symbol->string (var-name var)))) + (loop (cdr vars) (cdr vals)))))) +(define (free-variables node) + (if (eq? (node-fv node) #t) + (let ((x (apply set-union (map free-variables (node-children node))))) + (node-fv-set! + node + (cond ((ref? node) + (if (global? (ref-var node)) x (set-adjoin x (ref-var node)))) + ((set? node) + (if (global? (set-var node)) x (set-adjoin x (set-var node)))) + ((prc? node) (set-difference x (list->set (prc-parms node)))) + ((and (app? node) (prc? (app-oper node))) + (set-difference x (list->set (prc-parms (app-oper node))))) + (else x))))) + (node-fv node)) +(define (bound-variables node) (list->set (prc-parms node))) +(define (not-mutable? var) (set-empty? (var-sets var))) +(define (mutable? var) (not (not-mutable? var))) +(define (bound? var) (var-bound var)) +(define (global? var) (not (bound? var))) +(define (global-val var) + (and (global? var) + (let ((sets (set->list (var-sets var)))) + (and (pair? sets) + (null? (cdr sets)) + (def? (car sets)) + (eq? (compilation-strategy (node-decl (car sets))) block-sym) + (def-val (car sets)))))) +(define **not-sym (string->canonical-symbol "##NOT")) +(define **quasi-append-sym (string->canonical-symbol "##QUASI-APPEND")) +(define **quasi-list-sym (string->canonical-symbol "##QUASI-LIST")) +(define **quasi-cons-sym (string->canonical-symbol "##QUASI-CONS")) +(define **quasi-list->vector-sym + (string->canonical-symbol "##QUASI-LIST->VECTOR")) +(define **case-memv-sym (string->canonical-symbol "##CASE-MEMV")) +(define **unassigned?-sym (string->canonical-symbol "##UNASSIGNED?")) +(define **make-cell-sym (string->canonical-symbol "##MAKE-CELL")) +(define **cell-ref-sym (string->canonical-symbol "##CELL-REF")) +(define **cell-set!-sym (string->canonical-symbol "##CELL-SET!")) +(define **make-placeholder-sym (string->canonical-symbol "##MAKE-PLACEHOLDER")) +(define ieee-scheme-sym (string->canonical-symbol "IEEE-SCHEME")) +(define r4rs-scheme-sym (string->canonical-symbol "R4RS-SCHEME")) +(define multilisp-sym (string->canonical-symbol "MULTILISP")) +(define lambda-lift-sym (string->canonical-symbol "LAMBDA-LIFT")) +(define block-sym (string->canonical-symbol "BLOCK")) +(define separate-sym (string->canonical-symbol "SEPARATE")) +(define standard-bindings-sym (string->canonical-symbol "STANDARD-BINDINGS")) +(define extended-bindings-sym (string->canonical-symbol "EXTENDED-BINDINGS")) +(define safe-sym (string->canonical-symbol "SAFE")) +(define interrupts-enabled-sym (string->canonical-symbol "INTERRUPTS-ENABLED")) +(define-flag-decl ieee-scheme-sym 'dialect) +(define-flag-decl r4rs-scheme-sym 'dialect) +(define-flag-decl multilisp-sym 'dialect) +(define-boolean-decl lambda-lift-sym) +(define-flag-decl block-sym 'compilation-strategy) +(define-flag-decl separate-sym 'compilation-strategy) +(define-namable-boolean-decl standard-bindings-sym) +(define-namable-boolean-decl extended-bindings-sym) +(define-boolean-decl safe-sym) +(define-boolean-decl interrupts-enabled-sym) +(define (scheme-dialect decl) + (declaration-value 'dialect #f ieee-scheme-sym decl)) +(define (lambda-lift? decl) (declaration-value lambda-lift-sym #f #t decl)) +(define (compilation-strategy decl) + (declaration-value 'compilation-strategy #f separate-sym decl)) +(define (standard-binding? name decl) + (declaration-value standard-bindings-sym name #f decl)) +(define (extended-binding? name decl) + (declaration-value extended-bindings-sym name #f decl)) +(define (add-extended-bindings decl) + (add-decl (list extended-bindings-sym #t) decl)) +(define (intrs-enabled? decl) + (declaration-value interrupts-enabled-sym #f #t decl)) +(define (add-not-interrupts-enabled decl) + (add-decl (list interrupts-enabled-sym #f) decl)) +(define (safe? decl) (declaration-value safe-sym #f #f decl)) +(define (add-not-safe decl) (add-decl (list safe-sym #f) decl)) +(define (dialect-specific-keywords dialect) + (cond ((eq? dialect ieee-scheme-sym) ieee-scheme-specific-keywords) + ((eq? dialect r4rs-scheme-sym) r4rs-scheme-specific-keywords) + ((eq? dialect multilisp-sym) multilisp-specific-keywords) + (else + (compiler-internal-error + "dialect-specific-keywords, unknown dialect" + dialect)))) +(define (dialect-specific-procedures dialect) + (cond ((eq? dialect ieee-scheme-sym) ieee-scheme-specific-procedures) + ((eq? dialect r4rs-scheme-sym) r4rs-scheme-specific-procedures) + ((eq? dialect multilisp-sym) multilisp-specific-procedures) + (else + (compiler-internal-error + "dialect-specific-procedures, unknown dialect" + dialect)))) +(define (make-standard-procedure x) + (cons (string->canonical-symbol (car x)) (cdr x))) +(define (standard-procedure name decl) + (or (assq name (dialect-specific-procedures (scheme-dialect decl))) + (assq name common-procedures))) +(define (standard-procedure-call-pattern proc) (cdr proc)) +(define ieee-scheme-specific-keywords '()) +(define ieee-scheme-specific-procedures (map make-standard-procedure '())) +(define r4rs-scheme-specific-keywords (list delay-sym)) +(define r4rs-scheme-specific-procedures + (map make-standard-procedure + '(("LIST-TAIL" 2) + ("-" . 1) + ("/" . 1) + ("STRING->LIST" 1) + ("LIST->STRING" 1) + ("STRING-COPY" 1) + ("STRING-FILL!" 2) + ("VECTOR->LIST" 1) + ("LIST->VECTOR" 1) + ("VECTOR-FILL!" 2) + ("FORCE" 1) + ("WITH-INPUT-FROM-FILE" 2) + ("WITH-OUTPUT-TO-FILE" 2) + ("CHAR-READY?" 0 1) + ("LOAD" 1) + ("TRANSCRIPT-ON" 1) + ("TRANSCRIPT-OFF" 0)))) +(define multilisp-specific-keywords (list delay-sym future-sym)) +(define multilisp-specific-procedures + (map make-standard-procedure '(("FORCE" 1) ("TOUCH" 1)))) +(define common-keywords + (list quote-sym + quasiquote-sym + unquote-sym + unquote-splicing-sym + lambda-sym + if-sym + set!-sym + cond-sym + =>-sym + else-sym + and-sym + or-sym + case-sym + let-sym + let*-sym + letrec-sym + begin-sym + do-sym + define-sym + **define-macro-sym + **declare-sym + **include-sym)) +(define common-procedures + (map make-standard-procedure + '(("NOT" 1) + ("BOOLEAN?" 1) + ("EQV?" 2) + ("EQ?" 2) + ("EQUAL?" 2) + ("PAIR?" 1) + ("CONS" 2) + ("CAR" 1) + ("CDR" 1) + ("SET-CAR!" 2) + ("SET-CDR!" 2) + ("CAAR" 1) + ("CADR" 1) + ("CDAR" 1) + ("CDDR" 1) + ("CAAAR" 1) + ("CAADR" 1) + ("CADAR" 1) + ("CADDR" 1) + ("CDAAR" 1) + ("CDADR" 1) + ("CDDAR" 1) + ("CDDDR" 1) + ("CAAAAR" 1) + ("CAAADR" 1) + ("CAADAR" 1) + ("CAADDR" 1) + ("CADAAR" 1) + ("CADADR" 1) + ("CADDAR" 1) + ("CADDDR" 1) + ("CDAAAR" 1) + ("CDAADR" 1) + ("CDADAR" 1) + ("CDADDR" 1) + ("CDDAAR" 1) + ("CDDADR" 1) + ("CDDDAR" 1) + ("CDDDDR" 1) + ("NULL?" 1) + ("LIST?" 1) + ("LIST" . 0) + ("LENGTH" 1) + ("APPEND" . 0) + ("REVERSE" 1) + ("LIST-REF" 2) + ("MEMQ" 2) + ("MEMV" 2) + ("MEMBER" 2) + ("ASSQ" 2) + ("ASSV" 2) + ("ASSOC" 2) + ("SYMBOL?" 1) + ("SYMBOL->STRING" 1) + ("STRING->SYMBOL" 1) + ("NUMBER?" 1) + ("COMPLEX?" 1) + ("REAL?" 1) + ("RATIONAL?" 1) + ("INTEGER?" 1) + ("EXACT?" 1) + ("INEXACT?" 1) + ("=" . 2) + ("<" . 2) + (">" . 2) + ("<=" . 2) + (">=" . 2) + ("ZERO?" 1) + ("POSITIVE?" 1) + ("NEGATIVE?" 1) + ("ODD?" 1) + ("EVEN?" 1) + ("MAX" . 1) + ("MIN" . 1) + ("+" . 0) + ("*" . 0) + ("-" 1 2) + ("/" 1 2) + ("ABS" 1) + ("QUOTIENT" 2) + ("REMAINDER" 2) + ("MODULO" 2) + ("GCD" . 0) + ("LCM" . 0) + ("NUMERATOR" 1) + ("DENOMINATOR" 1) + ("FLOOR" 1) + ("CEILING" 1) + ("TRUNCATE" 1) + ("ROUND" 1) + ("RATIONALIZE" 2) + ("EXP" 1) + ("LOG" 1) + ("SIN" 1) + ("COS" 1) + ("TAN" 1) + ("ASIN" 1) + ("ACOS" 1) + ("ATAN" 1 2) + ("SQRT" 1) + ("EXPT" 2) + ("MAKE-RECTANGULAR" 2) + ("MAKE-POLAR" 2) + ("REAL-PART" 1) + ("IMAG-PART" 1) + ("MAGNITUDE" 1) + ("ANGLE" 1) + ("EXACT->INEXACT" 1) + ("INEXACT->EXACT" 1) + ("NUMBER->STRING" 1 2) + ("STRING->NUMBER" 1 2) + ("CHAR?" 1) + ("CHAR=?" 2) + ("CHAR<?" 2) + ("CHAR>?" 2) + ("CHAR<=?" 2) + ("CHAR>=?" 2) + ("CHAR-CI=?" 2) + ("CHAR-CI<?" 2) + ("CHAR-CI>?" 2) + ("CHAR-CI<=?" 2) + ("CHAR-CI>=?" 2) + ("CHAR-ALPHABETIC?" 1) + ("CHAR-NUMERIC?" 1) + ("CHAR-WHITESPACE?" 1) + ("CHAR-UPPER-CASE?" 1) + ("CHAR-LOWER-CASE?" 1) + ("CHAR->INTEGER" 1) + ("INTEGER->CHAR" 1) + ("CHAR-UPCASE" 1) + ("CHAR-DOWNCASE" 1) + ("STRING?" 1) + ("MAKE-STRING" 1 2) + ("STRING" . 0) + ("STRING-LENGTH" 1) + ("STRING-REF" 2) + ("STRING-SET!" 3) + ("STRING=?" 2) + ("STRING<?" 2) + ("STRING>?" 2) + ("STRING<=?" 2) + ("STRING>=?" 2) + ("STRING-CI=?" 2) + ("STRING-CI<?" 2) + ("STRING-CI>?" 2) + ("STRING-CI<=?" 2) + ("STRING-CI>=?" 2) + ("SUBSTRING" 3) + ("STRING-APPEND" . 0) + ("VECTOR?" 1) + ("MAKE-VECTOR" 1 2) + ("VECTOR" . 0) + ("VECTOR-LENGTH" 1) + ("VECTOR-REF" 2) + ("VECTOR-SET!" 3) + ("PROCEDURE?" 1) + ("APPLY" . 2) + ("MAP" . 2) + ("FOR-EACH" . 2) + ("CALL-WITH-CURRENT-CONTINUATION" 1) + ("CALL-WITH-INPUT-FILE" 2) + ("CALL-WITH-OUTPUT-FILE" 2) + ("INPUT-PORT?" 1) + ("OUTPUT-PORT?" 1) + ("CURRENT-INPUT-PORT" 0) + ("CURRENT-OUTPUT-PORT" 0) + ("OPEN-INPUT-FILE" 1) + ("OPEN-OUTPUT-FILE" 1) + ("CLOSE-INPUT-PORT" 1) + ("CLOSE-OUTPUT-PORT" 1) + ("EOF-OBJECT?" 1) + ("READ" 0 1) + ("READ-CHAR" 0 1) + ("PEEK-CHAR" 0 1) + ("WRITE" 1 2) + ("DISPLAY" 1 2) + ("NEWLINE" 0 1) + ("WRITE-CHAR" 1 2)))) +(define (parse-program program env module-name proc) + (define (parse-prog program env lst proc) + (if (null? program) + (proc (reverse lst) env) + (let ((source (car program))) + (cond ((macro-expr? source env) + (parse-prog + (cons (macro-expand source env) (cdr program)) + env + lst + proc)) + ((begin-defs-expr? source) + (parse-prog + (append (begin-defs-body source) (cdr program)) + env + lst + proc)) + ((include-expr? source) + (if *ptree-port* (display " " *ptree-port*)) + (let ((x (file->sources* + (include-filename source) + *ptree-port* + (source-locat source)))) + (if *ptree-port* (newline *ptree-port*)) + (parse-prog (append x (cdr program)) env lst proc))) + ((define-macro-expr? source env) + (if *ptree-port* + (begin + (display " \"macro\"" *ptree-port*) + (newline *ptree-port*))) + (parse-prog (cdr program) (add-macro source env) lst proc)) + ((declare-expr? source) + (if *ptree-port* + (begin + (display " \"decl\"" *ptree-port*) + (newline *ptree-port*))) + (parse-prog + (cdr program) + (add-declarations source env) + lst + proc)) + ((define-expr? source env) + (let* ((var** (definition-variable source)) + (var* (source-code var**)) + (var (env-lookup-var env var* var**))) + (if *ptree-port* + (begin + (display " " *ptree-port*) + (display (var-name var) *ptree-port*) + (newline *ptree-port*))) + (let ((node (pt (definition-value source) env 'true))) + (set-prc-names! (list var) (list node)) + (parse-prog + (cdr program) + env + (cons (cons (new-def source + (env-declarations env) + var + node) + env) + lst) + proc)))) + ((c-declaration-expr? source) + (if *ptree-port* + (begin + (display " \"c-decl\"" *ptree-port*) + (newline *ptree-port*))) + (add-c-declaration (source-code (cadr (source-code source)))) + (parse-prog (cdr program) env lst proc)) + ((c-init-expr? source) + (if *ptree-port* + (begin + (display " \"c-init\"" *ptree-port*) + (newline *ptree-port*))) + (add-c-init (source-code (cadr (source-code source)))) + (parse-prog (cdr program) env lst proc)) + (else + (if *ptree-port* + (begin + (display " \"expr\"" *ptree-port*) + (newline *ptree-port*))) + (parse-prog + (cdr program) + env + (cons (cons (pt source env 'true) env) lst) + proc)))))) + (if *ptree-port* + (begin (display "Parsing:" *ptree-port*) (newline *ptree-port*))) + (c-interface-begin module-name) + (parse-prog + program + env + '() + (lambda (lst env) + (if *ptree-port* (newline *ptree-port*)) + (proc lst env (c-interface-end))))) +(define (c-interface-begin module-name) + (set! c-interface-module-name module-name) + (set! c-interface-proc-count 0) + (set! c-interface-decls '()) + (set! c-interface-procs '()) + (set! c-interface-inits '()) + #f) +(define (c-interface-end) + (let ((i (make-c-intf + (reverse c-interface-decls) + (reverse c-interface-procs) + (reverse c-interface-inits)))) + (set! c-interface-module-name #f) + (set! c-interface-proc-count #f) + (set! c-interface-decls #f) + (set! c-interface-procs #f) + (set! c-interface-inits #f) + i)) +(define c-interface-module-name #f) +(define c-interface-proc-count #f) +(define c-interface-decls #f) +(define c-interface-procs #f) +(define c-interface-inits #f) +(define (make-c-intf decls procs inits) (vector decls procs inits)) +(define (c-intf-decls c-intf) (vector-ref c-intf 0)) +(define (c-intf-decls-set! c-intf x) (vector-set! c-intf 0 x)) +(define (c-intf-procs c-intf) (vector-ref c-intf 1)) +(define (c-intf-procs-set! c-intf x) (vector-set! c-intf 1 x)) +(define (c-intf-inits c-intf) (vector-ref c-intf 2)) +(define (c-intf-inits-set! c-intf x) (vector-set! c-intf 2 x)) +(define (c-declaration-expr? source) + (and (mymatch **c-declaration-sym 1 source) + (let ((code (source-code source))) + (or (string? (source-code (cadr code))) + (pt-syntax-error + source + "Argument to '##c-declaration' must be a string"))))) +(define (c-init-expr? source) + (and (mymatch **c-init-sym 1 source) + (let ((code (source-code source))) + (or (string? (source-code (cadr code))) + (pt-syntax-error + source + "Argument to '##c-init' must be a string"))))) +(define (c-procedure-expr? source) + (and (mymatch **c-procedure-sym 3 source) + (let ((code (source-code source))) + (if (not (string? (source-code (cadddr code)))) + (pt-syntax-error + source + "Last argument to '##c-procedure' must be a string") + (check-arg-and-result-types source (cadr code) (caddr code)))))) +(define scheme-to-c-notation + (list (list void-sym "VOID" "void") + (list char-sym "CHAR" "char") + (list signed-char-sym "SCHAR" "signed char") + (list unsigned-char-sym "UCHAR" "unsigned char") + (list short-sym "SHORT" "short") + (list unsigned-short-sym "USHORT" "unsigned short") + (list int-sym "INT" "int") + (list unsigned-int-sym "UINT" "unsigned int") + (list long-sym "LONG" "long") + (list unsigned-long-sym "ULONG" "unsigned long") + (list float-sym "FLOAT" "float") + (list double-sym "DOUBLE" "double") + (list pointer-sym "POINTER" "void*") + (list boolean-sym "BOOLEAN" "int") + (list string-sym "STRING" "char*") + (list scheme-object-sym "SCMOBJ" "long"))) +(define (convert-type typ) (if (assq typ scheme-to-c-notation) typ #f)) +(define (check-arg-and-result-types source arg-typs-source res-typ-source) + (let ((arg-typs (source-code arg-typs-source)) + (res-typ (source-code res-typ-source))) + (let ((res-type (convert-type res-typ))) + (if (not res-type) + (pt-syntax-error res-typ-source "Invalid result type") + (if (not (proper-length arg-typs)) + (pt-syntax-error + arg-typs-source + "Ill-terminated argument type list") + (let loop ((lst arg-typs)) + (if (pair? lst) + (let* ((arg-typ (source-code (car lst))) + (arg-type (convert-type arg-typ))) + (if (or (not arg-type) (eq? arg-type void-sym)) + (pt-syntax-error (car lst) "Invalid argument type") + (loop (cdr lst)))) + #t))))))) +(define (add-c-declaration declaration-string) + (set! c-interface-decls (cons declaration-string c-interface-decls)) + #f) +(define (add-c-init initialization-code-string) + (set! c-interface-inits (cons initialization-code-string c-interface-inits)) + #f) +(define (add-c-proc scheme-name c-name arity def) + (set! c-interface-procs + (cons (vector scheme-name c-name arity def) c-interface-procs)) + #f) +(define (pt-c-procedure source env use) + (let* ((code (source-code source)) + (name (build-c-procedure + (map source-code (source-code (cadr code))) + (source-code (caddr code)) + (source-code (cadddr code)))) + (decl (env-declarations env))) + (new-ref source decl (env-lookup-global-var env (string->symbol name))))) +(define (build-c-procedure argument-types result-type proc-name-or-code) + (define proc-name? + (let loop ((i (- (string-length proc-name-or-code) 1))) + (if (>= i 0) + (let ((c (string-ref proc-name-or-code i))) + (if (or (char-alphabetic? c) (char=? c #\_)) (loop (- i 1)) #f)) + #t))) + (define nl (string #\newline)) + (define undefined-value "UND") + (define scheme-arg-prefix "ARG") + (define scheme-result-name "RESULT") + (define c-arg-prefix "arg") + (define c-result-name "result") + (define scheme-to-c-prefix "SCMOBJ_TO_") + (define c-to-scheme-suffix "_TO_SCMOBJ") + (define (c-type-name typ) (cadr (assq typ scheme-to-c-notation))) + (define (c-type-decl typ) (caddr (assq typ scheme-to-c-notation))) + (define (listify strings) + (if (null? strings) + "" + (string-append + (car strings) + (apply string-append + (map (lambda (s) (string-append "," s)) (cdr strings)))))) + (define (scheme-arg-var t) + (string-append c-id-prefix scheme-arg-prefix (number->string (cdr t)))) + (define (c-arg-var t) + (string-append c-id-prefix c-arg-prefix (number->string (cdr t)))) + (define (make-c-procedure arg-types res-type) + (define (make-arg-decl) + (apply string-append + (map (lambda (t) + (string-append + (c-type-decl (car t)) + " " + (c-arg-var t) + ";" + nl)) + arg-types))) + (define (make-conversions) + (if (not (null? arg-types)) + (let loop ((lst arg-types) (str (string-append "if (" nl))) + (if (null? lst) + (string-append str " )" nl) + (let ((t (car lst)) (rest (cdr lst))) + (loop rest + (string-append + str + " " + c-id-prefix + scheme-to-c-prefix + (c-type-name (car t)) + "(" + (scheme-arg-var t) + "," + (c-arg-var t) + ")" + (if (null? rest) "" " &&") + nl))))) + "")) + (define (make-body) + (if proc-name? + (let* ((param-list (listify (map c-arg-var arg-types))) + (call (string-append proc-name-or-code "(" param-list ")"))) + (if (eq? res-type void-sym) + (string-append + "{" + nl + call + ";" + nl + c-id-prefix + scheme-result-name + " = " + c-id-prefix + undefined-value + ";" + nl + "}" + nl) + (string-append + c-id-prefix + (c-type-name res-type) + c-to-scheme-suffix + "(" + call + "," + c-id-prefix + scheme-result-name + ");" + nl))) + (if (eq? res-type void-sym) + (string-append + "{" + nl + proc-name-or-code + nl + c-id-prefix + scheme-result-name + " = " + c-id-prefix + undefined-value + ";" + nl + "}" + nl) + (string-append + "{" + nl + proc-name-or-code + nl + c-id-prefix + (c-type-name res-type) + c-to-scheme-suffix + "(" + c-id-prefix + c-result-name + "," + c-id-prefix + scheme-result-name + ");" + nl + "}" + nl)))) + (let* ((index (number->string c-interface-proc-count)) + (scheme-name (string-append "#!" c-interface-module-name "#" index)) + (c-name (string-append c-id-prefix (scheme-id->c-id scheme-name))) + (arity (length argument-types)) + (def (string-append + (if (or proc-name? (eq? res-type void-sym)) + "" + (string-append + (c-type-decl res-type) + " " + c-id-prefix + c-result-name + ";" + nl)) + (make-arg-decl) + (make-conversions) + (make-body)))) + (set! c-interface-proc-count (+ c-interface-proc-count 1)) + (add-c-proc scheme-name c-name arity def) + scheme-name)) + (let loop ((i 1) (lst1 argument-types) (lst2 '())) + (if (pair? lst1) + (loop (+ i 1) (cdr lst1) (cons (cons (car lst1) i) lst2)) + (make-c-procedure (reverse lst2) result-type)))) +(define (scheme-id->c-id s) + (define (hex->char i) (string-ref "0123456789abcdef" i)) + (let loop ((i (- (string-length s) 1)) (l '())) + (if (>= i 0) + (let ((c (string-ref s i))) + (cond ((or (char-alphabetic? c) (char-numeric? c)) + (loop (- i 1) (cons c l))) + ((char=? c #\_) (loop (- i 1) (cons c (cons c l)))) + (else + (let ((n (character-encoding c))) + (loop (- i 1) + (cons #\_ + (cons (hex->char (quotient n 16)) + (cons (hex->char (modulo n 16)) l)))))))) + (lst->string l)))) +(define (pt-syntax-error source msg . args) + (apply compiler-user-error + (cons (source-locat source) + (cons (string-append "Syntax error -- " msg) args)))) +(define (pt source env use) + (cond ((macro-expr? source env) (pt (macro-expand source env) env use)) + ((self-eval-expr? source) (pt-self-eval source env use)) + ((quote-expr? source) (pt-quote source env use)) + ((quasiquote-expr? source) (pt-quasiquote source env use)) + ((unquote-expr? source) + (pt-syntax-error source "Ill-placed 'unquote'")) + ((unquote-splicing-expr? source) + (pt-syntax-error source "Ill-placed 'unquote-splicing'")) + ((var-expr? source env) (pt-var source env use)) + ((set!-expr? source env) (pt-set! source env use)) + ((lambda-expr? source env) (pt-lambda source env use)) + ((if-expr? source) (pt-if source env use)) + ((cond-expr? source) (pt-cond source env use)) + ((and-expr? source) (pt-and source env use)) + ((or-expr? source) (pt-or source env use)) + ((case-expr? source) (pt-case source env use)) + ((let-expr? source env) (pt-let source env use)) + ((let*-expr? source env) (pt-let* source env use)) + ((letrec-expr? source env) (pt-letrec source env use)) + ((begin-expr? source) (pt-begin source env use)) + ((do-expr? source env) (pt-do source env use)) + ((define-expr? source env) + (pt-syntax-error source "Ill-placed 'define'")) + ((delay-expr? source env) (pt-delay source env use)) + ((future-expr? source env) (pt-future source env use)) + ((define-macro-expr? source env) + (pt-syntax-error source "Ill-placed '##define-macro'")) + ((begin-defs-expr? source) + (pt-syntax-error source "Ill-placed 'begin' style definitions")) + ((declare-expr? source) + (pt-syntax-error source "Ill-placed '##declare'")) + ((c-declaration-expr? source) + (pt-syntax-error source "Ill-placed '##c-declaration'")) + ((c-init-expr? source) + (pt-syntax-error source "Ill-placed '##c-init'")) + ((c-procedure-expr? source) (pt-c-procedure source env use)) + ((combination-expr? source) (pt-combination source env use)) + (else (compiler-internal-error "pt, unknown expression type" source)))) +(define (macro-expand source env) + (let ((code (source-code source))) + (expression->source + (apply (cdr (env-lookup-macro env (source-code (car code)))) + (cdr (source->expression source))) + source))) +(define (pt-self-eval source env use) + (let ((val (source->expression source))) + (if (eq? use 'none) + (new-cst source (env-declarations env) undef-object) + (new-cst source (env-declarations env) val)))) +(define (pt-quote source env use) + (let ((code (source-code source))) + (if (eq? use 'none) + (new-cst source (env-declarations env) undef-object) + (new-cst source + (env-declarations env) + (source->expression (cadr code)))))) +(define (pt-quasiquote source env use) + (let ((code (source-code source))) (pt-quasiquotation (cadr code) 1 env))) +(define (pt-quasiquotation form level env) + (cond ((= level 0) (pt form env 'true)) + ((quasiquote-expr? form) + (pt-quasiquotation-list form (source-code form) (+ level 1) env)) + ((unquote-expr? form) + (if (= level 1) + (pt (cadr (source-code form)) env 'true) + (pt-quasiquotation-list form (source-code form) (- level 1) env))) + ((unquote-splicing-expr? form) + (if (= level 1) + (pt-syntax-error form "Ill-placed 'unquote-splicing'") + (pt-quasiquotation-list form (source-code form) (- level 1) env))) + ((pair? (source-code form)) + (pt-quasiquotation-list form (source-code form) level env)) + ((vector? (source-code form)) + (vector-form + form + (pt-quasiquotation-list + form + (vector->lst (source-code form)) + level + env) + env)) + (else + (new-cst form (env-declarations env) (source->expression form))))) +(define (pt-quasiquotation-list form l level env) + (cond ((pair? l) + (if (and (unquote-splicing-expr? (car l)) (= level 1)) + (let ((x (pt (cadr (source-code (car l))) env 'true))) + (if (null? (cdr l)) + x + (append-form + (car l) + x + (pt-quasiquotation-list form (cdr l) 1 env) + env))) + (cons-form + form + (pt-quasiquotation (car l) level env) + (pt-quasiquotation-list form (cdr l) level env) + env))) + ((null? l) (new-cst form (env-declarations env) '())) + (else (pt-quasiquotation l level env)))) +(define (append-form source ptree1 ptree2 env) + (cond ((and (cst? ptree1) (cst? ptree2)) + (new-cst source + (env-declarations env) + (append (cst-val ptree1) (cst-val ptree2)))) + ((and (cst? ptree2) (null? (cst-val ptree2))) ptree1) + (else + (new-call* + source + (add-not-safe (env-declarations env)) + (new-ref-extended-bindings source **quasi-append-sym env) + (list ptree1 ptree2))))) +(define (cons-form source ptree1 ptree2 env) + (cond ((and (cst? ptree1) (cst? ptree2)) + (new-cst source + (env-declarations env) + (cons (cst-val ptree1) (cst-val ptree2)))) + ((and (cst? ptree2) (null? (cst-val ptree2))) + (new-call* + source + (add-not-safe (env-declarations env)) + (new-ref-extended-bindings source **quasi-list-sym env) + (list ptree1))) + (else + (new-call* + source + (add-not-safe (env-declarations env)) + (new-ref-extended-bindings source **quasi-cons-sym env) + (list ptree1 ptree2))))) +(define (vector-form source ptree env) + (if (cst? ptree) + (new-cst source (env-declarations env) (lst->vector (cst-val ptree))) + (new-call* + source + (add-not-safe (env-declarations env)) + (new-ref-extended-bindings source **quasi-list->vector-sym env) + (list ptree)))) +(define (pt-var source env use) + (if (eq? use 'none) + (new-cst source (env-declarations env) undef-object) + (new-ref source + (env-declarations env) + (env-lookup-var env (source-code source) source)))) +(define (pt-set! source env use) + (let ((code (source-code source))) + (new-set source + (env-declarations env) + (env-lookup-var env (source-code (cadr code)) (cadr code)) + (pt (caddr code) env 'true)))) +(define (pt-lambda source env use) + (let ((code (source-code source))) + (define (new-params parms) + (cond ((pair? parms) + (let* ((parm* (car parms)) + (parm (source-code parm*)) + (p* (if (pair? parm) (car parm) parm*))) + (cons (make-var (source-code p*) #t (set-empty) (set-empty) p*) + (new-params (cdr parms))))) + ((null? parms) '()) + (else + (list (make-var + (source-code parms) + #t + (set-empty) + (set-empty) + parms))))) + (define (min-params parms) + (let loop ((l parms) (n 0)) + (if (pair? l) + (if (pair? (source-code (car l))) n (loop (cdr l) (+ n 1))) + n))) + (define (rest-param? parms) + (if (pair? parms) (rest-param? (cdr parms)) (not (null? parms)))) + (define (optionals parms source body env) + (if (pair? parms) + (let* ((parm* (car parms)) (parm (source-code parm*))) + (if (and (pair? parm) (length? parm 2)) + (let* ((var (car parm)) + (vars (new-variables (list var))) + (decl (env-declarations env))) + (new-call* + parm* + decl + (new-prc parm* + decl + #f + 1 + #f + vars + (optionals + (cdr parms) + source + body + (env-frame env vars))) + (list (new-tst parm* + decl + (new-call* + parm* + decl + (new-ref-extended-bindings + parm* + **unassigned?-sym + env) + (list (new-ref parm* + decl + (env-lookup-var + env + (source-code var) + var)))) + (pt (cadr parm) env 'true) + (new-ref parm* + decl + (env-lookup-var + env + (source-code var) + var)))))) + (optionals (cdr parms) source body env))) + (pt-body source body env 'true))) + (if (eq? use 'none) + (new-cst source (env-declarations env) undef-object) + (let* ((parms (source->parms (cadr code))) (frame (new-params parms))) + (new-prc source + (env-declarations env) + #f + (min-params parms) + (rest-param? parms) + frame + (optionals + parms + source + (cddr code) + (env-frame env frame))))))) +(define (source->parms source) + (let ((x (source-code source))) (if (or (pair? x) (null? x)) x source))) +(define (pt-body source body env use) + (define (letrec-defines vars vals envs body env) + (cond ((null? body) + (pt-syntax-error + source + "Body must contain at least one evaluable expression")) + ((macro-expr? (car body) env) + (letrec-defines + vars + vals + envs + (cons (macro-expand (car body) env) (cdr body)) + env)) + ((begin-defs-expr? (car body)) + (letrec-defines + vars + vals + envs + (append (begin-defs-body (car body)) (cdr body)) + env)) + ((include-expr? (car body)) + (if *ptree-port* (display " " *ptree-port*)) + (let ((x (file->sources* + (include-filename (car body)) + *ptree-port* + (source-locat (car body))))) + (if *ptree-port* (newline *ptree-port*)) + (letrec-defines vars vals envs (append x (cdr body)) env))) + ((define-expr? (car body) env) + (let* ((var** (definition-variable (car body))) + (var* (source-code var**)) + (var (env-define-var env var* var**))) + (letrec-defines + (cons var vars) + (cons (definition-value (car body)) vals) + (cons env envs) + (cdr body) + env))) + ((declare-expr? (car body)) + (letrec-defines + vars + vals + envs + (cdr body) + (add-declarations (car body) env))) + ((define-macro-expr? (car body) env) + (letrec-defines + vars + vals + envs + (cdr body) + (add-macro (car body) env))) + ((c-declaration-expr? (car body)) + (add-c-declaration (source-code (cadr (source-code (car body))))) + (letrec-defines vars vals envs (cdr body) env)) + ((c-init-expr? (car body)) + (add-c-init (source-code (cadr (source-code (car body))))) + (letrec-defines vars vals envs (cdr body) env)) + ((null? vars) (pt-sequence source body env use)) + (else + (let ((vars* (reverse vars))) + (let loop ((vals* '()) (l1 vals) (l2 envs)) + (if (not (null? l1)) + (loop (cons (pt (car l1) (car l2) 'true) vals*) + (cdr l1) + (cdr l2)) + (pt-recursive-let source vars* vals* body env use))))))) + (letrec-defines '() '() '() body (env-frame env '()))) +(define (pt-sequence source seq env use) + (if (length? seq 1) + (pt (car seq) env use) + (new-seq source + (env-declarations env) + (pt (car seq) env 'none) + (pt-sequence source (cdr seq) env use)))) +(define (pt-if source env use) + (let ((code (source-code source))) + (new-tst source + (env-declarations env) + (pt (cadr code) env 'pred) + (pt (caddr code) env use) + (if (length? code 3) + (new-cst source (env-declarations env) undef-object) + (pt (cadddr code) env use))))) +(define (pt-cond source env use) + (define (pt-clauses clauses) + (if (length? clauses 0) + (new-cst source (env-declarations env) undef-object) + (let* ((clause* (car clauses)) (clause (source-code clause*))) + (cond ((eq? (source-code (car clause)) else-sym) + (pt-sequence clause* (cdr clause) env use)) + ((length? clause 1) + (new-disj + clause* + (env-declarations env) + (pt (car clause) env (if (eq? use 'true) 'true 'pred)) + (pt-clauses (cdr clauses)))) + ((eq? (source-code (cadr clause)) =>-sym) + (new-disj-call + clause* + (env-declarations env) + (pt (car clause) env 'true) + (pt (caddr clause) env 'true) + (pt-clauses (cdr clauses)))) + (else + (new-tst clause* + (env-declarations env) + (pt (car clause) env 'pred) + (pt-sequence clause* (cdr clause) env use) + (pt-clauses (cdr clauses)))))))) + (pt-clauses (cdr (source-code source)))) +(define (pt-and source env use) + (define (pt-exprs exprs) + (cond ((length? exprs 0) (new-cst source (env-declarations env) #t)) + ((length? exprs 1) (pt (car exprs) env use)) + (else + (new-conj + (car exprs) + (env-declarations env) + (pt (car exprs) env (if (eq? use 'true) 'true 'pred)) + (pt-exprs (cdr exprs)))))) + (pt-exprs (cdr (source-code source)))) +(define (pt-or source env use) + (define (pt-exprs exprs) + (cond ((length? exprs 0) + (new-cst source (env-declarations env) false-object)) + ((length? exprs 1) (pt (car exprs) env use)) + (else + (new-disj + (car exprs) + (env-declarations env) + (pt (car exprs) env (if (eq? use 'true) 'true 'pred)) + (pt-exprs (cdr exprs)))))) + (pt-exprs (cdr (source-code source)))) +(define (pt-case source env use) + (let ((code (source-code source)) (temp (new-temps source '(temp)))) + (define (pt-clauses clauses) + (if (length? clauses 0) + (new-cst source (env-declarations env) undef-object) + (let* ((clause* (car clauses)) (clause (source-code clause*))) + (if (eq? (source-code (car clause)) else-sym) + (pt-sequence clause* (cdr clause) env use) + (new-tst clause* + (env-declarations env) + (new-call* + clause* + (add-not-safe (env-declarations env)) + (new-ref-extended-bindings + clause* + **case-memv-sym + env) + (list (new-ref clause* + (env-declarations env) + (car temp)) + (new-cst (car clause) + (env-declarations env) + (source->expression (car clause))))) + (pt-sequence clause* (cdr clause) env use) + (pt-clauses (cdr clauses))))))) + (new-call* + source + (env-declarations env) + (new-prc source + (env-declarations env) + #f + 1 + #f + temp + (pt-clauses (cddr code))) + (list (pt (cadr code) env 'true))))) +(define (pt-let source env use) + (let ((code (source-code source))) + (if (bindable-var? (cadr code) env) + (let* ((self (new-variables (list (cadr code)))) + (bindings (map source-code (source-code (caddr code)))) + (vars (new-variables (map car bindings))) + (vals (map (lambda (x) (pt (cadr x) env 'true)) bindings)) + (env (env-frame (env-frame env vars) self)) + (self-proc + (list (new-prc source + (env-declarations env) + #f + (length vars) + #f + vars + (pt-body source (cdddr code) env use))))) + (set-prc-names! self self-proc) + (set-prc-names! vars vals) + (new-call* + source + (env-declarations env) + (new-prc source + (env-declarations env) + #f + 1 + #f + self + (new-call* + source + (env-declarations env) + (new-ref source (env-declarations env) (car self)) + vals)) + self-proc)) + (if (null? (source-code (cadr code))) + (pt-body source (cddr code) env use) + (let* ((bindings (map source-code (source-code (cadr code)))) + (vars (new-variables (map car bindings))) + (vals (map (lambda (x) (pt (cadr x) env 'true)) bindings)) + (env (env-frame env vars))) + (set-prc-names! vars vals) + (new-call* + source + (env-declarations env) + (new-prc source + (env-declarations env) + #f + (length vars) + #f + vars + (pt-body source (cddr code) env use)) + vals)))))) +(define (pt-let* source env use) + (let ((code (source-code source))) + (define (pt-bindings bindings env use) + (if (null? bindings) + (pt-body source (cddr code) env use) + (let* ((binding* (car bindings)) + (binding (source-code binding*)) + (vars (new-variables (list (car binding)))) + (vals (list (pt (cadr binding) env 'true))) + (env (env-frame env vars))) + (set-prc-names! vars vals) + (new-call* + binding* + (env-declarations env) + (new-prc binding* + (env-declarations env) + #f + 1 + #f + vars + (pt-bindings (cdr bindings) env use)) + vals)))) + (pt-bindings (source-code (cadr code)) env use))) +(define (pt-letrec source env use) + (let* ((code (source-code source)) + (bindings (map source-code (source-code (cadr code)))) + (vars* (new-variables (map car bindings))) + (env* (env-frame env vars*))) + (pt-recursive-let + source + vars* + (map (lambda (x) (pt (cadr x) env* 'true)) bindings) + (cddr code) + env* + use))) +(define (pt-recursive-let source vars vals body env use) + (define (dependency-graph vars vals) + (define (dgraph vars* vals*) + (if (null? vars*) + (set-empty) + (let ((var (car vars*)) (val (car vals*))) + (set-adjoin + (dgraph (cdr vars*) (cdr vals*)) + (make-gnode + var + (set-intersection (list->set vars) (free-variables val))))))) + (dgraph vars vals)) + (define (val-of var) + (list-ref vals (- (length vars) (length (memq var vars))))) + (define (bind-in-order order) + (if (null? order) + (pt-body source body env use) + (let* ((vars-set (car order)) (vars (set->list vars-set))) + (let loop1 ((l (reverse vars)) + (vars-b '()) + (vals-b '()) + (vars-a '())) + (if (not (null? l)) + (let* ((var (car l)) (val (val-of var))) + (if (or (prc? val) + (set-empty? + (set-intersection (free-variables val) vars-set))) + (loop1 (cdr l) + (cons var vars-b) + (cons val vals-b) + vars-a) + (loop1 (cdr l) vars-b vals-b (cons var vars-a)))) + (let* ((result1 (let loop2 ((l vars-a)) + (if (not (null? l)) + (let* ((var (car l)) (val (val-of var))) + (new-seq source + (env-declarations env) + (new-set source + (env-declarations + env) + var + val) + (loop2 (cdr l)))) + (bind-in-order (cdr order))))) + (result2 (if (null? vars-b) + result1 + (new-call* + source + (env-declarations env) + (new-prc source + (env-declarations env) + #f + (length vars-b) + #f + vars-b + result1) + vals-b))) + (result3 (if (null? vars-a) + result2 + (new-call* + source + (env-declarations env) + (new-prc source + (env-declarations env) + #f + (length vars-a) + #f + vars-a + result2) + (map (lambda (var) + (new-cst source + (env-declarations env) + undef-object)) + vars-a))))) + result3)))))) + (set-prc-names! vars vals) + (bind-in-order + (topological-sort (transitive-closure (dependency-graph vars vals))))) +(define (pt-begin source env use) + (pt-sequence source (cdr (source-code source)) env use)) +(define (pt-do source env use) + (let* ((code (source-code source)) + (loop (new-temps source '(loop))) + (bindings (map source-code (source-code (cadr code)))) + (vars (new-variables (map car bindings))) + (init (map (lambda (x) (pt (cadr x) env 'true)) bindings)) + (env (env-frame env vars)) + (step (map (lambda (x) + (pt (if (length? x 2) (car x) (caddr x)) env 'true)) + bindings)) + (exit (source-code (caddr code)))) + (set-prc-names! vars init) + (new-call* + source + (env-declarations env) + (new-prc source + (env-declarations env) + #f + 1 + #f + loop + (new-call* + source + (env-declarations env) + (new-ref source (env-declarations env) (car loop)) + init)) + (list (new-prc source + (env-declarations env) + #f + (length vars) + #f + vars + (new-tst source + (env-declarations env) + (pt (car exit) env 'pred) + (if (length? exit 1) + (new-cst (caddr code) + (env-declarations env) + undef-object) + (pt-sequence (caddr code) (cdr exit) env use)) + (if (length? code 3) + (new-call* + source + (env-declarations env) + (new-ref source + (env-declarations env) + (car loop)) + step) + (new-seq source + (env-declarations env) + (pt-sequence + source + (cdddr code) + env + 'none) + (new-call* + source + (env-declarations env) + (new-ref source + (env-declarations env) + (car loop)) + step))))))))) +(define (pt-combination source env use) + (let* ((code (source-code source)) + (oper (pt (car code) env 'true)) + (decl (node-decl oper))) + (new-call* + source + (env-declarations env) + oper + (map (lambda (x) (pt x env 'true)) (cdr code))))) +(define (pt-delay source env use) + (let ((code (source-code source))) + (new-call* + source + (add-not-safe (env-declarations env)) + (new-ref-extended-bindings source **make-placeholder-sym env) + (list (new-prc source + (env-declarations env) + #f + 0 + #f + '() + (pt (cadr code) env 'true)))))) +(define (pt-future source env use) + (let ((decl (env-declarations env)) (code (source-code source))) + (new-fut source decl (pt (cadr code) env 'true)))) +(define (self-eval-expr? source) + (let ((code (source-code source))) + (and (not (pair? code)) (not (symbol-object? code))))) +(define (quote-expr? source) (mymatch quote-sym 1 source)) +(define (quasiquote-expr? source) (mymatch quasiquote-sym 1 source)) +(define (unquote-expr? source) (mymatch unquote-sym 1 source)) +(define (unquote-splicing-expr? source) + (mymatch unquote-splicing-sym 1 source)) +(define (var-expr? source env) + (let ((code (source-code source))) + (and (symbol-object? code) + (not-keyword source env code) + (not-macro source env code)))) +(define (not-macro source env name) + (if (env-lookup-macro env name) + (pt-syntax-error source "Macro name can't be used as a variable:" name) + #t)) +(define (bindable-var? source env) + (let ((code (source-code source))) + (and (symbol-object? code) (not-keyword source env code)))) +(define (not-keyword source env name) + (if (or (memq name common-keywords) + (memq name + (dialect-specific-keywords + (scheme-dialect (env-declarations env))))) + (pt-syntax-error + source + "Predefined keyword can't be used as a variable:" + name) + #t)) +(define (set!-expr? source env) + (and (mymatch set!-sym 2 source) + (var-expr? (cadr (source-code source)) env))) +(define (lambda-expr? source env) + (and (mymatch lambda-sym -2 source) + (proper-parms? (source->parms (cadr (source-code source))) env))) +(define (if-expr? source) + (and (mymatch if-sym -2 source) + (or (<= (length (source-code source)) 4) + (pt-syntax-error source "Ill-formed special form" if-sym)))) +(define (cond-expr? source) + (and (mymatch cond-sym -1 source) (proper-clauses? source))) +(define (and-expr? source) (mymatch and-sym 0 source)) +(define (or-expr? source) (mymatch or-sym 0 source)) +(define (case-expr? source) + (and (mymatch case-sym -2 source) (proper-case-clauses? source))) +(define (let-expr? source env) + (and (mymatch let-sym -2 source) + (let ((code (source-code source))) + (if (bindable-var? (cadr code) env) + (and (proper-bindings? (caddr code) #t env) + (or (> (length code) 3) + (pt-syntax-error source "Ill-formed named 'let'"))) + (proper-bindings? (cadr code) #t env))))) +(define (let*-expr? source env) + (and (mymatch let*-sym -2 source) + (proper-bindings? (cadr (source-code source)) #f env))) +(define (letrec-expr? source env) + (and (mymatch letrec-sym -2 source) + (proper-bindings? (cadr (source-code source)) #t env))) +(define (begin-expr? source) (mymatch begin-sym -1 source)) +(define (do-expr? source env) + (and (mymatch do-sym -2 source) + (proper-do-bindings? source env) + (proper-do-exit? source))) +(define (define-expr? source env) + (and (mymatch define-sym -1 source) + (proper-definition? source env) + (let ((v (definition-variable source))) + (not-macro v env (source-code v))))) +(define (combination-expr? source) + (let ((length (proper-length (source-code source)))) + (if length + (or (> length 0) (pt-syntax-error source "Ill-formed procedure call")) + (pt-syntax-error source "Ill-terminated procedure call")))) +(define (delay-expr? source env) + (and (not (eq? (scheme-dialect (env-declarations env)) ieee-scheme-sym)) + (mymatch delay-sym 1 source))) +(define (future-expr? source env) + (and (eq? (scheme-dialect (env-declarations env)) multilisp-sym) + (mymatch future-sym 1 source))) +(define (macro-expr? source env) + (let ((code (source-code source))) + (and (pair? code) + (symbol-object? (source-code (car code))) + (let ((macr (env-lookup-macro env (source-code (car code))))) + (and macr + (let ((len (proper-length (cdr code)))) + (if len + (let ((len* (+ len 1)) (size (car macr))) + (or (if (> size 0) (= len* size) (>= len* (- size))) + (pt-syntax-error source "Ill-formed macro form"))) + (pt-syntax-error + source + "Ill-terminated macro form")))))))) +(define (define-macro-expr? source env) + (and (mymatch **define-macro-sym -1 source) (proper-definition? source env))) +(define (declare-expr? source) (mymatch **declare-sym -1 source)) +(define (include-expr? source) (mymatch **include-sym 1 source)) +(define (begin-defs-expr? source) (mymatch begin-sym 0 source)) +(define (mymatch keyword size source) + (let ((code (source-code source))) + (and (pair? code) + (eq? (source-code (car code)) keyword) + (let ((length (proper-length (cdr code)))) + (if length + (or (if (> size 0) (= length size) (>= length (- size))) + (pt-syntax-error source "Ill-formed special form" keyword)) + (pt-syntax-error + source + "Ill-terminated special form" + keyword)))))) +(define (proper-length l) + (define (length l n) + (cond ((pair? l) (length (cdr l) (+ n 1))) ((null? l) n) (else #f))) + (length l 0)) +(define (proper-definition? source env) + (let* ((code (source-code source)) + (pattern* (cadr code)) + (pattern (source-code pattern*)) + (body (cddr code))) + (cond ((bindable-var? pattern* env) + (cond ((length? body 0) #t) + ((length? body 1) #t) + (else (pt-syntax-error source "Ill-formed definition body")))) + ((pair? pattern) + (if (length? body 0) + (pt-syntax-error + source + "Body of a definition must have at least one expression")) + (if (bindable-var? (car pattern) env) + (proper-parms? (cdr pattern) env) + (pt-syntax-error + (car pattern) + "Procedure name must be an identifier"))) + (else (pt-syntax-error pattern* "Ill-formed definition pattern"))))) +(define (definition-variable def) + (let* ((code (source-code def)) (pattern (cadr code))) + (if (pair? (source-code pattern)) (car (source-code pattern)) pattern))) +(define (definition-value def) + (let ((code (source-code def)) (loc (source-locat def))) + (cond ((pair? (source-code (cadr code))) + (make-source + (cons (make-source lambda-sym loc) + (cons (parms->source (cdr (source-code (cadr code))) loc) + (cddr code))) + loc)) + ((null? (cddr code)) + (make-source + (list (make-source quote-sym loc) (make-source undef-object loc)) + loc)) + (else (caddr code))))) +(define (parms->source parms loc) + (if (or (pair? parms) (null? parms)) (make-source parms loc) parms)) +(define (proper-parms? parms env) + (define (proper-parms parms seen optional-seen) + (cond ((pair? parms) + (let* ((parm* (car parms)) (parm (source-code parm*))) + (cond ((pair? parm) + (if (eq? (scheme-dialect (env-declarations env)) + multilisp-sym) + (let ((length (proper-length parm))) + (if (or (eqv? length 1) (eqv? length 2)) + (let ((var (car parm))) + (if (bindable-var? var env) + (if (memq (source-code var) seen) + (pt-syntax-error + var + "Duplicate parameter in parameter list") + (proper-parms + (cdr parms) + (cons (source-code var) seen) + #t)) + (pt-syntax-error + var + "Parameter must be an identifier"))) + (pt-syntax-error + parm* + "Ill-formed optional parameter"))) + (pt-syntax-error + parm* + "optional parameters illegal in this dialect"))) + (optional-seen + (pt-syntax-error parm* "Optional parameter expected")) + ((bindable-var? parm* env) + (if (memq parm seen) + (pt-syntax-error + parm* + "Duplicate parameter in parameter list")) + (proper-parms (cdr parms) (cons parm seen) #f)) + (else + (pt-syntax-error + parm* + "Parameter must be an identifier"))))) + ((null? parms) #t) + ((bindable-var? parms env) + (if (memq (source-code parms) seen) + (pt-syntax-error parms "Duplicate parameter in parameter list") + #t)) + (else + (pt-syntax-error parms "Rest parameter must be an identifier")))) + (proper-parms parms '() #f)) +(define (proper-clauses? source) + (define (proper-clauses clauses) + (or (null? clauses) + (let* ((clause* (car clauses)) + (clause (source-code clause*)) + (length (proper-length clause))) + (if length + (if (>= length 1) + (if (eq? (source-code (car clause)) else-sym) + (cond ((= length 1) + (pt-syntax-error + clause* + "Else clause must have a body")) + ((not (null? (cdr clauses))) + (pt-syntax-error + clause* + "Else clause must be the last clause")) + (else (proper-clauses (cdr clauses)))) + (if (and (>= length 2) + (eq? (source-code (cadr clause)) =>-sym) + (not (= length 3))) + (pt-syntax-error + (cadr clause) + "'=>' must be followed by a single expression") + (proper-clauses (cdr clauses)))) + (pt-syntax-error clause* "Ill-formed 'cond' clause")) + (pt-syntax-error clause* "Ill-terminated 'cond' clause"))))) + (proper-clauses (cdr (source-code source)))) +(define (proper-case-clauses? source) + (define (proper-case-clauses clauses) + (or (null? clauses) + (let* ((clause* (car clauses)) + (clause (source-code clause*)) + (length (proper-length clause))) + (if length + (if (>= length 2) + (if (eq? (source-code (car clause)) else-sym) + (if (not (null? (cdr clauses))) + (pt-syntax-error + clause* + "Else clause must be the last clause") + (proper-case-clauses (cdr clauses))) + (begin + (proper-selector-list? (car clause)) + (proper-case-clauses (cdr clauses)))) + (pt-syntax-error + clause* + "A 'case' clause must have a selector list and a body")) + (pt-syntax-error clause* "Ill-terminated 'case' clause"))))) + (proper-case-clauses (cddr (source-code source)))) +(define (proper-selector-list? source) + (let* ((code (source-code source)) (length (proper-length code))) + (if length + (or (>= length 1) + (pt-syntax-error + source + "Selector list must contain at least one element")) + (pt-syntax-error source "Ill-terminated selector list")))) +(define (proper-bindings? bindings check-dupl? env) + (define (proper-bindings l seen) + (cond ((pair? l) + (let* ((binding* (car l)) (binding (source-code binding*))) + (if (eqv? (proper-length binding) 2) + (let ((var (car binding))) + (if (bindable-var? var env) + (if (and check-dupl? (memq (source-code var) seen)) + (pt-syntax-error + var + "Duplicate variable in bindings") + (proper-bindings + (cdr l) + (cons (source-code var) seen))) + (pt-syntax-error + var + "Binding variable must be an identifier"))) + (pt-syntax-error binding* "Ill-formed binding")))) + ((null? l) #t) + (else (pt-syntax-error bindings "Ill-terminated binding list")))) + (proper-bindings (source-code bindings) '())) +(define (proper-do-bindings? source env) + (let ((bindings (cadr (source-code source)))) + (define (proper-bindings l seen) + (cond ((pair? l) + (let* ((binding* (car l)) + (binding (source-code binding*)) + (length (proper-length binding))) + (if (or (eqv? length 2) (eqv? length 3)) + (let ((var (car binding))) + (if (bindable-var? var env) + (if (memq (source-code var) seen) + (pt-syntax-error + var + "Duplicate variable in bindings") + (proper-bindings + (cdr l) + (cons (source-code var) seen))) + (pt-syntax-error + var + "Binding variable must be an identifier"))) + (pt-syntax-error binding* "Ill-formed binding")))) + ((null? l) #t) + (else (pt-syntax-error bindings "Ill-terminated binding list")))) + (proper-bindings (source-code bindings) '()))) +(define (proper-do-exit? source) + (let* ((code (source-code (caddr (source-code source)))) + (length (proper-length code))) + (if length + (or (> length 0) (pt-syntax-error source "Ill-formed exit clause")) + (pt-syntax-error source "Ill-terminated exit clause")))) +(define (include-filename source) (source-code (cadr (source-code source)))) +(define (begin-defs-body source) (cdr (source-code source))) +(define (length? l n) + (cond ((null? l) (= n 0)) ((> n 0) (length? (cdr l) (- n 1))) (else #f))) +(define (transform-declaration source) + (let ((code (source-code source))) + (if (not (pair? code)) + (pt-syntax-error source "Ill-formed declaration") + (let* ((pos (not (eq? (source-code (car code)) not-sym))) + (x (if pos code (cdr code)))) + (if (not (pair? x)) + (pt-syntax-error source "Ill-formed declaration") + (let* ((id* (car x)) (id (source-code id*))) + (cond ((not (symbol-object? id)) + (pt-syntax-error + id* + "Declaration name must be an identifier")) + ((assq id flag-declarations) + (cond ((not pos) + (pt-syntax-error + id* + "Declaration can't be negated")) + ((null? (cdr x)) + (flag-decl + source + (cdr (assq id flag-declarations)) + id)) + (else + (pt-syntax-error + source + "Ill-formed declaration")))) + ((memq id parameterized-declarations) + (cond ((not pos) + (pt-syntax-error + id* + "Declaration can't be negated")) + ((eqv? (proper-length x) 2) + (parameterized-decl + source + id + (source->expression (cadr x)))) + (else + (pt-syntax-error + source + "Ill-formed declaration")))) + ((memq id boolean-declarations) + (if (null? (cdr x)) + (boolean-decl source id pos) + (pt-syntax-error source "Ill-formed declaration"))) + ((assq id namable-declarations) + (cond ((not pos) + (pt-syntax-error + id* + "Declaration can't be negated")) + (else + (namable-decl + source + (cdr (assq id namable-declarations)) + id + (map source->expression (cdr x)))))) + ((memq id namable-boolean-declarations) + (namable-boolean-decl + source + id + pos + (map source->expression (cdr x)))) + ((memq id namable-string-declarations) + (if (not (pair? (cdr x))) + (pt-syntax-error source "Ill-formed declaration") + (let* ((str* (cadr x)) (str (source-code str*))) + (cond ((not pos) + (pt-syntax-error + id* + "Declaration can't be negated")) + ((not (string? str)) + (pt-syntax-error str* "String expected")) + (else + (namable-string-decl + source + id + str + (map source->expression (cddr x)))))))) + (else (pt-syntax-error id* "Unknown declaration"))))))))) +(define (add-declarations source env) + (let loop ((l (cdr (source-code source))) (env env)) + (if (pair? l) + (loop (cdr l) (env-declare env (transform-declaration (car l)))) + env))) +(define (add-decl d decl) (env-declare decl d)) +(define (add-macro source env) + (define (form-size parms) + (let loop ((l parms) (n 1)) + (if (pair? l) (loop (cdr l) (+ n 1)) (if (null? l) n (- n))))) + (define (error-proc . msgs) + (apply compiler-user-error + (cons (source-locat source) (cons "(in macro body)" msgs)))) + (let ((var (definition-variable source)) (proc (definition-value source))) + (if (lambda-expr? proc env) + (env-macro + env + (source-code var) + (cons (form-size (source->parms (cadr (source-code proc)))) + (scheme-global-eval (source->expression proc) error-proc))) + (pt-syntax-error source "Macro value must be a lambda expression")))) +(define (ptree.begin! info-port) (set! *ptree-port* info-port) '()) +(define (ptree.end!) '()) +(define *ptree-port* '()) +(define (normalize-parse-tree ptree env) + (define (normalize ptree) + (let ((tree (assignment-convert (partial-evaluate ptree) env))) + (lambda-lift! tree) + tree)) + (if (def? ptree) + (begin + (node-children-set! ptree (list (normalize (def-val ptree)))) + ptree) + (normalize ptree))) +(define (partial-evaluate ptree) (pe ptree '())) +(define (pe ptree consts) + (cond ((cst? ptree) + (new-cst (node-source ptree) (node-decl ptree) (cst-val ptree))) + ((ref? ptree) + (let ((var (ref-var ptree))) + (var-refs-set! var (set-remove (var-refs var) ptree)) + (let ((x (assq var consts))) + (if x + (new-cst (node-source ptree) (node-decl ptree) (cdr x)) + (let ((y (global-val var))) + (if (and y (cst? y)) + (new-cst (node-source ptree) + (node-decl ptree) + (cst-val y)) + (new-ref (node-source ptree) + (node-decl ptree) + var))))))) + ((set? ptree) + (let ((var (set-var ptree)) (val (pe (set-val ptree) consts))) + (var-sets-set! var (set-remove (var-sets var) ptree)) + (new-set (node-source ptree) (node-decl ptree) var val))) + ((tst? ptree) + (let ((pre (pe (tst-pre ptree) consts))) + (if (cst? pre) + (let ((val (cst-val pre))) + (if (false-object? val) + (pe (tst-alt ptree) consts) + (pe (tst-con ptree) consts))) + (new-tst (node-source ptree) + (node-decl ptree) + pre + (pe (tst-con ptree) consts) + (pe (tst-alt ptree) consts))))) + ((conj? ptree) + (let ((pre (pe (conj-pre ptree) consts))) + (if (cst? pre) + (let ((val (cst-val pre))) + (if (false-object? val) pre (pe (conj-alt ptree) consts))) + (new-conj + (node-source ptree) + (node-decl ptree) + pre + (pe (conj-alt ptree) consts))))) + ((disj? ptree) + (let ((pre (pe (disj-pre ptree) consts))) + (if (cst? pre) + (let ((val (cst-val pre))) + (if (false-object? val) (pe (disj-alt ptree) consts) pre)) + (new-disj + (node-source ptree) + (node-decl ptree) + pre + (pe (disj-alt ptree) consts))))) + ((prc? ptree) + (new-prc (node-source ptree) + (node-decl ptree) + (prc-name ptree) + (prc-min ptree) + (prc-rest ptree) + (prc-parms ptree) + (pe (prc-body ptree) consts))) + ((app? ptree) + (let ((oper (app-oper ptree)) (args (app-args ptree))) + (if (and (prc? oper) + (not (prc-rest oper)) + (= (length (prc-parms oper)) (length args))) + (pe-let ptree consts) + (new-call + (node-source ptree) + (node-decl ptree) + (pe oper consts) + (map (lambda (x) (pe x consts)) args))))) + ((fut? ptree) + (new-fut (node-source ptree) + (node-decl ptree) + (pe (fut-val ptree) consts))) + (else (compiler-internal-error "pe, unknown parse tree node type")))) +(define (pe-let ptree consts) + (let* ((proc (app-oper ptree)) + (vals (app-args ptree)) + (vars (prc-parms proc)) + (non-mut-vars (set-keep not-mutable? (list->set vars)))) + (for-each + (lambda (var) + (var-refs-set! var (set-empty)) + (var-sets-set! var (set-empty))) + vars) + (let loop ((l vars) + (v vals) + (new-vars '()) + (new-vals '()) + (new-consts consts)) + (if (null? l) + (if (null? new-vars) + (pe (prc-body proc) new-consts) + (new-call + (node-source ptree) + (node-decl ptree) + (new-prc (node-source proc) + (node-decl proc) + #f + (length new-vars) + #f + (reverse new-vars) + (pe (prc-body proc) new-consts)) + (reverse new-vals))) + (let ((var (car l)) (val (pe (car v) consts))) + (if (and (set-member? var non-mut-vars) (cst? val)) + (loop (cdr l) + (cdr v) + new-vars + new-vals + (cons (cons var (cst-val val)) new-consts)) + (loop (cdr l) + (cdr v) + (cons var new-vars) + (cons val new-vals) + new-consts))))))) +(define (assignment-convert ptree env) + (ac ptree (env-declare env (list safe-sym #f)) '())) +(define (ac ptree env mut) + (cond ((cst? ptree) ptree) + ((ref? ptree) + (let ((var (ref-var ptree))) + (if (global? var) + ptree + (let ((x (assq var mut))) + (if x + (let ((source (node-source ptree))) + (var-refs-set! var (set-remove (var-refs var) ptree)) + (new-call + source + (node-decl ptree) + (new-ref-extended-bindings source **cell-ref-sym env) + (list (new-ref source (node-decl ptree) (cdr x))))) + ptree))))) + ((set? ptree) + (let ((var (set-var ptree)) + (source (node-source ptree)) + (val (ac (set-val ptree) env mut))) + (var-sets-set! var (set-remove (var-sets var) ptree)) + (if (global? var) + (new-set source (node-decl ptree) var val) + (new-call + source + (node-decl ptree) + (new-ref-extended-bindings source **cell-set!-sym env) + (list (new-ref source (node-decl ptree) (cdr (assq var mut))) + val))))) + ((tst? ptree) + (new-tst (node-source ptree) + (node-decl ptree) + (ac (tst-pre ptree) env mut) + (ac (tst-con ptree) env mut) + (ac (tst-alt ptree) env mut))) + ((conj? ptree) + (new-conj + (node-source ptree) + (node-decl ptree) + (ac (conj-pre ptree) env mut) + (ac (conj-alt ptree) env mut))) + ((disj? ptree) + (new-disj + (node-source ptree) + (node-decl ptree) + (ac (disj-pre ptree) env mut) + (ac (disj-alt ptree) env mut))) + ((prc? ptree) (ac-proc ptree env mut)) + ((app? ptree) + (let ((oper (app-oper ptree)) (args (app-args ptree))) + (if (and (prc? oper) + (not (prc-rest oper)) + (= (length (prc-parms oper)) (length args))) + (ac-let ptree env mut) + (new-call + (node-source ptree) + (node-decl ptree) + (ac oper env mut) + (map (lambda (x) (ac x env mut)) args))))) + ((fut? ptree) + (new-fut (node-source ptree) + (node-decl ptree) + (ac (fut-val ptree) env mut))) + (else (compiler-internal-error "ac, unknown parse tree node type")))) +(define (ac-proc ptree env mut) + (let* ((mut-parms (ac-mutables (prc-parms ptree))) + (mut-parms-copies (map var-copy mut-parms)) + (mut (append (pair-up mut-parms mut-parms-copies) mut)) + (new-body (ac (prc-body ptree) env mut))) + (new-prc (node-source ptree) + (node-decl ptree) + (prc-name ptree) + (prc-min ptree) + (prc-rest ptree) + (prc-parms ptree) + (if (null? mut-parms) + new-body + (new-call + (node-source ptree) + (node-decl ptree) + (new-prc (node-source ptree) + (node-decl ptree) + #f + (length mut-parms-copies) + #f + mut-parms-copies + new-body) + (map (lambda (var) + (new-call + (var-source var) + (node-decl ptree) + (new-ref-extended-bindings + (var-source var) + **make-cell-sym + env) + (list (new-ref (var-source var) + (node-decl ptree) + var)))) + mut-parms)))))) +(define (ac-let ptree env mut) + (let* ((proc (app-oper ptree)) + (vals (app-args ptree)) + (vars (prc-parms proc)) + (vals-fv (apply set-union (map free-variables vals))) + (mut-parms (ac-mutables vars)) + (mut-parms-copies (map var-copy mut-parms)) + (mut (append (pair-up mut-parms mut-parms-copies) mut))) + (let loop ((l vars) + (v vals) + (new-vars '()) + (new-vals '()) + (new-body (ac (prc-body proc) env mut))) + (if (null? l) + (new-let ptree proc new-vars new-vals new-body) + (let ((var (car l)) (val (car v))) + (if (memq var mut-parms) + (let ((src (node-source val)) + (decl (node-decl val)) + (var* (cdr (assq var mut)))) + (if (set-member? var vals-fv) + (loop (cdr l) + (cdr v) + (cons var* new-vars) + (cons (new-call + src + decl + (new-ref-extended-bindings + src + **make-cell-sym + env) + (list (new-cst src decl undef-object))) + new-vals) + (new-seq src + decl + (new-call + src + decl + (new-ref-extended-bindings + src + **cell-set!-sym + env) + (list (new-ref src decl var*) + (ac val env mut))) + new-body)) + (loop (cdr l) + (cdr v) + (cons var* new-vars) + (cons (new-call + src + decl + (new-ref-extended-bindings + src + **make-cell-sym + env) + (list (ac val env mut))) + new-vals) + new-body))) + (loop (cdr l) + (cdr v) + (cons var new-vars) + (cons (ac val env mut) new-vals) + new-body))))))) +(define (ac-mutables l) + (if (pair? l) + (let ((var (car l)) (rest (ac-mutables (cdr l)))) + (if (mutable? var) (cons var rest) rest)) + '())) +(define (lambda-lift! ptree) (ll! ptree (set-empty) '())) +(define (ll! ptree cst-procs env) + (define (new-env env vars) + (define (loop i l) + (if (pair? l) + (let ((var (car l))) + (cons (cons var (cons (length (set->list (var-refs var))) i)) + (loop (+ i 1) (cdr l)))) + env)) + (loop (length env) vars)) + (cond ((or (cst? ptree) + (ref? ptree) + (set? ptree) + (tst? ptree) + (conj? ptree) + (disj? ptree) + (fut? ptree)) + (for-each + (lambda (child) (ll! child cst-procs env)) + (node-children ptree))) + ((prc? ptree) + (ll! (prc-body ptree) cst-procs (new-env env (prc-parms ptree)))) + ((app? ptree) + (let ((oper (app-oper ptree)) (args (app-args ptree))) + (if (and (prc? oper) + (not (prc-rest oper)) + (= (length (prc-parms oper)) (length args))) + (ll!-let ptree cst-procs (new-env env (prc-parms oper))) + (for-each + (lambda (child) (ll! child cst-procs env)) + (node-children ptree))))) + (else (compiler-internal-error "ll!, unknown parse tree node type")))) +(define (ll!-let ptree cst-procs env) + (let* ((proc (app-oper ptree)) + (vals (app-args ptree)) + (vars (prc-parms proc)) + (var-val-map (pair-up vars vals))) + (define (var->val var) (cdr (assq var var-val-map))) + (define (liftable-proc-vars vars) + (let loop ((cst-proc-vars + (set-keep + (lambda (var) + (let ((val (var->val var))) + (and (prc? val) + (lambda-lift? (node-decl val)) + (set-every? oper-pos? (var-refs var))))) + (list->set vars)))) + (let* ((non-cst-proc-vars + (set-keep + (lambda (var) + (let ((val (var->val var))) + (and (prc? val) (not (set-member? var cst-proc-vars))))) + (list->set vars))) + (cst-proc-vars* + (set-keep + (lambda (var) + (let ((val (var->val var))) + (set-empty? + (set-intersection + (free-variables val) + non-cst-proc-vars)))) + cst-proc-vars))) + (if (set-equal? cst-proc-vars cst-proc-vars*) + cst-proc-vars + (loop cst-proc-vars*))))) + (define (transitively-closed-free-variables vars) + (let ((tcfv-map + (map (lambda (var) (cons var (free-variables (var->val var)))) + vars))) + (let loop ((changed? #f)) + (for-each + (lambda (var-tcfv) + (let loop2 ((l (set->list (cdr var-tcfv))) (fv (cdr var-tcfv))) + (if (null? l) + (if (not (set-equal? fv (cdr var-tcfv))) + (begin (set-cdr! var-tcfv fv) (set! changed? #t))) + (let ((x (assq (car l) tcfv-map))) + (loop2 (cdr l) (if x (set-union fv (cdr x)) fv)))))) + tcfv-map) + (if changed? (loop #f) tcfv-map)))) + (let* ((tcfv-map + (transitively-closed-free-variables (liftable-proc-vars vars))) + (cst-proc-vars-list (map car tcfv-map)) + (cst-procs* (set-union (list->set cst-proc-vars-list) cst-procs))) + (define (var->tcfv var) (cdr (assq var tcfv-map))) + (define (order-vars vars) + (map car + (sort-list + (map (lambda (var) (assq var env)) vars) + (lambda (x y) + (if (= (cadr x) (cadr y)) + (< (cddr x) (cddr y)) + (< (cadr x) (cadr y))))))) + (define (lifted-vars var) + (order-vars (set->list (set-difference (var->tcfv var) cst-procs*)))) + (define (lift-app! var) + (let* ((val (var->val var)) (vars (lifted-vars var))) + (define (new-ref* var) + (new-ref (var-source var) (node-decl val) var)) + (if (not (null? vars)) + (for-each + (lambda (oper) + (let ((node (node-parent oper))) + (node-children-set! + node + (cons (app-oper node) + (append (map new-ref* vars) (app-args node)))))) + (set->list (var-refs var)))))) + (define (lift-prc! var) + (let* ((val (var->val var)) (vars (lifted-vars var))) + (if (not (null? vars)) + (let ((var-copies (map var-copy vars))) + (prc-parms-set! val (append var-copies (prc-parms val))) + (for-each (lambda (x) (var-bound-set! x val)) var-copies) + (node-fv-invalidate! val) + (prc-min-set! val (+ (prc-min val) (length vars))) + (ll-rename! val (pair-up vars var-copies)))))) + (for-each lift-app! cst-proc-vars-list) + (for-each lift-prc! cst-proc-vars-list) + (for-each (lambda (node) (ll! node cst-procs* env)) vals) + (ll! (prc-body proc) cst-procs* env)))) +(define (ll-rename! ptree var-map) + (cond ((ref? ptree) + (let* ((var (ref-var ptree)) (x (assq var var-map))) + (if x + (begin + (var-refs-set! var (set-remove (var-refs var) ptree)) + (var-refs-set! (cdr x) (set-adjoin (var-refs (cdr x)) ptree)) + (ref-var-set! ptree (cdr x)))))) + ((set? ptree) + (let* ((var (set-var ptree)) (x (assq var var-map))) + (if x + (begin + (var-sets-set! var (set-remove (var-sets var) ptree)) + (var-sets-set! (cdr x) (set-adjoin (var-sets (cdr x)) ptree)) + (set-var-set! ptree (cdr x))))))) + (node-fv-set! ptree #t) + (for-each (lambda (child) (ll-rename! child var-map)) (node-children ptree))) +(define (parse-tree->expression ptree) (se ptree '() (list 0))) +(define (se ptree env num) + (cond ((cst? ptree) (list quote-sym (cst-val ptree))) + ((ref? ptree) + (let ((x (assq (ref-var ptree) env))) + (if x (cdr x) (var-name (ref-var ptree))))) + ((set? ptree) + (list set!-sym + (let ((x (assq (set-var ptree) env))) + (if x (cdr x) (var-name (set-var ptree)))) + (se (set-val ptree) env num))) + ((def? ptree) + (list define-sym + (let ((x (assq (def-var ptree) env))) + (if x (cdr x) (var-name (def-var ptree)))) + (se (def-val ptree) env num))) + ((tst? ptree) + (list if-sym + (se (tst-pre ptree) env num) + (se (tst-con ptree) env num) + (se (tst-alt ptree) env num))) + ((conj? ptree) + (list and-sym + (se (conj-pre ptree) env num) + (se (conj-alt ptree) env num))) + ((disj? ptree) + (list or-sym + (se (disj-pre ptree) env num) + (se (disj-alt ptree) env num))) + ((prc? ptree) + (let ((new-env (se-rename (prc-parms ptree) env num))) + (list lambda-sym + (se-parameters + (prc-parms ptree) + (prc-rest ptree) + (prc-min ptree) + new-env) + (se (prc-body ptree) new-env num)))) + ((app? ptree) + (let ((oper (app-oper ptree)) (args (app-args ptree))) + (if (and (prc? oper) + (not (prc-rest oper)) + (= (length (prc-parms oper)) (length args))) + (let ((new-env (se-rename (prc-parms oper) env num))) + (list (if (set-empty? + (set-intersection + (list->set (prc-parms oper)) + (apply set-union (map free-variables args)))) + let-sym + letrec-sym) + (se-bindings (prc-parms oper) args new-env num) + (se (prc-body oper) new-env num))) + (map (lambda (x) (se x env num)) (cons oper args))))) + ((fut? ptree) (list future-sym (se (fut-val ptree) env num))) + (else (compiler-internal-error "se, unknown parse tree node type")))) +(define (se-parameters parms rest min env) + (define (se-parms parms rest n env) + (cond ((null? parms) '()) + ((and rest (null? (cdr parms))) (cdr (assq (car parms) env))) + (else + (let ((parm (cdr (assq (car parms) env)))) + (cons (if (> n 0) parm (list parm)) + (se-parms (cdr parms) rest (- n 1) env)))))) + (se-parms parms rest min env)) +(define (se-bindings vars vals env num) + (if (null? vars) + '() + (cons (list (cdr (assq (car vars) env)) (se (car vals) env num)) + (se-bindings (cdr vars) (cdr vals) env num)))) +(define (se-rename vars env num) + (define (rename vars) + (if (null? vars) + env + (cons (cons (car vars) + (string->canonical-symbol + (string-append + (symbol->string (var-name (car vars))) + "#" + (number->string (car num))))) + (rename (cdr vars))))) + (set-car! num (+ (car num) 1)) + (rename vars)) +(define *opnd-table* '()) +(define *opnd-table-alloc* '()) +(define opnd-table-size 10000) +(define (enter-opnd arg1 arg2) + (let loop ((i 0)) + (if (< i *opnd-table-alloc*) + (let ((x (vector-ref *opnd-table* i))) + (if (and (eqv? (car x) arg1) (eqv? (cdr x) arg2)) i (loop (+ i 1)))) + (if (< *opnd-table-alloc* opnd-table-size) + (begin + (set! *opnd-table-alloc* (+ *opnd-table-alloc* 1)) + (vector-set! *opnd-table* i (cons arg1 arg2)) + i) + (compiler-limitation-error + "program is too long [virtual machine operand table overflow]"))))) +(define (contains-opnd? opnd1 opnd2) + (cond ((eqv? opnd1 opnd2) #t) + ((clo? opnd2) (contains-opnd? opnd1 (clo-base opnd2))) + (else #f))) +(define (any-contains-opnd? opnd opnds) + (if (null? opnds) + #f + (or (contains-opnd? opnd (car opnds)) + (any-contains-opnd? opnd (cdr opnds))))) +(define (make-reg num) num) +(define (reg? x) (< x 10000)) +(define (reg-num x) (modulo x 10000)) +(define (make-stk num) (+ num 10000)) +(define (stk? x) (= (quotient x 10000) 1)) +(define (stk-num x) (modulo x 10000)) +(define (make-glo name) (+ (enter-opnd name #t) 30000)) +(define (glo? x) (= (quotient x 10000) 3)) +(define (glo-name x) (car (vector-ref *opnd-table* (modulo x 10000)))) +(define (make-clo base index) (+ (enter-opnd base index) 40000)) +(define (clo? x) (= (quotient x 10000) 4)) +(define (clo-base x) (car (vector-ref *opnd-table* (modulo x 10000)))) +(define (clo-index x) (cdr (vector-ref *opnd-table* (modulo x 10000)))) +(define (make-lbl num) (+ num 20000)) +(define (lbl? x) (= (quotient x 10000) 2)) +(define (lbl-num x) (modulo x 10000)) +(define label-limit 9999) +(define (make-obj val) (+ (enter-opnd val #f) 50000)) +(define (obj? x) (= (quotient x 10000) 5)) +(define (obj-val x) (car (vector-ref *opnd-table* (modulo x 10000)))) +(define (make-pcontext fs map) (vector fs map)) +(define (pcontext-fs x) (vector-ref x 0)) +(define (pcontext-map x) (vector-ref x 1)) +(define (make-frame size slots regs closed live) + (vector size slots regs closed live)) +(define (frame-size x) (vector-ref x 0)) +(define (frame-slots x) (vector-ref x 1)) +(define (frame-regs x) (vector-ref x 2)) +(define (frame-closed x) (vector-ref x 3)) +(define (frame-live x) (vector-ref x 4)) +(define (frame-eq? x y) (= (frame-size x) (frame-size y))) +(define (frame-truncate frame nb-slots) + (let ((fs (frame-size frame))) + (make-frame + nb-slots + (nth-after (frame-slots frame) (- fs nb-slots)) + (frame-regs frame) + (frame-closed frame) + (frame-live frame)))) +(define (frame-live? var frame) + (let ((live (frame-live frame))) + (if (eq? var closure-env-var) + (let ((closed (frame-closed frame))) + (if (or (set-member? var live) + (not (set-empty? + (set-intersection live (list->set closed))))) + closed + #f)) + (if (set-member? var live) var #f)))) +(define (frame-first-empty-slot frame) + (let loop ((i 1) (s (reverse (frame-slots frame)))) + (if (pair? s) + (if (frame-live? (car s) frame) (loop (+ i 1) (cdr s)) i) + i))) +(define (make-proc-obj + name + primitive? + code + call-pat + side-effects? + strict-pat + type) + (let ((proc-obj + (vector proc-obj-tag + name + primitive? + code + call-pat + #f + #f + #f + side-effects? + strict-pat + type))) + (proc-obj-specialize-set! proc-obj (lambda (decls) proc-obj)) + proc-obj)) +(define proc-obj-tag (list 'proc-obj)) +(define (proc-obj? x) + (and (vector? x) + (> (vector-length x) 0) + (eq? (vector-ref x 0) proc-obj-tag))) +(define (proc-obj-name obj) (vector-ref obj 1)) +(define (proc-obj-primitive? obj) (vector-ref obj 2)) +(define (proc-obj-code obj) (vector-ref obj 3)) +(define (proc-obj-call-pat obj) (vector-ref obj 4)) +(define (proc-obj-test obj) (vector-ref obj 5)) +(define (proc-obj-inlinable obj) (vector-ref obj 6)) +(define (proc-obj-specialize obj) (vector-ref obj 7)) +(define (proc-obj-side-effects? obj) (vector-ref obj 8)) +(define (proc-obj-strict-pat obj) (vector-ref obj 9)) +(define (proc-obj-type obj) (vector-ref obj 10)) +(define (proc-obj-code-set! obj x) (vector-set! obj 3 x)) +(define (proc-obj-test-set! obj x) (vector-set! obj 5 x)) +(define (proc-obj-inlinable-set! obj x) (vector-set! obj 6 x)) +(define (proc-obj-specialize-set! obj x) (vector-set! obj 7 x)) +(define (make-pattern min-args nb-parms rest?) + (let loop ((x (if rest? (- nb-parms 1) (list nb-parms))) + (y (if rest? (- nb-parms 1) nb-parms))) + (let ((z (- y 1))) (if (< z min-args) x (loop (cons z x) z))))) +(define (pattern-member? n pat) + (cond ((pair? pat) (if (= (car pat) n) #t (pattern-member? n (cdr pat)))) + ((null? pat) #f) + (else (<= pat n)))) +(define (type-name type) (if (pair? type) (car type) type)) +(define (type-pot-fut? type) (pair? type)) +(define (make-bbs) + (vector (make-counter 1 label-limit bbs-limit-err) (queue-empty) '())) +(define (bbs-limit-err) + (compiler-limitation-error "procedure is too long [too many labels]")) +(define (bbs-lbl-counter bbs) (vector-ref bbs 0)) +(define (bbs-lbl-counter-set! bbs cntr) (vector-set! bbs 0 cntr)) +(define (bbs-bb-queue bbs) (vector-ref bbs 1)) +(define (bbs-bb-queue-set! bbs bbq) (vector-set! bbs 1 bbq)) +(define (bbs-entry-lbl-num bbs) (vector-ref bbs 2)) +(define (bbs-entry-lbl-num-set! bbs lbl-num) (vector-set! bbs 2 lbl-num)) +(define (bbs-new-lbl! bbs) ((bbs-lbl-counter bbs))) +(define (lbl-num->bb lbl-num bbs) + (let loop ((bb-list (queue->list (bbs-bb-queue bbs)))) + (if (= (bb-lbl-num (car bb-list)) lbl-num) + (car bb-list) + (loop (cdr bb-list))))) +(define (make-bb label-instr bbs) + (let ((bb (vector label-instr (queue-empty) '() '() '()))) + (queue-put! (vector-ref bbs 1) bb) + bb)) +(define (bb-lbl-num bb) (label-lbl-num (vector-ref bb 0))) +(define (bb-label-type bb) (label-type (vector-ref bb 0))) +(define (bb-label-instr bb) (vector-ref bb 0)) +(define (bb-label-instr-set! bb l) (vector-set! bb 0 l)) +(define (bb-non-branch-instrs bb) (queue->list (vector-ref bb 1))) +(define (bb-non-branch-instrs-set! bb l) (vector-set! bb 1 (list->queue l))) +(define (bb-branch-instr bb) (vector-ref bb 2)) +(define (bb-branch-instr-set! bb b) (vector-set! bb 2 b)) +(define (bb-references bb) (vector-ref bb 3)) +(define (bb-references-set! bb l) (vector-set! bb 3 l)) +(define (bb-precedents bb) (vector-ref bb 4)) +(define (bb-precedents-set! bb l) (vector-set! bb 4 l)) +(define (bb-entry-frame-size bb) + (frame-size (gvm-instr-frame (bb-label-instr bb)))) +(define (bb-exit-frame-size bb) + (frame-size (gvm-instr-frame (bb-branch-instr bb)))) +(define (bb-slots-gained bb) + (- (bb-exit-frame-size bb) (bb-entry-frame-size bb))) +(define (bb-put-non-branch! bb gvm-instr) + (queue-put! (vector-ref bb 1) gvm-instr)) +(define (bb-put-branch! bb gvm-instr) (vector-set! bb 2 gvm-instr)) +(define (bb-add-reference! bb ref) + (if (not (memq ref (vector-ref bb 3))) + (vector-set! bb 3 (cons ref (vector-ref bb 3))))) +(define (bb-add-precedent! bb prec) + (if (not (memq prec (vector-ref bb 4))) + (vector-set! bb 4 (cons prec (vector-ref bb 4))))) +(define (bb-last-non-branch-instr bb) + (let ((non-branch-instrs (bb-non-branch-instrs bb))) + (if (null? non-branch-instrs) + (bb-label-instr bb) + (let loop ((l non-branch-instrs)) + (if (pair? (cdr l)) (loop (cdr l)) (car l)))))) +(define (gvm-instr-type gvm-instr) (vector-ref gvm-instr 0)) +(define (gvm-instr-frame gvm-instr) (vector-ref gvm-instr 1)) +(define (gvm-instr-comment gvm-instr) (vector-ref gvm-instr 2)) +(define (make-label-simple lbl-num frame comment) + (vector 'label frame comment lbl-num 'simple)) +(define (make-label-entry lbl-num nb-parms min rest? closed? frame comment) + (vector 'label frame comment lbl-num 'entry nb-parms min rest? closed?)) +(define (make-label-return lbl-num frame comment) + (vector 'label frame comment lbl-num 'return)) +(define (make-label-task-entry lbl-num frame comment) + (vector 'label frame comment lbl-num 'task-entry)) +(define (make-label-task-return lbl-num frame comment) + (vector 'label frame comment lbl-num 'task-return)) +(define (label-lbl-num gvm-instr) (vector-ref gvm-instr 3)) +(define (label-lbl-num-set! gvm-instr n) (vector-set! gvm-instr 3 n)) +(define (label-type gvm-instr) (vector-ref gvm-instr 4)) +(define (label-entry-nb-parms gvm-instr) (vector-ref gvm-instr 5)) +(define (label-entry-min gvm-instr) (vector-ref gvm-instr 6)) +(define (label-entry-rest? gvm-instr) (vector-ref gvm-instr 7)) +(define (label-entry-closed? gvm-instr) (vector-ref gvm-instr 8)) +(define (make-apply prim opnds loc frame comment) + (vector 'apply frame comment prim opnds loc)) +(define (apply-prim gvm-instr) (vector-ref gvm-instr 3)) +(define (apply-opnds gvm-instr) (vector-ref gvm-instr 4)) +(define (apply-loc gvm-instr) (vector-ref gvm-instr 5)) +(define (make-copy opnd loc frame comment) + (vector 'copy frame comment opnd loc)) +(define (copy-opnd gvm-instr) (vector-ref gvm-instr 3)) +(define (copy-loc gvm-instr) (vector-ref gvm-instr 4)) +(define (make-close parms frame comment) (vector 'close frame comment parms)) +(define (close-parms gvm-instr) (vector-ref gvm-instr 3)) +(define (make-closure-parms loc lbl opnds) (vector loc lbl opnds)) +(define (closure-parms-loc x) (vector-ref x 0)) +(define (closure-parms-lbl x) (vector-ref x 1)) +(define (closure-parms-opnds x) (vector-ref x 2)) +(define (make-ifjump test opnds true false poll? frame comment) + (vector 'ifjump frame comment test opnds true false poll?)) +(define (ifjump-test gvm-instr) (vector-ref gvm-instr 3)) +(define (ifjump-opnds gvm-instr) (vector-ref gvm-instr 4)) +(define (ifjump-true gvm-instr) (vector-ref gvm-instr 5)) +(define (ifjump-false gvm-instr) (vector-ref gvm-instr 6)) +(define (ifjump-poll? gvm-instr) (vector-ref gvm-instr 7)) +(define (make-jump opnd nb-args poll? frame comment) + (vector 'jump frame comment opnd nb-args poll?)) +(define (jump-opnd gvm-instr) (vector-ref gvm-instr 3)) +(define (jump-nb-args gvm-instr) (vector-ref gvm-instr 4)) +(define (jump-poll? gvm-instr) (vector-ref gvm-instr 5)) +(define (first-class-jump? gvm-instr) (jump-nb-args gvm-instr)) +(define (make-comment) (cons 'comment '())) +(define (comment-put! comment name val) + (set-cdr! comment (cons (cons name val) (cdr comment)))) +(define (comment-get comment name) + (and comment (let ((x (assq name (cdr comment)))) (if x (cdr x) #f)))) +(define (bbs-purify! bbs) + (let loop () + (bbs-remove-jump-cascades! bbs) + (bbs-remove-dead-code! bbs) + (let* ((changed1? (bbs-remove-common-code! bbs)) + (changed2? (bbs-remove-useless-jumps! bbs))) + (if (or changed1? changed2?) (loop) (bbs-order! bbs))))) +(define (bbs-remove-jump-cascades! bbs) + (define (empty-bb? bb) + (and (eq? (bb-label-type bb) 'simple) (null? (bb-non-branch-instrs bb)))) + (define (jump-to-non-entry-lbl? branch) + (and (eq? (gvm-instr-type branch) 'jump) + (not (first-class-jump? branch)) + (jump-lbl? branch))) + (define (jump-cascade-to lbl-num fs poll? seen thunk) + (if (memq lbl-num seen) + (thunk lbl-num fs poll?) + (let ((bb (lbl-num->bb lbl-num bbs))) + (if (and (empty-bb? bb) (<= (bb-slots-gained bb) 0)) + (let ((jump-lbl-num + (jump-to-non-entry-lbl? (bb-branch-instr bb)))) + (if jump-lbl-num + (jump-cascade-to + jump-lbl-num + (+ fs (bb-slots-gained bb)) + (or poll? (jump-poll? (bb-branch-instr bb))) + (cons lbl-num seen) + thunk) + (thunk lbl-num fs poll?))) + (thunk lbl-num fs poll?))))) + (define (equiv-lbl lbl-num seen) + (if (memq lbl-num seen) + lbl-num + (let ((bb (lbl-num->bb lbl-num bbs))) + (if (empty-bb? bb) + (let ((jump-lbl-num + (jump-to-non-entry-lbl? (bb-branch-instr bb)))) + (if (and jump-lbl-num + (not (jump-poll? (bb-branch-instr bb))) + (= (bb-slots-gained bb) 0)) + (equiv-lbl jump-lbl-num (cons lbl-num seen)) + lbl-num)) + lbl-num)))) + (define (remove-cascade! bb) + (let ((branch (bb-branch-instr bb))) + (case (gvm-instr-type branch) + ((ifjump) + (bb-put-branch! + bb + (make-ifjump + (ifjump-test branch) + (ifjump-opnds branch) + (equiv-lbl (ifjump-true branch) '()) + (equiv-lbl (ifjump-false branch) '()) + (ifjump-poll? branch) + (gvm-instr-frame branch) + (gvm-instr-comment branch)))) + ((jump) + (if (not (first-class-jump? branch)) + (let ((dest-lbl-num (jump-lbl? branch))) + (if dest-lbl-num + (jump-cascade-to + dest-lbl-num + (frame-size (gvm-instr-frame branch)) + (jump-poll? branch) + '() + (lambda (lbl-num fs poll?) + (let* ((dest-bb (lbl-num->bb lbl-num bbs)) + (last-branch (bb-branch-instr dest-bb))) + (if (and (empty-bb? dest-bb) + (or (not poll?) + put-poll-on-ifjump? + (not (eq? (gvm-instr-type last-branch) + 'ifjump)))) + (let* ((new-fs (+ fs (bb-slots-gained dest-bb))) + (new-frame + (frame-truncate + (gvm-instr-frame branch) + new-fs))) + (define (adjust-opnd opnd) + (cond ((stk? opnd) + (make-stk + (+ (- fs (bb-entry-frame-size dest-bb)) + (stk-num opnd)))) + ((clo? opnd) + (make-clo + (adjust-opnd (clo-base opnd)) + (clo-index opnd))) + (else opnd))) + (case (gvm-instr-type last-branch) + ((ifjump) + (bb-put-branch! + bb + (make-ifjump + (ifjump-test last-branch) + (map adjust-opnd (ifjump-opnds last-branch)) + (equiv-lbl (ifjump-true last-branch) '()) + (equiv-lbl (ifjump-false last-branch) '()) + (or poll? (ifjump-poll? last-branch)) + new-frame + (gvm-instr-comment last-branch)))) + ((jump) + (bb-put-branch! + bb + (make-jump + (adjust-opnd (jump-opnd last-branch)) + (jump-nb-args last-branch) + (or poll? (jump-poll? last-branch)) + new-frame + (gvm-instr-comment last-branch)))) + (else + (compiler-internal-error + "bbs-remove-jump-cascades!, unknown branch type")))) + (bb-put-branch! + bb + (make-jump + (make-lbl lbl-num) + (jump-nb-args branch) + (or poll? (jump-poll? branch)) + (frame-truncate (gvm-instr-frame branch) fs) + (gvm-instr-comment branch))))))))))) + (else + (compiler-internal-error + "bbs-remove-jump-cascades!, unknown branch type"))))) + (for-each remove-cascade! (queue->list (bbs-bb-queue bbs)))) +(define (jump-lbl? branch) + (let ((opnd (jump-opnd branch))) (if (lbl? opnd) (lbl-num opnd) #f))) +(define put-poll-on-ifjump? #f) +(set! put-poll-on-ifjump? #t) +(define (bbs-remove-dead-code! bbs) + (let ((new-bb-queue (queue-empty)) (scan-queue (queue-empty))) + (define (reachable ref bb) + (if bb (bb-add-reference! bb ref)) + (if (not (memq ref (queue->list new-bb-queue))) + (begin + (bb-references-set! ref '()) + (bb-precedents-set! ref '()) + (queue-put! new-bb-queue ref) + (queue-put! scan-queue ref)))) + (define (direct-jump to-bb from-bb) + (reachable to-bb from-bb) + (bb-add-precedent! to-bb from-bb)) + (define (scan-instr gvm-instr bb) + (define (scan-opnd gvm-opnd) + (cond ((lbl? gvm-opnd) + (reachable (lbl-num->bb (lbl-num gvm-opnd) bbs) bb)) + ((clo? gvm-opnd) (scan-opnd (clo-base gvm-opnd))))) + (case (gvm-instr-type gvm-instr) + ((label) '()) + ((apply) + (for-each scan-opnd (apply-opnds gvm-instr)) + (if (apply-loc gvm-instr) (scan-opnd (apply-loc gvm-instr)))) + ((copy) + (scan-opnd (copy-opnd gvm-instr)) + (scan-opnd (copy-loc gvm-instr))) + ((close) + (for-each + (lambda (parm) + (reachable (lbl-num->bb (closure-parms-lbl parm) bbs) bb) + (scan-opnd (closure-parms-loc parm)) + (for-each scan-opnd (closure-parms-opnds parm))) + (close-parms gvm-instr))) + ((ifjump) + (for-each scan-opnd (ifjump-opnds gvm-instr)) + (direct-jump (lbl-num->bb (ifjump-true gvm-instr) bbs) bb) + (direct-jump (lbl-num->bb (ifjump-false gvm-instr) bbs) bb)) + ((jump) + (let ((opnd (jump-opnd gvm-instr))) + (if (lbl? opnd) + (direct-jump (lbl-num->bb (lbl-num opnd) bbs) bb) + (scan-opnd (jump-opnd gvm-instr))))) + (else + (compiler-internal-error + "bbs-remove-dead-code!, unknown GVM instruction type")))) + (reachable (lbl-num->bb (bbs-entry-lbl-num bbs) bbs) #f) + (let loop () + (if (not (queue-empty? scan-queue)) + (let ((bb (queue-get! scan-queue))) + (begin + (scan-instr (bb-label-instr bb) bb) + (for-each + (lambda (gvm-instr) (scan-instr gvm-instr bb)) + (bb-non-branch-instrs bb)) + (scan-instr (bb-branch-instr bb) bb) + (loop))))) + (bbs-bb-queue-set! bbs new-bb-queue))) +(define (bbs-remove-useless-jumps! bbs) + (let ((changed? #f)) + (define (remove-useless-jump bb) + (let ((branch (bb-branch-instr bb))) + (if (and (eq? (gvm-instr-type branch) 'jump) + (not (first-class-jump? branch)) + (not (jump-poll? branch)) + (jump-lbl? branch)) + (let* ((dest-bb (lbl-num->bb (jump-lbl? branch) bbs)) + (frame1 (gvm-instr-frame (bb-last-non-branch-instr bb))) + (frame2 (gvm-instr-frame (bb-label-instr dest-bb)))) + (if (and (eq? (bb-label-type dest-bb) 'simple) + (frame-eq? frame1 frame2) + (= (length (bb-precedents dest-bb)) 1)) + (begin + (set! changed? #t) + (bb-non-branch-instrs-set! + bb + (append (bb-non-branch-instrs bb) + (bb-non-branch-instrs dest-bb) + '())) + (bb-branch-instr-set! bb (bb-branch-instr dest-bb)) + (remove-useless-jump bb))))))) + (for-each remove-useless-jump (queue->list (bbs-bb-queue bbs))) + changed?)) +(define (bbs-remove-common-code! bbs) + (let* ((bb-list (queue->list (bbs-bb-queue bbs))) + (n (length bb-list)) + (hash-table-length (cond ((< n 50) 43) ((< n 500) 403) (else 4003))) + (hash-table (make-vector hash-table-length '())) + (prim-table '()) + (block-map '()) + (changed? #f)) + (define (hash-prim prim) + (let ((n (length prim-table)) (i (pos-in-list prim prim-table))) + (if i + (- n i) + (begin (set! prim-table (cons prim prim-table)) (+ n 1))))) + (define (hash-opnds l) + (let loop ((l l) (n 0)) + (if (pair? l) + (loop (cdr l) + (let ((x (car l))) + (if (lbl? x) + n + (modulo (+ (* n 10000) x) hash-table-length)))) + n))) + (define (hash-bb bb) + (let ((branch (bb-branch-instr bb))) + (modulo (case (gvm-instr-type branch) + ((ifjump) + (+ (hash-opnds (ifjump-opnds branch)) + (* 10 (hash-prim (ifjump-test branch))) + (* 100 (frame-size (gvm-instr-frame branch))))) + ((jump) + (+ (hash-opnds (list (jump-opnd branch))) + (* 10 (or (jump-nb-args branch) -1)) + (* 100 (frame-size (gvm-instr-frame branch))))) + (else 0)) + hash-table-length))) + (define (replacement-lbl-num lbl) + (let ((x (assv lbl block-map))) (if x (cdr x) lbl))) + (define (fix-map! bb1 bb2) + (let loop ((l block-map)) + (if (pair? l) + (let ((x (car l))) + (if (= bb1 (cdr x)) (set-cdr! x bb2)) + (loop (cdr l)))))) + (define (enter-bb! bb) + (let ((h (hash-bb bb))) + (vector-set! hash-table h (add-bb bb (vector-ref hash-table h))))) + (define (add-bb bb l) + (if (pair? l) + (let ((bb* (car l))) + (set! block-map + (cons (cons (bb-lbl-num bb) (bb-lbl-num bb*)) block-map)) + (if (eqv-bb? bb bb*) + (begin + (fix-map! (bb-lbl-num bb) (bb-lbl-num bb*)) + (set! changed? #t) + l) + (begin + (set! block-map (cdr block-map)) + (if (eqv-gvm-instr? + (bb-branch-instr bb) + (bb-branch-instr bb*)) + (extract-common-tail + bb + bb* + (lambda (head head* tail) + (if (null? tail) + (cons bb* (add-bb bb (cdr l))) + (let* ((lbl (bbs-new-lbl! bbs)) + (branch (bb-branch-instr bb)) + (fs** (need-gvm-instrs tail branch)) + (frame (frame-truncate + (gvm-instr-frame + (if (null? head) + (bb-label-instr bb) + (car head))) + fs**)) + (bb** (make-bb (make-label-simple + lbl + frame + #f) + bbs))) + (bb-non-branch-instrs-set! bb** tail) + (bb-branch-instr-set! bb** branch) + (bb-non-branch-instrs-set! bb* (reverse head*)) + (bb-branch-instr-set! + bb* + (make-jump (make-lbl lbl) #f #f frame #f)) + (bb-non-branch-instrs-set! bb (reverse head)) + (bb-branch-instr-set! + bb + (make-jump (make-lbl lbl) #f #f frame #f)) + (set! changed? #t) + (cons bb (cons bb* (add-bb bb** (cdr l)))))))) + (cons bb* (add-bb bb (cdr l))))))) + (list bb))) + (define (extract-common-tail bb1 bb2 cont) + (let loop ((l1 (reverse (bb-non-branch-instrs bb1))) + (l2 (reverse (bb-non-branch-instrs bb2))) + (tail '())) + (if (and (pair? l1) (pair? l2)) + (let ((i1 (car l1)) (i2 (car l2))) + (if (eqv-gvm-instr? i1 i2) + (loop (cdr l1) (cdr l2) (cons i1 tail)) + (cont l1 l2 tail))) + (cont l1 l2 tail)))) + (define (eqv-bb? bb1 bb2) + (let ((bb1-non-branch (bb-non-branch-instrs bb1)) + (bb2-non-branch (bb-non-branch-instrs bb2))) + (and (= (length bb1-non-branch) (length bb2-non-branch)) + (eqv-gvm-instr? (bb-label-instr bb1) (bb-label-instr bb2)) + (eqv-gvm-instr? (bb-branch-instr bb1) (bb-branch-instr bb2)) + (eqv-list? eqv-gvm-instr? bb1-non-branch bb2-non-branch)))) + (define (eqv-list? pred? l1 l2) + (if (pair? l1) + (and (pair? l2) + (pred? (car l1) (car l2)) + (eqv-list? pred? (cdr l1) (cdr l2))) + (not (pair? l2)))) + (define (eqv-lbl-num? lbl1 lbl2) + (= (replacement-lbl-num lbl1) (replacement-lbl-num lbl2))) + (define (eqv-gvm-opnd? opnd1 opnd2) + (if (not opnd1) + (not opnd2) + (and opnd2 + (cond ((lbl? opnd1) + (and (lbl? opnd2) + (eqv-lbl-num? (lbl-num opnd1) (lbl-num opnd2)))) + ((clo? opnd1) + (and (clo? opnd2) + (= (clo-index opnd1) (clo-index opnd2)) + (eqv-gvm-opnd? (clo-base opnd1) (clo-base opnd2)))) + (else (eqv? opnd1 opnd2)))))) + (define (eqv-gvm-instr? instr1 instr2) + (define (eqv-closure-parms? p1 p2) + (and (eqv-gvm-opnd? (closure-parms-loc p1) (closure-parms-loc p2)) + (eqv-lbl-num? (closure-parms-lbl p1) (closure-parms-lbl p2)) + (eqv-list? + eqv-gvm-opnd? + (closure-parms-opnds p1) + (closure-parms-opnds p2)))) + (let ((type1 (gvm-instr-type instr1)) (type2 (gvm-instr-type instr2))) + (and (eq? type1 type2) + (frame-eq? (gvm-instr-frame instr1) (gvm-instr-frame instr2)) + (case type1 + ((label) + (let ((ltype1 (label-type instr1)) + (ltype2 (label-type instr2))) + (and (eq? ltype1 ltype2) + (case ltype1 + ((simple return task-entry task-return) #t) + ((entry) + (and (= (label-entry-min instr1) + (label-entry-min instr2)) + (= (label-entry-nb-parms instr1) + (label-entry-nb-parms instr2)) + (eq? (label-entry-rest? instr1) + (label-entry-rest? instr2)) + (eq? (label-entry-closed? instr1) + (label-entry-closed? instr2)))) + (else + (compiler-internal-error + "eqv-gvm-instr?, unknown label type")))))) + ((apply) + (and (eq? (apply-prim instr1) (apply-prim instr2)) + (eqv-list? + eqv-gvm-opnd? + (apply-opnds instr1) + (apply-opnds instr2)) + (eqv-gvm-opnd? (apply-loc instr1) (apply-loc instr2)))) + ((copy) + (and (eqv-gvm-opnd? (copy-opnd instr1) (copy-opnd instr2)) + (eqv-gvm-opnd? (copy-loc instr1) (copy-loc instr2)))) + ((close) + (eqv-list? + eqv-closure-parms? + (close-parms instr1) + (close-parms instr2))) + ((ifjump) + (and (eq? (ifjump-test instr1) (ifjump-test instr2)) + (eqv-list? + eqv-gvm-opnd? + (ifjump-opnds instr1) + (ifjump-opnds instr2)) + (eqv-lbl-num? (ifjump-true instr1) (ifjump-true instr2)) + (eqv-lbl-num? (ifjump-false instr1) (ifjump-false instr2)) + (eq? (ifjump-poll? instr1) (ifjump-poll? instr2)))) + ((jump) + (and (eqv-gvm-opnd? (jump-opnd instr1) (jump-opnd instr2)) + (eqv? (jump-nb-args instr1) (jump-nb-args instr2)) + (eq? (jump-poll? instr1) (jump-poll? instr2)))) + (else + (compiler-internal-error + "eqv-gvm-instr?, unknown 'gvm-instr':" + instr1)))))) + (define (update-bb! bb) (replace-label-references! bb replacement-lbl-num)) + (for-each enter-bb! bb-list) + (bbs-entry-lbl-num-set! bbs (replacement-lbl-num (bbs-entry-lbl-num bbs))) + (let loop ((i 0) (result '())) + (if (< i hash-table-length) + (let ((bb-kept (vector-ref hash-table i))) + (for-each update-bb! bb-kept) + (loop (+ i 1) (append bb-kept result))) + (bbs-bb-queue-set! bbs (list->queue result)))) + changed?)) +(define (replace-label-references! bb replacement-lbl-num) + (define (update-gvm-opnd opnd) + (if opnd + (cond ((lbl? opnd) (make-lbl (replacement-lbl-num (lbl-num opnd)))) + ((clo? opnd) + (make-clo (update-gvm-opnd (clo-base opnd)) (clo-index opnd))) + (else opnd)) + opnd)) + (define (update-gvm-instr instr) + (define (update-closure-parms p) + (make-closure-parms + (update-gvm-opnd (closure-parms-loc p)) + (replacement-lbl-num (closure-parms-lbl p)) + (map update-gvm-opnd (closure-parms-opnds p)))) + (case (gvm-instr-type instr) + ((apply) + (make-apply + (apply-prim instr) + (map update-gvm-opnd (apply-opnds instr)) + (update-gvm-opnd (apply-loc instr)) + (gvm-instr-frame instr) + (gvm-instr-comment instr))) + ((copy) + (make-copy + (update-gvm-opnd (copy-opnd instr)) + (update-gvm-opnd (copy-loc instr)) + (gvm-instr-frame instr) + (gvm-instr-comment instr))) + ((close) + (make-close + (map update-closure-parms (close-parms instr)) + (gvm-instr-frame instr) + (gvm-instr-comment instr))) + ((ifjump) + (make-ifjump + (ifjump-test instr) + (map update-gvm-opnd (ifjump-opnds instr)) + (replacement-lbl-num (ifjump-true instr)) + (replacement-lbl-num (ifjump-false instr)) + (ifjump-poll? instr) + (gvm-instr-frame instr) + (gvm-instr-comment instr))) + ((jump) + (make-jump + (update-gvm-opnd (jump-opnd instr)) + (jump-nb-args instr) + (jump-poll? instr) + (gvm-instr-frame instr) + (gvm-instr-comment instr))) + (else + (compiler-internal-error "update-gvm-instr, unknown 'instr':" instr)))) + (bb-non-branch-instrs-set! + bb + (map update-gvm-instr (bb-non-branch-instrs bb))) + (bb-branch-instr-set! bb (update-gvm-instr (bb-branch-instr bb)))) +(define (bbs-order! bbs) + (let ((new-bb-queue (queue-empty)) + (left-to-schedule (queue->list (bbs-bb-queue bbs)))) + (define (remove x l) + (if (eq? (car l) x) (cdr l) (cons (car l) (remove x (cdr l))))) + (define (remove-bb! bb) + (set! left-to-schedule (remove bb left-to-schedule)) + bb) + (define (prec-bb bb) + (let loop ((l (bb-precedents bb)) (best #f) (best-fs #f)) + (if (null? l) + best + (let* ((x (car l)) (x-fs (bb-exit-frame-size x))) + (if (and (memq x left-to-schedule) + (or (not best) (< x-fs best-fs))) + (loop (cdr l) x x-fs) + (loop (cdr l) best best-fs)))))) + (define (succ-bb bb) + (define (branches-to-lbl? bb) + (let ((branch (bb-branch-instr bb))) + (case (gvm-instr-type branch) + ((ifjump) #t) + ((jump) (lbl? (jump-opnd branch))) + (else + (compiler-internal-error "bbs-order!, unknown branch type"))))) + (define (best-succ bb1 bb2) + (if (branches-to-lbl? bb1) + bb1 + (if (branches-to-lbl? bb2) + bb2 + (if (< (bb-exit-frame-size bb1) (bb-exit-frame-size bb2)) + bb2 + bb1)))) + (let ((branch (bb-branch-instr bb))) + (case (gvm-instr-type branch) + ((ifjump) + (let* ((true-bb (lbl-num->bb (ifjump-true branch) bbs)) + (true-bb* (and (memq true-bb left-to-schedule) true-bb)) + (false-bb (lbl-num->bb (ifjump-false branch) bbs)) + (false-bb* (and (memq false-bb left-to-schedule) false-bb))) + (if (and true-bb* false-bb*) + (best-succ true-bb* false-bb*) + (or true-bb* false-bb*)))) + ((jump) + (let ((opnd (jump-opnd branch))) + (and (lbl? opnd) + (let ((bb (lbl-num->bb (lbl-num opnd) bbs))) + (and (memq bb left-to-schedule) bb))))) + (else (compiler-internal-error "bbs-order!, unknown branch type"))))) + (define (schedule-from bb) + (queue-put! new-bb-queue bb) + (let ((x (succ-bb bb))) + (if x + (begin + (schedule-around (remove-bb! x)) + (let ((y (succ-bb bb))) + (if y (schedule-around (remove-bb! y))))))) + (schedule-refs bb)) + (define (schedule-around bb) + (let ((x (prec-bb bb))) + (if x + (let ((bb-list (schedule-back (remove-bb! x) '()))) + (queue-put! new-bb-queue x) + (schedule-forw bb) + (for-each schedule-refs bb-list)) + (schedule-from bb)))) + (define (schedule-back bb bb-list) + (let ((bb-list* (cons bb bb-list)) (x (prec-bb bb))) + (if x + (let ((bb-list (schedule-back (remove-bb! x) bb-list*))) + (queue-put! new-bb-queue x) + bb-list) + bb-list*))) + (define (schedule-forw bb) + (queue-put! new-bb-queue bb) + (let ((x (succ-bb bb))) + (if x + (begin + (schedule-forw (remove-bb! x)) + (let ((y (succ-bb bb))) + (if y (schedule-around (remove-bb! y))))))) + (schedule-refs bb)) + (define (schedule-refs bb) + (for-each + (lambda (x) + (if (memq x left-to-schedule) (schedule-around (remove-bb! x)))) + (bb-references bb))) + (schedule-from (remove-bb! (lbl-num->bb (bbs-entry-lbl-num bbs) bbs))) + (bbs-bb-queue-set! bbs new-bb-queue) + (let ((bb-list (queue->list new-bb-queue))) + (let loop ((l bb-list) (i 1) (lbl-map '())) + (if (pair? l) + (let* ((label-instr (bb-label-instr (car l))) + (old-lbl-num (label-lbl-num label-instr))) + (label-lbl-num-set! label-instr i) + (loop (cdr l) (+ i 1) (cons (cons old-lbl-num i) lbl-map))) + (let () + (define (replacement-lbl-num x) (cdr (assv x lbl-map))) + (define (update-bb! bb) + (replace-label-references! bb replacement-lbl-num)) + (for-each update-bb! bb-list) + (bbs-lbl-counter-set! + bbs + (make-counter + (* (+ 1 (quotient (bbs-new-lbl! bbs) 1000)) 1000) + label-limit + bbs-limit-err)))))))) +(define (make-code bb gvm-instr sn) (vector bb gvm-instr sn)) +(define (code-bb code) (vector-ref code 0)) +(define (code-gvm-instr code) (vector-ref code 1)) +(define (code-slots-needed code) (vector-ref code 2)) +(define (code-slots-needed-set! code n) (vector-set! code 2 n)) +(define (bbs->code-list bbs) + (let ((code-list (linearize bbs))) + (setup-slots-needed! code-list) + code-list)) +(define (linearize bbs) + (let ((code-queue (queue-empty))) + (define (put-bb bb) + (define (put-instr gvm-instr) + (queue-put! code-queue (make-code bb gvm-instr #f))) + (put-instr (bb-label-instr bb)) + (for-each put-instr (bb-non-branch-instrs bb)) + (put-instr (bb-branch-instr bb))) + (for-each put-bb (queue->list (bbs-bb-queue bbs))) + (queue->list code-queue))) +(define (setup-slots-needed! code-list) + (if (null? code-list) + #f + (let* ((code (car code-list)) + (gvm-instr (code-gvm-instr code)) + (sn-rest (setup-slots-needed! (cdr code-list)))) + (case (gvm-instr-type gvm-instr) + ((label) + (if (> sn-rest (frame-size (gvm-instr-frame gvm-instr))) + (compiler-internal-error + "setup-slots-needed!, incoherent slots needed for LABEL")) + (code-slots-needed-set! code sn-rest) + #f) + ((ifjump jump) + (let ((sn (frame-size (gvm-instr-frame gvm-instr)))) + (code-slots-needed-set! code sn) + (need-gvm-instr gvm-instr sn))) + (else + (code-slots-needed-set! code sn-rest) + (need-gvm-instr gvm-instr sn-rest)))))) +(define (need-gvm-instrs non-branch branch) + (if (pair? non-branch) + (need-gvm-instr + (car non-branch) + (need-gvm-instrs (cdr non-branch) branch)) + (need-gvm-instr branch (frame-size (gvm-instr-frame branch))))) +(define (need-gvm-instr gvm-instr sn-rest) + (case (gvm-instr-type gvm-instr) + ((label) sn-rest) + ((apply) + (let ((loc (apply-loc gvm-instr))) + (need-gvm-opnds + (apply-opnds gvm-instr) + (need-gvm-loc-opnd loc (need-gvm-loc loc sn-rest))))) + ((copy) + (let ((loc (copy-loc gvm-instr))) + (need-gvm-opnd + (copy-opnd gvm-instr) + (need-gvm-loc-opnd loc (need-gvm-loc loc sn-rest))))) + ((close) + (let ((parms (close-parms gvm-instr))) + (define (need-parms-opnds p) + (if (null? p) + sn-rest + (need-gvm-opnds + (closure-parms-opnds (car p)) + (need-parms-opnds (cdr p))))) + (define (need-parms-loc p) + (if (null? p) + (need-parms-opnds parms) + (let ((loc (closure-parms-loc (car p)))) + (need-gvm-loc-opnd + loc + (need-gvm-loc loc (need-parms-loc (cdr p))))))) + (need-parms-loc parms))) + ((ifjump) (need-gvm-opnds (ifjump-opnds gvm-instr) sn-rest)) + ((jump) (need-gvm-opnd (jump-opnd gvm-instr) sn-rest)) + (else + (compiler-internal-error + "need-gvm-instr, unknown 'gvm-instr':" + gvm-instr)))) +(define (need-gvm-loc loc sn-rest) + (if (and loc (stk? loc) (>= (stk-num loc) sn-rest)) + (- (stk-num loc) 1) + sn-rest)) +(define (need-gvm-loc-opnd gvm-loc slots-needed) + (if (and gvm-loc (clo? gvm-loc)) + (need-gvm-opnd (clo-base gvm-loc) slots-needed) + slots-needed)) +(define (need-gvm-opnd gvm-opnd slots-needed) + (cond ((stk? gvm-opnd) (max (stk-num gvm-opnd) slots-needed)) + ((clo? gvm-opnd) (need-gvm-opnd (clo-base gvm-opnd) slots-needed)) + (else slots-needed))) +(define (need-gvm-opnds gvm-opnds slots-needed) + (if (null? gvm-opnds) + slots-needed + (need-gvm-opnd + (car gvm-opnds) + (need-gvm-opnds (cdr gvm-opnds) slots-needed)))) +(define (write-bb bb port) + (write-gvm-instr (bb-label-instr bb) port) + (display " [precedents=" port) + (write (map bb-lbl-num (bb-precedents bb)) port) + (display "]" port) + (newline port) + (for-each + (lambda (x) (write-gvm-instr x port) (newline port)) + (bb-non-branch-instrs bb)) + (write-gvm-instr (bb-branch-instr bb) port)) +(define (write-bbs bbs port) + (for-each + (lambda (bb) + (if (= (bb-lbl-num bb) (bbs-entry-lbl-num bbs)) + (begin (display "**** Entry block:" port) (newline port))) + (write-bb bb port) + (newline port)) + (queue->list (bbs-bb-queue bbs)))) +(define (virtual.dump proc port) + (let ((proc-seen (queue-empty)) (proc-left (queue-empty))) + (define (scan-opnd gvm-opnd) + (cond ((obj? gvm-opnd) + (let ((val (obj-val gvm-opnd))) + (if (and (proc-obj? val) + (proc-obj-code val) + (not (memq val (queue->list proc-seen)))) + (begin + (queue-put! proc-seen val) + (queue-put! proc-left val))))) + ((clo? gvm-opnd) (scan-opnd (clo-base gvm-opnd))))) + (define (dump-proc p) + (define (scan-code code) + (let ((gvm-instr (code-gvm-instr code))) + (write-gvm-instr gvm-instr port) + (newline port) + (case (gvm-instr-type gvm-instr) + ((apply) + (for-each scan-opnd (apply-opnds gvm-instr)) + (if (apply-loc gvm-instr) (scan-opnd (apply-loc gvm-instr)))) + ((copy) + (scan-opnd (copy-opnd gvm-instr)) + (scan-opnd (copy-loc gvm-instr))) + ((close) + (for-each + (lambda (parms) + (scan-opnd (closure-parms-loc parms)) + (for-each scan-opnd (closure-parms-opnds parms))) + (close-parms gvm-instr))) + ((ifjump) (for-each scan-opnd (ifjump-opnds gvm-instr))) + ((jump) (scan-opnd (jump-opnd gvm-instr))) + (else '())))) + (if (proc-obj-primitive? p) + (display "**** #[primitive " port) + (display "**** #[procedure " port)) + (display (proc-obj-name p) port) + (display "] =" port) + (newline port) + (let loop ((l (bbs->code-list (proc-obj-code p))) + (prev-filename "") + (prev-line 0)) + (if (pair? l) + (let* ((code (car l)) + (instr (code-gvm-instr code)) + (src (comment-get (gvm-instr-comment instr) 'source)) + (loc (and src (source-locat src))) + (filename + (if (and loc (eq? (vector-ref loc 0) 'file)) + (vector-ref loc 1) + prev-filename)) + (line (if (and loc (eq? (vector-ref loc 0) 'file)) + (vector-ref loc 3) + prev-line))) + (if (or (not (string=? filename prev-filename)) + (not (= line prev-line))) + (begin + (display "#line " port) + (display line port) + (if (not (string=? filename prev-filename)) + (begin (display " " port) (write filename port))) + (newline port))) + (scan-code code) + (loop (cdr l) filename line)) + (newline port)))) + (scan-opnd (make-obj proc)) + (let loop () + (if (not (queue-empty? proc-left)) + (begin (dump-proc (queue-get! proc-left)) (loop)))))) +(define (write-gvm-instr gvm-instr port) + (define (write-closure-parms parms) + (display " " port) + (let ((len (+ 1 (write-gvm-opnd (closure-parms-loc parms) port)))) + (display " = (" port) + (let ((len (+ len (+ 4 (write-gvm-lbl (closure-parms-lbl parms) port))))) + (+ len + (write-terminated-opnd-list (closure-parms-opnds parms) port))))) + (define (write-terminated-opnd-list l port) + (let loop ((l l) (len 0)) + (if (pair? l) + (let ((opnd (car l))) + (display " " port) + (loop (cdr l) (+ len (+ 1 (write-gvm-opnd opnd port))))) + (begin (display ")" port) (+ len 1))))) + (define (write-param-pattern gvm-instr port) + (let ((len (if (not (= (label-entry-min gvm-instr) + (label-entry-nb-parms gvm-instr))) + (let ((len (write-returning-len + (label-entry-min gvm-instr) + port))) + (display "-" port) + (+ len 1)) + 0))) + (let ((len (+ len + (write-returning-len + (label-entry-nb-parms gvm-instr) + port)))) + (if (label-entry-rest? gvm-instr) + (begin (display "+" port) (+ len 1)) + len)))) + (define (write-prim-applic prim opnds port) + (display "(" port) + (let ((len (+ 1 (display-returning-len (proc-obj-name prim) port)))) + (+ len (write-terminated-opnd-list opnds port)))) + (define (write-instr gvm-instr) + (case (gvm-instr-type gvm-instr) + ((label) + (let ((len (write-gvm-lbl (label-lbl-num gvm-instr) port))) + (display " " port) + (let ((len (+ len + (+ 1 + (write-returning-len + (frame-size (gvm-instr-frame gvm-instr)) + port))))) + (case (label-type gvm-instr) + ((simple) len) + ((entry) + (if (label-entry-closed? gvm-instr) + (begin + (display " closure-entry-point " port) + (+ len (+ 21 (write-param-pattern gvm-instr port)))) + (begin + (display " entry-point " port) + (+ len (+ 13 (write-param-pattern gvm-instr port)))))) + ((return) (display " return-point" port) (+ len 13)) + ((task-entry) (display " task-entry-point" port) (+ len 17)) + ((task-return) (display " task-return-point" port) (+ len 18)) + (else + (compiler-internal-error + "write-gvm-instr, unknown label type")))))) + ((apply) + (display " " port) + (let ((len (+ 2 + (if (apply-loc gvm-instr) + (let ((len (write-gvm-opnd + (apply-loc gvm-instr) + port))) + (display " = " port) + (+ len 3)) + 0)))) + (+ len + (write-prim-applic + (apply-prim gvm-instr) + (apply-opnds gvm-instr) + port)))) + ((copy) + (display " " port) + (let ((len (+ 2 (write-gvm-opnd (copy-loc gvm-instr) port)))) + (display " = " port) + (+ len (+ 3 (write-gvm-opnd (copy-opnd gvm-instr) port))))) + ((close) + (display " close" port) + (let ((len (+ 7 (write-closure-parms (car (close-parms gvm-instr)))))) + (let loop ((l (cdr (close-parms gvm-instr))) (len len)) + (if (pair? l) + (let ((x (car l))) + (display "," port) + (loop (cdr l) (+ len (+ 1 (write-closure-parms x))))) + len)))) + ((ifjump) + (display " if " port) + (let ((len (+ 5 + (write-prim-applic + (ifjump-test gvm-instr) + (ifjump-opnds gvm-instr) + port)))) + (let ((len (+ len + (if (ifjump-poll? gvm-instr) + (begin (display " jump* " port) 7) + (begin (display " jump " port) 6))))) + (let ((len (+ len + (write-returning-len + (frame-size (gvm-instr-frame gvm-instr)) + port)))) + (display " " port) + (let ((len (+ len + (+ 1 + (write-gvm-lbl (ifjump-true gvm-instr) port))))) + (display " else " port) + (+ len (+ 6 (write-gvm-lbl (ifjump-false gvm-instr) port)))))))) + ((jump) + (display " " port) + (let ((len (+ 2 + (if (jump-poll? gvm-instr) + (begin (display "jump* " port) 6) + (begin (display "jump " port) 5))))) + (let ((len (+ len + (write-returning-len + (frame-size (gvm-instr-frame gvm-instr)) + port)))) + (display " " port) + (let ((len (+ len + (+ 1 (write-gvm-opnd (jump-opnd gvm-instr) port))))) + (+ len + (if (jump-nb-args gvm-instr) + (begin + (display " " port) + (+ 1 + (write-returning-len (jump-nb-args gvm-instr) port))) + 0)))))) + (else + (compiler-internal-error + "write-gvm-instr, unknown 'gvm-instr':" + gvm-instr)))) + (define (spaces n) + (if (> n 0) + (if (> n 7) + (begin (display " " port) (spaces (- n 8))) + (begin (display " " port) (spaces (- n 1)))))) + (let ((len (write-instr gvm-instr))) + (spaces (- 40 len)) + (display " " port) + (write-frame (gvm-instr-frame gvm-instr) port)) + (let ((x (gvm-instr-comment gvm-instr))) + (if x + (let ((y (comment-get x 'text))) + (if y (begin (display " ; " port) (display y port))))))) +(define (write-frame frame port) + (define (write-var var opnd sep) + (display sep port) + (write-gvm-opnd opnd port) + (if var + (begin + (display "=" port) + (cond ((eq? var closure-env-var) + (write (map (lambda (var) (var-name var)) + (frame-closed frame)) + port)) + ((eq? var ret-var) (display "#" port)) + ((temp-var? var) (display "." port)) + (else (write (var-name var) port)))))) + (define (live? var) + (let ((live (frame-live frame))) + (or (set-member? var live) + (and (eq? var closure-env-var) + (not (set-empty? + (set-intersection + live + (list->set (frame-closed frame))))))))) + (let loop1 ((i 1) (l (reverse (frame-slots frame))) (sep "; ")) + (if (pair? l) + (let ((var (car l))) + (write-var (if (live? var) var #f) (make-stk i) sep) + (loop1 (+ i 1) (cdr l) " ")) + (let loop2 ((i 0) (l (frame-regs frame)) (sep sep)) + (if (pair? l) + (let ((var (car l))) + (if (live? var) + (begin + (write-var var (make-reg i) sep) + (loop2 (+ i 1) (cdr l) " ")) + (loop2 (+ i 1) (cdr l) sep)))))))) +(define (write-gvm-opnd gvm-opnd port) + (define (write-opnd) + (cond ((reg? gvm-opnd) + (display "+" port) + (+ 1 (write-returning-len (reg-num gvm-opnd) port))) + ((stk? gvm-opnd) + (display "-" port) + (+ 1 (write-returning-len (stk-num gvm-opnd) port))) + ((glo? gvm-opnd) (write-returning-len (glo-name gvm-opnd) port)) + ((clo? gvm-opnd) + (let ((len (write-gvm-opnd (clo-base gvm-opnd) port))) + (display "(" port) + (let ((len (+ len + (+ 1 + (write-returning-len + (clo-index gvm-opnd) + port))))) + (display ")" port) + (+ len 1)))) + ((lbl? gvm-opnd) (write-gvm-lbl (lbl-num gvm-opnd) port)) + ((obj? gvm-opnd) + (display "'" port) + (+ (write-gvm-obj (obj-val gvm-opnd) port) 1)) + (else + (compiler-internal-error + "write-gvm-opnd, unknown 'gvm-opnd':" + gvm-opnd)))) + (write-opnd)) +(define (write-gvm-lbl lbl port) + (display "#" port) + (+ (write-returning-len lbl port) 1)) +(define (write-gvm-obj val port) + (cond ((false-object? val) (display "#f" port) 2) + ((undef-object? val) (display "#[undefined]" port) 12) + ((proc-obj? val) + (if (proc-obj-primitive? val) + (display "#[primitive " port) + (display "#[procedure " port)) + (let ((len (display-returning-len (proc-obj-name val) port))) + (display "]" port) + (+ len 13))) + (else (write-returning-len val port)))) +(define (virtual.begin!) + (set! *opnd-table* (make-vector opnd-table-size)) + (set! *opnd-table-alloc* 0) + '()) +(define (virtual.end!) (set! *opnd-table* '()) '()) +(define (make-target version name) + (define current-target-version 4) + (if (not (= version current-target-version)) + (compiler-internal-error + "make-target, version of target package is not current" + name)) + (let ((x (make-vector 11))) (vector-set! x 1 name) x)) +(define (target-name x) (vector-ref x 1)) +(define (target-begin! x) (vector-ref x 2)) +(define (target-begin!-set! x y) (vector-set! x 2 y)) +(define (target-end! x) (vector-ref x 3)) +(define (target-end!-set! x y) (vector-set! x 3 y)) +(define (target-dump x) (vector-ref x 4)) +(define (target-dump-set! x y) (vector-set! x 4 y)) +(define (target-nb-regs x) (vector-ref x 5)) +(define (target-nb-regs-set! x y) (vector-set! x 5 y)) +(define (target-prim-info x) (vector-ref x 6)) +(define (target-prim-info-set! x y) (vector-set! x 6 y)) +(define (target-label-info x) (vector-ref x 7)) +(define (target-label-info-set! x y) (vector-set! x 7 y)) +(define (target-jump-info x) (vector-ref x 8)) +(define (target-jump-info-set! x y) (vector-set! x 8 y)) +(define (target-proc-result x) (vector-ref x 9)) +(define (target-proc-result-set! x y) (vector-set! x 9 y)) +(define (target-task-return x) (vector-ref x 10)) +(define (target-task-return-set! x y) (vector-set! x 10 y)) +(define targets-loaded '()) +(define (get-target name) + (let ((x (assq name targets-loaded))) + (if x (cdr x) (compiler-error "Target package is not available" name)))) +(define (put-target targ) + (let* ((name (target-name targ)) (x (assq name targets-loaded))) + (if x + (set-cdr! x targ) + (set! targets-loaded (cons (cons name targ) targets-loaded))) + '())) +(define (default-target) + (if (null? targets-loaded) + (compiler-error "No target package is available") + (car (car targets-loaded)))) +(define (select-target! name info-port) + (set! target (get-target name)) + ((target-begin! target) info-port) + (set! target.dump (target-dump target)) + (set! target.nb-regs (target-nb-regs target)) + (set! target.prim-info (target-prim-info target)) + (set! target.label-info (target-label-info target)) + (set! target.jump-info (target-jump-info target)) + (set! target.proc-result (target-proc-result target)) + (set! target.task-return (target-task-return target)) + (set! **not-proc-obj (target.prim-info **not-sym)) + '()) +(define (unselect-target!) ((target-end! target)) '()) +(define target '()) +(define target.dump '()) +(define target.nb-regs '()) +(define target.prim-info '()) +(define target.label-info '()) +(define target.jump-info '()) +(define target.proc-result '()) +(define target.task-return '()) +(define **not-proc-obj '()) +(define (target.specialized-prim-info* name decl) + (let ((x (target.prim-info* name decl))) + (and x ((proc-obj-specialize x) decl)))) +(define (target.prim-info* name decl) + (and (if (standard-procedure name decl) + (standard-binding? name decl) + (extended-binding? name decl)) + (target.prim-info name))) +(define generic-sym (string->canonical-symbol "GENERIC")) +(define fixnum-sym (string->canonical-symbol "FIXNUM")) +(define flonum-sym (string->canonical-symbol "FLONUM")) +(define-namable-decl generic-sym 'arith) +(define-namable-decl fixnum-sym 'arith) +(define-namable-decl flonum-sym 'arith) +(define (arith-implementation name decls) + (declaration-value 'arith name generic-sym decls)) +(define (cf source target-name . opts) + (let* ((dest (file-root source)) + (module-name (file-name dest)) + (info-port (if (memq 'verbose opts) (current-output-port) #f)) + (result (compile-program + (list **include-sym source) + (if target-name target-name (default-target)) + opts + module-name + dest + info-port))) + (if (and info-port (not (eq? info-port (current-output-port)))) + (close-output-port info-port)) + result)) +(define (ce source target-name . opts) + (let* ((dest "program") + (module-name "program") + (info-port (if (memq 'verbose opts) (current-output-port) #f)) + (result (compile-program + source + (if target-name target-name (default-target)) + opts + module-name + dest + info-port))) + (if (and info-port (not (eq? info-port (current-output-port)))) + (close-output-port info-port)) + result)) +(define wrap-program #f) +(set! wrap-program (lambda (program) program)) +(define (compile-program program target-name opts module-name dest info-port) + (define (compiler-body) + (if (not (valid-module-name? module-name)) + (compiler-error + "Invalid characters in file name (must be a symbol with no \"#\")") + (begin + (ptree.begin! info-port) + (virtual.begin!) + (select-target! target-name info-port) + (parse-program + (list (expression->source (wrap-program program) #f)) + (make-global-environment) + module-name + (lambda (lst env c-intf) + (let ((parsed-program + (map (lambda (x) (normalize-parse-tree (car x) (cdr x))) + lst))) + (if (memq 'expansion opts) + (let ((port (current-output-port))) + (display "Expansion:" port) + (newline port) + (let loop ((l parsed-program)) + (if (pair? l) + (let ((ptree (car l))) + (pp-expression + (parse-tree->expression ptree) + port) + (loop (cdr l))))) + (newline port))) + (let ((module-init-proc + (compile-parsed-program + module-name + parsed-program + env + c-intf + info-port))) + (if (memq 'report opts) (generate-report env)) + (if (memq 'gvm opts) + (let ((gvm-port + (open-output-file (string-append dest ".gvm")))) + (virtual.dump module-init-proc gvm-port) + (close-output-port gvm-port))) + (target.dump module-init-proc dest c-intf opts) + (dump-c-intf module-init-proc dest c-intf))))) + (unselect-target!) + (virtual.end!) + (ptree.end!) + #t))) + (let ((successful (with-exception-handling compiler-body))) + (if info-port + (if successful + (begin + (display "Compilation finished." info-port) + (newline info-port)) + (begin + (display "Compilation terminated abnormally." info-port) + (newline info-port)))) + successful)) +(define (valid-module-name? module-name) + (define (valid-char? c) + (and (not (memv c + '(#\# + #\; + #\( + #\) + #\space + #\[ + #\] + #\{ + #\} + #\" + #\' + #\` + #\,))) + (not (char-whitespace? c)))) + (let ((n (string-length module-name))) + (and (> n 0) + (not (string=? module-name ".")) + (not (string->number module-name 10)) + (let loop ((i 0)) + (if (< i n) + (if (valid-char? (string-ref module-name i)) (loop (+ i 1)) #f) + #t))))) +(define (dump-c-intf module-init-proc dest c-intf) + (let ((decls (c-intf-decls c-intf)) + (procs (c-intf-procs c-intf)) + (inits (c-intf-inits c-intf))) + (if (or (not (null? decls)) (not (null? procs)) (not (null? inits))) + (let* ((module-name (proc-obj-name module-init-proc)) + (filename (string-append dest ".c")) + (port (open-output-file filename))) + (display "/* File: \"" port) + (display filename port) + (display "\", C-interface file produced by Gambit " port) + (display compiler-version port) + (display " */" port) + (newline port) + (display "#define " port) + (display c-id-prefix port) + (display "MODULE_NAME \"" port) + (display module-name port) + (display "\"" port) + (newline port) + (display "#define " port) + (display c-id-prefix port) + (display "MODULE_LINKER " port) + (display c-id-prefix port) + (display (scheme-id->c-id module-name) port) + (newline port) + (display "#define " port) + (display c-id-prefix port) + (display "VERSION \"" port) + (display compiler-version port) + (display "\"" port) + (newline port) + (if (not (null? procs)) + (begin + (display "#define " port) + (display c-id-prefix port) + (display "C_PRC_COUNT " port) + (display (length procs) port) + (newline port))) + (display "#include \"gambit.h\"" port) + (newline port) + (display c-id-prefix port) + (display "BEGIN_MODULE" port) + (newline port) + (for-each + (lambda (x) + (let ((scheme-name (vector-ref x 0))) + (display c-id-prefix port) + (display "SUPPLY_PRM(" port) + (display c-id-prefix port) + (display "P_" port) + (display (scheme-id->c-id scheme-name) port) + (display ")" port) + (newline port))) + procs) + (newline port) + (for-each (lambda (x) (display x port) (newline port)) decls) + (if (not (null? procs)) + (begin + (for-each + (lambda (x) + (let ((scheme-name (vector-ref x 0)) + (c-name (vector-ref x 1)) + (arity (vector-ref x 2)) + (def (vector-ref x 3))) + (display c-id-prefix port) + (display "BEGIN_C_COD(" port) + (display c-name port) + (display "," port) + (display c-id-prefix port) + (display "P_" port) + (display (scheme-id->c-id scheme-name) port) + (display "," port) + (display arity port) + (display ")" port) + (newline port) + (display "#undef ___ARG1" port) + (newline port) + (display "#define ___ARG1 ___R1" port) + (newline port) + (display "#undef ___ARG2" port) + (newline port) + (display "#define ___ARG2 ___R2" port) + (newline port) + (display "#undef ___ARG3" port) + (newline port) + (display "#define ___ARG3 ___R3" port) + (newline port) + (display "#undef ___RESULT" port) + (newline port) + (display "#define ___RESULT ___R1" port) + (newline port) + (display def port) + (display c-id-prefix port) + (display "END_C_COD" port) + (newline port))) + procs) + (newline port) + (display c-id-prefix port) + (display "BEGIN_C_PRC" port) + (newline port) + (let loop ((i 0) (lst procs)) + (if (not (null? lst)) + (let* ((x (car lst)) + (scheme-name (vector-ref x 0)) + (c-name (vector-ref x 1)) + (arity (vector-ref x 2))) + (if (= i 0) (display " " port) (display "," port)) + (display c-id-prefix port) + (display "DEF_C_PRC(" port) + (display c-name port) + (display "," port) + (display c-id-prefix port) + (display "P_" port) + (display (scheme-id->c-id scheme-name) port) + (display "," port) + (display arity port) + (display ")" port) + (newline port) + (loop (+ i 1) (cdr lst))))) + (display c-id-prefix port) + (display "END_C_PRC" port) + (newline port))) + (newline port) + (display c-id-prefix port) + (display "BEGIN_PRM" port) + (newline port) + (for-each (lambda (x) (display x port) (newline port)) inits) + (display c-id-prefix port) + (display "END_PRM" port) + (newline port) + (close-output-port port))))) +(define (generate-report env) + (let ((vars (sort-variables (env-global-variables env))) + (decl (env-declarations env))) + (define (report title pred? vars wrote-something?) + (if (pair? vars) + (let ((var (car vars))) + (if (pred? var) + (begin + (if (not wrote-something?) + (begin (display " ") (display title) (newline))) + (let loop1 ((l (var-refs var)) (r? #f) (c? #f)) + (if (pair? l) + (let* ((x (car l)) (y (node-parent x))) + (if (and y (app? y) (eq? x (app-oper y))) + (loop1 (cdr l) r? #t) + (loop1 (cdr l) #t c?))) + (let loop2 ((l (var-sets var)) (d? #f) (a? #f)) + (if (pair? l) + (if (set? (car l)) + (loop2 (cdr l) d? #t) + (loop2 (cdr l) #t a?)) + (begin + (display " [") + (if d? (display "D") (display " ")) + (if a? (display "A") (display " ")) + (if r? (display "R") (display " ")) + (if c? (display "C") (display " ")) + (display "] ") + (display (var-name var)) + (newline)))))) + (report title pred? (cdr vars) #t)) + (cons (car vars) + (report title pred? (cdr vars) wrote-something?)))) + (begin (if wrote-something? (newline)) '()))) + (display "Global variable usage:") + (newline) + (newline) + (report "OTHERS" + (lambda (x) #t) + (report "EXTENDED" + (lambda (x) (target.prim-info (var-name x))) + (report "STANDARD" + (lambda (x) (standard-procedure (var-name x) decl)) + vars + #f) + #f) + #f))) +(define (compile-parsed-program module-name program env c-intf info-port) + (if info-port (display "Compiling:" info-port)) + (set! trace-indentation 0) + (set! *bbs* (make-bbs)) + (set! *global-env* env) + (set! proc-queue '()) + (set! constant-vars '()) + (set! known-procs '()) + (restore-context (make-context 0 '() (list ret-var) '() (entry-poll) #f)) + (let* ((entry-lbl (bbs-new-lbl! *bbs*)) + (body-lbl (bbs-new-lbl! *bbs*)) + (frame (current-frame ret-var-set)) + (comment (if (null? program) #f (source-comment (car program))))) + (bbs-entry-lbl-num-set! *bbs* entry-lbl) + (set! entry-bb + (make-bb (make-label-entry entry-lbl 0 0 #f #f frame comment) *bbs*)) + (bb-put-branch! entry-bb (make-jump (make-lbl body-lbl) #f #f frame #f)) + (set! *bb* (make-bb (make-label-simple body-lbl frame comment) *bbs*)) + (let loop1 ((l (c-intf-procs c-intf))) + (if (not (null? l)) + (let* ((x (car l)) + (name (vector-ref x 0)) + (sym (string->canonical-symbol name)) + (var (env-lookup-global-var *global-env* sym))) + (add-constant-var + var + (make-obj (make-proc-obj name #t #f 0 #t '() '(#f)))) + (loop1 (cdr l))))) + (let loop2 ((l program)) + (if (not (null? l)) + (let ((node (car l))) + (if (def? node) + (let* ((var (def-var node)) (val (global-val var))) + (if (and val (prc? val)) + (add-constant-var + var + (make-obj + (make-proc-obj + (symbol->string (var-name var)) + #t + #f + (call-pattern val) + #t + '() + '(#f))))))) + (loop2 (cdr l))))) + (let loop3 ((l program)) + (if (null? l) + (let ((ret-opnd (var->opnd ret-var))) + (seal-bb #t 'return) + (dealloc-slots nb-slots) + (bb-put-branch! + *bb* + (make-jump ret-opnd #f #f (current-frame (set-empty)) #f))) + (let ((node (car l))) + (if (def? node) + (begin + (gen-define (def-var node) (def-val node) info-port) + (loop3 (cdr l))) + (if (null? (cdr l)) + (gen-node node ret-var-set 'tail) + (begin + (gen-node node ret-var-set 'need) + (loop3 (cdr l)))))))) + (let loop4 () + (if (pair? proc-queue) + (let ((x (car proc-queue))) + (set! proc-queue (cdr proc-queue)) + (gen-proc (car x) (cadr x) (caddr x) info-port) + (trace-unindent info-port) + (loop4)))) + (if info-port (begin (newline info-port) (newline info-port))) + (bbs-purify! *bbs*) + (let ((proc (make-proc-obj + (string-append "#!" module-name) + #t + *bbs* + '(0) + #t + '() + '(#f)))) + (set! *bb* '()) + (set! *bbs* '()) + (set! *global-env* '()) + (set! proc-queue '()) + (set! constant-vars '()) + (set! known-procs '()) + (clear-context) + proc))) +(define *bb* '()) +(define *bbs* '()) +(define *global-env* '()) +(define proc-queue '()) +(define constant-vars '()) +(define known-procs '()) +(define trace-indentation '()) +(define (trace-indent info-port) + (set! trace-indentation (+ trace-indentation 1)) + (if info-port + (begin + (newline info-port) + (let loop ((i trace-indentation)) + (if (> i 0) (begin (display " " info-port) (loop (- i 1)))))))) +(define (trace-unindent info-port) + (set! trace-indentation (- trace-indentation 1))) +(define (gen-define var node info-port) + (if (prc? node) + (let* ((p-bbs *bbs*) + (p-bb *bb*) + (p-proc-queue proc-queue) + (p-known-procs known-procs) + (p-context (current-context)) + (bbs (make-bbs)) + (lbl1 (bbs-new-lbl! bbs)) + (lbl2 (bbs-new-lbl! bbs)) + (context (entry-context node '())) + (frame (context->frame + context + (set-union (free-variables (prc-body node)) ret-var-set))) + (bb1 (make-bb (make-label-entry + lbl1 + (length (prc-parms node)) + (prc-min node) + (prc-rest node) + #f + frame + (source-comment node)) + bbs)) + (bb2 (make-bb (make-label-simple lbl2 frame (source-comment node)) + bbs))) + (define (do-body) + (gen-proc node bb2 context info-port) + (let loop () + (if (pair? proc-queue) + (let ((x (car proc-queue))) + (set! proc-queue (cdr proc-queue)) + (gen-proc (car x) (cadr x) (caddr x) info-port) + (trace-unindent info-port) + (loop)))) + (trace-unindent info-port) + (bbs-purify! *bbs*)) + (context-entry-bb-set! context bb1) + (bbs-entry-lbl-num-set! bbs lbl1) + (bb-put-branch! bb1 (make-jump (make-lbl lbl2) #f #f frame #f)) + (set! *bbs* bbs) + (set! proc-queue '()) + (set! known-procs '()) + (if (constant-var? var) + (let-constant-var + var + (make-lbl lbl1) + (lambda () (add-known-proc lbl1 node) (do-body))) + (do-body)) + (set! *bbs* p-bbs) + (set! *bb* p-bb) + (set! proc-queue p-proc-queue) + (set! known-procs p-known-procs) + (restore-context p-context) + (let* ((x (assq var constant-vars)) + (proc (if x + (let ((p (cdr x))) + (proc-obj-code-set! (obj-val p) bbs) + p) + (make-obj + (make-proc-obj + (symbol->string (var-name var)) + #f + bbs + (call-pattern node) + #t + '() + '(#f)))))) + (put-copy + proc + (make-glo (var-name var)) + #f + ret-var-set + (source-comment node)))) + (put-copy + (gen-node node ret-var-set 'need) + (make-glo (var-name var)) + #f + ret-var-set + (source-comment node)))) +(define (call-pattern node) + (make-pattern (prc-min node) (length (prc-parms node)) (prc-rest node))) +(define (make-context nb-slots slots regs closed poll entry-bb) + (vector nb-slots slots regs closed poll entry-bb)) +(define (context-nb-slots x) (vector-ref x 0)) +(define (context-slots x) (vector-ref x 1)) +(define (context-regs x) (vector-ref x 2)) +(define (context-closed x) (vector-ref x 3)) +(define (context-poll x) (vector-ref x 4)) +(define (context-entry-bb x) (vector-ref x 5)) +(define (context-entry-bb-set! x y) (vector-set! x 5 y)) +(define nb-slots '()) +(define slots '()) +(define regs '()) +(define closed '()) +(define poll '()) +(define entry-bb '()) +(define (restore-context context) + (set! nb-slots (context-nb-slots context)) + (set! slots (context-slots context)) + (set! regs (context-regs context)) + (set! closed (context-closed context)) + (set! poll (context-poll context)) + (set! entry-bb (context-entry-bb context))) +(define (clear-context) + (restore-context (make-context '() '() '() '() '() '()))) +(define (current-context) + (make-context nb-slots slots regs closed poll entry-bb)) +(define (current-frame live) (make-frame nb-slots slots regs closed live)) +(define (context->frame context live) + (make-frame + (context-nb-slots context) + (context-slots context) + (context-regs context) + (context-closed context) + live)) +(define (make-poll since-entry? delta) (cons since-entry? delta)) +(define (poll-since-entry? x) (car x)) +(define (poll-delta x) (cdr x)) +(define (entry-poll) (make-poll #f (- poll-period poll-head))) +(define (return-poll poll) + (let ((delta (poll-delta poll))) + (make-poll (poll-since-entry? poll) (+ poll-head (max delta poll-tail))))) +(define (poll-merge poll other-poll) + (make-poll + (or (poll-since-entry? poll) (poll-since-entry? other-poll)) + (max (poll-delta poll) (poll-delta other-poll)))) +(define poll-period #f) +(set! poll-period 90) +(define poll-head #f) +(set! poll-head 15) +(define poll-tail #f) +(set! poll-tail 15) +(define (entry-context proc closed) + (define (empty-vars-list n) + (if (> n 0) (cons empty-var (empty-vars-list (- n 1))) '())) + (let* ((parms (prc-parms proc)) + (pc (target.label-info + (prc-min proc) + (length parms) + (prc-rest proc) + (not (null? closed)))) + (fs (pcontext-fs pc)) + (slots-list (empty-vars-list fs)) + (regs-list (empty-vars-list target.nb-regs))) + (define (assign-var-to-loc var loc) + (let ((x (cond ((reg? loc) + (let ((i (reg-num loc))) + (if (<= i target.nb-regs) + (nth-after regs-list i) + (compiler-internal-error + "entry-context, reg out of bound in back-end's pcontext")))) + ((stk? loc) + (let ((i (stk-num loc))) + (if (<= i fs) + (nth-after slots-list (- fs i)) + (compiler-internal-error + "entry-context, stk out of bound in back-end's pcontext")))) + (else + (compiler-internal-error + "entry-context, loc other than reg or stk in back-end's pcontext"))))) + (if (eq? (car x) empty-var) + (set-car! x var) + (compiler-internal-error + "entry-context, duplicate location in back-end's pcontext")))) + (let loop ((l (pcontext-map pc))) + (if (not (null? l)) + (let* ((couple (car l)) (name (car couple)) (loc (cdr couple))) + (cond ((eq? name 'return) (assign-var-to-loc ret-var loc)) + ((eq? name 'closure-env) + (assign-var-to-loc closure-env-var loc)) + (else (assign-var-to-loc (list-ref parms (- name 1)) loc))) + (loop (cdr l))))) + (make-context fs slots-list regs-list closed (entry-poll) #f))) +(define (get-var opnd) + (cond ((glo? opnd) (env-lookup-global-var *global-env* (glo-name opnd))) + ((reg? opnd) (list-ref regs (reg-num opnd))) + ((stk? opnd) (list-ref slots (- nb-slots (stk-num opnd)))) + (else + (compiler-internal-error + "get-var, location must be global, register or stack slot")))) +(define (put-var opnd new) + (define (put-v opnd new) + (cond ((reg? opnd) (set! regs (replace-nth regs (reg-num opnd) new))) + ((stk? opnd) + (set! slots (replace-nth slots (- nb-slots (stk-num opnd)) new))) + (else + (compiler-internal-error + "put-var, location must be register or stack slot, for var:" + (var-name new))))) + (if (eq? new ret-var) + (let ((x (var->opnd ret-var))) (and x (put-v x empty-var)))) + (put-v opnd new)) +(define (flush-regs) (set! regs '())) +(define (push-slot) + (set! nb-slots (+ nb-slots 1)) + (set! slots (cons empty-var slots))) +(define (dealloc-slots n) + (set! nb-slots (- nb-slots n)) + (set! slots (nth-after slots n))) +(define (pop-slot) (dealloc-slots 1)) +(define (replace-nth l i v) + (if (null? l) + (if (= i 0) (list v) (cons empty-var (replace-nth l (- i 1) v))) + (if (= i 0) + (cons v (cdr l)) + (cons (car l) (replace-nth (cdr l) (- i 1) v))))) +(define (live-vars live) + (if (not (set-empty? (set-intersection live (list->set closed)))) + (set-adjoin live closure-env-var) + live)) +(define (dead-slots live) + (let ((live-v (live-vars live))) + (define (loop s l i) + (cond ((null? l) (list->set (reverse s))) + ((set-member? (car l) live-v) (loop s (cdr l) (- i 1))) + (else (loop (cons i s) (cdr l) (- i 1))))) + (loop '() slots nb-slots))) +(define (live-slots live) + (let ((live-v (live-vars live))) + (define (loop s l i) + (cond ((null? l) (list->set (reverse s))) + ((set-member? (car l) live-v) (loop (cons i s) (cdr l) (- i 1))) + (else (loop s (cdr l) (- i 1))))) + (loop '() slots nb-slots))) +(define (dead-regs live) + (let ((live-v (live-vars live))) + (define (loop s l i) + (cond ((>= i target.nb-regs) (list->set (reverse s))) + ((null? l) (loop (cons i s) l (+ i 1))) + ((and (set-member? (car l) live-v) (not (memq (car l) slots))) + (loop s (cdr l) (+ i 1))) + (else (loop (cons i s) (cdr l) (+ i 1))))) + (loop '() regs 0))) +(define (live-regs live) + (let ((live-v (live-vars live))) + (define (loop s l i) + (cond ((null? l) (list->set (reverse s))) + ((and (set-member? (car l) live-v) (not (memq (car l) slots))) + (loop (cons i s) (cdr l) (+ i 1))) + (else (loop s (cdr l) (+ i 1))))) + (loop '() regs 0))) +(define (lowest-dead-slot live) + (make-stk (or (lowest (dead-slots live)) (+ nb-slots 1)))) +(define (highest-live-slot live) (make-stk (or (highest (live-slots live)) 0))) +(define (lowest-dead-reg live) + (let ((x (lowest (set-remove (dead-regs live) 0)))) (if x (make-reg x) #f))) +(define (highest-dead-reg live) + (let ((x (highest (dead-regs live)))) (if x (make-reg x) #f))) +(define (highest set) (if (set-empty? set) #f (apply max (set->list set)))) +(define (lowest set) (if (set-empty? set) #f (apply min (set->list set)))) +(define (above set n) (set-keep (lambda (x) (> x n)) set)) +(define (below set n) (set-keep (lambda (x) (< x n)) set)) +(define (var->opnd var) + (let ((x (assq var constant-vars))) + (if x + (cdr x) + (if (global? var) + (make-glo (var-name var)) + (let ((n (pos-in-list var regs))) + (if n + (make-reg n) + (let ((n (pos-in-list var slots))) + (if n + (make-stk (- nb-slots n)) + (let ((n (pos-in-list var closed))) + (if n + (make-clo (var->opnd closure-env-var) (+ n 1)) + (compiler-internal-error + "var->opnd, variable is not accessible:" + (var-name var)))))))))))) +(define (source-comment node) + (let ((x (make-comment))) (comment-put! x 'source (node-source node)) x)) +(define (sort-variables lst) + (sort-list + lst + (lambda (x y) + (string<? (symbol->string (var-name x)) (symbol->string (var-name y)))))) +(define (add-constant-var var opnd) + (set! constant-vars (cons (cons var opnd) constant-vars))) +(define (let-constant-var var opnd thunk) + (let* ((x (assq var constant-vars)) (temp (cdr x))) + (set-cdr! x opnd) + (thunk) + (set-cdr! x temp))) +(define (constant-var? var) (assq var constant-vars)) +(define (not-constant-var? var) (not (constant-var? var))) +(define (add-known-proc label proc) + (set! known-procs (cons (cons label proc) known-procs))) +(define (gen-proc proc bb context info-port) + (trace-indent info-port) + (if info-port + (if (prc-name proc) + (display (prc-name proc) info-port) + (display "\"unknown\"" info-port))) + (let ((lbl (bb-lbl-num bb)) + (live (set-union (free-variables (prc-body proc)) ret-var-set))) + (set! *bb* bb) + (restore-context context) + (gen-node (prc-body proc) ret-var-set 'tail))) +(define (schedule-gen-proc proc closed-list) + (let* ((lbl1 (bbs-new-lbl! *bbs*)) + (lbl2 (bbs-new-lbl! *bbs*)) + (context (entry-context proc closed-list)) + (frame (context->frame + context + (set-union (free-variables (prc-body proc)) ret-var-set))) + (bb1 (make-bb (make-label-entry + lbl1 + (length (prc-parms proc)) + (prc-min proc) + (prc-rest proc) + (not (null? closed-list)) + frame + (source-comment proc)) + *bbs*)) + (bb2 (make-bb (make-label-simple lbl2 frame (source-comment proc)) + *bbs*))) + (context-entry-bb-set! context bb1) + (bb-put-branch! bb1 (make-jump (make-lbl lbl2) #f #f frame #f)) + (set! proc-queue (cons (list proc bb2 context) proc-queue)) + (make-lbl lbl1))) +(define (gen-node node live why) + (cond ((cst? node) (gen-return (make-obj (cst-val node)) why node)) + ((ref? node) + (let* ((var (ref-var node)) (name (var-name var))) + (gen-return + (cond ((eq? why 'side) (make-obj undef-object)) + ((global? var) + (let ((prim (target.prim-info* name (node-decl node)))) + (if prim (make-obj prim) (var->opnd var)))) + (else (var->opnd var))) + why + node))) + ((set? node) + (let* ((src (gen-node + (set-val node) + (set-adjoin live (set-var node)) + 'keep)) + (dst (var->opnd (set-var node)))) + (put-copy src dst #f live (source-comment node)) + (gen-return (make-obj undef-object) why node))) + ((def? node) + (compiler-internal-error + "gen-node, 'def' node not at root of parse tree")) + ((tst? node) (gen-tst node live why)) + ((conj? node) (gen-conj/disj node live why)) + ((disj? node) (gen-conj/disj node live why)) + ((prc? node) + (let* ((closed (not-constant-closed-vars node)) + (closed-list (sort-variables (set->list closed))) + (proc-lbl (schedule-gen-proc node closed-list))) + (let ((opnd (if (null? closed-list) + (begin + (add-known-proc (lbl-num proc-lbl) node) + proc-lbl) + (begin + (dealloc-slots + (- nb-slots + (stk-num (highest-live-slot + (set-union closed live))))) + (push-slot) + (let ((slot (make-stk nb-slots)) + (var (make-temp-var 'closure))) + (put-var slot var) + (bb-put-non-branch! + *bb* + (make-close + (list (make-closure-parms + slot + (lbl-num proc-lbl) + (map var->opnd closed-list))) + (current-frame (set-adjoin live var)) + (source-comment node))) + slot))))) + (gen-return opnd why node)))) + ((app? node) (gen-call node live why)) + ((fut? node) (gen-fut node live why)) + (else + (compiler-internal-error + "gen-node, unknown parse tree node type:" + node)))) +(define (gen-return opnd why node) + (cond ((eq? why 'tail) + (let ((var (make-temp-var 'result))) + (put-copy + opnd + target.proc-result + var + ret-var-set + (source-comment node)) + (let ((ret-opnd (var->opnd ret-var))) + (seal-bb (intrs-enabled? (node-decl node)) 'return) + (dealloc-slots nb-slots) + (bb-put-branch! + *bb* + (make-jump + ret-opnd + #f + #f + (current-frame (set-singleton var)) + #f))))) + (else opnd))) +(define (not-constant-closed-vars val) + (set-keep not-constant-var? (free-variables val))) +(define (predicate node live cont) + (define (cont* true-lbl false-lbl) (cont false-lbl true-lbl)) + (define (generic-true-test) + (predicate-test node live **not-proc-obj '0 (list node) cont*)) + (cond ((or (conj? node) (disj? node)) (predicate-conj/disj node live cont)) + ((app? node) + (let ((proc (node->proc (app-oper node)))) + (if proc + (let ((spec (specialize-for-call proc (node-decl node)))) + (if (and (proc-obj-test spec) + (nb-args-conforms? + (length (app-args node)) + (proc-obj-call-pat spec))) + (if (eq? spec **not-proc-obj) + (predicate (car (app-args node)) live cont*) + (predicate-test + node + live + spec + (proc-obj-strict-pat proc) + (app-args node) + cont)) + (generic-true-test))) + (generic-true-test)))) + (else (generic-true-test)))) +(define (predicate-conj/disj node live cont) + (let* ((pre (if (conj? node) (conj-pre node) (disj-pre node))) + (alt (if (conj? node) (conj-alt node) (disj-alt node))) + (alt-live (set-union live (free-variables alt)))) + (predicate + pre + alt-live + (lambda (true-lbl false-lbl) + (let ((pre-context (current-context))) + (set! *bb* + (make-bb (make-label-simple + (if (conj? node) true-lbl false-lbl) + (current-frame alt-live) + (source-comment alt)) + *bbs*)) + (predicate + alt + live + (lambda (true-lbl2 false-lbl2) + (let ((alt-context (current-context))) + (restore-context pre-context) + (set! *bb* + (make-bb (make-label-simple + (if (conj? node) false-lbl true-lbl) + (current-frame live) + (source-comment alt)) + *bbs*)) + (merge-contexts-and-seal-bb + alt-context + live + (intrs-enabled? (node-decl node)) + 'internal + (source-comment node)) + (bb-put-branch! + *bb* + (make-jump + (make-lbl (if (conj? node) false-lbl2 true-lbl2)) + #f + #f + (current-frame live) + #f)) + (cont true-lbl2 false-lbl2))))))))) +(define (predicate-test node live test strict-pat args cont) + (let loop ((args* args) (liv live) (vars* '())) + (if (not (null? args*)) + (let* ((needed (vals-live-vars liv (cdr args*))) + (var (save-var + (gen-node (car args*) needed 'need) + (make-temp-var 'predicate) + needed + (source-comment (car args*))))) + (loop (cdr args*) (set-adjoin liv var) (cons var vars*))) + (let* ((true-lbl (bbs-new-lbl! *bbs*)) + (false-lbl (bbs-new-lbl! *bbs*))) + (seal-bb (intrs-enabled? (node-decl node)) 'internal) + (bb-put-branch! + *bb* + (make-ifjump + test + (map var->opnd (reverse vars*)) + true-lbl + false-lbl + #f + (current-frame live) + (source-comment node))) + (cont true-lbl false-lbl))))) +(define (gen-tst node live why) + (let ((pre (tst-pre node)) (con (tst-con node)) (alt (tst-alt node))) + (predicate + pre + (set-union live (free-variables con) (free-variables alt)) + (lambda (true-lbl false-lbl) + (let ((pre-context (current-context)) + (true-bb (make-bb (make-label-simple + true-lbl + (current-frame + (set-union live (free-variables con))) + (source-comment con)) + *bbs*)) + (false-bb + (make-bb (make-label-simple + false-lbl + (current-frame (set-union live (free-variables alt))) + (source-comment alt)) + *bbs*))) + (set! *bb* true-bb) + (let ((con-opnd (gen-node con live why))) + (if (eq? why 'tail) + (begin + (restore-context pre-context) + (set! *bb* false-bb) + (gen-node alt live why)) + (let* ((result-var (make-temp-var 'result)) + (live-after (set-adjoin live result-var))) + (save-opnd-to-reg + con-opnd + target.proc-result + result-var + live + (source-comment con)) + (let ((con-context (current-context)) (con-bb *bb*)) + (restore-context pre-context) + (set! *bb* false-bb) + (save-opnd-to-reg + (gen-node alt live why) + target.proc-result + result-var + live + (source-comment alt)) + (let ((next-lbl (bbs-new-lbl! *bbs*)) (alt-bb *bb*)) + (if (> (context-nb-slots con-context) nb-slots) + (begin + (seal-bb (intrs-enabled? (node-decl node)) + 'internal) + (let ((alt-context (current-context))) + (restore-context con-context) + (set! *bb* con-bb) + (merge-contexts-and-seal-bb + alt-context + live-after + (intrs-enabled? (node-decl node)) + 'internal + (source-comment node)))) + (let ((alt-context (current-context))) + (restore-context con-context) + (set! *bb* con-bb) + (seal-bb (intrs-enabled? (node-decl node)) + 'internal) + (let ((con-context* (current-context))) + (restore-context alt-context) + (set! *bb* alt-bb) + (merge-contexts-and-seal-bb + con-context* + live-after + (intrs-enabled? (node-decl node)) + 'internal + (source-comment node))))) + (let ((frame (current-frame live-after))) + (bb-put-branch! + con-bb + (make-jump (make-lbl next-lbl) #f #f frame #f)) + (bb-put-branch! + alt-bb + (make-jump (make-lbl next-lbl) #f #f frame #f)) + (set! *bb* + (make-bb (make-label-simple + next-lbl + frame + (source-comment node)) + *bbs*)) + target.proc-result))))))))))) +(define (nb-args-conforms? n call-pat) (pattern-member? n call-pat)) +(define (merge-contexts-and-seal-bb other-context live poll? where comment) + (let ((live-v (live-vars live)) + (other-nb-slots (context-nb-slots other-context)) + (other-regs (context-regs other-context)) + (other-slots (context-slots other-context)) + (other-poll (context-poll other-context)) + (other-entry-bb (context-entry-bb other-context))) + (let loop1 ((i (- target.nb-regs 1))) + (if (>= i 0) + (let ((other-var (reg->var other-regs i)) (var (reg->var regs i))) + (if (and (not (eq? var other-var)) (set-member? other-var live-v)) + (let ((r (make-reg i))) + (put-var r empty-var) + (if (not (or (not (set-member? var live-v)) + (memq var regs) + (memq var slots))) + (let ((top (make-stk (+ nb-slots 1)))) + (put-copy r top var live-v comment))) + (put-copy (var->opnd other-var) r other-var live-v comment))) + (loop1 (- i 1))))) + (let loop2 ((i 1)) + (if (<= i other-nb-slots) + (let ((other-var (stk->var other-slots i)) (var (stk->var slots i))) + (if (and (not (eq? var other-var)) (set-member? other-var live-v)) + (let ((s (make-stk i))) + (if (<= i nb-slots) (put-var s empty-var)) + (if (not (or (not (set-member? var live-v)) + (memq var regs) + (memq var slots))) + (let ((top (make-stk (+ nb-slots 1)))) + (put-copy s top var live-v comment))) + (put-copy (var->opnd other-var) s other-var live-v comment)) + (if (> i nb-slots) + (let ((top (make-stk (+ nb-slots 1)))) + (put-copy + (make-obj undef-object) + top + empty-var + live-v + comment)))) + (loop2 (+ i 1))))) + (dealloc-slots (- nb-slots other-nb-slots)) + (let loop3 ((i (- target.nb-regs 1))) + (if (>= i 0) + (let ((other-var (reg->var other-regs i)) (var (reg->var regs i))) + (if (not (eq? var other-var)) (put-var (make-reg i) empty-var)) + (loop3 (- i 1))))) + (let loop4 ((i 1)) + (if (<= i other-nb-slots) + (let ((other-var (stk->var other-slots i)) (var (stk->var slots i))) + (if (not (eq? var other-var)) (put-var (make-stk i) empty-var)) + (loop4 (+ i 1))))) + (seal-bb poll? where) + (set! poll (poll-merge poll other-poll)) + (if (not (eq? entry-bb other-entry-bb)) + (compiler-internal-error + "merge-contexts-and-seal-bb, entry-bb's do not agree")))) +(define (seal-bb poll? where) + (define (my-last-pair l) (if (pair? (cdr l)) (my-last-pair (cdr l)) l)) + (define (poll-at split-point) + (let loop ((i 0) (l1 (bb-non-branch-instrs *bb*)) (l2 '())) + (if (< i split-point) + (loop (+ i 1) (cdr l1) (cons (car l1) l2)) + (let* ((label-instr (bb-label-instr *bb*)) + (non-branch-instrs1 (reverse l2)) + (non-branch-instrs2 l1) + (frame (gvm-instr-frame + (car (my-last-pair + (cons label-instr non-branch-instrs1))))) + (prec-bb (make-bb label-instr *bbs*)) + (new-lbl (bbs-new-lbl! *bbs*))) + (bb-non-branch-instrs-set! prec-bb non-branch-instrs1) + (bb-put-branch! + prec-bb + (make-jump (make-lbl new-lbl) #f #t frame #f)) + (bb-label-instr-set! *bb* (make-label-simple new-lbl frame #f)) + (bb-non-branch-instrs-set! *bb* non-branch-instrs2) + (set! poll (make-poll #t 0)))))) + (define (poll-at-end) (poll-at (length (bb-non-branch-instrs *bb*)))) + (define (impose-polling-constraints) + (let ((n (+ (length (bb-non-branch-instrs *bb*)) 1)) + (delta (poll-delta poll))) + (if (> (+ delta n) poll-period) + (begin + (poll-at (max (- poll-period delta) 0)) + (impose-polling-constraints))))) + (if poll? (impose-polling-constraints)) + (let* ((n (+ (length (bb-non-branch-instrs *bb*)) 1)) + (delta (+ (poll-delta poll) n)) + (since-entry? (poll-since-entry? poll))) + (if (and poll? + (case where + ((call) (> delta (- poll-period poll-head))) + ((tail-call) (> delta poll-tail)) + ((return) (and since-entry? (> delta (+ poll-head poll-tail)))) + ((internal) #f) + (else + (compiler-internal-error "seal-bb, unknown 'where':" where)))) + (poll-at-end) + (set! poll (make-poll since-entry? delta))))) +(define (reg->var regs i) + (cond ((null? regs) '()) + ((> i 0) (reg->var (cdr regs) (- i 1))) + (else (car regs)))) +(define (stk->var slots i) + (let ((j (- (length slots) i))) (if (< j 0) '() (list-ref slots j)))) +(define (gen-conj/disj node live why) + (let ((pre (if (conj? node) (conj-pre node) (disj-pre node))) + (alt (if (conj? node) (conj-alt node) (disj-alt node)))) + (let ((needed (set-union live (free-variables alt))) + (bool? (boolean-value? pre)) + (predicate-var (make-temp-var 'predicate))) + (define (general-predicate node live cont) + (let* ((con-lbl (bbs-new-lbl! *bbs*)) (alt-lbl (bbs-new-lbl! *bbs*))) + (save-opnd-to-reg + (gen-node pre live 'need) + target.proc-result + predicate-var + live + (source-comment pre)) + (seal-bb (intrs-enabled? (node-decl node)) 'internal) + (bb-put-branch! + *bb* + (make-ifjump + **not-proc-obj + (list target.proc-result) + alt-lbl + con-lbl + #f + (current-frame (set-adjoin live predicate-var)) + (source-comment node))) + (cont con-lbl alt-lbl))) + (define (alternative con-lbl alt-lbl) + (let* ((pre-context (current-context)) + (result-var (make-temp-var 'result)) + (con-live (if bool? live (set-adjoin live predicate-var))) + (alt-live (set-union live (free-variables alt))) + (con-bb (make-bb (make-label-simple + con-lbl + (current-frame con-live) + (source-comment alt)) + *bbs*)) + (alt-bb (make-bb (make-label-simple + alt-lbl + (current-frame alt-live) + (source-comment alt)) + *bbs*))) + (if bool? + (begin + (set! *bb* con-bb) + (save-opnd-to-reg + (make-obj (if (conj? node) false-object #t)) + target.proc-result + result-var + live + (source-comment node))) + (put-var (var->opnd predicate-var) result-var)) + (let ((con-context (current-context))) + (set! *bb* alt-bb) + (restore-context pre-context) + (let ((alt-opnd (gen-node alt live why))) + (if (eq? why 'tail) + (begin + (restore-context con-context) + (set! *bb* con-bb) + (let ((ret-opnd (var->opnd ret-var)) + (result-set (set-singleton result-var))) + (seal-bb (intrs-enabled? (node-decl node)) 'return) + (dealloc-slots nb-slots) + (bb-put-branch! + *bb* + (make-jump + ret-opnd + #f + #f + (current-frame result-set) + #f)))) + (let ((alt-context* (current-context)) (alt-bb* *bb*)) + (restore-context con-context) + (set! *bb* con-bb) + (seal-bb (intrs-enabled? (node-decl node)) 'internal) + (let ((con-context* (current-context)) + (next-lbl (bbs-new-lbl! *bbs*))) + (restore-context alt-context*) + (set! *bb* alt-bb*) + (save-opnd-to-reg + alt-opnd + target.proc-result + result-var + live + (source-comment alt)) + (merge-contexts-and-seal-bb + con-context* + (set-adjoin live result-var) + (intrs-enabled? (node-decl node)) + 'internal + (source-comment node)) + (let ((frame (current-frame + (set-adjoin live result-var)))) + (bb-put-branch! + *bb* + (make-jump (make-lbl next-lbl) #f #f frame #f)) + (bb-put-branch! + con-bb + (make-jump (make-lbl next-lbl) #f #f frame #f)) + (set! *bb* + (make-bb (make-label-simple + next-lbl + frame + (source-comment node)) + *bbs*)) + target.proc-result)))))))) + ((if bool? predicate general-predicate) + pre + needed + (lambda (true-lbl false-lbl) + (if (conj? node) + (alternative false-lbl true-lbl) + (alternative true-lbl false-lbl))))))) +(define (gen-call node live why) + (let* ((oper (app-oper node)) (args (app-args node)) (nb-args (length args))) + (if (and (prc? oper) + (not (prc-rest oper)) + (= (length (prc-parms oper)) nb-args)) + (gen-let (prc-parms oper) args (prc-body oper) live why) + (if (inlinable-app? node) + (let ((eval-order (arg-eval-order #f args)) + (vars (map (lambda (x) (cons x #f)) args))) + (let loop ((l eval-order) (liv live)) + (if (not (null? l)) + (let* ((needed (vals-live-vars liv (map car (cdr l)))) + (arg (car (car l))) + (pos (cdr (car l))) + (var (save-var + (gen-node arg needed 'need) + (make-temp-var pos) + needed + (source-comment arg)))) + (set-cdr! (assq arg vars) var) + (loop (cdr l) (set-adjoin liv var))) + (let ((loc (if (eq? why 'side) + (make-reg 0) + (or (lowest-dead-reg live) + (lowest-dead-slot live))))) + (if (and (stk? loc) (> (stk-num loc) nb-slots)) + (push-slot)) + (let* ((args (map var->opnd (map cdr vars))) + (var (make-temp-var 'result)) + (proc (node->proc oper)) + (strict-pat (proc-obj-strict-pat proc))) + (if (not (eq? why 'side)) (put-var loc var)) + (bb-put-non-branch! + *bb* + (make-apply + (specialize-for-call proc (node-decl node)) + args + (if (eq? why 'side) #f loc) + (current-frame + (if (eq? why 'side) live (set-adjoin live var))) + (source-comment node))) + (gen-return loc why node)))))) + (let* ((calling-local-proc? + (and (ref? oper) + (let ((opnd (var->opnd (ref-var oper)))) + (and (lbl? opnd) + (let ((x (assq (lbl-num opnd) known-procs))) + (and x + (let ((proc (cdr x))) + (and (not (prc-rest proc)) + (= (prc-min proc) nb-args) + (= (length (prc-parms proc)) + nb-args) + (lbl-num opnd))))))))) + (jstate (get-jump-state + args + (if calling-local-proc? + (target.label-info nb-args nb-args #f #f) + (target.jump-info nb-args)))) + (in-stk (jump-state-in-stk jstate)) + (in-reg (jump-state-in-reg jstate)) + (eval-order + (arg-eval-order (if calling-local-proc? #f oper) in-reg)) + (live-after + (if (eq? why 'tail) (set-remove live ret-var) live)) + (live-for-regs (args-live-vars live eval-order)) + (return-lbl (if (eq? why 'tail) #f (bbs-new-lbl! *bbs*)))) + (save-regs + (live-regs live-after) + (stk-live-vars live-for-regs in-stk why) + (source-comment node)) + (let ((frame-start (stk-num (highest-live-slot live-after)))) + (let loop1 ((l in-stk) (liv live-after) (i (+ frame-start 1))) + (if (not (null? l)) + (let ((arg (car l)) + (slot (make-stk i)) + (needed (set-union + (stk-live-vars liv (cdr l) why) + live-for-regs))) + (if arg + (let ((var (if (and (eq? arg 'return) + (eq? why 'tail)) + ret-var + (make-temp-var (- frame-start i))))) + (save-opnd-to-stk + (if (eq? arg 'return) + (if (eq? why 'tail) + (var->opnd ret-var) + (make-lbl return-lbl)) + (gen-node arg needed 'need)) + slot + var + needed + (source-comment + (if (eq? arg 'return) node arg))) + (loop1 (cdr l) (set-adjoin liv var) (+ i 1))) + (begin + (if (> i nb-slots) + (put-copy + (make-obj undef-object) + slot + empty-var + liv + (source-comment node))) + (loop1 (cdr l) liv (+ i 1))))) + (let loop2 ((l eval-order) + (liv liv) + (reg-map '()) + (oper-var '())) + (if (not (null? l)) + (let* ((arg (car (car l))) + (pos (cdr (car l))) + (needed (args-live-vars liv (cdr l))) + (var (if (and (eq? arg 'return) + (eq? why 'tail)) + ret-var + (make-temp-var pos))) + (opnd (if (eq? arg 'return) + (if (eq? why 'tail) + (var->opnd ret-var) + (make-lbl return-lbl)) + (gen-node arg needed 'need)))) + (if (eq? pos 'operator) + (if (and (ref? arg) + (not (or (obj? opnd) (lbl? opnd)))) + (loop2 (cdr l) + (set-adjoin liv (ref-var arg)) + reg-map + (ref-var arg)) + (begin + (save-arg + opnd + var + needed + (source-comment + (if (eq? arg 'return) node arg))) + (loop2 (cdr l) + (set-adjoin liv var) + reg-map + var))) + (let ((reg (make-reg pos))) + (if (all-args-trivial? (cdr l)) + (save-opnd-to-reg + opnd + reg + var + needed + (source-comment + (if (eq? arg 'return) node arg))) + (save-in-slot + opnd + var + needed + (source-comment + (if (eq? arg 'return) node arg)))) + (loop2 (cdr l) + (set-adjoin liv var) + (cons (cons pos var) reg-map) + oper-var)))) + (let loop3 ((i (- target.nb-regs 1))) + (if (>= i 0) + (let ((couple (assq i reg-map))) + (if couple + (let ((var (cdr couple))) + (if (not (eq? (reg->var regs i) var)) + (save-opnd-to-reg + (var->opnd var) + (make-reg i) + var + liv + (source-comment node))))) + (loop3 (- i 1))) + (let ((opnd (if calling-local-proc? + (make-lbl + (+ calling-local-proc? 1)) + (var->opnd oper-var)))) + (seal-bb (intrs-enabled? (node-decl node)) + (if return-lbl 'call 'tail-call)) + (dealloc-slots + (- nb-slots + (+ frame-start (length in-stk)))) + (bb-put-branch! + *bb* + (make-jump + opnd + (if calling-local-proc? #f nb-args) + #f + (current-frame liv) + (source-comment node))) + (let ((result-var (make-temp-var 'result))) + (dealloc-slots (- nb-slots frame-start)) + (flush-regs) + (put-var target.proc-result result-var) + (if return-lbl + (begin + (set! poll (return-poll poll)) + (set! *bb* + (make-bb (make-label-return + return-lbl + (current-frame + (set-adjoin + live + result-var)) + (source-comment + node)) + *bbs*)))) + target.proc-result)))))))))))))) +(define (contained-reg/slot opnd) + (cond ((reg? opnd) opnd) + ((stk? opnd) opnd) + ((clo? opnd) (contained-reg/slot (clo-base opnd))) + (else #f))) +(define (opnd-needed opnd needed) + (let ((x (contained-reg/slot opnd))) + (if x (set-adjoin needed (get-var x)) needed))) +(define (save-opnd opnd live comment) + (let ((slot (lowest-dead-slot live))) + (put-copy opnd slot (get-var opnd) live comment))) +(define (save-regs regs live comment) + (for-each + (lambda (i) (save-opnd (make-reg i) live comment)) + (set->list regs))) +(define (save-opnd-to-reg opnd reg var live comment) + (if (set-member? (reg-num reg) (live-regs live)) + (save-opnd reg (opnd-needed opnd live) comment)) + (put-copy opnd reg var live comment)) +(define (save-opnd-to-stk opnd stk var live comment) + (if (set-member? (stk-num stk) (live-slots live)) + (save-opnd stk (opnd-needed opnd live) comment)) + (put-copy opnd stk var live comment)) +(define (all-args-trivial? l) + (if (null? l) + #t + (let ((arg (car (car l)))) + (or (eq? arg 'return) + (and (trivial? arg) (all-args-trivial? (cdr l))))))) +(define (every-trivial? l) + (or (null? l) (and (trivial? (car l)) (every-trivial? (cdr l))))) +(define (trivial? node) + (or (cst? node) + (ref? node) + (and (set? node) (trivial? (set-val node))) + (and (inlinable-app? node) (every-trivial? (app-args node))))) +(define (inlinable-app? node) + (if (app? node) + (let ((proc (node->proc (app-oper node)))) + (and proc + (let ((spec (specialize-for-call proc (node-decl node)))) + (and (proc-obj-inlinable spec) + (nb-args-conforms? + (length (app-args node)) + (proc-obj-call-pat spec)))))) + #f)) +(define (boolean-value? node) + (or (and (conj? node) + (boolean-value? (conj-pre node)) + (boolean-value? (conj-alt node))) + (and (disj? node) + (boolean-value? (disj-pre node)) + (boolean-value? (disj-alt node))) + (boolean-app? node))) +(define (boolean-app? node) + (if (app? node) + (let ((proc (node->proc (app-oper node)))) + (if proc (eq? (type-name (proc-obj-type proc)) 'boolean) #f)) + #f)) +(define (node->proc node) + (cond ((cst? node) (if (proc-obj? (cst-val node)) (cst-val node) #f)) + ((ref? node) + (if (global? (ref-var node)) + (target.prim-info* (var-name (ref-var node)) (node-decl node)) + #f)) + (else #f))) +(define (specialize-for-call proc decl) ((proc-obj-specialize proc) decl)) +(define (get-jump-state args pc) + (define (empty-node-list n) + (if (> n 0) (cons #f (empty-node-list (- n 1))) '())) + (let* ((fs (pcontext-fs pc)) + (slots-list (empty-node-list fs)) + (regs-list (empty-node-list target.nb-regs))) + (define (assign-node-to-loc var loc) + (let ((x (cond ((reg? loc) + (let ((i (reg-num loc))) + (if (<= i target.nb-regs) + (nth-after regs-list i) + (compiler-internal-error + "jump-state, reg out of bound in back-end's pcontext")))) + ((stk? loc) + (let ((i (stk-num loc))) + (if (<= i fs) + (nth-after slots-list (- i 1)) + (compiler-internal-error + "jump-state, stk out of bound in back-end's pcontext")))) + (else + (compiler-internal-error + "jump-state, loc other than reg or stk in back-end's pcontext"))))) + (if (not (car x)) + (set-car! x var) + (compiler-internal-error + "jump-state, duplicate location in back-end's pcontext")))) + (let loop ((l (pcontext-map pc))) + (if (not (null? l)) + (let* ((couple (car l)) (name (car couple)) (loc (cdr couple))) + (cond ((eq? name 'return) (assign-node-to-loc 'return loc)) + (else (assign-node-to-loc (list-ref args (- name 1)) loc))) + (loop (cdr l))))) + (vector slots-list regs-list))) +(define (jump-state-in-stk x) (vector-ref x 0)) +(define (jump-state-in-reg x) (vector-ref x 1)) +(define (arg-eval-order oper nodes) + (define (loop nodes pos part1 part2) + (cond ((null? nodes) + (let ((p1 (reverse part1)) (p2 (free-vars-order part2))) + (cond ((not oper) (append p1 p2)) + ((trivial? oper) + (append p1 p2 (list (cons oper 'operator)))) + (else (append (cons (cons oper 'operator) p1) p2))))) + ((not (car nodes)) (loop (cdr nodes) (+ pos 1) part1 part2)) + ((or (eq? (car nodes) 'return) (trivial? (car nodes))) + (loop (cdr nodes) + (+ pos 1) + part1 + (cons (cons (car nodes) pos) part2))) + (else + (loop (cdr nodes) + (+ pos 1) + (cons (cons (car nodes) pos) part1) + part2)))) + (loop nodes 0 '() '())) +(define (free-vars-order l) + (let ((bins '()) (ordered-args '())) + (define (free-v x) (if (eq? x 'return) (set-empty) (free-variables x))) + (define (add-to-bin! x) + (let ((y (assq x bins))) + (if y (set-cdr! y (+ (cdr y) 1)) (set! bins (cons (cons x 1) bins))))) + (define (payoff-if-removed node) + (let ((x (free-v node))) + (let loop ((l (set->list x)) (r 0)) + (if (null? l) + r + (let ((y (cdr (assq (car l) bins)))) + (loop (cdr l) (+ r (quotient 1000 (* y y))))))))) + (define (remove-free-vars! x) + (let loop ((l (set->list x))) + (if (not (null? l)) + (let ((y (assq (car l) bins))) + (set-cdr! y (- (cdr y) 1)) + (loop (cdr l)))))) + (define (find-max-payoff l thunk) + (if (null? l) + (thunk '() -1) + (find-max-payoff + (cdr l) + (lambda (best-arg best-payoff) + (let ((payoff (payoff-if-removed (car (car l))))) + (if (>= payoff best-payoff) + (thunk (car l) payoff) + (thunk best-arg best-payoff))))))) + (define (remove x l) + (cond ((null? l) '()) + ((eq? x (car l)) (cdr l)) + (else (cons (car l) (remove x (cdr l)))))) + (for-each + (lambda (x) (for-each add-to-bin! (set->list (free-v (car x))))) + l) + (let loop ((args l) (ordered-args '())) + (if (null? args) + (reverse ordered-args) + (find-max-payoff + args + (lambda (best-arg best-payoff) + (remove-free-vars! (free-v (car best-arg))) + (loop (remove best-arg args) (cons best-arg ordered-args)))))))) +(define (args-live-vars live order) + (cond ((null? order) live) + ((eq? (car (car order)) 'return) + (args-live-vars (set-adjoin live ret-var) (cdr order))) + (else + (args-live-vars + (set-union live (free-variables (car (car order)))) + (cdr order))))) +(define (stk-live-vars live slots why) + (cond ((null? slots) live) + ((not (car slots)) (stk-live-vars live (cdr slots) why)) + ((eq? (car slots) 'return) + (stk-live-vars + (if (eq? why 'tail) (set-adjoin live ret-var) live) + (cdr slots) + why)) + (else + (stk-live-vars + (set-union live (free-variables (car slots))) + (cdr slots) + why)))) +(define (gen-let vars vals node live why) + (let ((var-val-map (pair-up vars vals)) + (var-set (list->set vars)) + (all-live + (set-union + live + (free-variables node) + (apply set-union (map free-variables vals))))) + (define (var->val var) (cdr (assq var var-val-map))) + (define (proc-var? var) (prc? (var->val var))) + (define (closed-vars var const-proc-vars) + (set-difference + (not-constant-closed-vars (var->val var)) + const-proc-vars)) + (define (no-closed-vars? var const-proc-vars) + (set-empty? (closed-vars var const-proc-vars))) + (define (closed-vars? var const-proc-vars) + (not (no-closed-vars? var const-proc-vars))) + (define (compute-const-proc-vars proc-vars) + (let loop1 ((const-proc-vars proc-vars)) + (let ((new-const-proc-vars + (set-keep + (lambda (x) (no-closed-vars? x const-proc-vars)) + const-proc-vars))) + (if (not (set-equal? new-const-proc-vars const-proc-vars)) + (loop1 new-const-proc-vars) + const-proc-vars)))) + (let* ((proc-vars (set-keep proc-var? var-set)) + (const-proc-vars (compute-const-proc-vars proc-vars)) + (clo-vars + (set-keep (lambda (x) (closed-vars? x const-proc-vars)) proc-vars)) + (clo-vars-list (set->list clo-vars))) + (for-each + (lambda (proc-var) + (let ((label (schedule-gen-proc (var->val proc-var) '()))) + (add-known-proc (lbl-num label) (var->val proc-var)) + (add-constant-var proc-var label))) + (set->list const-proc-vars)) + (let ((non-clo-vars-list + (set->list + (set-keep + (lambda (var) + (and (not (set-member? var const-proc-vars)) + (not (set-member? var clo-vars)))) + vars))) + (liv (set-union + live + (apply set-union + (map (lambda (x) (closed-vars x const-proc-vars)) + clo-vars-list)) + (free-variables node)))) + (let loop2 ((vars* non-clo-vars-list)) + (if (not (null? vars*)) + (let* ((var (car vars*)) + (val (var->val var)) + (needed (vals-live-vars liv (map var->val (cdr vars*))))) + (if (var-useless? var) + (gen-node val needed 'side) + (save-val + (gen-node val needed 'need) + var + needed + (source-comment val))) + (loop2 (cdr vars*))))) + (if (pair? clo-vars-list) + (begin + (dealloc-slots (- nb-slots (stk-num (highest-live-slot liv)))) + (let loop3 ((l clo-vars-list)) + (if (not (null? l)) + (begin + (push-slot) + (let ((var (car l)) (slot (make-stk nb-slots))) + (put-var slot var) + (loop3 (cdr l)))))) + (bb-put-non-branch! + *bb* + (make-close + (map (lambda (var) + (let ((closed-list + (sort-variables + (set->list (closed-vars var const-proc-vars))))) + (if (null? closed-list) + (compiler-internal-error + "gen-let, no closed variables:" + (var-name var)) + (make-closure-parms + (var->opnd var) + (lbl-num (schedule-gen-proc + (var->val var) + closed-list)) + (map var->opnd closed-list))))) + clo-vars-list) + (current-frame liv) + (source-comment node))))) + (gen-node node live why))))) +(define (save-arg opnd var live comment) + (if (glo? opnd) + (add-constant-var var opnd) + (save-val opnd var live comment))) +(define (save-val opnd var live comment) + (cond ((or (obj? opnd) (lbl? opnd)) (add-constant-var var opnd)) + ((and (reg? opnd) (not (set-member? (reg-num opnd) (live-regs live)))) + (put-var opnd var)) + ((and (stk? opnd) (not (set-member? (stk-num opnd) (live-slots live)))) + (put-var opnd var)) + (else (save-in-slot opnd var live comment)))) +(define (save-in-slot opnd var live comment) + (let ((slot (lowest-dead-slot live))) (put-copy opnd slot var live comment))) +(define (save-var opnd var live comment) + (cond ((or (obj? opnd) (lbl? opnd)) (add-constant-var var opnd) var) + ((or (glo? opnd) (reg? opnd) (stk? opnd)) (get-var opnd)) + (else + (let ((dest (or (highest-dead-reg live) (lowest-dead-slot live)))) + (put-copy opnd dest var live comment) + var)))) +(define (put-copy opnd loc var live comment) + (if (and (stk? loc) (> (stk-num loc) nb-slots)) (push-slot)) + (if var (put-var loc var)) + (if (not (eq? opnd loc)) + (bb-put-non-branch! + *bb* + (make-copy + opnd + loc + (current-frame (if var (set-adjoin live var) live)) + comment)))) +(define (var-useless? var) + (and (set-empty? (var-refs var)) (set-empty? (var-sets var)))) +(define (vals-live-vars live vals) + (if (null? vals) + live + (vals-live-vars + (set-union live (free-variables (car vals))) + (cdr vals)))) +(define (gen-fut node live why) + (let* ((val (fut-val node)) + (clo-vars (not-constant-closed-vars val)) + (clo-vars-list (set->list clo-vars)) + (ret-var* (make-temp-var 0)) + (live-after live) + (live-starting-task + (set-adjoin (set-union live-after clo-vars) ret-var*)) + (task-lbl (bbs-new-lbl! *bbs*)) + (return-lbl (bbs-new-lbl! *bbs*))) + (save-regs (live-regs live-after) live-starting-task (source-comment node)) + (let ((frame-start (stk-num (highest-live-slot live-after)))) + (save-opnd-to-reg + (make-lbl return-lbl) + target.task-return + ret-var* + (set-remove live-starting-task ret-var*) + (source-comment node)) + (let loop1 ((l clo-vars-list) (i 0)) + (if (null? l) + (dealloc-slots (- nb-slots (+ frame-start i))) + (let ((var (car l)) (rest (cdr l))) + (if (memq var regs) + (loop1 rest i) + (let loop2 ((j (- target.nb-regs 1))) + (if (>= j 0) + (if (or (>= j (length regs)) + (not (set-member? + (list-ref regs j) + live-starting-task))) + (let ((reg (make-reg j))) + (put-copy + (var->opnd var) + reg + var + live-starting-task + (source-comment node)) + (loop1 rest i)) + (loop2 (- j 1))) + (let ((slot (make-stk (+ frame-start (+ i 1)))) + (needed (list->set rest))) + (if (and (or (> (stk-num slot) nb-slots) + (not (memq (list-ref + slots + (- nb-slots (stk-num slot))) + regs))) + (set-member? + (stk-num slot) + (live-slots needed))) + (save-opnd + slot + live-starting-task + (source-comment node))) + (put-copy + (var->opnd var) + slot + var + live-starting-task + (source-comment node)) + (loop1 rest (+ i 1))))))))) + (seal-bb (intrs-enabled? (node-decl node)) 'call) + (bb-put-branch! + *bb* + (make-jump + (make-lbl task-lbl) + #f + #f + (current-frame live-starting-task) + #f)) + (let ((task-context + (make-context + (- nb-slots frame-start) + (reverse (nth-after (reverse slots) frame-start)) + (cons ret-var (cdr regs)) + '() + poll + entry-bb)) + (return-context + (make-context + frame-start + (nth-after slots (- nb-slots frame-start)) + '() + closed + (return-poll poll) + entry-bb))) + (restore-context task-context) + (set! *bb* + (make-bb (make-label-task-entry + task-lbl + (current-frame live-starting-task) + (source-comment node)) + *bbs*)) + (gen-node val ret-var-set 'tail) + (let ((result-var (make-temp-var 'future))) + (restore-context return-context) + (put-var target.proc-result result-var) + (set! *bb* + (make-bb (make-label-task-return + return-lbl + (current-frame (set-adjoin live result-var)) + (source-comment node)) + *bbs*)) + (gen-return target.proc-result why node)))))) +(define prim-procs + '(("not" (1) #f 0 boolean) + ("boolean?" (1) #f 0 boolean) + ("eqv?" (2) #f 0 boolean) + ("eq?" (2) #f 0 boolean) + ("equal?" (2) #f 0 boolean) + ("pair?" (1) #f 0 boolean) + ("cons" (2) #f () pair) + ("car" (1) #f 0 (#f)) + ("cdr" (1) #f 0 (#f)) + ("set-car!" (2) #t (1) pair) + ("set-cdr!" (2) #t (1) pair) + ("caar" (1) #f 0 (#f)) + ("cadr" (1) #f 0 (#f)) + ("cdar" (1) #f 0 (#f)) + ("cddr" (1) #f 0 (#f)) + ("caaar" (1) #f 0 (#f)) + ("caadr" (1) #f 0 (#f)) + ("cadar" (1) #f 0 (#f)) + ("caddr" (1) #f 0 (#f)) + ("cdaar" (1) #f 0 (#f)) + ("cdadr" (1) #f 0 (#f)) + ("cddar" (1) #f 0 (#f)) + ("cdddr" (1) #f 0 (#f)) + ("caaaar" (1) #f 0 (#f)) + ("caaadr" (1) #f 0 (#f)) + ("caadar" (1) #f 0 (#f)) + ("caaddr" (1) #f 0 (#f)) + ("cadaar" (1) #f 0 (#f)) + ("cadadr" (1) #f 0 (#f)) + ("caddar" (1) #f 0 (#f)) + ("cadddr" (1) #f 0 (#f)) + ("cdaaar" (1) #f 0 (#f)) + ("cdaadr" (1) #f 0 (#f)) + ("cdadar" (1) #f 0 (#f)) + ("cdaddr" (1) #f 0 (#f)) + ("cddaar" (1) #f 0 (#f)) + ("cddadr" (1) #f 0 (#f)) + ("cdddar" (1) #f 0 (#f)) + ("cddddr" (1) #f 0 (#f)) + ("null?" (1) #f 0 boolean) + ("list?" (1) #f 0 boolean) + ("list" 0 #f () list) + ("length" (1) #f 0 integer) + ("append" 0 #f 0 list) + ("reverse" (1) #f 0 list) + ("list-ref" (2) #f 0 (#f)) + ("memq" (2) #f 0 list) + ("memv" (2) #f 0 list) + ("member" (2) #f 0 list) + ("assq" (2) #f 0 #f) + ("assv" (2) #f 0 #f) + ("assoc" (2) #f 0 #f) + ("symbol?" (1) #f 0 boolean) + ("symbol->string" (1) #f 0 string) + ("string->symbol" (1) #f 0 symbol) + ("number?" (1) #f 0 boolean) + ("complex?" (1) #f 0 boolean) + ("real?" (1) #f 0 boolean) + ("rational?" (1) #f 0 boolean) + ("integer?" (1) #f 0 boolean) + ("exact?" (1) #f 0 boolean) + ("inexact?" (1) #f 0 boolean) + ("=" 0 #f 0 boolean) + ("<" 0 #f 0 boolean) + (">" 0 #f 0 boolean) + ("<=" 0 #f 0 boolean) + (">=" 0 #f 0 boolean) + ("zero?" (1) #f 0 boolean) + ("positive?" (1) #f 0 boolean) + ("negative?" (1) #f 0 boolean) + ("odd?" (1) #f 0 boolean) + ("even?" (1) #f 0 boolean) + ("max" 1 #f 0 number) + ("min" 1 #f 0 number) + ("+" 0 #f 0 number) + ("*" 0 #f 0 number) + ("-" 1 #f 0 number) + ("/" 1 #f 0 number) + ("abs" (1) #f 0 number) + ("quotient" 1 #f 0 integer) + ("remainder" (2) #f 0 integer) + ("modulo" (2) #f 0 integer) + ("gcd" 1 #f 0 integer) + ("lcm" 1 #f 0 integer) + ("numerator" (1) #f 0 integer) + ("denominator" (1) #f 0 integer) + ("floor" (1) #f 0 integer) + ("ceiling" (1) #f 0 integer) + ("truncate" (1) #f 0 integer) + ("round" (1) #f 0 integer) + ("rationalize" (2) #f 0 number) + ("exp" (1) #f 0 number) + ("log" (1) #f 0 number) + ("sin" (1) #f 0 number) + ("cos" (1) #f 0 number) + ("tan" (1) #f 0 number) + ("asin" (1) #f 0 number) + ("acos" (1) #f 0 number) + ("atan" (1 2) #f 0 number) + ("sqrt" (1) #f 0 number) + ("expt" (2) #f 0 number) + ("make-rectangular" (2) #f 0 number) + ("make-polar" (2) #f 0 number) + ("real-part" (1) #f 0 real) + ("imag-part" (1) #f 0 real) + ("magnitude" (1) #f 0 real) + ("angle" (1) #f 0 real) + ("exact->inexact" (1) #f 0 number) + ("inexact->exact" (1) #f 0 number) + ("number->string" (1 2) #f 0 string) + ("string->number" (1 2) #f 0 number) + ("char?" (1) #f 0 boolean) + ("char=?" 0 #f 0 boolean) + ("char<?" 0 #f 0 boolean) + ("char>?" 0 #f 0 boolean) + ("char<=?" 0 #f 0 boolean) + ("char>=?" 0 #f 0 boolean) + ("char-ci=?" 0 #f 0 boolean) + ("char-ci<?" 0 #f 0 boolean) + ("char-ci>?" 0 #f 0 boolean) + ("char-ci<=?" 0 #f 0 boolean) + ("char-ci>=?" 0 #f 0 boolean) + ("char-alphabetic?" (1) #f 0 boolean) + ("char-numeric?" (1) #f 0 boolean) + ("char-whitespace?" (1) #f 0 boolean) + ("char-upper-case?" (1) #f 0 boolean) + ("char-lower-case?" (1) #f 0 boolean) + ("char->integer" (1) #f 0 integer) + ("integer->char" (1) #f 0 char) + ("char-upcase" (1) #f 0 char) + ("char-downcase" (1) #f 0 char) + ("string?" (1) #f 0 boolean) + ("make-string" (1 2) #f 0 string) + ("string" 0 #f 0 string) + ("string-length" (1) #f 0 integer) + ("string-ref" (2) #f 0 char) + ("string-set!" (3) #t 0 string) + ("string=?" 0 #f 0 boolean) + ("string<?" 0 #f 0 boolean) + ("string>?" 0 #f 0 boolean) + ("string<=?" 0 #f 0 boolean) + ("string>=?" 0 #f 0 boolean) + ("string-ci=?" 0 #f 0 boolean) + ("string-ci<?" 0 #f 0 boolean) + ("string-ci>?" 0 #f 0 boolean) + ("string-ci<=?" 0 #f 0 boolean) + ("string-ci>=?" 0 #f 0 boolean) + ("substring" (3) #f 0 string) + ("string-append" 0 #f 0 string) + ("vector?" (1) #f 0 boolean) + ("make-vector" (1 2) #f (1) vector) + ("vector" 0 #f () vector) + ("vector-length" (1) #f 0 integer) + ("vector-ref" (2) #f 0 (#f)) + ("vector-set!" (3) #t (1 2) vector) + ("procedure?" (1) #f 0 boolean) + ("apply" 2 #t 0 (#f)) + ("map" 2 #t 0 list) + ("for-each" 2 #t 0 #f) + ("call-with-current-continuation" (1) #t 0 (#f)) + ("call-with-input-file" (2) #t 0 (#f)) + ("call-with-output-file" (2) #t 0 (#f)) + ("input-port?" (1) #f 0 boolean) + ("output-port?" (1) #f 0 boolean) + ("current-input-port" (0) #f 0 port) + ("current-output-port" (0) #f 0 port) + ("open-input-file" (1) #t 0 port) + ("open-output-file" (1) #t 0 port) + ("close-input-port" (1) #t 0 #f) + ("close-output-port" (1) #t 0 #f) + ("eof-object?" (1) #f 0 boolean) + ("read" (0 1) #t 0 #f) + ("read-char" (0 1) #t 0 #f) + ("peek-char" (0 1) #t 0 #f) + ("write" (0 1) #t 0 #f) + ("display" (0 1) #t 0 #f) + ("newline" (0 1) #t 0 #f) + ("write-char" (1 2) #t 0 #f) + ("list-tail" (2) #f 0 (#f)) + ("string->list" (1) #f 0 list) + ("list->string" (1) #f 0 string) + ("string-copy" (1) #f 0 string) + ("string-fill!" (2) #t 0 string) + ("vector->list" (1) #f 0 list) + ("list->vector" (1) #f 0 vector) + ("vector-fill!" (2) #t 0 vector) + ("force" (1) #t 0 #f) + ("with-input-from-file" (2) #t 0 (#f)) + ("with-output-to-file" (2) #t 0 (#f)) + ("char-ready?" (0 1) #f 0 boolean) + ("load" (1) #t 0 (#f)) + ("transcript-on" (1) #t 0 #f) + ("transcript-off" (0) #t 0 #f) + ("touch" (1) #t 0 #f) + ("##type" (1) #f () integer) + ("##type-cast" (2) #f () (#f)) + ("##subtype" (1) #f () integer) + ("##subtype-set!" (2) #t () #f) + ("##not" (1) #f () boolean) + ("##null?" (1) #f () boolean) + ("##unassigned?" (1) #f () boolean) + ("##unbound?" (1) #f () boolean) + ("##eq?" (2) #f () boolean) + ("##fixnum?" (1) #f () boolean) + ("##flonum?" (1) #f () boolean) + ("##special?" (1) #f () boolean) + ("##pair?" (1) #f () boolean) + ("##subtyped?" (1) #f () boolean) + ("##procedure?" (1) #f () boolean) + ("##placeholder?" (1) #f () boolean) + ("##vector?" (1) #f () boolean) + ("##symbol?" (1) #f () boolean) + ("##ratnum?" (1) #f () boolean) + ("##cpxnum?" (1) #f () boolean) + ("##string?" (1) #f () boolean) + ("##bignum?" (1) #f () boolean) + ("##char?" (1) #f () boolean) + ("##closure?" (1) #f () boolean) + ("##subprocedure?" (1) #f () boolean) + ("##return-dynamic-env-bind?" (1) #f () boolean) + ("##fixnum.+" 0 #f () integer) + ("##fixnum.*" 0 #f () integer) + ("##fixnum.-" 1 #f () integer) + ("##fixnum.quotient" (2) #f () integer) + ("##fixnum.remainder" (2) #f () integer) + ("##fixnum.modulo" (2) #f () integer) + ("##fixnum.logior" 0 #f () integer) + ("##fixnum.logxor" 0 #f () integer) + ("##fixnum.logand" 0 #f () integer) + ("##fixnum.lognot" (1) #f () integer) + ("##fixnum.ash" (2) #f () integer) + ("##fixnum.lsh" (2) #f () integer) + ("##fixnum.zero?" (1) #f () boolean) + ("##fixnum.positive?" (1) #f () boolean) + ("##fixnum.negative?" (1) #f () boolean) + ("##fixnum.odd?" (1) #f () boolean) + ("##fixnum.even?" (1) #f () boolean) + ("##fixnum.=" 0 #f () boolean) + ("##fixnum.<" 0 #f () boolean) + ("##fixnum.>" 0 #f () boolean) + ("##fixnum.<=" 0 #f () boolean) + ("##fixnum.>=" 0 #f () boolean) + ("##flonum.->fixnum" (1) #f () integer) + ("##flonum.<-fixnum" (1) #f () real) + ("##flonum.+" 0 #f () real) + ("##flonum.*" 0 #f () real) + ("##flonum.-" 1 #f () real) + ("##flonum./" 1 #f () real) + ("##flonum.abs" (1) #f () real) + ("##flonum.truncate" (1) #f () real) + ("##flonum.round" (1) #f () real) + ("##flonum.exp" (1) #f () real) + ("##flonum.log" (1) #f () real) + ("##flonum.sin" (1) #f () real) + ("##flonum.cos" (1) #f () real) + ("##flonum.tan" (1) #f () real) + ("##flonum.asin" (1) #f () real) + ("##flonum.acos" (1) #f () real) + ("##flonum.atan" (1) #f () real) + ("##flonum.sqrt" (1) #f () real) + ("##flonum.zero?" (1) #f () boolean) + ("##flonum.positive?" (1) #f () boolean) + ("##flonum.negative?" (1) #f () boolean) + ("##flonum.=" 0 #f () boolean) + ("##flonum.<" 0 #f () boolean) + ("##flonum.>" 0 #f () boolean) + ("##flonum.<=" 0 #f () boolean) + ("##flonum.>=" 0 #f () boolean) + ("##char=?" 0 #f () boolean) + ("##char<?" 0 #f () boolean) + ("##char>?" 0 #f () boolean) + ("##char<=?" 0 #f () boolean) + ("##char>=?" 0 #f () boolean) + ("##cons" (2) #f () pair) + ("##set-car!" (2) #t () pair) + ("##set-cdr!" (2) #t () pair) + ("##car" (1) #f () (#f)) + ("##cdr" (1) #f () (#f)) + ("##caar" (1) #f () (#f)) + ("##cadr" (1) #f () (#f)) + ("##cdar" (1) #f () (#f)) + ("##cddr" (1) #f () (#f)) + ("##caaar" (1) #f () (#f)) + ("##caadr" (1) #f () (#f)) + ("##cadar" (1) #f () (#f)) + ("##caddr" (1) #f () (#f)) + ("##cdaar" (1) #f () (#f)) + ("##cdadr" (1) #f () (#f)) + ("##cddar" (1) #f () (#f)) + ("##cdddr" (1) #f () (#f)) + ("##caaaar" (1) #f () (#f)) + ("##caaadr" (1) #f () (#f)) + ("##caadar" (1) #f () (#f)) + ("##caaddr" (1) #f () (#f)) + ("##cadaar" (1) #f () (#f)) + ("##cadadr" (1) #f () (#f)) + ("##caddar" (1) #f () (#f)) + ("##cadddr" (1) #f () (#f)) + ("##cdaaar" (1) #f () (#f)) + ("##cdaadr" (1) #f () (#f)) + ("##cdadar" (1) #f () (#f)) + ("##cdaddr" (1) #f () (#f)) + ("##cddaar" (1) #f () (#f)) + ("##cddadr" (1) #f () (#f)) + ("##cdddar" (1) #f () (#f)) + ("##cddddr" (1) #f () (#f)) + ("##make-cell" (1) #f () pair) + ("##cell-ref" (1) #f () (#f)) + ("##cell-set!" (2) #t () pair) + ("##vector" 0 #f () vector) + ("##make-vector" (2) #f () vector) + ("##vector-length" (1) #f () integer) + ("##vector-ref" (2) #f () (#f)) + ("##vector-set!" (3) #t () vector) + ("##vector-shrink!" (2) #t () vector) + ("##string" 0 #f () string) + ("##make-string" (2) #f () string) + ("##string-length" (1) #f () integer) + ("##string-ref" (2) #f () char) + ("##string-set!" (3) #t () string) + ("##string-shrink!" (2) #t () string) + ("##vector8" 0 #f () string) + ("##make-vector8" (2) #f () string) + ("##vector8-length" (1) #f () integer) + ("##vector8-ref" (2) #f () integer) + ("##vector8-set!" (3) #t () string) + ("##vector8-shrink!" (2) #t () string) + ("##vector16" 0 #f () string) + ("##make-vector16" (2) #f () string) + ("##vector16-length" (1) #f () integer) + ("##vector16-ref" (2) #f () integer) + ("##vector16-set!" (3) #t () string) + ("##vector16-shrink!" (2) #t () string) + ("##closure-code" (1) #f () #f) + ("##closure-ref" (2) #f () (#f)) + ("##closure-set!" (3) #t () #f) + ("##subprocedure-id" (1) #f () #f) + ("##subprocedure-parent" (1) #f () #f) + ("##return-fs" (1) #f () #f) + ("##return-link" (1) #f () #f) + ("##procedure-info" (1) #f () #f) + ("##pstate" (0) #f () #f) + ("##make-placeholder" (1) #f 0 (#f)) + ("##touch" (1) #t 0 #f) + ("##apply" (2) #t () (#f)) + ("##call-with-current-continuation" (1) #t () (#f)) + ("##global-var" (1) #t () #f) + ("##global-var-ref" (1) #f () (#f)) + ("##global-var-set!" (2) #t () #f) + ("##atomic-car" (1) #f () (#f)) + ("##atomic-cdr" (1) #f () (#f)) + ("##atomic-set-car!" (2) #t () pair) + ("##atomic-set-cdr!" (2) #t () pair) + ("##atomic-set-car-if-eq?!" (3) #t () boolean) + ("##atomic-set-cdr-if-eq?!" (3) #t () boolean) + ("##quasi-append" 0 #f 0 list) + ("##quasi-list" 0 #f () list) + ("##quasi-cons" (2) #f () pair) + ("##quasi-list->vector" (1) #f 0 vector) + ("##case-memv" (2) #f 0 list))) +(define ofile-version-major 5) +(define ofile-version-minor 0) +(define prim-proc-prefix 1) +(define user-proc-prefix 2) +(define pair-prefix 3) +(define flonum-prefix 4) +(define local-object-bits -524281) +(define symbol-object-bits -393209) +(define prim-proc-object-bits -262137) +(define padding-tag 0) +(define end-of-code-tag 32768) +(define m68020-proc-code-tag 32769) +(define m68881-proc-code-tag 32770) +(define stat-tag 32771) +(define global-var-ref-tag 34816) +(define global-var-set-tag 36864) +(define global-var-ref-jump-tag 38912) +(define prim-proc-ref-tag 40960) +(define local-proc-ref-tag 49152) +(define long-index-mask 16383) +(define word-index-mask 2047) +(define (ofile.begin! filename add-obj) + (set! ofile-add-obj add-obj) + (set! ofile-syms (queue-empty)) +; (set! *ofile-port1* (open-output-file (string-append filename ".O"))) + (if ofile-asm? + (begin + (set! *ofile-port2* + (asm-open-output-file (string-append filename ".asm"))) + (set! *ofile-pos* 0))) + (ofile-word ofile-version-major) + (ofile-word ofile-version-minor) + '()) +(define (ofile.end!) + (ofile-line "") +; (close-output-port *ofile-port1*) + (if ofile-asm? (asm-close-output-port *ofile-port2*)) + '()) +(define asm-output '()) +(define asm-line '()) +(define (asm-open-output-file filename) + (set! asm-output '()) + (set! asm-line '())) +(define (asm-close-output-port asm-port) #f) +(define (asm-newline asm-port) (asm-display char-newline asm-port)) +(define (asm-display obj asm-port) + (if (eqv? obj char-newline) + (begin + (set! asm-output + (cons (apply string-append (reverse asm-line)) asm-output)) + (set! asm-line '())) + (set! asm-line + (cons (cond ((string? obj) obj) + ((char? obj) (if (eqv? obj char-tab) " " (string obj))) + ((number? obj) (number->string obj)) + (else (compiler-internal-error "asm-display" obj))) + asm-line)))) +(define (asm-output-get) (reverse asm-output)) +(define *ofile-port1* '()) +(define *ofile-port2* '()) +(define *ofile-pos* '()) +(define ofile-nl char-newline) +(define ofile-tab char-tab) +(define ofile-asm? '()) +(set! ofile-asm? '()) +(define ofile-asm-bits? '()) +(set! ofile-asm-bits? #f) +(define ofile-asm-gvm? '()) +(set! ofile-asm-gvm? #f) +(define ofile-stats? '()) +(set! ofile-stats? '()) +(define ofile-add-obj '()) +(set! ofile-add-obj '()) +(define ofile-syms '()) +(set! ofile-syms '()) +(define (ofile-word n) + (let ((n (modulo n 65536))) + (if (and ofile-asm? ofile-asm-bits?) + (let () + (define (ofile-display x) + (asm-display x *ofile-port2*) + (cond ((eq? x ofile-nl) (set! *ofile-pos* 0)) + ((eq? x ofile-tab) + (set! *ofile-pos* (* (quotient (+ *ofile-pos* 8) 8) 8))) + (else (set! *ofile-pos* (+ *ofile-pos* (string-length x)))))) + (if (> *ofile-pos* 64) (ofile-display ofile-nl)) + (if (= *ofile-pos* 0) (ofile-display " .word") (ofile-display ",")) + (ofile-display ofile-tab) + (let ((s (make-string 6 #\0))) + (string-set! s 1 #\x) + (let loop ((i 5) (n n)) + (if (> n 0) + (begin + (string-set! + s + i + (string-ref "0123456789ABCDEF" (remainder n 16))) + (loop (- i 1) (quotient n 16))))) + (ofile-display s)))) +' (write-word n *ofile-port1*))) +(define (ofile-long x) (ofile-word (upper-16bits x)) (ofile-word x)) +(define (ofile-string s) + (let ((len (string-length s))) + (define (ref i) (if (>= i len) 0 (character-encoding (string-ref s i)))) + (let loop ((i 0)) + (if (< i len) + (begin + (ofile-word (+ (* (ref i) 256) (ref (+ i 1)))) + (loop (+ i 2))))) + (if (= (remainder len 2) 0) (ofile-word 0)))) +(define (ofile-wsym tag name) + (let ((n (string-pos-in-list name (queue->list ofile-syms)))) + (if n + (ofile-word (+ tag n)) + (let ((m (length (queue->list ofile-syms)))) + (queue-put! ofile-syms name) + (ofile-word (+ tag word-index-mask)) + (ofile-string name))))) +(define (ofile-lsym tag name) + (let ((n (string-pos-in-list name (queue->list ofile-syms)))) + (if n + (ofile-long (+ tag (* n 8))) + (let ((m (length (queue->list ofile-syms)))) + (queue-put! ofile-syms name) + (ofile-long (+ tag (* long-index-mask 8))) + (ofile-string name))))) +(define (ofile-ref obj) + (let ((n (obj-encoding obj))) + (if n + (ofile-long n) + (if (symbol-object? obj) + (begin (ofile-lsym symbol-object-bits (symbol->string obj))) + (let ((m (ofile-add-obj obj))) + (if m + (ofile-long (+ local-object-bits (* m 8))) + (begin + (ofile-lsym + prim-proc-object-bits + (proc-obj-name obj))))))))) +(define (ofile-prim-proc s) + (ofile-long prim-proc-prefix) + (ofile-wsym 0 s) + (ofile-comment (list "| #[primitive " s "] ="))) +(define (ofile-user-proc) (ofile-long user-proc-prefix)) +(define (ofile-line s) + (if ofile-asm? + (begin + (if (> *ofile-pos* 0) (asm-newline *ofile-port2*)) + (asm-display s *ofile-port2*) + (asm-newline *ofile-port2*) + (set! *ofile-pos* 0)))) +(define (ofile-tabs-to n) + (let loop () + (if (< *ofile-pos* n) + (begin + (asm-display ofile-tab *ofile-port2*) + (set! *ofile-pos* (* (quotient (+ *ofile-pos* 8) 8) 8)) + (loop))))) +(define (ofile-comment l) + (if ofile-asm? + (let () + (if ofile-asm-bits? + (begin (ofile-tabs-to 32) (asm-display "|" *ofile-port2*))) + (for-each (lambda (x) (asm-display x *ofile-port2*)) l) + (asm-newline *ofile-port2*) + (set! *ofile-pos* 0)))) +(define (ofile-gvm-instr code) + (if (and ofile-asm? ofile-asm-gvm?) + (let ((gvm-instr (code-gvm-instr code)) (sn (code-slots-needed code))) + (if (> *ofile-pos* 0) + (begin (asm-newline *ofile-port2*) (set! *ofile-pos* 0))) + (if ofile-asm-bits? (ofile-tabs-to 32)) + (asm-display "| GVM: [" *ofile-port2*) + (asm-display sn *ofile-port2*) + (asm-display "] " *ofile-port2*) + (asm-newline *ofile-port2*) + (set! *ofile-pos* 0)))) +(define (ofile-stat stat) + (define (obj->string x) + (cond ((string? x) x) + ((symbol-object? x) (symbol->string x)) + ((number? x) (number->string x)) + ((false-object? x) "#f") + ((eq? x #t) "#t") + ((null? x) "()") + ((pair? x) + (let loop ((l1 (cdr x)) (l2 (list (obj->string (car x)) "("))) + (cond ((pair? l1) + (loop (cdr l1) + (cons (obj->string (car l1)) (cons " " l2)))) + ((null? l1) (apply string-append (reverse (cons ")" l2)))) + (else + (apply string-append + (reverse (cons ")" + (cons (obj->string l1) + (cons " . " l2))))))))) + (else + (compiler-internal-error + "ofile-stat, can't convert to string 'x'" + x)))) + (ofile-string (obj->string stat))) +(define (upper-16bits x) + (cond ((>= x 0) (quotient x 65536)) + ((>= x (- 65536)) -1) + (else (- (quotient (+ x 65537) 65536) 2)))) +(define type-fixnum 0) +(define type-flonum 1) +(define type-special 7) +(define type-pair 4) +(define type-placeholder 5) +(define type-subtyped 3) +(define type-procedure 2) +(define subtype-vector 0) +(define subtype-symbol 1) +(define subtype-port 2) +(define subtype-ratnum 3) +(define subtype-cpxnum 4) +(define subtype-string 16) +(define subtype-bignum 17) +(define data-false (- 33686019)) +(define data-null (- 67372037)) +(define data-true -2) +(define data-undef -3) +(define data-unass -4) +(define data-unbound -5) +(define data-eof -6) +(define data-max-fixnum 268435455) +(define data-min-fixnum (- 268435456)) +(define (make-encoding data type) (+ (* data 8) type)) +(define (obj-type obj) + (cond ((false-object? obj) 'special) + ((undef-object? obj) 'special) + ((symbol-object? obj) 'subtyped) + ((proc-obj? obj) 'procedure) + ((eq? obj #t) 'special) + ((null? obj) 'special) + ((pair? obj) 'pair) + ((number? obj) + (cond ((and (integer? obj) + (exact? obj) + (>= obj data-min-fixnum) + (<= obj data-max-fixnum)) + 'fixnum) + ( +#t +;; (and (inexact? (real-part obj)) +;; (zero? (imag-part obj)) +;; (exact? (imag-part obj))) + 'flonum) + (else 'subtyped))) + ((char? obj) 'special) + (else 'subtyped))) +(define (obj-subtype obj) + (cond ((symbol-object? obj) 'symbol) + ((number? obj) + (cond ((and (integer? obj) (exact? obj)) 'bignum) + ((and (rational? obj) (exact? obj)) 'ratnum) + (else 'cpxnum))) + ((vector? obj) 'vector) + ((string? obj) 'string) + (else + (compiler-internal-error "obj-subtype, unknown object 'obj'" obj)))) +(define (obj-type-tag obj) + (case (obj-type obj) + ((fixnum) type-fixnum) + ((flonum) type-flonum) + ((special) type-special) + ((pair) type-pair) + ((subtyped) type-subtyped) + ((procedure) type-procedure) + (else (compiler-internal-error "obj-type-tag, unknown object 'obj'" obj)))) +(define (obj-encoding obj) + (case (obj-type obj) + ((fixnum) (make-encoding obj type-fixnum)) + ((special) + (make-encoding + (cond ((false-object? obj) data-false) + ((undef-object? obj) data-undef) + ((eq? obj #t) data-true) + ((null? obj) data-null) + ((char? obj) (character-encoding obj)) + (else + (compiler-internal-error + "obj-encoding, unknown SPECIAL object 'obj'" + obj))) + type-special)) + (else #f))) +(define bits-false (make-encoding data-false type-special)) +(define bits-null (make-encoding data-null type-special)) +(define bits-true (make-encoding data-true type-special)) +(define bits-unass (make-encoding data-unass type-special)) +(define bits-unbound (make-encoding data-unbound type-special)) +(define (asm.begin!) + (set! asm-code-queue (queue-empty)) + (set! asm-const-queue (queue-empty)) + '()) +(define (asm.end! debug-info) + (asm-assemble! debug-info) + (set! asm-code-queue '()) + (set! asm-const-queue '()) + '()) +(define asm-code-queue '()) +(define asm-const-queue '()) +(define (asm-word x) (queue-put! asm-code-queue (modulo x 65536))) +(define (asm-long x) (asm-word (upper-16bits x)) (asm-word x)) +(define (asm-label lbl label-descr) + (queue-put! asm-code-queue (cons 'label (cons lbl label-descr)))) +(define (asm-comment x) (queue-put! asm-code-queue (cons 'comment x))) +(define (asm-align n offset) + (queue-put! asm-code-queue (cons 'align (cons n offset)))) +(define (asm-ref-glob glob) + (queue-put! + asm-code-queue + (cons 'ref-glob (symbol->string (glob-name glob))))) +(define (asm-set-glob glob) + (queue-put! + asm-code-queue + (cons 'set-glob (symbol->string (glob-name glob))))) +(define (asm-ref-glob-jump glob) + (queue-put! + asm-code-queue + (cons 'ref-glob-jump (symbol->string (glob-name glob))))) +(define (asm-proc-ref num offset) + (queue-put! asm-code-queue (cons 'proc-ref (cons num offset)))) +(define (asm-prim-ref proc offset) + (queue-put! + asm-code-queue + (cons 'prim-ref (cons (proc-obj-name proc) offset)))) +(define (asm-m68020-proc) (queue-put! asm-code-queue '(m68020-proc))) +(define (asm-m68881-proc) (queue-put! asm-code-queue '(m68881-proc))) +(define (asm-stat x) (queue-put! asm-code-queue (cons 'stat x))) +(define (asm-brel type lbl) + (queue-put! asm-code-queue (cons 'brab (cons type lbl)))) +(define (asm-wrel lbl offs) + (queue-put! asm-code-queue (cons 'wrel (cons lbl offs)))) +(define (asm-lrel lbl offs n) + (queue-put! asm-code-queue (cons 'lrel (cons lbl (cons offs n))))) +(define (asm-assemble! debug-info) + (define header-offset 2) + (define ref-glob-len 2) + (define set-glob-len 10) + (define ref-glob-jump-len 2) + (define proc-ref-len 4) + (define prim-ref-len 4) + (define stat-len 4) + (define (padding loc n offset) (modulo (- offset loc) n)) + (queue-put! asm-const-queue debug-info) + (asm-align 4 0) + (emit-label const-lbl) + (let ((code-list (queue->list asm-code-queue)) + (const-list (queue->list asm-const-queue))) + (let* ((fix-list + (let loop ((l code-list) (len header-offset) (x '())) + (if (null? l) + (reverse x) + (let ((part (car l)) (rest (cdr l))) + (if (pair? part) + (case (car part) + ((label align brab) + (loop rest 0 (cons (cons len part) x))) + ((wrel) (loop rest (+ len 2) x)) + ((lrel) (loop rest (+ len 4) x)) + ((ref-glob) (loop rest (+ len ref-glob-len) x)) + ((set-glob) (loop rest (+ len set-glob-len) x)) + ((ref-glob-jump) + (loop rest (+ len ref-glob-jump-len) x)) + ((proc-ref) (loop rest (+ len proc-ref-len) x)) + ((prim-ref) (loop rest (+ len prim-ref-len) x)) + ((stat) (loop rest (+ len stat-len) x)) + ((comment m68020-proc m68881-proc) (loop rest len x)) + (else + (compiler-internal-error + "asm-assemble!, unknown code list element" + part))) + (loop rest (+ len 2) x)))))) + (lbl-list + (let loop ((l fix-list) (x '())) + (if (null? l) + x + (let ((part (cdar l)) (rest (cdr l))) + (if (eq? (car part) 'label) + (loop rest (cons (cons (cadr part) part) x)) + (loop rest x))))))) + (define (replace-lbl-refs-by-pointer-to-label) + (let loop ((l code-list)) + (if (not (null? l)) + (let ((part (car l)) (rest (cdr l))) + (if (pair? part) + (case (car part) + ((brab) + (set-cdr! (cdr part) (cdr (assq (cddr part) lbl-list)))) + ((wrel) + (set-car! (cdr part) (cdr (assq (cadr part) lbl-list)))) + ((lrel) + (set-car! + (cdr part) + (cdr (assq (cadr part) lbl-list)))))) + (loop rest))))) + (define (assign-loc-to-labels) + (let loop ((l fix-list) (loc 0)) + (if (not (null? l)) + (let* ((first (car l)) + (rest (cdr l)) + (len (car first)) + (cur-loc (+ loc len)) + (part (cdr first))) + (case (car part) + ((label) + (if (cddr part) + (vector-set! + (cddr part) + 0 + (quotient (- cur-loc header-offset) 8))) + (set-car! (cdr part) cur-loc) + (loop rest cur-loc)) + ((align) + (loop rest + (+ cur-loc + (padding cur-loc (cadr part) (cddr part))))) + ((brab) (loop rest (+ cur-loc 2))) + ((braw) (loop rest (+ cur-loc 4))) + (else + (compiler-internal-error + "assign-loc-to-labels, unknown code list element" + part))))))) + (define (branch-tensioning-pass) + (assign-loc-to-labels) + (let loop ((changed? #f) (l fix-list) (loc 0)) + (if (null? l) + (if changed? (branch-tensioning-pass)) + (let* ((first (car l)) + (rest (cdr l)) + (len (car first)) + (cur-loc (+ loc len)) + (part (cdr first))) + (case (car part) + ((label) (loop changed? rest cur-loc)) + ((align) + (loop changed? + rest + (+ cur-loc + (padding cur-loc (cadr part) (cddr part))))) + ((brab) + (let ((dist (- (cadr (cddr part)) (+ cur-loc 2)))) + (if (or (< dist -128) (> dist 127) (= dist 0)) + (begin + (set-car! part 'braw) + (loop #t rest (+ cur-loc 2))) + (loop changed? rest (+ cur-loc 2))))) + ((braw) (loop changed? rest (+ cur-loc 4))) + (else + (compiler-internal-error + "branch-tensioning-pass, unknown code list element" + part))))))) + (define (write-block start-loc end-loc start end) + (if (> end-loc start-loc) + (ofile-word (quotient (- end-loc start-loc) 2))) + (let loop ((loc start-loc) (l start)) + (if (not (eq? l end)) + (let ((part (car l)) (rest (cdr l))) + (if (pair? part) + (case (car part) + ((label) (loop loc rest)) + ((align) + (let ((n (padding loc (cadr part) (cddr part)))) + (let pad ((i 0)) + (if (< i n) + (begin (ofile-word 0) (pad (+ i 2))) + (loop (+ loc n) rest))))) + ((brab) + (let ((dist (- (cadr (cddr part)) (+ loc 2)))) + (ofile-word (+ (cadr part) (modulo dist 256))) + (loop (+ loc 2) rest))) + ((braw) + (let ((dist (- (cadr (cddr part)) (+ loc 2)))) + (ofile-word (cadr part)) + (ofile-word (modulo dist 65536)) + (loop (+ loc 4) rest))) + ((wrel) + (let ((dist (+ (- (cadr (cadr part)) loc) (cddr part)))) + (ofile-word (modulo dist 65536)) + (loop (+ loc 2) rest))) + ((lrel) + (let ((dist (+ (- (cadr (cadr part)) loc) + (caddr part)))) + (ofile-long (+ (* dist 65536) (cdddr part))) + (loop (+ loc 4) rest))) + ((comment) + (let ((x (cdr part))) + (if (pair? x) (ofile-comment x) (ofile-gvm-instr x)) + (loop loc rest)))) + (begin (ofile-word part) (loop (+ loc 2) rest))))))) + (define (write-code) + (let ((proc-len + (+ (cadr (cdr (assq const-lbl lbl-list))) + (* (length const-list) 4)))) + (if (>= proc-len 32768) + (compiler-limitation-error + "procedure is too big (32K bytes limit per procedure)")) + (ofile-word (+ 32768 proc-len))) + (let loop1 ((start code-list) (start-loc header-offset)) + (let loop2 ((end start) (loc start-loc)) + (if (null? end) + (write-block start-loc loc start end) + (let ((part (car end)) (rest (cdr end))) + (if (pair? part) + (case (car part) + ((label comment) (loop2 rest loc)) + ((align) + (loop2 rest + (+ loc (padding loc (cadr part) (cddr part))))) + ((brab wrel) (loop2 rest (+ loc 2))) + ((braw) (loop2 rest (+ loc 4))) + ((lrel) (loop2 rest (+ loc 4))) + (else + (write-block start-loc loc start end) + (case (car part) + ((ref-glob) + (ofile-wsym global-var-ref-tag (cdr part)) + (loop1 rest (+ loc ref-glob-len))) + ((set-glob) + (ofile-wsym global-var-set-tag (cdr part)) + (loop1 rest (+ loc set-glob-len))) + ((ref-glob-jump) + (ofile-wsym global-var-ref-jump-tag (cdr part)) + (loop1 rest (+ loc ref-glob-jump-len))) + ((proc-ref) + (ofile-word (+ local-proc-ref-tag (cadr part))) + (ofile-word (cddr part)) + (loop1 rest (+ loc proc-ref-len))) + ((prim-ref) + (ofile-wsym prim-proc-ref-tag (cadr part)) + (ofile-word (cddr part)) + (loop1 rest (+ loc prim-ref-len))) + ((m68020-proc) + (ofile-word m68020-proc-code-tag) + (loop1 rest loc)) + ((m68881-proc) + (ofile-word m68881-proc-code-tag) + (loop1 rest loc)) + ((stat) + (ofile-word stat-tag) + (ofile-stat (cdr part)) + (loop1 rest (+ loc stat-len)))))) + (loop2 rest (+ loc 2))))))) + (ofile-word end-of-code-tag) + (for-each ofile-ref const-list) + (ofile-long (obj-encoding (+ (length const-list) 1)))) + (replace-lbl-refs-by-pointer-to-label) + (branch-tensioning-pass) + (write-code)))) +(define const-lbl 0) +(define (identical-opnd68? opnd1 opnd2) (eqv? opnd1 opnd2)) +(define (reg68? x) (or (dreg? x) (areg? x))) +(define (make-dreg num) num) +(define (dreg? x) (and (integer? x) (>= x 0) (< x 8))) +(define (dreg-num x) x) +(define (make-areg num) (+ num 8)) +(define (areg? x) (and (integer? x) (>= x 8) (< x 16))) +(define (areg-num x) (- x 8)) +(define (make-ind areg) (+ areg 8)) +(define (ind? x) (and (integer? x) (>= x 16) (< x 24))) +(define (ind-areg x) (- x 8)) +(define (make-pinc areg) (+ areg 16)) +(define (pinc? x) (and (integer? x) (>= x 24) (< x 32))) +(define (pinc-areg x) (- x 16)) +(define (make-pdec areg) (+ areg 24)) +(define (pdec? x) (and (integer? x) (>= x 32) (< x 40))) +(define (pdec-areg x) (- x 24)) +(define (make-disp areg offset) (+ (+ areg 32) (* (modulo offset 65536) 8))) +(define (disp? x) (and (integer? x) (>= x 40) (< x 524328))) +(define (disp-areg x) (+ (remainder x 8) 8)) +(define (disp-offset x) + (- (modulo (+ (quotient (- x 40) 8) 32768) 65536) 32768)) +(define (make-disp* areg offset) + (if (= offset 0) (make-ind areg) (make-disp areg offset))) +(define (disp*? x) (or (ind? x) (disp? x))) +(define (disp*-areg x) (if (ind? x) (ind-areg x) (disp-areg x))) +(define (disp*-offset x) (if (ind? x) 0 (disp-offset x))) +(define (make-inx areg ireg offset) + (+ (+ areg 524320) (* ireg 8) (* (modulo offset 256) 128))) +(define (inx? x) (and (integer? x) (>= x 524328) (< x 557096))) +(define (inx-areg x) (+ (remainder (- x 524328) 8) 8)) +(define (inx-ireg x) (quotient (remainder (- x 524328) 128) 8)) +(define (inx-offset x) + (- (modulo (+ (quotient (- x 524328) 128) 128) 256) 128)) +(define (make-freg num) (+ 557096 num)) +(define (freg? x) (and (integer? x) (>= x 557096) (< x 557104))) +(define (freg-num x) (- x 557096)) +(define (make-pcr lbl offset) + (+ 557104 (+ (modulo offset 65536) (* lbl 65536)))) +(define (pcr? x) (and (integer? x) (>= x 557104))) +(define (pcr-lbl x) (quotient (- x 557104) 65536)) +(define (pcr-offset x) (- (modulo (- x 524336) 65536) 32768)) +(define (make-imm val) (if (< val 0) (* val 2) (- -1 (* val 2)))) +(define (imm? x) (and (integer? x) (< x 0))) +(define (imm-val x) (if (even? x) (quotient x 2) (- (quotient x 2)))) +(define (make-glob name) name) +(define (glob? x) (symbol? x)) +(define (glob-name x) x) +(define (make-frame-base-rel slot) (make-disp sp-reg slot)) +(define (frame-base-rel? x) + (and (disp? x) (identical-opnd68? sp-reg (disp-areg x)))) +(define (frame-base-rel-slot x) (disp-offset x)) +(define (make-reg-list regs) regs) +(define (reg-list? x) (or (pair? x) (null? x))) +(define (reg-list-regs x) x) +(define first-dtemp 0) +(define gvm-reg1 1) +(define poll-timer-reg (make-dreg 5)) +(define null-reg (make-dreg 6)) +(define placeholder-reg (make-dreg 6)) +(define false-reg (make-dreg 7)) +(define pair-reg (make-dreg 7)) +(define gvm-reg0 0) +(define first-atemp 1) +(define heap-reg (make-areg 3)) +(define ltq-tail-reg (make-areg 4)) +(define pstate-reg (make-areg 5)) +(define table-reg (make-areg 6)) +(define sp-reg (make-areg 7)) +(define pdec-sp (make-pdec sp-reg)) +(define pinc-sp (make-pinc sp-reg)) +(define dtemp1 (make-dreg first-dtemp)) +(define atemp1 (make-areg first-atemp)) +(define atemp2 (make-areg (+ first-atemp 1))) +(define ftemp1 (make-freg 0)) +(define arg-count-reg dtemp1) +(define (trap-offset n) (+ 32768 (* (- n 32) 8))) +(define (emit-move.l opnd1 opnd2) + (let ((src (opnd->mode/reg opnd1)) (dst (opnd->reg/mode opnd2))) + (asm-word (+ 8192 (+ dst src))) + (opnd-ext-rd-long opnd1) + (opnd-ext-wr-long opnd2) + (if ofile-asm? + (emit-asm "movl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))) +(define (emit-move.w opnd1 opnd2) + (let ((src (opnd->mode/reg opnd1)) (dst (opnd->reg/mode opnd2))) + (asm-word (+ 12288 (+ dst src))) + (opnd-ext-rd-word opnd1) + (opnd-ext-wr-word opnd2) + (if ofile-asm? + (emit-asm "movw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))) +(define (emit-move.b opnd1 opnd2) + (let ((src (opnd->mode/reg opnd1)) (dst (opnd->reg/mode opnd2))) + (asm-word (+ 4096 (+ dst src))) + (opnd-ext-rd-word opnd1) + (opnd-ext-wr-word opnd2) + (if ofile-asm? + (emit-asm "movb" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2))))) +(define (emit-moveq n opnd) + (asm-word (+ 28672 (+ (* (dreg-num opnd) 512) (modulo n 256)))) + (if ofile-asm? (emit-asm "moveq" ofile-tab "#" n "," (opnd-str opnd)))) +(define (emit-movem.l opnd1 opnd2) + (define (reg-mask reg-list flip-bits?) + (let loop ((i 15) (bit 32768) (mask 0)) + (if (>= i 0) + (loop (- i 1) + (quotient bit 2) + (if (memq i reg-list) + (+ mask (if flip-bits? (quotient 32768 bit) bit)) + mask)) + mask))) + (define (movem op reg-list opnd) + (asm-word (+ op (opnd->mode/reg opnd))) + (asm-word (reg-mask reg-list (pdec? opnd)))) + (if (reg-list? opnd1) + (begin (movem 18624 opnd1 opnd2) (opnd-ext-wr-long opnd2)) + (begin (movem 19648 opnd2 opnd1) (opnd-ext-rd-long opnd1))) + (if ofile-asm? + (emit-asm "moveml" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-exg opnd1 opnd2) + (define (exg r1 r2) + (let ((mode (if (dreg? r2) 49472 (if (dreg? r1) 49544 49480))) + (num1 (if (dreg? r1) (dreg-num r1) (areg-num r1))) + (num2 (if (dreg? r2) (dreg-num r2) (areg-num r2)))) + (asm-word (+ mode (+ (* num1 512) num2))))) + (if (dreg? opnd2) (exg opnd2 opnd1) (exg opnd1 opnd2)) + (if ofile-asm? + (emit-asm "exg" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-eor.l opnd1 opnd2) + (cond ((imm? opnd1) + (asm-word (+ 2688 (opnd->mode/reg opnd2))) + (opnd-ext-rd-long opnd1) + (opnd-ext-wr-long opnd2)) + (else + (asm-word + (+ 45440 (+ (* (dreg-num opnd1) 512) (opnd->mode/reg opnd2)))) + (opnd-ext-wr-long opnd2))) + (if ofile-asm? + (emit-asm "eorl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-and.l opnd1 opnd2) + (cond ((imm? opnd1) + (asm-word (+ 640 (opnd->mode/reg opnd2))) + (opnd-ext-rd-long opnd1) + (opnd-ext-wr-long opnd2)) + (else + (let ((mode (if (dreg? opnd2) 49280 49536)) + (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1))) + (other (if (dreg? opnd2) opnd1 opnd2))) + (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other)))) + (if (dreg? opnd2) + (opnd-ext-rd-long other) + (opnd-ext-wr-long other))))) + (if ofile-asm? + (emit-asm "andl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-and.w opnd1 opnd2) + (cond ((imm? opnd1) + (asm-word (+ 576 (opnd->mode/reg opnd2))) + (opnd-ext-rd-word opnd1) + (opnd-ext-wr-word opnd2)) + (else + (let ((mode (if (dreg? opnd2) 49216 49472)) + (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1))) + (other (if (dreg? opnd2) opnd1 opnd2))) + (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other)))) + (if (dreg? opnd2) + (opnd-ext-rd-word other) + (opnd-ext-wr-word other))))) + (if ofile-asm? + (emit-asm "andw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-or.l opnd1 opnd2) + (cond ((imm? opnd1) + (asm-word (+ 128 (opnd->mode/reg opnd2))) + (opnd-ext-rd-long opnd1) + (opnd-ext-wr-long opnd2)) + (else + (let ((mode (if (dreg? opnd2) 32896 33152)) + (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1))) + (other (if (dreg? opnd2) opnd1 opnd2))) + (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other)))) + (if (dreg? opnd2) + (opnd-ext-rd-long other) + (opnd-ext-wr-long other))))) + (if ofile-asm? + (emit-asm "orl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-addq.l n opnd) + (let ((m (if (= n 8) 0 n))) + (asm-word (+ 20608 (* m 512) (opnd->mode/reg opnd))) + (opnd-ext-wr-long opnd) + (if ofile-asm? (emit-asm "addql" ofile-tab "#" n "," (opnd-str opnd))))) +(define (emit-addq.w n opnd) + (let ((m (if (= n 8) 0 n))) + (asm-word (+ 20544 (* m 512) (opnd->mode/reg opnd))) + (opnd-ext-wr-word opnd) + (if ofile-asm? (emit-asm "addqw" ofile-tab "#" n "," (opnd-str opnd))))) +(define (emit-add.l opnd1 opnd2) + (cond ((areg? opnd2) + (asm-word + (+ 53696 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-long opnd1)) + ((imm? opnd1) + (asm-word (+ 1664 (opnd->mode/reg opnd2))) + (opnd-ext-rd-long opnd1) + (opnd-ext-wr-long opnd2)) + (else + (let ((mode (if (dreg? opnd2) 53376 53632)) + (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1))) + (other (if (dreg? opnd2) opnd1 opnd2))) + (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other)))) + (if (dreg? opnd2) + (opnd-ext-rd-long other) + (opnd-ext-wr-long other))))) + (if ofile-asm? + (emit-asm "addl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-add.w opnd1 opnd2) + (cond ((areg? opnd2) + (asm-word + (+ 53440 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-word opnd1)) + ((imm? opnd1) + (asm-word (+ 1600 (opnd->mode/reg opnd2))) + (opnd-ext-rd-word opnd1) + (opnd-ext-wr-word opnd2)) + (else + (let ((mode (if (dreg? opnd2) 53312 53568)) + (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1))) + (other (if (dreg? opnd2) opnd1 opnd2))) + (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other)))) + (if (dreg? opnd2) + (opnd-ext-rd-word other) + (opnd-ext-wr-word other))))) + (if ofile-asm? + (emit-asm "addw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-addx.w opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 53568 (+ (* (dreg-num opnd2) 512) (dreg-num opnd1)))) + (asm-word + (+ 53576 + (+ (* (areg-num (pdec-areg opnd2)) 512) + (areg-num (pdec-areg opnd1)))))) + (if ofile-asm? + (emit-asm "addxw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-subq.l n opnd) + (let ((m (if (= n 8) 0 n))) + (asm-word (+ 20864 (* m 512) (opnd->mode/reg opnd))) + (opnd-ext-wr-long opnd) + (if ofile-asm? (emit-asm "subql" ofile-tab "#" n "," (opnd-str opnd))))) +(define (emit-subq.w n opnd) + (let ((m (if (= n 8) 0 n))) + (asm-word (+ 20800 (* m 512) (opnd->mode/reg opnd))) + (opnd-ext-wr-word opnd) + (if ofile-asm? (emit-asm "subqw" ofile-tab "#" n "," (opnd-str opnd))))) +(define (emit-sub.l opnd1 opnd2) + (cond ((areg? opnd2) + (asm-word + (+ 37312 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-long opnd1)) + ((imm? opnd1) + (asm-word (+ 1152 (opnd->mode/reg opnd2))) + (opnd-ext-rd-long opnd1) + (opnd-ext-wr-long opnd2)) + (else + (let ((mode (if (dreg? opnd2) 36992 37248)) + (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1))) + (other (if (dreg? opnd2) opnd1 opnd2))) + (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other)))) + (if (dreg? opnd2) + (opnd-ext-rd-long other) + (opnd-ext-wr-long other))))) + (if ofile-asm? + (emit-asm "subl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-sub.w opnd1 opnd2) + (cond ((areg? opnd2) + (asm-word + (+ 37056 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-word opnd1)) + ((imm? opnd1) + (asm-word (+ 1088 (opnd->mode/reg opnd2))) + (opnd-ext-rd-word opnd1) + (opnd-ext-wr-word opnd2)) + (else + (let ((mode (if (dreg? opnd2) 36928 37184)) + (reg (if (dreg? opnd2) (dreg-num opnd2) (dreg-num opnd1))) + (other (if (dreg? opnd2) opnd1 opnd2))) + (asm-word (+ mode (+ (* reg 512) (opnd->mode/reg other)))) + (if (dreg? opnd2) + (opnd-ext-rd-word other) + (opnd-ext-wr-word other))))) + (if ofile-asm? + (emit-asm "subw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-asl.l opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 57760 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2)))) + (let ((n (imm-val opnd1))) + (asm-word (+ 57728 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2)))))) + (if ofile-asm? + (emit-asm "asll" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-asl.w opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 57696 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2)))) + (let ((n (imm-val opnd1))) + (asm-word (+ 57664 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2)))))) + (if ofile-asm? + (emit-asm "aslw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-asr.l opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 57504 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2)))) + (let ((n (imm-val opnd1))) + (asm-word (+ 57472 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2)))))) + (if ofile-asm? + (emit-asm "asrl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-asr.w opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 57440 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2)))) + (let ((n (imm-val opnd1))) + (asm-word (+ 57408 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2)))))) + (if ofile-asm? + (emit-asm "asrw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-lsl.l opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 57768 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2)))) + (let ((n (imm-val opnd1))) + (asm-word (+ 57736 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2)))))) + (if ofile-asm? + (emit-asm "lsll" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-lsr.l opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 57512 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2)))) + (let ((n (imm-val opnd1))) + (asm-word (+ 57480 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2)))))) + (if ofile-asm? + (emit-asm "lsrl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-lsr.w opnd1 opnd2) + (if (dreg? opnd1) + (asm-word (+ 57448 (+ (* (dreg-num opnd1) 512) (dreg-num opnd2)))) + (let ((n (imm-val opnd1))) + (asm-word (+ 57416 (+ (* (if (= n 8) 0 n) 512) (dreg-num opnd2)))))) + (if ofile-asm? + (emit-asm "lsrw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-clr.l opnd) + (asm-word (+ 17024 (opnd->mode/reg opnd))) + (opnd-ext-wr-long opnd) + (if ofile-asm? (emit-asm "clrl" ofile-tab (opnd-str opnd)))) +(define (emit-neg.l opnd) + (asm-word (+ 17536 (opnd->mode/reg opnd))) + (opnd-ext-wr-long opnd) + (if ofile-asm? (emit-asm "negl" ofile-tab (opnd-str opnd)))) +(define (emit-not.l opnd) + (asm-word (+ 18048 (opnd->mode/reg opnd))) + (opnd-ext-wr-long opnd) + (if ofile-asm? (emit-asm "notl" ofile-tab (opnd-str opnd)))) +(define (emit-ext.l opnd) + (asm-word (+ 18624 (dreg-num opnd))) + (if ofile-asm? (emit-asm "extl" ofile-tab (opnd-str opnd)))) +(define (emit-ext.w opnd) + (asm-word (+ 18560 (dreg-num opnd))) + (if ofile-asm? (emit-asm "extw" ofile-tab (opnd-str opnd)))) +(define (emit-swap opnd) + (asm-word (+ 18496 (dreg-num opnd))) + (if ofile-asm? (emit-asm "swap" ofile-tab (opnd-str opnd)))) +(define (emit-cmp.l opnd1 opnd2) + (cond ((areg? opnd2) + (asm-word + (+ 45504 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-long opnd1)) + ((imm? opnd1) + (asm-word (+ 3200 (opnd->mode/reg opnd2))) + (opnd-ext-rd-long opnd1) + (opnd-ext-rd-long opnd2)) + (else + (asm-word + (+ 45184 (+ (* (dreg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-long opnd1))) + (if ofile-asm? + (emit-asm "cmpl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-cmp.w opnd1 opnd2) + (cond ((areg? opnd2) + (asm-word + (+ 45248 (+ (* (areg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-word opnd1)) + ((imm? opnd1) + (asm-word (+ 3136 (opnd->mode/reg opnd2))) + (opnd-ext-rd-word opnd1) + (opnd-ext-rd-word opnd2)) + (else + (asm-word + (+ 45120 (+ (* (dreg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-word opnd1))) + (if ofile-asm? + (emit-asm "cmpw" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-cmp.b opnd1 opnd2) + (cond ((imm? opnd1) + (asm-word (+ 3072 (opnd->mode/reg opnd2))) + (opnd-ext-rd-word opnd1) + (opnd-ext-rd-word opnd2)) + (else + (asm-word + (+ 45056 (+ (* (dreg-num opnd2) 512) (opnd->mode/reg opnd1)))) + (opnd-ext-rd-word opnd1))) + (if ofile-asm? + (emit-asm "cmpb" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-tst.l opnd) + (asm-word (+ 19072 (opnd->mode/reg opnd))) + (opnd-ext-rd-long opnd) + (if ofile-asm? (emit-asm "tstl" ofile-tab (opnd-str opnd)))) +(define (emit-tst.w opnd) + (asm-word (+ 19008 (opnd->mode/reg opnd))) + (opnd-ext-rd-word opnd) + (if ofile-asm? (emit-asm "tstw" ofile-tab (opnd-str opnd)))) +(define (emit-lea opnd areg) + (asm-word (+ 16832 (+ (* (areg-num areg) 512) (opnd->mode/reg opnd)))) + (opnd-ext-rd-long opnd) + (if ofile-asm? + (emit-asm "lea" ofile-tab (opnd-str opnd) "," (opnd-str areg)))) +(define (emit-unlk areg) + (asm-word (+ 20056 (areg-num areg))) + (if ofile-asm? (emit-asm "unlk" ofile-tab (opnd-str areg)))) +(define (emit-move-proc num opnd) + (let ((dst (opnd->reg/mode opnd))) + (asm-word (+ 8192 (+ dst 60))) + (asm-proc-ref num 0) + (opnd-ext-wr-long opnd) + (if ofile-asm? (emit-asm "MOVE_PROC(" num "," (opnd-str opnd) ")")))) +(define (emit-move-prim val opnd) + (let ((dst (opnd->reg/mode opnd))) + (asm-word (+ 8192 (+ dst 60))) + (asm-prim-ref val 0) + (opnd-ext-wr-long opnd) + (if ofile-asm? + (emit-asm "MOVE_PRIM(" (proc-obj-name val) "," (opnd-str opnd) ")")))) +(define (emit-pea opnd) + (asm-word (+ 18496 (opnd->mode/reg opnd))) + (opnd-ext-rd-long opnd) + (if ofile-asm? (emit-asm "pea" ofile-tab (opnd-str opnd)))) +(define (emit-pea* n) + (asm-word 18552) + (asm-word n) + (if ofile-asm? (emit-asm "pea" ofile-tab n))) +(define (emit-btst opnd1 opnd2) + (asm-word (+ 256 (+ (* (dreg-num opnd1) 512) (opnd->mode/reg opnd2)))) + (opnd-ext-rd-word opnd2) + (if ofile-asm? + (emit-asm "btst" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-bra lbl) + (asm-brel 24576 lbl) + (if ofile-asm? (emit-asm "bra" ofile-tab "L" lbl))) +(define (emit-bcc lbl) + (asm-brel 25600 lbl) + (if ofile-asm? (emit-asm "bcc" ofile-tab "L" lbl))) +(define (emit-bcs lbl) + (asm-brel 25856 lbl) + (if ofile-asm? (emit-asm "bcs" ofile-tab "L" lbl))) +(define (emit-bhi lbl) + (asm-brel 25088 lbl) + (if ofile-asm? (emit-asm "bhi" ofile-tab "L" lbl))) +(define (emit-bls lbl) + (asm-brel 25344 lbl) + (if ofile-asm? (emit-asm "bls" ofile-tab "L" lbl))) +(define (emit-bmi lbl) + (asm-brel 27392 lbl) + (if ofile-asm? (emit-asm "bmi" ofile-tab "L" lbl))) +(define (emit-bpl lbl) + (asm-brel 27136 lbl) + (if ofile-asm? (emit-asm "bpl" ofile-tab "L" lbl))) +(define (emit-beq lbl) + (asm-brel 26368 lbl) + (if ofile-asm? (emit-asm "beq" ofile-tab "L" lbl))) +(define (emit-bne lbl) + (asm-brel 26112 lbl) + (if ofile-asm? (emit-asm "bne" ofile-tab "L" lbl))) +(define (emit-blt lbl) + (asm-brel 27904 lbl) + (if ofile-asm? (emit-asm "blt" ofile-tab "L" lbl))) +(define (emit-bgt lbl) + (asm-brel 28160 lbl) + (if ofile-asm? (emit-asm "bgt" ofile-tab "L" lbl))) +(define (emit-ble lbl) + (asm-brel 28416 lbl) + (if ofile-asm? (emit-asm "ble" ofile-tab "L" lbl))) +(define (emit-bge lbl) + (asm-brel 27648 lbl) + (if ofile-asm? (emit-asm "bge" ofile-tab "L" lbl))) +(define (emit-dbra dreg lbl) + (asm-word (+ 20936 dreg)) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "dbra" ofile-tab (opnd-str dreg) ",L" lbl))) +(define (emit-trap num) + (asm-word (+ 20032 num)) + (if ofile-asm? (emit-asm "trap" ofile-tab "#" num))) +(define (emit-trap1 num args) + (asm-word (+ 20136 (areg-num table-reg))) + (asm-word (trap-offset num)) + (let loop ((args args)) + (if (not (null? args)) (begin (asm-word (car args)) (loop (cdr args))))) + (if ofile-asm? + (let () + (define (words l) + (if (null? l) (list ")") (cons "," (cons (car l) (words (cdr l)))))) + (apply emit-asm (cons "TRAP1(" (cons num (words args))))))) +(define (emit-trap2 num args) + (asm-word (+ 20136 (areg-num table-reg))) + (asm-word (trap-offset num)) + (asm-align 8 (modulo (- 4 (* (length args) 2)) 8)) + (let loop ((args args)) + (if (not (null? args)) (begin (asm-word (car args)) (loop (cdr args))))) + (if ofile-asm? + (let () + (define (words l) + (if (null? l) (list ")") (cons "," (cons (car l) (words (cdr l)))))) + (apply emit-asm (cons "TRAP2(" (cons num (words args))))))) +(define (emit-trap3 num) + (asm-word (+ 20200 (areg-num table-reg))) + (asm-word (trap-offset num)) + (if ofile-asm? (emit-asm "TRAP3(" num ")"))) +(define (emit-rts) (asm-word 20085) (if ofile-asm? (emit-asm "rts"))) +(define (emit-nop) (asm-word 20081) (if ofile-asm? (emit-asm "nop"))) +(define (emit-jmp opnd) + (asm-word (+ 20160 (opnd->mode/reg opnd))) + (opnd-ext-rd-long opnd) + (if ofile-asm? (emit-asm "jmp" ofile-tab (opnd-str opnd)))) +(define (emit-jmp-glob glob) + (asm-word 8814) + (asm-ref-glob-jump glob) + (asm-word 20177) + (if ofile-asm? (emit-asm "JMP_GLOB(" (glob-name glob) ")"))) +(define (emit-jmp-proc num offset) + (asm-word 20217) + (asm-proc-ref num offset) + (if ofile-asm? (emit-asm "JMP_PROC(" num "," offset ")"))) +(define (emit-jmp-prim val offset) + (asm-word 20217) + (asm-prim-ref val offset) + (if ofile-asm? (emit-asm "JMP_PRIM(" (proc-obj-name val) "," offset ")"))) +(define (emit-jsr opnd) + (asm-word (+ 20096 (opnd->mode/reg opnd))) + (opnd-ext-rd-long opnd) + (if ofile-asm? (emit-asm "jsr" ofile-tab (opnd-str opnd)))) +(define (emit-word n) + (asm-word n) + (if ofile-asm? (emit-asm ".word" ofile-tab n))) +(define (emit-label lbl) + (asm-label lbl #f) + (if ofile-asm? (emit-asm* "L" lbl ":"))) +(define (emit-label-subproc lbl parent-lbl label-descr) + (asm-align 8 0) + (asm-wrel parent-lbl (- 32768 type-procedure)) + (asm-label lbl label-descr) + (if ofile-asm? + (begin (emit-asm "SUBPROC(L" parent-lbl ")") (emit-asm* "L" lbl ":")))) +(define (emit-label-return lbl parent-lbl fs link label-descr) + (asm-align 8 4) + (asm-word (* fs 4)) + (asm-word (* (- fs link) 4)) + (asm-wrel parent-lbl (- 32768 type-procedure)) + (asm-label lbl label-descr) + (if ofile-asm? + (begin + (emit-asm "RETURN(L" parent-lbl "," fs "," link ")") + (emit-asm* "L" lbl ":")))) +(define (emit-label-task-return lbl parent-lbl fs link label-descr) + (asm-align 8 4) + (asm-word (+ 32768 (* fs 4))) + (asm-word (* (- fs link) 4)) + (asm-wrel parent-lbl (- 32768 type-procedure)) + (asm-label lbl label-descr) + (if ofile-asm? + (begin + (emit-asm "TASK_RETURN(L" parent-lbl "," fs "," link ")") + (emit-asm* "L" lbl ":")))) +(define (emit-lbl-ptr lbl) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "LBL_PTR(L" lbl ")"))) +(define (emit-set-glob glob) + (asm-set-glob glob) + (if ofile-asm? (emit-asm "SET_GLOB(" (glob-name glob) ")"))) +(define (emit-const obj) + (let ((n (pos-in-list obj (queue->list asm-const-queue)))) + (if n + (make-pcr const-lbl (* n 4)) + (let ((m (length (queue->list asm-const-queue)))) + (queue-put! asm-const-queue obj) + (make-pcr const-lbl (* m 4)))))) +(define (emit-stat stat) + (asm-word 21177) + (asm-stat stat) + (if ofile-asm? (emit-asm "STAT(" stat ")"))) +(define (emit-asm . l) (asm-comment (cons ofile-tab l))) +(define (emit-asm* . l) (asm-comment l)) +(define (emit-muls.l opnd1 opnd2) + (asm-m68020-proc) + (asm-word (+ 19456 (opnd->mode/reg opnd1))) + (asm-word (+ 2048 (* (dreg-num opnd2) 4096))) + (opnd-ext-rd-long opnd1) + (if ofile-asm? + (emit-asm "mulsl" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-divsl.l opnd1 opnd2 opnd3) + (asm-m68020-proc) + (asm-word (+ 19520 (opnd->mode/reg opnd1))) + (asm-word (+ 2048 (* (dreg-num opnd3) 4096) (dreg-num opnd2))) + (opnd-ext-rd-long opnd1) + (if ofile-asm? + (emit-asm + "divsll" + ofile-tab + (opnd-str opnd1) + "," + (opnd-str opnd2) + ":" + (opnd-str opnd3)))) +(define (emit-fint.dx opnd1 opnd2) (emit-fop.dx "int" 1 opnd1 opnd2)) +(define (emit-fsinh.dx opnd1 opnd2) (emit-fop.dx "sinh" 2 opnd1 opnd2)) +(define (emit-fintrz.dx opnd1 opnd2) (emit-fop.dx "intrz" 3 opnd1 opnd2)) +(define (emit-fsqrt.dx opnd1 opnd2) (emit-fop.dx "sqrt" 4 opnd1 opnd2)) +(define (emit-flognp1.dx opnd1 opnd2) (emit-fop.dx "lognp1" 6 opnd1 opnd2)) +(define (emit-fetoxm1.dx opnd1 opnd2) (emit-fop.dx "etoxm1" 8 opnd1 opnd2)) +(define (emit-ftanh.dx opnd1 opnd2) (emit-fop.dx "tanh" 9 opnd1 opnd2)) +(define (emit-fatan.dx opnd1 opnd2) (emit-fop.dx "atan" 10 opnd1 opnd2)) +(define (emit-fasin.dx opnd1 opnd2) (emit-fop.dx "asin" 12 opnd1 opnd2)) +(define (emit-fatanh.dx opnd1 opnd2) (emit-fop.dx "atanh" 13 opnd1 opnd2)) +(define (emit-fsin.dx opnd1 opnd2) (emit-fop.dx "sin" 14 opnd1 opnd2)) +(define (emit-ftan.dx opnd1 opnd2) (emit-fop.dx "tan" 15 opnd1 opnd2)) +(define (emit-fetox.dx opnd1 opnd2) (emit-fop.dx "etox" 16 opnd1 opnd2)) +(define (emit-ftwotox.dx opnd1 opnd2) (emit-fop.dx "twotox" 17 opnd1 opnd2)) +(define (emit-ftentox.dx opnd1 opnd2) (emit-fop.dx "tentox" 18 opnd1 opnd2)) +(define (emit-flogn.dx opnd1 opnd2) (emit-fop.dx "logn" 20 opnd1 opnd2)) +(define (emit-flog10.dx opnd1 opnd2) (emit-fop.dx "log10" 21 opnd1 opnd2)) +(define (emit-flog2.dx opnd1 opnd2) (emit-fop.dx "log2" 22 opnd1 opnd2)) +(define (emit-fabs.dx opnd1 opnd2) (emit-fop.dx "abs" 24 opnd1 opnd2)) +(define (emit-fcosh.dx opnd1 opnd2) (emit-fop.dx "cosh" 25 opnd1 opnd2)) +(define (emit-fneg.dx opnd1 opnd2) (emit-fop.dx "neg" 26 opnd1 opnd2)) +(define (emit-facos.dx opnd1 opnd2) (emit-fop.dx "acos" 28 opnd1 opnd2)) +(define (emit-fcos.dx opnd1 opnd2) (emit-fop.dx "cos" 29 opnd1 opnd2)) +(define (emit-fgetexp.dx opnd1 opnd2) (emit-fop.dx "getexp" 30 opnd1 opnd2)) +(define (emit-fgetman.dx opnd1 opnd2) (emit-fop.dx "getman" 31 opnd1 opnd2)) +(define (emit-fdiv.dx opnd1 opnd2) (emit-fop.dx "div" 32 opnd1 opnd2)) +(define (emit-fmod.dx opnd1 opnd2) (emit-fop.dx "mod" 33 opnd1 opnd2)) +(define (emit-fadd.dx opnd1 opnd2) (emit-fop.dx "add" 34 opnd1 opnd2)) +(define (emit-fmul.dx opnd1 opnd2) (emit-fop.dx "mul" 35 opnd1 opnd2)) +(define (emit-fsgldiv.dx opnd1 opnd2) (emit-fop.dx "sgldiv" 36 opnd1 opnd2)) +(define (emit-frem.dx opnd1 opnd2) (emit-fop.dx "rem" 37 opnd1 opnd2)) +(define (emit-fscale.dx opnd1 opnd2) (emit-fop.dx "scale" 38 opnd1 opnd2)) +(define (emit-fsglmul.dx opnd1 opnd2) (emit-fop.dx "sglmul" 39 opnd1 opnd2)) +(define (emit-fsub.dx opnd1 opnd2) (emit-fop.dx "sub" 40 opnd1 opnd2)) +(define (emit-fcmp.dx opnd1 opnd2) (emit-fop.dx "cmp" 56 opnd1 opnd2)) +(define (emit-fop.dx name code opnd1 opnd2) + (asm-m68881-proc) + (asm-word (+ 61952 (opnd->mode/reg opnd1))) + (asm-word + (+ (if (freg? opnd1) (* (freg-num opnd1) 1024) 21504) + (* (freg-num opnd2) 128) + code)) + (opnd-ext-rd-long opnd1) + (if ofile-asm? + (emit-asm + "f" + name + (if (freg? opnd1) "x" "d") + ofile-tab + (opnd-str opnd1) + "," + (opnd-str opnd2)))) +(define (emit-fmov.dx opnd1 opnd2) + (emit-fmov + (if (and (freg? opnd1) (freg? opnd2)) (* (freg-num opnd1) 1024) 21504) + opnd1 + opnd2) + (if ofile-asm? + (emit-asm + (if (and (freg? opnd1) (freg? opnd2)) "fmovex" "fmoved") + ofile-tab + (opnd-str opnd1) + "," + (opnd-str opnd2)))) +(define (emit-fmov.l opnd1 opnd2) + (emit-fmov 16384 opnd1 opnd2) + (if ofile-asm? + (emit-asm "fmovel" ofile-tab (opnd-str opnd1) "," (opnd-str opnd2)))) +(define (emit-fmov code opnd1 opnd2) + (define (fmov code opnd1 opnd2) + (asm-m68881-proc) + (asm-word (+ 61952 (opnd->mode/reg opnd1))) + (asm-word (+ (* (freg-num opnd2) 128) code)) + (opnd-ext-rd-long opnd1)) + (if (freg? opnd2) (fmov code opnd1 opnd2) (fmov (+ code 8192) opnd2 opnd1))) +(define (emit-fbeq lbl) + (asm-m68881-proc) + (asm-word 62081) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "fbeq" ofile-tab "L" lbl))) +(define (emit-fbne lbl) + (asm-m68881-proc) + (asm-word 62094) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "fbne" ofile-tab "L" lbl))) +(define (emit-fblt lbl) + (asm-m68881-proc) + (asm-word 62100) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "fblt" ofile-tab "L" lbl))) +(define (emit-fbgt lbl) + (asm-m68881-proc) + (asm-word 62098) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "fbgt" ofile-tab "L" lbl))) +(define (emit-fble lbl) + (asm-m68881-proc) + (asm-word 62101) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "fble" ofile-tab "L" lbl))) +(define (emit-fbge lbl) + (asm-m68881-proc) + (asm-word 62099) + (asm-wrel lbl 0) + (if ofile-asm? (emit-asm "fbge" ofile-tab "L" lbl))) +(define (opnd->mode/reg opnd) + (cond ((disp? opnd) (+ 32 (disp-areg opnd))) + ((inx? opnd) (+ 40 (inx-areg opnd))) + ((pcr? opnd) 58) + ((imm? opnd) 60) + ((glob? opnd) (+ 32 table-reg)) + ((freg? opnd) 0) + (else opnd))) +(define (opnd->reg/mode opnd) + (let ((x (opnd->mode/reg opnd))) + (* (+ (* 8 (remainder x 8)) (quotient x 8)) 64))) +(define (opnd-ext-rd-long opnd) (opnd-extension opnd #f #f)) +(define (opnd-ext-rd-word opnd) (opnd-extension opnd #f #t)) +(define (opnd-ext-wr-long opnd) (opnd-extension opnd #t #f)) +(define (opnd-ext-wr-word opnd) (opnd-extension opnd #t #t)) +(define (opnd-extension opnd write? word?) + (cond ((disp? opnd) (asm-word (disp-offset opnd))) + ((inx? opnd) + (asm-word + (+ (+ (* (inx-ireg opnd) 4096) 2048) + (modulo (inx-offset opnd) 256)))) + ((pcr? opnd) (asm-wrel (pcr-lbl opnd) (pcr-offset opnd))) + ((imm? opnd) + (if word? (asm-word (imm-val opnd)) (asm-long (imm-val opnd)))) + ((glob? opnd) (if write? (asm-set-glob opnd) (asm-ref-glob opnd))))) +(define (opnd-str opnd) + (cond ((dreg? opnd) + (vector-ref + '#("d0" "d1" "d2" "d3" "d4" "d5" "d6" "d7") + (dreg-num opnd))) + ((areg? opnd) + (vector-ref + '#("a0" "a1" "a2" "a3" "a4" "a5" "a6" "sp") + (areg-num opnd))) + ((ind? opnd) + (vector-ref + '#("a0@" "a1@" "a2@" "a3@" "a4@" "a5@" "a6@" "sp@") + (areg-num (ind-areg opnd)))) + ((pinc? opnd) + (vector-ref + '#("a0@+" "a1@+" "a2@+" "a3@+" "a4@+" "a5@+" "a6@+" "sp@+") + (areg-num (pinc-areg opnd)))) + ((pdec? opnd) + (vector-ref + '#("a0@-" "a1@-" "a2@-" "a3@-" "a4@-" "a5@-" "a6@-" "sp@-") + (areg-num (pdec-areg opnd)))) + ((disp? opnd) + (string-append + (opnd-str (disp-areg opnd)) + "@(" + (number->string (disp-offset opnd)) + ")")) + ((inx? opnd) + (string-append + (opnd-str (inx-areg opnd)) + "@(" + (number->string (inx-offset opnd)) + "," + (opnd-str (inx-ireg opnd)) + ":l)")) + ((pcr? opnd) + (let ((lbl (pcr-lbl opnd)) (offs (pcr-offset opnd))) + (if (= offs 0) + (string-append "L" (number->string lbl)) + (string-append + "L" + (number->string lbl) + "+" + (number->string offs))))) + ((imm? opnd) (string-append "#" (number->string (imm-val opnd)))) + ((glob? opnd) + (string-append "GLOB(" (symbol->string (glob-name opnd)) ")")) + ((freg? opnd) + (vector-ref + '#("fp0" "fp1" "fp2" "fp3" "fp4" "fp5" "fp6" "fp7") + (freg-num opnd))) + ((reg-list? opnd) + (let loop ((l (reg-list-regs opnd)) (result "[") (sep "")) + (if (pair? l) + (loop (cdr l) (string-append result sep (opnd-str (car l))) "/") + (string-append result "]")))) + (else (compiler-internal-error "opnd-str, unknown 'opnd'" opnd)))) +(define (begin! info-port targ) + (set! return-reg (make-reg 0)) + (target-end!-set! targ end!) + (target-dump-set! targ dump) + (target-nb-regs-set! targ nb-gvm-regs) + (target-prim-info-set! targ prim-info) + (target-label-info-set! targ label-info) + (target-jump-info-set! targ jump-info) + (target-proc-result-set! targ (make-reg 1)) + (target-task-return-set! targ return-reg) + (set! *info-port* info-port) + '()) +(define (end!) '()) +(define *info-port* '()) +(define nb-gvm-regs 5) +(define nb-arg-regs 3) +(define pointer-size 4) +(define prim-proc-table + (map (lambda (x) + (cons (string->canonical-symbol (car x)) + (apply make-proc-obj (car x) #t #f (cdr x)))) + prim-procs)) +(define (prim-info name) + (let ((x (assq name prim-proc-table))) (if x (cdr x) #f))) +(define (get-prim-info name) + (let ((proc (prim-info (string->canonical-symbol name)))) + (if proc + proc + (compiler-internal-error "get-prim-info, unknown primitive:" name)))) +(define (label-info min-args nb-parms rest? closed?) + (let ((nb-stacked (max 0 (- nb-parms nb-arg-regs)))) + (define (location-of-parms i) + (if (> i nb-parms) + '() + (cons (cons i + (if (> i nb-stacked) + (make-reg (- i nb-stacked)) + (make-stk i))) + (location-of-parms (+ i 1))))) + (let ((x (cons (cons 'return 0) (location-of-parms 1)))) + (make-pcontext + nb-stacked + (if closed? + (cons (cons 'closure-env (make-reg (+ nb-arg-regs 1))) x) + x))))) +(define (jump-info nb-args) + (let ((nb-stacked (max 0 (- nb-args nb-arg-regs)))) + (define (location-of-args i) + (if (> i nb-args) + '() + (cons (cons i + (if (> i nb-stacked) + (make-reg (- i nb-stacked)) + (make-stk i))) + (location-of-args (+ i 1))))) + (make-pcontext + nb-stacked + (cons (cons 'return (make-reg 0)) (location-of-args 1))))) +(define (closed-var-offset i) (+ (* i pointer-size) 2)) +(define (dump proc filename c-intf options) + (if *info-port* + (begin (display "Dumping:" *info-port*) (newline *info-port*))) + (set! ofile-asm? (memq 'asm options)) + (set! ofile-stats? (memq 'stats options)) + (set! debug-info? (memq 'debug options)) + (set! object-queue (queue-empty)) + (set! objects-dumped (queue-empty)) + (ofile.begin! filename add-object) + (queue-put! object-queue proc) + (queue-put! objects-dumped proc) + (let loop ((index 0)) + (if (not (queue-empty? object-queue)) + (let ((obj (queue-get! object-queue))) + (dump-object obj index) + (loop (+ index 1))))) + (ofile.end!) + (if *info-port* (newline *info-port*)) + (set! object-queue '()) + (set! objects-dumped '())) +(define debug-info? '()) +(define object-queue '()) +(define objects-dumped '()) +(define (add-object obj) + (if (and (proc-obj? obj) (not (proc-obj-code obj))) + #f + (let ((n (pos-in-list obj (queue->list objects-dumped)))) + (if n + n + (let ((m (length (queue->list objects-dumped)))) + (queue-put! objects-dumped obj) + (queue-put! object-queue obj) + m))))) +(define (dump-object obj index) + (ofile-line "|------------------------------------------------------") + (case (obj-type obj) + ((pair) (dump-pair obj)) + ((flonum) (dump-flonum obj)) + ((subtyped) + (case (obj-subtype obj) + ((vector) (dump-vector obj)) + ((symbol) (dump-symbol obj)) +;; ((ratnum) (dump-ratnum obj)) +;; ((cpxnum) (dump-cpxnum obj)) + ((string) (dump-string obj)) + ((bignum) (dump-bignum obj)) + (else + (compiler-internal-error + "dump-object, can't dump object 'obj':" + obj)))) + ((procedure) (dump-procedure obj)) + (else + (compiler-internal-error "dump-object, can't dump object 'obj':" obj)))) +(define (dump-pair pair) + (ofile-long pair-prefix) + (ofile-ref (cdr pair)) + (ofile-ref (car pair))) +(define (dump-vector v) + (ofile-long (+ (* (vector-length v) 1024) (* subtype-vector 8))) + (let ((len (vector-length v))) + (let loop ((i 0)) + (if (< i len) (begin (ofile-ref (vector-ref v i)) (loop (+ i 1))))))) +(define (dump-symbol sym) + (compiler-internal-error "dump-symbol, can't dump SYMBOL type")) +;;(define (dump-ratnum x) +;; (ofile-long (+ (* 2 1024) (* subtype-ratnum 8))) +;; (ofile-ref (numerator x)) +;; (ofile-ref (denominator x))) +;;(define (dump-cpxnum x) +;; (ofile-long (+ (* 2 1024) (* subtype-cpxnum 8))) +;; (ofile-ref (real-part x)) +;; (ofile-ref (imag-part x))) +(define (dump-string s) + (ofile-long (+ (* (+ (string-length s) 1) 256) (* subtype-string 8))) + (let ((len (string-length s))) + (define (ref i) (if (>= i len) 0 (character-encoding (string-ref s i)))) + (let loop ((i 0)) + (if (<= i len) + (begin + (ofile-word (+ (* (ref i) 256) (ref (+ i 1)))) + (loop (+ i 2))))))) +(define (dump-flonum x) + (let ((bits (flonum->bits x))) + (ofile-long flonum-prefix) + (ofile-long (quotient bits 4294967296)) + (ofile-long (modulo bits 4294967296)))) +(define (flonum->inexact-exponential-format x) + (define (exp-form-pos x y i) + (let ((i*2 (+ i i))) + (let ((z (if (and (not (< flonum-e-bias i*2)) (not (< x y))) + (exp-form-pos x (* y y) i*2) + (cons x 0)))) + (let ((a (car z)) (b (cdr z))) + (let ((i+b (+ i b))) + (if (and (not (< flonum-e-bias i+b)) (not (< a y))) + (begin (set-car! z (/ a y)) (set-cdr! z i+b))) + z))))) + (define (exp-form-neg x y i) + (let ((i*2 (+ i i))) + (let ((z (if (and (< i*2 flonum-e-bias-minus-1) (< x y)) + (exp-form-neg x (* y y) i*2) + (cons x 0)))) + (let ((a (car z)) (b (cdr z))) + (let ((i+b (+ i b))) + (if (and (< i+b flonum-e-bias-minus-1) (< a y)) + (begin (set-car! z (/ a y)) (set-cdr! z i+b))) + z))))) + (define (exp-form x) + (if (< x inexact-+1) + (let ((z (exp-form-neg x inexact-+1/2 1))) + (set-car! z (* inexact-+2 (car z))) + (set-cdr! z (- -1 (cdr z))) + z) + (exp-form-pos x inexact-+2 1))) + (if (negative? x) + (let ((z (exp-form (- inexact-0 x)))) + (set-car! z (- inexact-0 (car z))) + z) + (exp-form x))) +(define (flonum->exact-exponential-format x) + (let ((z (flonum->inexact-exponential-format x))) + (let ((y (car z))) + (cond ((not (< y inexact-+2)) + (set-car! z flonum-+m-min) + (set-cdr! z flonum-e-bias-plus-1)) + ((not (< inexact--2 y)) + (set-car! z flonum--m-min) + (set-cdr! z flonum-e-bias-plus-1)) + (else + (set-car! + z + (truncate (inexact->exact (* (car z) inexact-m-min)))))) + (set-cdr! z (- (cdr z) flonum-m-bits)) + z))) +(define (flonum->bits x) + (define (bits a b) + (if (< a flonum-+m-min) + a + (+ (- a flonum-+m-min) + (* (+ (+ b flonum-m-bits) flonum-e-bias) flonum-+m-min)))) + (let ((z (flonum->exact-exponential-format x))) + (let ((a (car z)) (b (cdr z))) + (if (negative? a) (+ flonum-sign-bit (bits (- 0 a) b)) (bits a b))))) +(define flonum-m-bits 52) +(define flonum-e-bits 11) +(define flonum-sign-bit 9223372036854775808) +(define flonum-+m-min 4503599627370496) +(define flonum--m-min -4503599627370496) +(define flonum-e-bias 1023) +(define flonum-e-bias-plus-1 1024) +(define flonum-e-bias-minus-1 1022) +(define inexact-m-min (exact->inexact flonum-+m-min)) +(define inexact-+2 (exact->inexact 2)) +(define inexact--2 (exact->inexact -2)) +(define inexact-+1 (exact->inexact 1)) +(define inexact-+1/2 (/ (exact->inexact 1) (exact->inexact 2))) +(define inexact-0 (exact->inexact 0)) +(define (dump-bignum x) + (define radix 16384) + (define (integer->digits n) + (if (= n 0) + '() + (cons (remainder n radix) (integer->digits (quotient n radix))))) + (let ((l (integer->digits (abs x)))) + (ofile-long (+ (* (+ (length l) 1) 512) (* subtype-bignum 8))) + (if (< x 0) (ofile-word 0) (ofile-word 1)) + (for-each ofile-word l))) +(define (dump-procedure proc) + (let ((bbs (proc-obj-code proc))) + (set! entry-lbl-num (bbs-entry-lbl-num bbs)) + (set! label-counter (bbs-lbl-counter bbs)) + (set! var-descr-queue (queue-empty)) + (set! first-class-label-queue (queue-empty)) + (set! deferred-code-queue (queue-empty)) + (if *info-port* + (begin + (display " #[" *info-port*) + (if (proc-obj-primitive? proc) + (display "primitive " *info-port*) + (display "procedure " *info-port*)) + (display (proc-obj-name proc) *info-port*) + (display "]" *info-port*))) + (if (proc-obj-primitive? proc) + (ofile-prim-proc (proc-obj-name proc)) + (ofile-user-proc)) + (asm.begin!) + (let loop ((prev-bb #f) (prev-gvm-instr #f) (l (bbs->code-list bbs))) + (if (not (null? l)) + (let ((pres-bb (code-bb (car l))) + (pres-gvm-instr (code-gvm-instr (car l))) + (pres-slots-needed (code-slots-needed (car l))) + (next-gvm-instr + (if (null? (cdr l)) #f (code-gvm-instr (cadr l))))) + (if ofile-asm? (asm-comment (car l))) + (gen-gvm-instr + prev-gvm-instr + pres-gvm-instr + next-gvm-instr + pres-slots-needed) + (loop pres-bb pres-gvm-instr (cdr l))))) + (asm.end! + (if debug-info? + (vector (lst->vector (queue->list first-class-label-queue)) + (lst->vector (queue->list var-descr-queue))) + #f)) + (if *info-port* (newline *info-port*)) + (set! var-descr-queue '()) + (set! first-class-label-queue '()) + (set! deferred-code-queue '()) + (set! instr-source '()) + (set! entry-frame '()) + (set! exit-frame '()))) +(define label-counter (lambda () 0)) +(define entry-lbl-num '()) +(define var-descr-queue '()) +(define first-class-label-queue '()) +(define deferred-code-queue '()) +(define instr-source '()) +(define entry-frame '()) +(define exit-frame '()) +(define (defer-code! thunk) (queue-put! deferred-code-queue thunk)) +(define (gen-deferred-code!) + (let loop () + (if (not (queue-empty? deferred-code-queue)) + (let ((thunk (queue-get! deferred-code-queue))) (thunk) (loop))))) +(define (add-var-descr! descr) + (define (index x l) + (let loop ((l l) (i 0)) + (cond ((not (pair? l)) #f) + ((equal? (car l) x) i) + (else (loop (cdr l) (+ i 1)))))) + (let ((n (index descr (queue->list var-descr-queue)))) + (if n + n + (let ((m (length (queue->list var-descr-queue)))) + (queue-put! var-descr-queue descr) + m)))) +(define (add-first-class-label! source slots frame) + (let loop ((i 0) (l1 slots) (l2 '())) + (if (pair? l1) + (let ((var (car l1))) + (let ((x (frame-live? var frame))) + (if (and x (or (pair? x) (not (temp-var? x)))) + (let ((descr-index + (add-var-descr! + (if (pair? x) + (map (lambda (y) (add-var-descr! (var-name y))) x) + (var-name x))))) + (loop (+ i 1) + (cdr l1) + (cons (+ (* i 16384) descr-index) l2))) + (loop (+ i 1) (cdr l1) l2)))) + (let ((label-descr (lst->vector (cons 0 (cons source l2))))) + (queue-put! first-class-label-queue label-descr) + label-descr)))) +(define (gen-gvm-instr prev-gvm-instr gvm-instr next-gvm-instr sn) + (set! instr-source (comment-get (gvm-instr-comment gvm-instr) 'source)) + (set! exit-frame (gvm-instr-frame gvm-instr)) + (set! entry-frame (and prev-gvm-instr (gvm-instr-frame prev-gvm-instr))) + (case (gvm-instr-type gvm-instr) + ((label) + (set! entry-frame exit-frame) + (set! current-fs (frame-size exit-frame)) + (case (label-type gvm-instr) + ((simple) (gen-label-simple (label-lbl-num gvm-instr) sn)) + ((entry) + (gen-label-entry + (label-lbl-num gvm-instr) + (label-entry-nb-parms gvm-instr) + (label-entry-min gvm-instr) + (label-entry-rest? gvm-instr) + (label-entry-closed? gvm-instr) + sn)) + ((return) (gen-label-return (label-lbl-num gvm-instr) sn)) + ((task-entry) (gen-label-task-entry (label-lbl-num gvm-instr) sn)) + ((task-return) (gen-label-task-return (label-lbl-num gvm-instr) sn)) + (else (compiler-internal-error "gen-gvm-instr, unknown label type")))) + ((apply) + (gen-apply + (apply-prim gvm-instr) + (apply-opnds gvm-instr) + (apply-loc gvm-instr) + sn)) + ((copy) (gen-copy (copy-opnd gvm-instr) (copy-loc gvm-instr) sn)) + ((close) (gen-close (close-parms gvm-instr) sn)) + ((ifjump) + (gen-ifjump + (ifjump-test gvm-instr) + (ifjump-opnds gvm-instr) + (ifjump-true gvm-instr) + (ifjump-false gvm-instr) + (ifjump-poll? gvm-instr) + (if (and next-gvm-instr + (memq (label-type next-gvm-instr) '(simple task-entry))) + (label-lbl-num next-gvm-instr) + #f))) + ((jump) + (gen-jump + (jump-opnd gvm-instr) + (jump-nb-args gvm-instr) + (jump-poll? gvm-instr) + (if (and next-gvm-instr + (memq (label-type next-gvm-instr) '(simple task-entry))) + (label-lbl-num next-gvm-instr) + #f))) + (else + (compiler-internal-error + "gen-gvm-instr, unknown 'gvm-instr':" + gvm-instr)))) +(define (reg-in-opnd68 opnd) + (cond ((dreg? opnd) opnd) + ((areg? opnd) opnd) + ((ind? opnd) (ind-areg opnd)) + ((pinc? opnd) (pinc-areg opnd)) + ((pdec? opnd) (pdec-areg opnd)) + ((disp? opnd) (disp-areg opnd)) + ((inx? opnd) (inx-ireg opnd)) + (else #f))) +(define (temp-in-opnd68 opnd) + (let ((reg (reg-in-opnd68 opnd))) + (if reg + (cond ((identical-opnd68? reg dtemp1) reg) + ((identical-opnd68? reg atemp1) reg) + ((identical-opnd68? reg atemp2) reg) + (else #f)) + #f))) +(define (pick-atemp keep) + (if (and keep (identical-opnd68? keep atemp1)) atemp2 atemp1)) +(define return-reg '()) +(define max-nb-args 1024) +(define heap-allocation-fudge (* pointer-size (+ (* 2 max-nb-args) 1024))) +(define intr-flag 0) +(define ltq-tail 1) +(define ltq-head 2) +(define heap-lim 12) +(define closure-lim 17) +(define closure-ptr 18) +(define intr-flag-slot (make-disp* pstate-reg (* pointer-size intr-flag))) +(define ltq-tail-slot (make-disp* pstate-reg (* pointer-size ltq-tail))) +(define ltq-head-slot (make-disp* pstate-reg (* pointer-size ltq-head))) +(define heap-lim-slot (make-disp* pstate-reg (* pointer-size heap-lim))) +(define closure-lim-slot (make-disp* pstate-reg (* pointer-size closure-lim))) +(define closure-ptr-slot (make-disp* pstate-reg (* pointer-size closure-ptr))) +(define touch-trap 1) +(define non-proc-jump-trap 6) +(define rest-params-trap 7) +(define rest-params-closed-trap 8) +(define wrong-nb-arg1-trap 9) +(define wrong-nb-arg1-closed-trap 10) +(define wrong-nb-arg2-trap 11) +(define wrong-nb-arg2-closed-trap 12) +(define heap-alloc1-trap 13) +(define heap-alloc2-trap 14) +(define closure-alloc-trap 15) +(define intr-trap 24) +(define cache-line-length 16) +(define polling-intermittency '()) +(set! polling-intermittency 10) +(define (stat-clear!) (set! *stats* (cons 0 '()))) +(define (stat-dump!) (emit-stat (cdr *stats*))) +(define (stat-add! bin count) + (define (add! stats bin count) + (set-car! stats (+ (car stats) count)) + (if (not (null? bin)) + (let ((x (assoc (car bin) (cdr stats)))) + (if x + (add! (cdr x) (cdr bin) count) + (begin + (set-cdr! stats (cons (list (car bin) 0) (cdr stats))) + (add! (cdadr stats) (cdr bin) count)))))) + (add! *stats* bin count)) +(define (fetch-stat-add! gvm-opnd) (opnd-stat-add! 'fetch gvm-opnd)) +(define (store-stat-add! gvm-opnd) (opnd-stat-add! 'store gvm-opnd)) +(define (jump-stat-add! gvm-opnd) (opnd-stat-add! 'jump gvm-opnd)) +(define (opnd-stat-add! type opnd) + (cond ((reg? opnd) (stat-add! (list 'gvm-opnd 'reg type (reg-num opnd)) 1)) + ((stk? opnd) (stat-add! (list 'gvm-opnd 'stk type) 1)) + ((glo? opnd) (stat-add! (list 'gvm-opnd 'glo type (glo-name opnd)) 1)) + ((clo? opnd) + (stat-add! (list 'gvm-opnd 'clo type) 1) + (fetch-stat-add! (clo-base opnd))) + ((lbl? opnd) (stat-add! (list 'gvm-opnd 'lbl type) 1)) + ((obj? opnd) + (let ((val (obj-val opnd))) + (if (number? val) + (stat-add! (list 'gvm-opnd 'obj type val) 1) + (stat-add! (list 'gvm-opnd 'obj type (obj-type val)) 1)))) + (else + (compiler-internal-error "opnd-stat-add!, unknown 'opnd':" opnd)))) +(define (opnd-stat opnd) + (cond ((reg? opnd) 'reg) + ((stk? opnd) 'stk) + ((glo? opnd) 'glo) + ((clo? opnd) 'clo) + ((lbl? opnd) 'lbl) + ((obj? opnd) 'obj) + (else (compiler-internal-error "opnd-stat, unknown 'opnd':" opnd)))) +(define *stats* '()) +(define (move-opnd68-to-loc68 opnd loc) + (if (not (identical-opnd68? opnd loc)) + (if (imm? opnd) + (move-n-to-loc68 (imm-val opnd) loc) + (emit-move.l opnd loc)))) +(define (move-obj-to-loc68 obj loc) + (let ((n (obj-encoding obj))) + (if n (move-n-to-loc68 n loc) (emit-move.l (emit-const obj) loc)))) +(define (move-n-to-loc68 n loc) + (cond ((= n bits-null) (emit-move.l null-reg loc)) + ((= n bits-false) (emit-move.l false-reg loc)) + ((and (dreg? loc) (>= n -128) (<= n 127)) (emit-moveq n loc)) + ((and (areg? loc) (>= n -32768) (<= n 32767)) + (emit-move.w (make-imm n) loc)) + ((and (identical-opnd68? loc pdec-sp) (>= n -32768) (<= n 32767)) + (emit-pea* n)) + ((= n 0) (emit-clr.l loc)) + ((and (not (and (inx? loc) (= (inx-ireg loc) dtemp1))) + (>= n -128) + (<= n 127)) + (emit-moveq n dtemp1) + (emit-move.l dtemp1 loc)) + (else (emit-move.l (make-imm n) loc)))) +(define (add-n-to-loc68 n loc) + (if (not (= n 0)) + (cond ((and (>= n -8) (<= n 8)) + (if (> n 0) (emit-addq.l n loc) (emit-subq.l (- n) loc))) + ((and (areg? loc) (>= n -32768) (<= n 32767)) + (emit-lea (make-disp loc n) loc)) + ((and (not (identical-opnd68? loc dtemp1)) (>= n -128) (<= n 128)) + (emit-moveq (- (abs n)) dtemp1) + (if (> n 0) (emit-sub.l dtemp1 loc) (emit-add.l dtemp1 loc))) + (else (emit-add.l (make-imm n) loc))))) +(define (power-of-2 n) + (let loop ((i 0) (k 1)) + (cond ((= k n) i) ((> k n) #f) (else (loop (+ i 1) (* k 2)))))) +(define (mul-n-to-reg68 n reg) + (if (= n 0) + (emit-moveq 0 reg) + (let ((abs-n (abs n))) + (if (= abs-n 1) + (if (< n 0) (emit-neg.l reg)) + (let ((shift (power-of-2 abs-n))) + (if shift + (let ((m (min shift 32))) + (if (or (<= m 8) (identical-opnd68? reg dtemp1)) + (let loop ((i m)) + (if (> i 0) + (begin + (emit-asl.l (make-imm (min i 8)) reg) + (loop (- i 8))))) + (begin (emit-moveq m dtemp1) (emit-asl.l dtemp1 reg))) + (if (< n 0) (emit-neg.l reg))) + (emit-muls.l (make-imm n) reg))))))) +(define (div-n-to-reg68 n reg) + (let ((abs-n (abs n))) + (if (= abs-n 1) + (if (< n 0) (emit-neg.l reg)) + (let ((shift (power-of-2 abs-n))) + (if shift + (let ((m (min shift 32)) (lbl (new-lbl!))) + (emit-move.l reg reg) + (emit-bpl lbl) + (add-n-to-loc68 (* (- abs-n 1) 8) reg) + (emit-label lbl) + (if (or (<= m 8) (identical-opnd68? reg dtemp1)) + (let loop ((i m)) + (if (> i 0) + (begin + (emit-asr.l (make-imm (min i 8)) reg) + (loop (- i 8))))) + (begin (emit-moveq m dtemp1) (emit-asr.l dtemp1 reg))) + (if (< n 0) (emit-neg.l reg))) + (emit-divsl.l (make-imm n) reg reg)))))) +(define (cmp-n-to-opnd68 n opnd) + (cond ((= n bits-null) (emit-cmp.l opnd null-reg) #f) + ((= n bits-false) (emit-cmp.l opnd false-reg) #f) + ((or (pcr? opnd) (imm? opnd)) + (if (= n 0) + (begin (emit-move.l opnd dtemp1) #t) + (begin + (move-opnd68-to-loc68 opnd atemp1) + (if (and (>= n -32768) (<= n 32767)) + (emit-cmp.w (make-imm n) atemp1) + (emit-cmp.l (make-imm n) atemp1)) + #t))) + ((= n 0) (emit-move.l opnd dtemp1) #t) + ((and (>= n -128) (<= n 127) (not (identical-opnd68? opnd dtemp1))) + (emit-moveq n dtemp1) + (emit-cmp.l opnd dtemp1) + #f) + (else (emit-cmp.l (make-imm n) opnd) #t))) +(define current-fs '()) +(define (adjust-current-fs n) (set! current-fs (+ current-fs n))) +(define (new-lbl!) (label-counter)) +(define (needed? loc sn) (and loc (if (stk? loc) (<= (stk-num loc) sn) #t))) +(define (sn-opnd opnd sn) + (cond ((stk? opnd) (max (stk-num opnd) sn)) + ((clo? opnd) (sn-opnd (clo-base opnd) sn)) + (else sn))) +(define (sn-opnds opnds sn) + (if (null? opnds) sn (sn-opnd (car opnds) (sn-opnds (cdr opnds) sn)))) +(define (sn-opnd68 opnd sn) + (cond ((and (disp*? opnd) (identical-opnd68? (disp*-areg opnd) sp-reg)) + (max (disp*-offset opnd) sn)) + ((identical-opnd68? opnd pdec-sp) (max (+ current-fs 1) sn)) + ((identical-opnd68? opnd pinc-sp) (max current-fs sn)) + (else sn))) +(define (resize-frame n) + (let ((x (- n current-fs))) + (adjust-current-fs x) + (add-n-to-loc68 (* (- pointer-size) x) sp-reg))) +(define (shrink-frame n) + (cond ((< n current-fs) (resize-frame n)) + ((> n current-fs) + (compiler-internal-error "shrink-frame, can't increase frame size")))) +(define (make-top-of-frame n sn) + (if (and (< n current-fs) (>= n sn)) (resize-frame n))) +(define (make-top-of-frame-if-stk-opnd68 opnd sn) + (if (frame-base-rel? opnd) + (make-top-of-frame (frame-base-rel-slot opnd) sn))) +(define (make-top-of-frame-if-stk-opnds68 opnd1 opnd2 sn) + (if (frame-base-rel? opnd1) + (let ((slot1 (frame-base-rel-slot opnd1))) + (if (frame-base-rel? opnd2) + (make-top-of-frame (max (frame-base-rel-slot opnd2) slot1) sn) + (make-top-of-frame slot1 sn))) + (if (frame-base-rel? opnd2) + (make-top-of-frame (frame-base-rel-slot opnd2) sn)))) +(define (opnd68->true-opnd68 opnd sn) + (if (frame-base-rel? opnd) + (let ((slot (frame-base-rel-slot opnd))) + (cond ((> slot current-fs) (adjust-current-fs 1) pdec-sp) + ((and (= slot current-fs) (< sn current-fs)) + (adjust-current-fs -1) + pinc-sp) + (else (make-disp* sp-reg (* pointer-size (- current-fs slot)))))) + opnd)) +(define (move-opnd68-to-any-areg opnd keep sn) + (if (areg? opnd) + opnd + (let ((areg (pick-atemp keep))) + (make-top-of-frame-if-stk-opnd68 opnd sn) + (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn) areg) + areg))) +(define (clo->opnd68 opnd keep sn) + (let ((base (clo-base opnd)) (offs (closed-var-offset (clo-index opnd)))) + (if (lbl? base) (make-pcr (lbl-num base) offs) (clo->loc68 opnd keep sn)))) +(define (clo->loc68 opnd keep sn) + (let ((base (clo-base opnd)) (offs (closed-var-offset (clo-index opnd)))) + (cond ((eq? base return-reg) (make-disp* (reg->reg68 base) offs)) + ((obj? base) + (let ((areg (pick-atemp keep))) + (move-obj-to-loc68 (obj-val base) areg) + (make-disp* areg offs))) + (else + (let ((areg (pick-atemp keep))) + (move-opnd-to-loc68 base areg sn) + (make-disp* areg offs)))))) +(define (reg->reg68 reg) (reg-num->reg68 (reg-num reg))) +(define (reg-num->reg68 num) + (if (= num 0) (make-areg gvm-reg0) (make-dreg (+ (- num 1) gvm-reg1)))) +(define (opnd->opnd68 opnd keep sn) + (cond ((lbl? opnd) + (let ((areg (pick-atemp keep))) + (emit-lea (make-pcr (lbl-num opnd) 0) areg) + areg)) + ((obj? opnd) + (let ((val (obj-val opnd))) + (if (proc-obj? val) + (let ((num (add-object val)) (areg (pick-atemp keep))) + (if num (emit-move-proc num areg) (emit-move-prim val areg)) + areg) + (let ((n (obj-encoding val))) + (if n (make-imm n) (emit-const val)))))) + ((clo? opnd) (clo->opnd68 opnd keep sn)) + (else (loc->loc68 opnd keep sn)))) +(define (loc->loc68 loc keep sn) + (cond ((reg? loc) (reg->reg68 loc)) + ((stk? loc) (make-frame-base-rel (stk-num loc))) + ((glo? loc) (make-glob (glo-name loc))) + ((clo? loc) (clo->loc68 loc keep sn)) + (else (compiler-internal-error "loc->loc68, unknown 'loc':" loc)))) +(define (move-opnd68-to-loc opnd loc sn) + (cond ((reg? loc) + (make-top-of-frame-if-stk-opnd68 opnd sn) + (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn) (reg->reg68 loc))) + ((stk? loc) + (let* ((loc-slot (stk-num loc)) + (sn-after-opnd1 (if (< loc-slot sn) sn (- loc-slot 1)))) + (if (> current-fs loc-slot) + (make-top-of-frame + (if (frame-base-rel? opnd) + (let ((opnd-slot (frame-base-rel-slot opnd))) + (if (>= opnd-slot (- loc-slot 1)) opnd-slot loc-slot)) + loc-slot) + sn-after-opnd1)) + (let* ((opnd1 (opnd68->true-opnd68 opnd sn-after-opnd1)) + (opnd2 (opnd68->true-opnd68 + (make-frame-base-rel loc-slot) + sn))) + (move-opnd68-to-loc68 opnd1 opnd2)))) + ((glo? loc) + (make-top-of-frame-if-stk-opnd68 opnd sn) + (move-opnd68-to-loc68 + (opnd68->true-opnd68 opnd sn) + (make-glob (glo-name loc)))) + ((clo? loc) + (let ((clo (clo->loc68 + loc + (temp-in-opnd68 opnd) + (sn-opnd68 opnd sn)))) + (make-top-of-frame-if-stk-opnd68 opnd sn) + (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd sn) clo))) + (else + (compiler-internal-error "move-opnd68-to-loc, unknown 'loc':" loc)))) +(define (move-opnd-to-loc68 opnd loc68 sn) + (if (and (lbl? opnd) (areg? loc68)) + (emit-lea (make-pcr (lbl-num opnd) 0) loc68) + (let* ((sn-after-opnd68 (sn-opnd68 loc68 sn)) + (opnd68 (opnd->opnd68 + opnd + (temp-in-opnd68 loc68) + sn-after-opnd68))) + (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn) + (let* ((opnd68* (opnd68->true-opnd68 opnd68 sn-after-opnd68)) + (loc68* (opnd68->true-opnd68 loc68 sn))) + (move-opnd68-to-loc68 opnd68* loc68*))))) +(define (copy-opnd-to-loc opnd loc sn) + (if (and (lbl? opnd) (eq? loc return-reg)) + (emit-lea (make-pcr (lbl-num opnd) 0) (reg->reg68 loc)) + (move-opnd68-to-loc (opnd->opnd68 opnd #f (sn-opnd loc sn)) loc sn))) +(define (touch-reg68-to-reg68 src dst) + (define (trap-to-touch-handler dreg lbl) + (if ofile-stats? + (emit-stat + '((touch 0 + (determined-placeholder -1) + (undetermined-placeholder 1))))) + (gen-trap + instr-source + entry-frame + #t + dreg + (+ touch-trap (dreg-num dreg)) + lbl)) + (define (touch-dreg-to-reg src dst) + (let ((lbl1 (new-lbl!))) + (emit-btst src placeholder-reg) + (emit-bne lbl1) + (if ofile-stats? + (emit-stat + '((touch 0 (non-placeholder -1) (determined-placeholder 1))))) + (trap-to-touch-handler src lbl1) + (move-opnd68-to-loc68 src dst))) + (define (touch-areg-to-dreg src dst) + (let ((lbl1 (new-lbl!))) + (emit-move.l src dst) + (emit-btst dst placeholder-reg) + (emit-bne lbl1) + (if ofile-stats? + (emit-stat + '((touch 0 (non-placeholder -1) (determined-placeholder 1))))) + (trap-to-touch-handler dst lbl1))) + (if ofile-stats? (emit-stat '((touch 1 (non-placeholder 1))))) + (cond ((dreg? src) (touch-dreg-to-reg src dst)) + ((dreg? dst) (touch-areg-to-dreg src dst)) + (else (emit-move.l src dtemp1) (touch-dreg-to-reg dtemp1 dst)))) +(define (touch-opnd-to-any-reg68 opnd sn) + (if (reg? opnd) + (let ((reg (reg->reg68 opnd))) (touch-reg68-to-reg68 reg reg) reg) + (let ((opnd68 (opnd->opnd68 opnd #f sn))) + (make-top-of-frame-if-stk-opnd68 opnd68 sn) + (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd68 sn) dtemp1) + (touch-reg68-to-reg68 dtemp1 dtemp1) + dtemp1))) +(define (touch-opnd-to-loc opnd loc sn) + (if (reg? opnd) + (let ((reg68 (reg->reg68 opnd))) + (if (reg? loc) + (touch-reg68-to-reg68 reg68 (reg->reg68 loc)) + (begin + (touch-reg68-to-reg68 reg68 reg68) + (move-opnd68-to-loc reg68 loc sn)))) + (if (reg? loc) + (let ((reg68 (reg->reg68 loc))) + (move-opnd-to-loc68 opnd reg68 sn) + (touch-reg68-to-reg68 reg68 reg68)) + (let ((reg68 (touch-opnd-to-any-reg68 opnd sn))) + (move-opnd68-to-loc reg68 loc sn))))) +(define (gen-trap source frame save-live? not-save-reg num lbl) + (define (adjust-slots l n) + (cond ((= n 0) (append l '())) + ((< n 0) (adjust-slots (cdr l) (+ n 1))) + (else (adjust-slots (cons empty-var l) (- n 1))))) + (define (set-slot! slots i x) + (let loop ((l slots) (n (- (length slots) i))) + (if (> n 0) (loop (cdr l) (- n 1)) (set-car! l x)))) + (let ((ret-slot (frame-first-empty-slot frame))) + (let loop1 ((save1 '()) (save2 #f) (regs (frame-regs frame)) (i 0)) + (if (pair? regs) + (let ((var (car regs))) + (if (eq? var ret-var) + (let ((x (cons (reg->reg68 (make-reg i)) var))) + (if (> ret-slot current-fs) + (loop1 (cons x save1) save2 (cdr regs) (+ i 1)) + (loop1 save1 x (cdr regs) (+ i 1)))) + (if (and save-live? + (frame-live? var frame) + (not (eqv? not-save-reg (reg->reg68 (make-reg i))))) + (loop1 (cons (cons (reg->reg68 (make-reg i)) var) save1) + save2 + (cdr regs) + (+ i 1)) + (loop1 save1 save2 (cdr regs) (+ i 1))))) + (let ((order (sort-list save1 (lambda (x y) (< (car x) (car y)))))) + (let ((slots (append (map cdr order) + (adjust-slots + (frame-slots frame) + (- current-fs (frame-size frame))))) + (reg-list (map car order)) + (nb-regs (length order))) + (define (trap) + (emit-trap2 num '()) + (gen-label-return* + (new-lbl!) + (add-first-class-label! source slots frame) + slots + 0)) + (if save2 + (begin + (emit-move.l + (car save2) + (make-disp* + sp-reg + (* pointer-size (- current-fs ret-slot)))) + (set-slot! slots ret-slot (cdr save2)))) + (if (> (length order) 2) + (begin + (emit-movem.l reg-list pdec-sp) + (trap) + (emit-movem.l pinc-sp reg-list)) + (let loop2 ((l (reverse reg-list))) + (if (pair? l) + (let ((reg (car l))) + (emit-move.l reg pdec-sp) + (loop2 (cdr l)) + (emit-move.l pinc-sp reg)) + (trap)))) + (if save2 + (emit-move.l + (make-disp* sp-reg (* pointer-size (- current-fs ret-slot))) + (car save2))) + (emit-label lbl))))))) +(define (gen-label-simple lbl sn) + (if ofile-stats? + (begin (stat-clear!) (stat-add! '(gvm-instr label simple) 1))) + (set! pointers-allocated 0) + (emit-label lbl)) +(define (gen-label-entry lbl nb-parms min rest? closed? sn) + (if ofile-stats? + (begin + (stat-clear!) + (stat-add! + (list 'gvm-instr + 'label + 'entry + nb-parms + min + (if rest? 'rest 'not-rest) + (if closed? 'closed 'not-closed)) + 1))) + (set! pointers-allocated 0) + (let ((label-descr (add-first-class-label! instr-source '() exit-frame))) + (if (= lbl entry-lbl-num) + (emit-label lbl) + (emit-label-subproc lbl entry-lbl-num label-descr))) + (let* ((nb-parms* (if rest? (- nb-parms 1) nb-parms)) + (dispatch-lbls (make-vector (+ (- nb-parms min) 1))) + (optional-lbls (make-vector (+ (- nb-parms min) 1)))) + (let loop ((i min)) + (if (<= i nb-parms) + (let ((lbl (new-lbl!))) + (vector-set! optional-lbls (- nb-parms i) lbl) + (vector-set! + dispatch-lbls + (- nb-parms i) + (if (or (>= i nb-parms) (<= nb-parms nb-arg-regs)) + lbl + (new-lbl!))) + (loop (+ i 1))))) + (if closed? + (let ((closure-reg (reg-num->reg68 (+ nb-arg-regs 1)))) + (emit-move.l pinc-sp closure-reg) + (emit-subq.l 6 closure-reg) + (if (or (and (<= min 1) (<= 1 nb-parms*)) + (and (<= min 2) (<= 2 nb-parms*))) + (emit-move.w dtemp1 dtemp1)))) + (if (and (<= min 2) (<= 2 nb-parms*)) + (emit-beq (vector-ref dispatch-lbls (- nb-parms 2)))) + (if (and (<= min 1) (<= 1 nb-parms*)) + (emit-bmi (vector-ref dispatch-lbls (- nb-parms 1)))) + (let loop ((i min)) + (if (<= i nb-parms*) + (begin + (if (not (or (= i 1) (= i 2))) + (begin + (emit-cmp.w (make-imm (encode-arg-count i)) arg-count-reg) + (emit-beq (vector-ref dispatch-lbls (- nb-parms i))))) + (loop (+ i 1))))) + (cond (rest? + (emit-trap1 + (if closed? rest-params-closed-trap rest-params-trap) + (list min nb-parms*)) + (if (not closed?) (emit-lbl-ptr lbl)) + (set! pointers-allocated 1) + (gen-guarantee-fudge) + (emit-bra (vector-ref optional-lbls 0))) + ((= min nb-parms*) + (emit-trap1 + (if closed? wrong-nb-arg1-closed-trap wrong-nb-arg1-trap) + (list nb-parms*)) + (if (not closed?) (emit-lbl-ptr lbl))) + (else + (emit-trap1 + (if closed? wrong-nb-arg2-closed-trap wrong-nb-arg2-trap) + (list min nb-parms*)) + (if (not closed?) (emit-lbl-ptr lbl)))) + (if (> nb-parms nb-arg-regs) + (let loop1 ((i (- nb-parms 1))) + (if (>= i min) + (let ((nb-stacked (if (<= i nb-arg-regs) 0 (- i nb-arg-regs)))) + (emit-label (vector-ref dispatch-lbls (- nb-parms i))) + (let loop2 ((j 1)) + (if (and (<= j nb-arg-regs) + (<= j i) + (<= j (- (- nb-parms nb-arg-regs) nb-stacked))) + (begin + (emit-move.l (reg-num->reg68 j) pdec-sp) + (loop2 (+ j 1))) + (let loop3 ((k j)) + (if (and (<= k nb-arg-regs) (<= k i)) + (begin + (emit-move.l + (reg-num->reg68 k) + (reg-num->reg68 (+ (- k j) 1))) + (loop3 (+ k 1))))))) + (if (> i min) + (emit-bra (vector-ref optional-lbls (- nb-parms i)))) + (loop1 (- i 1)))))) + (let loop ((i min)) + (if (<= i nb-parms) + (let ((val (if (= i nb-parms*) bits-null bits-unass))) + (emit-label (vector-ref optional-lbls (- nb-parms i))) + (cond ((> (- nb-parms i) nb-arg-regs) + (move-n-to-loc68 val pdec-sp)) + ((< i nb-parms) + (move-n-to-loc68 + val + (reg-num->reg68 (parm->reg-num (+ i 1) nb-parms))))) + (loop (+ i 1))))))) +(define (encode-arg-count n) (cond ((= n 1) -1) ((= n 2) 0) (else (+ n 1)))) +(define (parm->reg-num i nb-parms) + (if (<= nb-parms nb-arg-regs) i (+ i (- nb-arg-regs nb-parms)))) +(define (no-arg-check-entry-offset proc nb-args) + (let ((x (proc-obj-call-pat proc))) + (if (and (pair? x) (null? (cdr x))) + (let ((arg-count (car x))) + (if (= arg-count nb-args) + (if (or (= arg-count 1) (= arg-count 2)) 10 14) + 0)) + 0))) +(define (gen-label-return lbl sn) + (if ofile-stats? + (begin (stat-clear!) (stat-add! '(gvm-instr label return) 1))) + (set! pointers-allocated 0) + (let ((slots (frame-slots exit-frame))) + (gen-label-return* + lbl + (add-first-class-label! instr-source slots exit-frame) + slots + 0))) +(define (gen-label-return* lbl label-descr slots extra) + (let ((i (pos-in-list ret-var slots))) + (if i + (let* ((fs (length slots)) (link (- fs i))) + (emit-label-return lbl entry-lbl-num (+ fs extra) link label-descr)) + (compiler-internal-error + "gen-label-return*, no return address in frame")))) +(define (gen-label-task-entry lbl sn) + (if ofile-stats? + (begin (stat-clear!) (stat-add! '(gvm-instr label task-entry) 1))) + (set! pointers-allocated 0) + (emit-label lbl) + (if (= current-fs 0) + (begin + (emit-move.l (reg->reg68 return-reg) pdec-sp) + (emit-move.l sp-reg (make-pinc ltq-tail-reg))) + (begin + (emit-move.l sp-reg atemp1) + (emit-move.l (make-pinc atemp1) pdec-sp) + (let loop ((i (- current-fs 1))) + (if (> i 0) + (begin + (emit-move.l (make-pinc atemp1) (make-disp atemp1 -8)) + (loop (- i 1))))) + (emit-move.l (reg->reg68 return-reg) (make-pdec atemp1)) + (emit-move.l atemp1 (make-pinc ltq-tail-reg)))) + (emit-move.l ltq-tail-reg ltq-tail-slot)) +(define (gen-label-task-return lbl sn) + (if ofile-stats? + (begin (stat-clear!) (stat-add! '(gvm-instr label task-return) 1))) + (set! pointers-allocated 0) + (let ((slots (frame-slots exit-frame))) + (set! current-fs (+ current-fs 1)) + (let ((dummy-lbl (new-lbl!)) (skip-lbl (new-lbl!))) + (gen-label-return* + dummy-lbl + (add-first-class-label! instr-source slots exit-frame) + slots + 1) + (emit-bra skip-lbl) + (gen-label-task-return* + lbl + (add-first-class-label! instr-source slots exit-frame) + slots + 1) + (emit-subq.l pointer-size ltq-tail-reg) + (emit-label skip-lbl)))) +(define (gen-label-task-return* lbl label-descr slots extra) + (let ((i (pos-in-list ret-var slots))) + (if i + (let* ((fs (length slots)) (link (- fs i))) + (emit-label-task-return + lbl + entry-lbl-num + (+ fs extra) + link + label-descr)) + (compiler-internal-error + "gen-label-task-return*, no return address in frame")))) +(define (gen-apply prim opnds loc sn) + (if ofile-stats? + (begin + (stat-add! + (list 'gvm-instr + 'apply + (string->canonical-symbol (proc-obj-name prim)) + (map opnd-stat opnds) + (if loc (opnd-stat loc) #f)) + 1) + (for-each fetch-stat-add! opnds) + (if loc (store-stat-add! loc)))) + (let ((x (proc-obj-inlinable prim))) + (if (not x) + (compiler-internal-error "gen-APPLY, unknown 'prim':" prim) + (if (or (needed? loc sn) (car x)) ((cdr x) opnds loc sn))))) +(define (define-apply name side-effects? proc) + (let ((prim (get-prim-info name))) + (proc-obj-inlinable-set! prim (cons side-effects? proc)))) +(define (gen-copy opnd loc sn) + (if ofile-stats? + (begin + (stat-add! (list 'gvm-instr 'copy (opnd-stat opnd) (opnd-stat loc)) 1) + (fetch-stat-add! opnd) + (store-stat-add! loc))) + (if (needed? loc sn) (copy-opnd-to-loc opnd loc sn))) +(define (gen-close parms sn) + (define (size->bytes size) + (* (quotient + (+ (* (+ size 2) pointer-size) (- cache-line-length 1)) + cache-line-length) + cache-line-length)) + (define (parms->bytes parms) + (if (null? parms) + 0 + (+ (size->bytes (length (closure-parms-opnds (car parms)))) + (parms->bytes (cdr parms))))) + (if ofile-stats? + (begin + (for-each + (lambda (x) + (stat-add! + (list 'gvm-instr + 'close + (opnd-stat (closure-parms-loc x)) + (map opnd-stat (closure-parms-opnds x))) + 1) + (store-stat-add! (closure-parms-loc x)) + (fetch-stat-add! (make-lbl (closure-parms-lbl x))) + (for-each fetch-stat-add! (closure-parms-opnds x))) + parms))) + (let ((total-space-needed (parms->bytes parms)) (lbl1 (new-lbl!))) + (emit-move.l closure-ptr-slot atemp2) + (move-n-to-loc68 total-space-needed dtemp1) + (emit-sub.l dtemp1 atemp2) + (emit-cmp.l closure-lim-slot atemp2) + (emit-bcc lbl1) + (gen-trap instr-source entry-frame #f #f closure-alloc-trap lbl1) + (emit-move.l atemp2 closure-ptr-slot) + (let* ((opnds* (apply append (map closure-parms-opnds parms))) + (sn* (sn-opnds opnds* sn))) + (let loop1 ((parms parms)) + (let ((loc (closure-parms-loc (car parms))) + (size (length (closure-parms-opnds (car parms)))) + (rest (cdr parms))) + (if (= size 1) + (emit-addq.l type-procedure atemp2) + (emit-move.w + (make-imm (+ 32768 (* (+ size 1) 4))) + (make-pinc atemp2))) + (move-opnd68-to-loc + atemp2 + loc + (sn-opnds (map closure-parms-loc rest) sn*)) + (if (null? rest) + (add-n-to-loc68 + (+ (- (size->bytes size) total-space-needed) 2) + atemp2) + (begin + (add-n-to-loc68 (- (size->bytes size) type-procedure) atemp2) + (loop1 rest))))) + (let loop2 ((parms parms)) + (let* ((opnds (closure-parms-opnds (car parms))) + (lbl (closure-parms-lbl (car parms))) + (size (length opnds)) + (rest (cdr parms))) + (emit-lea (make-pcr lbl 0) atemp1) + (emit-move.l atemp1 (make-pinc atemp2)) + (let loop3 ((opnds opnds)) + (if (not (null? opnds)) + (let ((sn** (sn-opnds + (apply append (map closure-parms-opnds rest)) + sn))) + (move-opnd-to-loc68 + (car opnds) + (make-pinc atemp2) + (sn-opnds (cdr opnds) sn**)) + (loop3 (cdr opnds))))) + (if (not (null? rest)) + (begin + (add-n-to-loc68 + (- (size->bytes size) (* (+ size 1) pointer-size)) + atemp2) + (loop2 rest)))))))) +(define (gen-ifjump test opnds true-lbl false-lbl poll? next-lbl) + (if ofile-stats? + (begin + (stat-add! + (list 'gvm-instr + 'ifjump + (string->canonical-symbol (proc-obj-name test)) + (map opnd-stat opnds) + (if poll? 'poll 'not-poll)) + 1) + (for-each fetch-stat-add! opnds) + (stat-dump!))) + (let ((proc (proc-obj-test test))) + (if proc + (gen-ifjump* proc opnds true-lbl false-lbl poll? next-lbl) + (compiler-internal-error "gen-IFJUMP, unknown 'test':" test)))) +(define (gen-ifjump* proc opnds true-lbl false-lbl poll? next-lbl) + (let ((fs (frame-size exit-frame))) + (define (double-branch) + (proc #t opnds false-lbl fs) + (if ofile-stats? + (emit-stat + '((gvm-instr.ifjump.fall-through 1) + (gvm-instr.ifjump.double-branch 1)))) + (emit-bra true-lbl) + (gen-deferred-code!)) + (gen-guarantee-fudge) + (if poll? (gen-poll)) + (if next-lbl + (cond ((= true-lbl next-lbl) + (proc #t opnds false-lbl fs) + (if ofile-stats? + (emit-stat '((gvm-instr.ifjump.fall-through 1))))) + ((= false-lbl next-lbl) + (proc #f opnds true-lbl fs) + (if ofile-stats? + (emit-stat '((gvm-instr.ifjump.fall-through 1))))) + (else (double-branch))) + (double-branch)))) +(define (define-ifjump name proc) + (define-apply + name + #f + (lambda (opnds loc sn) + (let ((true-lbl (new-lbl!)) + (cont-lbl (new-lbl!)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (proc #f opnds true-lbl current-fs) + (move-n-to-loc68 bits-false reg68) + (emit-bra cont-lbl) + (emit-label true-lbl) + (move-n-to-loc68 bits-true reg68) + (emit-label cont-lbl) + (move-opnd68-to-loc reg68 loc sn)))) + (proc-obj-test-set! (get-prim-info name) proc)) +(define (gen-jump opnd nb-args poll? next-lbl) + (let ((fs (frame-size exit-frame))) + (if ofile-stats? + (begin + (stat-add! + (list 'gvm-instr + 'jump + (opnd-stat opnd) + nb-args + (if poll? 'poll 'not-poll)) + 1) + (jump-stat-add! opnd) + (if (and (lbl? opnd) next-lbl (= next-lbl (lbl-num opnd))) + (stat-add! '(gvm-instr.jump.fall-through) 1)) + (stat-dump!))) + (gen-guarantee-fudge) + (cond ((glo? opnd) + (if poll? (gen-poll)) + (setup-jump fs nb-args) + (emit-jmp-glob (make-glob (glo-name opnd))) + (gen-deferred-code!)) + ((and (stk? opnd) (= (stk-num opnd) (+ fs 1)) (not nb-args)) + (if poll? (gen-poll)) + (setup-jump (+ fs 1) nb-args) + (emit-rts) + (gen-deferred-code!)) + ((lbl? opnd) + (if (and poll? + (= fs current-fs) + (not nb-args) + (not (and next-lbl (= next-lbl (lbl-num opnd))))) + (gen-poll-branch (lbl-num opnd)) + (begin + (if poll? (gen-poll)) + (setup-jump fs nb-args) + (if (not (and next-lbl (= next-lbl (lbl-num opnd)))) + (emit-bra (lbl-num opnd)))))) + ((obj? opnd) + (if poll? (gen-poll)) + (let ((val (obj-val opnd))) + (if (proc-obj? val) + (let ((num (add-object val)) + (offset (no-arg-check-entry-offset val nb-args))) + (setup-jump fs (if (<= offset 0) nb-args #f)) + (if num + (emit-jmp-proc num offset) + (emit-jmp-prim val offset)) + (gen-deferred-code!)) + (gen-jump* (opnd->opnd68 opnd #f fs) fs nb-args)))) + (else + (if poll? (gen-poll)) + (gen-jump* (opnd->opnd68 opnd #f fs) fs nb-args))))) +(define (gen-jump* opnd fs nb-args) + (if nb-args + (let ((lbl (new-lbl!))) + (make-top-of-frame-if-stk-opnd68 opnd fs) + (move-opnd68-to-loc68 (opnd68->true-opnd68 opnd fs) atemp1) + (shrink-frame fs) + (emit-move.l atemp1 dtemp1) + (emit-addq.w (modulo (- type-pair type-procedure) 8) dtemp1) + (emit-btst dtemp1 pair-reg) + (emit-beq lbl) + (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg) + (emit-trap3 non-proc-jump-trap) + (emit-label lbl) + (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg) + (emit-jmp (make-ind atemp1))) + (let ((areg (move-opnd68-to-any-areg opnd #f fs))) + (setup-jump fs nb-args) + (emit-jmp (make-ind areg)))) + (gen-deferred-code!)) +(define (setup-jump fs nb-args) + (shrink-frame fs) + (if nb-args (move-n-to-loc68 (encode-arg-count nb-args) arg-count-reg))) +(define (gen-poll) + (let ((lbl (new-lbl!))) + (emit-dbra poll-timer-reg lbl) + (emit-moveq (- polling-intermittency 1) poll-timer-reg) + (emit-cmp.l intr-flag-slot sp-reg) + (emit-bcc lbl) + (gen-trap instr-source entry-frame #f #f intr-trap lbl))) +(define (gen-poll-branch lbl) + (emit-dbra poll-timer-reg lbl) + (emit-moveq (- polling-intermittency 1) poll-timer-reg) + (emit-cmp.l intr-flag-slot sp-reg) + (emit-bcc lbl) + (gen-trap instr-source entry-frame #f #f intr-trap (new-lbl!)) + (emit-bra lbl)) +(define (make-gen-slot-ref slot type) + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) (opnd (car opnds))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (move-opnd68-to-loc + (make-disp* atemp1 (- (* slot pointer-size) type)) + loc + sn)))) +(define (make-gen-slot-set! slot type) + (lambda (opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let* ((first-opnd (car opnds)) + (second-opnd (cadr opnds)) + (sn-second-opnd (sn-opnd second-opnd sn-loc))) + (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd) + (move-opnd-to-loc68 + second-opnd + (make-disp* atemp1 (- (* slot pointer-size) type)) + sn-loc) + (if loc + (if (not (eq? first-opnd loc)) + (move-opnd68-to-loc atemp1 loc sn))))))) +(define (gen-cons opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (let ((first-opnd (car opnds)) (second-opnd (cadr opnds))) + (gen-guarantee-space 2) + (if (contains-opnd? loc second-opnd) + (let ((sn-second-opnd (sn-opnd second-opnd sn-loc))) + (move-opnd-to-loc68 first-opnd (make-pdec heap-reg) sn-second-opnd) + (move-opnd68-to-loc68 heap-reg atemp2) + (move-opnd-to-loc68 second-opnd (make-pdec heap-reg) sn-loc) + (move-opnd68-to-loc atemp2 loc sn)) + (let* ((sn-second-opnd (sn-opnd second-opnd sn)) + (sn-loc (sn-opnd loc sn-second-opnd))) + (move-opnd-to-loc68 first-opnd (make-pdec heap-reg) sn-loc) + (move-opnd68-to-loc heap-reg loc sn-second-opnd) + (move-opnd-to-loc68 second-opnd (make-pdec heap-reg) sn)))))) +(define (make-gen-apply-c...r pattern) + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) (opnd (car opnds))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (let loop ((pattern pattern)) + (if (<= pattern 3) + (if (= pattern 3) + (move-opnd68-to-loc (make-pdec atemp1) loc sn) + (move-opnd68-to-loc (make-ind atemp1) loc sn)) + (begin + (if (odd? pattern) + (emit-move.l (make-pdec atemp1) atemp1) + (emit-move.l (make-ind atemp1) atemp1)) + (loop (quotient pattern 2)))))))) +(define (gen-set-car! opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let* ((first-opnd (car opnds)) + (second-opnd (cadr opnds)) + (sn-second-opnd (sn-opnd second-opnd sn-loc))) + (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd) + (move-opnd-to-loc68 second-opnd (make-ind atemp1) sn-loc) + (if (and loc (not (eq? first-opnd loc))) + (move-opnd68-to-loc atemp1 loc sn))))) +(define (gen-set-cdr! opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let* ((first-opnd (car opnds)) + (second-opnd (cadr opnds)) + (sn-second-opnd (sn-opnd second-opnd sn-loc))) + (move-opnd-to-loc68 first-opnd atemp1 sn-second-opnd) + (if (and loc (not (eq? first-opnd loc))) + (move-opnd-to-loc68 + second-opnd + (make-disp atemp1 (- pointer-size)) + sn-loc) + (move-opnd-to-loc68 second-opnd (make-pdec atemp1) sn-loc)) + (if (and loc (not (eq? first-opnd loc))) + (move-opnd68-to-loc atemp1 loc sn))))) +(define (commut-oper gen opnds loc sn self? accum-self accum-other) + (if (null? opnds) + (gen (reverse accum-self) (reverse accum-other) loc sn self?) + (let ((opnd (car opnds)) (rest (cdr opnds))) + (cond ((and (not self?) (eq? opnd loc)) + (commut-oper gen rest loc sn #t accum-self accum-other)) + ((contains-opnd? loc opnd) + (commut-oper + gen + rest + loc + sn + self? + (cons opnd accum-self) + accum-other)) + (else + (commut-oper + gen + rest + loc + sn + self? + accum-self + (cons opnd accum-other))))))) +(define (gen-add-in-place opnds loc68 sn) + (if (not (null? opnds)) + (let* ((first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)) + (opnd68 (opnd->opnd68 + first-opnd + (temp-in-opnd68 loc68) + (sn-opnd68 loc68 sn)))) + (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds) + (if (imm? opnd68) + (add-n-to-loc68 + (imm-val opnd68) + (opnd68->true-opnd68 loc68 sn-other-opnds)) + (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds))) + (if (or (dreg? opnd68) (reg68? loc68)) + (emit-add.l + opnd68* + (opnd68->true-opnd68 loc68 sn-other-opnds)) + (begin + (move-opnd68-to-loc68 opnd68* dtemp1) + (emit-add.l + dtemp1 + (opnd68->true-opnd68 loc68 sn-other-opnds)))))) + (gen-add-in-place other-opnds loc68 sn)))) +(define (gen-add self-opnds other-opnds loc sn self?) + (let* ((opnds (append self-opnds other-opnds)) + (first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))) + (if (<= (length self-opnds) 1) + (let ((loc68 (loc->loc68 loc #f sn-first-opnd))) + (if self? + (gen-add-in-place opnds loc68 sn) + (begin + (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds) + (gen-add-in-place other-opnds loc68 sn)))) + (begin + (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds)) + (gen-add-in-place other-opnds dtemp1 (sn-opnd loc sn)) + (if self? + (let ((loc68 (loc->loc68 loc dtemp1 sn))) + (make-top-of-frame-if-stk-opnd68 loc68 sn) + (emit-add.l dtemp1 (opnd68->true-opnd68 loc68 sn))) + (move-opnd68-to-loc dtemp1 loc sn)))))) +(define (gen-sub-in-place opnds loc68 sn) + (if (not (null? opnds)) + (let* ((first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)) + (opnd68 (opnd->opnd68 + first-opnd + (temp-in-opnd68 loc68) + (sn-opnd68 loc68 sn)))) + (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds) + (if (imm? opnd68) + (add-n-to-loc68 + (- (imm-val opnd68)) + (opnd68->true-opnd68 loc68 sn-other-opnds)) + (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds))) + (if (or (dreg? opnd68) (reg68? loc68)) + (emit-sub.l + opnd68* + (opnd68->true-opnd68 loc68 sn-other-opnds)) + (begin + (move-opnd68-to-loc68 opnd68* dtemp1) + (emit-sub.l + dtemp1 + (opnd68->true-opnd68 loc68 sn-other-opnds)))))) + (gen-sub-in-place other-opnds loc68 sn)))) +(define (gen-sub first-opnd other-opnds loc sn self-opnds?) + (if (null? other-opnds) + (if (and (or (reg? loc) (stk? loc)) (not (eq? loc return-reg))) + (begin + (copy-opnd-to-loc first-opnd loc (sn-opnd loc sn)) + (let ((loc68 (loc->loc68 loc #f sn))) + (make-top-of-frame-if-stk-opnd68 loc68 sn) + (emit-neg.l (opnd68->true-opnd68 loc68 sn)))) + (begin + (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn)) + (emit-neg.l dtemp1) + (move-opnd68-to-loc dtemp1 loc sn))) + (let* ((sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))) + (if (and (not self-opnds?) (or (reg? loc) (stk? loc))) + (let ((loc68 (loc->loc68 loc #f sn-first-opnd))) + (if (not (eq? first-opnd loc)) + (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds)) + (gen-sub-in-place other-opnds loc68 sn)) + (begin + (move-opnd-to-loc68 + first-opnd + dtemp1 + (sn-opnd loc sn-other-opnds)) + (gen-sub-in-place other-opnds dtemp1 (sn-opnd loc sn)) + (move-opnd68-to-loc dtemp1 loc sn)))))) +(define (gen-mul-in-place opnds reg68 sn) + (if (not (null? opnds)) + (let* ((first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 reg68) sn))) + (make-top-of-frame-if-stk-opnd68 opnd68 sn-other-opnds) + (if (imm? opnd68) + (mul-n-to-reg68 (quotient (imm-val opnd68) 8) reg68) + (begin + (emit-asr.l (make-imm 3) reg68) + (emit-muls.l (opnd68->true-opnd68 opnd68 sn-other-opnds) reg68))) + (gen-mul-in-place other-opnds reg68 sn)))) +(define (gen-mul self-opnds other-opnds loc sn self?) + (let* ((opnds (append self-opnds other-opnds)) + (first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))) + (if (null? self-opnds) + (let ((loc68 (loc->loc68 loc #f sn-first-opnd))) + (if self? + (gen-mul-in-place opnds loc68 sn) + (begin + (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds) + (gen-mul-in-place other-opnds loc68 sn)))) + (begin + (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds)) + (gen-mul-in-place other-opnds dtemp1 (sn-opnd loc sn)) + (if self? + (let ((loc68 (loc->loc68 loc dtemp1 sn))) + (make-top-of-frame-if-stk-opnd68 loc68 sn) + (emit-asr.l (make-imm 3) dtemp1) + (emit-muls.l dtemp1 (opnd68->true-opnd68 loc68 sn))) + (move-opnd68-to-loc dtemp1 loc sn)))))) +(define (gen-div-in-place opnds reg68 sn) + (if (not (null? opnds)) + (let* ((first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)) + (opnd68 (opnd->opnd68 first-opnd (temp-in-opnd68 reg68) sn))) + (make-top-of-frame-if-stk-opnd68 opnd68 sn-other-opnds) + (if (imm? opnd68) + (let ((n (quotient (imm-val opnd68) 8))) + (div-n-to-reg68 n reg68) + (if (> (abs n) 1) (emit-and.w (make-imm -8) reg68))) + (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds))) + (emit-divsl.l opnd68* reg68 reg68) + (emit-asl.l (make-imm 3) reg68))) + (gen-div-in-place other-opnds reg68 sn)))) +(define (gen-div first-opnd other-opnds loc sn self-opnds?) + (if (null? other-opnds) + (begin + (move-opnd-to-loc68 first-opnd pdec-sp (sn-opnd loc sn)) + (emit-moveq 8 dtemp1) + (emit-divsl.l pinc-sp dtemp1 dtemp1) + (emit-asl.l (make-imm 3) dtemp1) + (emit-and.w (make-imm -8) dtemp1) + (move-opnd68-to-loc dtemp1 loc sn)) + (let* ((sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))) + (if (and (reg? loc) (not self-opnds?) (not (eq? loc return-reg))) + (let ((reg68 (reg->reg68 loc))) + (if (not (eq? first-opnd loc)) + (move-opnd-to-loc68 first-opnd reg68 sn-other-opnds)) + (gen-div-in-place other-opnds reg68 sn)) + (begin + (move-opnd-to-loc68 + first-opnd + dtemp1 + (sn-opnd loc sn-other-opnds)) + (gen-div-in-place other-opnds dtemp1 (sn-opnd loc sn)) + (move-opnd68-to-loc dtemp1 loc sn)))))) +(define (gen-rem first-opnd second-opnd loc sn) + (let* ((sn-loc (sn-opnd loc sn)) + (sn-second-opnd (sn-opnd second-opnd sn-loc))) + (move-opnd-to-loc68 first-opnd dtemp1 sn-second-opnd) + (let ((opnd68 (opnd->opnd68 second-opnd #f sn-loc)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + false-reg))) + (make-top-of-frame-if-stk-opnd68 opnd68 sn-loc) + (let ((opnd68* (if (areg? opnd68) + (begin (emit-move.l opnd68 reg68) reg68) + (opnd68->true-opnd68 opnd68 sn-loc)))) + (emit-divsl.l opnd68* reg68 dtemp1)) + (move-opnd68-to-loc reg68 loc sn) + (if (not (and (reg? loc) (not (eq? loc return-reg)))) + (emit-move.l (make-imm bits-false) false-reg))))) +(define (gen-mod first-opnd second-opnd loc sn) + (let* ((sn-loc (sn-opnd loc sn)) + (sn-first-opnd (sn-opnd first-opnd sn-loc)) + (sn-second-opnd (sn-opnd second-opnd sn-first-opnd)) + (opnd68 (opnd->opnd68 second-opnd #f sn-second-opnd))) + (define (general-case) + (let ((lbl1 (new-lbl!)) + (lbl2 (new-lbl!)) + (lbl3 (new-lbl!)) + (opnd68** (opnd68->true-opnd68 opnd68 sn-second-opnd)) + (opnd68* (opnd68->true-opnd68 + (opnd->opnd68 first-opnd #f sn-second-opnd) + sn-second-opnd))) + (move-opnd68-to-loc68 opnd68* dtemp1) + (move-opnd68-to-loc68 opnd68** false-reg) + (emit-divsl.l false-reg false-reg dtemp1) + (emit-move.l false-reg false-reg) + (emit-beq lbl3) + (move-opnd68-to-loc68 opnd68* dtemp1) + (emit-bmi lbl1) + (move-opnd68-to-loc68 opnd68** dtemp1) + (emit-bpl lbl3) + (emit-bra lbl2) + (emit-label lbl1) + (move-opnd68-to-loc68 opnd68** dtemp1) + (emit-bmi lbl3) + (emit-label lbl2) + (emit-add.l dtemp1 false-reg) + (emit-label lbl3) + (move-opnd68-to-loc false-reg loc sn) + (emit-move.l (make-imm bits-false) false-reg))) + (make-top-of-frame-if-stk-opnd68 opnd68 sn-first-opnd) + (if (imm? opnd68) + (let ((n (quotient (imm-val opnd68) 8))) + (if (> n 0) + (let ((shift (power-of-2 n))) + (if shift + (let ((reg68 (if (and (reg? loc) + (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (move-opnd-to-loc68 first-opnd reg68 sn-loc) + (emit-and.l (make-imm (* (- n 1) 8)) reg68) + (move-opnd68-to-loc reg68 loc sn)) + (general-case))) + (general-case))) + (general-case)))) +(define (gen-op emit-op dst-ok?) + (define (gen-op-in-place opnds loc68 sn) + (if (not (null? opnds)) + (let* ((first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds)) + (opnd68 (opnd->opnd68 + first-opnd + (temp-in-opnd68 loc68) + (sn-opnd68 loc68 sn)))) + (make-top-of-frame-if-stk-opnds68 opnd68 loc68 sn-other-opnds) + (if (imm? opnd68) + (emit-op opnd68 (opnd68->true-opnd68 loc68 sn-other-opnds)) + (let ((opnd68* (opnd68->true-opnd68 opnd68 sn-other-opnds))) + (if (or (dreg? opnd68) (dst-ok? loc68)) + (emit-op opnd68* + (opnd68->true-opnd68 loc68 sn-other-opnds)) + (begin + (move-opnd68-to-loc68 opnd68* dtemp1) + (emit-op dtemp1 + (opnd68->true-opnd68 loc68 sn-other-opnds)))))) + (gen-op-in-place other-opnds loc68 sn)))) + (lambda (self-opnds other-opnds loc sn self?) + (let* ((opnds (append self-opnds other-opnds)) + (first-opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn)) + (sn-first-opnd (sn-opnd first-opnd sn-other-opnds))) + (if (<= (length self-opnds) 1) + (let ((loc68 (loc->loc68 loc #f sn-first-opnd))) + (if self? + (gen-op-in-place opnds loc68 sn) + (begin + (move-opnd-to-loc68 first-opnd loc68 sn-other-opnds) + (gen-op-in-place other-opnds loc68 sn)))) + (begin + (move-opnd-to-loc68 first-opnd dtemp1 (sn-opnd loc sn-other-opnds)) + (gen-op-in-place other-opnds dtemp1 (sn-opnd loc sn)) + (if self? + (let ((loc68 (loc->loc68 loc dtemp1 sn))) + (make-top-of-frame-if-stk-opnd68 loc68 sn) + (emit-op dtemp1 (opnd68->true-opnd68 loc68 sn))) + (move-opnd68-to-loc dtemp1 loc sn))))))) +(define gen-logior (gen-op emit-or.l dreg?)) +(define gen-logxor (gen-op emit-eor.l (lambda (x) #f))) +(define gen-logand (gen-op emit-and.l dreg?)) +(define (gen-shift right-shift) + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (let* ((opnd1 (car opnds)) + (opnd2 (cadr opnds)) + (sn-opnd1 (sn-opnd opnd1 sn-loc)) + (o2 (opnd->opnd68 opnd2 #f sn-opnd1))) + (make-top-of-frame-if-stk-opnd68 o2 sn-opnd1) + (if (imm? o2) + (let* ((reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1)) + (n (quotient (imm-val o2) 8)) + (emit-shft (if (> n 0) emit-lsl.l right-shift))) + (move-opnd-to-loc68 opnd1 reg68 sn-loc) + (let loop ((i (min (abs n) 29))) + (if (> i 0) + (begin + (emit-shft (make-imm (min i 8)) reg68) + (loop (- i 8))))) + (if (< n 0) (emit-and.w (make-imm -8) reg68)) + (move-opnd68-to-loc reg68 loc sn)) + (let* ((reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1)) + (reg68* (if (and (reg? loc) (not (eq? loc return-reg))) + dtemp1 + false-reg)) + (lbl1 (new-lbl!)) + (lbl2 (new-lbl!))) + (emit-move.l (opnd68->true-opnd68 o2 sn-opnd1) reg68*) + (move-opnd-to-loc68 opnd1 reg68 sn-loc) + (emit-asr.l (make-imm 3) reg68*) + (emit-bmi lbl1) + (emit-lsl.l reg68* reg68) + (emit-bra lbl2) + (emit-label lbl1) + (emit-neg.l reg68*) + (right-shift reg68* reg68) + (emit-and.w (make-imm -8) reg68) + (emit-label lbl2) + (move-opnd68-to-loc reg68 loc sn) + (if (not (and (reg? loc) (not (eq? loc return-reg)))) + (emit-move.l (make-imm bits-false) false-reg)))))))) +(define (flo-oper oper1 oper2 opnds loc sn) + (gen-guarantee-space 2) + (move-opnd-to-loc68 + (car opnds) + atemp1 + (sn-opnds (cdr opnds) (sn-opnd loc sn))) + (oper1 (make-disp* atemp1 (- type-flonum)) ftemp1) + (let loop ((opnds (cdr opnds))) + (if (not (null? opnds)) + (let* ((opnd (car opnds)) + (other-opnds (cdr opnds)) + (sn-other-opnds (sn-opnds other-opnds sn))) + (move-opnd-to-loc68 opnd atemp1 sn-other-opnds) + (oper2 (make-disp* atemp1 (- type-flonum)) ftemp1) + (loop (cdr opnds))))) + (add-n-to-loc68 (* -2 pointer-size) heap-reg) + (emit-fmov.dx ftemp1 (make-ind heap-reg)) + (let ((reg68 (if (reg? loc) (reg->reg68 loc) atemp1))) + (emit-move.l heap-reg reg68) + (emit-addq.l type-flonum reg68)) + (if (not (reg? loc)) (move-opnd68-to-loc atemp1 loc sn))) +(define (gen-make-placeholder opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (let ((opnd (car opnds))) + (gen-guarantee-space 4) + (emit-clr.l (make-pdec heap-reg)) + (move-opnd-to-loc68 opnd (make-pdec heap-reg) sn-loc) + (emit-move.l null-reg (make-pdec heap-reg)) + (move-opnd68-to-loc68 heap-reg atemp2) + (emit-addq.l (modulo (- type-placeholder type-pair) 8) atemp2) + (emit-move.l atemp2 (make-pdec heap-reg)) + (move-opnd68-to-loc atemp2 loc sn)))) +(define (gen-subprocedure-id opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) + (opnd (car opnds)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (move-n-to-loc68 32768 reg68) + (emit-sub.w (make-disp* atemp1 -2) reg68) + (move-opnd68-to-loc reg68 loc sn))) +(define (gen-subprocedure-parent opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) (opnd (car opnds))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (emit-add.w (make-disp* atemp1 -2) atemp1) + (add-n-to-loc68 -32768 atemp1) + (move-opnd68-to-loc atemp1 loc sn))) +(define (gen-return-fs opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) + (opnd (car opnds)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1)) + (lbl (new-lbl!))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (emit-moveq 0 reg68) + (emit-move.w (make-disp* atemp1 -6) reg68) + (emit-beq lbl) + (emit-and.w (make-imm 32767) reg68) + (emit-subq.l 8 reg68) + (emit-label lbl) + (emit-addq.l 8 reg68) + (emit-asl.l (make-imm 1) reg68) + (move-opnd68-to-loc reg68 loc sn))) +(define (gen-return-link opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) + (opnd (car opnds)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1)) + (lbl (new-lbl!))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (emit-moveq 0 reg68) + (emit-move.w (make-disp* atemp1 -6) reg68) + (emit-beq lbl) + (emit-and.w (make-imm 32767) reg68) + (emit-subq.l 8 reg68) + (emit-label lbl) + (emit-addq.l 8 reg68) + (emit-sub.w (make-disp* atemp1 -4) reg68) + (emit-asl.l (make-imm 1) reg68) + (move-opnd68-to-loc reg68 loc sn))) +(define (gen-procedure-info opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) (opnd (car opnds))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (emit-add.w (make-disp* atemp1 -2) atemp1) + (move-opnd68-to-loc (make-disp* atemp1 (- 32768 6)) loc sn))) +(define (gen-guarantee-space n) + (set! pointers-allocated (+ pointers-allocated n)) + (if (> pointers-allocated heap-allocation-fudge) + (begin (gen-guarantee-fudge) (set! pointers-allocated n)))) +(define (gen-guarantee-fudge) + (if (> pointers-allocated 0) + (let ((lbl (new-lbl!))) + (emit-cmp.l heap-lim-slot heap-reg) + (emit-bcc lbl) + (gen-trap instr-source entry-frame #f #f heap-alloc1-trap lbl) + (set! pointers-allocated 0)))) +(define pointers-allocated '()) +(define (gen-type opnds loc sn) + (let* ((sn-loc (sn-opnd loc sn)) + (opnd (car opnds)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (move-opnd-to-loc68 opnd reg68 sn-loc) + (emit-and.l (make-imm 7) reg68) + (emit-asl.l (make-imm 3) reg68) + (move-opnd68-to-loc reg68 loc sn))) +(define (gen-type-cast opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let ((first-opnd (car opnds)) (second-opnd (cadr opnds))) + (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) sn-loc sn)) + (o1 (opnd->opnd68 first-opnd #f (sn-opnd second-opnd sn-loc))) + (o2 (opnd->opnd68 second-opnd (temp-in-opnd68 o1) sn-loc)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc) + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o1 (sn-opnd68 o2 sn-loc)) + reg68) + (emit-and.w (make-imm -8) reg68) + (if (imm? o2) + (let ((n (quotient (imm-val o2) 8))) + (if (> n 0) (emit-addq.w n reg68))) + (begin + (move-opnd68-to-loc68 (opnd68->true-opnd68 o2 sn-loc) atemp1) + (emit-exg atemp1 reg68) + (emit-asr.l (make-imm 3) reg68) + (emit-add.l atemp1 reg68))) + (move-opnd68-to-loc reg68 loc sn))))) +(define (gen-subtype opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) + (opnd (car opnds)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (emit-moveq 0 reg68) + (emit-move.b (make-ind atemp1) reg68) + (move-opnd68-to-loc reg68 loc sn))) +(define (gen-subtype-set! opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let ((first-opnd (car opnds)) (second-opnd (cadr opnds))) + (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) sn-loc sn)) + (o1 (opnd->opnd68 first-opnd #f (sn-opnd second-opnd sn-loc))) + (o2 (opnd->opnd68 second-opnd (temp-in-opnd68 o1) sn-loc))) + (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc) + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o1 (sn-opnd68 o2 sn-loc)) + atemp1) + (if (imm? o2) + (emit-move.b (make-imm (imm-val o2)) (make-ind atemp1)) + (begin + (move-opnd68-to-loc68 (opnd68->true-opnd68 o2 sn-loc) dtemp1) + (emit-move.b dtemp1 (make-ind atemp1)))) + (if (and loc (not (eq? first-opnd loc))) + (move-opnd68-to-loc atemp1 loc sn)))))) +(define (vector-select kind vector string vector8 vector16) + (case kind + ((string) string) + ((vector8) vector8) + ((vector16) vector16) + (else vector))) +(define (obj-vector? kind) (vector-select kind #t #f #f #f)) +(define (make-gen-vector kind) + (lambda (opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let* ((n (length opnds)) + (bytes (+ pointer-size + (* (vector-select kind 4 1 1 2) + (+ n (if (eq? kind 'string) 1 0))))) + (adjust (modulo (- bytes) 8))) + (gen-guarantee-space + (quotient (* (quotient (+ bytes (- 8 1)) 8) 8) pointer-size)) + (if (not (= adjust 0)) (emit-subq.l adjust heap-reg)) + (if (eq? kind 'string) (emit-move.b (make-imm 0) (make-pdec heap-reg))) + (let loop ((opnds (reverse opnds))) + (if (pair? opnds) + (let* ((o (car opnds)) (sn-o (sn-opnds (cdr opnds) sn-loc))) + (if (eq? kind 'vector) + (move-opnd-to-loc68 o (make-pdec heap-reg) sn-o) + (begin + (move-opnd-to-loc68 o dtemp1 sn-o) + (emit-asr.l (make-imm 3) dtemp1) + (if (eq? kind 'vector16) + (emit-move.w dtemp1 (make-pdec heap-reg)) + (emit-move.b dtemp1 (make-pdec heap-reg))))) + (loop (cdr opnds))))) + (emit-move.l + (make-imm + (+ (* 256 (- bytes pointer-size)) + (* 8 (if (eq? kind 'vector) subtype-vector subtype-string)))) + (make-pdec heap-reg)) + (if loc + (begin + (emit-lea (make-disp* heap-reg type-subtyped) atemp2) + (move-opnd68-to-loc atemp2 loc sn))))))) +(define (make-gen-vector-length kind) + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) + (opnd (car opnds)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (move-opnd-to-loc68 opnd atemp1 sn-loc) + (move-opnd68-to-loc68 (make-disp* atemp1 (- type-subtyped)) reg68) + (emit-lsr.l (make-imm (vector-select kind 7 5 5 6)) reg68) + (if (not (eq? kind 'vector)) + (begin + (emit-and.w (make-imm -8) reg68) + (if (eq? kind 'string) (emit-subq.l 8 reg68)))) + (move-opnd68-to-loc reg68 loc sn)))) +(define (make-gen-vector-ref kind) + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (let ((first-opnd (car opnds)) + (second-opnd (cadr opnds)) + (reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (let* ((o2 (opnd->opnd68 second-opnd #f (sn-opnd first-opnd sn-loc))) + (o1 (opnd->opnd68 first-opnd (temp-in-opnd68 o2) sn-loc))) + (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc) + (let* ((offset (if (eq? kind 'closure) + (- pointer-size type-procedure) + (- pointer-size type-subtyped))) + (loc68 (if (imm? o2) + (begin + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o1 sn-loc) + atemp1) + (make-disp* + atemp1 + (+ (quotient + (imm-val o2) + (vector-select kind 2 8 8 4)) + offset))) + (begin + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc)) + dtemp1) + (emit-asr.l + (make-imm (vector-select kind 1 3 3 2)) + dtemp1) + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o1 sn-loc) + atemp1) + (if (and (identical-opnd68? reg68 dtemp1) + (not (obj-vector? kind))) + (begin + (emit-move.l dtemp1 atemp2) + (make-inx atemp1 atemp2 offset)) + (make-inx atemp1 dtemp1 offset)))))) + (if (not (obj-vector? kind)) (emit-moveq 0 reg68)) + (case kind + ((string vector8) (emit-move.b loc68 reg68)) + ((vector16) (emit-move.w loc68 reg68)) + (else (emit-move.l loc68 reg68))) + (if (not (obj-vector? kind)) + (begin + (emit-asl.l (make-imm 3) reg68) + (if (eq? kind 'string) (emit-addq.w type-special reg68)))) + (move-opnd68-to-loc reg68 loc sn))))))) +(define (make-gen-vector-set! kind) + (lambda (opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let ((first-opnd (car opnds)) + (second-opnd (cadr opnds)) + (third-opnd (caddr opnds))) + (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) + (sn-opnd first-opnd sn-loc) + sn)) + (sn-third-opnd (sn-opnd third-opnd sn-loc)) + (o2 (opnd->opnd68 + second-opnd + #f + (sn-opnd first-opnd sn-third-opnd))) + (o1 (opnd->opnd68 + first-opnd + (temp-in-opnd68 o2) + sn-third-opnd))) + (make-top-of-frame-if-stk-opnds68 o1 o2 sn-third-opnd) + (let* ((offset (if (eq? kind 'closure) + (- pointer-size type-procedure) + (- pointer-size type-subtyped))) + (loc68 (if (imm? o2) + (begin + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o1 sn-third-opnd) + atemp1) + (make-disp* + atemp1 + (+ (quotient + (imm-val o2) + (vector-select kind 2 8 8 4)) + offset))) + (begin + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc)) + dtemp1) + (emit-asr.l + (make-imm (vector-select kind 1 3 3 2)) + dtemp1) + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o1 sn-loc) + atemp1) + (if (obj-vector? kind) + (make-inx atemp1 dtemp1 offset) + (begin + (emit-move.l dtemp1 atemp2) + (make-inx atemp1 atemp2 offset))))))) + (if (obj-vector? kind) + (move-opnd-to-loc68 third-opnd loc68 sn-loc) + (begin + (move-opnd-to-loc68 third-opnd dtemp1 sn-loc) + (emit-asr.l (make-imm 3) dtemp1) + (if (eq? kind 'vector16) + (emit-move.w dtemp1 loc68) + (emit-move.b dtemp1 loc68)))) + (if (and loc (not (eq? first-opnd loc))) + (copy-opnd-to-loc first-opnd loc sn)))))))) +(define (make-gen-vector-shrink! kind) + (lambda (opnds loc sn) + (let ((sn-loc (if loc (sn-opnd loc sn) sn))) + (let ((first-opnd (car opnds)) (second-opnd (cadr opnds))) + (let* ((sn-loc (if (and loc (not (eq? first-opnd loc))) + (sn-opnd first-opnd sn-loc) + sn)) + (o2 (opnd->opnd68 second-opnd #f (sn-opnd first-opnd sn-loc))) + (o1 (opnd->opnd68 first-opnd (temp-in-opnd68 o2) sn-loc))) + (make-top-of-frame-if-stk-opnds68 o1 o2 sn-loc) + (move-opnd68-to-loc68 + (opnd68->true-opnd68 o2 (sn-opnd68 o1 sn-loc)) + dtemp1) + (emit-move.l (opnd68->true-opnd68 o1 sn-loc) atemp1) + (if (eq? kind 'string) + (begin + (emit-asr.l (make-imm 3) dtemp1) + (emit-move.b + (make-imm 0) + (make-inx atemp1 dtemp1 (- pointer-size type-subtyped))) + (emit-addq.l 1 dtemp1) + (emit-asl.l (make-imm 8) dtemp1)) + (emit-asl.l (make-imm (vector-select kind 7 5 5 6)) dtemp1)) + (emit-move.b (make-ind atemp1) dtemp1) + (emit-move.l dtemp1 (make-disp* atemp1 (- type-subtyped))) + (if (and loc (not (eq? first-opnd loc))) + (move-opnd68-to-loc atemp1 loc sn))))))) +(define (gen-eq-test bits not? opnds lbl fs) + (gen-compare* (opnd->opnd68 (car opnds) #f fs) (make-imm bits) fs) + (if not? (emit-bne lbl) (emit-beq lbl))) +(define (gen-compare opnd1 opnd2 fs) + (let* ((o1 (opnd->opnd68 opnd1 #f (sn-opnd opnd2 fs))) + (o2 (opnd->opnd68 opnd2 (temp-in-opnd68 o1) fs))) + (gen-compare* o1 o2 fs))) +(define (gen-compare* o1 o2 fs) + (make-top-of-frame-if-stk-opnds68 o1 o2 fs) + (let ((order-1-2 + (cond ((imm? o1) + (cmp-n-to-opnd68 (imm-val o1) (opnd68->true-opnd68 o2 fs))) + ((imm? o2) + (not (cmp-n-to-opnd68 + (imm-val o2) + (opnd68->true-opnd68 o1 fs)))) + ((reg68? o1) (emit-cmp.l (opnd68->true-opnd68 o2 fs) o1) #f) + ((reg68? o2) (emit-cmp.l (opnd68->true-opnd68 o1 fs) o2) #t) + (else + (emit-move.l (opnd68->true-opnd68 o1 (sn-opnd68 o2 fs)) dtemp1) + (emit-cmp.l (opnd68->true-opnd68 o2 fs) dtemp1) + #f)))) + (shrink-frame fs) + order-1-2)) +(define (gen-compares branch< branch>= branch> branch<= not? opnds lbl fs) + (gen-compares* + gen-compare + branch< + branch>= + branch> + branch<= + not? + opnds + lbl + fs)) +(define (gen-compares* + gen-comp + branch< + branch>= + branch> + branch<= + not? + opnds + lbl + fs) + (define (gen-compare-sequence opnd1 opnd2 rest) + (if (null? rest) + (if (gen-comp opnd1 opnd2 fs) + (if not? (branch<= lbl) (branch> lbl)) + (if not? (branch>= lbl) (branch< lbl))) + (let ((order-1-2 + (gen-comp opnd1 opnd2 (sn-opnd opnd2 (sn-opnds rest fs))))) + (if (= current-fs fs) + (if not? + (begin + (if order-1-2 (branch<= lbl) (branch>= lbl)) + (gen-compare-sequence opnd2 (car rest) (cdr rest))) + (let ((exit-lbl (new-lbl!))) + (if order-1-2 (branch<= exit-lbl) (branch>= exit-lbl)) + (gen-compare-sequence opnd2 (car rest) (cdr rest)) + (emit-label exit-lbl))) + (if not? + (let ((next-lbl (new-lbl!))) + (if order-1-2 (branch> next-lbl) (branch< next-lbl)) + (shrink-frame fs) + (emit-bra lbl) + (emit-label next-lbl) + (gen-compare-sequence opnd2 (car rest) (cdr rest))) + (let* ((next-lbl (new-lbl!)) (exit-lbl (new-lbl!))) + (if order-1-2 (branch> next-lbl) (branch< next-lbl)) + (shrink-frame fs) + (emit-bra exit-lbl) + (emit-label next-lbl) + (gen-compare-sequence opnd2 (car rest) (cdr rest)) + (emit-label exit-lbl))))))) + (if (or (null? opnds) (null? (cdr opnds))) + (begin (shrink-frame fs) (if (not not?) (emit-bra lbl))) + (gen-compare-sequence (car opnds) (cadr opnds) (cddr opnds)))) +(define (gen-compare-flo opnd1 opnd2 fs) + (let* ((o1 (opnd->opnd68 opnd1 #f (sn-opnd opnd2 fs))) + (o2 (opnd->opnd68 opnd2 (temp-in-opnd68 o1) fs))) + (make-top-of-frame-if-stk-opnds68 o1 o2 fs) + (emit-move.l (opnd68->true-opnd68 o1 (sn-opnd68 o2 fs)) atemp1) + (emit-move.l (opnd68->true-opnd68 o2 fs) atemp2) + (emit-fmov.dx (make-disp* atemp2 (- type-flonum)) ftemp1) + (emit-fcmp.dx (make-disp* atemp1 (- type-flonum)) ftemp1) + #t)) +(define (gen-compares-flo branch< branch>= branch> branch<= not? opnds lbl fs) + (gen-compares* + gen-compare-flo + branch< + branch>= + branch> + branch<= + not? + opnds + lbl + fs)) +(define (gen-type-test tag not? opnds lbl fs) + (let ((opnd (car opnds))) + (let ((o (opnd->opnd68 opnd #f fs))) + (define (mask-test set-reg correction) + (emit-btst + (if (= correction 0) + (if (dreg? o) + o + (begin + (emit-move.l (opnd68->true-opnd68 o fs) dtemp1) + dtemp1)) + (begin + (if (not (eq? o dtemp1)) + (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)) + (emit-addq.w correction dtemp1) + dtemp1)) + set-reg)) + (make-top-of-frame-if-stk-opnd68 o fs) + (cond ((= tag 0) + (if (eq? o dtemp1) + (emit-and.w (make-imm 7) dtemp1) + (begin + (emit-move.l (opnd68->true-opnd68 o fs) dtemp1) + (emit-and.w (make-imm 7) dtemp1)))) + ((= tag type-placeholder) (mask-test placeholder-reg 0)) + (else (mask-test pair-reg (modulo (- type-pair tag) 8)))) + (shrink-frame fs) + (if not? (emit-bne lbl) (emit-beq lbl))))) +(define (gen-subtype-test type not? opnds lbl fs) + (let ((opnd (car opnds))) + (let ((o (opnd->opnd68 opnd #f fs)) (cont-lbl (new-lbl!))) + (make-top-of-frame-if-stk-opnd68 o fs) + (if (not (eq? o dtemp1)) (emit-move.l (opnd68->true-opnd68 o fs) dtemp1)) + (emit-move.l dtemp1 atemp1) + (emit-addq.w (modulo (- type-pair type-subtyped) 8) dtemp1) + (emit-btst dtemp1 pair-reg) + (shrink-frame fs) + (if not? (emit-bne lbl) (emit-bne cont-lbl)) + (emit-cmp.b (make-imm (* type 8)) (make-ind atemp1)) + (if not? (emit-bne lbl) (emit-beq lbl)) + (emit-label cont-lbl)))) +(define (gen-even-test not? opnds lbl fs) + (move-opnd-to-loc68 (car opnds) dtemp1 fs) + (emit-and.w (make-imm 8) dtemp1) + (shrink-frame fs) + (if not? (emit-bne lbl) (emit-beq lbl))) +(define (def-spec name specializer-maker) + (let ((proc-name (string->canonical-symbol name))) + (let ((proc (prim-info proc-name))) + (if proc + (proc-obj-specialize-set! proc (specializer-maker proc proc-name)) + (compiler-internal-error "def-spec, unknown primitive:" name))))) +(define (safe name) + (lambda (proc proc-name) + (let ((spec (get-prim-info name))) (lambda (decls) spec)))) +(define (unsafe name) + (lambda (proc proc-name) + (let ((spec (get-prim-info name))) + (lambda (decls) (if (not (safe? decls)) spec proc))))) +(define (safe-arith fix-name flo-name) (arith #t fix-name flo-name)) +(define (unsafe-arith fix-name flo-name) (arith #f fix-name flo-name)) +(define (arith fix-safe? fix-name flo-name) + (lambda (proc proc-name) + (let ((fix-spec (if fix-name (get-prim-info fix-name) proc)) + (flo-spec (if flo-name (get-prim-info flo-name) proc))) + (lambda (decls) + (let ((arith (arith-implementation proc-name decls))) + (cond ((eq? arith fixnum-sym) + (if (or fix-safe? (not (safe? decls))) fix-spec proc)) + ((eq? arith flonum-sym) (if (not (safe? decls)) flo-spec proc)) + (else proc))))))) +(define-apply "##TYPE" #f (lambda (opnds loc sn) (gen-type opnds loc sn))) +(define-apply + "##TYPE-CAST" + #f + (lambda (opnds loc sn) (gen-type-cast opnds loc sn))) +(define-apply + "##SUBTYPE" + #f + (lambda (opnds loc sn) (gen-subtype opnds loc sn))) +(define-apply + "##SUBTYPE-SET!" + #t + (lambda (opnds loc sn) (gen-subtype-set! opnds loc sn))) +(define-ifjump + "##NOT" + (lambda (not? opnds lbl fs) (gen-eq-test bits-false not? opnds lbl fs))) +(define-ifjump + "##NULL?" + (lambda (not? opnds lbl fs) (gen-eq-test bits-null not? opnds lbl fs))) +(define-ifjump + "##UNASSIGNED?" + (lambda (not? opnds lbl fs) (gen-eq-test bits-unass not? opnds lbl fs))) +(define-ifjump + "##UNBOUND?" + (lambda (not? opnds lbl fs) (gen-eq-test bits-unbound not? opnds lbl fs))) +(define-ifjump + "##EQ?" + (lambda (not? opnds lbl fs) + (gen-compares emit-beq emit-bne emit-beq emit-bne not? opnds lbl fs))) +(define-ifjump + "##FIXNUM?" + (lambda (not? opnds lbl fs) (gen-type-test type-fixnum not? opnds lbl fs))) +(define-ifjump + "##FLONUM?" + (lambda (not? opnds lbl fs) (gen-type-test type-flonum not? opnds lbl fs))) +(define-ifjump + "##SPECIAL?" + (lambda (not? opnds lbl fs) (gen-type-test type-special not? opnds lbl fs))) +(define-ifjump + "##PAIR?" + (lambda (not? opnds lbl fs) (gen-type-test type-pair not? opnds lbl fs))) +(define-ifjump + "##SUBTYPED?" + (lambda (not? opnds lbl fs) (gen-type-test type-subtyped not? opnds lbl fs))) +(define-ifjump + "##PROCEDURE?" + (lambda (not? opnds lbl fs) (gen-type-test type-procedure not? opnds lbl fs))) +(define-ifjump + "##PLACEHOLDER?" + (lambda (not? opnds lbl fs) + (gen-type-test type-placeholder not? opnds lbl fs))) +(define-ifjump + "##VECTOR?" + (lambda (not? opnds lbl fs) + (gen-subtype-test subtype-vector not? opnds lbl fs))) +(define-ifjump + "##SYMBOL?" + (lambda (not? opnds lbl fs) + (gen-subtype-test subtype-symbol not? opnds lbl fs))) +(define-ifjump + "##RATNUM?" + (lambda (not? opnds lbl fs) + (gen-subtype-test subtype-ratnum not? opnds lbl fs))) +(define-ifjump + "##CPXNUM?" + (lambda (not? opnds lbl fs) + (gen-subtype-test subtype-cpxnum not? opnds lbl fs))) +(define-ifjump + "##STRING?" + (lambda (not? opnds lbl fs) + (gen-subtype-test subtype-string not? opnds lbl fs))) +(define-ifjump + "##BIGNUM?" + (lambda (not? opnds lbl fs) + (gen-subtype-test subtype-bignum not? opnds lbl fs))) +(define-ifjump + "##CHAR?" + (lambda (not? opnds lbl fs) + (let ((opnd (car opnds))) + (let ((o (opnd->opnd68 opnd #f fs)) (cont-lbl (new-lbl!))) + (make-top-of-frame-if-stk-opnd68 o fs) + (emit-move.l (opnd68->true-opnd68 o fs) dtemp1) + (if not? (emit-bmi lbl) (emit-bmi cont-lbl)) + (emit-addq.w (modulo (- type-pair type-special) 8) dtemp1) + (emit-btst dtemp1 pair-reg) + (shrink-frame fs) + (if not? (emit-bne lbl) (emit-beq lbl)) + (emit-label cont-lbl))))) +(define-ifjump + "##CLOSURE?" + (lambda (not? opnds lbl fs) + (move-opnd-to-loc68 (car opnds) atemp1 fs) + (shrink-frame fs) + (emit-cmp.w (make-imm 20153) (make-ind atemp1)) + (if not? (emit-bne lbl) (emit-beq lbl)))) +(define-ifjump + "##SUBPROCEDURE?" + (lambda (not? opnds lbl fs) + (move-opnd-to-loc68 (car opnds) atemp1 fs) + (shrink-frame fs) + (emit-move.w (make-pdec atemp1) dtemp1) + (if not? (emit-bmi lbl) (emit-bpl lbl)))) +(define-ifjump + "##RETURN-DYNAMIC-ENV-BIND?" + (lambda (not? opnds lbl fs) + (move-opnd-to-loc68 (car opnds) atemp1 fs) + (shrink-frame fs) + (emit-move.w (make-disp* atemp1 -6) dtemp1) + (if not? (emit-bne lbl) (emit-beq lbl)))) +(define-apply + "##FIXNUM.+" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (cond ((null? opnds) (copy-opnd-to-loc (make-obj '0) loc sn)) + ((null? (cdr opnds)) (copy-opnd-to-loc (car opnds) loc sn)) + ((or (reg? loc) (stk? loc)) + (commut-oper gen-add opnds loc sn #f '() '())) + (else (gen-add opnds '() loc sn #f)))))) +(define-apply + "##FIXNUM.-" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (gen-sub (car opnds) + (cdr opnds) + loc + sn + (any-contains-opnd? loc (cdr opnds)))))) +(define-apply + "##FIXNUM.*" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (cond ((null? opnds) (copy-opnd-to-loc (make-obj '1) loc sn)) + ((null? (cdr opnds)) (copy-opnd-to-loc (car opnds) loc sn)) + ((and (reg? loc) (not (eq? loc return-reg))) + (commut-oper gen-mul opnds loc sn #f '() '())) + (else (gen-mul opnds '() loc sn #f)))))) +(define-apply + "##FIXNUM.QUOTIENT" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (gen-div (car opnds) + (cdr opnds) + loc + sn + (any-contains-opnd? loc (cdr opnds)))))) +(define-apply + "##FIXNUM.REMAINDER" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (gen-rem (car opnds) (cadr opnds) loc sn)))) +(define-apply + "##FIXNUM.MODULO" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (gen-mod (car opnds) (cadr opnds) loc sn)))) +(define-apply + "##FIXNUM.LOGIOR" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (cond ((null? opnds) (copy-opnd-to-loc (make-obj '0) loc sn)) + ((null? (cdr opnds)) (copy-opnd-to-loc (car opnds) loc sn)) + ((or (reg? loc) (stk? loc)) + (commut-oper gen-logior opnds loc sn #f '() '())) + (else (gen-logior opnds '() loc sn #f)))))) +(define-apply + "##FIXNUM.LOGXOR" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (cond ((null? opnds) (copy-opnd-to-loc (make-obj '0) loc sn)) + ((null? (cdr opnds)) (copy-opnd-to-loc (car opnds) loc sn)) + ((or (reg? loc) (stk? loc)) + (commut-oper gen-logxor opnds loc sn #f '() '())) + (else (gen-logxor opnds '() loc sn #f)))))) +(define-apply + "##FIXNUM.LOGAND" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (cond ((null? opnds) (copy-opnd-to-loc (make-obj '-1) loc sn)) + ((null? (cdr opnds)) (copy-opnd-to-loc (car opnds) loc sn)) + ((or (reg? loc) (stk? loc)) + (commut-oper gen-logand opnds loc sn #f '() '())) + (else (gen-logand opnds '() loc sn #f)))))) +(define-apply + "##FIXNUM.LOGNOT" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn)) (opnd (car opnds))) + (if (and (or (reg? loc) (stk? loc)) (not (eq? loc return-reg))) + (begin + (copy-opnd-to-loc opnd loc sn-loc) + (let ((loc68 (loc->loc68 loc #f sn))) + (make-top-of-frame-if-stk-opnd68 loc68 sn) + (emit-not.l (opnd68->true-opnd68 loc68 sn)) + (emit-and.w (make-imm -8) (opnd68->true-opnd68 loc68 sn)))) + (begin + (move-opnd-to-loc68 opnd dtemp1 (sn-opnd loc sn)) + (emit-not.l dtemp1) + (emit-and.w (make-imm -8) dtemp1) + (move-opnd68-to-loc dtemp1 loc sn)))))) +(define-apply "##FIXNUM.ASH" #f (gen-shift emit-asr.l)) +(define-apply "##FIXNUM.LSH" #f (gen-shift emit-lsr.l)) +(define-ifjump + "##FIXNUM.ZERO?" + (lambda (not? opnds lbl fs) (gen-eq-test 0 not? opnds lbl fs))) +(define-ifjump + "##FIXNUM.POSITIVE?" + (lambda (not? opnds lbl fs) + (gen-compares + emit-bgt + emit-ble + emit-blt + emit-bge + not? + (list (car opnds) (make-obj '0)) + lbl + fs))) +(define-ifjump + "##FIXNUM.NEGATIVE?" + (lambda (not? opnds lbl fs) + (gen-compares + emit-blt + emit-bge + emit-bgt + emit-ble + not? + (list (car opnds) (make-obj '0)) + lbl + fs))) +(define-ifjump + "##FIXNUM.ODD?" + (lambda (not? opnds lbl fs) (gen-even-test (not not?) opnds lbl fs))) +(define-ifjump + "##FIXNUM.EVEN?" + (lambda (not? opnds lbl fs) (gen-even-test not? opnds lbl fs))) +(define-ifjump + "##FIXNUM.=" + (lambda (not? opnds lbl fs) + (gen-compares emit-beq emit-bne emit-beq emit-bne not? opnds lbl fs))) +(define-ifjump + "##FIXNUM.<" + (lambda (not? opnds lbl fs) + (gen-compares emit-blt emit-bge emit-bgt emit-ble not? opnds lbl fs))) +(define-ifjump + "##FIXNUM.>" + (lambda (not? opnds lbl fs) + (gen-compares emit-bgt emit-ble emit-blt emit-bge not? opnds lbl fs))) +(define-ifjump + "##FIXNUM.<=" + (lambda (not? opnds lbl fs) + (gen-compares emit-ble emit-bgt emit-bge emit-blt not? opnds lbl fs))) +(define-ifjump + "##FIXNUM.>=" + (lambda (not? opnds lbl fs) + (gen-compares emit-bge emit-blt emit-ble emit-bgt not? opnds lbl fs))) +(define-apply + "##FLONUM.->FIXNUM" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (move-opnd-to-loc68 (car opnds) atemp1 sn-loc) + (let ((reg68 (if (and (reg? loc) (not (eq? loc return-reg))) + (reg->reg68 loc) + dtemp1))) + (emit-fmov.dx (make-disp* atemp1 (- type-flonum)) ftemp1) + (emit-fmov.l ftemp1 reg68) + (emit-asl.l (make-imm 3) reg68) + (if (not (and (reg? loc) (not (eq? loc return-reg)))) + (move-opnd68-to-loc reg68 loc sn)))))) +(define-apply + "##FLONUM.<-FIXNUM" + #f + (lambda (opnds loc sn) + (gen-guarantee-space 2) + (move-opnd-to-loc68 + (car opnds) + dtemp1 + (sn-opnds (cdr opnds) (sn-opnd loc sn))) + (emit-asr.l (make-imm 3) dtemp1) + (emit-fmov.l dtemp1 ftemp1) + (add-n-to-loc68 (* -2 pointer-size) heap-reg) + (emit-fmov.dx ftemp1 (make-ind heap-reg)) + (let ((reg68 (if (reg? loc) (reg->reg68 loc) atemp1))) + (emit-move.l heap-reg reg68) + (emit-addq.l type-flonum reg68)) + (if (not (reg? loc)) (move-opnd68-to-loc atemp1 loc sn)))) +(define-apply + "##FLONUM.+" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (cond ((null? opnds) (copy-opnd-to-loc (make-obj inexact-0) loc sn)) + ((null? (cdr opnds)) (copy-opnd-to-loc (car opnds) loc sn)) + (else (flo-oper emit-fmov.dx emit-fadd.dx opnds loc sn)))))) +(define-apply + "##FLONUM.*" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (cond ((null? opnds) (copy-opnd-to-loc (make-obj inexact-+1) loc sn)) + ((null? (cdr opnds)) (copy-opnd-to-loc (car opnds) loc sn)) + (else (flo-oper emit-fmov.dx emit-fmul.dx opnds loc sn)))))) +(define-apply + "##FLONUM.-" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (if (null? (cdr opnds)) + (flo-oper emit-fneg.dx #f opnds loc sn) + (flo-oper emit-fmov.dx emit-fsub.dx opnds loc sn))))) +(define-apply + "##FLONUM./" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (if (null? (cdr opnds)) + (flo-oper + emit-fmov.dx + emit-fdiv.dx + (cons (make-obj inexact-+1) opnds) + loc + sn) + (flo-oper emit-fmov.dx emit-fdiv.dx opnds loc sn))))) +(define-apply + "##FLONUM.ABS" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fabs.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.TRUNCATE" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) + (flo-oper emit-fintrz.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.ROUND" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fint.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.EXP" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fetox.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.LOG" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-flogn.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.SIN" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fsin.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.COS" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fcos.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.TAN" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-ftan.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.ASIN" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fasin.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.ACOS" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-facos.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.ATAN" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fatan.dx #f opnds loc sn)))) +(define-apply + "##FLONUM.SQRT" + #f + (lambda (opnds loc sn) + (let ((sn-loc (sn-opnd loc sn))) (flo-oper emit-fsqrt.dx #f opnds loc sn)))) +(define-ifjump + "##FLONUM.ZERO?" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fbeq + emit-fbne + emit-fbeq + emit-fbne + not? + (list (car opnds) (make-obj inexact-0)) + lbl + fs))) +(define-ifjump + "##FLONUM.NEGATIVE?" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fblt + emit-fbge + emit-fbgt + emit-fble + not? + (list (car opnds) (make-obj inexact-0)) + lbl + fs))) +(define-ifjump + "##FLONUM.POSITIVE?" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fbgt + emit-fble + emit-fblt + emit-fbge + not? + (list (car opnds) (make-obj inexact-0)) + lbl + fs))) +(define-ifjump + "##FLONUM.=" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fbeq + emit-fbne + emit-fbeq + emit-fbne + not? + opnds + lbl + fs))) +(define-ifjump + "##FLONUM.<" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fblt + emit-fbge + emit-fbgt + emit-fble + not? + opnds + lbl + fs))) +(define-ifjump + "##FLONUM.>" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fbgt + emit-fble + emit-fblt + emit-fbge + not? + opnds + lbl + fs))) +(define-ifjump + "##FLONUM.<=" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fble + emit-fbgt + emit-fbge + emit-fblt + not? + opnds + lbl + fs))) +(define-ifjump + "##FLONUM.>=" + (lambda (not? opnds lbl fs) + (gen-compares-flo + emit-fbge + emit-fblt + emit-fble + emit-fbgt + not? + opnds + lbl + fs))) +(define-ifjump + "##CHAR=?" + (lambda (not? opnds lbl fs) + (gen-compares emit-beq emit-bne emit-beq emit-bne not? opnds lbl fs))) +(define-ifjump + "##CHAR<?" + (lambda (not? opnds lbl fs) + (gen-compares emit-blt emit-bge emit-bgt emit-ble not? opnds lbl fs))) +(define-ifjump + "##CHAR>?" + (lambda (not? opnds lbl fs) + (gen-compares emit-bgt emit-ble emit-blt emit-bge not? opnds lbl fs))) +(define-ifjump + "##CHAR<=?" + (lambda (not? opnds lbl fs) + (gen-compares emit-ble emit-bgt emit-bge emit-blt not? opnds lbl fs))) +(define-ifjump + "##CHAR>=?" + (lambda (not? opnds lbl fs) + (gen-compares emit-bge emit-blt emit-ble emit-bgt not? opnds lbl fs))) +(define-apply "##CONS" #f (lambda (opnds loc sn) (gen-cons opnds loc sn))) +(define-apply + "##SET-CAR!" + #t + (lambda (opnds loc sn) (gen-set-car! opnds loc sn))) +(define-apply + "##SET-CDR!" + #t + (lambda (opnds loc sn) (gen-set-cdr! opnds loc sn))) +(define-apply "##CAR" #f (make-gen-apply-c...r 2)) +(define-apply "##CDR" #f (make-gen-apply-c...r 3)) +(define-apply "##CAAR" #f (make-gen-apply-c...r 4)) +(define-apply "##CADR" #f (make-gen-apply-c...r 5)) +(define-apply "##CDAR" #f (make-gen-apply-c...r 6)) +(define-apply "##CDDR" #f (make-gen-apply-c...r 7)) +(define-apply "##CAAAR" #f (make-gen-apply-c...r 8)) +(define-apply "##CAADR" #f (make-gen-apply-c...r 9)) +(define-apply "##CADAR" #f (make-gen-apply-c...r 10)) +(define-apply "##CADDR" #f (make-gen-apply-c...r 11)) +(define-apply "##CDAAR" #f (make-gen-apply-c...r 12)) +(define-apply "##CDADR" #f (make-gen-apply-c...r 13)) +(define-apply "##CDDAR" #f (make-gen-apply-c...r 14)) +(define-apply "##CDDDR" #f (make-gen-apply-c...r 15)) +(define-apply "##CAAAAR" #f (make-gen-apply-c...r 16)) +(define-apply "##CAAADR" #f (make-gen-apply-c...r 17)) +(define-apply "##CAADAR" #f (make-gen-apply-c...r 18)) +(define-apply "##CAADDR" #f (make-gen-apply-c...r 19)) +(define-apply "##CADAAR" #f (make-gen-apply-c...r 20)) +(define-apply "##CADADR" #f (make-gen-apply-c...r 21)) +(define-apply "##CADDAR" #f (make-gen-apply-c...r 22)) +(define-apply "##CADDDR" #f (make-gen-apply-c...r 23)) +(define-apply "##CDAAAR" #f (make-gen-apply-c...r 24)) +(define-apply "##CDAADR" #f (make-gen-apply-c...r 25)) +(define-apply "##CDADAR" #f (make-gen-apply-c...r 26)) +(define-apply "##CDADDR" #f (make-gen-apply-c...r 27)) +(define-apply "##CDDAAR" #f (make-gen-apply-c...r 28)) +(define-apply "##CDDADR" #f (make-gen-apply-c...r 29)) +(define-apply "##CDDDAR" #f (make-gen-apply-c...r 30)) +(define-apply "##CDDDDR" #f (make-gen-apply-c...r 31)) +(define-apply + "##MAKE-CELL" + #f + (lambda (opnds loc sn) (gen-cons (list (car opnds) (make-obj '())) loc sn))) +(define-apply "##CELL-REF" #f (make-gen-apply-c...r 2)) +(define-apply + "##CELL-SET!" + #t + (lambda (opnds loc sn) (gen-set-car! opnds loc sn))) +(define-apply "##VECTOR" #f (make-gen-vector 'vector)) +(define-apply "##VECTOR-LENGTH" #f (make-gen-vector-length 'vector)) +(define-apply "##VECTOR-REF" #f (make-gen-vector-ref 'vector)) +(define-apply "##VECTOR-SET!" #t (make-gen-vector-set! 'vector)) +(define-apply "##VECTOR-SHRINK!" #t (make-gen-vector-shrink! 'vector)) +(define-apply "##STRING" #f (make-gen-vector 'string)) +(define-apply "##STRING-LENGTH" #f (make-gen-vector-length 'string)) +(define-apply "##STRING-REF" #f (make-gen-vector-ref 'string)) +(define-apply "##STRING-SET!" #t (make-gen-vector-set! 'string)) +(define-apply "##STRING-SHRINK!" #t (make-gen-vector-shrink! 'string)) +(define-apply "##VECTOR8" #f (make-gen-vector 'vector8)) +(define-apply "##VECTOR8-LENGTH" #f (make-gen-vector-length 'vector8)) +(define-apply "##VECTOR8-REF" #f (make-gen-vector-ref 'vector8)) +(define-apply "##VECTOR8-SET!" #t (make-gen-vector-set! 'vector8)) +(define-apply "##VECTOR8-SHRINK!" #t (make-gen-vector-shrink! 'vector8)) +(define-apply "##VECTOR16" #f (make-gen-vector 'vector16)) +(define-apply "##VECTOR16-LENGTH" #f (make-gen-vector-length 'vector16)) +(define-apply "##VECTOR16-REF" #f (make-gen-vector-ref 'vector16)) +(define-apply "##VECTOR16-SET!" #t (make-gen-vector-set! 'vector16)) +(define-apply "##VECTOR16-SHRINK!" #t (make-gen-vector-shrink! 'vector16)) +(define-apply "##CLOSURE-CODE" #f (make-gen-slot-ref 1 type-procedure)) +(define-apply "##CLOSURE-REF" #f (make-gen-vector-ref 'closure)) +(define-apply "##CLOSURE-SET!" #t (make-gen-vector-set! 'closure)) +(define-apply + "##SUBPROCEDURE-ID" + #f + (lambda (opnds loc sn) (gen-subprocedure-id opnds loc sn))) +(define-apply + "##SUBPROCEDURE-PARENT" + #f + (lambda (opnds loc sn) (gen-subprocedure-parent opnds loc sn))) +(define-apply + "##RETURN-FS" + #f + (lambda (opnds loc sn) (gen-return-fs opnds loc sn))) +(define-apply + "##RETURN-LINK" + #f + (lambda (opnds loc sn) (gen-return-link opnds loc sn))) +(define-apply + "##PROCEDURE-INFO" + #f + (lambda (opnds loc sn) (gen-procedure-info opnds loc sn))) +(define-apply + "##PSTATE" + #f + (lambda (opnds loc sn) (move-opnd68-to-loc pstate-reg loc sn))) +(define-apply + "##MAKE-PLACEHOLDER" + #f + (lambda (opnds loc sn) (gen-make-placeholder opnds loc sn))) +(define-apply + "##TOUCH" + #t + (lambda (opnds loc sn) + (let ((opnd (car opnds))) + (if loc + (touch-opnd-to-loc opnd loc sn) + (touch-opnd-to-any-reg68 opnd sn))))) +(def-spec "NOT" (safe "##NOT")) +(def-spec "NULL?" (safe "##NULL?")) +(def-spec "EQ?" (safe "##EQ?")) +(def-spec "PAIR?" (safe "##PAIR?")) +(def-spec "PROCEDURE?" (safe "##PROCEDURE?")) +(def-spec "VECTOR?" (safe "##VECTOR?")) +(def-spec "SYMBOL?" (safe "##SYMBOL?")) +(def-spec "STRING?" (safe "##STRING?")) +(def-spec "CHAR?" (safe "##CHAR?")) +(def-spec "ZERO?" (safe-arith "##FIXNUM.ZERO?" "##FLONUM.ZERO?")) +(def-spec "POSITIVE?" (safe-arith "##FIXNUM.POSITIVE?" "##FLONUM.POSITIVE?")) +(def-spec "NEGATIVE?" (safe-arith "##FIXNUM.NEGATIVE?" "##FLONUM.NEGATIVE?")) +(def-spec "ODD?" (safe-arith "##FIXNUM.ODD?" #f)) +(def-spec "EVEN?" (safe-arith "##FIXNUM.EVEN?" #f)) +(def-spec "+" (unsafe-arith "##FIXNUM.+" "##FLONUM.+")) +(def-spec "*" (unsafe-arith "##FIXNUM.*" "##FLONUM.*")) +(def-spec "-" (unsafe-arith "##FIXNUM.-" "##FLONUM.-")) +(def-spec "/" (unsafe-arith #f "##FLONUM./")) +(def-spec "QUOTIENT" (unsafe-arith "##FIXNUM.QUOTIENT" #f)) +(def-spec "REMAINDER" (unsafe-arith "##FIXNUM.REMAINDER" #f)) +(def-spec "MODULO" (unsafe-arith "##FIXNUM.MODULO" #f)) +(def-spec "=" (safe-arith "##FIXNUM.=" "##FLONUM.=")) +(def-spec "<" (safe-arith "##FIXNUM.<" "##FLONUM.<")) +(def-spec ">" (safe-arith "##FIXNUM.>" "##FLONUM.>")) +(def-spec "<=" (safe-arith "##FIXNUM.<=" "##FLONUM.<=")) +(def-spec ">=" (safe-arith "##FIXNUM.>=" "##FLONUM.>=")) +(def-spec "ABS" (unsafe-arith #f "##FLONUM.ABS")) +(def-spec "TRUNCATE" (unsafe-arith #f "##FLONUM.TRUNCATE")) +(def-spec "EXP" (unsafe-arith #f "##FLONUM.EXP")) +(def-spec "LOG" (unsafe-arith #f "##FLONUM.LOG")) +(def-spec "SIN" (unsafe-arith #f "##FLONUM.SIN")) +(def-spec "COS" (unsafe-arith #f "##FLONUM.COS")) +(def-spec "TAN" (unsafe-arith #f "##FLONUM.TAN")) +(def-spec "ASIN" (unsafe-arith #f "##FLONUM.ASIN")) +(def-spec "ACOS" (unsafe-arith #f "##FLONUM.ACOS")) +(def-spec "ATAN" (unsafe-arith #f "##FLONUM.ATAN")) +(def-spec "SQRT" (unsafe-arith #f "##FLONUM.SQRT")) +(def-spec "CHAR=?" (safe "##CHAR=?")) +(def-spec "CHAR<?" (safe "##CHAR<?")) +(def-spec "CHAR>?" (safe "##CHAR>?")) +(def-spec "CHAR<=?" (safe "##CHAR<=?")) +(def-spec "CHAR>=?" (safe "##CHAR>=?")) +(def-spec "CONS" (safe "##CONS")) +(def-spec "SET-CAR!" (unsafe "##SET-CAR!")) +(def-spec "SET-CDR!" (unsafe "##SET-CDR!")) +(def-spec "CAR" (unsafe "##CAR")) +(def-spec "CDR" (unsafe "##CDR")) +(def-spec "CAAR" (unsafe "##CAAR")) +(def-spec "CADR" (unsafe "##CADR")) +(def-spec "CDAR" (unsafe "##CDAR")) +(def-spec "CDDR" (unsafe "##CDDR")) +(def-spec "CAAAR" (unsafe "##CAAAR")) +(def-spec "CAADR" (unsafe "##CAADR")) +(def-spec "CADAR" (unsafe "##CADAR")) +(def-spec "CADDR" (unsafe "##CADDR")) +(def-spec "CDAAR" (unsafe "##CDAAR")) +(def-spec "CDADR" (unsafe "##CDADR")) +(def-spec "CDDAR" (unsafe "##CDDAR")) +(def-spec "CDDDR" (unsafe "##CDDDR")) +(def-spec "CAAAAR" (unsafe "##CAAAAR")) +(def-spec "CAAADR" (unsafe "##CAAADR")) +(def-spec "CAADAR" (unsafe "##CAADAR")) +(def-spec "CAADDR" (unsafe "##CAADDR")) +(def-spec "CADAAR" (unsafe "##CADAAR")) +(def-spec "CADADR" (unsafe "##CADADR")) +(def-spec "CADDAR" (unsafe "##CADDAR")) +(def-spec "CADDDR" (unsafe "##CADDDR")) +(def-spec "CDAAAR" (unsafe "##CDAAAR")) +(def-spec "CDAADR" (unsafe "##CDAADR")) +(def-spec "CDADAR" (unsafe "##CDADAR")) +(def-spec "CDADDR" (unsafe "##CDADDR")) +(def-spec "CDDAAR" (unsafe "##CDDAAR")) +(def-spec "CDDADR" (unsafe "##CDDADR")) +(def-spec "CDDDAR" (unsafe "##CDDDAR")) +(def-spec "CDDDDR" (unsafe "##CDDDDR")) +(def-spec "VECTOR" (safe "##VECTOR")) +(def-spec "VECTOR-LENGTH" (unsafe "##VECTOR-LENGTH")) +(def-spec "VECTOR-REF" (unsafe "##VECTOR-REF")) +(def-spec "VECTOR-SET!" (unsafe "##VECTOR-SET!")) +(def-spec "STRING" (safe "##STRING")) +(def-spec "STRING-LENGTH" (unsafe "##STRING-LENGTH")) +(def-spec "STRING-REF" (unsafe "##STRING-REF")) +(def-spec "STRING-SET!" (unsafe "##STRING-SET!")) +(def-spec "TOUCH" (safe "##TOUCH")) +(let ((targ (make-target 4 'm68000))) + (target-begin!-set! targ (lambda (info-port) (begin! info-port targ))) + (put-target targ)) + +(define input-source-code ' +(begin +(declare (standard-bindings) (fixnum) (not safe) (block)) + +(define (fib n) + (if (< n 2) + n + (+ (fib (- n 1)) + (fib (- n 2))))) + +(define (tak x y z) + (if (not (< y x)) + z + (tak (tak (- x 1) y z) + (tak (- y 1) z x) + (tak (- z 1) x y)))) + +(define (ack m n) + (cond ((= m 0) (+ n 1)) + ((= n 0) (ack (- m 1) 1)) + (else (ack (- m 1) (ack m (- n 1)))))) + +(define (create-x n) + (define result (make-vector n)) + (do ((i 0 (+ i 1))) + ((>= i n) result) + (vector-set! result i i))) + +(define (create-y x) + (let* ((n (vector-length x)) + (result (make-vector n))) + (do ((i (- n 1) (- i 1))) + ((< i 0) result) + (vector-set! result i (vector-ref x i))))) + +(define (my-try n) + (vector-length (create-y (create-x n)))) + +(define (go n) + (let loop ((repeat 100) + (result 0)) + (if (> repeat 0) + (loop (- repeat 1) (my-try n)) + result))) + +(+ (fib 20) + (tak 18 12 6) + (ack 3 9) + (go 200000)) +)) + +(define output-expected '( +"|------------------------------------------------------" +"| #[primitive #!program] =" +"L1:" +" cmpw #1,d0" +" beq L1000" +" TRAP1(9,0)" +" LBL_PTR(L1)" +"L1000:" +" MOVE_PROC(1,a1)" +" movl a1,GLOB(fib)" +" MOVE_PROC(2,a1)" +" movl a1,GLOB(tak)" +" MOVE_PROC(3,a1)" +" movl a1,GLOB(ack)" +" MOVE_PROC(4,a1)" +" movl a1,GLOB(create-x)" +" MOVE_PROC(5,a1)" +" movl a1,GLOB(create-y)" +" MOVE_PROC(6,a1)" +" movl a1,GLOB(my-try)" +" MOVE_PROC(7,a1)" +" movl a1,GLOB(go)" +" movl a0,sp@-" +" movl #160,d1" +" lea L2,a0" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1002:" +"L1001:" +" JMP_PROC(1,10)" +" RETURN(L1,1,1)" +"L2:" +" movl d1,sp@-" +" moveq #48,d3" +" moveq #96,d2" +" movl #144,d1" +" lea L3,a0" +" JMP_PROC(2,14)" +" RETURN(L1,2,1)" +"L3:" +" movl d1,sp@-" +" moveq #72,d2" +" moveq #24,d1" +" lea L4,a0" +" JMP_PROC(3,10)" +" RETURN(L1,3,1)" +"L4:" +" movl d1,sp@-" +" movl #1600000,d1" +" lea L5,a0" +" JMP_PROC(7,10)" +" RETURN(L1,4,1)" +"L5:" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" TRAP2(24)" +" RETURN(L1,4,1)" +"L1004:" +"L1003:" +"L6:" +" addl sp@(8),d1" +" addl sp@(4),d1" +" addl sp@+,d1" +" addql #8,sp" +" rts" +"L0:" +"|------------------------------------------------------" +"| #[primitive fib] =" +"L1:" +" bmi L1000" +" TRAP1(9,1)" +" LBL_PTR(L1)" +"L1000:" +" moveq #16,d0" +" cmpl d1,d0" +" ble L3" +" bra L4" +" RETURN(L1,2,1)" +"L2:" +" movl d1,sp@-" +" movl sp@(4),d1" +" moveq #-16,d0" +" addl d0,d1" +" lea L5,a0" +" moveq #16,d0" +" cmpl d1,d0" +" bgt L4" +"L3:" +" movl a0,sp@-" +" movl d1,sp@-" +" subql #8,d1" +" lea L2,a0" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" TRAP2(24)" +" RETURN(L1,2,1)" +"L1002:" +"L1001:" +" moveq #16,d0" +" cmpl d1,d0" +" ble L3" +"L4:" +" jmp a0@" +" RETURN(L1,3,1)" +"L5:" +" addl sp@+,d1" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" TRAP2(24)" +" RETURN(L1,2,1)" +"L1004:" +"L1003:" +" addql #4,sp" +" rts" +"L0:" +"|------------------------------------------------------" +"| #[primitive tak] =" +"L1:" +" cmpw #4,d0" +" beq L1000" +" TRAP1(9,3)" +" LBL_PTR(L1)" +"L1000:" +" cmpl d1,d2" +" bge L4" +" bra L3" +" RETURN(L1,6,1)" +"L2:" +" movl d1,d3" +" movl sp@(20),a0" +" movl sp@+,d2" +" movl sp@+,d1" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" movl a0,sp@(12)" +" TRAP2(24)" +" RETURN(L1,4,1)" +"L1002:" +" movl sp@(12),a0" +"L1001:" +" cmpl d1,d2" +" lea sp@(16),sp" +" bge L4" +"L3:" +" movl a0,sp@-" +" movl d1,sp@-" +" movl d2,sp@-" +" movl d3,sp@-" +" subql #8,d1" +" lea L5,a0" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" TRAP2(24)" +" RETURN(L1,4,1)" +"L1004:" +"L1003:" +" cmpl d1,d2" +" blt L3" +"L4:" +" movl d3,d1" +" jmp a0@" +" RETURN(L1,4,1)" +"L5:" +" movl d1,sp@-" +" movl sp@(12),d3" +" movl sp@(4),d2" +" movl sp@(8),d1" +" subql #8,d1" +" lea L6,a0" +" cmpl d1,d2" +" bge L4" +" bra L3" +" RETURN(L1,5,1)" +"L6:" +" movl d1,sp@-" +" movl sp@(12),d3" +" movl sp@(16),d2" +" movl sp@(8),d1" +" subql #8,d1" +" lea L2,a0" +" cmpl d1,d2" +" bge L4" +" bra L3" +"L0:" +"|------------------------------------------------------" +"| #[primitive ack] =" +"L1:" +" beq L1000" +" TRAP1(9,2)" +" LBL_PTR(L1)" +"L1000:" +" movl d1,d0" +" bne L3" +" bra L5" +" RETURN(L1,2,1)" +"L2:" +" movl d1,d2" +" movl sp@+,d1" +" subql #8,d1" +" movl sp@+,a0" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1002:" +" movl sp@+,a0" +"L1001:" +" movl d1,d0" +" beq L5" +"L3:" +" movl d2,d0" +" bne L6" +"L4:" +" subql #8,d1" +" moveq #8,d2" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1004:" +" movl sp@+,a0" +"L1003:" +" movl d1,d0" +" bne L3" +"L5:" +" movl d2,d1" +" addql #8,d1" +" jmp a0@" +"L6:" +" movl a0,sp@-" +" movl d1,sp@-" +" movl d2,d1" +" subql #8,d1" +" movl d1,d2" +" movl sp@,d1" +" lea L2,a0" +" dbra d5,L1005" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1005" +" TRAP2(24)" +" RETURN(L1,2,1)" +"L1006:" +"L1005:" +" movl d1,d0" +" bne L3" +" bra L5" +"L0:" +"|------------------------------------------------------" +"| #[primitive create-x] =" +"L1:" +" bmi L1000" +" TRAP1(9,1)" +" LBL_PTR(L1)" +"L1000:" +" movl a0,sp@-" +" movl d1,sp@-" +" lea L2,a0" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" TRAP2(24)" +" RETURN(L1,2,1)" +"L1002:" +"L1001:" +" moveq #-1,d0" +" JMP_PRIM(make-vector,0)" +" RETURN(L1,2,1)" +"L2:" +" movl d1,d2" +" movl sp@+,d1" +" moveq #0,d3" +" movl sp@+,a0" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1004:" +" movl sp@+,a0" +"L1003:" +" cmpl d1,d3" +" bge L4" +"L3:" +" movl d3,d0" +" asrl #1,d0" +" movl d2,a1" +" movl d3,a1@(1,d0:l)" +" addql #8,d3" +" dbra d5,L1005" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1005" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1006:" +" movl sp@+,a0" +"L1005:" +" cmpl d1,d3" +" blt L3" +"L4:" +" movl d2,d1" +" jmp a0@" +"L0:" +"|------------------------------------------------------" +"| #[primitive create-y] =" +"L1:" +" bmi L1000" +" TRAP1(9,1)" +" LBL_PTR(L1)" +"L1000:" +" movl d1,a1" +" movl a1@(-3),d2" +" lsrl #7,d2" +" movl a0,sp@-" +" movl d1,sp@-" +" movl d2,sp@-" +" movl d2,d1" +" lea L2,a0" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" TRAP2(24)" +" RETURN(L1,3,1)" +"L1002:" +"L1001:" +" moveq #-1,d0" +" JMP_PRIM(make-vector,0)" +" RETURN(L1,3,1)" +"L2:" +" movl sp@+,d2" +" subql #8,d2" +" movl d2,d3" +" movl d1,d2" +" movl sp@+,d1" +" movl sp@+,a0" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1004:" +" movl sp@+,a0" +"L1003:" +" movl d3,d0" +" blt L4" +"L3:" +" movl d3,d0" +" asrl #1,d0" +" movl d1,a1" +" movl a1@(1,d0:l),d4" +" movl d3,d0" +" asrl #1,d0" +" movl d2,a1" +" movl d4,a1@(1,d0:l)" +" subql #8,d3" +" dbra d5,L1005" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1005" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1006:" +" movl sp@+,a0" +"L1005:" +" movl d3,d0" +" bge L3" +"L4:" +" movl d2,d1" +" jmp a0@" +"L0:" +"|------------------------------------------------------" +"| #[primitive my-try] =" +"L1:" +" bmi L1000" +" TRAP1(9,1)" +" LBL_PTR(L1)" +"L1000:" +" movl a0,sp@-" +" lea L2,a0" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1002:" +"L1001:" +" JMP_PROC(4,10)" +" RETURN(L1,1,1)" +"L2:" +" lea L3,a0" +" JMP_PROC(5,10)" +" RETURN(L1,1,1)" +"L3:" +" movl d1,a1" +" movl a1@(-3),d1" +" lsrl #7,d1" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1004:" +"L1003:" +" rts" +"L0:" +"|------------------------------------------------------" +"| #[primitive go] =" +"L1:" +" bmi L1000" +" TRAP1(9,1)" +" LBL_PTR(L1)" +"L1000:" +" moveq #0,d3" +" movl #800,d2" +" dbra d5,L1001" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1001" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1002:" +" movl sp@+,a0" +"L1001:" +" movl d2,d0" +" ble L4" +" bra L3" +" RETURN(L1,3,1)" +"L2:" +" movl d1,d3" +" movl sp@+,d1" +" subql #8,d1" +" movl d1,d2" +" movl sp@+,d1" +" movl sp@+,a0" +" dbra d5,L1003" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1003" +" movl a0,sp@-" +" TRAP2(24)" +" RETURN(L1,1,1)" +"L1004:" +" movl sp@+,a0" +"L1003:" +" movl d2,d0" +" ble L4" +"L3:" +" movl a0,sp@-" +" movl d1,sp@-" +" movl d2,sp@-" +" lea L2,a0" +" dbra d5,L1005" +" moveq #9,d5" +" cmpl a5@,sp" +" bcc L1005" +" TRAP2(24)" +" RETURN(L1,3,1)" +"L1006:" +"L1005:" +" JMP_PROC(6,10)" +"L4:" +" movl d3,d1" +" jmp a0@" +"L0:" +"")) + +(define (main . args) + (run-benchmark + "compiler" + compiler-iters + (lambda (result) + (equal? result output-expected)) + (lambda (expr target opt) (lambda () (ce expr target opt) (asm-output-get))) + input-source-code + 'm68000 + 'asm)) + +(main) diff --git a/tests/runtests.sh b/tests/runtests.sh index daf6e9b1..057b3dd8 100644 --- a/tests/runtests.sh +++ b/tests/runtests.sh @@ -208,7 +208,8 @@ $compile -e embedded2.scm ./a.out echo "======================================== timing compilation ..." -time $compile silex.scm -t -S -O3 +time $compile compiler.scm -t -S -O5 -debug pbo -vv +time ./a.out echo "======================================== running floating-point benchmark ..." echo "boxed:" diff --git a/tests/silex.scm b/tests/silex.scm deleted file mode 100644 index df550540..00000000 --- a/tests/silex.scm +++ /dev/null @@ -1,6717 +0,0 @@ -;; Copyright (C) 1997 Danny Dube, Universite de Montreal. -;; All rights reserved. - -;; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following -;; conditions are met: - -;; Redistributions of source code must retain the above copyright notice, this list of conditions and the following -;; disclaimer. -;; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following -;; disclaimer in the documentation and/or other materials provided with the distribution. -;; Neither the name of the author nor the names of its contributors may be used to endorse or promote -;; products derived from this software without specific prior written permission. - -;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS -;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY -;; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR -;; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -;; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -;; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -;; POSSIBILITY OF SUCH DAMAGE. - - -(declare - (fixnum) - (no-procedure-checks-for-usual-bindings) ) - - -(require-library srfi-13) - - -(module silex * - (import scheme srfi-13) ; srfi-13 for string-downcase - -;---------------------------------------------------------------------------------------------------- - -(define (string-append-list lst) - (let loop1 ((n 0) (x lst) (y '())) - (if (pair? x) - (let ((s (car x))) - (loop1 (+ n (string-length s)) (cdr x) (cons s y))) - (let ((result (make-string n #\space))) - (let loop2 ((k (- n 1)) (y y)) - (if (pair? y) - (let ((s (car y))) - (let loop3 ((i k) (j (- (string-length s) 1))) - (if (not (< j 0)) - (begin - (string-set! result i (string-ref s j)) - (loop3 (- i 1) (- j 1))) - (loop2 i (cdr y))))) - result)))))) - -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; Module util.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; -; Quelques definitions de constantes -; - -(define eof-tok 0) -(define hblank-tok 1) -(define vblank-tok 2) -(define pipe-tok 3) -(define question-tok 4) -(define plus-tok 5) -(define star-tok 6) -(define lpar-tok 7) -(define rpar-tok 8) -(define dot-tok 9) -(define lbrack-tok 10) -(define lbrack-rbrack-tok 11) -(define lbrack-caret-tok 12) -(define lbrack-minus-tok 13) -(define subst-tok 14) -(define power-tok 15) -(define doublequote-tok 16) -(define char-tok 17) -(define caret-tok 18) -(define dollar-tok 19) -(define <<EOF>>-tok 20) -(define <<ERROR>>-tok 21) -(define percent-percent-tok 22) -(define id-tok 23) -(define rbrack-tok 24) -(define minus-tok 25) -(define illegal-tok 26) -; Tokens agreges -(define class-tok 27) -(define string-tok 28) - -(define number-of-tokens 29) - -(define newline-ch (char->integer #\newline)) -(define tab-ch (char->integer #\ )) -(define dollar-ch (char->integer #\$)) -(define minus-ch (char->integer #\-)) -(define rbrack-ch (char->integer #\])) -(define caret-ch (char->integer #\^)) - -(define dot-class (list (cons 'inf- (- newline-ch 1)) - (cons (+ newline-ch 1) 'inf+))) - -(define default-action - (string-append " (yycontinue)" (string #\newline))) -(define default-<<EOF>>-action - (string-append " '(0)" (string #\newline))) -(define default-<<ERROR>>-action - (string-append " (begin" - (string #\newline) - " (display \"Error: Invalid token.\")" - (string #\newline) - " (newline)" - (string #\newline) - " 'error)" - (string #\newline))) - - - - -; -; Fabrication de tables de dispatch -; - -(define make-dispatch-table - (lambda (size alist default) - (let ((v (make-vector size default))) - (let loop ((alist alist)) - (if (null? alist) - v - (begin - (vector-set! v (caar alist) (cdar alist)) - (loop (cdr alist)))))))) - - - - -; -; Fonctions de manipulation des tokens -; - -(define make-tok - (lambda (tok-type lexeme line column . attr) - (cond ((null? attr) - (vector tok-type line column lexeme)) - ((null? (cdr attr)) - (vector tok-type line column lexeme (car attr))) - (else - (vector tok-type line column lexeme (car attr) (cadr attr)))))) - -(define get-tok-type (lambda (tok) (vector-ref tok 0))) -(define get-tok-line (lambda (tok) (vector-ref tok 1))) -(define get-tok-column (lambda (tok) (vector-ref tok 2))) -(define get-tok-lexeme (lambda (tok) (vector-ref tok 3))) -(define get-tok-attr (lambda (tok) (vector-ref tok 4))) -(define get-tok-2nd-attr (lambda (tok) (vector-ref tok 5))) - - - - -; -; Fonctions de manipulations des regles -; - -(define make-rule - (lambda (line eof? error? bol? eol? regexp action) - (vector line eof? error? bol? eol? regexp action #f))) - -(define get-rule-line (lambda (rule) (vector-ref rule 0))) -(define get-rule-eof? (lambda (rule) (vector-ref rule 1))) -(define get-rule-error? (lambda (rule) (vector-ref rule 2))) -(define get-rule-bol? (lambda (rule) (vector-ref rule 3))) -(define get-rule-eol? (lambda (rule) (vector-ref rule 4))) -(define get-rule-regexp (lambda (rule) (vector-ref rule 5))) -(define get-rule-action (lambda (rule) (vector-ref rule 6))) -(define get-rule-yytext? (lambda (rule) (vector-ref rule 7))) - -(define set-rule-regexp (lambda (rule regexp) (vector-set! rule 5 regexp))) -(define set-rule-action (lambda (rule action) (vector-set! rule 6 action))) -(define set-rule-yytext? (lambda (rule yytext?) (vector-set! rule 7 yytext?))) - - - - -; -; Noeuds des regexp -; - -(define epsilon-re 0) -(define or-re 1) -(define conc-re 2) -(define star-re 3) -(define plus-re 4) -(define question-re 5) -(define class-re 6) -(define char-re 7) - -(define make-re - (lambda (re-type . lattr) - (cond ((null? lattr) - (vector re-type)) - ((null? (cdr lattr)) - (vector re-type (car lattr))) - ((null? (cddr lattr)) - (vector re-type (car lattr) (cadr lattr)))))) - -(define get-re-type (lambda (re) (vector-ref re 0))) -(define get-re-attr1 (lambda (re) (vector-ref re 1))) -(define get-re-attr2 (lambda (re) (vector-ref re 2))) - - - - -; -; Fonctions de manipulation des ensembles d'etats -; - -; Intersection de deux ensembles d'etats -(define ss-inter - (lambda (ss1 ss2) - (cond ((null? ss1) - '()) - ((null? ss2) - '()) - (else - (let ((t1 (car ss1)) - (t2 (car ss2))) - (cond ((< t1 t2) - (ss-inter (cdr ss1) ss2)) - ((= t1 t2) - (cons t1 (ss-inter (cdr ss1) (cdr ss2)))) - (else - (ss-inter ss1 (cdr ss2))))))))) - -; Difference entre deux ensembles d'etats -(define ss-diff - (lambda (ss1 ss2) - (cond ((null? ss1) - '()) - ((null? ss2) - ss1) - (else - (let ((t1 (car ss1)) - (t2 (car ss2))) - (cond ((< t1 t2) - (cons t1 (ss-diff (cdr ss1) ss2))) - ((= t1 t2) - (ss-diff (cdr ss1) (cdr ss2))) - (else - (ss-diff ss1 (cdr ss2))))))))) - -; Union de deux ensembles d'etats -(define ss-union - (lambda (ss1 ss2) - (cond ((null? ss1) - ss2) - ((null? ss2) - ss1) - (else - (let ((t1 (car ss1)) - (t2 (car ss2))) - (cond ((< t1 t2) - (cons t1 (ss-union (cdr ss1) ss2))) - ((= t1 t2) - (cons t1 (ss-union (cdr ss1) (cdr ss2)))) - (else - (cons t2 (ss-union ss1 (cdr ss2)))))))))) - -; Decoupage de deux ensembles d'etats -(define ss-sep - (lambda (ss1 ss2) - (let loop ((ss1 ss1) (ss2 ss2) (l '()) (c '()) (r '())) - (if (null? ss1) - (if (null? ss2) - (vector (reverse l) (reverse c) (reverse r)) - (loop ss1 (cdr ss2) l c (cons (car ss2) r))) - (if (null? ss2) - (loop (cdr ss1) ss2 (cons (car ss1) l) c r) - (let ((t1 (car ss1)) - (t2 (car ss2))) - (cond ((< t1 t2) - (loop (cdr ss1) ss2 (cons t1 l) c r)) - ((= t1 t2) - (loop (cdr ss1) (cdr ss2) l (cons t1 c) r)) - (else - (loop ss1 (cdr ss2) l c (cons t2 r)))))))))) - - - - -; -; Fonctions de manipulation des classes de caracteres -; - -; Comparaisons de bornes d'intervalles -(define class-= eqv?) - -(define class-<= - (lambda (b1 b2) - (cond ((eq? b1 'inf-) #t) - ((eq? b2 'inf+) #t) - ((eq? b1 'inf+) #f) - ((eq? b2 'inf-) #f) - (else (<= b1 b2))))) - -(define class->= - (lambda (b1 b2) - (cond ((eq? b1 'inf+) #t) - ((eq? b2 'inf-) #t) - ((eq? b1 'inf-) #f) - ((eq? b2 'inf+) #f) - (else (>= b1 b2))))) - -(define class-< - (lambda (b1 b2) - (cond ((eq? b1 'inf+) #f) - ((eq? b2 'inf-) #f) - ((eq? b1 'inf-) #t) - ((eq? b2 'inf+) #t) - (else (< b1 b2))))) - -(define class-> - (lambda (b1 b2) - (cond ((eq? b1 'inf-) #f) - ((eq? b2 'inf+) #f) - ((eq? b1 'inf+) #t) - ((eq? b2 'inf-) #t) - (else (> b1 b2))))) - -; Complementation d'une classe -(define class-compl - (lambda (c) - (let loop ((c c) (start 'inf-)) - (if (null? c) - (list (cons start 'inf+)) - (let* ((r (car c)) - (rstart (car r)) - (rend (cdr r))) - (if (class-< start rstart) - (cons (cons start (- rstart 1)) - (loop c rstart)) - (if (class-< rend 'inf+) - (loop (cdr c) (+ rend 1)) - '()))))))) - -; Union de deux classes de caracteres -(define class-union - (lambda (c1 c2) - (let loop ((c1 c1) (c2 c2) (u '())) - (if (null? c1) - (if (null? c2) - (reverse u) - (loop c1 (cdr c2) (cons (car c2) u))) - (if (null? c2) - (loop (cdr c1) c2 (cons (car c1) u)) - (let* ((r1 (car c1)) - (r2 (car c2)) - (r1start (car r1)) - (r1end (cdr r1)) - (r2start (car r2)) - (r2end (cdr r2))) - (if (class-<= r1start r2start) - (cond ((class-= r1end 'inf+) - (loop c1 (cdr c2) u)) - ((class-< (+ r1end 1) r2start) - (loop (cdr c1) c2 (cons r1 u))) - ((class-<= r1end r2end) - (loop (cdr c1) - (cons (cons r1start r2end) (cdr c2)) - u)) - (else - (loop c1 (cdr c2) u))) - (cond ((class-= r2end 'inf+) - (loop (cdr c1) c2 u)) - ((class-> r1start (+ r2end 1)) - (loop c1 (cdr c2) (cons r2 u))) - ((class->= r1end r2end) - (loop (cons (cons r2start r1end) (cdr c1)) - (cdr c2) - u)) - (else - (loop (cdr c1) c2 u)))))))))) - -; Decoupage de deux classes de caracteres -(define class-sep - (lambda (c1 c2) - (let loop ((c1 c1) (c2 c2) (l '()) (c '()) (r '())) - (if (null? c1) - (if (null? c2) - (vector (reverse l) (reverse c) (reverse r)) - (loop c1 (cdr c2) l c (cons (car c2) r))) - (if (null? c2) - (loop (cdr c1) c2 (cons (car c1) l) c r) - (let* ((r1 (car c1)) - (r2 (car c2)) - (r1start (car r1)) - (r1end (cdr r1)) - (r2start (car r2)) - (r2end (cdr r2))) - (cond ((class-< r1start r2start) - (if (class-< r1end r2start) - (loop (cdr c1) c2 (cons r1 l) c r) - (loop (cons (cons r2start r1end) (cdr c1)) c2 - (cons (cons r1start (- r2start 1)) l) c r))) - ((class-> r1start r2start) - (if (class-> r1start r2end) - (loop c1 (cdr c2) l c (cons r2 r)) - (loop c1 (cons (cons r1start r2end) (cdr c2)) - l c (cons (cons r2start (- r1start 1)) r)))) - (else - (cond ((class-< r1end r2end) - (loop (cdr c1) - (cons (cons (+ r1end 1) r2end) (cdr c2)) - l (cons r1 c) r)) - ((class-= r1end r2end) - (loop (cdr c1) (cdr c2) l (cons r1 c) r)) - (else - (loop (cons (cons (+ r2end 1) r1end) (cdr c1)) - (cdr c2) - l (cons r2 c) r))))))))))) - -; Transformer une classe (finie) de caracteres en une liste de ... -(define class->char-list - (lambda (c) - (let loop1 ((c c)) - (if (null? c) - '() - (let* ((r (car c)) - (rend (cdr r)) - (tail (loop1 (cdr c)))) - (let loop2 ((rstart (car r))) - (if (<= rstart rend) - (cons (integer->char rstart) (loop2 (+ rstart 1))) - tail))))))) - -; Transformer une classe de caracteres en une liste poss. compl. -; 1er element = #t -> classe complementee -(define class->tagged-char-list - (lambda (c) - (let* ((finite? (or (null? c) (number? (caar c)))) - (c2 (if finite? c (class-compl c))) - (c-l (class->char-list c2))) - (cons (not finite?) c-l)))) - - - - -; -; Fonction digraph -; - -; Fonction "digraph". -; Etant donne un graphe dirige dont les noeuds comportent une valeur, -; calcule pour chaque noeud la "somme" des valeurs contenues dans le -; noeud lui-meme et ceux atteignables a partir de celui-ci. La "somme" -; consiste a appliquer un operateur commutatif et associatif aux valeurs -; lorsqu'elles sont additionnees. -; L'entree consiste en un vecteur de voisinages externes, un autre de -; valeurs initiales et d'un operateur. -; La sortie est un vecteur de valeurs finales. -(define digraph - (lambda (arcs init op) - (let* ((nbnodes (vector-length arcs)) - (infinity nbnodes) - (prio (make-vector nbnodes -1)) - (stack (make-vector nbnodes #f)) - (sp 0) - (final (make-vector nbnodes #f))) - (letrec ((store-final - (lambda (self-sp value) - (let loop () - (if (> sp self-sp) - (let ((voisin (vector-ref stack (- sp 1)))) - (vector-set! prio voisin infinity) - (set! sp (- sp 1)) - (vector-set! final voisin value) - (loop)))))) - (visit-node - (lambda (n) - (let ((self-sp sp)) - (vector-set! prio n self-sp) - (vector-set! stack sp n) - (set! sp (+ sp 1)) - (vector-set! final n (vector-ref init n)) - (let loop ((vois (vector-ref arcs n))) - (if (pair? vois) - (let* ((v (car vois)) - (vprio (vector-ref prio v))) - (if (= vprio -1) - (visit-node v)) - (vector-set! prio n (min (vector-ref prio n) - (vector-ref prio v))) - (vector-set! final n (op (vector-ref final n) - (vector-ref final v))) - (loop (cdr vois))))) - (if (= (vector-ref prio n) self-sp) - (store-final self-sp (vector-ref final n))))))) - (let loop ((n 0)) - (if (< n nbnodes) - (begin - (if (= (vector-ref prio n) -1) - (visit-node n)) - (loop (+ n 1))))) - final)))) - - - - -; -; Fonction de tri -; - -(define merge-sort-merge - (lambda (l1 l2 cmp-<=) - (cond ((null? l1) - l2) - ((null? l2) - l1) - (else - (let ((h1 (car l1)) - (h2 (car l2))) - (if (cmp-<= h1 h2) - (cons h1 (merge-sort-merge (cdr l1) l2 cmp-<=)) - (cons h2 (merge-sort-merge l1 (cdr l2) cmp-<=)))))))) - -(define merge-sort - (lambda (l cmp-<=) - (if (null? l) - l - (let loop1 ((ll (map list l))) - (if (null? (cdr ll)) - (car ll) - (loop1 - (let loop2 ((ll ll)) - (cond ((null? ll) - ll) - ((null? (cdr ll)) - ll) - (else - (cons (merge-sort-merge (car ll) (cadr ll) cmp-<=) - (loop2 (cddr ll)))))))))))) - -; Module action.l.scm. -; -; Table generated from the file action.l by SILex 1.0 -; - -(define action-tables - (vector - 'all - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok eof-tok yytext yyline yycolumn) - )) - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (begin - (display "Error: Invalid token.") - (newline) - 'error) - )) - (vector - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok hblank-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok vblank-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok char-tok yytext yyline yycolumn) - ))) - 'tagged-chars-lists - 0 - 0 - '#((((#f #\ #\space) . 4) - ((#f #\;) . 3) - ((#f #\newline) . 2) - ((#t #\ #\newline #\space #\;) . 1)) - (((#t #\newline) . 1)) - () - (((#t #\newline) . 3)) - (((#f #\ #\space) . 4) - ((#f #\;) . 3) - ((#t #\ #\newline #\space #\;) . 1))) - '#((#f . #f) (2 . 2) (1 . 1) (0 . 0) (0 . 0)))) - -; Module class.l.scm. -; -; Table generated from the file class.l by SILex 1.0 -; - -(define class-tables - (vector - 'all - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok eof-tok yytext yyline yycolumn) - )) - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (begin - (display "Error: Invalid token.") - (newline) - 'error) - )) - (vector - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok rbrack-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok minus-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-spec-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-digits-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-digits-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-quoted-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-ordinary-char yytext yyline yycolumn) - ))) - 'tagged-chars-lists - 0 - 0 - '#((((#f #\]) . 4) ((#f #\-) . 3) ((#f #\\) . 2) ((#t #\- #\\ #\]) . 1)) - () - (((#f #\n) . 8) - ((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 7) - ((#f #\-) . 6) - ((#t #\- #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\n) . 5)) - () - () - () - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 9)) - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 10)) - () - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 9)) - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 10))) - '#((#f . #f) (6 . 6) (6 . 6) (1 . 1) (0 . 0) (5 . 5) (5 . 5) - (3 . 3) (2 . 2) (4 . 4) (3 . 3)))) - -; Module macro.l.scm. -; -; Table generated from the file macro.l by SILex 1.0 -; - -(define macro-tables - (vector - 'all - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok eof-tok yytext yyline yycolumn) - )) - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (begin - (display "Error: Invalid token.") - (newline) - 'error) - )) - (vector - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok hblank-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok vblank-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok percent-percent-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-id yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok illegal-tok yytext yyline yycolumn) - ))) - 'tagged-chars-lists - 0 - 0 - '#((((#f #\ #\space) . 8) - ((#f #\;) . 7) - ((#f #\newline) . 6) - ((#f #\%) . 5) - ((#f #\! #\$ #\& #\* #\/ #\: #\< #\= #\> #\? #\A #\B #\C #\D #\E - #\F #\G #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U - #\V #\W #\X #\Y #\Z #\^ #\_ #\a #\b #\c #\d #\e #\f #\g #\h #\i - #\j #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y - #\z #\~) - . - 4) - ((#f #\+ #\-) . 3) - ((#f #\.) . 2) - ((#t #\ #\newline #\space #\! #\$ - #\% #\& #\* #\+ #\- #\. - #\/ #\: #\; #\< #\= #\> - #\? #\A #\B #\C #\D #\E - #\F #\G #\H #\I #\J #\K - #\L #\M #\N #\O #\P #\Q - #\R #\S #\T #\U #\V #\W - #\X #\Y #\Z #\^ #\_ #\a - #\b #\c #\d #\e #\f #\g - #\h #\i #\j #\k #\l #\m - #\n #\o #\p #\q #\r #\s - #\t #\u #\v #\w #\x #\y - #\z #\~) - . - 1)) - () - (((#f #\.) . 9)) - () - (((#f #\! #\$ #\% #\& #\* #\+ #\- #\. #\/ #\0 #\1 #\2 #\3 #\4 #\5 - #\6 #\7 #\8 #\9 #\: #\< #\= #\> #\? #\A #\B #\C #\D #\E #\F #\G - #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W - #\X #\Y #\Z #\^ #\_ #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k - #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z #\~) - . - 10)) - (((#f #\%) . 11) - ((#f #\! #\$ #\& #\* #\+ #\- #\. #\/ #\0 #\1 #\2 #\3 #\4 #\5 #\6 - #\7 #\8 #\9 #\: #\< #\= #\> #\? #\A #\B #\C #\D #\E #\F #\G #\H - #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X - #\Y #\Z #\^ #\_ #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k #\l - #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z #\~) - . - 10)) - () - (((#t #\newline) . 12)) - () - (((#f #\.) . 13)) - (((#f #\! #\$ #\% #\& #\* #\+ #\- #\. #\/ #\0 #\1 #\2 #\3 #\4 #\5 - #\6 #\7 #\8 #\9 #\: #\< #\= #\> #\? #\A #\B #\C #\D #\E #\F #\G - #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W - #\X #\Y #\Z #\^ #\_ #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k - #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z #\~) - . - 10)) - (((#f #\! #\$ #\% #\& #\* #\+ #\- #\. #\/ #\0 #\1 #\2 #\3 #\4 #\5 - #\6 #\7 #\8 #\9 #\: #\< #\= #\> #\? #\A #\B #\C #\D #\E #\F #\G - #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W - #\X #\Y #\Z #\^ #\_ #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k - #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z #\~) - . - 10)) - (((#t #\newline) . 12)) - ()) - '#((#f . #f) (4 . 4) (4 . 4) (3 . 3) (3 . 3) (3 . 3) (1 . 1) - (0 . 0) (0 . 0) (#f . #f) (3 . 3) (2 . 2) (0 . 0) (3 . 3)))) - -; Module regexp.l.scm. -; -; Table generated from the file regexp.l by SILex 1.0 -; - -(define regexp-tables - (vector - 'all - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok eof-tok yytext yyline yycolumn) - )) - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (begin - (display "Error: Invalid token.") - (newline) - 'error) - )) - (vector - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok hblank-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok vblank-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok pipe-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok question-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok plus-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok star-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok lpar-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok rpar-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok dot-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok lbrack-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok lbrack-rbrack-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok lbrack-caret-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok lbrack-minus-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-id-ref yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-power-m yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-power-m-inf yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-power-m-n yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok illegal-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok doublequote-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-spec-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-digits-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-digits-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-quoted-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok caret-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok dollar-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-ordinary-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok <<EOF>>-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok <<ERROR>>-tok yytext yyline yycolumn) - ))) - 'tagged-chars-lists - 0 - 0 - '#((((#f #\ #\space) . 18) - ((#f #\;) . 17) - ((#f #\newline) . 16) - ((#f #\|) . 15) - ((#f #\?) . 14) - ((#f #\+) . 13) - ((#f #\*) . 12) - ((#f #\() . 11) - ((#f #\)) . 10) - ((#f #\.) . 9) - ((#f #\[) . 8) - ((#f #\{) . 7) - ((#f #\") . 6) - ((#f #\\) . 5) - ((#f #\^) . 4) - ((#f #\$) . 3) - ((#t #\ #\newline #\space #\" #\$ - #\( #\) #\* #\+ #\. #\; - #\< #\? #\[ #\\ #\^ #\{ - #\|) - . - 2) - ((#f #\<) . 1)) - (((#f #\<) . 19)) - () - () - () - (((#f #\n) . 23) - ((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 22) - ((#f #\-) . 21) - ((#t #\- #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\n) . 20)) - () - (((#f #\! #\$ #\% #\& #\* #\/ #\: #\< #\= #\> #\? #\A #\B #\C #\D - #\E #\F #\G #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T - #\U #\V #\W #\X #\Y #\Z #\^ #\_ #\a #\b #\c #\d #\e #\f #\g #\h - #\i #\j #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x - #\y #\z #\~) - . - 27) - ((#f #\+ #\-) . 26) - ((#f #\.) . 25) - ((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 24)) - (((#f #\]) . 30) ((#f #\^) . 29) ((#f #\-) . 28)) - () - () - () - () - () - () - () - () - (((#t #\newline) . 31)) - () - (((#f #\E) . 32)) - () - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 33)) - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 34)) - () - (((#f #\}) . 36) - ((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 24) - ((#f #\,) . 35)) - (((#f #\.) . 37)) - (((#f #\}) . 38)) - (((#f #\}) . 38) - ((#f #\! #\$ #\% #\& #\* #\+ #\- #\. #\/ #\0 #\1 #\2 #\3 #\4 #\5 - #\6 #\7 #\8 #\9 #\: #\< #\= #\> #\? #\A #\B #\C #\D #\E #\F #\G - #\H #\I #\J #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W - #\X #\Y #\Z #\^ #\_ #\a #\b #\c #\d #\e #\f #\g #\h #\i #\j #\k - #\l #\m #\n #\o #\p #\q #\r #\s #\t #\u #\v #\w #\x #\y #\z #\~) - . - 27)) - () - () - () - (((#t #\newline) . 31)) - (((#f #\O) . 40) ((#f #\R) . 39)) - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 33)) - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 34)) - (((#f #\}) . 42) ((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 41)) - () - (((#f #\.) . 26)) - () - (((#f #\R) . 43)) - (((#f #\F) . 44)) - (((#f #\}) . 45) ((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 41)) - () - (((#f #\O) . 46)) - (((#f #\>) . 47)) - () - (((#f #\R) . 48)) - (((#f #\>) . 49)) - (((#f #\>) . 50)) - () - (((#f #\>) . 51)) - ()) - '#((#f . #f) (25 . 25) (25 . 25) (24 . 24) (23 . 23) (25 . 25) (18 . 18) - (17 . 17) (9 . 9) (8 . 8) (7 . 7) (6 . 6) (5 . 5) (4 . 4) - (3 . 3) (2 . 2) (1 . 1) (0 . 0) (0 . 0) (#f . #f) (22 . 22) - (22 . 22) (20 . 20) (19 . 19) (#f . #f) (#f . #f) (#f . #f) (#f . #f) - (12 . 12) (11 . 11) (10 . 10) (0 . 0) (#f . #f) (21 . 21) (20 . 20) - (#f . #f) (14 . 14) (#f . #f) (13 . 13) (#f . #f) (#f . #f) (#f . #f) - (15 . 15) (#f . #f) (#f . #f) (16 . 16) (#f . #f) (#f . #f) (#f . #f) - (26 . 26) (#f . #f) (27 . 27)))) - -; Module string.l.scm. -; -; Table generated from the file string.l by SILex 1.0 -; - -(define string-tables - (vector - 'all - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok eof-tok yytext yyline yycolumn) - )) - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (begin - (display "Error: Invalid token.") - (newline) - 'error) - )) - (vector - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (make-tok doublequote-tok yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-spec-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-digits-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-digits-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-quoted-char yytext yyline yycolumn) - )) - #t - (lambda (yycontinue yygetc yyungetc) - (lambda (yytext yyline yycolumn yyoffset) - (parse-ordinary-char yytext yyline yycolumn) - ))) - 'tagged-chars-lists - 0 - 0 - '#((((#f #\") . 3) ((#f #\\) . 2) ((#t #\" #\\) . 1)) - () - (((#f #\n) . 7) - ((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 6) - ((#f #\-) . 5) - ((#t #\- #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\n) . 4)) - () - () - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 8)) - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 9)) - () - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 8)) - (((#f #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9) . 9))) - '#((#f . #f) (5 . 5) (5 . 5) (0 . 0) (4 . 4) (4 . 4) (2 . 2) - (1 . 1) (3 . 3) (2 . 2)))) - -; Module multilex.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; -; Gestion des Input Systems -; Fonctions a utiliser par l'usager: -; lexer-make-IS, lexer-get-func-getc, lexer-get-func-ungetc, -; lexer-get-func-line, lexer-get-func-column et lexer-get-func-offset -; - -; Taille initiale par defaut du buffer d'entree -(define lexer-init-buffer-len 1024) - -; Numero du caractere newline -(define lexer-integer-newline (char->integer #\newline)) - -; Constructeur d'IS brut -(define lexer-raw-IS-maker - (lambda (buffer read-ptr input-f counters) - (let ((input-f input-f) ; Entree reelle - (buffer buffer) ; Buffer - (buflen (string-length buffer)) - (read-ptr read-ptr) - (start-ptr 1) ; Marque de debut de lexeme - (start-line 1) - (start-column 1) - (start-offset 0) - (end-ptr 1) ; Marque de fin de lexeme - (point-ptr 1) ; Le point - (user-ptr 1) ; Marque de l'usager - (user-line 1) - (user-column 1) - (user-offset 0) - (user-up-to-date? #t)) ; Concerne la colonne seul. - (letrec - ((start-go-to-end-none ; Fonctions de depl. des marques - (lambda () - (set! start-ptr end-ptr))) - (start-go-to-end-line - (lambda () - (let loop ((ptr start-ptr) (line start-line)) - (if (= ptr end-ptr) - (begin - (set! start-ptr ptr) - (set! start-line line)) - (if (char=? (string-ref buffer ptr) #\newline) - (loop (+ ptr 1) (+ line 1)) - (loop (+ ptr 1) line)))))) - (start-go-to-end-all - (lambda () - (set! start-offset (+ start-offset (- end-ptr start-ptr))) - (let loop ((ptr start-ptr) - (line start-line) - (column start-column)) - (if (= ptr end-ptr) - (begin - (set! start-ptr ptr) - (set! start-line line) - (set! start-column column)) - (if (char=? (string-ref buffer ptr) #\newline) - (loop (+ ptr 1) (+ line 1) 1) - (loop (+ ptr 1) line (+ column 1))))))) - (start-go-to-user-none - (lambda () - (set! start-ptr user-ptr))) - (start-go-to-user-line - (lambda () - (set! start-ptr user-ptr) - (set! start-line user-line))) - (start-go-to-user-all - (lambda () - (set! start-line user-line) - (set! start-offset user-offset) - (if user-up-to-date? - (begin - (set! start-ptr user-ptr) - (set! start-column user-column)) - (let loop ((ptr start-ptr) (column start-column)) - (if (= ptr user-ptr) - (begin - (set! start-ptr ptr) - (set! start-column column)) - (if (char=? (string-ref buffer ptr) #\newline) - (loop (+ ptr 1) 1) - (loop (+ ptr 1) (+ column 1)))))))) - (end-go-to-point - (lambda () - (set! end-ptr point-ptr))) - (point-go-to-start - (lambda () - (set! point-ptr start-ptr))) - (user-go-to-start-none - (lambda () - (set! user-ptr start-ptr))) - (user-go-to-start-line - (lambda () - (set! user-ptr start-ptr) - (set! user-line start-line))) - (user-go-to-start-all - (lambda () - (set! user-ptr start-ptr) - (set! user-line start-line) - (set! user-column start-column) - (set! user-offset start-offset) - (set! user-up-to-date? #t))) - (init-lexeme-none ; Debute un nouveau lexeme - (lambda () - (if (< start-ptr user-ptr) - (start-go-to-user-none)) - (point-go-to-start))) - (init-lexeme-line - (lambda () - (if (< start-ptr user-ptr) - (start-go-to-user-line)) - (point-go-to-start))) - (init-lexeme-all - (lambda () - (if (< start-ptr user-ptr) - (start-go-to-user-all)) - (point-go-to-start))) - (get-start-line ; Obtention des stats du debut du lxm - (lambda () - start-line)) - (get-start-column - (lambda () - start-column)) - (get-start-offset - (lambda () - start-offset)) - (peek-left-context ; Obtention de caracteres (#f si EOF) - (lambda () - (char->integer (string-ref buffer (- start-ptr 1))))) - (peek-char - (lambda () - (if (< point-ptr read-ptr) - (char->integer (string-ref buffer point-ptr)) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer point-ptr c) - (set! read-ptr (+ point-ptr 1)) - (char->integer c)) - (begin - (set! input-f (lambda () 'eof)) - #f)))))) - (read-char - (lambda () - (if (< point-ptr read-ptr) - (let ((c (string-ref buffer point-ptr))) - (set! point-ptr (+ point-ptr 1)) - (char->integer c)) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer point-ptr c) - (set! read-ptr (+ point-ptr 1)) - (set! point-ptr read-ptr) - (char->integer c)) - (begin - (set! input-f (lambda () 'eof)) - #f)))))) - (get-start-end-text ; Obtention du lexeme - (lambda () - (substring buffer start-ptr end-ptr))) - (get-user-line-line ; Fonctions pour l'usager - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-line)) - user-line)) - (get-user-line-all - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-all)) - user-line)) - (get-user-column-all - (lambda () - (cond ((< user-ptr start-ptr) - (user-go-to-start-all) - user-column) - (user-up-to-date? - user-column) - (else - (let loop ((ptr start-ptr) (column start-column)) - (if (= ptr user-ptr) - (begin - (set! user-column column) - (set! user-up-to-date? #t) - column) - (if (char=? (string-ref buffer ptr) #\newline) - (loop (+ ptr 1) 1) - (loop (+ ptr 1) (+ column 1))))))))) - (get-user-offset-all - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-all)) - user-offset)) - (user-getc-none - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-none)) - (if (< user-ptr read-ptr) - (let ((c (string-ref buffer user-ptr))) - (set! user-ptr (+ user-ptr 1)) - c) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer user-ptr c) - (set! read-ptr (+ read-ptr 1)) - (set! user-ptr read-ptr) - c) - (begin - (set! input-f (lambda () 'eof)) - 'eof)))))) - (user-getc-line - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-line)) - (if (< user-ptr read-ptr) - (let ((c (string-ref buffer user-ptr))) - (set! user-ptr (+ user-ptr 1)) - (if (char=? c #\newline) - (set! user-line (+ user-line 1))) - c) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer user-ptr c) - (set! read-ptr (+ read-ptr 1)) - (set! user-ptr read-ptr) - (if (char=? c #\newline) - (set! user-line (+ user-line 1))) - c) - (begin - (set! input-f (lambda () 'eof)) - 'eof)))))) - (user-getc-all - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-all)) - (if (< user-ptr read-ptr) - (let ((c (string-ref buffer user-ptr))) - (set! user-ptr (+ user-ptr 1)) - (if (char=? c #\newline) - (begin - (set! user-line (+ user-line 1)) - (set! user-column 1)) - (set! user-column (+ user-column 1))) - (set! user-offset (+ user-offset 1)) - c) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer user-ptr c) - (set! read-ptr (+ read-ptr 1)) - (set! user-ptr read-ptr) - (if (char=? c #\newline) - (begin - (set! user-line (+ user-line 1)) - (set! user-column 1)) - (set! user-column (+ user-column 1))) - (set! user-offset (+ user-offset 1)) - c) - (begin - (set! input-f (lambda () 'eof)) - 'eof)))))) - (user-ungetc-none - (lambda () - (if (> user-ptr start-ptr) - (set! user-ptr (- user-ptr 1))))) - (user-ungetc-line - (lambda () - (if (> user-ptr start-ptr) - (begin - (set! user-ptr (- user-ptr 1)) - (let ((c (string-ref buffer user-ptr))) - (if (char=? c #\newline) - (set! user-line (- user-line 1)))))))) - (user-ungetc-all - (lambda () - (if (> user-ptr start-ptr) - (begin - (set! user-ptr (- user-ptr 1)) - (let ((c (string-ref buffer user-ptr))) - (if (char=? c #\newline) - (begin - (set! user-line (- user-line 1)) - (set! user-up-to-date? #f)) - (set! user-column (- user-column 1))) - (set! user-offset (- user-offset 1))))))) - (reorganize-buffer ; Decaler ou agrandir le buffer - (lambda () - (if (< (* 2 start-ptr) buflen) - (let* ((newlen (* 2 buflen)) - (newbuf (make-string newlen)) - (delta (- start-ptr 1))) - (let loop ((from (- start-ptr 1))) - (if (< from buflen) - (begin - (string-set! newbuf - (- from delta) - (string-ref buffer from)) - (loop (+ from 1))))) - (set! buffer newbuf) - (set! buflen newlen) - (set! read-ptr (- read-ptr delta)) - (set! start-ptr (- start-ptr delta)) - (set! end-ptr (- end-ptr delta)) - (set! point-ptr (- point-ptr delta)) - (set! user-ptr (- user-ptr delta))) - (let ((delta (- start-ptr 1))) - (let loop ((from (- start-ptr 1))) - (if (< from buflen) - (begin - (string-set! buffer - (- from delta) - (string-ref buffer from)) - (loop (+ from 1))))) - (set! read-ptr (- read-ptr delta)) - (set! start-ptr (- start-ptr delta)) - (set! end-ptr (- end-ptr delta)) - (set! point-ptr (- point-ptr delta)) - (set! user-ptr (- user-ptr delta))))))) - (list (cons 'start-go-to-end - (cond ((eq? counters 'none) start-go-to-end-none) - ((eq? counters 'line) start-go-to-end-line) - ((eq? counters 'all ) start-go-to-end-all))) - (cons 'end-go-to-point - end-go-to-point) - (cons 'init-lexeme - (cond ((eq? counters 'none) init-lexeme-none) - ((eq? counters 'line) init-lexeme-line) - ((eq? counters 'all ) init-lexeme-all))) - (cons 'get-start-line - get-start-line) - (cons 'get-start-column - get-start-column) - (cons 'get-start-offset - get-start-offset) - (cons 'peek-left-context - peek-left-context) - (cons 'peek-char - peek-char) - (cons 'read-char - read-char) - (cons 'get-start-end-text - get-start-end-text) - (cons 'get-user-line - (cond ((eq? counters 'none) #f) - ((eq? counters 'line) get-user-line-line) - ((eq? counters 'all ) get-user-line-all))) - (cons 'get-user-column - (cond ((eq? counters 'none) #f) - ((eq? counters 'line) #f) - ((eq? counters 'all ) get-user-column-all))) - (cons 'get-user-offset - (cond ((eq? counters 'none) #f) - ((eq? counters 'line) #f) - ((eq? counters 'all ) get-user-offset-all))) - (cons 'user-getc - (cond ((eq? counters 'none) user-getc-none) - ((eq? counters 'line) user-getc-line) - ((eq? counters 'all ) user-getc-all))) - (cons 'user-ungetc - (cond ((eq? counters 'none) user-ungetc-none) - ((eq? counters 'line) user-ungetc-line) - ((eq? counters 'all ) user-ungetc-all)))))))) - -; Construit un Input System -; Le premier parametre doit etre parmi "port", "procedure" ou "string" -; Prend un parametre facultatif qui doit etre parmi -; "none", "line" ou "all" -(define lexer-make-IS - (lambda (input-type input . largs) - (let ((counters-type (cond ((null? largs) - 'line) - ((memq (car largs) '(none line all)) - (car largs)) - (else - 'line)))) - (cond ((and (eq? input-type 'port) (input-port? input)) - (let* ((buffer (make-string lexer-init-buffer-len #\newline)) - (read-ptr 1) - (input-f (lambda () (read-char input)))) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))) - ((and (eq? input-type 'procedure) (procedure? input)) - (let* ((buffer (make-string lexer-init-buffer-len #\newline)) - (read-ptr 1) - (input-f input)) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))) - ((and (eq? input-type 'string) (string? input)) - (let* ((buffer (string-append (string #\newline) input)) - (read-ptr (string-length buffer)) - (input-f (lambda () 'eof))) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))) - (else - (let* ((buffer (string #\newline)) - (read-ptr 1) - (input-f (lambda () 'eof))) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))))))) - -; Les fonctions: -; lexer-get-func-getc, lexer-get-func-ungetc, -; lexer-get-func-line, lexer-get-func-column et lexer-get-func-offset -(define lexer-get-func-getc - (lambda (IS) (cdr (assq 'user-getc IS)))) -(define lexer-get-func-ungetc - (lambda (IS) (cdr (assq 'user-ungetc IS)))) -(define lexer-get-func-line - (lambda (IS) (cdr (assq 'get-user-line IS)))) -(define lexer-get-func-column - (lambda (IS) (cdr (assq 'get-user-column IS)))) -(define lexer-get-func-offset - (lambda (IS) (cdr (assq 'get-user-offset IS)))) - -; -; Gestion des lexers -; - -; Fabrication de lexer a partir d'arbres de decision -(define lexer-make-tree-lexer - (lambda (tables IS) - (letrec - (; Contenu de la table - (counters-type (vector-ref tables 0)) - (<<EOF>>-pre-action (vector-ref tables 1)) - (<<ERROR>>-pre-action (vector-ref tables 2)) - (rules-pre-actions (vector-ref tables 3)) - (table-nl-start (vector-ref tables 5)) - (table-no-nl-start (vector-ref tables 6)) - (trees-v (vector-ref tables 7)) - (acc-v (vector-ref tables 8)) - - ; Contenu du IS - (IS-start-go-to-end (cdr (assq 'start-go-to-end IS))) - (IS-end-go-to-point (cdr (assq 'end-go-to-point IS))) - (IS-init-lexeme (cdr (assq 'init-lexeme IS))) - (IS-get-start-line (cdr (assq 'get-start-line IS))) - (IS-get-start-column (cdr (assq 'get-start-column IS))) - (IS-get-start-offset (cdr (assq 'get-start-offset IS))) - (IS-peek-left-context (cdr (assq 'peek-left-context IS))) - (IS-peek-char (cdr (assq 'peek-char IS))) - (IS-read-char (cdr (assq 'read-char IS))) - (IS-get-start-end-text (cdr (assq 'get-start-end-text IS))) - (IS-get-user-line (cdr (assq 'get-user-line IS))) - (IS-get-user-column (cdr (assq 'get-user-column IS))) - (IS-get-user-offset (cdr (assq 'get-user-offset IS))) - (IS-user-getc (cdr (assq 'user-getc IS))) - (IS-user-ungetc (cdr (assq 'user-ungetc IS))) - - ; Resultats - (<<EOF>>-action #f) - (<<ERROR>>-action #f) - (rules-actions #f) - (states #f) - (final-lexer #f) - - ; Gestion des hooks - (hook-list '()) - (add-hook - (lambda (thunk) - (set! hook-list (cons thunk hook-list)))) - (apply-hooks - (lambda () - (let loop ((l hook-list)) - (if (pair? l) - (begin - ((car l)) - (loop (cdr l))))))) - - ; Preparation des actions - (set-action-statics - (lambda (pre-action) - (pre-action final-lexer IS-user-getc IS-user-ungetc))) - (prepare-special-action-none - (lambda (pre-action) - (let ((action #f)) - (let ((result - (lambda () - (action ""))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-special-action-line - (lambda (pre-action) - (let ((action #f)) - (let ((result - (lambda (yyline) - (action "" yyline))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-special-action-all - (lambda (pre-action) - (let ((action #f)) - (let ((result - (lambda (yyline yycolumn yyoffset) - (action "" yyline yycolumn yyoffset))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-special-action - (lambda (pre-action) - (cond ((eq? counters-type 'none) - (prepare-special-action-none pre-action)) - ((eq? counters-type 'line) - (prepare-special-action-line pre-action)) - ((eq? counters-type 'all) - (prepare-special-action-all pre-action))))) - (prepare-action-yytext-none - (lambda (pre-action) - (let ((get-start-end-text IS-get-start-end-text) - (start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda () - (let ((yytext (get-start-end-text))) - (start-go-to-end) - (action yytext)))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-yytext-line - (lambda (pre-action) - (let ((get-start-end-text IS-get-start-end-text) - (start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline) - (let ((yytext (get-start-end-text))) - (start-go-to-end) - (action yytext yyline)))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-yytext-all - (lambda (pre-action) - (let ((get-start-end-text IS-get-start-end-text) - (start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline yycolumn yyoffset) - (let ((yytext (get-start-end-text))) - (start-go-to-end) - (action yytext yyline yycolumn yyoffset)))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-yytext - (lambda (pre-action) - (cond ((eq? counters-type 'none) - (prepare-action-yytext-none pre-action)) - ((eq? counters-type 'line) - (prepare-action-yytext-line pre-action)) - ((eq? counters-type 'all) - (prepare-action-yytext-all pre-action))))) - (prepare-action-no-yytext-none - (lambda (pre-action) - (let ((start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda () - (start-go-to-end) - (action))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-no-yytext-line - (lambda (pre-action) - (let ((start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline) - (start-go-to-end) - (action yyline))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-no-yytext-all - (lambda (pre-action) - (let ((start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline yycolumn yyoffset) - (start-go-to-end) - (action yyline yycolumn yyoffset))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-no-yytext - (lambda (pre-action) - (cond ((eq? counters-type 'none) - (prepare-action-no-yytext-none pre-action)) - ((eq? counters-type 'line) - (prepare-action-no-yytext-line pre-action)) - ((eq? counters-type 'all) - (prepare-action-no-yytext-all pre-action))))) - - ; Fabrique les fonctions de dispatch - (prepare-dispatch-err - (lambda (leaf) - (lambda (c) - #f))) - (prepare-dispatch-number - (lambda (leaf) - (let ((state-function #f)) - (let ((result - (lambda (c) - state-function)) - (hook - (lambda () - (set! state-function (vector-ref states leaf))))) - (add-hook hook) - result)))) - (prepare-dispatch-leaf - (lambda (leaf) - (if (eq? leaf 'err) - (prepare-dispatch-err leaf) - (prepare-dispatch-number leaf)))) - (prepare-dispatch-< - (lambda (tree) - (let ((left-tree (list-ref tree 1)) - (right-tree (list-ref tree 2))) - (let ((bound (list-ref tree 0)) - (left-func (prepare-dispatch-tree left-tree)) - (right-func (prepare-dispatch-tree right-tree))) - (lambda (c) - (if (< c bound) - (left-func c) - (right-func c))))))) - (prepare-dispatch-= - (lambda (tree) - (let ((left-tree (list-ref tree 2)) - (right-tree (list-ref tree 3))) - (let ((bound (list-ref tree 1)) - (left-func (prepare-dispatch-tree left-tree)) - (right-func (prepare-dispatch-tree right-tree))) - (lambda (c) - (if (= c bound) - (left-func c) - (right-func c))))))) - (prepare-dispatch-tree - (lambda (tree) - (cond ((not (pair? tree)) - (prepare-dispatch-leaf tree)) - ((eq? (car tree) '=) - (prepare-dispatch-= tree)) - (else - (prepare-dispatch-< tree))))) - (prepare-dispatch - (lambda (tree) - (let ((dicho-func (prepare-dispatch-tree tree))) - (lambda (c) - (and c (dicho-func c)))))) - - ; Fabrique les fonctions de transition (read & go) et (abort) - (prepare-read-n-go - (lambda (tree) - (let ((dispatch-func (prepare-dispatch tree)) - (read-char IS-read-char)) - (lambda () - (dispatch-func (read-char)))))) - (prepare-abort - (lambda (tree) - (lambda () - #f))) - (prepare-transition - (lambda (tree) - (if (eq? tree 'err) - (prepare-abort tree) - (prepare-read-n-go tree)))) - - ; Fabrique les fonctions d'etats ([set-end] & trans) - (prepare-state-no-acc - (lambda (s r1 r2) - (let ((trans-func (prepare-transition (vector-ref trees-v s)))) - (lambda (action) - (let ((next-state (trans-func))) - (if next-state - (next-state action) - action)))))) - (prepare-state-yes-no - (lambda (s r1 r2) - (let ((peek-char IS-peek-char) - (end-go-to-point IS-end-go-to-point) - (new-action1 #f) - (trans-func (prepare-transition (vector-ref trees-v s)))) - (let ((result - (lambda (action) - (let* ((c (peek-char)) - (new-action - (if (or (not c) (= c lexer-integer-newline)) - (begin - (end-go-to-point) - new-action1) - action)) - (next-state (trans-func))) - (if next-state - (next-state new-action) - new-action)))) - (hook - (lambda () - (set! new-action1 (vector-ref rules-actions r1))))) - (add-hook hook) - result)))) - (prepare-state-diff-acc - (lambda (s r1 r2) - (let ((end-go-to-point IS-end-go-to-point) - (peek-char IS-peek-char) - (new-action1 #f) - (new-action2 #f) - (trans-func (prepare-transition (vector-ref trees-v s)))) - (let ((result - (lambda (action) - (end-go-to-point) - (let* ((c (peek-char)) - (new-action - (if (or (not c) (= c lexer-integer-newline)) - new-action1 - new-action2)) - (next-state (trans-func))) - (if next-state - (next-state new-action) - new-action)))) - (hook - (lambda () - (set! new-action1 (vector-ref rules-actions r1)) - (set! new-action2 (vector-ref rules-actions r2))))) - (add-hook hook) - result)))) - (prepare-state-same-acc - (lambda (s r1 r2) - (let ((end-go-to-point IS-end-go-to-point) - (trans-func (prepare-transition (vector-ref trees-v s))) - (new-action #f)) - (let ((result - (lambda (action) - (end-go-to-point) - (let ((next-state (trans-func))) - (if next-state - (next-state new-action) - new-action)))) - (hook - (lambda () - (set! new-action (vector-ref rules-actions r1))))) - (add-hook hook) - result)))) - (prepare-state - (lambda (s) - (let* ((acc (vector-ref acc-v s)) - (r1 (car acc)) - (r2 (cdr acc))) - (cond ((not r1) (prepare-state-no-acc s r1 r2)) - ((not r2) (prepare-state-yes-no s r1 r2)) - ((< r1 r2) (prepare-state-diff-acc s r1 r2)) - (else (prepare-state-same-acc s r1 r2)))))) - - ; Fabrique la fonction de lancement du lexage a l'etat de depart - (prepare-start-same - (lambda (s1 s2) - (let ((peek-char IS-peek-char) - (eof-action #f) - (start-state #f) - (error-action #f)) - (let ((result - (lambda () - (if (not (peek-char)) - eof-action - (start-state error-action)))) - (hook - (lambda () - (set! eof-action <<EOF>>-action) - (set! start-state (vector-ref states s1)) - (set! error-action <<ERROR>>-action)))) - (add-hook hook) - result)))) - (prepare-start-diff - (lambda (s1 s2) - (let ((peek-char IS-peek-char) - (eof-action #f) - (peek-left-context IS-peek-left-context) - (start-state1 #f) - (start-state2 #f) - (error-action #f)) - (let ((result - (lambda () - (cond ((not (peek-char)) - eof-action) - ((= (peek-left-context) lexer-integer-newline) - (start-state1 error-action)) - (else - (start-state2 error-action))))) - (hook - (lambda () - (set! eof-action <<EOF>>-action) - (set! start-state1 (vector-ref states s1)) - (set! start-state2 (vector-ref states s2)) - (set! error-action <<ERROR>>-action)))) - (add-hook hook) - result)))) - (prepare-start - (lambda () - (let ((s1 table-nl-start) - (s2 table-no-nl-start)) - (if (= s1 s2) - (prepare-start-same s1 s2) - (prepare-start-diff s1 s2))))) - - ; Fabrique la fonction principale - (prepare-lexer-none - (lambda () - (let ((init-lexeme IS-init-lexeme) - (start-func (prepare-start))) - (lambda () - (init-lexeme) - ((start-func)))))) - (prepare-lexer-line - (lambda () - (let ((init-lexeme IS-init-lexeme) - (get-start-line IS-get-start-line) - (start-func (prepare-start))) - (lambda () - (init-lexeme) - (let ((yyline (get-start-line))) - ((start-func) yyline)))))) - (prepare-lexer-all - (lambda () - (let ((init-lexeme IS-init-lexeme) - (get-start-line IS-get-start-line) - (get-start-column IS-get-start-column) - (get-start-offset IS-get-start-offset) - (start-func (prepare-start))) - (lambda () - (init-lexeme) - (let ((yyline (get-start-line)) - (yycolumn (get-start-column)) - (yyoffset (get-start-offset))) - ((start-func) yyline yycolumn yyoffset)))))) - (prepare-lexer - (lambda () - (cond ((eq? counters-type 'none) (prepare-lexer-none)) - ((eq? counters-type 'line) (prepare-lexer-line)) - ((eq? counters-type 'all) (prepare-lexer-all)))))) - - ; Calculer la valeur de <<EOF>>-action et de <<ERROR>>-action - (set! <<EOF>>-action (prepare-special-action <<EOF>>-pre-action)) - (set! <<ERROR>>-action (prepare-special-action <<ERROR>>-pre-action)) - - ; Calculer la valeur de rules-actions - (let* ((len (quotient (vector-length rules-pre-actions) 2)) - (v (make-vector len))) - (let loop ((r (- len 1))) - (if (< r 0) - (set! rules-actions v) - (let* ((yytext? (vector-ref rules-pre-actions (* 2 r))) - (pre-action (vector-ref rules-pre-actions (+ (* 2 r) 1))) - (action (if yytext? - (prepare-action-yytext pre-action) - (prepare-action-no-yytext pre-action)))) - (vector-set! v r action) - (loop (- r 1)))))) - - ; Calculer la valeur de states - (let* ((len (vector-length trees-v)) - (v (make-vector len))) - (let loop ((s (- len 1))) - (if (< s 0) - (set! states v) - (begin - (vector-set! v s (prepare-state s)) - (loop (- s 1)))))) - - ; Calculer la valeur de final-lexer - (set! final-lexer (prepare-lexer)) - - ; Executer les hooks - (apply-hooks) - - ; Resultat - final-lexer))) - -; Fabrication de lexer a partir de listes de caracteres taggees -(define lexer-make-char-lexer - (let* ((char->class - (lambda (c) - (let ((n (char->integer c))) - (list (cons n n))))) - (merge-sort - (lambda (l combine zero-elt) - (if (null? l) - zero-elt - (let loop1 ((l l)) - (if (null? (cdr l)) - (car l) - (loop1 - (let loop2 ((l l)) - (cond ((null? l) - l) - ((null? (cdr l)) - l) - (else - (cons (combine (car l) (cadr l)) - (loop2 (cddr l)))))))))))) - (finite-class-union - (lambda (c1 c2) - (let loop ((c1 c1) (c2 c2) (u '())) - (if (null? c1) - (if (null? c2) - (reverse u) - (loop c1 (cdr c2) (cons (car c2) u))) - (if (null? c2) - (loop (cdr c1) c2 (cons (car c1) u)) - (let* ((r1 (car c1)) - (r2 (car c2)) - (r1start (car r1)) - (r1end (cdr r1)) - (r2start (car r2)) - (r2end (cdr r2))) - (if (<= r1start r2start) - (cond ((< (+ r1end 1) r2start) - (loop (cdr c1) c2 (cons r1 u))) - ((<= r1end r2end) - (loop (cdr c1) - (cons (cons r1start r2end) (cdr c2)) - u)) - (else - (loop c1 (cdr c2) u))) - (cond ((> r1start (+ r2end 1)) - (loop c1 (cdr c2) (cons r2 u))) - ((>= r1end r2end) - (loop (cons (cons r2start r1end) (cdr c1)) - (cdr c2) - u)) - (else - (loop (cdr c1) c2 u)))))))))) - (char-list->class - (lambda (cl) - (let ((classes (map char->class cl))) - (merge-sort classes finite-class-union '())))) - (class-< - (lambda (b1 b2) - (cond ((eq? b1 'inf+) #f) - ((eq? b2 'inf-) #f) - ((eq? b1 'inf-) #t) - ((eq? b2 'inf+) #t) - (else (< b1 b2))))) - (finite-class-compl - (lambda (c) - (let loop ((c c) (start 'inf-)) - (if (null? c) - (list (cons start 'inf+)) - (let* ((r (car c)) - (rstart (car r)) - (rend (cdr r))) - (if (class-< start rstart) - (cons (cons start (- rstart 1)) - (loop c rstart)) - (loop (cdr c) (+ rend 1)))))))) - (tagged-chars->class - (lambda (tcl) - (let* ((inverse? (car tcl)) - (cl (cdr tcl)) - (class-tmp (char-list->class cl))) - (if inverse? (finite-class-compl class-tmp) class-tmp)))) - (charc->arc - (lambda (charc) - (let* ((tcl (car charc)) - (dest (cdr charc)) - (class (tagged-chars->class tcl))) - (cons class dest)))) - (arc->sharcs - (lambda (arc) - (let* ((range-l (car arc)) - (dest (cdr arc)) - (op (lambda (range) (cons range dest)))) - (map op range-l)))) - (class-<= - (lambda (b1 b2) - (cond ((eq? b1 'inf-) #t) - ((eq? b2 'inf+) #t) - ((eq? b1 'inf+) #f) - ((eq? b2 'inf-) #f) - (else (<= b1 b2))))) - (sharc-<= - (lambda (sharc1 sharc2) - (class-<= (caar sharc1) (caar sharc2)))) - (merge-sharcs - (lambda (l1 l2) - (let loop ((l1 l1) (l2 l2)) - (cond ((null? l1) - l2) - ((null? l2) - l1) - (else - (let ((sharc1 (car l1)) - (sharc2 (car l2))) - (if (sharc-<= sharc1 sharc2) - (cons sharc1 (loop (cdr l1) l2)) - (cons sharc2 (loop l1 (cdr l2)))))))))) - (class-= eqv?) - (fill-error - (lambda (sharcs) - (let loop ((sharcs sharcs) (start 'inf-)) - (cond ((class-= start 'inf+) - '()) - ((null? sharcs) - (cons (cons (cons start 'inf+) 'err) - (loop sharcs 'inf+))) - (else - (let* ((sharc (car sharcs)) - (h (caar sharc)) - (t (cdar sharc))) - (if (class-< start h) - (cons (cons (cons start (- h 1)) 'err) - (loop sharcs h)) - (cons sharc (loop (cdr sharcs) - (if (class-= t 'inf+) - 'inf+ - (+ t 1))))))))))) - (charcs->tree - (lambda (charcs) - (let* ((op (lambda (charc) (arc->sharcs (charc->arc charc)))) - (sharcs-l (map op charcs)) - (sorted-sharcs (merge-sort sharcs-l merge-sharcs '())) - (full-sharcs (fill-error sorted-sharcs)) - (op (lambda (sharc) (cons (caar sharc) (cdr sharc)))) - (table (list->vector (map op full-sharcs)))) - (let loop ((left 0) (right (- (vector-length table) 1))) - (if (= left right) - (cdr (vector-ref table left)) - (let ((mid (quotient (+ left right 1) 2))) - (if (and (= (+ left 2) right) - (= (+ (car (vector-ref table mid)) 1) - (car (vector-ref table right))) - (eqv? (cdr (vector-ref table left)) - (cdr (vector-ref table right)))) - (list '= - (car (vector-ref table mid)) - (cdr (vector-ref table mid)) - (cdr (vector-ref table left))) - (list (car (vector-ref table mid)) - (loop left (- mid 1)) - (loop mid right)))))))))) - (lambda (tables IS) - (let ((counters (vector-ref tables 0)) - (<<EOF>>-action (vector-ref tables 1)) - (<<ERROR>>-action (vector-ref tables 2)) - (rules-actions (vector-ref tables 3)) - (nl-start (vector-ref tables 5)) - (no-nl-start (vector-ref tables 6)) - (charcs-v (vector-ref tables 7)) - (acc-v (vector-ref tables 8))) - (let* ((len (vector-length charcs-v)) - (v (make-vector len))) - (let loop ((i (- len 1))) - (if (>= i 0) - (begin - (vector-set! v i (charcs->tree (vector-ref charcs-v i))) - (loop (- i 1))) - (lexer-make-tree-lexer - (vector counters - <<EOF>>-action - <<ERROR>>-action - rules-actions - 'decision-trees - nl-start - no-nl-start - v - acc-v) - IS)))))))) - -; Fabrication d'un lexer a partir de code pre-genere -(define lexer-make-code-lexer - (lambda (tables IS) - (let ((<<EOF>>-pre-action (vector-ref tables 1)) - (<<ERROR>>-pre-action (vector-ref tables 2)) - (rules-pre-action (vector-ref tables 3)) - (code (vector-ref tables 5))) - (code <<EOF>>-pre-action <<ERROR>>-pre-action rules-pre-action IS)))) - -(define lexer-make-lexer - (lambda (tables IS) - (let ((automaton-type (vector-ref tables 4))) - (cond ((eq? automaton-type 'decision-trees) - (lexer-make-tree-lexer tables IS)) - ((eq? automaton-type 'tagged-chars-lists) - (lexer-make-char-lexer tables IS)) - ((eq? automaton-type 'code) - (lexer-make-code-lexer tables IS)))))) - -; Module lexparser.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; -; Fonctions auxilliaires du lexer -; - -(define parse-spec-char - (lambda (lexeme line column) - (make-tok char-tok lexeme line column newline-ch))) - -(define parse-digits-char - (lambda (lexeme line column) - (let* ((num (substring lexeme 1 (string-length lexeme))) - (n (string->number num))) - (make-tok char-tok lexeme line column n)))) - -(define parse-quoted-char - (lambda (lexeme line column) - (let ((c (string-ref lexeme 1))) - (make-tok char-tok lexeme line column (char->integer c))))) - -(define parse-ordinary-char - (lambda (lexeme line column) - (let ((c (string-ref lexeme 0))) - (make-tok char-tok lexeme line column (char->integer c))))) - -(define extract-id - (lambda (s) - (let ((len (string-length s))) - (substring s 1 (- len 1))))) - -(define parse-id - (lambda (lexeme line column) - (make-tok id-tok lexeme line column (string-downcase lexeme) lexeme))) - -(define parse-id-ref - (lambda (lexeme line column) - (let* ((orig-name (extract-id lexeme)) - (name (string-downcase orig-name))) - (make-tok subst-tok lexeme line column name orig-name)))) - -(define parse-power-m - (lambda (lexeme line column) - (let* ((len (string-length lexeme)) - (substr (substring lexeme 1 (- len 1))) - (m (string->number substr)) - (range (cons m m))) - (make-tok power-tok lexeme line column range)))) - -(define parse-power-m-inf - (lambda (lexeme line column) - (let* ((len (string-length lexeme)) - (substr (substring lexeme 1 (- len 2))) - (m (string->number substr)) - (range (cons m 'inf))) - (make-tok power-tok lexeme line column range)))) - -(define parse-power-m-n - (lambda (lexeme line column) - (let ((len (string-length lexeme))) - (let loop ((comma 2)) - (if (char=? (string-ref lexeme comma) #\,) - (let* ((sub1 (substring lexeme 1 comma)) - (sub2 (substring lexeme (+ comma 1) (- len 1))) - (m (string->number sub1)) - (n (string->number sub2)) - (range (cons m n))) - (make-tok power-tok lexeme line column range)) - (loop (+ comma 1))))))) - - - - -; -; Lexer generique -; - -(define lexer-raw #f) -(define lexer-stack '()) - -(define lexer-alist #f) - -(define lexer-buffer #f) -(define lexer-buffer-empty? #t) - -(define lexer-history '()) -(define lexer-history-interp #f) - -(define init-lexer - (lambda (port) - (let* ((IS (lexer-make-IS 'port port 'all)) - (action-lexer (lexer-make-lexer action-tables IS)) - (class-lexer (lexer-make-lexer class-tables IS)) - (macro-lexer (lexer-make-lexer macro-tables IS)) - (regexp-lexer (lexer-make-lexer regexp-tables IS)) - (string-lexer (lexer-make-lexer string-tables IS))) - (set! lexer-raw #f) - (set! lexer-stack '()) - (set! lexer-alist - (list (cons 'action action-lexer) - (cons 'class class-lexer) - (cons 'macro macro-lexer) - (cons 'regexp regexp-lexer) - (cons 'string string-lexer))) - (set! lexer-buffer-empty? #t) - (set! lexer-history '())))) - -; Lexer brut -; S'assurer qu'il n'y a pas de risque de changer de -; lexer quand le buffer est rempli -(define push-lexer - (lambda (name) - (set! lexer-stack (cons lexer-raw lexer-stack)) - (set! lexer-raw (cdr (assq name lexer-alist))))) - -(define pop-lexer - (lambda () - (set! lexer-raw (car lexer-stack)) - (set! lexer-stack (cdr lexer-stack)))) - -; Traite le "unget" (capacite du unget: 1) -(define lexer2 - (lambda () - (if lexer-buffer-empty? - (lexer-raw) - (begin - (set! lexer-buffer-empty? #t) - lexer-buffer)))) - -(define lexer2-unget - (lambda (tok) - (set! lexer-buffer tok) - (set! lexer-buffer-empty? #f))) - -; Traite l'historique -(define lexer - (lambda () - (let* ((tok (lexer2)) - (tok-lexeme (get-tok-lexeme tok)) - (hist-lexeme (if lexer-history-interp - (blank-translate tok-lexeme) - tok-lexeme))) - (set! lexer-history (cons hist-lexeme lexer-history)) - tok))) - -(define lexer-unget - (lambda (tok) - (set! lexer-history (cdr lexer-history)) - (lexer2-unget tok))) - -(define lexer-set-blank-history - (lambda (b) - (set! lexer-history-interp b))) - -(define blank-translate - (lambda (s) - (let ((ss (string-copy s))) - (let loop ((i (- (string-length ss) 1))) - (cond ((< i 0) - ss) - ((char=? (string-ref ss i) (integer->char tab-ch)) - (loop (- i 1))) - ((char=? (string-ref ss i) #\newline) - (loop (- i 1))) - (else - (string-set! ss i #\space) - (loop (- i 1)))))))) - -(define lexer-get-history - (lambda () - (let* ((rightlist (reverse lexer-history)) - (str (string-append-list rightlist)) - (strlen (string-length str)) - (str2 (if (and (> strlen 0) - (char=? (string-ref str (- strlen 1)) #\newline)) - str - (string-append str (string #\newline))))) - (set! lexer-history '()) - str2))) - - - - -; -; Traitement des listes de tokens -; - -(define de-anchor-tokens - (let ((not-anchor-toks (make-dispatch-table number-of-tokens - (list (cons caret-tok #f) - (cons dollar-tok #f) - (cons <<EOF>>-tok #f) - (cons <<ERROR>>-tok #f)) - #t))) - (lambda (tok-list) - (if (null? tok-list) - '() - (let* ((tok (car tok-list)) - (tok-type (get-tok-type tok)) - (toks (cdr tok-list)) - (new-toks (de-anchor-tokens toks))) - (cond ((vector-ref not-anchor-toks tok-type) - (cons tok new-toks)) - ((or (= tok-type caret-tok) (= tok-type dollar-tok)) - (let* ((line (get-tok-line tok)) - (column (get-tok-column tok)) - (attr (if (= tok-type caret-tok) caret-ch dollar-ch)) - (new-tok (make-tok char-tok "" line column attr))) - (cons new-tok new-toks))) - ((= tok-type <<EOF>>-tok) - (lex-error (get-tok-line tok) - (get-tok-column tok) - "the <<EOF>> anchor must be used alone" - " and only after %%.")) - ((= tok-type <<ERROR>>-tok) - (lex-error (get-tok-line tok) - (get-tok-column tok) - "the <<ERROR>> anchor must be used alone" - " and only after %%.")))))))) - -(define strip-end - (lambda (l) - (if (null? (cdr l)) - '() - (cons (car l) (strip-end (cdr l)))))) - -(define extract-anchors - (lambda (tok-list) - (let* ((tok1 (car tok-list)) - (line (get-tok-line tok1)) - (tok1-type (get-tok-type tok1))) - (cond ((and (= tok1-type <<EOF>>-tok) (null? (cdr tok-list))) - (make-rule line #t #f #f #f '() #f)) - ((and (= tok1-type <<ERROR>>-tok) (null? (cdr tok-list))) - (make-rule line #f #t #f #f '() #f)) - (else - (let* ((bol? (= tok1-type caret-tok)) - (tok-list2 (if bol? (cdr tok-list) tok-list))) - (if (null? tok-list2) - (make-rule line #f #f bol? #f tok-list2 #f) - (let* ((len (length tok-list2)) - (tok2 (list-ref tok-list2 (- len 1))) - (tok2-type (get-tok-type tok2)) - (eol? (= tok2-type dollar-tok)) - (tok-list3 (if eol? - (strip-end tok-list2) - tok-list2))) - (make-rule line #f #f bol? eol? tok-list3 #f))))))))) - -(define char-list->conc - (lambda (char-list) - (if (null? char-list) - (make-re epsilon-re) - (let loop ((cl char-list)) - (let* ((c (car cl)) - (cl2 (cdr cl))) - (if (null? cl2) - (make-re char-re c) - (make-re conc-re (make-re char-re c) (loop cl2)))))))) - -(define parse-tokens-atom - (let ((action-table - (make-dispatch-table - number-of-tokens - (list (cons lpar-tok - (lambda (tok tok-list macros) - (parse-tokens-sub tok-list macros))) - (cons dot-tok - (lambda (tok tok-list macros) - (cons (make-re class-re dot-class) (cdr tok-list)))) - (cons subst-tok - (lambda (tok tok-list macros) - (let* ((name (get-tok-attr tok)) - (ass (assoc name macros))) - (if ass - (cons (cdr ass) (cdr tok-list)) - (lex-error (get-tok-line tok) - (get-tok-column tok) - "unknown macro \"" - (get-tok-2nd-attr tok) - "\"."))))) - (cons char-tok - (lambda (tok tok-list macros) - (let ((c (get-tok-attr tok))) - (cons (make-re char-re c) (cdr tok-list))))) - (cons class-tok - (lambda (tok tok-list macros) - (let ((class (get-tok-attr tok))) - (cons (make-re class-re class) (cdr tok-list))))) - (cons string-tok - (lambda (tok tok-list macros) - (let* ((char-list (get-tok-attr tok)) - (re (char-list->conc char-list))) - (cons re (cdr tok-list)))))) - (lambda (tok tok-list macros) - (lex-error (get-tok-line tok) - (get-tok-column tok) - "syntax error in regular expression."))))) - (lambda (tok-list macros) - (let* ((tok (car tok-list)) - (tok-type (get-tok-type tok)) - (action (vector-ref action-table tok-type))) - (action tok tok-list macros))))) - -(define check-power-tok - (lambda (tok) - (let* ((range (get-tok-attr tok)) - (start (car range)) - (end (cdr range))) - (if (or (eq? 'inf end) (<= start end)) - range - (lex-error (get-tok-line tok) - (get-tok-column tok) - "incorrect power specification."))))) - -(define power->star-plus - (lambda (re range) - (power->star-plus-rec re (car range) (cdr range)))) - -(define power->star-plus-rec - (lambda (re start end) - (cond ((eq? end 'inf) - (cond ((= start 0) - (make-re star-re re)) - ((= start 1) - (make-re plus-re re)) - (else - (make-re conc-re - re - (power->star-plus-rec re (- start 1) 'inf))))) - ((= start 0) - (cond ((= end 0) - (make-re epsilon-re)) - ((= end 1) - (make-re question-re re)) - (else - (make-re question-re - (power->star-plus-rec re 1 end))))) - ((= start 1) - (if (= end 1) - re - (make-re conc-re re (power->star-plus-rec re 0 (- end 1))))) - (else - (make-re conc-re - re - (power->star-plus-rec re (- start 1) (- end 1))))))) - -(define parse-tokens-fact - (let ((not-op-toks (make-dispatch-table number-of-tokens - (list (cons question-tok #f) - (cons plus-tok #f) - (cons star-tok #f) - (cons power-tok #f)) - #t))) - (lambda (tok-list macros) - (let* ((result (parse-tokens-atom tok-list macros)) - (re (car result)) - (tok-list2 (cdr result))) - (let loop ((re re) (tok-list3 tok-list2)) - (let* ((tok (car tok-list3)) - (tok-type (get-tok-type tok))) - (cond ((vector-ref not-op-toks tok-type) - (cons re tok-list3)) - ((= tok-type question-tok) - (loop (make-re question-re re) (cdr tok-list3))) - ((= tok-type plus-tok) - (loop (make-re plus-re re) (cdr tok-list3))) - ((= tok-type star-tok) - (loop (make-re star-re re) (cdr tok-list3))) - ((= tok-type power-tok) - (loop (power->star-plus re (check-power-tok tok)) - (cdr tok-list3)))))))))) - -(define parse-tokens-conc - (lambda (tok-list macros) - (let* ((result1 (parse-tokens-fact tok-list macros)) - (re1 (car result1)) - (tok-list2 (cdr result1)) - (tok (car tok-list2)) - (tok-type (get-tok-type tok))) - (cond ((or (= tok-type pipe-tok) - (= tok-type rpar-tok)) - result1) - (else ; Autres facteurs - (let* ((result2 (parse-tokens-conc tok-list2 macros)) - (re2 (car result2)) - (tok-list3 (cdr result2))) - (cons (make-re conc-re re1 re2) tok-list3))))))) - -(define parse-tokens-or - (lambda (tok-list macros) - (let* ((result1 (parse-tokens-conc tok-list macros)) - (re1 (car result1)) - (tok-list2 (cdr result1)) - (tok (car tok-list2)) - (tok-type (get-tok-type tok))) - (cond ((= tok-type pipe-tok) - (let* ((tok-list3 (cdr tok-list2)) - (result2 (parse-tokens-or tok-list3 macros)) - (re2 (car result2)) - (tok-list4 (cdr result2))) - (cons (make-re or-re re1 re2) tok-list4))) - (else ; rpar-tok - result1))))) - -(define parse-tokens-sub - (lambda (tok-list macros) - (let* ((tok-list2 (cdr tok-list)) ; Manger le lpar-tok - (result (parse-tokens-or tok-list2 macros)) - (re (car result)) - (tok-list3 (cdr result)) - (tok-list4 (cdr tok-list3))) ; Manger le rpar-tok - (cons re tok-list4)))) - -(define parse-tokens-match - (lambda (tok-list line) - (let loop ((tl tok-list) (count 0)) - (if (null? tl) - (if (> count 0) - (lex-error line - #f - "mismatched parentheses.")) - (let* ((tok (car tl)) - (tok-type (get-tok-type tok))) - (cond ((= tok-type lpar-tok) - (loop (cdr tl) (+ count 1))) - ((= tok-type rpar-tok) - (if (zero? count) - (lex-error line - #f - "mismatched parentheses.")) - (loop (cdr tl) (- count 1))) - (else - (loop (cdr tl) count)))))))) - -; Ne traite pas les anchors -(define parse-tokens - (lambda (tok-list macros) - (if (null? tok-list) - (make-re epsilon-re) - (let ((line (get-tok-line (car tok-list)))) - (parse-tokens-match tok-list line) - (let* ((begin-par (make-tok lpar-tok "" line 1)) - (end-par (make-tok rpar-tok "" line 1))) - (let* ((tok-list2 (append (list begin-par) - tok-list - (list end-par))) - (result (parse-tokens-sub tok-list2 macros))) - (car result))))))) ; (cdr result) == () obligatoirement - -(define tokens->regexp - (lambda (tok-list macros) - (let ((tok-list2 (de-anchor-tokens tok-list))) - (parse-tokens tok-list2 macros)))) - -(define tokens->rule - (lambda (tok-list macros) - (let* ((rule (extract-anchors tok-list)) - (tok-list2 (get-rule-regexp rule)) - (tok-list3 (de-anchor-tokens tok-list2)) - (re (parse-tokens tok-list3 macros))) - (set-rule-regexp rule re) - rule))) - -; Retourne une paire: <<EOF>>-action et vecteur des regles ordinaires -(define adapt-rules - (lambda (rules) - (let loop ((r rules) (revr '()) (<<EOF>>-action #f) (<<ERROR>>-action #f)) - (if (null? r) - (cons (or <<EOF>>-action default-<<EOF>>-action) - (cons (or <<ERROR>>-action default-<<ERROR>>-action) - (list->vector (reverse revr)))) - (let ((r1 (car r))) - (cond ((get-rule-eof? r1) - (if <<EOF>>-action - (lex-error (get-rule-line r1) - #f - "the <<EOF>> anchor can be " - "used at most once.") - (loop (cdr r) - revr - (get-rule-action r1) - <<ERROR>>-action))) - ((get-rule-error? r1) - (if <<ERROR>>-action - (lex-error (get-rule-line r1) - #f - "the <<ERROR>> anchor can be " - "used at most once.") - (loop (cdr r) - revr - <<EOF>>-action - (get-rule-action r1)))) - (else - (loop (cdr r) - (cons r1 revr) - <<EOF>>-action - <<ERROR>>-action)))))))) - - - - -; -; Analyseur de fichier lex -; - -(define parse-hv-blanks - (lambda () - (let* ((tok (lexer)) - (tok-type (get-tok-type tok))) - (if (or (= tok-type hblank-tok) - (= tok-type vblank-tok)) - (parse-hv-blanks) - (lexer-unget tok))))) - -(define parse-class-range - (lambda () - (let* ((tok (lexer)) - (tok-type (get-tok-type tok))) - (cond ((= tok-type char-tok) - (let* ((c (get-tok-attr tok)) - (tok2 (lexer)) - (tok2-type (get-tok-type tok2))) - (if (not (= tok2-type minus-tok)) - (begin - (lexer-unget tok2) - (cons c c)) - (let* ((tok3 (lexer)) - (tok3-type (get-tok-type tok3))) - (cond ((= tok3-type char-tok) - (let ((c2 (get-tok-attr tok3))) - (if (> c c2) - (lex-error (get-tok-line tok3) - (get-tok-column tok3) - "bad range specification in " - "character class;" - #\newline - "the start character is " - "higher than the end one.") - (cons c c2)))) - ((or (= tok3-type rbrack-tok) - (= tok3-type minus-tok)) - (lex-error (get-tok-line tok3) - (get-tok-column tok3) - "bad range specification in " - "character class; a specification" - #\newline - "like \"-x\", \"x--\" or \"x-]\" has " - "been used.")) - ((= tok3-type eof-tok) - (lex-error (get-tok-line tok3) - #f - "eof of file found while parsing " - "a character class."))))))) - ((= tok-type minus-tok) - (lex-error (get-tok-line tok) - (get-tok-column tok) - "bad range specification in character class; a " - "specification" - #\newline - "like \"-x\", \"x--\" or \"x-]\" has been used.")) - ((= tok-type rbrack-tok) - #f) - ((= tok-type eof-tok) - (lex-error (get-tok-line tok) - #f - "eof of file found while parsing " - "a character class.")))))) - -(define parse-class - (lambda (initial-class negative-class? line column) - (push-lexer 'class) - (let loop ((class initial-class)) - (let ((new-range (parse-class-range))) - (if new-range - (loop (class-union (list new-range) class)) - (let ((class (if negative-class? - (class-compl class) - class))) - (pop-lexer) - (make-tok class-tok "" line column class))))))) - -(define parse-string - (lambda (line column) - (push-lexer 'string) - (let ((char-list (let loop () - (let* ((tok (lexer)) - (tok-type (get-tok-type tok))) - (cond ((= tok-type char-tok) - (cons (get-tok-attr tok) (loop))) - ((= tok-type doublequote-tok) - (pop-lexer) - '()) - (else ; eof-tok - (lex-error (get-tok-line tok) - #f - "end of file found while " - "parsing a string."))))))) - (make-tok string-tok "" line column char-list)))) - -(define parse-regexp - (let* ((end-action - (lambda (tok loop) - (lexer-unget tok) - (pop-lexer) - (lexer-set-blank-history #f) - `())) - (action-table - (make-dispatch-table - number-of-tokens - (list (cons eof-tok end-action) - (cons hblank-tok end-action) - (cons vblank-tok end-action) - (cons lbrack-tok - (lambda (tok loop) - (let ((tok1 (parse-class (list) - #f - (get-tok-line tok) - (get-tok-column tok)))) - (cons tok1 (loop))))) - (cons lbrack-rbrack-tok - (lambda (tok loop) - (let ((tok1 (parse-class - (list (cons rbrack-ch rbrack-ch)) - #f - (get-tok-line tok) - (get-tok-column tok)))) - (cons tok1 (loop))))) - (cons lbrack-caret-tok - (lambda (tok loop) - (let ((tok1 (parse-class (list) - #t - (get-tok-line tok) - (get-tok-column tok)))) - (cons tok1 (loop))))) - (cons lbrack-minus-tok - (lambda (tok loop) - (let ((tok1 (parse-class - (list (cons minus-ch minus-ch)) - #f - (get-tok-line tok) - (get-tok-column tok)))) - (cons tok1 (loop))))) - (cons doublequote-tok - (lambda (tok loop) - (let ((tok1 (parse-string (get-tok-line tok) - (get-tok-column tok)))) - (cons tok1 (loop))))) - (cons illegal-tok - (lambda (tok loop) - (lex-error (get-tok-line tok) - (get-tok-column tok) - "syntax error in macro reference.")))) - (lambda (tok loop) - (cons tok (loop)))))) - (lambda () - (push-lexer 'regexp) - (lexer-set-blank-history #t) - (parse-hv-blanks) - (let loop () - (let* ((tok (lexer)) - (tok-type (get-tok-type tok)) - (action (vector-ref action-table tok-type))) - (action tok loop)))))) - -(define parse-ws1-regexp ; Exige un blanc entre le nom et la RE d'une macro - (lambda () - (let* ((tok (lexer)) - (tok-type (get-tok-type tok))) - (cond ((or (= tok-type hblank-tok) (= tok-type vblank-tok)) - (parse-regexp)) - (else ; percent-percent-tok, id-tok ou illegal-tok - (lex-error (get-tok-line tok) - (get-tok-column tok) - "white space expected.")))))) - -(define parse-macro - (lambda (macros) - (push-lexer 'macro) - (parse-hv-blanks) - (let* ((tok (lexer)) - (tok-type (get-tok-type tok))) - (cond ((= tok-type id-tok) - (let* ((name (get-tok-attr tok)) - (ass (assoc name macros))) - (if ass - (lex-error (get-tok-line tok) - (get-tok-column tok) - "the macro \"" - (get-tok-2nd-attr tok) - "\" has already been defined.") - (let* ((tok-list (parse-ws1-regexp)) - (regexp (tokens->regexp tok-list macros))) - (pop-lexer) - (cons name regexp))))) - ((= tok-type percent-percent-tok) - (pop-lexer) - #f) - ((= tok-type illegal-tok) - (lex-error (get-tok-line tok) - (get-tok-column tok) - "macro name expected.")) - ((= tok-type eof-tok) - (lex-error (get-tok-line tok) - #f - "end of file found before %%.")))))) - -(define parse-macros - (lambda () - (let loop ((macros '())) - (let ((macro (parse-macro macros))) - (if macro - (loop (cons macro macros)) - macros))))) - -(define parse-action-end - (lambda (<<EOF>>-action? <<ERROR>>-action? action?) - (let ((act (lexer-get-history))) - (cond (action? - act) - (<<EOF>>-action? - (string-append act default-<<EOF>>-action)) - (<<ERROR>>-action? - (string-append act default-<<ERROR>>-action)) - (else - (string-append act default-action)))))) - -(define parse-action - (lambda (<<EOF>>-action? <<ERROR>>-action?) - (push-lexer 'action) - (let loop ((action? #f)) - (let* ((tok (lexer)) - (tok-type (get-tok-type tok))) - (cond ((= tok-type char-tok) - (loop #t)) - ((= tok-type hblank-tok) - (loop action?)) - ((= tok-type vblank-tok) - (push-lexer 'regexp) - (let* ((tok (lexer)) - (tok-type (get-tok-type tok)) - (bidon (lexer-unget tok))) - (pop-lexer) - (if (or (= tok-type hblank-tok) - (= tok-type vblank-tok)) - (loop action?) - (begin - (pop-lexer) - (parse-action-end <<EOF>>-action? - <<ERROR>>-action? - action?))))) - (else ; eof-tok - (lexer-unget tok) - (pop-lexer) - (parse-action-end <<EOF>>-action? - <<ERROR>>-action? - action?))))))) - -(define parse-rule - (lambda (macros) - (let ((tok-list (parse-regexp))) - (if (null? tok-list) - #f - (let* ((rule (tokens->rule tok-list macros)) - (action - (parse-action (get-rule-eof? rule) (get-rule-error? rule)))) - (set-rule-action rule action) - rule))))) - -(define parse-rules - (lambda (macros) - (parse-action #f #f) - (let loop () - (let ((rule (parse-rule macros))) - (if rule - (cons rule (loop)) - '()))))) - -(define parser - (lambda (filename) - (let* ((port (open-input-file filename)) - (port-open? #t)) - (lex-unwind-protect (lambda () - (if port-open? - (close-input-port port)))) - (init-lexer port) - (let* ((macros (parse-macros)) - (rules (parse-rules macros))) - (close-input-port port) - (set! port-open? #f) - (adapt-rules rules))))) - -; Module re2nfa.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; Le vecteur d'etats contient la table de transition du nfa. -; Chaque entree contient les arcs partant de l'etat correspondant. -; Les arcs sont stockes dans une liste. -; Chaque arc est une paire (class . destination). -; Les caracteres d'une classe sont enumeres par ranges. -; Les ranges sont donnes dans une liste, -; chaque element etant une paire (debut . fin). -; Le symbole eps peut remplacer une classe. -; L'acceptation est decrite par une paire (acc-if-eol . acc-if-no-eol). - -; Quelques variables globales -(define r2n-counter 0) -(define r2n-v-arcs '#(#f)) -(define r2n-v-acc '#(#f)) -(define r2n-v-len 1) - -; Initialisation des variables globales -(define r2n-init - (lambda () - (set! r2n-counter 0) - (set! r2n-v-arcs (vector '())) - (set! r2n-v-acc (vector #f)) - (set! r2n-v-len 1))) - -; Agrandissement des vecteurs -(define r2n-extend-v - (lambda () - (let* ((new-len (* 2 r2n-v-len)) - (new-v-arcs (make-vector new-len '())) - (new-v-acc (make-vector new-len #f))) - (let loop ((i 0)) - (if (< i r2n-v-len) - (begin - (vector-set! new-v-arcs i (vector-ref r2n-v-arcs i)) - (vector-set! new-v-acc i (vector-ref r2n-v-acc i)) - (loop (+ i 1))))) - (set! r2n-v-arcs new-v-arcs) - (set! r2n-v-acc new-v-acc) - (set! r2n-v-len new-len)))) - -; Finalisation des vecteurs -(define r2n-finalize-v - (lambda () - (let* ((new-v-arcs (make-vector r2n-counter)) - (new-v-acc (make-vector r2n-counter))) - (let loop ((i 0)) - (if (< i r2n-counter) - (begin - (vector-set! new-v-arcs i (vector-ref r2n-v-arcs i)) - (vector-set! new-v-acc i (vector-ref r2n-v-acc i)) - (loop (+ i 1))))) - (set! r2n-v-arcs new-v-arcs) - (set! r2n-v-acc new-v-acc) - (set! r2n-v-len r2n-counter)))) - -; Creation d'etat -(define r2n-get-state - (lambda (acc) - (if (= r2n-counter r2n-v-len) - (r2n-extend-v)) - (let ((state r2n-counter)) - (set! r2n-counter (+ r2n-counter 1)) - (vector-set! r2n-v-acc state (or acc (cons #f #f))) - state))) - -; Ajout d'un arc -(define r2n-add-arc - (lambda (start chars end) - (vector-set! r2n-v-arcs - start - (cons (cons chars end) (vector-ref r2n-v-arcs start))))) - -; Construction de l'automate a partir des regexp -(define r2n-build-epsilon - (lambda (re start end) - (r2n-add-arc start 'eps end))) - -(define r2n-build-or - (lambda (re start end) - (let ((re1 (get-re-attr1 re)) - (re2 (get-re-attr2 re))) - (r2n-build-re re1 start end) - (r2n-build-re re2 start end)))) - -(define r2n-build-conc - (lambda (re start end) - (let* ((re1 (get-re-attr1 re)) - (re2 (get-re-attr2 re)) - (inter (r2n-get-state #f))) - (r2n-build-re re1 start inter) - (r2n-build-re re2 inter end)))) - -(define r2n-build-star - (lambda (re start end) - (let* ((re1 (get-re-attr1 re)) - (inter1 (r2n-get-state #f)) - (inter2 (r2n-get-state #f))) - (r2n-add-arc start 'eps inter1) - (r2n-add-arc inter1 'eps inter2) - (r2n-add-arc inter2 'eps end) - (r2n-build-re re1 inter2 inter1)))) - -(define r2n-build-plus - (lambda (re start end) - (let* ((re1 (get-re-attr1 re)) - (inter1 (r2n-get-state #f)) - (inter2 (r2n-get-state #f))) - (r2n-add-arc start 'eps inter1) - (r2n-add-arc inter2 'eps inter1) - (r2n-add-arc inter2 'eps end) - (r2n-build-re re1 inter1 inter2)))) - -(define r2n-build-question - (lambda (re start end) - (let ((re1 (get-re-attr1 re))) - (r2n-add-arc start 'eps end) - (r2n-build-re re1 start end)))) - -(define r2n-build-class - (lambda (re start end) - (let ((class (get-re-attr1 re))) - (r2n-add-arc start class end)))) - -(define r2n-build-char - (lambda (re start end) - (let* ((c (get-re-attr1 re)) - (class (list (cons c c)))) - (r2n-add-arc start class end)))) - -(define r2n-build-re - (let ((sub-function-v (vector r2n-build-epsilon - r2n-build-or - r2n-build-conc - r2n-build-star - r2n-build-plus - r2n-build-question - r2n-build-class - r2n-build-char))) - (lambda (re start end) - (let* ((re-type (get-re-type re)) - (sub-f (vector-ref sub-function-v re-type))) - (sub-f re start end))))) - -; Construction de l'automate relatif a une regle -(define r2n-build-rule - (lambda (rule ruleno nl-start no-nl-start) - (let* ((re (get-rule-regexp rule)) - (bol? (get-rule-bol? rule)) - (eol? (get-rule-eol? rule)) - (rule-start (r2n-get-state #f)) - (rule-end (r2n-get-state (if eol? - (cons ruleno #f) - (cons ruleno ruleno))))) - (r2n-build-re re rule-start rule-end) - (r2n-add-arc nl-start 'eps rule-start) - (if (not bol?) - (r2n-add-arc no-nl-start 'eps rule-start))))) - -; Construction de l'automate complet -(define re2nfa - (lambda (rules) - (let ((nb-of-rules (vector-length rules))) - (r2n-init) - (let* ((nl-start (r2n-get-state #f)) - (no-nl-start (r2n-get-state #f))) - (let loop ((i 0)) - (if (< i nb-of-rules) - (begin - (r2n-build-rule (vector-ref rules i) - i - nl-start - no-nl-start) - (loop (+ i 1))))) - (r2n-finalize-v) - (let ((v-arcs r2n-v-arcs) - (v-acc r2n-v-acc)) - (r2n-init) - (list nl-start no-nl-start v-arcs v-acc)))))) - -; Module noeps.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; Fonction "merge" qui elimine les repetitions -(define noeps-merge-1 - (lambda (l1 l2) - (cond ((null? l1) - l2) - ((null? l2) - l1) - (else - (let ((t1 (car l1)) - (t2 (car l2))) - (cond ((< t1 t2) - (cons t1 (noeps-merge-1 (cdr l1) l2))) - ((= t1 t2) - (cons t1 (noeps-merge-1 (cdr l1) (cdr l2)))) - (else - (cons t2 (noeps-merge-1 l1 (cdr l2)))))))))) - -; Fabrication des voisinages externes -(define noeps-mkvois - (lambda (trans-v) - (let* ((nbnodes (vector-length trans-v)) - (arcs (make-vector nbnodes '()))) - (let loop1 ((n 0)) - (if (< n nbnodes) - (begin - (let loop2 ((trans (vector-ref trans-v n)) (ends '())) - (if (null? trans) - (vector-set! arcs n ends) - (let* ((tran (car trans)) - (class (car tran)) - (end (cdr tran))) - (loop2 (cdr trans) (if (eq? class 'eps) - (noeps-merge-1 ends (list end)) - ends))))) - (loop1 (+ n 1))))) - arcs))) - -; Fabrication des valeurs initiales -(define noeps-mkinit - (lambda (trans-v) - (let* ((nbnodes (vector-length trans-v)) - (init (make-vector nbnodes))) - (let loop ((n 0)) - (if (< n nbnodes) - (begin - (vector-set! init n (list n)) - (loop (+ n 1))))) - init))) - -; Traduction d'une liste d'arcs -(define noeps-trad-arcs - (lambda (trans dict) - (let loop ((trans trans)) - (if (null? trans) - '() - (let* ((tran (car trans)) - (class (car tran)) - (end (cdr tran))) - (if (eq? class 'eps) - (loop (cdr trans)) - (let* ((new-end (vector-ref dict end)) - (new-tran (cons class new-end))) - (cons new-tran (loop (cdr trans)))))))))) - -; Elimination des transitions eps -(define noeps - (lambda (nl-start no-nl-start arcs acc) - (let* ((digraph-arcs (noeps-mkvois arcs)) - (digraph-init (noeps-mkinit arcs)) - (dict (digraph digraph-arcs digraph-init noeps-merge-1)) - (new-nl-start (vector-ref dict nl-start)) - (new-no-nl-start (vector-ref dict no-nl-start))) - (let loop ((i (- (vector-length arcs) 1))) - (if (>= i 0) - (begin - (vector-set! arcs i (noeps-trad-arcs (vector-ref arcs i) dict)) - (loop (- i 1))))) - (list new-nl-start new-no-nl-start arcs acc)))) - -; Module sweep.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; Preparer les arcs pour digraph -(define sweep-mkarcs - (lambda (trans-v) - (let* ((nbnodes (vector-length trans-v)) - (arcs-v (make-vector nbnodes '()))) - (let loop1 ((n 0)) - (if (< n nbnodes) - (let loop2 ((trans (vector-ref trans-v n)) (arcs '())) - (if (null? trans) - (begin - (vector-set! arcs-v n arcs) - (loop1 (+ n 1))) - (loop2 (cdr trans) (noeps-merge-1 (cdar trans) arcs)))) - arcs-v))))) - -; Preparer l'operateur pour digraph -(define sweep-op - (let ((acc-min (lambda (rule1 rule2) - (cond ((not rule1) - rule2) - ((not rule2) - rule1) - (else - (min rule1 rule2)))))) - (lambda (acc1 acc2) - (cons (acc-min (car acc1) (car acc2)) - (acc-min (cdr acc1) (cdr acc2)))))) - -; Renumerotation des etats (#f pour etat a eliminer) -; Retourne (new-nbnodes . dict) -(define sweep-renum - (lambda (dist-acc-v) - (let* ((nbnodes (vector-length dist-acc-v)) - (dict (make-vector nbnodes))) - (let loop ((n 0) (new-n 0)) - (if (< n nbnodes) - (let* ((acc (vector-ref dist-acc-v n)) - (dead? (equal? acc '(#f . #f)))) - (if dead? - (begin - (vector-set! dict n #f) - (loop (+ n 1) new-n)) - (begin - (vector-set! dict n new-n) - (loop (+ n 1) (+ new-n 1))))) - (cons new-n dict)))))) - -; Elimination des etats inutiles d'une liste d'etats -(define sweep-list - (lambda (ss dict) - (if (null? ss) - '() - (let* ((olds (car ss)) - (news (vector-ref dict olds))) - (if news - (cons news (sweep-list (cdr ss) dict)) - (sweep-list (cdr ss) dict)))))) - -; Elimination des etats inutiles d'une liste d'arcs -(define sweep-arcs - (lambda (arcs dict) - (if (null? arcs) - '() - (let* ((arc (car arcs)) - (class (car arc)) - (ss (cdr arc)) - (new-ss (sweep-list ss dict))) - (if (null? new-ss) - (sweep-arcs (cdr arcs) dict) - (cons (cons class new-ss) (sweep-arcs (cdr arcs) dict))))))) - -; Elimination des etats inutiles dans toutes les transitions -(define sweep-all-arcs - (lambda (arcs-v dict) - (let loop ((n (- (vector-length arcs-v) 1))) - (if (>= n 0) - (begin - (vector-set! arcs-v n (sweep-arcs (vector-ref arcs-v n) dict)) - (loop (- n 1))) - arcs-v)))) - -; Elimination des etats inutiles dans un vecteur -(define sweep-states - (lambda (v new-nbnodes dict) - (let ((nbnodes (vector-length v)) - (new-v (make-vector new-nbnodes))) - (let loop ((n 0)) - (if (< n nbnodes) - (let ((new-n (vector-ref dict n))) - (if new-n - (vector-set! new-v new-n (vector-ref v n))) - (loop (+ n 1))) - new-v))))) - -; Elimination des etats inutiles -(define sweep - (lambda (nl-start no-nl-start arcs-v acc-v) - (let* ((digraph-arcs (sweep-mkarcs arcs-v)) - (digraph-init acc-v) - (digraph-op sweep-op) - (dist-acc-v (digraph digraph-arcs digraph-init digraph-op)) - (result (sweep-renum dist-acc-v)) - (new-nbnodes (car result)) - (dict (cdr result)) - (new-nl-start (sweep-list nl-start dict)) - (new-no-nl-start (sweep-list no-nl-start dict)) - (new-arcs-v (sweep-states (sweep-all-arcs arcs-v dict) - new-nbnodes - dict)) - (new-acc-v (sweep-states acc-v new-nbnodes dict))) - (list new-nl-start new-no-nl-start new-arcs-v new-acc-v)))) - -; Module nfa2dfa.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; Recoupement de deux arcs -(define n2d-2arcs - (lambda (arc1 arc2) - (let* ((class1 (car arc1)) - (ss1 (cdr arc1)) - (class2 (car arc2)) - (ss2 (cdr arc2)) - (result (class-sep class1 class2)) - (classl (vector-ref result 0)) - (classc (vector-ref result 1)) - (classr (vector-ref result 2)) - (ssl ss1) - (ssc (ss-union ss1 ss2)) - (ssr ss2)) - (vector (if (or (null? classl) (null? ssl)) #f (cons classl ssl)) - (if (or (null? classc) (null? ssc)) #f (cons classc ssc)) - (if (or (null? classr) (null? ssr)) #f (cons classr ssr)))))) - -; Insertion d'un arc dans une liste d'arcs a classes distinctes -(define n2d-insert-arc - (lambda (new-arc arcs) - (if (null? arcs) - (list new-arc) - (let* ((arc (car arcs)) - (others (cdr arcs)) - (result (n2d-2arcs new-arc arc)) - (arcl (vector-ref result 0)) - (arcc (vector-ref result 1)) - (arcr (vector-ref result 2)) - (list-arcc (if arcc (list arcc) '())) - (list-arcr (if arcr (list arcr) '()))) - (if arcl - (append list-arcc list-arcr (n2d-insert-arc arcl others)) - (append list-arcc list-arcr others)))))) - -; Regroupement des arcs qui aboutissent au meme sous-ensemble d'etats -(define n2d-factorize-arcs - (lambda (arcs) - (if (null? arcs) - '() - (let* ((arc (car arcs)) - (arc-ss (cdr arc)) - (others-no-fact (cdr arcs)) - (others (n2d-factorize-arcs others-no-fact))) - (let loop ((o others)) - (if (null? o) - (list arc) - (let* ((o1 (car o)) - (o1-ss (cdr o1))) - (if (equal? o1-ss arc-ss) - (let* ((arc-class (car arc)) - (o1-class (car o1)) - (new-class (class-union arc-class o1-class)) - (new-arc (cons new-class arc-ss))) - (cons new-arc (cdr o))) - (cons o1 (loop (cdr o))))))))))) - -; Transformer une liste d'arcs quelconques en des arcs a classes distinctes -(define n2d-distinguish-arcs - (lambda (arcs) - (let loop ((arcs arcs) (n-arcs '())) - (if (null? arcs) - n-arcs - (loop (cdr arcs) (n2d-insert-arc (car arcs) n-arcs)))))) - -; Transformer une liste d'arcs quelconques en des arcs a classes et a -; destinations distinctes -(define n2d-normalize-arcs - (lambda (arcs) - (n2d-factorize-arcs (n2d-distinguish-arcs arcs)))) - -; Factoriser des arcs a destination unique (~deterministes) -(define n2d-factorize-darcs - (lambda (arcs) - (if (null? arcs) - '() - (let* ((arc (car arcs)) - (arc-end (cdr arc)) - (other-arcs (cdr arcs)) - (farcs (n2d-factorize-darcs other-arcs))) - (let loop ((farcs farcs)) - (if (null? farcs) - (list arc) - (let* ((farc (car farcs)) - (farc-end (cdr farc))) - (if (= farc-end arc-end) - (let* ((arc-class (car arc)) - (farc-class (car farc)) - (new-class (class-union farc-class arc-class)) - (new-arc (cons new-class arc-end))) - (cons new-arc (cdr farcs))) - (cons farc (loop (cdr farcs))))))))))) - -; Normaliser un vecteur de listes d'arcs -(define n2d-normalize-arcs-v - (lambda (arcs-v) - (let* ((nbnodes (vector-length arcs-v)) - (new-v (make-vector nbnodes))) - (let loop ((n 0)) - (if (= n nbnodes) - new-v - (begin - (vector-set! new-v n (n2d-normalize-arcs (vector-ref arcs-v n))) - (loop (+ n 1)))))))) - -; Inserer un arc dans une liste d'arcs a classes distinctes en separant -; les arcs contenant une partie de la classe du nouvel arc des autres arcs -; Retourne: (oui . non) -(define n2d-ins-sep-arc - (lambda (new-arc arcs) - (if (null? arcs) - (cons (list new-arc) '()) - (let* ((arc (car arcs)) - (others (cdr arcs)) - (result (n2d-2arcs new-arc arc)) - (arcl (vector-ref result 0)) - (arcc (vector-ref result 1)) - (arcr (vector-ref result 2)) - (l-arcc (if arcc (list arcc) '())) - (l-arcr (if arcr (list arcr) '())) - (result (if arcl - (n2d-ins-sep-arc arcl others) - (cons '() others))) - (oui-arcs (car result)) - (non-arcs (cdr result))) - (cons (append l-arcc oui-arcs) (append l-arcr non-arcs)))))) - -; Combiner deux listes d'arcs a classes distinctes -; Ne tente pas de combiner les arcs qui ont nec. des classes disjointes -; Conjecture: les arcs crees ont leurs classes disjointes -; Note: envisager de rajouter un "n2d-factorize-arcs" !!!!!!!!!!!! -(define n2d-combine-arcs - (lambda (arcs1 arcs2) - (let loop ((arcs1 arcs1) (arcs2 arcs2) (dist-arcs2 '())) - (if (null? arcs1) - (append arcs2 dist-arcs2) - (let* ((arc (car arcs1)) - (result (n2d-ins-sep-arc arc arcs2)) - (oui-arcs (car result)) - (non-arcs (cdr result))) - (loop (cdr arcs1) non-arcs (append oui-arcs dist-arcs2))))))) - -; ; -; ; Section temporaire: vieille facon de generer le dfa -; ; Dictionnaire d'etat det. Recherche lineaire. Creation naive -; ; des arcs d'un ensemble d'etats. -; ; -; -; ; Quelques variables globales -; (define n2d-state-dict '#(#f)) -; (define n2d-state-len 1) -; (define n2d-state-count 0) -; -; ; Fonctions de gestion des entrees du dictionnaire -; (define make-dentry (lambda (ss) (vector ss #f #f))) -; -; (define get-dentry-ss (lambda (dentry) (vector-ref dentry 0))) -; (define get-dentry-darcs (lambda (dentry) (vector-ref dentry 1))) -; (define get-dentry-acc (lambda (dentry) (vector-ref dentry 2))) -; -; (define set-dentry-darcs (lambda (dentry arcs) (vector-set! dentry 1 arcs))) -; (define set-dentry-acc (lambda (dentry acc) (vector-set! dentry 2 acc))) -; -; ; Initialisation des variables globales -; (define n2d-init-glob-vars -; (lambda () -; (set! n2d-state-dict (vector #f)) -; (set! n2d-state-len 1) -; (set! n2d-state-count 0))) -; -; ; Extension du dictionnaire -; (define n2d-extend-dict -; (lambda () -; (let* ((new-len (* 2 n2d-state-len)) -; (v (make-vector new-len #f))) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (begin -; (set! n2d-state-dict v) -; (set! n2d-state-len new-len)) -; (begin -; (vector-set! v n (vector-ref n2d-state-dict n)) -; (loop (+ n 1)))))))) -; -; ; Ajout d'un etat -; (define n2d-add-state -; (lambda (ss) -; (let* ((s n2d-state-count) -; (dentry (make-dentry ss))) -; (if (= n2d-state-count n2d-state-len) -; (n2d-extend-dict)) -; (vector-set! n2d-state-dict s dentry) -; (set! n2d-state-count (+ n2d-state-count 1)) -; s))) -; -; ; Recherche d'un etat -; (define n2d-search-state -; (lambda (ss) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (n2d-add-state ss) -; (let* ((dentry (vector-ref n2d-state-dict n)) -; (dentry-ss (get-dentry-ss dentry))) -; (if (equal? dentry-ss ss) -; n -; (loop (+ n 1)))))))) -; -; ; Transformer un arc non-det. en un arc det. -; (define n2d-translate-arc -; (lambda (arc) -; (let* ((class (car arc)) -; (ss (cdr arc)) -; (s (n2d-search-state ss))) -; (cons class s)))) -; -; ; Transformer une liste d'arcs non-det. en ... -; (define n2d-translate-arcs -; (lambda (arcs) -; (map n2d-translate-arc arcs))) -; -; ; Trouver le minimum de deux acceptants -; (define n2d-acc-min2 -; (let ((acc-min (lambda (rule1 rule2) -; (cond ((not rule1) -; rule2) -; ((not rule2) -; rule1) -; (else -; (min rule1 rule2)))))) -; (lambda (acc1 acc2) -; (cons (acc-min (car acc1) (car acc2)) -; (acc-min (cdr acc1) (cdr acc2)))))) -; -; ; Trouver le minimum de plusieurs acceptants -; (define n2d-acc-mins -; (lambda (accs) -; (if (null? accs) -; (cons #f #f) -; (n2d-acc-min2 (car accs) (n2d-acc-mins (cdr accs)))))) -; -; ; Fabriquer les vecteurs d'arcs et d'acceptance -; (define n2d-extract-vs -; (lambda () -; (let* ((arcs-v (make-vector n2d-state-count)) -; (acc-v (make-vector n2d-state-count))) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (cons arcs-v acc-v) -; (begin -; (vector-set! arcs-v n (get-dentry-darcs -; (vector-ref n2d-state-dict n))) -; (vector-set! acc-v n (get-dentry-acc -; (vector-ref n2d-state-dict n))) -; (loop (+ n 1)))))))) -; -; ; Effectuer la transformation de l'automate de non-det. a det. -; (define nfa2dfa -; (lambda (nl-start no-nl-start arcs-v acc-v) -; (n2d-init-glob-vars) -; (let* ((nl-d (n2d-search-state nl-start)) -; (no-nl-d (n2d-search-state no-nl-start))) -; (let loop ((n 0)) -; (if (< n n2d-state-count) -; (let* ((dentry (vector-ref n2d-state-dict n)) -; (ss (get-dentry-ss dentry)) -; (arcss (map (lambda (s) (vector-ref arcs-v s)) ss)) -; (arcs (apply append arcss)) -; (dist-arcs (n2d-distinguish-arcs arcs)) -; (darcs (n2d-translate-arcs dist-arcs)) -; (fact-darcs (n2d-factorize-darcs darcs)) -; (accs (map (lambda (s) (vector-ref acc-v s)) ss)) -; (acc (n2d-acc-mins accs))) -; (set-dentry-darcs dentry fact-darcs) -; (set-dentry-acc dentry acc) -; (loop (+ n 1))))) -; (let* ((result (n2d-extract-vs)) -; (new-arcs-v (car result)) -; (new-acc-v (cdr result))) -; (n2d-init-glob-vars) -; (list nl-d no-nl-d new-arcs-v new-acc-v))))) - -; ; -; ; Section temporaire: vieille facon de generer le dfa -; ; Dictionnaire d'etat det. Recherche lineaire. Creation des -; ; arcs d'un ensemble d'etats en combinant des ensembles d'arcs a -; ; classes distinctes. -; ; -; -; ; Quelques variables globales -; (define n2d-state-dict '#(#f)) -; (define n2d-state-len 1) -; (define n2d-state-count 0) -; -; ; Fonctions de gestion des entrees du dictionnaire -; (define make-dentry (lambda (ss) (vector ss #f #f))) -; -; (define get-dentry-ss (lambda (dentry) (vector-ref dentry 0))) -; (define get-dentry-darcs (lambda (dentry) (vector-ref dentry 1))) -; (define get-dentry-acc (lambda (dentry) (vector-ref dentry 2))) -; -; (define set-dentry-darcs (lambda (dentry arcs) (vector-set! dentry 1 arcs))) -; (define set-dentry-acc (lambda (dentry acc) (vector-set! dentry 2 acc))) -; -; ; Initialisation des variables globales -; (define n2d-init-glob-vars -; (lambda () -; (set! n2d-state-dict (vector #f)) -; (set! n2d-state-len 1) -; (set! n2d-state-count 0))) -; -; ; Extension du dictionnaire -; (define n2d-extend-dict -; (lambda () -; (let* ((new-len (* 2 n2d-state-len)) -; (v (make-vector new-len #f))) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (begin -; (set! n2d-state-dict v) -; (set! n2d-state-len new-len)) -; (begin -; (vector-set! v n (vector-ref n2d-state-dict n)) -; (loop (+ n 1)))))))) -; -; ; Ajout d'un etat -; (define n2d-add-state -; (lambda (ss) -; (let* ((s n2d-state-count) -; (dentry (make-dentry ss))) -; (if (= n2d-state-count n2d-state-len) -; (n2d-extend-dict)) -; (vector-set! n2d-state-dict s dentry) -; (set! n2d-state-count (+ n2d-state-count 1)) -; s))) -; -; ; Recherche d'un etat -; (define n2d-search-state -; (lambda (ss) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (n2d-add-state ss) -; (let* ((dentry (vector-ref n2d-state-dict n)) -; (dentry-ss (get-dentry-ss dentry))) -; (if (equal? dentry-ss ss) -; n -; (loop (+ n 1)))))))) -; -; ; Combiner des listes d'arcs a classes dictinctes -; (define n2d-combine-arcs-l -; (lambda (arcs-l) -; (if (null? arcs-l) -; '() -; (let* ((arcs (car arcs-l)) -; (other-arcs-l (cdr arcs-l)) -; (other-arcs (n2d-combine-arcs-l other-arcs-l))) -; (n2d-combine-arcs arcs other-arcs))))) -; -; ; Transformer un arc non-det. en un arc det. -; (define n2d-translate-arc -; (lambda (arc) -; (let* ((class (car arc)) -; (ss (cdr arc)) -; (s (n2d-search-state ss))) -; (cons class s)))) -; -; ; Transformer une liste d'arcs non-det. en ... -; (define n2d-translate-arcs -; (lambda (arcs) -; (map n2d-translate-arc arcs))) -; -; ; Trouver le minimum de deux acceptants -; (define n2d-acc-min2 -; (let ((acc-min (lambda (rule1 rule2) -; (cond ((not rule1) -; rule2) -; ((not rule2) -; rule1) -; (else -; (min rule1 rule2)))))) -; (lambda (acc1 acc2) -; (cons (acc-min (car acc1) (car acc2)) -; (acc-min (cdr acc1) (cdr acc2)))))) -; -; ; Trouver le minimum de plusieurs acceptants -; (define n2d-acc-mins -; (lambda (accs) -; (if (null? accs) -; (cons #f #f) -; (n2d-acc-min2 (car accs) (n2d-acc-mins (cdr accs)))))) -; -; ; Fabriquer les vecteurs d'arcs et d'acceptance -; (define n2d-extract-vs -; (lambda () -; (let* ((arcs-v (make-vector n2d-state-count)) -; (acc-v (make-vector n2d-state-count))) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (cons arcs-v acc-v) -; (begin -; (vector-set! arcs-v n (get-dentry-darcs -; (vector-ref n2d-state-dict n))) -; (vector-set! acc-v n (get-dentry-acc -; (vector-ref n2d-state-dict n))) -; (loop (+ n 1)))))))) -; -; ; Effectuer la transformation de l'automate de non-det. a det. -; (define nfa2dfa -; (lambda (nl-start no-nl-start arcs-v acc-v) -; (n2d-init-glob-vars) -; (let* ((nl-d (n2d-search-state nl-start)) -; (no-nl-d (n2d-search-state no-nl-start)) -; (norm-arcs-v (n2d-normalize-arcs-v arcs-v))) -; (let loop ((n 0)) -; (if (< n n2d-state-count) -; (let* ((dentry (vector-ref n2d-state-dict n)) -; (ss (get-dentry-ss dentry)) -; (arcs-l (map (lambda (s) (vector-ref norm-arcs-v s)) ss)) -; (arcs (n2d-combine-arcs-l arcs-l)) -; (darcs (n2d-translate-arcs arcs)) -; (fact-darcs (n2d-factorize-darcs darcs)) -; (accs (map (lambda (s) (vector-ref acc-v s)) ss)) -; (acc (n2d-acc-mins accs))) -; (set-dentry-darcs dentry fact-darcs) -; (set-dentry-acc dentry acc) -; (loop (+ n 1))))) -; (let* ((result (n2d-extract-vs)) -; (new-arcs-v (car result)) -; (new-acc-v (cdr result))) -; (n2d-init-glob-vars) -; (list nl-d no-nl-d new-arcs-v new-acc-v))))) - -; ; -; ; Section temporaire: vieille facon de generer le dfa -; ; Dictionnaire d'etat det. Arbre de recherche. Creation des -; ; arcs d'un ensemble d'etats en combinant des ensembles d'arcs a -; ; classes distinctes. -; ; -; -; ; Quelques variables globales -; (define n2d-state-dict '#(#f)) -; (define n2d-state-len 1) -; (define n2d-state-count 0) -; (define n2d-state-tree '#(#f ())) -; -; ; Fonctions de gestion des entrees du dictionnaire -; (define make-dentry (lambda (ss) (vector ss #f #f))) -; -; (define get-dentry-ss (lambda (dentry) (vector-ref dentry 0))) -; (define get-dentry-darcs (lambda (dentry) (vector-ref dentry 1))) -; (define get-dentry-acc (lambda (dentry) (vector-ref dentry 2))) -; -; (define set-dentry-darcs (lambda (dentry arcs) (vector-set! dentry 1 arcs))) -; (define set-dentry-acc (lambda (dentry acc) (vector-set! dentry 2 acc))) -; -; ; Fonctions de gestion de l'arbre de recherche -; (define make-snode (lambda () (vector #f '()))) -; -; (define get-snode-dstate (lambda (snode) (vector-ref snode 0))) -; (define get-snode-children (lambda (snode) (vector-ref snode 1))) -; -; (define set-snode-dstate -; (lambda (snode dstate) (vector-set! snode 0 dstate))) -; (define set-snode-children -; (lambda (snode children) (vector-set! snode 1 children))) -; -; ; Initialisation des variables globales -; (define n2d-init-glob-vars -; (lambda () -; (set! n2d-state-dict (vector #f)) -; (set! n2d-state-len 1) -; (set! n2d-state-count 0) -; (set! n2d-state-tree (make-snode)))) -; -; ; Extension du dictionnaire -; (define n2d-extend-dict -; (lambda () -; (let* ((new-len (* 2 n2d-state-len)) -; (v (make-vector new-len #f))) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (begin -; (set! n2d-state-dict v) -; (set! n2d-state-len new-len)) -; (begin -; (vector-set! v n (vector-ref n2d-state-dict n)) -; (loop (+ n 1)))))))) -; -; ; Ajout d'un etat -; (define n2d-add-state -; (lambda (ss) -; (let* ((s n2d-state-count) -; (dentry (make-dentry ss))) -; (if (= n2d-state-count n2d-state-len) -; (n2d-extend-dict)) -; (vector-set! n2d-state-dict s dentry) -; (set! n2d-state-count (+ n2d-state-count 1)) -; s))) -; -; ; Recherche d'un etat -; (define n2d-search-state -; (lambda (ss) -; (let loop ((s-l ss) (snode n2d-state-tree)) -; (if (null? s-l) -; (or (get-snode-dstate snode) -; (let ((s (n2d-add-state ss))) -; (set-snode-dstate snode s) -; s)) -; (let* ((next-s (car s-l)) -; (alist (get-snode-children snode)) -; (ass (or (assv next-s alist) -; (let ((ass (cons next-s (make-snode)))) -; (set-snode-children snode (cons ass alist)) -; ass)))) -; (loop (cdr s-l) (cdr ass))))))) -; -; ; Combiner des listes d'arcs a classes dictinctes -; (define n2d-combine-arcs-l -; (lambda (arcs-l) -; (if (null? arcs-l) -; '() -; (let* ((arcs (car arcs-l)) -; (other-arcs-l (cdr arcs-l)) -; (other-arcs (n2d-combine-arcs-l other-arcs-l))) -; (n2d-combine-arcs arcs other-arcs))))) -; -; ; Transformer un arc non-det. en un arc det. -; (define n2d-translate-arc -; (lambda (arc) -; (let* ((class (car arc)) -; (ss (cdr arc)) -; (s (n2d-search-state ss))) -; (cons class s)))) -; -; ; Transformer une liste d'arcs non-det. en ... -; (define n2d-translate-arcs -; (lambda (arcs) -; (map n2d-translate-arc arcs))) -; -; ; Trouver le minimum de deux acceptants -; (define n2d-acc-min2 -; (let ((acc-min (lambda (rule1 rule2) -; (cond ((not rule1) -; rule2) -; ((not rule2) -; rule1) -; (else -; (min rule1 rule2)))))) -; (lambda (acc1 acc2) -; (cons (acc-min (car acc1) (car acc2)) -; (acc-min (cdr acc1) (cdr acc2)))))) -; -; ; Trouver le minimum de plusieurs acceptants -; (define n2d-acc-mins -; (lambda (accs) -; (if (null? accs) -; (cons #f #f) -; (n2d-acc-min2 (car accs) (n2d-acc-mins (cdr accs)))))) -; -; ; Fabriquer les vecteurs d'arcs et d'acceptance -; (define n2d-extract-vs -; (lambda () -; (let* ((arcs-v (make-vector n2d-state-count)) -; (acc-v (make-vector n2d-state-count))) -; (let loop ((n 0)) -; (if (= n n2d-state-count) -; (cons arcs-v acc-v) -; (begin -; (vector-set! arcs-v n (get-dentry-darcs -; (vector-ref n2d-state-dict n))) -; (vector-set! acc-v n (get-dentry-acc -; (vector-ref n2d-state-dict n))) -; (loop (+ n 1)))))))) -; -; ; Effectuer la transformation de l'automate de non-det. a det. -; (define nfa2dfa -; (lambda (nl-start no-nl-start arcs-v acc-v) -; (n2d-init-glob-vars) -; (let* ((nl-d (n2d-search-state nl-start)) -; (no-nl-d (n2d-search-state no-nl-start)) -; (norm-arcs-v (n2d-normalize-arcs-v arcs-v))) -; (let loop ((n 0)) -; (if (< n n2d-state-count) -; (let* ((dentry (vector-ref n2d-state-dict n)) -; (ss (get-dentry-ss dentry)) -; (arcs-l (map (lambda (s) (vector-ref norm-arcs-v s)) ss)) -; (arcs (n2d-combine-arcs-l arcs-l)) -; (darcs (n2d-translate-arcs arcs)) -; (fact-darcs (n2d-factorize-darcs darcs)) -; (accs (map (lambda (s) (vector-ref acc-v s)) ss)) -; (acc (n2d-acc-mins accs))) -; (set-dentry-darcs dentry fact-darcs) -; (set-dentry-acc dentry acc) -; (loop (+ n 1))))) -; (let* ((result (n2d-extract-vs)) -; (new-arcs-v (car result)) -; (new-acc-v (cdr result))) -; (n2d-init-glob-vars) -; (list nl-d no-nl-d new-arcs-v new-acc-v))))) - -; -; Section temporaire: vieille facon de generer le dfa -; Dictionnaire d'etat det. Table de hashage. Creation des -; arcs d'un ensemble d'etats en combinant des ensembles d'arcs a -; classes distinctes. -; - -; Quelques variables globales -(define n2d-state-dict '#(#f)) -(define n2d-state-len 1) -(define n2d-state-count 0) -(define n2d-state-hash '#()) - -; Fonctions de gestion des entrees du dictionnaire -(define make-dentry (lambda (ss) (vector ss #f #f))) - -(define get-dentry-ss (lambda (dentry) (vector-ref dentry 0))) -(define get-dentry-darcs (lambda (dentry) (vector-ref dentry 1))) -(define get-dentry-acc (lambda (dentry) (vector-ref dentry 2))) - -(define set-dentry-darcs (lambda (dentry arcs) (vector-set! dentry 1 arcs))) -(define set-dentry-acc (lambda (dentry acc) (vector-set! dentry 2 acc))) - -; Initialisation des variables globales -(define n2d-init-glob-vars - (lambda (hash-len) - (set! n2d-state-dict (vector #f)) - (set! n2d-state-len 1) - (set! n2d-state-count 0) - (set! n2d-state-hash (make-vector hash-len '())))) - -; Extension du dictionnaire -(define n2d-extend-dict - (lambda () - (let* ((new-len (* 2 n2d-state-len)) - (v (make-vector new-len #f))) - (let loop ((n 0)) - (if (= n n2d-state-count) - (begin - (set! n2d-state-dict v) - (set! n2d-state-len new-len)) - (begin - (vector-set! v n (vector-ref n2d-state-dict n)) - (loop (+ n 1)))))))) - -; Ajout d'un etat -(define n2d-add-state - (lambda (ss) - (let* ((s n2d-state-count) - (dentry (make-dentry ss))) - (if (= n2d-state-count n2d-state-len) - (n2d-extend-dict)) - (vector-set! n2d-state-dict s dentry) - (set! n2d-state-count (+ n2d-state-count 1)) - s))) - -; Recherche d'un etat -(define n2d-search-state - (lambda (ss) - (let* ((hash-no (if (null? ss) 0 (car ss))) - (alist (vector-ref n2d-state-hash hash-no)) - (ass (assoc ss alist))) - (if ass - (cdr ass) - (let* ((s (n2d-add-state ss)) - (new-ass (cons ss s))) - (vector-set! n2d-state-hash hash-no (cons new-ass alist)) - s))))) - -; Combiner des listes d'arcs a classes dictinctes -(define n2d-combine-arcs-l - (lambda (arcs-l) - (if (null? arcs-l) - '() - (let* ((arcs (car arcs-l)) - (other-arcs-l (cdr arcs-l)) - (other-arcs (n2d-combine-arcs-l other-arcs-l))) - (n2d-combine-arcs arcs other-arcs))))) - -; Transformer un arc non-det. en un arc det. -(define n2d-translate-arc - (lambda (arc) - (let* ((class (car arc)) - (ss (cdr arc)) - (s (n2d-search-state ss))) - (cons class s)))) - -; Transformer une liste d'arcs non-det. en ... -(define n2d-translate-arcs - (lambda (arcs) - (map n2d-translate-arc arcs))) - -; Trouver le minimum de deux acceptants -(define n2d-acc-min2 - (let ((acc-min (lambda (rule1 rule2) - (cond ((not rule1) - rule2) - ((not rule2) - rule1) - (else - (min rule1 rule2)))))) - (lambda (acc1 acc2) - (cons (acc-min (car acc1) (car acc2)) - (acc-min (cdr acc1) (cdr acc2)))))) - -; Trouver le minimum de plusieurs acceptants -(define n2d-acc-mins - (lambda (accs) - (if (null? accs) - (cons #f #f) - (n2d-acc-min2 (car accs) (n2d-acc-mins (cdr accs)))))) - -; Fabriquer les vecteurs d'arcs et d'acceptance -(define n2d-extract-vs - (lambda () - (let* ((arcs-v (make-vector n2d-state-count)) - (acc-v (make-vector n2d-state-count))) - (let loop ((n 0)) - (if (= n n2d-state-count) - (cons arcs-v acc-v) - (begin - (vector-set! arcs-v n (get-dentry-darcs - (vector-ref n2d-state-dict n))) - (vector-set! acc-v n (get-dentry-acc - (vector-ref n2d-state-dict n))) - (loop (+ n 1)))))))) - -; Effectuer la transformation de l'automate de non-det. a det. -(define nfa2dfa - (lambda (nl-start no-nl-start arcs-v acc-v) - (n2d-init-glob-vars (vector-length arcs-v)) - (let* ((nl-d (n2d-search-state nl-start)) - (no-nl-d (n2d-search-state no-nl-start)) - (norm-arcs-v (n2d-normalize-arcs-v arcs-v))) - (let loop ((n 0)) - (if (< n n2d-state-count) - (let* ((dentry (vector-ref n2d-state-dict n)) - (ss (get-dentry-ss dentry)) - (arcs-l (map (lambda (s) (vector-ref norm-arcs-v s)) ss)) - (arcs (n2d-combine-arcs-l arcs-l)) - (darcs (n2d-translate-arcs arcs)) - (fact-darcs (n2d-factorize-darcs darcs)) - (accs (map (lambda (s) (vector-ref acc-v s)) ss)) - (acc (n2d-acc-mins accs))) - (set-dentry-darcs dentry fact-darcs) - (set-dentry-acc dentry acc) - (loop (+ n 1))))) - (let* ((result (n2d-extract-vs)) - (new-arcs-v (car result)) - (new-acc-v (cdr result))) - (n2d-init-glob-vars 0) - (list nl-d no-nl-d new-arcs-v new-acc-v))))) - -; Module prep.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; -; Divers pre-traitements avant l'ecriture des tables -; - -; Passe d'un arc multi-range a une liste d'arcs mono-range -(define prep-arc->sharcs - (lambda (arc) - (let* ((range-l (car arc)) - (dest (cdr arc)) - (op (lambda (range) (cons range dest)))) - (map op range-l)))) - -; Compare des arcs courts selon leur premier caractere -(define prep-sharc-<= - (lambda (sharc1 sharc2) - (class-<= (caar sharc1) (caar sharc2)))) - -; Remplit les trous parmi les sharcs avec des arcs "erreur" -(define prep-fill-error - (lambda (sharcs) - (let loop ((sharcs sharcs) (start 'inf-)) - (cond ((class-= start 'inf+) - '()) - ((null? sharcs) - (cons (cons (cons start 'inf+) 'err) (loop sharcs 'inf+))) - (else - (let* ((sharc (car sharcs)) - (h (caar sharc)) - (t (cdar sharc))) - (if (class-< start h) - (cons (cons (cons start (- h 1)) 'err) (loop sharcs h)) - (cons sharc (loop (cdr sharcs) - (if (class-= t 'inf+) - 'inf+ - (+ t 1))))))))))) - -; ; Passe d'une liste d'arcs a un arbre de decision -; ; 1ere methode: seulement des comparaisons < -; (define prep-arcs->tree -; (lambda (arcs) -; (let* ((sharcs-l (map prep-arc->sharcs arcs)) -; (sharcs (apply append sharcs-l)) -; (sorted-with-holes (merge-sort sharcs prep-sharc-<=)) -; (sorted (prep-fill-error sorted-with-holes)) -; (op (lambda (sharc) (cons (caar sharc) (cdr sharc)))) -; (table (list->vector (map op sorted)))) -; (let loop ((left 0) (right (- (vector-length table) 1))) -; (if (= left right) -; (cdr (vector-ref table left)) -; (let ((mid (quotient (+ left right 1) 2))) -; (list (car (vector-ref table mid)) -; (loop left (- mid 1)) -; (loop mid right)))))))) - -; Passe d'une liste d'arcs a un arbre de decision -; 2eme methode: permettre des comparaisons = quand ca adonne -(define prep-arcs->tree - (lambda (arcs) - (let* ((sharcs-l (map prep-arc->sharcs arcs)) - (sharcs (apply append sharcs-l)) - (sorted-with-holes (merge-sort sharcs prep-sharc-<=)) - (sorted (prep-fill-error sorted-with-holes)) - (op (lambda (sharc) (cons (caar sharc) (cdr sharc)))) - (table (list->vector (map op sorted)))) - (let loop ((left 0) (right (- (vector-length table) 1))) - (if (= left right) - (cdr (vector-ref table left)) - (let ((mid (quotient (+ left right 1) 2))) - (if (and (= (+ left 2) right) - (= (+ (car (vector-ref table mid)) 1) - (car (vector-ref table right))) - (eqv? (cdr (vector-ref table left)) - (cdr (vector-ref table right)))) - (list '= - (car (vector-ref table mid)) - (cdr (vector-ref table mid)) - (cdr (vector-ref table left))) - (list (car (vector-ref table mid)) - (loop left (- mid 1)) - (loop mid right))))))))) - -; Determine si une action a besoin de calculer yytext -(define prep-detect-yytext - (lambda (s) - (let loop1 ((i (- (string-length s) 6))) - (cond ((< i 0) - #f) - ((char-ci=? (string-ref s i) #\y) - (let loop2 ((j 5)) - (cond ((= j 0) - #t) - ((char-ci=? (string-ref s (+ i j)) - (string-ref "yytext" j)) - (loop2 (- j 1))) - (else - (loop1 (- i 1)))))) - (else - (loop1 (- i 1))))))) - -; Note dans une regle si son action a besoin de yytext -(define prep-set-rule-yytext? - (lambda (rule) - (let ((action (get-rule-action rule))) - (set-rule-yytext? rule (prep-detect-yytext action))))) - -; Note dans toutes les regles si leurs actions ont besoin de yytext -(define prep-set-rules-yytext? - (lambda (rules) - (let loop ((n (- (vector-length rules) 1))) - (if (>= n 0) - (begin - (prep-set-rule-yytext? (vector-ref rules n)) - (loop (- n 1))))))) - -; Module output.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; -; Nettoie les actions en enlevant les lignes blanches avant et apres -; - -(define out-split-in-lines - (lambda (s) - (let ((len (string-length s))) - (let loop ((i 0) (start 0)) - (cond ((= i len) - '()) - ((char=? (string-ref s i) #\newline) - (cons (substring s start (+ i 1)) - (loop (+ i 1) (+ i 1)))) - (else - (loop (+ i 1) start))))))) - -(define out-empty-line? - (lambda (s) - (let ((len (- (string-length s) 1))) - (let loop ((i 0)) - (cond ((= i len) - #t) - ((char-whitespace? (string-ref s i)) - (loop (+ i 1))) - (else - #f)))))) - -; Enleve les lignes vides dans une liste avant et apres l'action -(define out-remove-empty-lines - (lambda (lines) - (let loop ((lines lines) (top? #t)) - (if (null? lines) - '() - (let ((line (car lines))) - (cond ((not (out-empty-line? line)) - (cons line (loop (cdr lines) #f))) - (top? - (loop (cdr lines) #t)) - (else - (let ((rest (loop (cdr lines) #f))) - (if (null? rest) - '() - (cons line rest)))))))))) - -; Enleve les lignes vides avant et apres l'action -(define out-clean-action - (lambda (s) - (let* ((lines (out-split-in-lines s)) - (clean-lines (out-remove-empty-lines lines))) - (string-append-list clean-lines)))) - - - - -; -; Pretty-printer pour les booleens, la liste vide, les nombres, -; les symboles, les caracteres, les chaines, les listes et les vecteurs -; - -; Colonne limite pour le pretty-printer (a ne pas atteindre) -(define out-max-col 76) - -(define out-flatten-list - (lambda (ll) - (let loop ((ll ll) (part-out '())) - (if (null? ll) - part-out - (let* ((new-part-out (loop (cdr ll) part-out)) - (head (car ll))) - (cond ((null? head) - new-part-out) - ((pair? head) - (loop head new-part-out)) - (else - (cons head new-part-out)))))))) - -(define out-force-string - (lambda (obj) - (if (char? obj) - (string obj) - obj))) - -; Transforme une liste impropre en une liste propre qui s'ecrit -; de la meme facon -(define out-regular-list - (let ((symbolic-dot (string->symbol "."))) - (lambda (p) - (let ((tail (cdr p))) - (cond ((null? tail) - p) - ((pair? tail) - (cons (car p) (out-regular-list tail))) - (else - (list (car p) symbolic-dot tail))))))) - -; Cree des chaines d'espaces de facon paresseuse -(define out-blanks - (let ((cache-v (make-vector 80 #f))) - (lambda (n) - (or (vector-ref cache-v n) - (let ((result (make-string n #\space))) - (vector-set! cache-v n result) - result))))) - -; Insere le separateur entre chaque element d'une liste non-vide -(define out-separate - (lambda (text-l sep) - (if (null? (cdr text-l)) - text-l - (cons (car text-l) (cons sep (out-separate (cdr text-l) sep)))))) - -; Met des donnees en colonnes. Retourne comme out-pp-aux-list -(define out-pp-columns - (lambda (left right wmax txt&lens) - (let loop1 ((tls txt&lens) (lwmax 0) (lwlast 0) (lines '())) - (if (null? tls) - (vector #t 0 lwmax lwlast (reverse lines)) - (let loop2 ((tls tls) (len 0) (first? #t) (prev-pad 0) (line '())) - (cond ((null? tls) - (loop1 tls - (max len lwmax) - len - (cons (reverse line) lines))) - ((> (+ left len prev-pad 1 wmax) out-max-col) - (loop1 tls - (max len lwmax) - len - (cons (reverse line) lines))) - (first? - (let ((text (caar tls)) - (text-len (cdar tls))) - (loop2 (cdr tls) - (+ len text-len) - #f - (- wmax text-len) - (cons text line)))) - ((pair? (cdr tls)) - (let* ((prev-pad-s (out-blanks prev-pad)) - (text (caar tls)) - (text-len (cdar tls))) - (loop2 (cdr tls) - (+ len prev-pad 1 text-len) - #f - (- wmax text-len) - (cons text (cons " " (cons prev-pad-s line)))))) - (else - (let ((prev-pad-s (out-blanks prev-pad)) - (text (caar tls)) - (text-len (cdar tls))) - (if (> (+ left len prev-pad 1 text-len) right) - (loop1 tls - (max len lwmax) - len - (cons (reverse line) lines)) - (loop2 (cdr tls) - (+ len prev-pad 1 text-len) - #f - (- wmax text-len) - (append (list text " " prev-pad-s) - line))))))))))) - -; Retourne un vecteur #( multiline? width-all width-max width-last text-l ) -(define out-pp-aux-list - (lambda (l left right) - (let loop ((l l) (multi? #f) (wall -1) (wmax -1) (wlast -1) (txt&lens '())) - (if (null? l) - (cond (multi? - (vector #t wall wmax wlast (map car (reverse txt&lens)))) - ((<= (+ left wall) right) - (vector #f wall wmax wlast (map car (reverse txt&lens)))) - ((<= (+ left wmax 1 wmax) out-max-col) - (out-pp-columns left right wmax (reverse txt&lens))) - (else - (vector #t wall wmax wlast (map car (reverse txt&lens))))) - (let* ((obj (car l)) - (last? (null? (cdr l))) - (this-right (if last? right out-max-col)) - (result (out-pp-aux obj left this-right)) - (obj-multi? (vector-ref result 0)) - (obj-wmax (vector-ref result 1)) - (obj-wlast (vector-ref result 2)) - (obj-text (vector-ref result 3))) - (loop (cdr l) - (or multi? obj-multi?) - (+ wall obj-wmax 1) - (max wmax obj-wmax) - obj-wlast - (cons (cons obj-text obj-wmax) txt&lens))))))) - -; Retourne un vecteur #( multiline? wmax wlast text ) -(define out-pp-aux - (lambda (obj left right) - (cond ((boolean? obj) - (vector #f 2 2 (if obj '("#t") '("#f")))) - ((null? obj) - (vector #f 2 2 '("()"))) - ((number? obj) - (let* ((s (number->string obj)) - (len (string-length s))) - (vector #f len len (list s)))) - ((symbol? obj) - (let* ((s (symbol->string obj)) - (len (string-length s))) - (vector #f len len (list s)))) - ((char? obj) - (cond ((char=? obj #\space) - (vector #f 7 7 (list "#\\space"))) - ((char=? obj #\newline) - (vector #f 9 9 (list "#\\newline"))) - (else - (vector #f 3 3 (list "#\\" obj))))) - ((string? obj) - (let loop ((i (- (string-length obj) 1)) - (len 1) - (text '("\""))) - (if (= i -1) - (vector #f (+ len 1) (+ len 1) (cons "\"" text)) - (let ((c (string-ref obj i))) - (cond ((char=? c #\\) - (loop (- i 1) (+ len 2) (cons "\\\\" text))) - ((char=? c #\") - (loop (- i 1) (+ len 2) (cons "\\\"" text))) - (else - (loop (- i 1) (+ len 1) (cons (string c) text)))))))) - ((pair? obj) - (let* ((l (out-regular-list obj)) - (result (out-pp-aux-list l (+ left 1) (- right 1))) - (multiline? (vector-ref result 0)) - (width-all (vector-ref result 1)) - (width-max (vector-ref result 2)) - (width-last (vector-ref result 3)) - (text-l (vector-ref result 4))) - (if multiline? - (let* ((sep (list #\newline (out-blanks left))) - (formatted-text (out-separate text-l sep)) - (text (list "(" formatted-text ")"))) - (vector #t - (+ (max width-max (+ width-last 1)) 1) - (+ width-last 2) - text)) - (let* ((sep (list " ")) - (formatted-text (out-separate text-l sep)) - (text (list "(" formatted-text ")"))) - (vector #f (+ width-all 2) (+ width-all 2) text))))) - ((and (vector? obj) (zero? (vector-length obj))) - (vector #f 3 3 '("#()"))) - ((vector? obj) - (let* ((l (vector->list obj)) - (result (out-pp-aux-list l (+ left 2) (- right 1))) - (multiline? (vector-ref result 0)) - (width-all (vector-ref result 1)) - (width-max (vector-ref result 2)) - (width-last (vector-ref result 3)) - (text-l (vector-ref result 4))) - (if multiline? - (let* ((sep (list #\newline (out-blanks (+ left 1)))) - (formatted-text (out-separate text-l sep)) - (text (list "#(" formatted-text ")"))) - (vector #t - (+ (max width-max (+ width-last 1)) 2) - (+ width-last 3) - text)) - (let* ((sep (list " ")) - (formatted-text (out-separate text-l sep)) - (text (list "#(" formatted-text ")"))) - (vector #f (+ width-all 3) (+ width-all 3) text))))) - (else - (display "Internal error: out-pp") - (newline))))) - -; Retourne la chaine a afficher -(define out-pp - (lambda (obj col) - (let* ((list-rec-of-strings-n-chars - (vector-ref (out-pp-aux obj col out-max-col) 3)) - (list-of-strings-n-chars - (out-flatten-list list-rec-of-strings-n-chars)) - (list-of-strings - (map out-force-string list-of-strings-n-chars))) - (string-append-list list-of-strings)))) - - - - -; -; Nice-printer, plus rapide mais moins beau que le pretty-printer -; - -(define out-np - (lambda (obj start) - (letrec ((line-pad - (string-append (string #\newline) - (out-blanks (- start 1)))) - (step-line - (lambda (p) - (set-car! p line-pad))) - (p-bool - (lambda (obj col objw texts hole cont) - (let ((text (if obj "#t" "#f"))) - (cont (+ col 2) (+ objw 2) (cons text texts) hole)))) - (p-number - (lambda (obj col objw texts hole cont) - (let* ((text (number->string obj)) - (len (string-length text))) - (cont (+ col len) (+ objw len) (cons text texts) hole)))) - (p-symbol - (lambda (obj col objw texts hole cont) - (let* ((text (symbol->string obj)) - (len (string-length text))) - (cont (+ col len) (+ objw len) (cons text texts) hole)))) - (p-char - (lambda (obj col objw texts hole cont) - (let* ((text - (cond ((char=? obj #\space) "#\\space") - ((char=? obj #\newline) "#\\newline") - (else (string-append "#\\" (string obj))))) - (len (string-length text))) - (cont (+ col len) (+ objw len) (cons text texts) hole)))) - (p-list - (lambda (obj col objw texts hole cont) - (p-tail obj (+ col 1) (+ objw 1) (cons "(" texts) hole cont))) - (p-vector - (lambda (obj col objw texts hole cont) - (p-list (vector->list obj) - (+ col 1) (+ objw 1) (cons "#" texts) hole cont))) - (p-tail - (lambda (obj col objw texts hole cont) - (if (null? obj) - (cont (+ col 1) (+ objw 1) (cons ")" texts) hole) - (p-obj (car obj) col objw texts hole - (make-cdr-cont obj cont))))) - (make-cdr-cont - (lambda (obj cont) - (lambda (col objw texts hole) - (cond ((null? (cdr obj)) - (cont (+ col 1) (+ objw 1) (cons ")" texts) hole)) - ((> col out-max-col) - (step-line hole) - (let ((hole2 (cons " " texts))) - (p-cdr obj (+ start objw 1) 0 hole2 hole2 cont))) - (else - (let ((hole2 (cons " " texts))) - (p-cdr obj (+ col 1) 0 hole2 hole2 cont))))))) - (p-cdr - (lambda (obj col objw texts hole cont) - (if (pair? (cdr obj)) - (p-tail (cdr obj) col objw texts hole cont) - (p-dot col objw texts hole - (make-cdr-cont (list #f (cdr obj)) cont))))) - (p-dot - (lambda (col objw texts hole cont) - (cont (+ col 1) (+ objw 1) (cons "." texts) hole))) - (p-obj - (lambda (obj col objw texts hole cont) - (cond ((boolean? obj) - (p-bool obj col objw texts hole cont)) - ((number? obj) - (p-number obj col objw texts hole cont)) - ((symbol? obj) - (p-symbol obj col objw texts hole cont)) - ((char? obj) - (p-char obj col objw texts hole cont)) - ((or (null? obj) (pair? obj)) - (p-list obj col objw texts hole cont)) - ((vector? obj) - (p-vector obj col objw texts hole cont)))))) - (p-obj obj start 0 '() (cons #f #f) - (lambda (col objw texts hole) - (if (> col out-max-col) - (step-line hole)) - (string-append-list (reverse texts))))))) - - - - -; -; Fonction pour afficher une table -; Appelle la sous-routine adequate pour le type de fin de table -; - -; Affiche la table d'un driver -(define out-print-table - (lambda (args-alist - <<EOF>>-action <<ERROR>>-action rules - nl-start no-nl-start arcs-v acc-v - port) - (let* ((filein - (cdr (assq 'filein args-alist))) - (table-name - (cdr (assq 'table-name args-alist))) - (pretty? - (assq 'pp args-alist)) - (counters-type - (let ((a (assq 'counters args-alist))) - (if a (cdr a) 'line))) - (counters-param-list - (cond ((eq? counters-type 'none) - ")") - ((eq? counters-type 'line) - " yyline)") - (else ; 'all - " yyline yycolumn yyoffset)"))) - (counters-param-list-short - (if (char=? (string-ref counters-param-list 0) #\space) - (substring counters-param-list - 1 - (string-length counters-param-list)) - counters-param-list)) - (clean-eof-action - (out-clean-action <<EOF>>-action)) - (clean-error-action - (out-clean-action <<ERROR>>-action)) - (rule-op - (lambda (rule) (out-clean-action (get-rule-action rule)))) - (rules-l - (vector->list rules)) - (clean-actions-l - (map rule-op rules-l)) - (yytext?-l - (map get-rule-yytext? rules-l))) - - ; Commentaires prealables - (display ";" port) - (newline port) - (display "; Table generated from the file " port) - (display filein port) - (display " by SILex 1.0" port) - (newline port) - (display ";" port) - (newline port) - (newline port) - - ; Ecrire le debut de la table - (display "(define " port) - (display table-name port) - (newline port) - (display " (vector" port) - (newline port) - - ; Ecrire la description du type de compteurs - (display " '" port) - (write counters-type port) - (newline port) - - ; Ecrire l'action pour la fin de fichier - (display " (lambda (yycontinue yygetc yyungetc)" port) - (newline port) - (display " (lambda (yytext" port) - (display counters-param-list port) - (newline port) - (display clean-eof-action port) - (display " ))" port) - (newline port) - - ; Ecrire l'action pour le cas d'erreur - (display " (lambda (yycontinue yygetc yyungetc)" port) - (newline port) - (display " (lambda (yytext" port) - (display counters-param-list port) - (newline port) - (display clean-error-action port) - (display " ))" port) - (newline port) - - ; Ecrire le vecteur des actions des regles ordinaires - (display " (vector" port) - (newline port) - (let loop ((al clean-actions-l) (yyl yytext?-l)) - (if (pair? al) - (let ((yytext? (car yyl))) - (display " " port) - (write yytext? port) - (newline port) - (display " (lambda (yycontinue yygetc yyungetc)" port) - (newline port) - (if yytext? - (begin - (display " (lambda (yytext" port) - (display counters-param-list port)) - (begin - (display " (lambda (" port) - (display counters-param-list-short port))) - (newline port) - (display (car al) port) - (display " ))" port) - (if (pair? (cdr al)) - (newline port)) - (loop (cdr al) (cdr yyl))))) - (display ")" port) - (newline port) - - ; Ecrire l'automate - (cond ((assq 'portable args-alist) - (out-print-table-chars - pretty? - nl-start no-nl-start arcs-v acc-v - port)) - ((assq 'code args-alist) - (out-print-table-code - counters-type (vector-length rules) yytext?-l - nl-start no-nl-start arcs-v acc-v - port)) - (else - (out-print-table-data - pretty? - nl-start no-nl-start arcs-v acc-v - port)))))) - -; -; Affiche l'automate sous forme d'arbres de decision -; Termine la table du meme coup -; - -(define out-print-table-data - (lambda (pretty? nl-start no-nl-start arcs-v acc-v port) - (let* ((len (vector-length arcs-v)) - (trees-v (make-vector len))) - (let loop ((i 0)) - (if (< i len) - (begin - (vector-set! trees-v i (prep-arcs->tree (vector-ref arcs-v i))) - (loop (+ i 1))))) - - ; Decrire le format de l'automate - (display " 'decision-trees" port) - (newline port) - - ; Ecrire l'etat de depart pour le cas "debut de la ligne" - (display " " port) - (write nl-start port) - (newline port) - - ; Ecrire l'etat de depart pour le cas "pas au debut de la ligne" - (display " " port) - (write no-nl-start port) - (newline port) - - ; Ecrire la table de transitions - (display " '" port) - (if pretty? - (display (out-pp trees-v 5) port) - (display (out-np trees-v 5) port)) - (newline port) - - ; Ecrire la table des acceptations - (display " '" port) - (if pretty? - (display (out-pp acc-v 5) port) - (display (out-np acc-v 5) port)) - - ; Ecrire la fin de la table - (display "))" port) - (newline port)))) - -; -; Affiche l'automate sous forme de listes de caracteres taggees -; Termine la table du meme coup -; - -(define out-print-table-chars - (lambda (pretty? nl-start no-nl-start arcs-v acc-v port) - (let* ((len (vector-length arcs-v)) - (portable-v (make-vector len)) - (arc-op (lambda (arc) - (cons (class->tagged-char-list (car arc)) (cdr arc))))) - (let loop ((s 0)) - (if (< s len) - (let* ((arcs (vector-ref arcs-v s)) - (port-arcs (map arc-op arcs))) - (vector-set! portable-v s port-arcs) - (loop (+ s 1))))) - - ; Decrire le format de l'automate - (display " 'tagged-chars-lists" port) - (newline port) - - ; Ecrire l'etat de depart pour le cas "debut de la ligne" - (display " " port) - (write nl-start port) - (newline port) - - ; Ecrire l'etat de depart pour le cas "pas au debut de la ligne" - (display " " port) - (write no-nl-start port) - (newline port) - - ; Ecrire la table de transitions - (display " '" port) - (if pretty? - (display (out-pp portable-v 5) port) - (display (out-np portable-v 5) port)) - (newline port) - - ; Ecrire la table des acceptations - (display " '" port) - (if pretty? - (display (out-pp acc-v 5) port) - (display (out-np acc-v 5) port)) - - ; Ecrire la fin de la table - (display "))" port) - (newline port)))) - -; -; Genere l'automate en code Scheme -; Termine la table du meme coup -; - -(define out-print-code-trans3 - (lambda (margin tree action-var port) - (newline port) - (display (out-blanks margin) port) - (cond ((eq? tree 'err) - (display action-var port)) - ((number? tree) - (display "(state-" port) - (display tree port) - (display " " port) - (display action-var port) - (display ")" port)) - ((eq? (car tree) '=) - (display "(if (= c " port) - (display (list-ref tree 1) port) - (display ")" port) - (out-print-code-trans3 (+ margin 4) - (list-ref tree 2) - action-var - port) - (out-print-code-trans3 (+ margin 4) - (list-ref tree 3) - action-var - port) - (display ")" port)) - (else - (display "(if (< c " port) - (display (list-ref tree 0) port) - (display ")" port) - (out-print-code-trans3 (+ margin 4) - (list-ref tree 1) - action-var - port) - (out-print-code-trans3 (+ margin 4) - (list-ref tree 2) - action-var - port) - (display ")" port))))) - -(define out-print-code-trans2 - (lambda (margin tree action-var port) - (newline port) - (display (out-blanks margin) port) - (display "(if c" port) - (out-print-code-trans3 (+ margin 4) tree action-var port) - (newline port) - (display (out-blanks (+ margin 4)) port) - (display action-var port) - (display ")" port))) - -(define out-print-code-trans1 - (lambda (margin tree action-var port) - (newline port) - (display (out-blanks margin) port) - (if (eq? tree 'err) - (display action-var port) - (begin - (display "(let ((c (read-char)))" port) - (out-print-code-trans2 (+ margin 2) tree action-var port) - (display ")" port))))) - -(define out-print-table-code - (lambda (counters nbrules yytext?-l - nl-start no-nl-start arcs-v acc-v - port) - (let* ((counters-params - (cond ((eq? counters 'none) ")") - ((eq? counters 'line) " yyline)") - ((eq? counters 'all) " yyline yycolumn yyoffset)"))) - (counters-params-short - (cond ((eq? counters 'none) ")") - ((eq? counters 'line) "yyline)") - ((eq? counters 'all) "yyline yycolumn yyoffset)"))) - (nbstates (vector-length arcs-v)) - (trees-v (make-vector nbstates))) - (let loop ((s 0)) - (if (< s nbstates) - (begin - (vector-set! trees-v s (prep-arcs->tree (vector-ref arcs-v s))) - (loop (+ s 1))))) - - ; Decrire le format de l'automate - (display " 'code" port) - (newline port) - - ; Ecrire l'entete de la fonction - (display " (lambda (<<EOF>>-pre-action" port) - (newline port) - (display " <<ERROR>>-pre-action" port) - (newline port) - (display " rules-pre-action" port) - (newline port) - (display " IS)" port) - (newline port) - - ; Ecrire le debut du letrec et les variables d'actions brutes - (display " (letrec" port) - (newline port) - (display " ((user-action-<<EOF>> #f)" port) - (newline port) - (display " (user-action-<<ERROR>> #f)" port) - (newline port) - (let loop ((i 0)) - (if (< i nbrules) - (begin - (display " (user-action-" port) - (write i port) - (display " #f)" port) - (newline port) - (loop (+ i 1))))) - - ; Ecrire l'extraction des fonctions du IS - (display " (start-go-to-end " port) - (display "(cdr (assq 'start-go-to-end IS)))" port) - (newline port) - (display " (end-go-to-point " port) - (display "(cdr (assq 'end-go-to-point IS)))" port) - (newline port) - (display " (init-lexeme " port) - (display "(cdr (assq 'init-lexeme IS)))" port) - (newline port) - (display " (get-start-line " port) - (display "(cdr (assq 'get-start-line IS)))" port) - (newline port) - (display " (get-start-column " port) - (display "(cdr (assq 'get-start-column IS)))" port) - (newline port) - (display " (get-start-offset " port) - (display "(cdr (assq 'get-start-offset IS)))" port) - (newline port) - (display " (peek-left-context " port) - (display "(cdr (assq 'peek-left-context IS)))" port) - (newline port) - (display " (peek-char " port) - (display "(cdr (assq 'peek-char IS)))" port) - (newline port) - (display " (read-char " port) - (display "(cdr (assq 'read-char IS)))" port) - (newline port) - (display " (get-start-end-text " port) - (display "(cdr (assq 'get-start-end-text IS)))" port) - (newline port) - (display " (user-getc " port) - (display "(cdr (assq 'user-getc IS)))" port) - (newline port) - (display " (user-ungetc " port) - (display "(cdr (assq 'user-ungetc IS)))" port) - (newline port) - - ; Ecrire les variables d'actions - (display " (action-<<EOF>>" port) - (newline port) - (display " (lambda (" port) - (display counters-params-short port) - (newline port) - (display " (user-action-<<EOF>> \"\"" port) - (display counters-params port) - (display "))" port) - (newline port) - (display " (action-<<ERROR>>" port) - (newline port) - (display " (lambda (" port) - (display counters-params-short port) - (newline port) - (display " (user-action-<<ERROR>> \"\"" port) - (display counters-params port) - (display "))" port) - (newline port) - (let loop ((i 0) (yyl yytext?-l)) - (if (< i nbrules) - (begin - (display " (action-" port) - (display i port) - (newline port) - (display " (lambda (" port) - (display counters-params-short port) - (newline port) - (if (car yyl) - (begin - (display " (let ((yytext" port) - (display " (get-start-end-text)))" port) - (newline port) - (display " (start-go-to-end)" port) - (newline port) - (display " (user-action-" port) - (display i port) - (display " yytext" port) - (display counters-params port) - (display ")))" port) - (newline port)) - (begin - (display " (start-go-to-end)" port) - (newline port) - (display " (user-action-" port) - (display i port) - (display counters-params port) - (display "))" port) - (newline port))) - (loop (+ i 1) (cdr yyl))))) - - ; Ecrire les variables d'etats - (let loop ((s 0)) - (if (< s nbstates) - (let* ((tree (vector-ref trees-v s)) - (acc (vector-ref acc-v s)) - (acc-eol (car acc)) - (acc-no-eol (cdr acc))) - (display " (state-" port) - (display s port) - (newline port) - (display " (lambda (action)" port) - (cond ((not acc-eol) - (out-print-code-trans1 13 tree "action" port)) - ((not acc-no-eol) - (newline port) - (if (eq? tree 'err) - (display " (let* ((c (peek-char))" port) - (display " (let* ((c (read-char))" port)) - (newline port) - (display " (new-action (if (o" port) - (display "r (not c) (= c lexer-integer-newline))" port) - (newline port) - (display " " port) - (display " (begin (end-go-to-point) action-" port) - (display acc-eol port) - (display ")" port) - (newline port) - (display " " port) - (display " action)))" port) - (if (eq? tree 'err) - (out-print-code-trans1 15 tree "new-action" port) - (out-print-code-trans2 15 tree "new-action" port)) - (display ")" port)) - ((< acc-eol acc-no-eol) - (newline port) - (display " (end-go-to-point)" port) - (newline port) - (if (eq? tree 'err) - (display " (let* ((c (peek-char))" port) - (display " (let* ((c (read-char))" port)) - (newline port) - (display " (new-action (if (o" port) - (display "r (not c) (= c lexer-integer-newline))" port) - (newline port) - (display " " port) - (display " action-" port) - (display acc-eol port) - (newline port) - (display " " port) - (display " action-" port) - (display acc-no-eol port) - (display ")))" port) - (if (eq? tree 'err) - (out-print-code-trans1 15 tree "new-action" port) - (out-print-code-trans2 15 tree "new-action" port)) - (display ")" port)) - (else - (let ((action-var - (string-append "action-" - (number->string acc-eol)))) - (newline port) - (display " (end-go-to-point)" port) - (out-print-code-trans1 13 tree action-var port)))) - (display "))" port) - (newline port) - (loop (+ s 1))))) - - ; Ecrire la variable de lancement de l'automate - (display " (start-automaton" port) - (newline port) - (display " (lambda ()" port) - (newline port) - (if (= nl-start no-nl-start) - (begin - (display " (if (peek-char)" port) - (newline port) - (display " (state-" port) - (display nl-start port) - (display " action-<<ERROR>>)" port) - (newline port) - (display " action-<<EOF>>)" port)) - (begin - (display " (cond ((not (peek-char))" port) - (newline port) - (display " action-<<EOF>>)" port) - (newline port) - (display " ((= (peek-left-context)" port) - (display " lexer-integer-newline)" port) - (newline port) - (display " (state-" port) - (display nl-start port) - (display " action-<<ERROR>>))" port) - (newline port) - (display " (else" port) - (newline port) - (display " (state-" port) - (display no-nl-start port) - (display " action-<<ERROR>>)))" port))) - (display "))" port) - (newline port) - - ; Ecrire la fonction principale de lexage - (display " (final-lexer" port) - (newline port) - (display " (lambda ()" port) - (newline port) - (display " (init-lexeme)" port) - (newline port) - (cond ((eq? counters 'none) - (display " ((start-automaton))" port)) - ((eq? counters 'line) - (display " (let ((yyline (get-start-line)))" port) - (newline port) - (display " ((start-automaton) yyline))" port)) - ((eq? counters 'all) - (display " (let ((yyline (get-start-line))" port) - (newline port) - (display " (yycolumn (get-start-column))" port) - (newline port) - (display " (yyoffset (get-start-offset)))" port) - (newline port) - (display " ((start-automat" port) - (display "on) yyline yycolumn yyoffset))" port))) - (display "))" port) - - ; Fermer les bindings du grand letrec - (display ")" port) - (newline port) - - ; Initialiser les variables user-action-XX - (display " (set! user-action-<<EOF>>" port) - (display " (<<EOF>>-pre-action" port) - (newline port) - (display " final-lexer" port) - (display " user-getc user-ungetc))" port) - (newline port) - (display " (set! user-action-<<ERROR>>" port) - (display " (<<ERROR>>-pre-action" port) - (newline port) - (display " final-lexer" port) - (display " user-getc user-ungetc))" port) - (newline port) - (let loop ((r 0)) - (if (< r nbrules) - (let* ((str-r (number->string r)) - (blanks (out-blanks (string-length str-r)))) - (display " (set! user-action-" port) - (display str-r port) - (display " ((vector-ref rules-pre-action " port) - (display (number->string (+ (* 2 r) 1)) port) - (display ")" port) - (newline port) - (display blanks port) - (display " final-lexer " port) - (display "user-getc user-ungetc))" port) - (newline port) - (loop (+ r 1))))) - - ; Faire retourner le lexer final et fermer la table au complet - (display " final-lexer))))" port) - (newline port)))) - -; -; Fonctions necessaires a l'initialisation automatique du lexer -; - -(define out-print-driver-functions - (lambda (args-alist port) - (let ((counters (cdr (or (assq 'counters args-alist) '(z . line)))) - (table-name (cdr (assq 'table-name args-alist)))) - (display ";" port) - (newline port) - (display "; User functions" port) - (newline port) - (display ";" port) - (newline port) - (newline port) - (display "(define lexer #f)" port) - (newline port) - (newline port) - (if (not (eq? counters 'none)) - (begin - (display "(define lexer-get-line #f)" port) - (newline port) - (if (eq? counters 'all) - (begin - (display "(define lexer-get-column #f)" port) - (newline port) - (display "(define lexer-get-offset #f)" port) - (newline port))))) - (display "(define lexer-getc #f)" port) - (newline port) - (display "(define lexer-ungetc #f)" port) - (newline port) - (newline port) - (display "(define lexer-init" port) - (newline port) - (display " (lambda (input-type input)" port) - (newline port) - (display " (let ((IS (lexer-make-IS input-type input '" port) - (write counters port) - (display ")))" port) - (newline port) - (display " (set! lexer (lexer-make-lexer " port) - (display table-name port) - (display " IS))" port) - (newline port) - (if (not (eq? counters 'none)) - (begin - (display " (set! lexer-get-line (lexer-get-func-line IS))" - port) - (newline port) - (if (eq? counters 'all) - (begin - (display - " (set! lexer-get-column (lexer-get-func-column IS))" - port) - (newline port) - (display - " (set! lexer-get-offset (lexer-get-func-offset IS))" - port) - (newline port))))) - (display " (set! lexer-getc (lexer-get-func-getc IS))" port) - (newline port) - (display " (set! lexer-ungetc (lexer-get-func-ungetc IS)))))" - port) - (newline port)))) - -; -; Fonction principale -; Affiche une table ou un driver complet -; - -(define output - (lambda (args-alist - <<EOF>>-action <<ERROR>>-action rules - nl-start no-nl-start arcs acc) - (let* ((fileout (cdr (assq 'fileout args-alist))) - (port (open-output-file fileout)) - (complete-driver? (cdr (assq 'complete-driver? args-alist)))) - (if complete-driver? - (begin - (out-print-run-time-lib port) - (newline port))) - (out-print-table args-alist - <<EOF>>-action <<ERROR>>-action rules - nl-start no-nl-start arcs acc - port) - (if complete-driver? - (begin - (newline port) - (out-print-driver-functions args-alist port))) - (close-output-port port)))) - -; Module output2.scm. -; -; Fonction de copiage du fichier run-time -; - -(define out-print-run-time-lib - (lambda (port) - (display "; *** This file start" port) - (display "s with a copy of the " port) - (display "file multilex.scm ***" port) - (newline port) - (display "; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; -; Gestion des Input Systems -; Fonctions a utiliser par l'usager: -; lexer-make-IS, lexer-get-func-getc, lexer-get-func-ungetc, -; lexer-get-func-line, lexer-get-func-column et lexer-get-func-offset -; - -; Taille initiale par defaut du buffer d'entree -(define lexer-init-buffer-len 1024) - -; Numero du caractere newline -(define lexer-integer-newline (char->integer #\\newline)) - -; Constructeur d'IS brut -(define lexer-raw-IS-maker - (lambda (buffer read-ptr input-f counters) - (let ((input-f input-f) ; Entree reelle - (buffer buffer) ; Buffer - (buflen (string-length buffer)) - (read-ptr read-ptr) - (start-ptr 1) ; Marque de debut de lexeme - (start-line 1) - (start-column 1) - (start-offset 0) - (end-ptr 1) ; Marque de fin de lexeme - (point-ptr 1) ; Le point - (user-ptr 1) ; Marque de l'usager - (user-line 1) - (user-column 1) - (user-offset 0) - (user-up-to-date? #t)) ; Concerne la colonne seul. - (letrec - ((start-go-to-end-none ; Fonctions de depl. des marques - (lambda () - (set! start-ptr end-ptr))) - (start-go-to-end-line - (lambda () - (let loop ((ptr start-ptr) (line start-line)) - (if (= ptr end-ptr) - (begin - (set! start-ptr ptr) - (set! start-line line)) - (if (char=? (string-ref buffer ptr) #\\newline) - (loop (+ ptr 1) (+ line 1)) - (loop (+ ptr 1) line)))))) - (start-go-to-end-all - (lambda () - (set! start-offset (+ start-offset (- end-ptr start-ptr))) - (let loop ((ptr start-ptr) - (line start-line) - (column start-column)) - (if (= ptr end-ptr) - (begin - (set! start-ptr ptr) - (set! start-line line) - (set! start-column column)) - (if (char=? (string-ref buffer ptr) #\\newline) - (loop (+ ptr 1) (+ line 1) 1) - (loop (+ ptr 1) line (+ column 1))))))) - (start-go-to-user-none - (lambda () - (set! start-ptr user-ptr))) - (start-go-to-user-line - (lambda () - (set! start-ptr user-ptr) - (set! start-line user-line))) - (start-go-to-user-all - (lambda () - (set! start-line user-line) - (set! start-offset user-offset) - (if user-up-to-date? - (begin - (set! start-ptr user-ptr) - (set! start-column user-column)) - (let loop ((ptr start-ptr) (column start-column)) - (if (= ptr user-ptr) - (begin - (set! start-ptr ptr) - (set! start-column column)) - (if (char=? (string-ref buffer ptr) #\\newline) - (loop (+ ptr 1) 1) - (loop (+ ptr 1) (+ column 1)))))))) - (end-go-to-point - (lambda () - (set! end-ptr point-ptr))) - (point-go-to-start - (lambda () - (set! point-ptr start-ptr))) - (user-go-to-start-none - (lambda () - (set! user-ptr start-ptr))) - (user-go-to-start-line - (lambda () - (set! user-ptr start-ptr) - (set! user-line start-line))) - (user-go-to-start-all - (lambda () - (set! user-ptr start-ptr) - (set! user-line start-line) - (set! user-column start-column) - (set! user-offset start-offset) - (set! user-up-to-date? #t))) - (init-lexeme-none ; Debute un nouveau lexeme - (lambda () - (if (< start-ptr user-ptr) - (start-go-to-user-none)) - (point-go-to-start))) - (init-lexeme-line - (lambda () - (if (< start-ptr user-ptr) - (start-go-to-user-line)) - (point-go-to-start))) - (init-lexeme-all - (lambda () - (if (< start-ptr user-ptr) - (start-go-to-user-all)) - (point-go-to-start))) - (get-start-line ; Obtention des stats du debut du lxm - (lambda () - start-line)) - (get-start-column - (lambda () - start-column)) - (get-start-offset - (lambda () - start-offset)) - (peek-left-context ; Obtention de caracteres (#f si EOF) - (lambda () - (char->integer (string-ref buffer (- start-ptr 1))))) - (peek-char - (lambda () - (if (< point-ptr read-ptr) - (char->integer (string-ref buffer point-ptr)) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer point-ptr c) - (set! read-ptr (+ point-ptr 1)) - (char->integer c)) - (begin - (set! input-f (lambda () 'eof)) - #f)))))) - (read-char - (lambda () - (if (< point-ptr read-ptr) - (let ((c (string-ref buffer point-ptr))) - (set! point-ptr (+ point-ptr 1)) - (char->integer c)) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer point-ptr c) - (set! read-ptr (+ point-ptr 1)) - (set! point-ptr read-ptr) - (char->integer c)) - (begin - (set! input-f (lambda () 'eof)) - #f)))))) - (get-start-end-text ; Obtention du lexeme - (lambda () - (substring buffer start-ptr end-ptr))) - (get-user-line-line ; Fonctions pour l'usager - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-line)) - user-line)) - (get-user-line-all - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-all)) - user-line)) - (get-user-column-all - (lambda () - (cond ((< user-ptr start-ptr) - (user-go-to-start-all) - user-column) - (user-up-to-date? - user-column) - (else - (let loop ((ptr start-ptr) (column start-column)) - (if (= ptr user-ptr) - (begin - (set! user-column column) - (set! user-up-to-date? #t) - column) - (if (char=? (string-ref buffer ptr) #\\newline) - (loop (+ ptr 1) 1) - (loop (+ ptr 1) (+ column 1))))))))) - (get-user-offset-all - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-all)) - user-offset)) - (user-getc-none - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-none)) - (if (< user-ptr read-ptr) - (let ((c (string-ref buffer user-ptr))) - (set! user-ptr (+ user-ptr 1)) - c) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer user-ptr c) - (set! read-ptr (+ read-ptr 1)) - (set! user-ptr read-ptr) - c) - (begin - (set! input-f (lambda () 'eof)) - 'eof)))))) - (user-getc-line - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-line)) - (if (< user-ptr read-ptr) - (let ((c (string-ref buffer user-ptr))) - (set! user-ptr (+ user-ptr 1)) - (if (char=? c #\\newline) - (set! user-line (+ user-line 1))) - c) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer user-ptr c) - (set! read-ptr (+ read-ptr 1)) - (set! user-ptr read-ptr) - (if (char=? c #\\newline) - (set! user-line (+ user-line 1))) - c) - (begin - (set! input-f (lambda () 'eof)) - 'eof)))))) - (user-getc-all - (lambda () - (if (< user-ptr start-ptr) - (user-go-to-start-all)) - (if (< user-ptr read-ptr) - (let ((c (string-ref buffer user-ptr))) - (set! user-ptr (+ user-ptr 1)) - (if (char=? c #\\newline) - (begin - (set! user-line (+ user-line 1)) - (set! user-column 1)) - (set! user-column (+ user-column 1))) - (set! user-offset (+ user-offset 1)) - c) - (let ((c (input-f))) - (if (char? c) - (begin - (if (= read-ptr buflen) - (reorganize-buffer)) - (string-set! buffer user-ptr c) - (set! read-ptr (+ read-ptr 1)) - (set! user-ptr read-ptr) - (if (char=? c #\\newline) - (begin - (set! user-line (+ user-line 1)) - (set! user-column 1)) - (set! user-column (+ user-column 1))) - (set! user-offset (+ user-offset 1)) - c) - (begin - (set! input-f (lambda () 'eof)) - 'eof)))))) - (user-ungetc-none - (lambda () - (if (> user-ptr start-ptr) - (set! user-ptr (- user-ptr 1))))) - (user-ungetc-line - (lambda () - (if (> user-ptr start-ptr) - (begin - (set! user-ptr (- user-ptr 1)) - (let ((c (string-ref buffer user-ptr))) - (if (char=? c #\\newline) - (set! user-line (- user-line 1)))))))) - (user-ungetc-all - (lambda () - (if (> user-ptr start-ptr) - (begin - (set! user-ptr (- user-ptr 1)) - (let ((c (string-ref buffer user-ptr))) - (if (char=? c #\\newline) - (begin - (set! user-line (- user-line 1)) - (set! user-up-to-date? #f)) - (set! user-column (- user-column 1))) - (set! user-offset (- user-offset 1))))))) - (reorganize-buffer ; Decaler ou agrandir le buffer - (lambda () - (if (< (* 2 start-ptr) buflen) - (let* ((newlen (* 2 buflen)) - (newbuf (make-string newlen)) - (delta (- start-ptr 1))) - (let loop ((from (- start-ptr 1))) - (if (< from buflen) - (begin - (string-set! newbuf - (- from delta) - (string-ref buffer from)) - (loop (+ from 1))))) - (set! buffer newbuf) - (set! buflen newlen) - (set! read-ptr (- read-ptr delta)) - (set! start-ptr (- start-ptr delta)) - (set! end-ptr (- end-ptr delta)) - (set! point-ptr (- point-ptr delta)) - (set! user-ptr (- user-ptr delta))) - (let ((delta (- start-ptr 1))) - (let loop ((from (- start-ptr 1))) - (if (< from buflen) - (begin - (string-set! buffer - (- from delta) - (string-ref buffer from)) - (loop (+ from 1))))) - (set! read-ptr (- read-ptr delta)) - (set! start-ptr (- start-ptr delta)) - (set! end-ptr (- end-ptr delta)) - (set! point-ptr (- point-ptr delta)) - (set! user-ptr (- user-ptr delta))))))) - (list (cons 'start-go-to-end - (cond ((eq? counters 'none) start-go-to-end-none) - ((eq? counters 'line) start-go-to-end-line) - ((eq? counters 'all ) start-go-to-end-all))) - (cons 'end-go-to-point - end-go-to-point) - (cons 'init-lexeme - (cond ((eq? counters 'none) init-lexeme-none) - ((eq? counters 'line) init-lexeme-line) - ((eq? counters 'all ) init-lexeme-all))) - (cons 'get-start-line - get-start-line) - (cons 'get-start-column - get-start-column) - (cons 'get-start-offset - get-start-offset) - (cons 'peek-left-context - peek-left-context) - (cons 'peek-char - peek-char) - (cons 'read-char - read-char) - (cons 'get-start-end-text - get-start-end-text) - (cons 'get-user-line - (cond ((eq? counters 'none) #f) - ((eq? counters 'line) get-user-line-line) - ((eq? counters 'all ) get-user-line-all))) - (cons 'get-user-column - (cond ((eq? counters 'none) #f) - ((eq? counters 'line) #f) - ((eq? counters 'all ) get-user-column-all))) - (cons 'get-user-offset - (cond ((eq? counters 'none) #f) - ((eq? counters 'line) #f) - ((eq? counters 'all ) get-user-offset-all))) - (cons 'user-getc - (cond ((eq? counters 'none) user-getc-none) - ((eq? counters 'line) user-getc-line) - ((eq? counters 'all ) user-getc-all))) - (cons 'user-ungetc - (cond ((eq? counters 'none) user-ungetc-none) - ((eq? counters 'line) user-ungetc-line) - ((eq? counters 'all ) user-ungetc-all)))))))) - -; Construit un Input System -; Le premier parametre doit etre parmi \"port\", \"procedure\" ou \"string\" -; Prend un parametre facultatif qui doit etre parmi -; \"none\", \"line\" ou \"all\" -(define lexer-make-IS - (lambda (input-type input . largs) - (let ((counters-type (cond ((null? largs) - 'line) - ((memq (car largs) '(none line all)) - (car largs)) - (else - 'line)))) - (cond ((and (eq? input-type 'port) (input-port? input)) - (let* ((buffer (make-string lexer-init-buffer-len #\\newline)) - (read-ptr 1) - (input-f (lambda () (read-char input)))) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))) - ((and (eq? input-type 'procedure) (procedure? input)) - (let* ((buffer (make-string lexer-init-buffer-len #\\newline)) - (read-ptr 1) - (input-f input)) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))) - ((and (eq? input-type 'string) (string? input)) - (let* ((buffer (string-append (string #\\newline) input)) - (read-ptr (string-length buffer)) - (input-f (lambda () 'eof))) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))) - (else - (let* ((buffer (string #\\newline)) - (read-ptr 1) - (input-f (lambda () 'eof))) - (lexer-raw-IS-maker buffer read-ptr input-f counters-type))))))) - -; Les fonctions: -; lexer-get-func-getc, lexer-get-func-ungetc, -; lexer-get-func-line, lexer-get-func-column et lexer-get-func-offset -(define lexer-get-func-getc - (lambda (IS) (cdr (assq 'user-getc IS)))) -(define lexer-get-func-ungetc - (lambda (IS) (cdr (assq 'user-ungetc IS)))) -(define lexer-get-func-line - (lambda (IS) (cdr (assq 'get-user-line IS)))) -(define lexer-get-func-column - (lambda (IS) (cdr (assq 'get-user-column IS)))) -(define lexer-get-func-offset - (lambda (IS) (cdr (assq 'get-user-offset IS)))) - -; -; Gestion des lexers -; - -; Fabrication de lexer a partir d'arbres de decision -(define lexer-make-tree-lexer - (lambda (tables IS) - (letrec - (; Contenu de la table - (counters-type (vector-ref tables 0)) - (<<EOF>>-pre-action (vector-ref tables 1)) - (<<ERROR>>-pre-action (vector-ref tables 2)) - (rules-pre-actions (vector-ref tables 3)) - (table-nl-start (vector-ref tables 5)) - (table-no-nl-start (vector-ref tables 6)) - (trees-v (vector-ref tables 7)) - (acc-v (vector-ref tables 8)) - - ; Contenu du IS - (IS-start-go-to-end (cdr (assq 'start-go-to-end IS))) - (IS-end-go-to-point (cdr (assq 'end-go-to-point IS))) - (IS-init-lexeme (cdr (assq 'init-lexeme IS))) - (IS-get-start-line (cdr (assq 'get-start-line IS))) - (IS-get-start-column (cdr (assq 'get-start-column IS))) - (IS-get-start-offset (cdr (assq 'get-start-offset IS))) - (IS-peek-left-context (cdr (assq 'peek-left-context IS))) - (IS-peek-char (cdr (assq 'peek-char IS))) - (IS-read-char (cdr (assq 'read-char IS))) - (IS-get-start-end-text (cdr (assq 'get-start-end-text IS))) - (IS-get-user-line (cdr (assq 'get-user-line IS))) - (IS-get-user-column (cdr (assq 'get-user-column IS))) - (IS-get-user-offset (cdr (assq 'get-user-offset IS))) - (IS-user-getc (cdr (assq 'user-getc IS))) - (IS-user-ungetc (cdr (assq 'user-ungetc IS))) - - ; Resultats - (<<EOF>>-action #f) - (<<ERROR>>-action #f) - (rules-actions #f) - (states #f) - (final-lexer #f) - - ; Gestion des hooks - (hook-list '()) - (add-hook - (lambda (thunk) - (set! hook-list (cons thunk hook-list)))) - (apply-hooks - (lambda () - (let loop ((l hook-list)) - (if (pair? l) - (begin - ((car l)) - (loop (cdr l))))))) - - ; Preparation des actions - (set-action-statics - (lambda (pre-action) - (pre-action final-lexer IS-user-getc IS-user-ungetc))) - (prepare-special-action-none - (lambda (pre-action) - (let ((action #f)) - (let ((result - (lambda () - (action \"\"))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-special-action-line - (lambda (pre-action) - (let ((action #f)) - (let ((result - (lambda (yyline) - (action \"\" yyline))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-special-action-all - (lambda (pre-action) - (let ((action #f)) - (let ((result - (lambda (yyline yycolumn yyoffset) - (action \"\" yyline yycolumn yyoffset))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-special-action - (lambda (pre-action) - (cond ((eq? counters-type 'none) - (prepare-special-action-none pre-action)) - ((eq? counters-type 'line) - (prepare-special-action-line pre-action)) - ((eq? counters-type 'all) - (prepare-special-action-all pre-action))))) - (prepare-action-yytext-none - (lambda (pre-action) - (let ((get-start-end-text IS-get-start-end-text) - (start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda () - (let ((yytext (get-start-end-text))) - (start-go-to-end) - (action yytext)))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-yytext-line - (lambda (pre-action) - (let ((get-start-end-text IS-get-start-end-text) - (start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline) - (let ((yytext (get-start-end-text))) - (start-go-to-end) - (action yytext yyline)))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-yytext-all - (lambda (pre-action) - (let ((get-start-end-text IS-get-start-end-text) - (start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline yycolumn yyoffset) - (let ((yytext (get-start-end-text))) - (start-go-to-end) - (action yytext yyline yycolumn yyoffset)))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-yytext - (lambda (pre-action) - (cond ((eq? counters-type 'none) - (prepare-action-yytext-none pre-action)) - ((eq? counters-type 'line) - (prepare-action-yytext-line pre-action)) - ((eq? counters-type 'all) - (prepare-action-yytext-all pre-action))))) - (prepare-action-no-yytext-none - (lambda (pre-action) - (let ((start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda () - (start-go-to-end) - (action))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-no-yytext-line - (lambda (pre-action) - (let ((start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline) - (start-go-to-end) - (action yyline))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-no-yytext-all - (lambda (pre-action) - (let ((start-go-to-end IS-start-go-to-end) - (action #f)) - (let ((result - (lambda (yyline yycolumn yyoffset) - (start-go-to-end) - (action yyline yycolumn yyoffset))) - (hook - (lambda () - (set! action (set-action-statics pre-action))))) - (add-hook hook) - result)))) - (prepare-action-no-yytext - (lambda (pre-action) - (cond ((eq? counters-type 'none) - (prepare-action-no-yytext-none pre-action)) - ((eq? counters-type 'line) - (prepare-action-no-yytext-line pre-action)) - ((eq? counters-type 'all) - (prepare-action-no-yytext-all pre-action))))) - - ; Fabrique les fonctions de dispatch - (prepare-dispatch-err - (lambda (leaf) - (lambda (c) - #f))) - (prepare-dispatch-number - (lambda (leaf) - (let ((state-function #f)) - (let ((result - (lambda (c) - state-function)) - (hook - (lambda () - (set! state-function (vector-ref states leaf))))) - (add-hook hook) - result)))) - (prepare-dispatch-leaf - (lambda (leaf) - (if (eq? leaf 'err) - (prepare-dispatch-err leaf) - (prepare-dispatch-number leaf)))) - (prepare-dispatch-< - (lambda (tree) - (let ((left-tree (list-ref tree 1)) - (right-tree (list-ref tree 2))) - (let ((bound (list-ref tree 0)) - (left-func (prepare-dispatch-tree left-tree)) - (right-func (prepare-dispatch-tree right-tree))) - (lambda (c) - (if (< c bound) - (left-func c) - (right-func c))))))) - (prepare-dispatch-= - (lambda (tree) - (let ((left-tree (list-ref tree 2)) - (right-tree (list-ref tree 3))) - (let ((bound (list-ref tree 1)) - (left-func (prepare-dispatch-tree left-tree)) - (right-func (prepare-dispatch-tree right-tree))) - (lambda (c) - (if (= c bound) - (left-func c) - (right-func c))))))) - (prepare-dispatch-tree - (lambda (tree) - (cond ((not (pair? tree)) - (prepare-dispatch-leaf tree)) - ((eq? (car tree) '=) - (prepare-dispatch-= tree)) - (else - (prepare-dispatch-< tree))))) - (prepare-dispatch - (lambda (tree) - (let ((dicho-func (prepare-dispatch-tree tree))) - (lambda (c) - (and c (dicho-func c)))))) - - ; Fabrique les fonctions de transition (read & go) et (abort) - (prepare-read-n-go - (lambda (tree) - (let ((dispatch-func (prepare-dispatch tree)) - (read-char IS-read-char)) - (lambda () - (dispatch-func (read-char)))))) - (prepare-abort - (lambda (tree) - (lambda () - #f))) - (prepare-transition - (lambda (tree) - (if (eq? tree 'err) - (prepare-abort tree) - (prepare-read-n-go tree)))) - - ; Fabrique les fonctions d'etats ([set-end] & trans) - (prepare-state-no-acc - (lambda (s r1 r2) - (let ((trans-func (prepare-transition (vector-ref trees-v s)))) - (lambda (action) - (let ((next-state (trans-func))) - (if next-state - (next-state action) - action)))))) - (prepare-state-yes-no - (lambda (s r1 r2) - (let ((peek-char IS-peek-char) - (end-go-to-point IS-end-go-to-point) - (new-action1 #f) - (trans-func (prepare-transition (vector-ref trees-v s)))) - (let ((result - (lambda (action) - (let* ((c (peek-char)) - (new-action - (if (or (not c) (= c lexer-integer-newline)) - (begin - (end-go-to-point) - new-action1) - action)) - (next-state (trans-func))) - (if next-state - (next-state new-action) - new-action)))) - (hook - (lambda () - (set! new-action1 (vector-ref rules-actions r1))))) - (add-hook hook) - result)))) - (prepare-state-diff-acc - (lambda (s r1 r2) - (let ((end-go-to-point IS-end-go-to-point) - (peek-char IS-peek-char) - (new-action1 #f) - (new-action2 #f) - (trans-func (prepare-transition (vector-ref trees-v s)))) - (let ((result - (lambda (action) - (end-go-to-point) - (let* ((c (peek-char)) - (new-action - (if (or (not c) (= c lexer-integer-newline)) - new-action1 - new-action2)) - (next-state (trans-func))) - (if next-state - (next-state new-action) - new-action)))) - (hook - (lambda () - (set! new-action1 (vector-ref rules-actions r1)) - (set! new-action2 (vector-ref rules-actions r2))))) - (add-hook hook) - result)))) - (prepare-state-same-acc - (lambda (s r1 r2) - (let ((end-go-to-point IS-end-go-to-point) - (trans-func (prepare-transition (vector-ref trees-v s))) - (new-action #f)) - (let ((result - (lambda (action) - (end-go-to-point) - (let ((next-state (trans-func))) - (if next-state - (next-state new-action) - new-action)))) - (hook - (lambda () - (set! new-action (vector-ref rules-actions r1))))) - (add-hook hook) - result)))) - (prepare-state - (lambda (s) - (let* ((acc (vector-ref acc-v s)) - (r1 (car acc)) - (r2 (cdr acc))) - (cond ((not r1) (prepare-state-no-acc s r1 r2)) - ((not r2) (prepare-state-yes-no s r1 r2)) - ((< r1 r2) (prepare-state-diff-acc s r1 r2)) - (else (prepare-state-same-acc s r1 r2)))))) - - ; Fabrique la fonction de lancement du lexage a l'etat de depart - (prepare-start-same - (lambda (s1 s2) - (let ((peek-char IS-peek-char) - (eof-action #f) - (start-state #f) - (error-action #f)) - (let ((result - (lambda () - (if (not (peek-char)) - eof-action - (start-state error-action)))) - (hook - (lambda () - (set! eof-action <<EOF>>-action) - (set! start-state (vector-ref states s1)) - (set! error-action <<ERROR>>-action)))) - (add-hook hook) - result)))) - (prepare-start-diff - (lambda (s1 s2) - (let ((peek-char IS-peek-char) - (eof-action #f) - (peek-left-context IS-peek-left-context) - (start-state1 #f) - (start-state2 #f) - (error-action #f)) - (let ((result - (lambda () - (cond ((not (peek-char)) - eof-action) - ((= (peek-left-context) lexer-integer-newline) - (start-state1 error-action)) - (else - (start-state2 error-action))))) - (hook - (lambda () - (set! eof-action <<EOF>>-action) - (set! start-state1 (vector-ref states s1)) - (set! start-state2 (vector-ref states s2)) - (set! error-action <<ERROR>>-action)))) - (add-hook hook) - result)))) - (prepare-start - (lambda () - (let ((s1 table-nl-start) - (s2 table-no-nl-start)) - (if (= s1 s2) - (prepare-start-same s1 s2) - (prepare-start-diff s1 s2))))) - - ; Fabrique la fonction principale - (prepare-lexer-none - (lambda () - (let ((init-lexeme IS-init-lexeme) - (start-func (prepare-start))) - (lambda () - (init-lexeme) - ((start-func)))))) - (prepare-lexer-line - (lambda () - (let ((init-lexeme IS-init-lexeme) - (get-start-line IS-get-start-line) - (start-func (prepare-start))) - (lambda () - (init-lexeme) - (let ((yyline (get-start-line))) - ((start-func) yyline)))))) - (prepare-lexer-all - (lambda () - (let ((init-lexeme IS-init-lexeme) - (get-start-line IS-get-start-line) - (get-start-column IS-get-start-column) - (get-start-offset IS-get-start-offset) - (start-func (prepare-start))) - (lambda () - (init-lexeme) - (let ((yyline (get-start-line)) - (yycolumn (get-start-column)) - (yyoffset (get-start-offset))) - ((start-func) yyline yycolumn yyoffset)))))) - (prepare-lexer - (lambda () - (cond ((eq? counters-type 'none) (prepare-lexer-none)) - ((eq? counters-type 'line) (prepare-lexer-line)) - ((eq? counters-type 'all) (prepare-lexer-all)))))) - - ; Calculer la valeur de <<EOF>>-action et de <<ERROR>>-action - (set! <<EOF>>-action (prepare-special-action <<EOF>>-pre-action)) - (set! <<ERROR>>-action (prepare-special-action <<ERROR>>-pre-action)) - - ; Calculer la valeur de rules-actions - (let* ((len (quotient (vector-length rules-pre-actions) 2)) - (v (make-vector len))) - (let loop ((r (- len 1))) - (if (< r 0) - (set! rules-actions v) - (let* ((yytext? (vector-ref rules-pre-actions (* 2 r))) - (pre-action (vector-ref rules-pre-actions (+ (* 2 r) 1))) - (action (if yytext? - (prepare-action-yytext pre-action) - (prepare-action-no-yytext pre-action)))) - (vector-set! v r action) - (loop (- r 1)))))) - - ; Calculer la valeur de states - (let* ((len (vector-length trees-v)) - (v (make-vector len))) - (let loop ((s (- len 1))) - (if (< s 0) - (set! states v) - (begin - (vector-set! v s (prepare-state s)) - (loop (- s 1)))))) - - ; Calculer la valeur de final-lexer - (set! final-lexer (prepare-lexer)) - - ; Executer les hooks - (apply-hooks) - - ; Resultat - final-lexer))) - -; Fabrication de lexer a partir de listes de caracteres taggees -(define lexer-make-char-lexer - (let* ((char->class - (lambda (c) - (let ((n (char->integer c))) - (list (cons n n))))) - (merge-sort - (lambda (l combine zero-elt) - (if (null? l) - zero-elt - (let loop1 ((l l)) - (if (null? (cdr l)) - (car l) - (loop1 - (let loop2 ((l l)) - (cond ((null? l) - l) - ((null? (cdr l)) - l) - (else - (cons (combine (car l) (cadr l)) - (loop2 (cddr l)))))))))))) - (finite-class-union - (lambda (c1 c2) - (let loop ((c1 c1) (c2 c2) (u '())) - (if (null? c1) - (if (null? c2) - (reverse u) - (loop c1 (cdr c2) (cons (car c2) u))) - (if (null? c2) - (loop (cdr c1) c2 (cons (car c1) u)) - (let* ((r1 (car c1)) - (r2 (car c2)) - (r1start (car r1)) - (r1end (cdr r1)) - (r2start (car r2)) - (r2end (cdr r2))) - (if (<= r1start r2start) - (cond ((< (+ r1end 1) r2start) - (loop (cdr c1) c2 (cons r1 u))) - ((<= r1end r2end) - (loop (cdr c1) - (cons (cons r1start r2end) (cdr c2)) - u)) - (else - (loop c1 (cdr c2) u))) - (cond ((> r1start (+ r2end 1)) - (loop c1 (cdr c2) (cons r2 u))) - ((>= r1end r2end) - (loop (cons (cons r2start r1end) (cdr c1)) - (cdr c2) - u)) - (else - (loop (cdr c1) c2 u)))))))))) - (char-list->class - (lambda (cl) - (let ((classes (map char->class cl))) - (merge-sort classes finite-class-union '())))) - (class-< - (lambda (b1 b2) - (cond ((eq? b1 'inf+) #f) - ((eq? b2 'inf-) #f) - ((eq? b1 'inf-) #t) - ((eq? b2 'inf+) #t) - (else (< b1 b2))))) - (finite-class-compl - (lambda (c) - (let loop ((c c) (start 'inf-)) - (if (null? c) - (list (cons start 'inf+)) - (let* ((r (car c)) - (rstart (car r)) - (rend (cdr r))) - (if (class-< start rstart) - (cons (cons start (- rstart 1)) - (loop c rstart)) - (loop (cdr c) (+ rend 1)))))))) - (tagged-chars->class - (lambda (tcl) - (let* ((inverse? (car tcl)) - (cl (cdr tcl)) - (class-tmp (char-list->class cl))) - (if inverse? (finite-class-compl class-tmp) class-tmp)))) - (charc->arc - (lambda (charc) - (let* ((tcl (car charc)) - (dest (cdr charc)) - (class (tagged-chars->class tcl))) - (cons class dest)))) - (arc->sharcs - (lambda (arc) - (let* ((range-l (car arc)) - (dest (cdr arc)) - (op (lambda (range) (cons range dest)))) - (map op range-l)))) - (class-<= - (lambda (b1 b2) - (cond ((eq? b1 'inf-) #t) - ((eq? b2 'inf+) #t) - ((eq? b1 'inf+) #f) - ((eq? b2 'inf-) #f) - (else (<= b1 b2))))) - (sharc-<= - (lambda (sharc1 sharc2) - (class-<= (caar sharc1) (caar sharc2)))) - (merge-sharcs - (lambda (l1 l2) - (let loop ((l1 l1) (l2 l2)) - (cond ((null? l1) - l2) - ((null? l2) - l1) - (else - (let ((sharc1 (car l1)) - (sharc2 (car l2))) - (if (sharc-<= sharc1 sharc2) - (cons sharc1 (loop (cdr l1) l2)) - (cons sharc2 (loop l1 (cdr l2)))))))))) - (class-= eqv?) - (fill-error - (lambda (sharcs) - (let loop ((sharcs sharcs) (start 'inf-)) - (cond ((class-= start 'inf+) - '()) - ((null? sharcs) - (cons (cons (cons start 'inf+) 'err) - (loop sharcs 'inf+))) - (else - (let* ((sharc (car sharcs)) - (h (caar sharc)) - (t (cdar sharc))) - (if (class-< start h) - (cons (cons (cons start (- h 1)) 'err) - (loop sharcs h)) - (cons sharc (loop (cdr sharcs) - (if (class-= t 'inf+) - 'inf+ - (+ t 1))))))))))) - (charcs->tree - (lambda (charcs) - (let* ((op (lambda (charc) (arc->sharcs (charc->arc charc)))) - (sharcs-l (map op charcs)) - (sorted-sharcs (merge-sort sharcs-l merge-sharcs '())) - (full-sharcs (fill-error sorted-sharcs)) - (op (lambda (sharc) (cons (caar sharc) (cdr sharc)))) - (table (list->vector (map op full-sharcs)))) - (let loop ((left 0) (right (- (vector-length table) 1))) - (if (= left right) - (cdr (vector-ref table left)) - (let ((mid (quotient (+ left right 1) 2))) - (if (and (= (+ left 2) right) - (= (+ (car (vector-ref table mid)) 1) - (car (vector-ref table right))) - (eqv? (cdr (vector-ref table left)) - (cdr (vector-ref table right)))) - (list '= - (car (vector-ref table mid)) - (cdr (vector-ref table mid)) - (cdr (vector-ref table left))) - (list (car (vector-ref table mid)) - (loop left (- mid 1)) - (loop mid right)))))))))) - (lambda (tables IS) - (let ((counters (vector-ref tables 0)) - (<<EOF>>-action (vector-ref tables 1)) - (<<ERROR>>-action (vector-ref tables 2)) - (rules-actions (vector-ref tables 3)) - (nl-start (vector-ref tables 5)) - (no-nl-start (vector-ref tables 6)) - (charcs-v (vector-ref tables 7)) - (acc-v (vector-ref tables 8))) - (let* ((len (vector-length charcs-v)) - (v (make-vector len))) - (let loop ((i (- len 1))) - (if (>= i 0) - (begin - (vector-set! v i (charcs->tree (vector-ref charcs-v i))) - (loop (- i 1))) - (lexer-make-tree-lexer - (vector counters - <<EOF>>-action - <<ERROR>>-action - rules-actions - 'decision-trees - nl-start - no-nl-start - v - acc-v) - IS)))))))) - -; Fabrication d'un lexer a partir de code pre-genere -(define lexer-make-code-lexer - (lambda (tables IS) - (let ((<<EOF>>-pre-action (vector-ref tables 1)) - (<<ERROR>>-pre-action (vector-ref tables 2)) - (rules-pre-action (vector-ref tables 3)) - (code (vector-ref tables 5))) - (code <<EOF>>-pre-action <<ERROR>>-pre-action rules-pre-action IS)))) - -(define lexer-make-lexer - (lambda (tables IS) - (let ((automaton-type (vector-ref tables 4))) - (cond ((eq? automaton-type 'decision-trees) - (lexer-make-tree-lexer tables IS)) - ((eq? automaton-type 'tagged-chars-lists) - (lexer-make-char-lexer tables IS)) - ((eq? automaton-type 'code) - (lexer-make-code-lexer tables IS)))))) -" port))) - -; Module main.scm. -; Copyright (C) 1997 Danny Dube', Universite' de Montre'al. -; All rights reserved. -; SILex 1.0. - -; -; Gestion d'erreurs -; - -(define lex-exit-continuation #f) -(define lex-unwind-protect-list '()) -(define lex-error-filename #f) - -(define lex-unwind-protect - (lambda (proc) - (set! lex-unwind-protect-list (cons proc lex-unwind-protect-list)))) - -(define lex-error - (lambda (line column . l) - (let* ((linestr (if line (number->string line) #f)) - (colstr (if column (number->string column) #f)) - (namelen (string-length lex-error-filename)) - (linelen (if line (string-length linestr) -1)) - (collen (if column (string-length colstr) -1)) - (totallen (+ namelen 1 linelen 1 collen 2))) - (display "Lex error:") - (newline) - (display lex-error-filename) - (if line - (begin - (display ":") - (display linestr))) - (if column - (begin - (display ":") - (display colstr))) - (display ": ") - (let loop ((l l)) - (if (null? l) - (newline) - (let ((item (car l))) - (display item) - (if (equal? '#\newline item) - (let loop2 ((i totallen)) - (if (> i 0) - (begin - (display #\space) - (loop2 (- i 1)))))) - (loop (cdr l))))) - (newline) - (let loop ((l lex-unwind-protect-list)) - (if (pair? l) - (begin - ((car l)) - (loop (cdr l))))) - (lex-exit-continuation #f)))) - - - - -; -; Decoupage des arguments -; - -(define lex-recognized-args - '(complete-driver? - filein - table-name - fileout - counters - portable - code - pp)) - -(define lex-valued-args - '(complete-driver? - filein - table-name - fileout - counters)) - -(define lex-parse-args - (lambda (args) - (let loop ((args args)) - (if (null? args) - '() - (let ((sym (car args))) - (cond ((not (symbol? sym)) - (lex-error #f #f "bad option list.")) - ((not (memq sym lex-recognized-args)) - (lex-error #f #f "unrecognized option \"" sym "\".")) - ((not (memq sym lex-valued-args)) - (cons (cons sym '()) (loop (cdr args)))) - ((null? (cdr args)) - (lex-error #f #f "the value of \"" sym "\" not specified.")) - (else - (cons (cons sym (cadr args)) (loop (cddr args)))))))))) - - - - -; -; Differentes etapes de la fabrication de l'automate -; - -(define lex1 - (lambda (filein) -; (display "lex1: ") (write (get-internal-run-time)) (newline) - (parser filein))) - -(define lex2 - (lambda (filein) - (let* ((result (lex1 filein)) - (<<EOF>>-action (car result)) - (<<ERROR>>-action (cadr result)) - (rules (cddr result))) -; (display "lex2: ") (write (get-internal-run-time)) (newline) - (append (list <<EOF>>-action <<ERROR>>-action rules) - (re2nfa rules))))) - -(define lex3 - (lambda (filein) - (let* ((result (lex2 filein)) - (<<EOF>>-action (list-ref result 0)) - (<<ERROR>>-action (list-ref result 1)) - (rules (list-ref result 2)) - (nl-start (list-ref result 3)) - (no-nl-start (list-ref result 4)) - (arcs (list-ref result 5)) - (acc (list-ref result 6))) -; (display "lex3: ") (write (get-internal-run-time)) (newline) - (append (list <<EOF>>-action <<ERROR>>-action rules) - (noeps nl-start no-nl-start arcs acc))))) - -(define lex4 - (lambda (filein) - (let* ((result (lex3 filein)) - (<<EOF>>-action (list-ref result 0)) - (<<ERROR>>-action (list-ref result 1)) - (rules (list-ref result 2)) - (nl-start (list-ref result 3)) - (no-nl-start (list-ref result 4)) - (arcs (list-ref result 5)) - (acc (list-ref result 6))) -; (display "lex4: ") (write (get-internal-run-time)) (newline) - (append (list <<EOF>>-action <<ERROR>>-action rules) - (sweep nl-start no-nl-start arcs acc))))) - -(define lex5 - (lambda (filein) - (let* ((result (lex4 filein)) - (<<EOF>>-action (list-ref result 0)) - (<<ERROR>>-action (list-ref result 1)) - (rules (list-ref result 2)) - (nl-start (list-ref result 3)) - (no-nl-start (list-ref result 4)) - (arcs (list-ref result 5)) - (acc (list-ref result 6))) -; (display "lex5: ") (write (get-internal-run-time)) (newline) - (append (list <<EOF>>-action <<ERROR>>-action rules) - (nfa2dfa nl-start no-nl-start arcs acc))))) - -(define lex6 - (lambda (args-alist) - (let* ((filein (cdr (assq 'filein args-alist))) - (result (lex5 filein)) - (<<EOF>>-action (list-ref result 0)) - (<<ERROR>>-action (list-ref result 1)) - (rules (list-ref result 2)) - (nl-start (list-ref result 3)) - (no-nl-start (list-ref result 4)) - (arcs (list-ref result 5)) - (acc (list-ref result 6))) -; (display "lex6: ") (write (get-internal-run-time)) (newline) - (prep-set-rules-yytext? rules) - (output args-alist - <<EOF>>-action <<ERROR>>-action - rules nl-start no-nl-start arcs acc) - #t))) - -(define lex7 - (lambda (args) - (call-with-current-continuation - (lambda (exit) - (set! lex-exit-continuation exit) - (set! lex-unwind-protect-list '()) - (set! lex-error-filename (cadr (memq 'filein args))) - (let* ((args-alist (lex-parse-args args)) - (result (lex6 args-alist))) -; (display "lex7: ") (write (get-internal-run-time)) (newline) - result))))) - - - - -; -; Fonctions principales -; - -(define lex - (lambda (filein fileout . options) - (lex7 (append (list 'complete-driver? #t - 'filein filein - 'table-name "lexer-default-table" - 'fileout fileout) - options)))) - -(define lex-tables - (lambda (filein table-name fileout . options) - (lex7 (append (list 'complete-driver? #f - 'filein filein - 'table-name table-name - 'fileout fileout) - options)))) - -)Trap