home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d556
/
scheme2c.lha
/
Scheme2C
/
Scheme-src.lzh
/
scsc
/
readtext.sc
< prev
next >
Wrap
Text File
|
1991-10-11
|
14KB
|
395 lines
;;; The functions in this file read the program text, expand text macros, and
;;; process all MODULE, INCLUDE, DEFINE-EXTERNAL, DEFINE-C-EXTERNAK and
;;; DEFINE-MACRO directives. The function READ-TEXT is called to read each
;;; S-expression from the source files(s). It will return the eof-object when
;;; all text has been read.
;;;
;* Copyright 1989 Digital Equipment Corporation
;* All Rights Reserved
;*
;* Permission to use, copy, and modify this software and its documentation is
;* hereby granted only under the following terms and conditions. Both the
;* above copyright notice and this permission notice must appear in all copies
;* of the software, derivative works or modified versions, and any portions
;* thereof, and both notices must appear in supporting documentation.
;*
;* Users of this software agree to the terms and conditions set forth herein,
;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
;* right and license under any changes, enhancements or extensions made to the
;* core functions of the software, including but not limited to those affording
;* compatibility with other hardware or software environments, but excluding
;* applications which incorporate this software. Users further agree to use
;* their best efforts to return to Digital any such changes, enhancements or
;* extensions that they make and inform Digital of noteworthy uses of this
;* software. Correspondence should be provided to Digital at:
;*
;* Director of Licensing
;* Western Research Laboratory
;* Digital Equipment Corporation
;* 100 Hamilton Avenue
;* Palo Alto, California 94301
;*
;* This software may be distributed (but not offered for sale or transferred
;* for compensation) to third parties, provided such third parties agree to
;* abide by the terms and conditions of this notice.
;*
;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
;* SOFTWARE.
(module readtext)
;;; External definitions.
(include "plist.sch")
(include "expform.sch")
(define (READ-TEXT)
(let ((form '()))
(if sc-splice
(begin (set! form (car sc-splice))
(set! sc-splice (cdr sc-splice)))
(begin (set! form (sc-expand (read-from-sc-input)))
(if (log? 'macro)
(begin (pretty-print-$tree form sc-icode)
(newline sc-icode)))))
(case (and (pair? form) (car form))
((define-external)
(do-define-external form)
(read-text))
((define-c-external)
(do-define-c-external form)
(read-text))
((define-macro)
(read-text))
((module)
(do-module form)
(read-text))
((include)
(do-include form)
(read-text))
((define-constant)
(read-text))
((eval-when)
(if (memq 'compile (cadr form))
(eval (cons 'begin (cddr form))))
(read-text))
(else (cond ((and (pair? form)
(pair? (car form))
(eq? (caar form) 'lambda)
(null? (cadar form)))
(set! sc-splice (append (cddar form) sc-splice))
(read-text))
(else (if (equal? module-name "")
(begin (report-error
"Module name is not defined")
(set! module-name "noname")))
form))))))
(define (READ-FROM-SC-INPUT)
(do ((form (read (car sc-input)) (read (car sc-input))))
((or (and (eof-object? form) (null? (cdr sc-input)))
(not (eof-object? form)))
(if (log? 'source)
(begin (pretty-print-$tree form sc-icode)
(newline sc-icode)))
form)
(close-port (car sc-input))
(set! sc-splice (cadr sc-input))
(set! sc-input (cddr sc-input))))
;;; Macro expansion is done by this code. It is based upon the ideas in
;;; "Expansion-Passing Style: Beyond Conventional Macros", 1986 ACM Conference
;;; on Lisp and Functional Programming.
(define (SC-EXPAND x) (sc-initial-expander x sc-initial-expander))
(define (SC-INITIAL-EXPANDER x e)
(let ((e1 (cond ((symbol? x) *sc-identifier-expander*)
((not (pair? x)) (lambda (x e) x))
((symbol? (car x))
(let ((func (get (car x) 'macro)))
(if (procedure? func)
func
*sc-application-expander*)))
(else *sc-application-expander*))))
(e1 x e)))
(define (SC-EXPAND-ONCE x) (sc-initial-expander x (lambda (x e) x)))
(define (*SC-IDENTIFIER-EXPANDER* x e)
(let ((constant (get x 'macro)))
(if (pair? constant) (car constant) x)))
(define (*SC-APPLICATION-EXPANDER* x e)
(if (islist x 1)
(map (lambda (x) (e x e)) x)
(expand-error '*SC-APPLICATION-EXPANDER* x)))
(define (INSTALL-SC-EXPANDER keyword function)
(put keyword 'macro function))
;;; External functions and variables which follow Scheme's conventions are
;;; defined by the following form:
;;;
;;; (DEFINE-EXTERNAL var module)
;;;
;;; (DEFINE-EXTERNAL var TOP-LEVEL)
;;;
;;; (DEFINE-EXTERNAL var "module" "name")
;;;
;;; (DEFINE-EXTERNAL (func args...) module)
;;;
;;; (DEFINE-EXTERNAL (func args...) "module" "name")
(define (DO-DEFINE-EXTERNAL exp)
(cond ((and (islist exp 3 3) (symbol? (cadr exp)) (symbol? (caddr exp)))
(let* ((var (cadr exp))
(hex (lchexname var))
(module (lchexname (caddr exp))))
(if (eq? (caddr exp) 'top-level)
(newv var 'use 'top-level 'module 'top-level
'vname (string-append (hex28 "" hex) "_v"))
(newv var 'use 'global 'module module
'vname (string-append (hex28 module hex) "_v")))))
((and (islist exp 4 4) (symbol? (cadr exp)) (string? (caddr exp))
(string? (cadddr exp)))
(let* ((var (cadr exp))
(module (caddr exp))
(vname (cadddr exp)))
(if (not (equal? module ""))
(set! vname (string-append module "_" vname)))
(newv var 'use 'global 'module module 'vname vname)))
((and (islist exp 3 3) (pair? (cadr exp)) (symbol? (caadr exp))
(symbol? (caddr exp)))
(let* ((func (caadr exp))
(vars (cdadr exp))
(hex (lchexname func))
(module (lchexname (caddr exp)))
(id ($lambda-id
(exp-form `(lambda ,vars) exp-form)))
(alpha '()))
(set! alpha (newv func 'use 'global 'module module
'vname
(string-append (hex28 module hex) "_v")
'cname
(string-append (hex28 module hex))))
(set-id-lambda! alpha id)
(set-lambda-generate! id 'procedure)
(set-lambda-name! id alpha)))
((and (islist exp 4 4) (pair? (cadr exp)) (symbol? (caadr exp))
(string? (caddr exp)))
(let* ((func (caadr exp))
(vars (cdadr exp))
(module (caddr exp))
(cname (cadddr exp))
(id ($lambda-id
(exp-form `(lambda ,vars) exp-form)))
(alpha '()))
(if (not (equal? module ""))
(set! cname (string-append module "_" cname)))
(set! alpha (newv func 'use 'global 'module module
'cname cname))
(set-id-lambda! alpha id)
(set-lambda-generate! id 'procedure)
(set-lambda-name! id alpha)))
(else (expand-error 'define-external exp))))
;;; External variables and functions which follow C's conventions are defined
;;; by the following forms:
;;;
;;; (DEFINE-C-EXTERNAL var type "name")
;;;
;;; (DEFINE-C-EXTERNAL (var type ...) type "name")
;;;
;;; (DEFINE-C-EXTERNAL (var type ... . type) type "name")
;;;
;;; where "type" is one of the following: tscp, pointer, void, char, int,
;;; shortint, longint, unsigned, shortunsigned longunsigned, float or double.
;;; Argument conversion is determined by the type specifications as follows:
;;;
;;; pointer argument may be a string, procedure, or a number. The address
;;; of the first character of the string will be provided. The
;;; code address of a procedure will be provided. The integer
;;; value of a number will be provided.
;;;
;;; char argument is a character. Its value will be supplied.
;;;
;;; int argument is a number. Its int value will be supplied.
;;; shortint
;;; longint
;;;
;;; unsigned argument is a number. Its value will be supplied.
;;; shortunsigned
;;; longunsigned
;;;
;;; float argument is a number. Its float value will be supplied.
;;;
;;; double argument is a number. Its double value will be supplied.
;;;
;;; tscp argument is any Scheme value which will be passed as is.
;;;
;;; void not allowed.
;;;
;;; Result conversion is as follows:
;;;
;;; pointer the pointer result (an unsigned value) is returned as a number.
;;;
;;; char the character result is returned as a character.
;;;
;;; int the integer result is returned as a number.
;;; shortint
;;; longint
;;;
;;; unsigned the unsigned result is returned as a number.
;;; shortunsigned
;;; longunsigned
;;;
;;; float the float result is returned as a number.
;;;
;;; double the double result is returned as a number.
;;;
;;; tscp the result is returned as is.
;;;
;;; void no result is returned.
(define (DO-DEFINE-C-EXTERNAL exp)
(if (islist exp 4 4)
(let ((form (cadr exp))
(c-type (caddr exp))
(cname (cadddr exp))
(c-type? (lambda (x)
(memq x
'(pointer char int shortint longint
unsigned shortunsigned longunsigned
float double tscp)))))
(cond ((and (symbol? form) (c-type? c-type))
(newv form 'use 'global 'module "" 'vname cname
'type c-type))
((and (pair? form) (symbol? (car form))
(or (c-type? c-type) (eq? c-type 'void)))
(let ((id ($lambda-id (exp-form `(lambda ,(cdr form))
exp-form)))
(alpha (newv (car form) 'use 'global 'module ""
'cname cname 'type c-type)))
(let loop ((req '()) (vars (cdr form)))
(cond ((null? vars)
(set-lambda-reqvars! id (reverse req)))
((c-type? vars)
(set-lambda-reqvars! id (reverse req))
(set-lambda-optvars! id (list vars)))
((and (pair? vars) (c-type? (car vars)))
(loop (cons (car vars) req) (cdr vars)))
(else (expand-error 'define-c-external
exp))))
(set-id-lambda! alpha id)
(set-lambda-generate! id 'procedure)
(set-lambda-name! id alpha)))
(else (expand-error 'define-c-external exp))))
(expand-error 'define-c-external exp)))
;;; Compile time text macros are defined by the form:
;;;
;;; (DEFINE-MACRO id macro-expander)
;;;
;;; where "id" is the identifier which is to be expanded, and "macro-expander"
;;; is an expression which is evaluated by the compiler and returns the
;;; function which does the macro expansion. This function must be a function
;;; of two arguments, where the first is the expression containing the
;;; identifier, and the second is the function to use to recursively expand
;;; the expression.
(define (DO-DEFINE-MACRO exp)
(if (and (islist exp 3 3) (symbol? (cadr exp)))
(put (cadr exp) 'macro (eval (caddr exp) '()))
(expand-error 'define-macro exp)))
;;; Source from additional files is included in the compilation by the
;;; INCLUDE form:
;;;
;;; (INCLUDE file)
;;;
;;; where file is a string which is the file name of the file containing the
;;; additional LISP source.
(define (DO-INCLUDE exp)
(define (TRY-OPEN name)
(call-with-current-continuation
(lambda (return)
(let ((save-error *error-handler*))
(set! *error-handler*
(lambda x
(set! *error-handler* save-error)
(return #f)))
(let ((result (open-input-file name)))
(set! *error-handler* save-error)
result)))))
(let ((file-name (and (islist exp 2 2) (string? (cadr exp)) (cadr exp))))
(if file-name
(let loop ((dirs sc-include-dirs))
(if dirs
(let ((port (try-open (string-append (car dirs)
file-name))))
(if port
(begin (set! sc-input
(cons port (cons sc-splice
sc-input)))
(set! sc-splice '()))
(loop (cdr dirs))))
(report-error "Can't open INCLUDE file:" file-name)))
(expand-error 'include exp))))
;;; The module name for this compilation is defined by including one (and only
;;; one) MODULE directive:
;;;
;;; (MODULE module-name
;;; [ (MAIN main-function) ]
;;; [ (HEAP heap-size) ]
;;; [ (TOP-LEVEL function ... ) ]
;;; [ (WITH module-name ...) ] )
;;;
;;; where module-name is a symbol which is the name for the current module and
;;; main-program is an optional symbol which denotes the "main" program.
(define (DO-MODULE exp)
(if (and (islist exp 2) (symbol? (cadr exp)))
(begin (if (equal? module-name "")
(begin (set! module-name (lchexname (cadr exp)))
(set! module-name-upcase
(symbol->string (cadr exp))))
(report-error "MODULE name is already defined as:"
module-name))
(for-each do-module-clauses (cddr exp)))
(expand-error 'module exp)))
(define (DO-MODULE-CLAUSES clause)
(cond ((and (islist clause 2 2) (eq? (car clause) 'main)
(not main-program-name) (symbol? (cadr clause)))
(if (not sc-interpreter)
(set! main-program-name (cadr clause))))
((and (islist clause 2 2) (eq? (car clause) 'heap)
(integer? (cadr clause)) (positive? (cadr clause)))
(set! heap-size (cadr clause)))
((and (islist clause 1) (eq? (car clause) 'top-level)
(eq? top-level-symbols #t))
(set! top-level-symbols (cdr clause)))
((and (islist clause 2) (eq? (car clause) 'with)
(not with-modules))
(set! with-modules (map lchexname (cdr clause))))
(else (report-error "Illegal or duplicate MODULE clause"))))
;;; Constants may be defined by the form:
;;;
;;; (DEFINE-CONSTANT symbol value)
(define (DO-DEFINE-CONSTANT exp)
(if (and (islist exp 3 3) (symbol? (cadr exp)))
(install-sc-expander (cadr exp) (list (eval (caddr exp) '())))
(expand-error 'define-constant exp)))