1 ;;;============================================================================
3 ;;; File: "syntax-case.scm", Time-stamp: <2008-12-15 11:35:18 feeley>
5 ;;; Copyright (c) 1998-2008 by Marc Feeley, All Rights Reserved.
7 ;;; This is version 3.2 .
9 ;; This version includes a patch which avoids quoting self-evaluating
10 ;; constants. This makes it possible to use some Gambit specific forms
11 ;; such as declare, namespace and define-macro.
13 ;; This is an implementation of "syntax-case" for the Gambit-C 4.0
14 ;; system based on the portable implementation "psyntax.ss". At the
15 ;; top of the file "psyntax.ss" can be found this information:
17 ;; Portable implementation of syntax-case
18 ;; Extracted from Chez Scheme Version 7.3 (Feb 26, 2007)
19 ;; Authors: R. Kent Dybvig, Oscar Waddell, Bob Hieb, Carl Bruggeman
21 ;; This file can be used to replace the builtin macro expander of the
22 ;; interpreter and compiler. Source code correlation information
23 ;; (filename and position in file) is preserved by the expander. The
24 ;; expander mangles non-global variable names and this complicates
25 ;; debugging somewhat. Note that Gambit's normal parser processes the
26 ;; input after expansion by the syntax-case expander. Since the
27 ;; syntax-case expander does not know about Gambit's syntactic
28 ;; extensions (like DSSSL parameters) some of the syntactic
29 ;; extensions cannot be used. On the other hand, the syntax-case
30 ;; expander defines some new special forms, such as "module",
31 ;; "alias", and "eval-when".
33 ;; You can simply load this file at the REPL with:
35 ;; (load "syntax-case")
37 ;; For faster macro processing it is worthwhile to compile the file
38 ;; with the compiler. You can also rename this file to "gambcext.scm"
39 ;; and put it in the Gambit "lib" installation directory so that it is
40 ;; loaded every time the interpreter and compiler are started.
42 ;; Alternatively, the expander can be loaded from the command line
45 ;; % gsi ~~lib/syntax-case -
46 ;; > (pp (lambda (x y) (if (< x y) (let ((z (* x x))) z))))
47 ;; (lambda (%%x0 %%y1)
48 ;; (if (< %%x0 %%y1) ((lambda (%%z2) %%z2) (* %%x0 %%x0)) (void)))
50 ;;;============================================================================
61 (##include "~~lib/gambit#.scm")
74 interaction-environment
86 interaction-environment
92 ;;;============================================================================
94 ;; The following procedures are needed by the syntax-case system.
97 (lambda (f first . rest)
100 (let andmap ((first first))
101 (let ((x (car first)) (first (cdr first)))
104 (and (f x) (andmap first)))))
105 (let andmap ((first first) (rest rest))
106 (let ((x (car first))
109 (rest (map cdr rest)))
111 (apply f (cons x xr))
112 (and (apply f (cons x xr)) (andmap first rest)))))))))
116 (and (not (null? list1))
117 (or (proc (car list1)) (ormap proc (cdr list1))))))
121 (cond ((and (##pair? expr)
122 (##equal? (##car expr) "noexpand")
123 (##pair? (##cdr expr))
124 (##null? (##cddr expr)))
125 (##eval (##cadr expr)))
126 ((and (##source? expr)
127 (##pair? (##source-code expr))
128 (##source? (##car (##source-code expr)))
129 (##equal? (##source-code (##car (##source-code expr))) "noexpand")
130 (##pair? (##cdr (##source-code expr)))
131 (##null? (##cddr (##source-code expr))))
132 (##eval (##cadr (##source-code expr))))
134 (##raise-error-exception
135 "eval expects an expression of the form (\"noexpand\" <expr>)"
138 (define gensym-count 0)
142 (let ((n gensym-count))
143 (set! gensym-count (+ n 1))
146 (if (null? id) "" (symbol->string (car id)))
147 (number->string n))))))
152 (let ((str (symbol->string obj)))
153 (and (> (string-length str) 2)
154 (string=? (substring str 0 2) "%%"))))))
156 (define prop-table (##make-table))
160 (let ((sym-key (cons sym key)))
161 (##table-set! prop-table sym-key))))
164 (lambda (sym key val)
165 (let ((sym-key (cons sym key)))
166 (##table-set! prop-table sym-key val))))
170 (let ((sym-key (cons sym key)))
171 (##table-ref prop-table sym-key #f))))
174 (lambda (arg1 . other-args)
177 (if (null? (cdr lst))
179 (cons (car lst) (fix (cdr lst)))))
181 (fix (cons arg1 other-args))))
188 (remq obj (cdr lst)))
190 (cons (car lst) (remq obj (cdr lst)))))))
192 ;;;----------------------------------------------------------------------------
194 ;; These initial definitions are needed because these variables are
195 ;; mutated with a "set!" without a prior definition.
197 (define $sc-put-cte #f)
198 (define sc-expand (lambda (src) src)) ; temporary definition
199 (define $make-environment #f)
200 (define environment? #f)
201 (define interaction-environment #f)
202 (define identifier? #f)
203 (define syntax->list #f)
204 (define syntax->vector #f)
205 (define syntax-object->datum #f)
206 (define datum->syntax-object #f)
207 (define generate-temporaries #f)
208 (define free-identifier=? #f)
209 (define bound-identifier=? #f)
210 (define literal-identifier=? #f)
211 (define syntax-error #f)
212 (define $syntax-dispatch #f)
214 ;;;----------------------------------------------------------------------------
216 ;;; Interface to Gambit's source code annotations.
220 ;; (pp `(annotation? ,x))
223 (define annotation-expression
225 ;; (pp `(annotation-expression ,x))
228 (define annotation-stripped
230 ;; (pp `(annotation-stripped ,x))
235 ;; (pp `(build-source ,ae ,x))
237 (##make-source x (##source-locat ae))
238 (##make-source x #f))))
248 (cons (build-source ae (car vars))
251 (build-source ae vars)))))
253 (if (or (null? vars) (pair? vars))
254 (build-source ae (fix vars))
257 (define attach-source
259 ;; (pp `(attach-source ,ae ,datum))
263 (##make-source ae #f))))
265 (define (datum->source x)
266 (##make-source (cond ((pair? x)
269 (box (datum->source (unbox x))))
274 (##source-locat src)))
276 (define (list-convert lst)
277 (cons (datum->source (car lst))
278 (list-tail-convert (cdr lst))))
280 (define (list-tail-convert lst)
282 (if (quoting-form? lst)
284 (cons (datum->source (car lst))
285 (list-tail-convert (cdr lst)))))
289 (datum->source lst))))
291 (define (quoting-form? x)
292 (let ((first (car x))
296 (or (eq? first 'quote)
297 (eq? first 'quasiquote)
299 (eq? first 'unquote-splicing)))))
301 (define (vector-convert vect)
302 (let* ((len (vector-length vect))
303 (v (make-vector len)))
304 (let loop ((i (- len 1)))
307 (vector-set! v i (datum->source (vector-ref vect i)))
311 (datum->source datum))))
313 ;;;----------------------------------------------------------------------------
332 ;;;============================================================================