home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / compiler / machines / C / cout.scm < prev    next >
Text File  |  1999-01-02  |  31KB  |  1,019 lines

  1. #| -*-Scheme-*-
  2.  
  3. $Id: cout.scm,v 1.21 1999/01/02 06:06:43 cph Exp $
  4.  
  5. Copyright (c) 1992-1999 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. |#
  21.  
  22. ;;;; C-output fake assembler and linker
  23. ;; package: (compiler lap-syntaxer)
  24.  
  25. (declare (usual-integrations))
  26.  
  27. (define *C-procedure-name* 'DEFAULT)
  28. (define *disable-timestamps?* false)
  29.  
  30. (define (stringify suffix initial-label lap-code info-output-pathname)
  31.   (define (stringify-object x)
  32.     (cond ((string? x)
  33.        x)
  34.       ((symbol? x)
  35.        (%symbol->string x))
  36.       ((number? x)
  37.        (number->string x))
  38.       (else
  39.        (error "stringify: Unknown frob" x))))
  40.  
  41.   (define (make-time-stamp)
  42.     (if *disable-timestamps?*
  43.     "_timestamp"
  44.     (let ((time (get-decoded-time)))
  45.       (string-append
  46.        "_"
  47.        (number->string (decoded-time/second time)) "_"
  48.        (number->string (decoded-time/minute time)) "_"
  49.        (number->string (decoded-time/hour time)) "_"
  50.        (number->string (decoded-time/day time)) "_"
  51.        (number->string (decoded-time/month time)) "_"
  52.        (number->string (decoded-time/year time))))))
  53.  
  54.   (define (->variable-declarations vars)
  55.     (if (null? vars)
  56.     (list "")
  57.     `("\tSCHEME_OBJECT\n\t  "
  58.       ,(car vars)
  59.       ,@(append-map (lambda (var)
  60.               (list ",\n\t  " var))
  61.             (cdr vars))
  62.       ";\n")))
  63.  
  64.   (define (choose-proc-name default midfix time-stamp)
  65.     (let ((path (and info-output-pathname
  66.              (merge-pathnames
  67.               (if (pair? info-output-pathname)
  68.               (car info-output-pathname)
  69.               info-output-pathname)))))
  70.     
  71.       (cond ((not *C-procedure-name*)
  72.          (string-append default suffix time-stamp))
  73.         ((not (eq? *C-procedure-name* 'DEFAULT))
  74.          (string-append *C-procedure-name*
  75.                 midfix
  76.                 suffix))
  77.         ((not path)
  78.          (string-append default suffix time-stamp))
  79.         ((or (string-null? suffix) *disable-timestamps?*)
  80.          (let ((dir (pathname-directory path)))
  81.            (string-append (if (or (not dir) (null? dir))
  82.                   default
  83.                   (canonicalize-label-name
  84.                    (car (last-pair dir))))
  85.                   "_"
  86.                   (canonicalize-label-name (pathname-name path))
  87.                   midfix
  88.                   suffix)))
  89.         (else
  90.          (string-append (canonicalize-label-name (pathname-name path))
  91.                 "_"
  92.                 default
  93.                 suffix
  94.                 time-stamp)))))
  95.  
  96.   (define (subroutine-information-1)
  97.     (cond ((eq? *invoke-interface* 'INFINITY)
  98.        (values (list "") (list "")))
  99.       ((< *invoke-interface* 5)
  100.        (values (list-tail (list
  101.                    "\ninvoke_interface_0:\n\tutlarg_1 = 0;\n"
  102.                    "\ninvoke_interface_1:\n\tutlarg_2 = 0;\n"
  103.                    "\ninvoke_interface_2:\n\tutlarg_3 = 0;\n"
  104.                    "\ninvoke_interface_3:\n\tutlarg_4 = 0;\n"
  105.                    "\ninvoke_interface_4:\n\t"
  106.                    "INVOKE_INTERFACE_CODE ();\n")
  107.                   *invoke-interface*)
  108.            (list "\tint utlarg_code;\n"
  109.              "\tlong utlarg_1, utlarg_2, utlarg_3, utlarg_4;\n")))
  110.       (else
  111.        (error "subroutine-information-1: Utilities take at most 4 args"
  112.           *invoke-interface*))))
  113.  
  114.   (define (subroutine-information-2)
  115.     (if *used-invoke-primitive*
  116.     (values (list "\ninvoke_primitive:\n\t"
  117.               "INVOKE_PRIMITIVE_CODE ();")
  118.         (list "\tSCHEME_OBJECT primitive;\n"
  119.               "\tlong primitive_nargs;\n"))
  120.     (values (list "") (list ""))))
  121.  
  122.   (define (subroutine-information)
  123.     (with-values subroutine-information-1
  124.       (lambda (code-1 vars-1)
  125.     (with-values subroutine-information-2
  126.       (lambda (code-2 vars-2)
  127.         (values (append code-1 code-2)
  128.             (append vars-1 vars-2)))))))
  129.  
  130.   (if *purification-root-object*
  131.       (define-object "PURIFICATION_ROOT"
  132.     (if (vector? (cdr *purification-root-object*))
  133.         *purification-root-object*
  134.         (cons (car *purification-root-object*)
  135.           (list->vector
  136.            (reverse (cdr *purification-root-object*)))))))
  137.  
  138.   (define-object (special-label/debugging)
  139.     (let frob ((obj info-output-pathname))
  140.       (cond ((pathname? obj)
  141.          (->namestring obj))
  142.         ((pair? obj)
  143.          (cons (frob (car obj))
  144.            (frob (cdr obj))))
  145.         (else
  146.          obj))))
  147.  
  148.   (define-object (special-label/environment) unspecific)
  149.  
  150.   (let ((n 1)                ; First word is vector header
  151.     (initial-offset (label->offset initial-label)))
  152.     (with-values (lambda () (handle-labels n))
  153.       (lambda (n ntags
  154.            label-defines label-dispatch
  155.            label-block-initialization symbol-table)
  156.     (with-values (lambda () (handle-free-refs-and-sets n))
  157.       (lambda (n free-defines free-block-initialization free-symbols)
  158.         (with-values (lambda () (handle-objects n))
  159.           (lambda (n decl-code decl-data
  160.              xtra-procs object-prefix
  161.              object-defines temp-vars
  162.              object-block-initialization)
  163.         (let* ((time-stamp (make-time-stamp))
  164.                (code-name
  165.             (choose-proc-name "code" "" time-stamp))
  166.                (data-name
  167.             (choose-proc-name "data" "_data" time-stamp))
  168.                (decl-code-name (string-append "decl_" code-name))
  169.                (decl-data-name (string-append "decl_" data-name)))
  170.           (with-values subroutine-information
  171.             (lambda (extra-code extra-variables)
  172.               (values
  173.                code-name
  174.                data-name
  175.                ntags
  176.                (cons* (cons (special-label/environment)
  177.                     (-1+ n))
  178.                   (cons (special-label/debugging)
  179.                     (- n 2))
  180.                   (append free-symbols symbol-table))
  181.                (list-of-strings->string
  182.             (map (lambda (x)
  183.                    (list-of-strings->string x)) 
  184.                  (list
  185.                   (if (string-null? suffix)
  186.                   (append
  187.                    (file-prefix)
  188.                    (list
  189.                     "#ifndef WANT_ONLY_DATA\n"
  190.                     ;; This must be a single line!
  191.                     "DECLARE_COMPILED_CODE (\"" code-name
  192.                     "\", " (number->string ntags)
  193.                     ", " decl-code-name
  194.                     ", " code-name ")\n"
  195.                     "#endif /* WANT_ONLY_DATA */\n\n"
  196.                     "#ifndef WANT_ONLY_CODE\n"
  197.                     ;; This must be a single line!
  198.                     "DECLARE_COMPILED_DATA (\"" code-name
  199.                     "\", " decl-data-name
  200.                     ", " data-name ")\n"
  201.                     "#endif /* WANT_ONLY_CODE */\n\n"
  202.                     "DECLARE_DYNAMIC_INITIALIZATION (\""
  203.                     code-name "\")\n\n"))
  204.                   '())
  205.                   xtra-procs
  206.  
  207.                   (if (string-null? suffix)
  208.                   (append
  209.                    (list "#ifndef WANT_ONLY_DATA\n")
  210.                    (list
  211.                     "int\n"
  212.                     "DEFUN_VOID (" decl-code-name ")\n{\n\t")
  213.                    decl-code
  214.                    (list "return (0);\n}\n"
  215.                      "#endif /* WANT_ONLY_DATA */\n\n")
  216.                    (list "#ifndef WANT_ONLY_CODE\n")
  217.                    (list
  218.                     "int\n"
  219.                     "DEFUN_VOID (" decl-data-name ")\n{\n\t")
  220.                    decl-data
  221.                    (list "return (0);\n}\n"
  222.                      "#endif /* WANT_ONLY_CODE */\n\n"))
  223.                   '())
  224.  
  225.                   label-defines
  226.                   object-defines
  227.                   free-defines
  228.                   (list "\n")
  229.               
  230.                   (list "#ifndef WANT_ONLY_CODE\n")
  231.                   (let ((header (data-function-header data-name)))
  232.                 (if (string-null? suffix)
  233.                     header
  234.                     (cons "static " header)))
  235.                   (list "\tSCHEME_OBJECT object"
  236.                     " = (ALLOCATE_VECTOR ("
  237.                     (number->string (- n 1))
  238.                     "L));\n"
  239.                     "\tSCHEME_OBJECT * current_block"
  240.                     " = (OBJECT_ADDRESS (object));\n")
  241.                   (->variable-declarations temp-vars)
  242.                   (list "\n\t")
  243.                   object-prefix
  244.                   label-block-initialization
  245.                   free-block-initialization
  246.                   object-block-initialization
  247.                   (list "\n\treturn (¤t_block["
  248.                     (stringify-object initial-offset)
  249.                     "]);\n")
  250.                   (function-trailer data-name)
  251.                   (list "#endif /* WANT_ONLY_CODE */\n")
  252.                   (list "\n")
  253.  
  254.                   (list "#ifndef WANT_ONLY_DATA\n")
  255.                   (let ((header (code-function-header code-name)))
  256.                 (if (string-null? suffix)
  257.                     header
  258.                     (cons "static " header)))
  259.                   (function-decls)
  260.                   (register-declarations)
  261.                   extra-variables
  262.                   (list
  263.                    "\n\tgoto perform_dispatch;\n\n"
  264.                    "pop_return:\n\t"
  265.                    "Rpc = (OBJECT_ADDRESS (*Rsp++));\n\n"
  266.                    "perform_dispatch:\n\n\t"
  267.                    "switch ((* ((unsigned long *) Rpc))"
  268.                    " - dispatch_base)\n\t{")
  269.                   label-dispatch
  270.                   (list
  271.                    "\n\t  default:\n\t\t"
  272.                    "UNCACHE_VARIABLES ();\n\t\t"
  273.                    "return (Rpc);\n\t}\n\t")
  274.                   (map stringify-object lap-code)
  275.                   extra-code
  276.                   (function-trailer code-name)
  277.                   (list
  278.                    "#endif /* WANT_ONLY_DATA */\n"))))))))))))))))
  279.  
  280. (define-integrable (list-of-strings->string strings)
  281.   (apply string-append strings))
  282.  
  283. (define-integrable (%symbol->string sym)
  284.   (system-pair-car sym))
  285.  
  286. (define (file-prefix)
  287.   (let ((time (get-decoded-time)))
  288.     (list "/* Emacs: this is properly parenthesized -*- C -*- code.\n"
  289.       "   Thank God it was generated by a machine.\n"
  290.       " */\n\n"
  291.       "/* C code produced\n   "
  292.       (decoded-time/date-string time)
  293.       " at "
  294.       (decoded-time/time-string time)
  295.       "\n   by Liar version "
  296.       (or (get-subsystem-version-string "liar") "?.?")
  297.       ".\n */\n\n"
  298.       "#include \"liarc.h\"\n\n")))
  299.  
  300. (define (code-function-header name)
  301.   (list "SCHEME_OBJECT *\n"
  302.     "DEFUN (" name ", (Rpc, dispatch_base),\n\t"
  303.     "SCHEME_OBJECT * Rpc AND unsigned long dispatch_base)\n"
  304.     "{\n"))
  305.  
  306. (define (data-function-header name)
  307.   (list "SCHEME_OBJECT *\n"
  308.     "DEFUN (" name ", (dispatch_base), unsigned long dispatch_base)\n"
  309.     "{\n"))
  310.  
  311. (define (function-decls)
  312.   (list
  313.    "\tREGISTER SCHEME_OBJECT * current_block;\n"
  314.    "\tSCHEME_OBJECT * Rdl;\n"
  315.    "\tDECLARE_VARIABLES ();\n"))
  316.  
  317. (define (function-trailer name)
  318.   (list "\n} /* End of " name ". */\n"))
  319.  
  320. (define (make-define-statement symbol val)
  321.   (string-append "#define " (if (symbol? symbol)
  322.                 (symbol->string symbol)
  323.                 symbol)
  324.          " "
  325.          (if (number? val)
  326.              (number->string val)
  327.              val)
  328.          "\n"))
  329.  
  330. ;;;; Object constructors
  331.  
  332. (define new-variables)
  333. (define *subblocks*)
  334. (define num)
  335.  
  336. (define (generate-variable-name)
  337.   (set! new-variables
  338.     (cons (string-append "tmpObj" (number->string num))
  339.           new-variables))
  340.   (set! num (1+ num))
  341.   (car new-variables))
  342.  
  343. (define-integrable (table/find table value)
  344.   ;; assv ?
  345.   (assq value table))
  346.  
  347. (define-integrable (guaranteed-fixnum? value)
  348.   (and (exact-integer? value)
  349.        (<= signed-fixnum/lower-limit value)
  350.        (< value signed-fixnum/upper-limit)))
  351.  
  352. (define-integrable (guaranteed-long? value)
  353.   (and (exact-integer? value)
  354.        (<= guaranteed-long/lower-limit value)
  355.        (< value guaranteed-long/upper-limit)))
  356.  
  357. (define trivial-objects
  358.   (list #f #t '() unspecific))
  359.  
  360. (define (trivial? object)
  361.   (or (memq object trivial-objects)
  362.       (guaranteed-fixnum? object)))
  363.  
  364. (define *depth-limit* 2)
  365.  
  366. (define (name-if-complicated node depth)
  367.   (cond ((fake-compiled-block? node)
  368.      (let ((name (fake-block/name node)))
  369.        (set! new-variables (cons name new-variables))
  370.        name))
  371.     ((or (%record? node)
  372.          (vector? node)
  373.          (> depth *depth-limit*))
  374.      (generate-variable-name))
  375.     (else
  376.      false)))  
  377.  
  378. (define (build-table nodes)
  379.   (map cdr
  380.        (sort (sort/enumerate
  381.           (list-transform-positive
  382.           (let loop ((nodes nodes)
  383.                  (table '()))
  384.             (if (null? nodes)
  385.             table
  386.             (loop (cdr nodes)
  387.                   (insert-in-table (car nodes)
  388.                            0
  389.                            table))))
  390.         (lambda (pair)
  391.           (cdr pair))))
  392.          (lambda (entry1 entry2)
  393.            (let ((obj1 (cadr entry1))
  394.              (obj2 (cadr entry2)))
  395.          (if (not (fake-compiled-block? obj2))
  396.              (or (fake-compiled-block? obj1)
  397.              (< (car entry1) (car entry2)))
  398.              (and (fake-compiled-block? obj1)
  399.               (< (fake-block/index obj1)
  400.                  (fake-block/index obj2)))))))))
  401.  
  402. ;; Hack to make sort a stable sort
  403.  
  404. (define (sort/enumerate l)
  405.   (let loop ((l l) (n 0) (l* '()))
  406.     (if (null? l)
  407.     l*
  408.     (loop (cdr l)
  409.           (1+ n)
  410.           (cons (cons n (car l))
  411.             l*)))))
  412.  
  413. (define (insert-in-table node depth table)
  414.   (cond ((trivial? node)
  415.      table)
  416.     ((table/find table node)
  417.      => (lambda (pair)
  418.           (if (not (cdr pair))
  419.           (set-cdr! pair (generate-variable-name)))
  420.           table))
  421.     (else
  422.      (let* ((name (name-if-complicated node depth))
  423.         (depth* (if name 1 (1+ depth)))
  424.         (table (cons (cons node name) table)))
  425.  
  426.        (define-integrable (do-vector-like node vlength vref)
  427.          (let loop ((table table)
  428.             (i (vlength node)))
  429.            (if (zero? i)
  430.            table
  431.            (let ((i-1 (-1+ i)))
  432.              (loop (insert-in-table (vref node i-1)
  433.                         depth*
  434.                         table)
  435.                i-1)))))
  436.          
  437.        (cond ((pair? node)
  438.           ;; Special treatment on the CDR because of RCONSM.
  439.           (insert-in-table
  440.            (car node)
  441.            depth*
  442.            (insert-in-table (cdr node)
  443.                     (if name 1 depth)
  444.                     table)))
  445.          ((vector? node)
  446.           (do-vector-like node vector-length vector-ref))
  447.          ((or (fake-compiled-procedure? node)
  448.               (fake-compiled-block? node))
  449.           table)
  450.          ((%record? node)
  451.           (do-vector-like node %record-length %record-ref))
  452.          (else
  453.           ;; Atom
  454.           table))))))
  455.  
  456. (define (top-level-constructor object&name)
  457.   ;; (values prefix suffix)
  458.   (let ((name (cdr object&name))
  459.     (object (car object&name)))
  460.     (cond ((pair? object)
  461.        (values '()
  462.            (list name " = (cons (SHARP_F, SHARP_F));\n\t")))
  463.       ((fake-compiled-block? object)
  464.        (set! *subblocks* (cons object *subblocks*))
  465.        (values (list name " = (initialize_subblock (\""
  466.              (fake-block/c-proc object)
  467.              "\"));\n\t")
  468.            '()))
  469.       ((fake-compiled-procedure? object)
  470.        (values '()
  471.            (list name " = "
  472.              (compiled-procedure-constructor
  473.               object)
  474.              ";\n\t")))
  475.       ((vector? object)
  476.        (values '()
  477.            (list name " = (ALLOCATE_VECTOR ("
  478.              (number->string (vector-length object))
  479.              "));\n\t")))
  480.       ((%record? object)
  481.        (values '()
  482.            (list name " = (ALLOCATE_RECORD ("
  483.              (number->string (%record-length object))
  484.              "));\n\t")))
  485.       (else
  486.        (values '()
  487.            (list name "\n\t  = "
  488.              (->simple-C-object object)
  489.              ";\n\t"))))))
  490.  
  491. (define (top-level-updator object&name table)
  492.   (let ((name (cdr object&name))
  493.     (object (car object&name)))
  494.  
  495.     (define-integrable (do-vector-like object vlength vref vset-name)
  496.       (let loop ((i (vlength object))
  497.          (code '()))
  498.     (if (zero? i)
  499.         code
  500.         (let ((i-1 (- i 1)))
  501.           (loop i-1
  502.             `(,vset-name " (" ,name ", "
  503.                  ,(number->string i-1) ", "
  504.                  ,(constructor (vref object i-1)
  505.                            table)
  506.                  ");\n\t"
  507.                  ,@code))))))
  508.  
  509.     (cond ((pair? object)
  510.        (list "SET_PAIR_CAR (" name ", "
  511.          (constructor (car object) table) ");\n\t"
  512.          "SET_PAIR_CDR (" name ", "
  513.          (constructor (cdr object) table) ");\n\t"))
  514.       ((or (fake-compiled-block? object)
  515.            (fake-compiled-procedure? object))
  516.        '(""))
  517.       ((%record? object)
  518.        (do-vector-like object %record-length %record-ref "RECORD_SET"))
  519.       ((vector? object)
  520.        (do-vector-like object vector-length vector-ref "VECTOR_SET"))
  521.       (else
  522.        '("")))))
  523.  
  524. (define (constructor object table)
  525.   (let process ((object object))
  526.     (cond ((table/find table object) => cdr)
  527.       ((pair? object)
  528.        (cond ((or (not (pair? (cdr object)))
  529.               (table/find table (cdr object)))
  530.           (string-append "(CONS (" (process (car object)) ", "
  531.                  (process (cdr object)) "))"))
  532.          (else
  533.           (let loop ((npairs 0)
  534.                  (object object)
  535.                  (frobs '()))
  536.             (if (and (pair? object) (not (table/find table object)))
  537.             (loop (1+ npairs)
  538.                   (cdr object)
  539.                   (cons (car object) frobs))
  540.             ;; List is reversed to call rconsm
  541.             (string-append
  542.              "(RCONSM (" (number->string (1+ npairs))
  543.              (apply string-append
  544.                 (map (lambda (frob)
  545.                        (string-append ",\n\t\t"
  546.                               (process frob)))
  547.                      (cons object frobs)))
  548.              "))"))))))
  549.       ((fake-compiled-procedure? object)
  550.        (compiled-procedure-constructor object))
  551.       ((or (fake-compiled-block? object)
  552.            (vector? object)
  553.            (%record? object))
  554.        (error "constructor: Can't build directly"
  555.           object))
  556.       (else
  557.        (->simple-C-object object)))))
  558.  
  559. (define (compiled-procedure-constructor object)
  560.   (string-append "(CC_BLOCK_TO_ENTRY ("
  561.          (fake-procedure/block-name object)
  562.          ", "
  563.          (number->string
  564.           (fake-procedure/label-index object))
  565.          "))"))
  566.  
  567. (define (top-level-constructors table)
  568.   ;; (values prefix suffix)
  569.   ;; (append-map top-level-constructor table)
  570.   (let loop ((table (reverse table)) (prefix '()) (suffix '()))
  571.     (if (null? table)
  572.     (values prefix suffix)
  573.     (with-values (lambda () (top-level-constructor (car table)))
  574.       (lambda (prefix* suffix*)
  575.         (loop (cdr table)
  576.           (append prefix* prefix)
  577.           (append suffix* suffix)))))))
  578.  
  579. (define (->constructors names objects)
  580.   ;; (values prefix-code suffix-code)
  581.   (let* ((table (build-table objects)))
  582.     (with-values (lambda () (top-level-constructors table))
  583.       (lambda (prefix suffix)
  584.     (values prefix
  585.         (append suffix
  586.             (append-map (lambda (object&name)
  587.                       (top-level-updator object&name table))
  588.                     table)
  589.             (append-map
  590.              (lambda (name object)
  591.                (list (string-append name "\n\t  = "
  592.                         (constructor object table)
  593.                         ";\n\t")))
  594.              names
  595.              objects)))))))
  596.  
  597. (define (string-reverse string)
  598.   (let* ((len (string-length string))
  599.      (res (make-string len)))
  600.     (do ((i (fix:- len 1) (fix:- i 1))
  601.      (j 0 (fix:+ j 1)))
  602.     ((fix:= j len) res)
  603.       (string-set! res i (string-ref string j)))))
  604.  
  605. (define (->simple-C-object object)
  606.   (cond ((symbol? object)
  607.      (let ((name (symbol->string object)))
  608.        (string-append "(C_SYM_INTERN ("
  609.               (number->string (string-length name))
  610.               "L, \"" (C-quotify-string name) "\"))")))
  611.     ((string? object)
  612.      (string-append "(C_STRING_TO_SCHEME_STRING ("
  613.             (number->string (string-length object))
  614.             "L, \"" (C-quotify-string object) "\"))"))
  615.     ((number? object)
  616.      (let process ((number object))
  617.        (cond ((flo:flonum? number)
  618.           (string-append "(DOUBLE_TO_FLONUM ("
  619.                  (number->string number) "))"))
  620.          ((guaranteed-long? number)
  621.           (string-append "(LONG_TO_INTEGER ("
  622.                  (number->string number) "L))"))
  623.          ((exact-integer? number)
  624.           (let ((bignum-string
  625.              (number->string (if (negative? number)
  626.                          (- number)
  627.                          number)
  628.                      16)))
  629.             (string-append "(DIGIT_STRING_TO_INTEGER ("
  630.                    (if (negative? number)
  631.                        "true, "
  632.                        "false, ")
  633.                    (number->string
  634.                     (string-length bignum-string))
  635.                    "L, \"" bignum-string "\"))")))
  636.          ((and (exact? number) (rational? number))
  637.           (string-append "(MAKE_RATIO ("
  638.                  (process (numerator number))
  639.                  ", " (process (denominator number))
  640.                  "))"))
  641.          ((and (complex? number) (not (real? number)))
  642.           (string-append "(MAKE_COMPLEX ("
  643.                  (process (real-part number))
  644.                  ", " (process (imag-part number))
  645.                  "))"))
  646.          (else
  647.           (error "scheme->C-object: Unknown number" number)))))
  648.     ((eq? #f object)
  649.      "SHARP_F")
  650.     ((eq? #t object)
  651.      "SHARP_T")
  652.     ((primitive-procedure? object)
  653.      (let ((arity (primitive-procedure-arity object)))
  654.        (if (< arity -1)
  655.            (error "scheme->C-object: Unknown arity primitive" object)
  656.            (string-append "(MAKE_PRIMITIVE_PROCEDURE (\""
  657.                   (symbol->string
  658.                    (primitive-procedure-name object))
  659.                   "\", "
  660.                   (number->string arity)
  661.                   "))"))))
  662.     ((char? object)
  663.      (string-append "(MAKE_CHAR ("
  664.             (let ((bits (char-bits object)))
  665.               (if (zero? bits)
  666.                   "0"
  667.                   (string-append "0x" (number->string bits 16))))
  668.             ", ((unsigned) "
  669.             (C-quotify-char (make-char (char-code object) 0))
  670.             ")))"))
  671.     ((bit-string? object)
  672.      (let ((string (number->string (bit-string->unsigned-integer object)
  673.                        16)))
  674.        (string-append "(DIGIT_STRING_TO_BIT_STRING ("
  675.               (number->string (bit-string-length object)) "L, "
  676.               (number->string (string-length string)) "L, \""
  677.               (string-reverse string)
  678.               "\"))")))
  679.     ((null? object)
  680.      "NIL")
  681.     ((eq? object unspecific)
  682.      "UNSPECIFIC")
  683.     ((or (object-type? (ucode-type true) object)
  684.          (object-type? (ucode-type false) object))
  685.      ;; Random assorted objects, e.g.: #!rest, #!optional
  686.      (string-append "(MAKE_OBJECT ("
  687.             (if (object-type? (ucode-type true) object)
  688.                 "TC_TRUE"
  689.                 "TC_FALSE")
  690.             ", "
  691.             (number->string (object-datum object))
  692.             "L))"))
  693.     ;; Note: The following are here because of the Scode interpreter
  694.     ;; and the runtime system.
  695.     ;; They are not necessary for ordinary code.
  696.     ((interpreter-return-address? object)
  697.      (string-append "(MAKE_OBJECT (TC_RETURN_CODE, 0x"
  698.             (number->string (object-datum object) 16)
  699.             "))"))
  700.     (else
  701.      (error "->simple-C-object: unrecognized-type"
  702.         object))))
  703.  
  704. (define char-set:C-char-quoted
  705.   (char-set-union char-set:not-graphic (char-set #\\ #\')))
  706.  
  707. (define char-set:C-string-quoted
  708.   (char-set-union char-set:not-graphic (char-set #\\ #\")))
  709.  
  710. (define char-set:C-named-chars
  711.   (char-set #\\ #\" #\Tab #\BS  ;; #\' Scheme does not quote it in strings
  712.         ;; #\VT #\BEL    ;; Cannot depend on ANSI C
  713.         #\Linefeed #\Return #\Page))
  714.  
  715. (define (C-quotify-string string)
  716.   (let ((index (string-find-next-char-in-set string char-set:C-string-quoted)))
  717.     (if (not index)
  718.     string
  719.     (string-append
  720.      (substring string 0 index)
  721.      (C-quotify-string-char (string-ref string index))
  722.      (C-quotify-string
  723.       (substring string (1+ index) (string-length string)))))))
  724.  
  725. ;; The following two routines rely on the fact that Scheme and C
  726. ;; use the same quoting convention for the named characters when they
  727. ;; appear in strings.
  728.  
  729. (define (C-quotify-string-char char)
  730.   (cond ((char-set-member? char-set:C-named-chars char)
  731.      (let ((result (write-to-string (string char))))
  732.        (substring result 1 (-1+ (string-length result)))))
  733.     ((char=? char #\NUL)
  734.      "\\0")
  735.     (else
  736.      (string-append
  737.       "\\"
  738.       (let ((s (number->string (char-code char) 8)))
  739.         (if (< (string-length s) 3)
  740.         (string-append (make-string (- 3 (string-length s)) #\0)
  741.                    s)
  742.         s))))))
  743.  
  744. (define (C-quotify-char char)
  745.   (cond ((not (char-set-member? char-set:C-char-quoted char))
  746.      (string #\' char #\'))
  747.     ((char-set-member? char-set:C-named-chars char)
  748.      (string-append
  749.       "'"
  750.       (let ((s (write-to-string (make-string 1 char))))
  751.         (substring s 1 (-1+ (string-length s))))
  752.       "'"))
  753.     ((char=? char #\')
  754.      "'\\''")
  755.     ((char=? char #\NUL)
  756.      "'\\0'")
  757.     (else
  758.      (string-append
  759.       "'\\"
  760.       (let ((s (number->string (char-code char) 8)))
  761.         (if (< (string-length s) 3)
  762.         (string-append (make-string (- 3 (string-length s)) #\0)
  763.                    s)
  764.         s))
  765.       "'"))))
  766.  
  767. (define (handle-objects n)
  768.   ;; All the reverses produce the correct order in the output block.
  769.   ;; The incoming objects are reversed
  770.   ;; (environment, debugging label, purification root, etc.)
  771.   ;; (values new-n decl-code decl-data xtra-procs object-prefix
  772.   ;;         object-defines temp-vars object-block-initialization)
  773.  
  774.   (fluid-let ((new-variables '())
  775.           (*subblocks* '())
  776.           (num 0))
  777.  
  778.     (define (iter n table names defines objects)
  779.       (if (null? table)
  780.       (with-values
  781.           (lambda () (->constructors (reverse names)
  782.                      (reverse objects)))
  783.         (lambda (prefix suffix)
  784.           (values n
  785.               (map fake-block->code-decl *subblocks*)
  786.               (map fake-block->data-decl *subblocks*)
  787.               (append-map fake-block->c-code *subblocks*)
  788.               prefix
  789.               defines
  790.               new-variables
  791.               suffix)))
  792.       (let ((entry (car table)))
  793.         (iter (1+ n)
  794.           (cdr table)
  795.           (cons (string-append "current_block["
  796.                        (entry-label entry) "]")
  797.             names)
  798.           (cons (make-define-statement (entry-label entry) n)
  799.             defines)
  800.           (cons (entry-value entry)
  801.             objects)))))
  802.  
  803.     (iter n (reverse (table->list-of-entries objects)) '() '() '())))
  804.  
  805. (define (handle-free-refs-and-sets start-offset)
  806.   ;; process free-uuo-links free-references free-assignments global-uuo-links
  807.   ;; return n defines initialization
  808.  
  809.   (define (make-linkage-section-header start kind count)
  810.     (string-append "current_block[" (number->string start)
  811.            "L] = (MAKE_LINKER_HEADER (" kind
  812.            ", " (number->string count) "));\n\t"))
  813.  
  814.   (define (insert-symbol label symbol)
  815.     (let ((name (symbol->string symbol)))
  816.       (string-append "current_block[" label
  817.              "] = (C_SYM_INTERN ("
  818.              (number->string (string-length name))
  819.              ", \"" name "\"));\n\t")))
  820.  
  821.   (define (process-links start links kind)
  822.     (if (null? (cdr links))
  823.     (values start 0 '() '())
  824.     (let process ((count 0)
  825.               (links (cdr links))
  826.               (offset (+ start 1))
  827.               (defines '())
  828.               (inits '()))
  829.       (cond ((null? links)
  830.          (values offset
  831.              1
  832.              (reverse defines)
  833.              (cons (make-linkage-section-header start kind count)
  834.                    (reverse inits))))
  835.         ((null? (cdr (car links)))
  836.          (process count (cdr links) offset defines inits))
  837.         (else
  838.          (let ((entry (cadar links)))
  839.            (let ((name (caar links))
  840.              (arity (car entry))
  841.              (symbol (cdr entry)))
  842.              (process (1+ count)
  843.                   (cons (cons (caar links) (cddar links))
  844.                     (cdr links))
  845.                   (+ offset 2)
  846.                   (cons (make-define-statement symbol offset)
  847.                     defines)
  848.                   (cons (string-append
  849.                      (insert-symbol symbol name)
  850.                      "current_block["
  851.                      symbol
  852.                      " + 1] = ((SCHEME_OBJECT) ("
  853.                      (number->string arity) "));\n\t")
  854.                     inits)))))))))
  855.  
  856.   (define (process-table start table kind)
  857.     (define (iter n table defines inits)
  858.       (if (null? table)
  859.       (values n
  860.           1
  861.           (reverse defines)
  862.           (cons (make-linkage-section-header start kind
  863.                              (- n (+ start 1)))
  864.             (reverse inits)))
  865.       (let ((symbol (entry-label (car table))))
  866.         (iter (1+ n)
  867.           (cdr table)
  868.           (cons (make-define-statement symbol n)
  869.             defines)
  870.           (cons (insert-symbol symbol (entry-value (car table)))
  871.             inits)))))
  872.  
  873.     (if (null? table)
  874.     (values start 0 '() '())
  875.     (iter (1+ start) table '() '())))
  876.  
  877.   (with-values
  878.       (lambda () (process-links start-offset free-uuo-links
  879.                 "OPERATOR_LINKAGE_KIND"))
  880.     (lambda (offset uuos? uuodef uuoinit)
  881.       (with-values
  882.       (lambda ()
  883.         (process-table offset
  884.                (table->list-of-entries free-references)
  885.                "REFERENCE_LINKAGE_KIND"))
  886.     (lambda (offset refs? refdef refinit)
  887.       (with-values
  888.           (lambda ()
  889.         (process-table offset
  890.                    (table->list-of-entries free-assignments)
  891.                    "ASSIGNMENT_LINKAGE_KIND"))
  892.         (lambda (offset asss? assdef assinit)
  893.           (with-values
  894.           (lambda () (process-links offset global-uuo-links
  895.                         "GLOBAL_OPERATOR_LINKAGE_KIND"))
  896.         (lambda (offset glob? globdef globinit)
  897.           (let ((free-references-sections (+ uuos? refs? asss? glob?)))
  898.             (values
  899.              offset
  900.              (append
  901.               uuodef refdef assdef globdef
  902.               (list
  903.                (make-define-statement
  904.             (special-label/free-references)
  905.             start-offset)
  906.                (make-define-statement
  907.             (special-label/number-of-sections)
  908.             free-references-sections)))
  909.              (append uuoinit refinit assinit globinit)
  910.              (list (cons (special-label/free-references)
  911.                  start-offset)
  912.                (cons (special-label/number-of-sections)
  913.                  free-references-sections)))))))))))))
  914.  
  915. (define (handle-labels n)
  916.   (define (iter offset tagno labels label-defines
  917.         label-dispatch label-block-initialization
  918.         label-bindings)
  919.     (if (null? labels)
  920.     (values (- offset 1)
  921.         tagno
  922.         (reverse label-defines)
  923.         (reverse label-dispatch)
  924.         (cons (string-append
  925.                "current_block["
  926.                (number->string n)
  927.                "L] = (MAKE_OBJECT (TC_MANIFEST_NM_VECTOR, "
  928.                (number->string (- (- offset 1) (+ n 1)))
  929.                "));\n\t")
  930.               (reverse label-block-initialization))
  931.         label-bindings)
  932.     (let* ((label-data (car labels))
  933.            (a-symbol (or (symbol-1 label-data)
  934.                  (symbol-2 label-data))))
  935.       (iter (+ offset 2)
  936.         (+ tagno 1)
  937.         (cdr labels)
  938.         (cons (string-append
  939.                (make-define-statement a-symbol offset)
  940.                (let ((other-symbol (or (symbol-2 label-data)
  941.                            (symbol-1 label-data))))
  942.              (if (eq? other-symbol a-symbol)
  943.                  ""
  944.                  (make-define-statement other-symbol a-symbol)))
  945.                (if (dispatch-1 label-data)
  946.                (make-define-statement (dispatch-1 label-data)
  947.                           tagno)
  948.                "")
  949.                (if (dispatch-2 label-data)
  950.                (make-define-statement (dispatch-2 label-data)
  951.                           tagno)
  952.                ""))
  953.               label-defines)
  954.         (cons (string-append
  955.                "\n\t  case "
  956.                (number->string tagno) ":\n\t\t"
  957.                "current_block = (Rpc - " a-symbol ");\n\t\t"
  958.                "goto "
  959.                (symbol->string (or (label-1 label-data)
  960.                        (label-2 label-data)))
  961.                ";\n")
  962.               label-dispatch)
  963.         (cons (string-append
  964.                "WRITE_LABEL_DESCRIPTOR(¤t_block["
  965.                a-symbol "], 0x"
  966.                (number->string (code-word-sel label-data) 16)
  967.                ", " a-symbol ");\n\t"
  968.                "current_block [" a-symbol
  969.                "] = (dispatch_base + " (number->string tagno) ");\n\t")
  970.               label-block-initialization)
  971.         (append
  972.          (if (label-1 label-data)
  973.              (list (cons (label-1 label-data) offset))
  974.              '())
  975.          (if (label-2 label-data)
  976.              (list (cons (label-2 label-data) offset))
  977.              '())
  978.          label-bindings)))))
  979.  
  980.     (iter (+ 2 n) 0 (reverse! labels) '() '() '() '()))
  981.  
  982. (define-structure (fake-compiled-procedure
  983.            (constructor make-fake-compiled-procedure)
  984.            (conc-name fake-procedure/))
  985.   (block-name false read-only true)
  986.   (label-index false read-only true))
  987.  
  988. (define-structure (fake-compiled-block
  989.            (constructor make-fake-compiled-block)
  990.            (conc-name fake-block/))
  991.   (name false read-only true)
  992.   (c-proc false read-only true)
  993.   (d-proc false read-only true)
  994.   (c-code false read-only true)
  995.   (index false read-only true)
  996.   (ntags false read-only true))
  997.  
  998. (define fake-compiled-block-name-prefix "ccBlock")
  999.  
  1000. (define (fake-compiled-block-name number)
  1001.   (string-append fake-compiled-block-name-prefix
  1002.          "_" (number->string (-1+ number))))
  1003.  
  1004. (define (fake-block->code-decl block)
  1005.   (string-append "DECLARE_SUBCODE (\""
  1006.          (fake-block/c-proc block)
  1007.          "\", " (number->string (fake-block/ntags block))
  1008.          ", NO_SUBBLOCKS, "
  1009.          (fake-block/c-proc block) ");\n\t"))
  1010.  
  1011. (define (fake-block->data-decl block)
  1012.   (string-append "DECLARE_SUBDATA (\""
  1013.          (fake-block/c-proc block)
  1014.          "\", NO_SUBBLOCKS, "
  1015.          (fake-block/d-proc block) ");\n\t"))
  1016.  
  1017. (define (fake-block->c-code block)
  1018.   (list (fake-block/c-code block)
  1019.     "\f\n"))