📄 psyntax.ss
字号:
;;;; -*-scheme-*-;;;;;;;; Copyright (C) 2001 Free Software Foundation, Inc.;;;; ;;;; This program is free software; you can redistribute it and/or modify;;;; it under the terms of the GNU General Public License as published by;;;; the Free Software Foundation; either version 2, or (at your option);;;; any later version.;;;; ;;;; This program is distributed in the hope that it will be useful,;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;;;; GNU General Public License for more details.;;;; ;;;; You should have received a copy of the GNU General Public License;;;; along with this software; see the file COPYING. If not, write to;;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,;;;; Boston, MA 02111-1307 USA;;;;;;;; As a special exception, the Free Software Foundation gives permission;;;; for additional uses of the text contained in its release of GUILE.;;;;;;;; The exception is that, if you link the GUILE library with other files;;;; to produce an executable, this does not by itself cause the;;;; resulting executable to be covered by the GNU General Public License.;;;; Your use of that executable is in no way restricted on account of;;;; linking the GUILE library code into it.;;;;;;;; This exception does not however invalidate any other reasons why;;;; the executable file might be covered by the GNU General Public License.;;;;;;;; This exception applies only to the code released by the;;;; Free Software Foundation under the name GUILE. If you copy;;;; code from other Free Software Foundation releases into a copy of;;;; GUILE, as the General Public License permits, the exception does;;;; not apply to the code that you add in this way. To avoid misleading;;;; anyone as to the status of such modified files, you must delete;;;; this exception notice from them.;;;;;;;; If you write modifications of your own for GUILE, it is your choice;;;; whether to permit this exception to apply to your modifications.;;;; If you do not wish that, delete this exception notice.;;;; ;;; Portable implementation of syntax-case;;; Extracted from Chez Scheme Version 5.9f;;; Authors: R. Kent Dybvig, Oscar Waddell, Bob Hieb, Carl Bruggeman;;; Modified by Mikael Djurfeldt <djurfeldt@nada.kth.se> according;;; to the ChangeLog distributed in the same directory as this file:;;; 1997-08-19, 1997-09-03, 1997-09-10, 2000-08-13, 2000-08-24,;;; 2000-09-12, 2001-03-08;;; Copyright (c) 1992-1997 Cadence Research Systems;;; Permission to copy this software, in whole or in part, to use this;;; software for any lawful purpose, and to redistribute this software;;; is granted subject to the restriction that all copies made of this;;; software must include this copyright notice in full. This software;;; is provided AS IS, with NO WARRANTY, EITHER EXPRESS OR IMPLIED,;;; INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY;;; OR FITNESS FOR ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE;;; AUTHORS BE LIABLE FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES OF ANY;;; NATURE WHATSOEVER.;;; Before attempting to port this code to a new implementation of;;; Scheme, please read the notes below carefully.;;; This file defines the syntax-case expander, sc-expand, and a set;;; of associated syntactic forms and procedures. Of these, the;;; following are documented in The Scheme Programming Language,;;; Second Edition (R. Kent Dybvig, Prentice Hall, 1996). Most are;;; also documented in the R4RS and draft R5RS.;;;;;; bound-identifier=?;;; datum->syntax-object;;; define-syntax;;; fluid-let-syntax;;; free-identifier=?;;; generate-temporaries;;; identifier?;;; identifier-syntax;;; let-syntax;;; letrec-syntax;;; syntax;;; syntax-case;;; syntax-object->datum;;; syntax-rules;;; with-syntax;;;;;; All standard Scheme syntactic forms are supported by the expander;;; or syntactic abstractions defined in this file. Only the R4RS;;; delay is omitted, since its expansion is implementation-dependent.;;; The remaining exports are listed below:;;;;;; (sc-expand datum);;; if datum represents a valid expression, sc-expand returns an;;; expanded version of datum in a core language that includes no;;; syntactic abstractions. The core language includes begin,;;; define, if, lambda, letrec, quote, and set!.;;; (eval-when situations expr ...);;; conditionally evaluates expr ... at compile-time or run-time;;; depending upon situations (see the Chez Scheme System Manual,;;; Revision 3, for a complete description);;; (syntax-error object message);;; used to report errors found during expansion;;; (install-global-transformer symbol value);;; used by expanded code to install top-level syntactic abstractions;;; (syntax-dispatch e p);;; used by expanded code to handle syntax-case matching;;; The following nonstandard procedures must be provided by the;;; implementation for this code to run.;;;;;; (void);;; returns the implementation's cannonical "unspecified value". This;;; usually works: (define void (lambda () (if #f #f))).;;;;;; (andmap proc list1 list2 ...);;; returns true if proc returns true when applied to each element of list1;;; along with the corresponding elements of list2 ....;;; The following definition works but does no error checking:;;;;;; (define andmap;;; (lambda (f first . rest);;; (or (null? first);;; (if (null? rest);;; (let andmap ((first first));;; (let ((x (car first)) (first (cdr first)));;; (if (null? first);;; (f x);;; (and (f x) (andmap first)))));;; (let andmap ((first first) (rest rest));;; (let ((x (car first));;; (xr (map car rest));;; (first (cdr first));;; (rest (map cdr rest)));;; (if (null? first);;; (apply f (cons x xr));;; (and (apply f (cons x xr)) (andmap first rest)))))))));;;;;; The following nonstandard procedures must also be provided by the;;; implementation for this code to run using the standard portable;;; hooks and output constructors. They are not used by expanded code,;;; and so need be present only at expansion time.;;;;;; (eval x);;; where x is always in the form ("noexpand" expr).;;; returns the value of expr. the "noexpand" flag is used to tell the;;; evaluator/expander that no expansion is necessary, since expr has;;; already been fully expanded to core forms.;;;;;; eval will not be invoked during the loading of psyntax.pp. After;;; psyntax.pp has been loaded, the expansion of any macro definition,;;; whether local or global, will result in a call to eval. If, however,;;; sc-expand has already been registered as the expander to be used;;; by eval, and eval accepts one argument, nothing special must be done;;; to support the "noexpand" flag, since it is handled by sc-expand.;;;;;; (error who format-string why what);;; where who is either a symbol or #f, format-string is always "~a ~s",;;; why is always a string, and what may be any object. error should;;; signal an error with a message something like;;;;;; "error in <who>: <why> <what>";;;;;; (gensym);;; returns a unique symbol each time it's called;;;;;; (putprop symbol key value);;; (getprop symbol key);;; key is always the symbol *sc-expander*; value may be any object.;;; putprop should associate the given value with the given symbol in;;; some way that it can be retrieved later with getprop.;;; When porting to a new Scheme implementation, you should define the;;; procedures listed above, load the expanded version of psyntax.ss;;; (psyntax.pp, which should be available whereever you found;;; psyntax.ss), and register sc-expand as the current expander (how;;; you do this depends upon your implementation of Scheme). You may;;; change the hooks and constructors defined toward the beginning of;;; the code below, but to avoid bootstrapping problems, do so only;;; after you have a working version of the expander.;;; Chez Scheme allows the syntactic form (syntax <template>) to be;;; abbreviated to #'<template>, just as (quote <datum>) may be;;; abbreviated to '<datum>. The #' syntax makes programs written;;; using syntax-case shorter and more readable and draws out the;;; intuitive connection between syntax and quote.;;; If you find that this code loads or runs slowly, consider;;; switching to faster hardware or a faster implementation of;;; Scheme. In Chez Scheme on a 200Mhz Pentium Pro, expanding,;;; compiling (with full optimization), and loading this file takes;;; between one and two seconds.;;; In the expander implementation, we sometimes use syntactic abstractions;;; when procedural abstractions would suffice. For example, we define;;; top-wrap and top-marked? as;;; (define-syntax top-wrap (identifier-syntax '((top))));;; (define-syntax top-marked?;;; (syntax-rules ();;; ((_ w) (memq 'top (wrap-marks w)))));;; rather than;;; (define top-wrap '((top)));;; (define top-marked?;;; (lambda (w) (memq 'top (wrap-marks w))));;; On ther other hand, we don't do this consistently; we define make-wrap,;;; wrap-marks, and wrap-subst simply as;;; (define make-wrap cons);;; (define wrap-marks car);;; (define wrap-subst cdr);;; In Chez Scheme, the syntactic and procedural forms of these;;; abstractions are equivalent, since the optimizer consistently;;; integrates constants and small procedures. Some Scheme;;; implementations, however, may benefit from more consistent use ;;; of one form or the other.;;; implementation information:;;; "begin" is treated as a splicing construct at top level and at;;; the beginning of bodies. Any sequence of expressions that would;;; be allowed where the "begin" occurs is allowed.;;; "let-syntax" and "letrec-syntax" are also treated as splicing;;; constructs, in violation of the R4RS appendix and probably the R5RS;;; when it comes out. A consequence, let-syntax and letrec-syntax do;;; not create local contours, as do let and letrec. Although the;;; functionality is greater as it is presently implemented, we will;;; probably change it to conform to the R4RS/expected R5RS.;;; Objects with no standard print syntax, including objects containing;;; cycles and syntax object, are allowed in quoted data as long as they;;; are contained within a syntax form or produced by datum->syntax-object.;;; Such objects are never copied.;;; All identifiers that don't have macro definitions and are not bound;;; lexically are assumed to be global variables;;; Top-level definitions of macro-introduced identifiers are allowed.;;; This may not be appropriate for implementations in which the;;; model is that bindings are created by definitions, as opposed to;;; one in which initial values are assigned by definitions.;;; Top-level variable definitions of syntax keywords is not permitted.;;; Any solution allowing this would be kludgey and would yield;;; surprising results in some cases. We can provide an undefine-syntax;;; form. The questions is, should define be an implicit undefine-syntax?;;; We've decided no for now.;;; Identifiers and syntax objects are implemented as vectors for;;; portability. As a result, it is possible to "forge" syntax;;; objects.;;; The implementation of generate-temporaries assumes that it is possible;;; to generate globally unique symbols (gensyms).;;; The input to sc-expand may contain "annotations" describing, e.g., the;;; source file and character position from where each object was read if;;; it was read from a file. These annotations are handled properly by;;; sc-expand only if the annotation? hook (see hooks below) is implemented;;; properly and the operators make-annotation, annotation-expression,;;; annotation-source, annotation-stripped, and set-annotation-stripped!;;; are supplied. If annotations are supplied, the proper annotation;;; source is passed to the various output constructors, allowing;;; implementations to accurately correlate source and expanded code.;;; Contact one of the authors for details if you wish to make use of;;; this feature.;;; Bootstrapping:;;; When changing syntax-object representations, it is necessary to support;;; both old and new syntax-object representations in id-var-name. It;;; should be sufficient to recognize old representations and treat;;; them as not lexically bound.(let ()(define-syntax define-structure (lambda (x) (define construct-name (lambda (template-identifier . args) (datum->syntax-object template-identifier (string->symbol (apply string-append (map (lambda (x) (if (string? x) x (symbol->string (syntax-object->datum x)))) args)))))) (syntax-case x () ((_ (name id1 ...)) (andmap identifier? (syntax (name id1 ...))) (with-syntax ((constructor (construct-name (syntax name) "make-" (syntax name))) (predicate (construct-name (syntax name) (syntax name) "?")) ((access ...) (map (lambda (x) (construct-name x (syntax name) "-" x)) (syntax (id1 ...)))) ((assign ...) (map (lambda (x) (construct-name x "set-" (syntax name) "-" x "!")) (syntax (id1 ...)))) (structure-length (+ (length (syntax (id1 ...))) 1)) ((index ...) (let f ((i 1) (ids (syntax (id1 ...)))) (if (null? ids) '() (cons i (f (+ i 1) (cdr ids))))))) (syntax (begin (define constructor (lambda (id1 ...) (vector 'name id1 ... ))) (define predicate (lambda (x) (and (vector? x) (= (vector-length x) structure-length) (eq? (vector-ref x 0) 'name)))) (define access (lambda (x) (vector-ref x index))) ... (define assign (lambda (x update) (vector-set! x index update))) ...)))))))(let ()(define noexpand "noexpand")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -