mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-29 19:30:36 +02:00
Update Makefile.am's; remove slib import
* Makefile.am: * module/Makefile.am: * module/language/scheme/Makefile.am: * module/system/Makefile.am: * module/system/base/Makefile.am: * module/system/il/Makefile.am: * module/system/repl/Makefile.am: * module/system/vm/Makefile.am: Cleaned up to be more complete, if not completely working. * module/guile/slib.scm: * module/slib/: Removed the slib import; it's a bit out of place here, and bitrotten at that.
This commit is contained in:
parent
0a5db6e11d
commit
83dff6e55f
176 changed files with 7 additions and 62200 deletions
|
@ -1,4 +1,5 @@
|
|||
SUBDIRS = src doc testsuite
|
||||
DIST_SUBDIRS = src module doc testsuite
|
||||
|
||||
# FIXME: The `module' directory is removed from `SUBDIRS' until it can
|
||||
# actually be built.
|
||||
|
|
|
@ -1,15 +1 @@
|
|||
SUBDIRS = system
|
||||
|
||||
DISTDIRS = $(srcdir)/system $(srcdir)/language $(srcdir)/guile $(srcdir)/slib
|
||||
EXCLUDES = --exclude=CVS --exclude=*.go --exclude=*~
|
||||
|
||||
all: slibcat
|
||||
|
||||
clean:
|
||||
rm -f slibcat slib/*.go
|
||||
|
||||
slibcat:
|
||||
guile -s $(top_srcdir)/src/guilec slib/*.scm
|
||||
|
||||
dist-hook:
|
||||
$(TAR) cf - $(EXCLUDES) $(DISTDIRS) | (cd $(distdir); $(TAR) xf -)
|
||||
SUBDIRS = system language
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
;;; Guile SLIB interface
|
||||
|
||||
;; 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 program; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
;; Boston, MA 02111-1307, USA.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(define-module (guile slib)
|
||||
:use-module (system vm core))
|
||||
|
||||
(define (slib:load file)
|
||||
(let ((comp (string-append file ".go")))
|
||||
(cond ((file-exists? comp) (load-compiled comp))
|
||||
((file-exists? file) (load file))
|
||||
(else (load (string-append file ".scm")))))
|
||||
(module-export! (current-module)
|
||||
(delq! '%module-public-interface
|
||||
(hash-fold (lambda (k v d) (cons k d)) '()
|
||||
(module-obarray (current-module))))))
|
||||
|
||||
(let ((file (%search-load-path "slib/guile.init")))
|
||||
(if file
|
||||
(slib:load file)
|
||||
(error "Could not find slib/guile.init in" %load-path)))
|
||||
|
||||
(define-public require require:require)
|
|
@ -1,16 +1,11 @@
|
|||
SOURCES =
|
||||
SOURCES = translate.scm spec.scm
|
||||
## FIXME: There's a bug showing up when compiling `translate.scm'.
|
||||
##
|
||||
## `spec.scm' cannot be compiled because it uses the `define-language'
|
||||
## macro which introduces an unregular object, namely the first-class
|
||||
## `<language>' procedure.
|
||||
GOBJECTS = $(SOURCES:%.scm=%.go)
|
||||
|
||||
vmdir = $(guiledir)/language/scheme
|
||||
vm_DATA = $(SOURCES) $(GOBJECTS)
|
||||
|
||||
CLEANFILES = $(GOBJECTS)
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
SUFFIXES = .scm .go
|
||||
%.go: %.scm
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
*.go
|
|
@ -1,171 +0,0 @@
|
|||
This message announces the availability of Scheme Library release slib2d1.
|
||||
|
||||
New in slib2d1:
|
||||
|
||||
+ Linux RPM distribution.
|
||||
|
||||
+ Automated generation of HTTP/HTML static and (multi-client)
|
||||
dynamically editable tables from relational databases.
|
||||
(HTTP server demo at http://www.foxkid.net:8143/tla/).
|
||||
|
||||
+ Reference implementation of Metric Interchange Format:
|
||||
"Representation of numerical values and SI units in character strings
|
||||
for information interchanges"
|
||||
http://swissnet.ai.mit.edu/~jaffer/MIXF.html
|
||||
|
||||
* Makefile (rpm): Added to dist target.
|
||||
(mfiles): Added slib.spec.
|
||||
* slib.spec: Added spec file to generate a .rpm file.
|
||||
Largely based on that of Dr. Robert J. Meier
|
||||
<robert.meier@computer.org>
|
||||
* Makefile (docfiles): Added all the *.txi.
|
||||
* db2html.scm (HTML editing tables): Replaced "record" with "row".
|
||||
* http-cgi.scm (query-alist->parameter-list): Null string --> #f.
|
||||
* coerce.scm (type-of): Removed 'null; broke (coerce '() 'string).
|
||||
* htmlform.scm (html:meta, html:http-equiv): Added.
|
||||
* htmlform.scm (html:meta-refresh): Added.
|
||||
* http-cgi.scm (query-alist->parameter-list): Only separate words
|
||||
for nary parameters.
|
||||
* getparam.scm (getopt->parameter-list): Accomodate positional
|
||||
arguments, both ends.
|
||||
(getopt->parameter-list, getopt->arglist): Take optional
|
||||
description strings.
|
||||
* db2html.scm (command:make-editable-table): Added optional
|
||||
arguments passed to command:modify-table.
|
||||
(command:modify-table): Added null-keys argument; removed pkl.
|
||||
* http-cgi.scm (http:forwarding-page): Added.
|
||||
* htmlform.scm (html:text-area): fixed.
|
||||
* http-cgi.scm (coerce->list): Added.
|
||||
* paramlst.scm (check-arities): Generate warning for wrong arity.
|
||||
* db2html.scm (command:make-editable-table): Deduce arities.
|
||||
* comlist.scm (comlist:list-of??): Added.
|
||||
* coerce.scm (coerce, type-of): Extracted from comlist.scm.
|
||||
* uri.scm (uri:path->keys): Takes list of type-symbols.
|
||||
* simetrix.scm (SI:unit-infos): bit is "bit" (not b).
|
||||
* uri.scm (uri:decode-path, uri:path->keys): Now take path-list
|
||||
instead of path. Fixes bug when '/' was in URI path.
|
||||
* http-cgi.scm (make-query-alist-command-server): Renamed from
|
||||
make-uriencoded-command-server; takes query-alist instead of
|
||||
query-string. Diagnostics can use query-alist without recreating.
|
||||
* db2html.scm (html:linked-row-converter): If a field has a
|
||||
foreign-key of "*catalog-data*", then link to foreign table.
|
||||
(catalog->html, table->linked-html): Put caption at BOTTOM.
|
||||
* htmlform.scm (command->p-specs): Renamed from command->html
|
||||
because it has changed so much. No longer does mapper argument.
|
||||
* db2html.scm (command:make-editable-table): Returns editing-row
|
||||
procedure.
|
||||
* htmlform.scm (html:select, html:buttons, form:element,
|
||||
form:delimited): value-list and visibles arguments combined.
|
||||
* dbutil.scm (get-foreign-choices): extracted from command->html.
|
||||
(make-defaulter): Added.
|
||||
* strcase.scm (symbol-append): Added.
|
||||
* http-cgi.scm (make-uriencoded-command-server): Only apply comval
|
||||
if arglist worked.
|
||||
* htmlform.scm (command->html): Big change; returns list of
|
||||
results of application of (new) MAPPER argument.
|
||||
(form:delimited, form:tabled): Added MAPPER procedures.
|
||||
* db2html.scm (html:editable-row-converter): Check for
|
||||
edit-converter being #f.
|
||||
(command:make-editable-table): *keys*, *row-hash* NOT optional.
|
||||
* htmlform.scm (form:element): Extracted from html:generate-form.
|
||||
* db2html.scm (html:editable-row-converter): Added.
|
||||
(command:modify-table): Handle case all fields are primary keys.
|
||||
* db2html.scm (command:modify-table, command:make-editable-table):
|
||||
(HTML editing tables): Added.
|
||||
* htmlform.scm (form:submit): Enhanced.
|
||||
* uri.scm (uri:decode-authority, make-uri): en/decode userinfo.
|
||||
(uri:make-path): Added.
|
||||
(read-anchor-string): Removed; just use paths for combined keys.
|
||||
* slib.texi (Lists as sets): Examples had incorrect order in
|
||||
returned lists.
|
||||
* uri.scm (html:base, html:isindex): Added.
|
||||
(uri->tree): Optional base-tree argument added for relative URI.
|
||||
Brought into full conformance with RFC 2396 test cases.
|
||||
* uri.scm (html:anchor, html:link uri->tree make-uri): Added.
|
||||
(uri:split-fields, uri:decode-query): Moved and renamed from
|
||||
http-cgi.scm.
|
||||
* htmlform.scm (form:image): Added.
|
||||
* uri.scm: Added collected URI functions from "http-cgi.scm" and
|
||||
"db2html.scm".
|
||||
* makcrc.scm (make-port-crc): Added CRC-16 default. Can now take
|
||||
just generator argument.
|
||||
* db2html.scm (html:linked-row-converter, table->linked-html,
|
||||
table->linked-page, db->html-files, db->html-directory): more
|
||||
evocative names.
|
||||
(html:catalog-row-converter): Stripped down version for catalog.
|
||||
* pp.scm (pretty-print->string): Added.
|
||||
(pp:pretty-print): Use (output-port-width port) for width.
|
||||
* genwrite.scm (genwrite:newline-str): abstracted.
|
||||
* htmlform.scm (html:pre): Improved HTML formatting.
|
||||
* http-cgi.scm (query-alist->parameter-list): Made robust for
|
||||
unexpected option-names; and generates warning.
|
||||
* db2html.scm: Fixed HTML per http://validator.w3.org/check.
|
||||
* simetrix.scm (SI:conversion-factor): Negative return codes.
|
||||
* simetrix.scm (SI:unit-infos): Added katal. Replaced bel (B)
|
||||
with decibel (dB).
|
||||
(SI:prefix-exponents): Added [IEC 60027-2] binary prefixes.
|
||||
(SI:unit-infos): Added bit and byte (B).
|
||||
* simetrix.scm (SI:unit-infos): Updated eV and u from CODATA-1998.
|
||||
(SI:solidus): Abstracted parse functions.
|
||||
* simetrix.scm: SI Metric Interchange Format for Scheme Added.
|
||||
* scanf.scm (stdio:scan-and-set read-ui): Fixed dependence on LET
|
||||
evaluation order.
|
||||
* schmooz.texi: Split out from slib.texi.
|
||||
* printf.scm (stdio:parse-float): Adjust so %e format prints an
|
||||
exponent of zero for 0.0
|
||||
* dbutil.scm (dbutil:list-table-definition): Added.
|
||||
* db2html.scm (html:caption): Split out from html:table.
|
||||
* rdms.scm (sync-database): Added.
|
||||
* pnm.scm (pnm:array-write): PGMs were always being written with
|
||||
15 for maxval.
|
||||
* http-cgi.scm (make-urlencoded-command-server): Uses the value of
|
||||
*suggest* if *command* is not in the query-string; if neither uses
|
||||
literal *default*.
|
||||
* htmlform.scm (html:form html:hidden html:checkbox html:text
|
||||
html:text-area html:select html:buttons form:submit form:reset):
|
||||
Procedures documented. No longer builds in <DL> tags.
|
||||
* htmlform.scm (html:blank): Added.
|
||||
(html:plain): Returns non-break-space for html:blank.
|
||||
(html:select html:buttons command->html html:generate-form): Added
|
||||
support for VISIBLE-NAME field for foreign-key domains.
|
||||
* debug.scm (for-each-top-level-definition-in-file): define-syntax
|
||||
is a top-level-definition too.
|
||||
* makcrc.scm (make-port-crc): Converted to use read-byte.
|
||||
* htmlform.scm (html:generate-form): was ignoring method.
|
||||
|
||||
From Ben Goetter <goetter@mazama.net>
|
||||
* pscheme.init: Revised.
|
||||
|
||||
From Lars Arvestad <arve@inddama.sto.se.pnu.com>
|
||||
* gambit.init (*features*): Gambit 3.0 provides
|
||||
call-with-input-string and call-with-output-string.
|
||||
|
||||
SLIB is a portable Scheme library providing compatibiliy and utility
|
||||
functions for all standard Scheme implementations.
|
||||
|
||||
SLIB includes initialization files for Bigloo, Chez, DrScheme, ELK,
|
||||
GAMBIT, MacScheme, MITScheme, PocketScheme, RScheme Scheme->C,
|
||||
Scheme48, SCM, SCSH, T3.1, UMB-Scheme, and VSCM.
|
||||
|
||||
Documentation includes a manifest, installation instructions, and
|
||||
coding guidelines for the library. Documentation of each library
|
||||
package is supplied. SLIB Documentation is online at:
|
||||
|
||||
http://swissnet.ai.mit.edu/~jaffer/SLIB.html
|
||||
|
||||
SLIB is available from:
|
||||
http://swissnet.ai.mit.edu/ftpdir/scm/slib2d1.zip
|
||||
http://swissnet.ai.mit.edu/ftpdir/scm/slib-2d1-1.noarch.rpm
|
||||
swissnet.ai.mit.edu:/pub/scm/slib2d1.zip
|
||||
swissnet.ai.mit.edu:/pub/scm/slib-2d1-1.noarch.rpm
|
||||
|
||||
SLIB-PSD is a portable debugger for Scheme (requires emacs editor):
|
||||
http://swissnet.ai.mit.edu/ftpdir/scm/slib-psd1-3.zip
|
||||
swissnet.ai.mit.edu:/pub/scm/slib-psd1-3.zip
|
||||
|
||||
SCHELOG is an embedding of Prolog in Scheme+SLIB:
|
||||
http://www.cs.rice.edu/CS/PLT/packages/schelog/
|
||||
|
||||
Programs for printing and viewing TexInfo documentation (which SLIB
|
||||
has) come with GNU Emacs or can be obtained via ftp from:
|
||||
ftp.gnu.org:pub/gnu/texinfo/texinfo-4.0.tar.gz
|
|
@ -1,94 +0,0 @@
|
|||
;;;; "Bev2slib.scm" Build SLIB catalogs for Stephen Bevan's libraries.
|
||||
;Copyright (C) 1998 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; Put this file into the implementation-vicinity directory for your
|
||||
;;; scheme implementation.
|
||||
|
||||
;;; Add the line
|
||||
;;; (load (in-vicinity (implementation-vicinity) "Bev2slib.scm"))
|
||||
;;; to "mkimpcat.scm"
|
||||
|
||||
;;; Delete "slibcat" in your implementation-vicinity.
|
||||
|
||||
;;; Bind `Bevan-dir' to the directory containing directories "bawk",
|
||||
;;; "mawk", "pathname", etc. Bev2slib.scm will put entries into the
|
||||
;;; catalog only for those directories and files which exist.
|
||||
|
||||
(let ((Bevan-dir (in-vicinity (library-vicinity) "../"));"/usr/local/lib/Bevan/"
|
||||
(catname "sitecat"))
|
||||
(call-with-output-file (in-vicinity (implementation-vicinity) catname)
|
||||
(lambda (op)
|
||||
(define (display* . args)
|
||||
(for-each (lambda (arg) (display arg op)) args)
|
||||
(newline op))
|
||||
(define (add-alias from to)
|
||||
(display " " op)
|
||||
(write (cons from to) op)
|
||||
(newline op))
|
||||
|
||||
(begin
|
||||
(display* ";\"" catname "\" Site-specific SLIB catalog for "
|
||||
(scheme-implementation-type) (scheme-implementation-version)
|
||||
". -*-scheme-*-")
|
||||
(display* ";")
|
||||
(display* "; DO NOT EDIT THIS FILE")
|
||||
(display* "; it is automagically generated by \"Bev2slib.scm\"")
|
||||
(newline op)
|
||||
)
|
||||
|
||||
;; Output association lists to file "sitecat"
|
||||
|
||||
(for-each
|
||||
(lambda (dir)
|
||||
(let* ((vic (in-vicinity Bevan-dir (string-append dir "/")))
|
||||
(map-file (in-vicinity vic (string-append dir ".map"))))
|
||||
|
||||
(display* ";;; from " map-file)
|
||||
(display* "(")
|
||||
|
||||
(and
|
||||
(file-exists? map-file)
|
||||
(call-with-input-file map-file
|
||||
(lambda (ip)
|
||||
(define files '())
|
||||
(do ((feature (read ip) (read ip)))
|
||||
((eof-object? feature))
|
||||
(let* ((type (read ip))
|
||||
(file (read ip))
|
||||
(fsym (string->symbol (string-append "Req::" file))))
|
||||
(and (not (assq fsym files))
|
||||
(set! files (cons (cons fsym file) files)))
|
||||
(add-alias feature fsym)))
|
||||
(for-each
|
||||
(lambda (pr) (add-alias (car pr) (in-vicinity vic (cdr pr))))
|
||||
files)
|
||||
)))
|
||||
|
||||
(display* ")")))
|
||||
|
||||
'("char-set" "conc-string" "string" "string-03"
|
||||
"avl-tree" "avl-trie"
|
||||
"bawk" "mawk" "pathname"))
|
||||
|
||||
(begin
|
||||
(display* "(")
|
||||
(add-alias 'btree (in-vicinity Bevan-dir "bawk/btree"))
|
||||
(add-alias 'read-line 'line-i/o)
|
||||
(display* ")")
|
||||
))))
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +0,0 @@
|
|||
;;;"DrScheme.init" Initialization for SLIB for DrScheme -*-scheme-*-
|
||||
;; Friedrich Dominicus <frido@q-software-solutions.com>
|
||||
;; Newsgroups: comp.lang.scheme
|
||||
;; Date: 02 Oct 2000 09:24:57 +0200
|
||||
|
||||
(require-library "init.ss" "slibinit")
|
217
module/slib/FAQ
217
module/slib/FAQ
|
@ -1,217 +0,0 @@
|
|||
FAQ (Frequently Asked Questions and answers) for SLIB Scheme Library (slib2d1).
|
||||
Written by Aubrey Jaffer (http://swissnet.ai.mit.edu/~jaffer).
|
||||
|
||||
INTRODUCTION AND GENERAL INFORMATION
|
||||
|
||||
[] What is SLIB?
|
||||
|
||||
SLIB is a portable scheme library meant to provide compatibiliy and
|
||||
utility functions for all standard scheme implementations.
|
||||
|
||||
[] What is Scheme?
|
||||
|
||||
Scheme is a programming language in the Lisp family.
|
||||
|
||||
[] Which implementations has SLIB been ported to?
|
||||
|
||||
SLIB is supported by Bigloo, Chez, DrScheme, ELK, GAMBIT, MacScheme,
|
||||
MITScheme, PocketScheme, RScheme Scheme->C, Scheme48, SCM, SCSH, T3.1,
|
||||
UMB-Scheme, and VSCM.
|
||||
|
||||
[] How can I obtain SLIB?
|
||||
|
||||
SLIB is available via http from:
|
||||
http://swissnet.ai.mit.edu/~jaffer/SLIB.html
|
||||
SLIB is available via ftp from:
|
||||
swissnet.ai.mit.edu:/pub/scm/
|
||||
|
||||
SLIB is also included with SCM floppy disks.
|
||||
|
||||
[] How do I install SLIB?
|
||||
|
||||
Read the INSTALLATION INSTRUCTIONS in "slib/README".
|
||||
|
||||
[] What are slib.texi and slib.info?
|
||||
|
||||
"slib.texi" is the `texinfo' format documentation for SLIB.
|
||||
"slib.info" is produced from "slib.texi" by either Gnu Emacs or the
|
||||
program `makeinfo'. "slib.info" can be viewed using either Gnu Emacs
|
||||
or `info' or a text editor.
|
||||
|
||||
Programs for printing and viewing TexInfo documentation (which SLIB
|
||||
has) come with GNU Emacs or can be obtained via ftp from:
|
||||
ftp.gnu.org:/pub/gnu/texinfo/texinfo-3.12.tar.gz
|
||||
|
||||
[] How often is SLIB released?
|
||||
|
||||
Several times a year.
|
||||
|
||||
[] What is the latest version?
|
||||
|
||||
The version as of this writing is slib2d1. The latest documentation
|
||||
is available online at:
|
||||
http://swissnet.ai.mit.edu/~jaffer/SLIB.html
|
||||
|
||||
[] Which version am I using?
|
||||
|
||||
The Version is in the first line of the files slib/FAQ, slib/ANNOUNCE,
|
||||
and slib/README. If you have Scheme and SLIB running, type
|
||||
(slib:report-version)
|
||||
|
||||
SLIB INSTALLATION PROBLEMS
|
||||
|
||||
[] When I load an SLIB initialization file for my Scheme
|
||||
implementation, I get ERROR: Couldn't find "require.scm"
|
||||
|
||||
Did you remember to set either the environment variable
|
||||
SCHEME_LIBRARY_PATH or the library-vicinity in your initialization
|
||||
file to the correct location? If you set SCHEME_LIBRARY_PATH, make
|
||||
sure that the Scheme implementation supports getenv.
|
||||
|
||||
[] When I load an SLIB initialization file for my Scheme
|
||||
implementation, I get ERROR: Couldn't find
|
||||
"/usr/local/lib/slibrequire.scm"
|
||||
|
||||
Notice that it is looking for "slibrequire.scm" rather than
|
||||
"slib/require.scm". You need to put a trailing slash on either the
|
||||
environment variable SCHEME_LIBRARY_PATH or in the library-vicinity in
|
||||
your initialization file.
|
||||
|
||||
[] SLIB used to work, but now I get ERROR: Couldn't find
|
||||
"slib/require.scm". What happened?
|
||||
|
||||
You changed directories and now the relative pathname
|
||||
"slib/require.scm" no longer refers to the same directory. The
|
||||
environment variable SCHEME_LIBRARY_PATH and library-vicinity in your
|
||||
initialization file should be absolute pathnames.
|
||||
|
||||
[] When I type (require 'macro) I get "ERROR: unbound variable:
|
||||
require".
|
||||
|
||||
You need to arrange to have your Scheme implementation load the
|
||||
appropriate SLIB initialization file ("foo.init") before using SLIB.
|
||||
If your implementation loads an initialization file on startup, you
|
||||
can have it load the SLIB initialization file automatically. For
|
||||
example (load "/usr/local/lib/slib/foo.init").
|
||||
|
||||
[] Why do I get a string-ref (or other) error when I try to load
|
||||
or use SLIB.
|
||||
|
||||
Check that the version of the Scheme implementation you are using
|
||||
matches the version for which the SLIB initialization file was
|
||||
written. There are some notes in the SLIB initialization files about
|
||||
earlier versions. You may need to get a more recent version of your
|
||||
Scheme implementation.
|
||||
|
||||
USING SLIB PROCEDURES
|
||||
|
||||
[] I installed SLIB. When I type (random 5) I get "ERROR:
|
||||
unbound variable: random". Doesn't SLIB have a `random'
|
||||
function?
|
||||
|
||||
Before you can use most SLIB functions, the associated module needs to
|
||||
be loaded. You do this by typing the line that appears at the top of
|
||||
the page in slib.info (or slib.texi) where the function is documented.
|
||||
In the case of random, that line is (require 'random).
|
||||
|
||||
[] Why doesn't SLIB just load all the functions so I don't have
|
||||
to type require statements?
|
||||
|
||||
SLIB has more than 1 Megabyte of Scheme source code. Many scheme
|
||||
implementations take unacceptably long to load 1 Megabyte of source;
|
||||
some implementations cannot allocate enough storage. If you use a
|
||||
package often, you can put the require statement in your Scheme
|
||||
initialization file. Consult the manual for your Scheme
|
||||
implementation to find out the initialization file's name.
|
||||
|
||||
`Autoloads' will work with many Scheme implementations. You could put
|
||||
the following in your initialization file:
|
||||
(define (random . args) (require 'random) (apply random args))
|
||||
|
||||
I find that I only type require statements at top level when
|
||||
debugging. I put require statements in my Scheme files so that the
|
||||
appropriate modules are loaded automatically.
|
||||
|
||||
[] Why does SLIB have PRINTF when it already has the more
|
||||
powerful (CommonLisp) FORMAT?
|
||||
|
||||
CommonLisp FORMAT does not support essential features which PRINTF
|
||||
does. For instance, how do you format a signed 0 extended number?
|
||||
|
||||
(format t "~8,'0,X~%" -3) ==> 000000-3
|
||||
|
||||
But printf gets it right:
|
||||
|
||||
(printf "%08x\n" -3) ==> -0000003
|
||||
|
||||
How can one trunctate a non-numeric field using FORMAT? This feature
|
||||
is essential for printing reports. The first 20 letters of a name is
|
||||
sufficient to identify it. But if that name doesn't get trucated to
|
||||
the desired length it can displace other fields off the page. Once
|
||||
again, printf gets it right:
|
||||
|
||||
(printf "%.20s\n" "the quick brown fox jumped over the lazy dog")
|
||||
==> the quick brown fox
|
||||
|
||||
FORMAT also lacks directives for formatting date and time. printf
|
||||
does not handle these directly, but a related function strftime does.
|
||||
|
||||
[] Why doesn't SLIB:ERROR call FORMAT?
|
||||
|
||||
Format does not provide a method to truncate fields. When an error
|
||||
message contains non-terminating or large expressions, the essential
|
||||
information of the message may be lost in the ensuing deluge.
|
||||
|
||||
FORMAT as currently written in SLIB is not reentrant. Until this is
|
||||
fixed, exception handlers and errors which might occur while using
|
||||
FORMAT cannot use it.
|
||||
|
||||
MACROS
|
||||
|
||||
[] Why are there so many macro implementations in SLIB?
|
||||
|
||||
The R4RS committee specified only the high level pattern language in
|
||||
the Revised^4 Report on Scheme and left to the free marketplace of
|
||||
ideas the details of the low-level facility. Each macro package has a
|
||||
different low-level facility. The low-level facilities are sometimes
|
||||
needed because the high level pattern language is insufficiently
|
||||
powerful to accomplish tasks macros are often written to do.
|
||||
|
||||
[] Why are there both R4RS macros and Common-Lisp style defmacros
|
||||
in SLIB?
|
||||
|
||||
Most Scheme implementations predate the adoption of the R4RS macro
|
||||
specification. All of the implementations except scheme48 version
|
||||
0.45 support defmacro natively.
|
||||
|
||||
[] I did (LOAD "slib/yasos.scm"). The error I get is "variable
|
||||
define-syntax is undefined".
|
||||
|
||||
The way to load the struct macro package is (REQUIRE 'YASOS).
|
||||
|
||||
[] I did (REQUIRE 'YASOS). Now when I type (DEFINE-PREDICATE
|
||||
CELL?) The error I get is "variable define-predicate is
|
||||
undefined".
|
||||
|
||||
If your Scheme does not natively support R4RS macros, you will need to
|
||||
install a macro-capable read-eval-print loop. This is done by:
|
||||
(require 'macro) ;already done if you did (require 'yasos)
|
||||
(require 'repl)
|
||||
(repl:top-level macro:eval)
|
||||
|
||||
This would also be true for a Scheme implementation which didn't
|
||||
support DEFMACRO. The lines in this case would be:
|
||||
(require 'repl)
|
||||
(repl:top-level defmacro:eval)
|
||||
|
||||
[] I always use R4RS macros with an implementation which doesn't
|
||||
natively support them. How can I avoid having to type require
|
||||
statements every time I start Scheme?
|
||||
|
||||
As explained in the Repl entry in slib.info (or slib.texi):
|
||||
|
||||
To have your top level loop always use macros, add any interrupt
|
||||
catching code and the following script to your Scheme init file:
|
||||
(require 'macro)
|
||||
(require 'repl)
|
||||
(repl:top-level macro:eval)
|
|
@ -1,333 +0,0 @@
|
|||
# Makefile for Scheme Library
|
||||
# Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998 Aubrey Jaffer.
|
||||
|
||||
SHELL = /bin/sh
|
||||
intro:
|
||||
@echo
|
||||
@echo "Welcome to SLIB. Read \"README\" and \"slib.info\" (or"
|
||||
@echo "\"slib.texi\") to learn how to install and use SLIB."
|
||||
@echo
|
||||
@echo
|
||||
-make slib.info
|
||||
|
||||
srcdir=$(HOME)/slib/
|
||||
PREVDOCS = slib/
|
||||
dvidir=../dvi/
|
||||
dvi: $(dvidir)slib.dvi
|
||||
$(dvidir)slib.dvi: version.txi slib.texi $(dvidir)slib.fn schmooz.texi
|
||||
# cd $(dvidir);export TEXINPUTS=$(srcdir):;texi2dvi $(srcdir)slib.texi
|
||||
-(cd $(dvidir);export TEXINPUTS=$(srcdir):;texindex slib.??)
|
||||
cd $(dvidir);export TEXINPUTS=$(srcdir):;tex $(srcdir)slib.texi
|
||||
$(dvidir)slib.fn:
|
||||
cd $(dvidir);export TEXINPUTS=$(srcdir):;tex $(srcdir)slib.texi \
|
||||
$(srcdir)schmooz.texi
|
||||
xdvi: $(dvidir)slib.dvi
|
||||
xdvi -s 6 $(dvidir)slib.dvi
|
||||
htmldir=../public_html/
|
||||
slib_toc.html: version.txi slib.texi htmlform.txi schmooz.texi
|
||||
texi2html -split -verbose slib.texi
|
||||
|
||||
$(PREVDOCS)slib_toc.html:
|
||||
cd slib;make slib_toc.html
|
||||
cd slib;texi2html -split -verbose slib.texi
|
||||
|
||||
html: $(htmldir)slib_toc.html
|
||||
$(htmldir)slib_toc.html: slib slib_toc.html Makefile
|
||||
hitch $(PREVDOCS)slib_\*.html slib_\*.html $(htmldir)
|
||||
|
||||
rpm_prefix=/usr/src/redhat/
|
||||
|
||||
prefix = /usr/local
|
||||
exec_prefix = $(prefix)
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
infodir = $(exec_prefix)/info
|
||||
RUNNABLE = scheme48
|
||||
LIB = $(libdir)/$(RUNNABLE)
|
||||
VM = scheme48vm
|
||||
IMAGE = slib.image
|
||||
INSTALL_DATA = install -c
|
||||
|
||||
slib48.036:
|
||||
(echo ,load `pwd`/scheme48.init; \
|
||||
echo "(define *args* '())"; \
|
||||
echo "(define (program-arguments) (cons \"$(VM)\" *args*))"; \
|
||||
echo ,dump $(LIB)/$(IMAGE); \
|
||||
echo ,exit) | scheme48
|
||||
(echo '#!/bin/sh'; \
|
||||
echo exec '$(LIB)/$(VM)' -i '$(LIB)/$(IMAGE)' \"\$$\@\") \
|
||||
> $(bindir)/slib48
|
||||
chmod +x $(bindir)/slib48
|
||||
|
||||
$(LIB)/slibcat:
|
||||
touch $(LIB)/slibcat
|
||||
|
||||
slib48: $(LIB)/slibcat Makefile
|
||||
(echo ",batch on"; \
|
||||
echo ",config"; \
|
||||
echo ",load =scheme48/misc/packages.scm"; \
|
||||
echo "(define-structure slib-primitives"; \
|
||||
echo " (export s48-error"; \
|
||||
echo " s48-ascii->char"; \
|
||||
echo " s48-force-output"; \
|
||||
echo " s48-current-error-port"; \
|
||||
echo " s48-system";\
|
||||
echo " s48-with-handler";\
|
||||
echo " s48-getenv)";\
|
||||
echo " (open scheme signals ascii extended-ports i/o"; \
|
||||
echo " primitives handle unix-getenv)"; \
|
||||
echo " (begin"; \
|
||||
echo " (define s48-error error)"; \
|
||||
echo " (define s48-ascii->char ascii->char)"; \
|
||||
echo " (define s48-force-output force-output)"; \
|
||||
echo " (define s48-current-error-port current-error-port)"; \
|
||||
echo " (define (s48-system c) (vm-extension 96 c))"; \
|
||||
echo " (define s48-with-handler with-handler)"; \
|
||||
echo " (define s48-getenv getenv)))"; \
|
||||
echo ",user"; \
|
||||
echo ",open slib-primitives"; \
|
||||
echo "(define (implementation-vicinity) \"$(LIB)/\")"; \
|
||||
echo "(define (library-vicinity) \"`pwd`/\")"; \
|
||||
echo ",load scheme48.init"; \
|
||||
echo "(define *args* '())"; \
|
||||
echo "(define (program-arguments) (cons \"scheme48\" *args*))"; \
|
||||
echo "(set! *catalog* #f)"; \
|
||||
echo ",collect"; \
|
||||
echo ",batch off"; \
|
||||
echo ",dump $(IMAGE) \"(slib $(VERSION))\""; \
|
||||
echo ",exit") | scheme48
|
||||
|
||||
install48: slib48
|
||||
$(INSTALL_DATA) $(IMAGE) $(LIB)
|
||||
(echo '#!/bin/sh'; \
|
||||
echo exec $(RUNNABLE) -i '$(LIB)/$(IMAGE)' \"\$$\@\") \
|
||||
> $(bindir)/slib48
|
||||
chmod +x $(bindir)/slib48
|
||||
|
||||
#### Stuff for maintaining SLIB below ####
|
||||
|
||||
VERSION = 2d1
|
||||
ver = $(VERSION)
|
||||
version.txi: Makefile
|
||||
echo @set SLIBVERSION $(VERSION) > version.txi
|
||||
echo @set SLIBDATE `date +"%B %Y"` >> version.txi
|
||||
|
||||
scheme = scm
|
||||
|
||||
htmlform.txi: *.scm
|
||||
$(scheme) -rschmooz -e'(schmooz "slib.texi")'
|
||||
slib.info: version.txi slib.texi htmlform.txi objdoc.txi schmooz.texi
|
||||
makeinfo slib.texi --no-split -o slib.info
|
||||
mv slib.info slib$(VERSION).info
|
||||
if [ -f $(PREVDOCS)slib.info ]; \
|
||||
then infobar $(PREVDOCS)slib.info slib$(VERSION).info slib.info; \
|
||||
else cp slib$(VERSION).info slib.info;fi
|
||||
info: installinfo
|
||||
installinfo: $(infodir)/slib.info
|
||||
$(infodir)/slib.info: slib.info
|
||||
cp -a slib.info $(infodir)/slib.info
|
||||
-install-info $(infodir)/slib.info $(infodir)/dir
|
||||
-rm $(infodir)/slib.info.gz
|
||||
infoz: installinfoz
|
||||
installinfoz: $(infodir)/slib.info.gz
|
||||
$(infodir)/slib.info.gz: $(infodir)/slib.info
|
||||
gzip -f $(infodir)/slib.info
|
||||
|
||||
ffiles = printf.scm format.scm genwrite.scm obj2str.scm pp.scm \
|
||||
ppfile.scm strcase.scm debug.scm trace.scm lineio.scm \
|
||||
strport.scm scanf.scm chap.scm qp.scm break.scm stdio.scm \
|
||||
strsrch.scm prec.scm schmooz.scm
|
||||
lfiles = sort.scm comlist.scm tree.scm logical.scm random.scm tsort.scm \
|
||||
coerce.scm
|
||||
revfiles = sc4opt.scm sc4sc3.scm sc2.scm mularg.scm mulapply.scm \
|
||||
trnscrpt.scm withfile.scm dynwind.scm promise.scm values.scm \
|
||||
eval.scm
|
||||
afiles = ratize.scm randinex.scm modular.scm factor.scm \
|
||||
charplot.scm root.scm minimize.scm cring.scm determ.scm \
|
||||
selfset.scm psxtime.scm cltime.scm timezone.scm tzfile.scm
|
||||
bfiles = collect.scm fluidlet.scm struct.scm object.scm recobj.scm yasyn.scm
|
||||
scfiles = r4rsyn.scm scmacro.scm synclo.scm synrul.scm synchk.scm \
|
||||
repl.scm macwork.scm mwexpand.scm mwdenote.scm mwsynrul.scm
|
||||
scafiles = scainit.scm scaglob.scm scamacr.scm scaoutp.scm scaexpp.scm \
|
||||
structure.scm
|
||||
dfiles = defmacex.scm mbe.scm
|
||||
efiles = record.scm dynamic.scm queue.scm process.scm \
|
||||
priorque.scm hash.scm hashtab.scm alist.scm \
|
||||
wttree.scm wttest.scm array.scm arraymap.scm \
|
||||
sierpinski.scm soundex.scm byte.scm nclients.scm pnm.scm \
|
||||
simetrix.scm
|
||||
rfiles = rdms.scm alistab.scm dbutil.scm paramlst.scm report.scm \
|
||||
batch.scm makcrc.scm dbrowse.scm comparse.scm getopt.scm \
|
||||
htmlform.scm db2html.scm http-cgi.scm getparam.scm glob.scm \
|
||||
fft.scm uri.scm
|
||||
gfiles = tek40.scm tek41.scm
|
||||
docfiles = ANNOUNCE README FAQ slib.info slib.texi schmooz.texi ChangeLog \
|
||||
coerce.txi lineio.txi nclients.txi factor.txi minimize.txi \
|
||||
obj2str.txi randinex.txi random.txi uri.txi db2html.txi \
|
||||
htmlform.txi http-cgi.txi version.txi fmtdoc.txi objdoc.txi
|
||||
mfiles = Makefile require.scm Template.scm syncase.sh mklibcat.scm \
|
||||
Bev2slib.scm slib.spec
|
||||
ifiles = bigloo.init chez.init elk.init macscheme.init \
|
||||
mitscheme.init scheme2c.init scheme48.init gambit.init t3.init \
|
||||
vscm.init mitcomp.pat scm.init scsh.init pscheme.init STk.init \
|
||||
RScheme.init DrScheme.init umbscheme.init
|
||||
tfiles = plottest.scm formatst.scm macrotst.scm scmactst.scm \
|
||||
dwindtst.scm structst.scm
|
||||
sfiles = $(ffiles) $(lfiles) $(revfiles) $(afiles) $(scfiles) $(efiles) \
|
||||
$(rfiles) $(gfiles) $(scafiles) $(dfiles)
|
||||
allfiles = $(docfiles) $(mfiles) $(ifiles) $(sfiles) $(tfiles) $(bfiles)
|
||||
|
||||
makedev = make -f $(HOME)/makefile.dev
|
||||
CHPAT=$(HOME)/bin/chpat
|
||||
RSYNC=rsync -avessh
|
||||
dest = $(HOME)/dist/
|
||||
temp/slib: $(allfiles)
|
||||
-rm -rf temp
|
||||
mkdir temp
|
||||
mkdir temp/slib
|
||||
ln $(allfiles) temp/slib
|
||||
|
||||
infotemp/slib: slib.info
|
||||
-rm -rf infotemp
|
||||
mkdir infotemp
|
||||
mkdir infotemp/slib
|
||||
ln slib.info slib.info-* infotemp/slib
|
||||
#For change-barred HTML.
|
||||
slib:
|
||||
unzip -a $(dest)slib[0-9]*.zip
|
||||
|
||||
distinfo: $(dest)slib.info.zip
|
||||
$(dest)slib.info.zip: infotemp/slib
|
||||
$(makedev) TEMP=infotemp/ DEST=$(dest) PROD=slib ver=.info zip
|
||||
rm -rf infotemp
|
||||
|
||||
release: dist rpm
|
||||
cvs tag -F slib$(VERSION)
|
||||
cp ANNOUNCE $(htmldir)SLIB_ANNOUNCE.txt
|
||||
$(RSYNC) $(htmldir)SLIB.html $(htmldir)SLIB_ANNOUNCE.txt nestle.ai.mit.edu:public_html/
|
||||
$(RSYNC) $(dest)README $(dest)slib$(VERSION).zip \
|
||||
$(dest)slib-$(VERSION)-1.noarch.rpm nestle.ai.mit.edu:dist/
|
||||
# upload $(dest)README $(dest)slib$(VERSION).zip ftp.gnu.org:gnu/jacal/
|
||||
# $(MAKE) indiana
|
||||
indiana:
|
||||
upload $(dest)slib$(VERSION).zip ftp@ftp.cs.indiana.edu:/pub/scheme-repository/incoming
|
||||
echo -e \
|
||||
'I have uploaded slib$(VERSION).zip to ftp.cs.indiana.edu:/pub/scheme-repository/incoming\n' \
|
||||
'for placement into ftp.cs.indiana.edu:/pub/scheme-repository/code/lib/' \
|
||||
| mail -s 'SLIB upload' -b jaffer scheme-repository-request@cs.indiana.edu
|
||||
|
||||
postnews:
|
||||
echo -e "Newsgroups: comp.lang.scheme\n" | cat - ANNOUNCE | \
|
||||
inews -h -O -S \
|
||||
-f "announce@docupress.com (Aubrey Jaffer & Radey Shouman)" \
|
||||
-t "SLIB$(VERSION) Released" -d world
|
||||
|
||||
upzip: $(HOME)/pub/slib.zip
|
||||
$(RSYNC) $(HOME)/pub/slib.zip nestle.ai.mit.edu:pub/
|
||||
|
||||
dist: $(dest)slib$(VERSION).zip
|
||||
$(dest)slib$(VERSION).zip: temp/slib
|
||||
$(makedev) DEST=$(dest) PROD=slib ver=$(VERSION) zip
|
||||
|
||||
rpm: $(dest)slib-$(VERSION)-1.noarch.rpm
|
||||
$(dest)slib-$(VERSION)-1.noarch.rpm: $(dest)slib$(VERSION).zip
|
||||
cp $(dest)slib$(VERSION).zip $(rpm_prefix)SOURCES
|
||||
rpm -bb --clean slib.spec
|
||||
rm $(rpm_prefix)SOURCES/slib$(VERSION).zip
|
||||
mv $(rpm_prefix)RPMS/noarch/slib-$(VERSION)-1.noarch.rpm $(dest)
|
||||
|
||||
shar: slib.shar
|
||||
slib.shar: temp/slib
|
||||
$(makedev) PROD=slib shar
|
||||
dclshar: slib.com
|
||||
com: slib.com
|
||||
slib.com: temp/slib
|
||||
$(makedev) PROD=slib com
|
||||
zip: slib.zip
|
||||
slib.zip: temp/slib
|
||||
$(makedev) PROD=slib zip
|
||||
doszip: /c/scm/dist/slib$(VERSION).zip
|
||||
/c/scm/dist/slib$(VERSION).zip: temp/slib
|
||||
$(makedev) DEST=/c/scm/dist/ PROD=slib ver=$(VERSION) zip
|
||||
zip -d /c/scm/dist/slib$(VERSION).zip slib/slib.info
|
||||
pubzip: temp/slib
|
||||
$(makedev) DEST=$(HOME)/pub/ PROD=slib zip
|
||||
|
||||
diffs: pubdiffs
|
||||
pubdiffs: temp/slib
|
||||
$(makedev) DEST=$(HOME)/pub/ PROD=slib pubdiffs
|
||||
distdiffs: temp/slib
|
||||
$(makedev) DEST=$(dest) PROD=slib ver=$(ver) distdiffs
|
||||
announcediffs: temp/slib
|
||||
$(makedev) DEST=$(dest) PROD=slib ver=$(VERSION) announcediffs
|
||||
|
||||
psdfiles=COPYING.psd README.psd cmuscheme.el comint.el instrum.scm pexpr.scm \
|
||||
primitives.scm psd-slib.scm psd.el read.scm runtime.scm version.scm
|
||||
psdocfiles=article.bbl article.tex manual.bbl manual.tex quick-intro.tex
|
||||
|
||||
psdtemp/slib:
|
||||
-rm -rf psdtemp
|
||||
mkdir psdtemp
|
||||
mkdir psdtemp/slib
|
||||
mkdir psdtemp/slib/psd
|
||||
cd psd; ln $(psdfiles) ../psdtemp/slib/psd
|
||||
mkdir psdtemp/slib/psd/doc
|
||||
cd psd/doc; ln $(psdocfiles) ../../psdtemp/slib/psd/doc
|
||||
|
||||
psdist: $(dest)slib-psd.tar.gz
|
||||
$(dest)slib-psd.tar.gz: psdtemp/slib
|
||||
$(makedev) DEST=$(dest) PROD=slib ver=-psd tar.gz TEMP=psdtemp/
|
||||
|
||||
new:
|
||||
echo `date` \ Aubrey Jaffer \ \<`whoami`@`hostname`\>> change
|
||||
echo>> change
|
||||
echo \ \* require.scm \(*SLIB-VERSION*\): Bumped from $(VERSION) to $(ver).>>change
|
||||
echo>> change
|
||||
cat ChangeLog >> change
|
||||
mv -f change ChangeLog
|
||||
$(CHPAT) slib$(VERSION) slib$(ver) ANNOUNCE FAQ ../scm/ANNOUNCE \
|
||||
../jacal/ANNOUNCE ../wb/README ../wb/ANNOUNCE \
|
||||
../synch/ANNOUNCE \
|
||||
$(htmldir)README.html ../dist/README \
|
||||
$(htmldir)JACAL.html \
|
||||
$(htmldir)SCM.html $(htmldir)Hobbit.html \
|
||||
$(htmldir)SIMSYNCH.html ../scm/scm.texi \
|
||||
/c/scm/dist/install.bat /c/scm/dist/makefile \
|
||||
/c/scm/dist/mkdisk.bat
|
||||
$(CHPAT) slib-$(VERSION) slib-$(ver) ANNOUNCE FAQ ../scm/ANNOUNCE \
|
||||
../jacal/ANNOUNCE ../wb/README ../wb/ANNOUNCE \
|
||||
../synch/ANNOUNCE \
|
||||
$(htmldir)README.html ../dist/README \
|
||||
$(htmldir)JACAL.html \
|
||||
$(htmldir)SCM.html $(htmldir)Hobbit.html \
|
||||
$(htmldir)SIMSYNCH.html ../scm/scm.texi \
|
||||
/c/scm/dist/install.bat /c/scm/dist/makefile \
|
||||
/c/scm/dist/mkdisk.bat
|
||||
$(CHPAT) $(VERSION) $(ver) README slib.texi require.scm Makefile \
|
||||
$(htmldir)SLIB.html slib.spec
|
||||
cvs commit -m '(*SLIB-VERSION*): Bumped from $(VERSION) to $(ver).'
|
||||
cvs tag -F slib$(ver)
|
||||
|
||||
tagfiles = version.txi slib.texi $(mfiles) $(sfiles) $(bfiles) $(tfiles) \
|
||||
$(ifiles)
|
||||
# README and $(ifiles) cause semgentation faults in ETAGS for Emacs version 19.
|
||||
tags: $(tagfiles)
|
||||
etags $(tagfiles)
|
||||
test: $(sfiles)
|
||||
scheme Template.scm $(sfiles)
|
||||
rights:
|
||||
scm -ladmin -e"(admin:check-all)" $(sfiles) $(tfiles) \
|
||||
$(bfiles) $(ifiles)
|
||||
report:
|
||||
scmlit -e"(slib:report #t)"
|
||||
scm -e"(slib:report #t)"
|
||||
clean:
|
||||
-rm -f *~ *.bak *.orig *.rej core a.out *.o \#*
|
||||
-rm -rf *temp
|
||||
distclean: realclean
|
||||
realclean:
|
||||
-rm -f *~ *.bak *.orig *.rej TAGS core a.out *.o \#*
|
||||
-rm -f slib.info* slib.?? slib.???
|
||||
-rm -rf *temp
|
||||
realempty: temp/slib
|
||||
-rm -f $(allfiles)
|
|
@ -1,297 +0,0 @@
|
|||
This directory contains the distribution of Scheme Library slib2d1.
|
||||
Slib conforms to Revised^5 Report on the Algorithmic Language Scheme
|
||||
and the IEEE P1178 specification. Slib supports Unix and similar
|
||||
systems, VMS, and MS-DOS.
|
||||
|
||||
The maintainer can be reached at jaffer @ ai.mit.edu.
|
||||
http://swissnet.ai.mit.edu/~jaffer/SLIB.html
|
||||
|
||||
MANIFEST
|
||||
|
||||
`README' is this file. It contains a MANIFEST, INSTALLATION
|
||||
INSTRUCTIONS, and coding guidelines.
|
||||
`FAQ' Frequently Asked Questions and answers.
|
||||
`ChangeLog' documents changes to slib.
|
||||
`slib.texi' has documentation on library packages in TexInfo format.
|
||||
|
||||
`Template.scm' Example configuration file. Copy and customize to
|
||||
reflect your system.
|
||||
`bigloo.init' is a configuration file for Bigloo.
|
||||
`chez.init' is a configuration file for Chez Scheme.
|
||||
`DrScheme.init' is a configuration file for DrScheme.
|
||||
`elk.init' is a configuration file for ELK 2.1
|
||||
`gambit.init' is a configuration file for Gambit Scheme.
|
||||
`macscheme.init' is a configuration file for MacScheme.
|
||||
`mitscheme.init' is a configuration file for MIT Scheme.
|
||||
`mitcomp.pat' is a patch file which adds definitions to SLIB files
|
||||
for the MitScheme compiler.
|
||||
`pscheme.init' is configuration file for PocketScheme 0.2.5 (WinCE SIOD)
|
||||
`RScheme.init' is a configuration file for RScheme.
|
||||
`scheme2c.init' is a configuration file for DEC's scheme->c.
|
||||
`scheme48.init' is a configuration file for Scheme48.
|
||||
`scsh.init' is a configuration file for Scheme-Shell
|
||||
`scm.init' is a configuration file for SCM.
|
||||
`t3.init' is a configuration file for T3.1 in Scheme mode.
|
||||
`STk.init' is a configuration file for STk.
|
||||
`umbscheme.init' is a configuration file for umb-scheme.
|
||||
`vscm.init' is a configuration file for VSCM.
|
||||
`mklibcat.scm' builds the *catalog* cache.
|
||||
`require.scm' has code which allows system independent access to
|
||||
the library files.
|
||||
|
||||
`Bev2slib.scm' Converts Stephen Bevan's "*.map" files to SLIB catalog entries.
|
||||
`format.scm' has Common-Lisp style format.
|
||||
`formatst.scm' has code to test format.scm
|
||||
`pp.scm' has pretty-print.
|
||||
`ppfile.scm' has pprint-file and pprint-filter-file.
|
||||
`obj2str.scm' has object->string.
|
||||
`strcase.scm' has functions for manipulating the case of strings.
|
||||
`genwrite.scm' has a generic-write which is used by pp.scm,
|
||||
pp2str.scm and obj2str.scm
|
||||
`printf.scm' has printf, fprintf, and sprintf compatible with C.
|
||||
`scanf.scm' has scanf, fscanf, and sscanf compatible by C.
|
||||
`lineio' has line oriented input/output functions.
|
||||
`qp.scm' has printer safe for circular structures.
|
||||
`break.scm' has break and continue.
|
||||
`trace.scm' has trace and untrace for tracing function execution.
|
||||
`debug.scm' has handy higher level debugging aids.
|
||||
`strport.scm' has routines for string-ports.
|
||||
`strsrch.scm' search for chars or substrings in strings and ports.
|
||||
|
||||
`alist.scm' has functions accessing and modifying association lists.
|
||||
`hash.scm' defines hash, hashq, and hashv.
|
||||
`hashtab.scm' has hash tables.
|
||||
`sierpinski.scm' 2-dimensional coordinate hash.
|
||||
`soundex.scm' English name hash.
|
||||
`logical.scm' emulates 2's complement logical operations.
|
||||
`random.scm' has random number generator compatible with Common Lisp.
|
||||
`randinex.scm' has inexact real number distributions.
|
||||
`primes.scm' has primes and probably-prime?.
|
||||
`factor.scm' has factor.
|
||||
`root.scm' has Newton's and Laguerre's methods for finding roots.
|
||||
`minimize.scm' has Golden Section Search for minimum value.
|
||||
`cring.scm' extend + and * to custom commutative rings.
|
||||
`selfset.scm' sets single letter identifiers to their symbols.
|
||||
`determ.scm' compute determinant of list of lists.
|
||||
`charplot.scm' has procedure for plotting on character screens.
|
||||
`plottest.scm' has code to test charplot.scm.
|
||||
`tek40.scm' has routines for Tektronix 4000 series graphics.
|
||||
`tek41.scm' has routines for Tektronix 4100 series graphics.
|
||||
`getopt.scm' has posix-like getopt for parsing command line arguments.
|
||||
`psxtime.scm' has Posix time conversion routines.
|
||||
`cltime.scm' has Common-Lisp time conversion routines.
|
||||
`timezone.scm' has the default time-zone, UTC.
|
||||
`tzfile.scm' reads sysV style (binary) timezone file.
|
||||
`comparse.scm' has shell-like command parsing.
|
||||
|
||||
`rdms.scm' has code to construct a relational database from a base
|
||||
table implementation.
|
||||
`alistab.scm' has association list base tables.
|
||||
`dbutil.scm' has utilities for creating and manipulating relational
|
||||
databases.
|
||||
`htmlform.scm' generates HTML-3.2 with forms.
|
||||
`db2html.scm' convert relational database to hyperlinked tables and
|
||||
pages.
|
||||
`http-cgi.scm' serves WWW pages with HTTP or CGI.
|
||||
`uri.scm' encodes and decodes Uniform Resource Identifiers.
|
||||
`dbrowse.scm' browses relational databases.
|
||||
`paramlst.scm' has procedures for passing parameters by name.
|
||||
`getparam.scm' has procedures for converting getopt to parameters.
|
||||
`report.scm' prints database reports.
|
||||
`schmooz.scm' is a simple, lightweight markup language for
|
||||
interspersing Texinfo documentation with Scheme source code.
|
||||
`glob.scm' has filename matching and manipulation.
|
||||
`batch.scm' Group and execute commands on various operating systems.
|
||||
`makcrc.scm' Create Scheme procedure to calculate POSIX.2 checksums
|
||||
or other CRCs.
|
||||
|
||||
`record.scm' a MITScheme user-definable datatypes package
|
||||
`promise.scm' has code from R4RS for supporting DELAY and FORCE.
|
||||
|
||||
`repl.scm' has a read-eval-print-loop.
|
||||
`defmacex.scm' has defmacro:expand*.
|
||||
`mbe.scm' has "Macro by Example" define-syntax.
|
||||
`scmacro.scm' is a syntactic closure R4RS macro package.
|
||||
r4rsyn.scm, synclo.scm, synrul.scm have syntax definitions
|
||||
and support.
|
||||
`scmactst.scm' is code for testing SYNTACTIC CLOSURE macros.
|
||||
`scainit.scm' is a syntax-case R4RS macro package.
|
||||
scaglob.scm scamacr.scm scaoutp.scm scaexpp.scm have
|
||||
syntax definitions and support. `syncase.sh' is a shell
|
||||
script for producing the SLIB version from the original.
|
||||
`macwork.scm' is a "Macros that work" package.
|
||||
mwexpand.scm mwdenote.scm mwsynrul.scm have support.
|
||||
`macrotst.scm' is code from R4RS for testing macros.
|
||||
|
||||
`values.scm' is multiple values.
|
||||
`queue.scm' has queues and stacks.
|
||||
|
||||
`object.scm' is an object system.
|
||||
`yasyn.scm' defines (syntax-rules) macros for object oriented programming.
|
||||
`collect.scm' is collection operators (like CL sequences).
|
||||
`priorque.scm' has code and documentation for priority queues.
|
||||
`wttree.scm' has weight-balanced trees.
|
||||
`wttest.scm' tests weight-balanced trees.
|
||||
`process.scm' has multi-processing primitives.
|
||||
`array.scm' has multi-dimensional arrays and sub-arrays.
|
||||
`arraymap.scm' has array-map!, array-for-each, and array-indexes.
|
||||
|
||||
`sort.scm' has sorted?, sort, sort!, merge, and merge!.
|
||||
`tsort.scm' has topological-sort.
|
||||
`comlist.scm' has many common list and mapping procedures.
|
||||
`tree.scm' has functions dealing with trees.
|
||||
`coerce.scm' has coerce and type-of from Common-Lisp.
|
||||
`chap.scm' has functions which compare and create strings in
|
||||
"chapter order".
|
||||
|
||||
`sc4opt.scm' has optional rev4 procedures.
|
||||
`sc4sc3.scm' has procedures to make a rev3 implementation run rev4
|
||||
code.
|
||||
`sc2.scm' has rev2 procedures eliminated in subsequent versions.
|
||||
`mularg.scm' redefines - and / to take more than 2 arguments.
|
||||
`mulapply.scm' redefines apply to take more than 2 arguments.
|
||||
`ratize.scm' has function rationalize from Revised^4 spec.
|
||||
`trnscrpt.scm' has transcript-on and transcript-off from Revised^4 spec.
|
||||
`withfile.scm' has with-input-from-file and with-output-to-file from R4RS.
|
||||
`dynwind.scm' has dynamic-wind from R5RS.
|
||||
`eval.scm' has eval with environments from R5RS.
|
||||
`dwindtst.scm' has routines for characterizing dynamic-wind.
|
||||
`dynamic.scm' has DYNAMIC data type [obsolete].
|
||||
`fluidlet.scm' has fluid-let syntax.
|
||||
`struct.scm' has defmacros which implement RECORDS from the book:
|
||||
"Essentials of Programming Languages".
|
||||
`structure.scm' has syntax-case macros for the same.
|
||||
`structst.scm' has test code for struct.scm.
|
||||
`byte.scm' has arrays of small integers.
|
||||
`nclients.scm' provides a Scheme interface to FTP and WWW Browsers.
|
||||
`pnm.scm' provides a Scheme interface to "portable bitmap" files.
|
||||
`simetrix.scm' provides SI Metric Interchange Format.
|
||||
|
||||
INSTALLATION INSTRUCTIONS
|
||||
|
||||
Check the manifest in `README' to find a configuration file for your
|
||||
Scheme implementation. Initialization files for most IEEE P1178
|
||||
compliant Scheme Implementations are included with this distribution.
|
||||
|
||||
If the Scheme implementation supports `getenv', then the value of the
|
||||
shell environment variable SCHEME_LIBRARY_PATH will be used for
|
||||
`(library-vicinity)' if it is defined. Currently, Chez, Elk,
|
||||
MITScheme, scheme->c, VSCM, and SCM support `getenv'. Scheme48
|
||||
supports `getenv' but does not use it for determining
|
||||
`library-vicinity'. (That is done from the Makefile.)
|
||||
|
||||
You should check the definitions of `software-type',
|
||||
`scheme-implementation-version', `implementation-vicinity', and
|
||||
`library-vicinity' in the initialization file. There are comments in
|
||||
the file for how to configure it.
|
||||
|
||||
Once this is done you can modify the startup file for your Scheme
|
||||
implementation to `load' this initialization file. SLIB is then
|
||||
installed.
|
||||
|
||||
Multiple implementations of Scheme can all use the same SLIB
|
||||
directory. Simply configure each implementation's initialization file
|
||||
as outlined above.
|
||||
|
||||
- Implementation: SCM
|
||||
The SCM implementation does not require any initialization file as
|
||||
SLIB support is already built into SCM. See the documentation
|
||||
with SCM for installation instructions.
|
||||
|
||||
- Implementation: VSCM
|
||||
From: Matthias Blume <blume@cs.Princeton.EDU>
|
||||
Date: Tue, 1 Mar 1994 11:42:31 -0500
|
||||
|
||||
Disclaimer: The code below is only a quick hack. If I find some
|
||||
time to spare I might get around to make some more things work.
|
||||
|
||||
You have to provide `vscm.init' as an explicit command line
|
||||
argument. Since this is not very nice I would recommend the
|
||||
following installation procedure:
|
||||
|
||||
1. run scheme
|
||||
|
||||
2. `(load "vscm.init")'
|
||||
|
||||
3. `(slib:dump "dumpfile")'
|
||||
|
||||
4. mv dumpfile place-where-vscm-standard-bootfile-resides e.g.
|
||||
mv dumpfile /usr/local/vscm/lib/scheme-boot (In this case
|
||||
vscm should have been compiled with flag
|
||||
-DDEFAULT_BOOTFILE='"/usr/local/vscm/lib/scheme-boot"'. See
|
||||
Makefile (definition of DDP) for details.)
|
||||
|
||||
|
||||
- Implementation: Scheme48
|
||||
To make a Scheme48 image for an installation under `<prefix>',
|
||||
|
||||
1. `cd' to the SLIB directory
|
||||
|
||||
2. type `make prefix=<prefix> slib48'.
|
||||
|
||||
3. To install the image, type `make prefix=<prefix> install48'.
|
||||
This will also create a shell script with the name `slib48'
|
||||
which will invoke the saved image.
|
||||
|
||||
- Implementation: PLT Scheme
|
||||
- Implementation: DrScheme
|
||||
- Implementation: MzScheme
|
||||
Date: Mon, 2 Oct 2000 21:29:48 -0400 (EDT)
|
||||
From: Shriram Krishnamurthi <sk@cs.brown.edu>
|
||||
|
||||
We distribute an SLIB init file for our system. If you have PLT
|
||||
Scheme (our preferred name for the entire suite, which includes
|
||||
DrScheme, MzScheme and other implementations) installed, you ought
|
||||
to be able to run "help-desk", or run `drscheme' and choose Help
|
||||
Desk from the Help menu; in Help Desk, type `slib'. This will give
|
||||
instructions for how to load the SLIB init file.
|
||||
|
||||
PORTING INSTRUCTIONS
|
||||
|
||||
If there is no initialization file for your Scheme implementation, you
|
||||
will have to create one. Your Scheme implementation must be largely
|
||||
compliant with
|
||||
`IEEE Std 1178-1990',
|
||||
`Revised(4) Report on the Algorithmic Language Scheme', or
|
||||
`Revised(5) Report on the Algorithmic Language Scheme'
|
||||
in order to support SLIB.
|
||||
|
||||
`Template.scm' is an example configuration file. The comments inside
|
||||
will direct you on how to customize it to reflect your system. Give
|
||||
your new initialization file the implementation's name with `.init'
|
||||
appended. For instance, if you were porting `foo-scheme' then the
|
||||
initialization file might be called `foo.init'.
|
||||
|
||||
Your customized version should then be loaded as part of your scheme
|
||||
implementation's initialization. It will load `require.scm' from the
|
||||
library; this will allow the use of `provide', `provided?', and
|
||||
`require' along with the "vicinity" functions. The rest of the
|
||||
library will then be accessible in a system independent fashion.
|
||||
|
||||
Please mail new working configuration files to `jaffer@ai.mit.edu' so
|
||||
that they can be included in the SLIB distribution.
|
||||
|
||||
CODING GUIDELINES
|
||||
|
||||
All library packages are written in IEEE P1178 Scheme and assume that
|
||||
a configuration file and `require.scm' package have already been
|
||||
loaded. Other versions of Scheme can be supported in library packages
|
||||
as well by using, for example, `(provided? 'rev3-report)' or `(require
|
||||
'rev3-report)'.
|
||||
|
||||
`require.scm' defines `*catalog*', an association list of module
|
||||
names and filenames. When a new package is added to the library, an
|
||||
entry should be added to `require.scm'. Local packages can also be
|
||||
added to `*catalog*' and even shadow entries already in the table.
|
||||
|
||||
The module name and `:' should prefix each symbol defined in the
|
||||
package. Definitions for external use should then be exported by having
|
||||
`(define foo module-name:foo)'.
|
||||
|
||||
Submitted packages should not duplicate routines which are already in
|
||||
SLIB files. Use `require' to force those features to be supported in
|
||||
your package. Care should be taken that there are no circularities in
|
||||
the `require's and `load's between the library packages.
|
||||
|
||||
Documentation should be provided in Emacs Texinfo format if possible,
|
||||
But documentation must be provided.
|
|
@ -1,290 +0,0 @@
|
|||
;;;"RScheme.init" Initialization for SLIB for RScheme -*-scheme-*-
|
||||
;;;; From http://www.rscheme.org/rs/pg1/RScheme.scm
|
||||
;;; Author: Aubrey Jaffer
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
;;;
|
||||
;;; adapted for RScheme by Donovan Kolbly -- (v1 1997-09-14)
|
||||
;;;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
;;; UNIX, VMS, MACOS, AMIGA and MS-DOS are supported.
|
||||
|
||||
(define (software-type) 'UNIX)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'RScheme)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page) "http://www.rscheme.org/")
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-version) "0.7.1")
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define (implementation-vicinity)
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/local/lib/rs/0.7.1/")
|
||||
((VMS) "scheme$src:")
|
||||
((MS-DOS) "C:\\scheme\\")))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(or
|
||||
;; Use this getenv if your implementation supports it.
|
||||
(getenv "SCHEME_LIBRARY_PATH")
|
||||
;; Use this path if your scheme does not support GETENV
|
||||
;; or if SCHEME_LIBRARY_PATH is not set.
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/lib/slib/")
|
||||
((VMS) "lib$scheme:")
|
||||
((MS-DOS) "C:\\SLIB\\")
|
||||
(else "")))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
; compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
rev4-report ;conforms to
|
||||
; rev3-report ;conforms to
|
||||
; ieee-p1178 ;conforms to
|
||||
; sicp ;runs code from Structure and
|
||||
;Interpretation of Computer
|
||||
;Programs by Abelson and Sussman.
|
||||
rev4-optional-procedures ;LIST-TAIL, STRING->LIST,
|
||||
;LIST->STRING, STRING-COPY,
|
||||
;STRING-FILL!, LIST->VECTOR,
|
||||
;VECTOR->LIST, and VECTOR-FILL!
|
||||
; rev2-procedures ;SUBSTRING-MOVE-LEFT!,
|
||||
;SUBSTRING-MOVE-RIGHT!,
|
||||
;SUBSTRING-FILL!,
|
||||
;STRING-NULL?, APPEND!, 1+,
|
||||
;-1+, <?, <=?, =?, >?, >=?
|
||||
multiarg/and- ;/ and - can take more than 2 args.
|
||||
multiarg-apply ;APPLY can take more than 2 args.
|
||||
; rationalize
|
||||
delay ;has DELAY and FORCE
|
||||
with-file ;has WITH-INPUT-FROM-FILE and
|
||||
;WITH-OUTPUT-FROM-FILE
|
||||
string-port ;has CALL-WITH-INPUT-STRING and
|
||||
;CALL-WITH-OUTPUT-STRING
|
||||
; transcript ;TRANSCRIPT-ON and TRANSCRIPT-OFF
|
||||
char-ready?
|
||||
; macro ;has R4RS high level macros
|
||||
; defmacro ;has Common Lisp DEFMACRO
|
||||
; eval ;SLIB:EVAL is single argument eval
|
||||
; record ;has user defined data structures
|
||||
; values ;proposed multiple values
|
||||
; dynamic-wind ;proposed dynamic-wind
|
||||
; ieee-floating-point ;conforms to
|
||||
full-continuation ;can return multiple times
|
||||
; object-hash ;has OBJECT-HASH
|
||||
|
||||
; sort
|
||||
; queue ;queues
|
||||
; pretty-print
|
||||
; object->string
|
||||
; format
|
||||
; trace ;has macros: TRACE and UNTRACE
|
||||
; compiler ;has (COMPILER)
|
||||
; ed ;(ED) is editor
|
||||
; system ;posix (system <string>)
|
||||
getenv ;posix (getenv <string>)
|
||||
; program-arguments ;returns list of strings (argv)
|
||||
; Xwindows ;X support
|
||||
; curses ;screen management package
|
||||
; termcap ;terminal description package
|
||||
; terminfo ;sysV terminal description
|
||||
; current-time ;returns time in seconds since 1/1/1970
|
||||
))
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (CURRENT-ERROR-PORT)
|
||||
;(define current-error-port
|
||||
; (let ((port (current-output-port)))
|
||||
; (lambda () port)))
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam (let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(string-append "slib_" (number->string cntr)))))
|
||||
|
||||
;;; (FILE-EXISTS? <string>)
|
||||
(define (file-exists? f) (os-file-exists? f))
|
||||
|
||||
;;; (DELETE-FILE <string>)
|
||||
(define (delete-file f) #f)
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port
|
||||
;;; use this definition if your system doesn't have such a procedure.
|
||||
(define (force-output . arg)
|
||||
(flush-output-port (if (null? arg)
|
||||
(current-output-port)
|
||||
(car arg))))
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-*PUT-FILE.
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 65536)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum #x1FFFFFFF)
|
||||
|
||||
;;; Return argument
|
||||
;;(define (identity x) x)
|
||||
|
||||
;;; If your implementation provides eval SLIB:EVAL is single argument
|
||||
;;; eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
(define *defmacros*
|
||||
(list (cons 'defmacro
|
||||
(lambda (name parms . body)
|
||||
`(set! *defmacros* (cons (cons ',name (lambda ,parms ,@body))
|
||||
*defmacros*))))))
|
||||
(define (defmacro? m) (and (assq m *defmacros*) #t))
|
||||
|
||||
(define (macroexpand-1 e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a) (set! a (assq a *defmacros*))
|
||||
(if a (apply (cdr a) (cdr e)) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define (macroexpand e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a)
|
||||
(set! a (assq a *defmacros*))
|
||||
(if a (macroexpand (apply (cdr a) (cdr e))) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define gentemp
|
||||
(let ((*gensym-counter* -1))
|
||||
(lambda ()
|
||||
(set! *gensym-counter* (+ *gensym-counter* 1))
|
||||
(string->symbol
|
||||
(string-append "slib:G" (number->string *gensym-counter*))))))
|
||||
|
||||
(define base:eval slib:eval)
|
||||
(define (defmacro:eval x) (base:eval (defmacro:expand* x)))
|
||||
(define (defmacro:expand* x)
|
||||
(require 'defmacroexpand) (apply defmacro:expand* x '()))
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;;; define an error procedure for the library
|
||||
(define (slib:error msg . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(error "~a ~j" msg args))
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
;;; Support for older versions of Scheme. Not enough code for its own file.
|
||||
;(define (last-pair l) (if (pair? (cdr l)) (last-pair (cdr l)) l))
|
||||
(define t #t)
|
||||
(define nil #f)
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
|
||||
;(define (1+ n) (+ n 1))
|
||||
;(define (-1+ n) (+ n -1))
|
||||
;(define 1- -1+)
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit (lambda args (process-exit 0)))
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define (slib:load-source f) (load (string-append f ".scm")))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
|
@ -1,256 +0,0 @@
|
|||
;;;"STk.init" SLIB Initialization for STk -*-scheme-*-
|
||||
;;; Authors: Erick Gallesio (eg@unice.fr) and Aubrey Jaffer.
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
(require "unix")
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
;;; UNIX, VMS, MACOS, AMIGA and MSDOS are supported.
|
||||
|
||||
(define (software-type) 'UNIX)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) '|STk|)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page)
|
||||
"http://kaolin.unice.fr/STk/STk.html")
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-version) (version))
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define (implementation-vicinity) "/usr/local/lib/stk/3.99.3/")
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path (or (getenv "SCHEME_LIBRARY_PATH") "/usr/local/lib/slib/")))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;;
|
||||
;;;
|
||||
(define home-vicinity
|
||||
(let ((home-path (or (getenv "HOME") "/")))
|
||||
(lambda () home-path)))
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
rev4-report ;conforms to
|
||||
; rev3-report ;conforms to
|
||||
; ieee-p1178 ;conforms to
|
||||
; sicp ;runs code from Structure and
|
||||
;Interpretation of Computer
|
||||
;Programs by Abelson and Sussman.
|
||||
rev4-optional-procedures ;LIST-TAIL, STRING->LIST,
|
||||
;LIST->STRING, STRING-COPY,
|
||||
;STRING-FILL!, LIST->VECTOR,
|
||||
;VECTOR->LIST, and VECTOR-FILL!
|
||||
; rev3-procedures ;LAST-PAIR, T, and NIL
|
||||
; rev2-procedures ;SUBSTRING-MOVE-LEFT!,
|
||||
;SUBSTRING-MOVE-RIGHT!,
|
||||
;SUBSTRING-FILL!,
|
||||
;STRING-NULL?, APPEND!, 1+,
|
||||
;-1+, <?, <=?, =?, >?, >=?
|
||||
multiarg/and- ;/ and - can take more than 2 args.
|
||||
multiarg-apply ;APPLY can take more than 2 args.
|
||||
; rationalize
|
||||
delay ;has DELAY and FORCE
|
||||
with-file ;has WITH-INPUT-FROM-FILE and
|
||||
;WITH-OUTPUT-FROM-FILE
|
||||
string-port ;has CALL-WITH-INPUT-STRING and
|
||||
;CALL-WITH-OUTPUT-STRING
|
||||
; transcript ;TRANSCRIPT-ON and TRANSCRIPT-OFF
|
||||
; char-ready?
|
||||
; macro ;has R4RS high level macros
|
||||
; defmacro ;has Common Lisp DEFMACRO
|
||||
eval ;SLIB:EVAL is single argument eval
|
||||
; record ;has user defined data structures
|
||||
; values ;proposed multiple values
|
||||
dynamic-wind ;proposed dynamic-wind
|
||||
ieee-floating-point ;conforms to
|
||||
full-continuation ;can return multiple times
|
||||
; object-hash ;has OBJECT-HASH
|
||||
|
||||
; sort ; commented because icomplete
|
||||
; queue ;queues
|
||||
; pretty-print
|
||||
; object->string
|
||||
; format
|
||||
; compiler ;has (COMPILER)
|
||||
ed ;(ED) is editor
|
||||
system ;posix (system <string>)
|
||||
getenv ;posix (getenv <string>)
|
||||
; program-arguments ;returns list of strings (argv)
|
||||
; Xwindows ;X support
|
||||
; curses ;screen management package
|
||||
; termcap ;terminal description package
|
||||
; terminfo ;sysV terminal description
|
||||
))
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam (let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(string-append "slib_" (number->string cntr)))))
|
||||
|
||||
;;; (DELETE-FILE <string>)
|
||||
(define (delete-file f) (system (format #f "/bin/rm ~A" f)))
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port
|
||||
;;; use this definition if your system doesn't have such a procedure.
|
||||
(define (force-output . arg) (apply flush arg))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum #x0fffffff)
|
||||
|
||||
;;; If your implementation provides eval SLIB:EVAL is single argument
|
||||
;;; eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
(define *macros* '())
|
||||
|
||||
(define-macro (defmacro name args . body)
|
||||
`(begin
|
||||
(define-macro (,name ,@args) ,@body)
|
||||
(set! *macros* (cons ,name *macros*))))
|
||||
|
||||
|
||||
(define (defmacro? m) (and (memv m *macros*) #t))
|
||||
|
||||
(define macroexpand-1 MACRO-EXPAND-1)
|
||||
(define macroexpand MACRO-EXPAND)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define gentemp GENSYM)
|
||||
(define base:eval slib:eval)
|
||||
|
||||
(define (defmacro:eval x) (base:eval (defmacro:expand* x)))
|
||||
(define (defmacro:expand* x)
|
||||
(require 'defmacroexpand) (apply defmacro:expand* x '()))
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;;; define an error procedure for the library
|
||||
(define (slib:error . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(error (apply string-append (map (lambda (x) (format #f " ~a" x)) args))))
|
||||
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
(define -1+ 1-)
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit exit)
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define slib:load-source LOAD)
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;;
|
||||
;;; Retain original require/provide before loading "require.scm"
|
||||
;;;
|
||||
(define stk:require require)
|
||||
(define stk:provide provide)
|
||||
(define stk:provided? provided?)
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
||||
|
||||
|
||||
;;;
|
||||
;;; Redefine require/provide so that symbols use SLIB one and strings use STk one
|
||||
;;;
|
||||
|
||||
(define require
|
||||
(let ((slib:require require))
|
||||
(lambda (item)
|
||||
((if (symbol? item) slib:require stk:require) item ))))
|
||||
|
||||
(define provide
|
||||
(let ((slib:provide provide))
|
||||
(lambda (item)
|
||||
((if (symbol? item) slib:provide stk:provide) item))))
|
||||
|
||||
(define provided?
|
||||
(let ((slib:provided? provided?))
|
||||
(lambda (item)
|
||||
((if (symbol? item) slib:provided? stk:provided?) item))))
|
||||
|
||||
(define identity (lambda (x) x))
|
|
@ -1,282 +0,0 @@
|
|||
;;; "Template.scm" configuration template of *features* for Scheme -*-scheme-*-
|
||||
;;; Author: Aubrey Jaffer
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
;;; UNIX, VMS, MACOS, AMIGA and MS-DOS are supported.
|
||||
|
||||
(define (software-type) 'UNIX)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'Template)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page) #f)
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-version) "?")
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define (implementation-vicinity)
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/local/src/scheme/")
|
||||
((VMS) "scheme$src:")
|
||||
((MS-DOS) "C:\\scheme\\")))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(or
|
||||
;; Use this getenv if your implementation supports it.
|
||||
(getenv "SCHEME_LIBRARY_PATH")
|
||||
;; Use this path if your scheme does not support GETENV
|
||||
;; or if SCHEME_LIBRARY_PATH is not set.
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/local/lib/slib/")
|
||||
((VMS) "lib$scheme:")
|
||||
((MS-DOS) "C:\\SLIB\\")
|
||||
(else "")))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define home-vicinity
|
||||
(let ((home-path (getenv "HOME")))
|
||||
(lambda () home-path)))
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
; compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
; rev4-report ;conforms to
|
||||
; rev3-report ;conforms to
|
||||
; ieee-p1178 ;conforms to
|
||||
; sicp ;runs code from Structure and
|
||||
;Interpretation of Computer
|
||||
;Programs by Abelson and Sussman.
|
||||
; rev4-optional-procedures ;LIST-TAIL, STRING->LIST,
|
||||
;LIST->STRING, STRING-COPY,
|
||||
;STRING-FILL!, LIST->VECTOR,
|
||||
;VECTOR->LIST, and VECTOR-FILL!
|
||||
; rev2-procedures ;SUBSTRING-MOVE-LEFT!,
|
||||
;SUBSTRING-MOVE-RIGHT!,
|
||||
;SUBSTRING-FILL!,
|
||||
;STRING-NULL?, APPEND!, 1+,
|
||||
;-1+, <?, <=?, =?, >?, >=?
|
||||
; multiarg/and- ;/ and - can take more than 2 args.
|
||||
; multiarg-apply ;APPLY can take more than 2 args.
|
||||
; rationalize
|
||||
; delay ;has DELAY and FORCE
|
||||
; with-file ;has WITH-INPUT-FROM-FILE and
|
||||
;WITH-OUTPUT-FROM-FILE
|
||||
; string-port ;has CALL-WITH-INPUT-STRING and
|
||||
;CALL-WITH-OUTPUT-STRING
|
||||
; transcript ;TRANSCRIPT-ON and TRANSCRIPT-OFF
|
||||
; char-ready?
|
||||
; macro ;has R4RS high level macros
|
||||
; defmacro ;has Common Lisp DEFMACRO
|
||||
; eval ;R5RS two-argument eval
|
||||
; record ;has user defined data structures
|
||||
; values ;proposed multiple values
|
||||
; dynamic-wind ;proposed dynamic-wind
|
||||
; ieee-floating-point ;conforms to
|
||||
full-continuation ;can return multiple times
|
||||
; object-hash ;has OBJECT-HASH
|
||||
|
||||
; sort
|
||||
; queue ;queues
|
||||
; pretty-print
|
||||
; object->string
|
||||
; format
|
||||
; trace ;has macros: TRACE and UNTRACE
|
||||
; compiler ;has (COMPILER)
|
||||
; ed ;(ED) is editor
|
||||
; system ;posix (system <string>)
|
||||
getenv ;posix (getenv <string>)
|
||||
; program-arguments ;returns list of strings (argv)
|
||||
; Xwindows ;X support
|
||||
; curses ;screen management package
|
||||
; termcap ;terminal description package
|
||||
; terminfo ;sysV terminal description
|
||||
; current-time ;returns time in seconds since 1/1/1970
|
||||
))
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (CURRENT-ERROR-PORT)
|
||||
(define current-error-port
|
||||
(let ((port (current-output-port)))
|
||||
(lambda () port)))
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam (let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(string-append "slib_" (number->string cntr)))))
|
||||
|
||||
;;; (FILE-EXISTS? <string>)
|
||||
(define (file-exists? f) #f)
|
||||
|
||||
;;; (DELETE-FILE <string>)
|
||||
(define (delete-file f) #f)
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port
|
||||
;;; use this definition if your system doesn't have such a procedure.
|
||||
(define (force-output . arg) #t)
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-*PUT-FILE.
|
||||
|
||||
;;; "rationalize" adjunct procedures.
|
||||
;;(define (find-ratio x e)
|
||||
;; (let ((rat (rationalize x e)))
|
||||
;; (list (numerator rat) (denominator rat))))
|
||||
;;(define (find-ratio-between x y)
|
||||
;; (find-ratio (/ (+ x y) 2) (/ (- x y) 2)))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum #x0FFFFFFF)
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
(define *defmacros*
|
||||
(list (cons 'defmacro
|
||||
(lambda (name parms . body)
|
||||
`(set! *defmacros* (cons (cons ',name (lambda ,parms ,@body))
|
||||
*defmacros*))))))
|
||||
(define (defmacro? m) (and (assq m *defmacros*) #t))
|
||||
|
||||
(define (macroexpand-1 e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a) (set! a (assq a *defmacros*))
|
||||
(if a (apply (cdr a) (cdr e)) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define (macroexpand e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a)
|
||||
(set! a (assq a *defmacros*))
|
||||
(if a (macroexpand (apply (cdr a) (cdr e))) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define gentemp
|
||||
(let ((*gensym-counter* -1))
|
||||
(lambda ()
|
||||
(set! *gensym-counter* (+ *gensym-counter* 1))
|
||||
(string->symbol
|
||||
(string-append "slib:G" (number->string *gensym-counter*))))))
|
||||
|
||||
(define base:eval slib:eval)
|
||||
(define (defmacro:eval x) (base:eval (defmacro:expand* x)))
|
||||
(define (defmacro:expand* x)
|
||||
(require 'defmacroexpand) (apply defmacro:expand* x '()))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;;; define an error procedure for the library
|
||||
(define (slib:error . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(apply error args))
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
;;; Support for older versions of Scheme. Not enough code for its own file.
|
||||
(define (last-pair l) (if (pair? (cdr l)) (last-pair (cdr l)) l))
|
||||
(define t #t)
|
||||
(define nil #f)
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
|
||||
;(define (1+ n) (+ n 1))
|
||||
;(define (-1+ n) (+ n -1))
|
||||
;(define 1- -1+)
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit (lambda args #f))
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define (slib:load-source f) (load (string-append f ".scm")))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
|
@ -1,66 +0,0 @@
|
|||
;;;"alist.scm", alist functions for Scheme.
|
||||
;;;Copyright (c) 1992, 1993 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(define (predicate->asso pred)
|
||||
(cond ((eq? eq? pred) assq)
|
||||
((eq? = pred) assv)
|
||||
((eq? eqv? pred) assv)
|
||||
((eq? char=? pred) assv)
|
||||
((eq? equal? pred) assoc)
|
||||
((eq? string=? pred) assoc)
|
||||
(else (lambda (key alist)
|
||||
(let l ((al alist))
|
||||
(cond ((null? al) #f)
|
||||
((pred key (caar al)) (car al))
|
||||
(else (l (cdr al)))))))))
|
||||
|
||||
(define (alist-inquirer pred)
|
||||
(let ((assofun (predicate->asso pred)))
|
||||
(lambda (alist key)
|
||||
(let ((pair (assofun key alist)))
|
||||
(and pair (cdr pair))))))
|
||||
|
||||
(define (alist-associator pred)
|
||||
(let ((assofun (predicate->asso pred)))
|
||||
(lambda (alist key val)
|
||||
(let* ((pair (assofun key alist)))
|
||||
(cond (pair (set-cdr! pair val)
|
||||
alist)
|
||||
(else (cons (cons key val) alist)))))))
|
||||
|
||||
(define (alist-remover pred)
|
||||
(lambda (alist key)
|
||||
(cond ((null? alist) alist)
|
||||
((pred key (caar alist)) (cdr alist))
|
||||
((null? (cdr alist)) alist)
|
||||
((pred key (caadr alist))
|
||||
(set-cdr! alist (cddr alist)) alist)
|
||||
(else
|
||||
(let l ((al (cdr alist)))
|
||||
(cond ((null? (cdr al)) alist)
|
||||
((pred key (caadr al))
|
||||
(set-cdr! al (cddr al)) alist)
|
||||
(else (l (cdr al)))))))))
|
||||
|
||||
(define (alist-map proc alist)
|
||||
(map (lambda (pair) (cons (car pair) (proc (car pair) (cdr pair))))
|
||||
alist))
|
||||
|
||||
(define (alist-for-each proc alist)
|
||||
(for-each (lambda (pair) (proc (car pair) (cdr pair))) alist))
|
|
@ -1,352 +0,0 @@
|
|||
;;; "alistab.scm" database tables using association lists (assoc)
|
||||
; Copyright 1994, 1997 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; LLDB is (filename . alist-table)
|
||||
;;; HANDLE is (#(table-name key-dim) . TABLE)
|
||||
;;; TABLE is an alist of (Primary-key . ROW)
|
||||
;;; ROW is a list of non-primary VALUEs
|
||||
|
||||
(require 'common-list-functions)
|
||||
|
||||
(define alist-table
|
||||
(let ((catalog-id 0)
|
||||
(resources '*base-resources*)
|
||||
(make-list-keyifier (lambda (prinum types) identity))
|
||||
(make-keyifier-1 (lambda (type) list))
|
||||
(make-key->list (lambda (prinum types) identity))
|
||||
(make-key-extractor (lambda (primary-limit column-type-list index)
|
||||
(let ((i (+ -1 index)))
|
||||
(lambda (lst) (list-ref lst i))))))
|
||||
|
||||
(define keyify-1 (make-keyifier-1 'atom))
|
||||
|
||||
(define (make-base filename dim types)
|
||||
(list filename
|
||||
(list catalog-id)
|
||||
(list resources (list 'free-id 1))))
|
||||
|
||||
(define (open-base infile writable)
|
||||
(and (or (input-port? infile) (file-exists? infile))
|
||||
(cons (if (input-port? infile) #f infile)
|
||||
((lambda (fun)
|
||||
(if (input-port? infile)
|
||||
(fun infile)
|
||||
(call-with-input-file infile fun)))
|
||||
read))))
|
||||
|
||||
(define (write-base lldb outfile)
|
||||
((lambda (fun)
|
||||
(cond ((output-port? outfile) (fun outfile))
|
||||
((string? outfile) (call-with-output-file outfile fun))
|
||||
(else #f)))
|
||||
(lambda (port)
|
||||
(display (string-append
|
||||
";;; \"" outfile "\" SLIB alist-table database -*-scheme-*-")
|
||||
port)
|
||||
(newline port) (newline port)
|
||||
(display "(" port) (newline port)
|
||||
(for-each
|
||||
(lambda (table)
|
||||
(display " (" port)
|
||||
(write (car table) port) (newline port)
|
||||
(for-each
|
||||
(lambda (row)
|
||||
(display " " port) (write row port) (newline port))
|
||||
(cdr table))
|
||||
(display " )" port) (newline port))
|
||||
(cdr lldb))
|
||||
(display ")" port) (newline port)
|
||||
; (require 'pretty-print)
|
||||
; (pretty-print (cdr lldb) port)
|
||||
(set-car! lldb (if (string? outfile) outfile #f))
|
||||
#t)))
|
||||
|
||||
(define (sync-base lldb)
|
||||
(cond ((car lldb) (write-base lldb (car lldb)) #t)
|
||||
(else
|
||||
;;; (display "sync-base: database filename not known")
|
||||
#f)))
|
||||
|
||||
(define (close-base lldb)
|
||||
(cond ((car lldb) (write-base lldb (car lldb))
|
||||
(set-cdr! lldb #f)
|
||||
(set-car! lldb #f) #t)
|
||||
((cdr lldb) (set-cdr! lldb #f)
|
||||
(set-car! lldb #f) #t)
|
||||
(else
|
||||
;;; (display "close-base: database not open")
|
||||
#f)))
|
||||
|
||||
(define (make-table lldb dim types)
|
||||
(let ((free-hand (open-table lldb resources 1 '(atom integer))))
|
||||
(and free-hand
|
||||
(let* ((row (assoc* (keyify-1 'free-id) (handle->alist free-hand)))
|
||||
(table-id #f))
|
||||
(cond (row
|
||||
(set! table-id (cadr row))
|
||||
(set-car! (cdr row) (+ 1 table-id))
|
||||
(set-cdr! lldb (cons (list table-id) (cdr lldb)))
|
||||
table-id)
|
||||
(else #f))))))
|
||||
|
||||
(define (open-table lldb base-id dim types)
|
||||
(assoc base-id (cdr lldb)))
|
||||
|
||||
(define (kill-table lldb base-id dim types)
|
||||
(define ckey (list base-id))
|
||||
(let ((pair (assoc* ckey (cdr lldb))))
|
||||
(and pair (set-cdr! lldb (delete-assoc ckey (cdr lldb))))
|
||||
(and pair (not (assoc* ckey (cdr lldb))))))
|
||||
|
||||
(define handle->alist cdr)
|
||||
(define set-handle-alist! set-cdr!)
|
||||
|
||||
(define (assoc* keys alist)
|
||||
(let ((pair (assoc (car keys) alist)))
|
||||
(cond ((not pair) #f)
|
||||
((null? (cdr keys)) pair)
|
||||
(else (assoc* (cdr keys) (cdr pair))))))
|
||||
|
||||
(define (make-assoc* keys alist vals)
|
||||
(let ((pair (assoc (car keys) alist)))
|
||||
(cond ((not pair) (cons (cons (car keys)
|
||||
(if (null? (cdr keys))
|
||||
vals
|
||||
(make-assoc* (cdr keys) '() vals)))
|
||||
alist))
|
||||
(else (set-cdr! pair (if (null? (cdr keys))
|
||||
vals
|
||||
(make-assoc* (cdr keys) (cdr pair) vals)))
|
||||
alist))))
|
||||
|
||||
(define (delete-assoc ckey alist)
|
||||
(cond
|
||||
((null? ckey) '())
|
||||
((assoc (car ckey) alist)
|
||||
=> (lambda (match)
|
||||
(let ((adl (delete-assoc (cdr ckey) (cdr match))))
|
||||
(cond ((null? adl) (delete match alist))
|
||||
(else (set-cdr! match adl) alist)))))
|
||||
(else alist)))
|
||||
|
||||
(define (delete-assoc* ckey alist)
|
||||
(cond
|
||||
((every not ckey) '()) ;includes the null case.
|
||||
((not (car ckey))
|
||||
(delete '()
|
||||
(map (lambda (fodder)
|
||||
(let ((adl (delete-assoc* (cdr ckey) (cdr fodder))))
|
||||
(if (null? adl) '() (cons (car fodder) adl))))
|
||||
alist)))
|
||||
((procedure? (car ckey))
|
||||
(delete '()
|
||||
(map (lambda (fodder)
|
||||
(if ((car ckey) (car fodder))
|
||||
(let ((adl (delete-assoc* (cdr ckey) (cdr fodder))))
|
||||
(if (null? adl) '() (cons (car fodder) adl)))
|
||||
fodder))
|
||||
alist)))
|
||||
((assoc (car ckey) alist)
|
||||
=> (lambda (match)
|
||||
(let ((adl (delete-assoc* (cdr ckey) (cdr match))))
|
||||
(cond ((null? adl) (delete match alist))
|
||||
(else (set-cdr! match adl) alist)))))
|
||||
(else alist)))
|
||||
|
||||
(define (assoc*-for-each proc bkey ckey alist)
|
||||
(cond ((null? ckey) (proc (reverse bkey)))
|
||||
((not (car ckey))
|
||||
(for-each (lambda (alist)
|
||||
(assoc*-for-each proc
|
||||
(cons (car alist) bkey)
|
||||
(cdr ckey)
|
||||
(cdr alist)))
|
||||
alist))
|
||||
((procedure? (car ckey))
|
||||
(for-each (lambda (alist)
|
||||
(if ((car ckey) (car alist))
|
||||
(assoc*-for-each proc
|
||||
(cons (car alist) bkey)
|
||||
(cdr ckey)
|
||||
(cdr alist))))
|
||||
alist))
|
||||
((assoc (car ckey) alist)
|
||||
=> (lambda (match)
|
||||
(assoc*-for-each proc
|
||||
(cons (car match) bkey)
|
||||
(cdr ckey)
|
||||
(cdr match))))))
|
||||
|
||||
(define (assoc*-map proc bkey ckey alist)
|
||||
(cond ((null? ckey) (list (proc (reverse bkey))))
|
||||
((not (car ckey))
|
||||
(apply append
|
||||
(map (lambda (alist)
|
||||
(assoc*-map proc
|
||||
(cons (car alist) bkey)
|
||||
(cdr ckey)
|
||||
(cdr alist)))
|
||||
alist)))
|
||||
((procedure? (car ckey))
|
||||
(apply append
|
||||
(map (lambda (alist)
|
||||
(if ((car ckey) (car alist))
|
||||
(assoc*-map proc
|
||||
(cons (car alist) bkey)
|
||||
(cdr ckey)
|
||||
(cdr alist))
|
||||
'()))
|
||||
alist)))
|
||||
((assoc (car ckey) alist)
|
||||
=> (lambda (match)
|
||||
(assoc*-map proc
|
||||
(cons (car match) bkey)
|
||||
(cdr ckey)
|
||||
(cdr match))))
|
||||
(else '())))
|
||||
|
||||
(define (sorted-assoc*-for-each proc bkey ckey alist)
|
||||
(cond ((null? ckey) (proc (reverse bkey)))
|
||||
((not (car ckey))
|
||||
(for-each (lambda (alist)
|
||||
(sorted-assoc*-for-each proc
|
||||
(cons (car alist) bkey)
|
||||
(cdr ckey)
|
||||
(cdr alist)))
|
||||
(alist-sort! alist)))
|
||||
((procedure? (car ckey))
|
||||
(sorted-assoc*-for-each proc
|
||||
bkey
|
||||
(cons #f (cdr ckey))
|
||||
(remove-if-not (lambda (pair)
|
||||
((car ckey) (car pair)))
|
||||
alist)))
|
||||
((assoc (car ckey) alist)
|
||||
=> (lambda (match)
|
||||
(sorted-assoc*-for-each proc
|
||||
(cons (car match) bkey)
|
||||
(cdr ckey)
|
||||
(cdr match))))))
|
||||
|
||||
(define (alist-sort! alist)
|
||||
(define (key->sortable k)
|
||||
(cond ((number? k) k)
|
||||
((string? k) k)
|
||||
((symbol? k) (symbol->string k))
|
||||
((vector? k) (map key->sortable (vector->list k)))
|
||||
(else (slib:error "unsortable key" k))))
|
||||
;; This routine assumes that the car of its operands are either
|
||||
;; numbers or strings (or lists of those).
|
||||
(define (car-key-< x y)
|
||||
(key-< (car x) (car y)))
|
||||
(define (key-< x y)
|
||||
(cond ((and (number? x) (number? y)) (< x y))
|
||||
((number? x) #t)
|
||||
((number? y) #f)
|
||||
((string? x) (string<? x y))
|
||||
((key-< (car x) (car y)) #t)
|
||||
((key-< (car y) (car x)) #f)
|
||||
(else (key-< (cdr x) (cdr y)))))
|
||||
(require 'sort)
|
||||
(map cdr (sort! (map (lambda (p)
|
||||
(cons (key->sortable (car p)) p))
|
||||
alist)
|
||||
car-key-<)))
|
||||
|
||||
(define (present? handle ckey)
|
||||
(assoc* ckey (handle->alist handle)))
|
||||
|
||||
(define (make-putter prinum types)
|
||||
(lambda (handle ckey restcols)
|
||||
(set-handle-alist! handle
|
||||
(make-assoc* ckey (handle->alist handle) restcols))))
|
||||
|
||||
(define (make-getter prinum types)
|
||||
(lambda (handle ckey)
|
||||
(let ((row (assoc* ckey (handle->alist handle))))
|
||||
(and row (cdr row)))))
|
||||
|
||||
(define (for-each-key handle operation primary-limit column-type-list match-keys)
|
||||
(assoc*-for-each operation
|
||||
'()
|
||||
match-keys
|
||||
(handle->alist handle)))
|
||||
|
||||
(define (map-key handle operation primary-limit column-type-list match-keys)
|
||||
(assoc*-map operation
|
||||
'()
|
||||
match-keys
|
||||
(handle->alist handle)))
|
||||
|
||||
(define (ordered-for-each-key handle operation
|
||||
primary-limit column-type-list match-keys)
|
||||
(sorted-assoc*-for-each operation
|
||||
'()
|
||||
match-keys
|
||||
(handle->alist handle)))
|
||||
|
||||
(define (supported-type? type)
|
||||
(case type
|
||||
((base-id atom integer boolean string symbol expression number) #t)
|
||||
(else #f)))
|
||||
|
||||
(define (supported-key-type? type)
|
||||
(case type
|
||||
((atom integer number symbol string) #t)
|
||||
(else #f)))
|
||||
|
||||
;;make-table open-table remover assoc* make-assoc*
|
||||
;;(trace assoc*-for-each assoc*-map sorted-assoc*-for-each)
|
||||
|
||||
(lambda (operation-name)
|
||||
(case operation-name
|
||||
((make-base) make-base)
|
||||
((open-base) open-base)
|
||||
((write-base) write-base)
|
||||
((sync-base) sync-base)
|
||||
((close-base) close-base)
|
||||
((catalog-id) catalog-id)
|
||||
((make-table) make-table)
|
||||
((open-table) open-table)
|
||||
((kill-table) kill-table)
|
||||
((make-keyifier-1) make-keyifier-1)
|
||||
((make-list-keyifier) make-list-keyifier)
|
||||
((make-key->list) make-key->list)
|
||||
((make-key-extractor) make-key-extractor)
|
||||
((supported-type?) supported-type?)
|
||||
((supported-key-type?) supported-key-type?)
|
||||
((present?) present?)
|
||||
((make-putter) make-putter)
|
||||
((make-getter) make-getter)
|
||||
((delete)
|
||||
(lambda (handle ckey)
|
||||
(set-handle-alist! handle
|
||||
(delete-assoc ckey (handle->alist handle)))))
|
||||
((delete*)
|
||||
(lambda (handle primary-limit column-type-list match-keys)
|
||||
(set-handle-alist! handle
|
||||
(delete-assoc* match-keys
|
||||
(handle->alist handle)))))
|
||||
((for-each-key) for-each-key)
|
||||
((map-key) map-key)
|
||||
((ordered-for-each-key) ordered-for-each-key)
|
||||
(else #f)))
|
||||
))
|
||||
|
||||
;; #f (trace-all "/home/jaffer/slib/alistab.scm") (untrace alist-table) (set! *qp-width* 333)
|
|
@ -1,279 +0,0 @@
|
|||
;;;;"array.scm" Arrays for Scheme
|
||||
; Copyright (C) 1993 Alan Bawden
|
||||
;
|
||||
; Permission to copy this software, to redistribute it, and to use it
|
||||
; for any purpose is granted, subject to the following restrictions and
|
||||
; understandings.
|
||||
;
|
||||
; 1. Any copy made of this software must include this copyright notice
|
||||
; in full.
|
||||
;
|
||||
; 2. Users of this software agree to make their best efforts (a) to
|
||||
; return to me any improvements or extensions that they make, so that
|
||||
; these may be included in future releases; and (b) to inform me of
|
||||
; noteworthy uses of this software.
|
||||
;
|
||||
; 3. I have made no warrantee or representation that the operation of
|
||||
; this software will be error-free, and I am under no obligation to
|
||||
; provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
; 4. In conjunction with products arising from the use of this material,
|
||||
; there shall be no use of my name in any advertising, promotional, or
|
||||
; sales literature without prior written consent in each case.
|
||||
;
|
||||
; Alan Bawden
|
||||
; MIT Room NE43-510
|
||||
; 545 Tech. Sq.
|
||||
; Cambridge, MA 02139
|
||||
; Alan@LCS.MIT.EDU
|
||||
|
||||
(require 'record)
|
||||
|
||||
;(declare (usual-integrations))
|
||||
|
||||
(define array:rtd
|
||||
(make-record-type "Array"
|
||||
'(indexer ; Must be a -linear- function!
|
||||
shape ; Inclusive bounds: ((lower upper) ...)
|
||||
vector ; The actual contents
|
||||
)))
|
||||
|
||||
(define array:indexer (record-accessor array:rtd 'indexer))
|
||||
(define array-shape (record-accessor array:rtd 'shape))
|
||||
(define array:vector (record-accessor array:rtd 'vector))
|
||||
|
||||
(define array? (record-predicate array:rtd))
|
||||
|
||||
(define (array-rank obj)
|
||||
(if (array? obj) (length (array-shape obj)) 0))
|
||||
|
||||
(define (array-dimensions ra)
|
||||
(map (lambda (ind) (if (zero? (car ind)) (+ 1 (cadr ind)) ind))
|
||||
(array-shape ra)))
|
||||
|
||||
(define array:construct
|
||||
(record-constructor array:rtd '(shape vector indexer)))
|
||||
|
||||
(define (array:compute-shape specs)
|
||||
(map (lambda (spec)
|
||||
(cond ((and (integer? spec)
|
||||
(< 0 spec))
|
||||
(list 0 (- spec 1)))
|
||||
((and (pair? spec)
|
||||
(pair? (cdr spec))
|
||||
(null? (cddr spec))
|
||||
(integer? (car spec))
|
||||
(integer? (cadr spec))
|
||||
(<= (car spec) (cadr spec)))
|
||||
spec)
|
||||
(else (slib:error "array: Bad array dimension: " spec))))
|
||||
specs))
|
||||
|
||||
(define (make-array initial-value . specs)
|
||||
(let ((shape (array:compute-shape specs)))
|
||||
(let loop ((size 1)
|
||||
(indexer (lambda () 0))
|
||||
(l (reverse shape)))
|
||||
(if (null? l)
|
||||
(array:construct shape
|
||||
(make-vector size initial-value)
|
||||
(array:optimize-linear-function indexer shape))
|
||||
(loop (* size (+ 1 (- (cadar l) (caar l))))
|
||||
(lambda (first-index . rest-of-indices)
|
||||
(+ (* size (- first-index (caar l)))
|
||||
(apply indexer rest-of-indices)))
|
||||
(cdr l))))))
|
||||
|
||||
(define (make-shared-array array mapping . specs)
|
||||
(let ((new-shape (array:compute-shape specs))
|
||||
(old-indexer (array:indexer array)))
|
||||
(let check ((indices '())
|
||||
(bounds (reverse new-shape)))
|
||||
(cond ((null? bounds)
|
||||
(array:check-bounds array (apply mapping indices)))
|
||||
(else
|
||||
(check (cons (caar bounds) indices) (cdr bounds))
|
||||
(check (cons (cadar bounds) indices) (cdr bounds)))))
|
||||
(array:construct new-shape
|
||||
(array:vector array)
|
||||
(array:optimize-linear-function
|
||||
(lambda indices
|
||||
(apply old-indexer (apply mapping indices)))
|
||||
new-shape))))
|
||||
|
||||
(define (array:in-bounds? array indices)
|
||||
(let loop ((indices indices)
|
||||
(shape (array-shape array)))
|
||||
(if (null? indices)
|
||||
(null? shape)
|
||||
(let ((index (car indices)))
|
||||
(and (not (null? shape))
|
||||
(integer? index)
|
||||
(<= (caar shape) index (cadar shape))
|
||||
(loop (cdr indices) (cdr shape)))))))
|
||||
|
||||
(define (array:check-bounds array indices)
|
||||
(or (array:in-bounds? array indices)
|
||||
(slib:error "array: Bad indices for " array indices)))
|
||||
|
||||
(define (array-ref array . indices)
|
||||
(array:check-bounds array indices)
|
||||
(vector-ref (array:vector array)
|
||||
(apply (array:indexer array) indices)))
|
||||
|
||||
(define (array-set! array new-value . indices)
|
||||
(array:check-bounds array indices)
|
||||
(vector-set! (array:vector array)
|
||||
(apply (array:indexer array) indices)
|
||||
new-value))
|
||||
|
||||
(define (array-in-bounds? array . indices)
|
||||
(array:in-bounds? array indices))
|
||||
|
||||
; Fast versions of ARRAY-REF and ARRAY-SET! that do no error checking,
|
||||
; and don't cons intermediate lists of indices:
|
||||
|
||||
(define (array-1d-ref a i0)
|
||||
(vector-ref (array:vector a) ((array:indexer a) i0)))
|
||||
|
||||
(define (array-2d-ref a i0 i1)
|
||||
(vector-ref (array:vector a) ((array:indexer a) i0 i1)))
|
||||
|
||||
(define (array-3d-ref a i0 i1 i2)
|
||||
(vector-ref (array:vector a) ((array:indexer a) i0 i1 i2)))
|
||||
|
||||
(define (array-1d-set! a v i0)
|
||||
(vector-set! (array:vector a) ((array:indexer a) i0) v))
|
||||
|
||||
(define (array-2d-set! a v i0 i1)
|
||||
(vector-set! (array:vector a) ((array:indexer a) i0 i1) v))
|
||||
|
||||
(define (array-3d-set! a v i0 i1 i2)
|
||||
(vector-set! (array:vector a) ((array:indexer a) i0 i1 i2) v))
|
||||
|
||||
; STOP! Do not read beyond this point on your first reading of
|
||||
; this code -- you should simply assume that the rest of this file
|
||||
; contains only the following single definition:
|
||||
;
|
||||
; (define (array:optimize-linear-function f l) f)
|
||||
;
|
||||
; Of course everything would be pretty inefficient if this were really the
|
||||
; case, but it isn't. The following code takes advantage of the fact that
|
||||
; you can learn everything there is to know from a linear function by
|
||||
; simply probing around in its domain and observing its values -- then a
|
||||
; more efficient equivalent can be constructed.
|
||||
|
||||
(define (array:optimize-linear-function f l)
|
||||
(let ((d (length l)))
|
||||
(cond
|
||||
((= d 0)
|
||||
(array:0d-c (f)))
|
||||
((= d 1)
|
||||
(let ((c (f 0)))
|
||||
(array:1d-c0 c (- (f 1) c))))
|
||||
((= d 2)
|
||||
(let ((c (f 0 0)))
|
||||
(array:2d-c01 c (- (f 1 0) c) (- (f 0 1) c))))
|
||||
((= d 3)
|
||||
(let ((c (f 0 0 0)))
|
||||
(array:3d-c012 c (- (f 1 0 0) c) (- (f 0 1 0) c) (- (f 0 0 1) c))))
|
||||
(else
|
||||
(let* ((v (map (lambda (x) 0) l))
|
||||
(c (apply f v)))
|
||||
(let loop ((p v)
|
||||
(old-val c)
|
||||
(coefs '()))
|
||||
(cond ((null? p)
|
||||
(array:Nd-c* c (reverse coefs)))
|
||||
(else
|
||||
(set-car! p 1)
|
||||
(let ((new-val (apply f v)))
|
||||
(loop (cdr p)
|
||||
new-val
|
||||
(cons (- new-val old-val) coefs)))))))))))
|
||||
|
||||
; 0D cases:
|
||||
|
||||
(define (array:0d-c c)
|
||||
(lambda () c))
|
||||
|
||||
; 1D cases:
|
||||
|
||||
(define (array:1d-c c)
|
||||
(lambda (i0) (+ c i0)))
|
||||
|
||||
(define (array:1d-0 n0)
|
||||
(cond ((= 1 n0) +)
|
||||
(else (lambda (i0) (* n0 i0)))))
|
||||
|
||||
(define (array:1d-c0 c n0)
|
||||
(cond ((= 0 c) (array:1d-0 n0))
|
||||
((= 1 n0) (array:1d-c c))
|
||||
(else (lambda (i0) (+ c (* n0 i0))))))
|
||||
|
||||
; 2D cases:
|
||||
|
||||
(define (array:2d-0 n0)
|
||||
(lambda (i0 i1) (+ (* n0 i0) i1)))
|
||||
|
||||
(define (array:2d-1 n1)
|
||||
(lambda (i0 i1) (+ i0 (* n1 i1))))
|
||||
|
||||
(define (array:2d-c0 c n0)
|
||||
(lambda (i0 i1) (+ c (* n0 i0) i1)))
|
||||
|
||||
(define (array:2d-c1 c n1)
|
||||
(lambda (i0 i1) (+ c i0 (* n1 i1))))
|
||||
|
||||
(define (array:2d-01 n0 n1)
|
||||
(cond ((= 1 n0) (array:2d-1 n1))
|
||||
((= 1 n1) (array:2d-0 n0))
|
||||
(else (lambda (i0 i1) (+ (* n0 i0) (* n1 i1))))))
|
||||
|
||||
(define (array:2d-c01 c n0 n1)
|
||||
(cond ((= 0 c) (array:2d-01 n0 n1))
|
||||
((= 1 n0) (array:2d-c1 c n1))
|
||||
((= 1 n1) (array:2d-c0 c n0))
|
||||
(else (lambda (i0 i1) (+ c (* n0 i0) (* n1 i1))))))
|
||||
|
||||
; 3D cases:
|
||||
|
||||
(define (array:3d-01 n0 n1)
|
||||
(lambda (i0 i1 i2) (+ (* n0 i0) (* n1 i1) i2)))
|
||||
|
||||
(define (array:3d-02 n0 n2)
|
||||
(lambda (i0 i1 i2) (+ (* n0 i0) i1 (* n2 i2))))
|
||||
|
||||
(define (array:3d-12 n1 n2)
|
||||
(lambda (i0 i1 i2) (+ i0 (* n1 i1) (* n2 i2))))
|
||||
|
||||
(define (array:3d-c12 c n1 n2)
|
||||
(lambda (i0 i1 i2) (+ c i0 (* n1 i1) (* n2 i2))))
|
||||
|
||||
(define (array:3d-c02 c n0 n2)
|
||||
(lambda (i0 i1 i2) (+ c (* n0 i0) i1 (* n2 i2))))
|
||||
|
||||
(define (array:3d-c01 c n0 n1)
|
||||
(lambda (i0 i1 i2) (+ c (* n0 i0) (* n1 i1) i2)))
|
||||
|
||||
(define (array:3d-012 n0 n1 n2)
|
||||
(cond ((= 1 n0) (array:3d-12 n1 n2))
|
||||
((= 1 n1) (array:3d-02 n0 n2))
|
||||
((= 1 n2) (array:3d-01 n0 n1))
|
||||
(else (lambda (i0 i1 i2) (+ (* n0 i0) (* n1 i1) (* n2 i2))))))
|
||||
|
||||
(define (array:3d-c012 c n0 n1 n2)
|
||||
(cond ((= 0 c) (array:3d-012 n0 n1 n2))
|
||||
((= 1 n0) (array:3d-c12 c n1 n2))
|
||||
((= 1 n1) (array:3d-c02 c n0 n2))
|
||||
((= 1 n2) (array:3d-c01 c n0 n1))
|
||||
(else (lambda (i0 i1 i2) (+ c (* n0 i0) (* n1 i1) (* n2 i2))))))
|
||||
|
||||
; ND cases:
|
||||
|
||||
(define (array:Nd-* coefs)
|
||||
(lambda indices (apply + (map * coefs indices))))
|
||||
|
||||
(define (array:Nd-c* c coefs)
|
||||
(cond ((= 0 c) (array:Nd-* coefs))
|
||||
(else (lambda indices (apply + c (map * coefs indices))))))
|
|
@ -1,78 +0,0 @@
|
|||
;;;; "arraymap.scm", applicative routines for arrays in Scheme.
|
||||
;;; Copyright (c) 1993 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'array)
|
||||
|
||||
(define (array-map! ra0 proc . ras)
|
||||
(define (ramap rshape inds)
|
||||
(if (null? (cdr rshape))
|
||||
(do ((i (cadar rshape) (+ -1 i))
|
||||
(is (cons (cadar rshape) inds)
|
||||
(cons (+ -1 i) inds)))
|
||||
((< i (caar rshape)))
|
||||
(apply array-set! ra0
|
||||
(apply proc (map (lambda (ra) (apply array-ref ra is))
|
||||
ras))
|
||||
is))
|
||||
(let ((crshape (cdr rshape))
|
||||
(ll (caar rshape)))
|
||||
(do ((i (cadar rshape) (+ -1 i)))
|
||||
((< i ll))
|
||||
(ramap crshape (cons i inds))))))
|
||||
(ramap (reverse (array-shape ra0)) '()))
|
||||
|
||||
(define (array-for-each proc . ras)
|
||||
(define (rafe rshape inds)
|
||||
(if (null? (cdr rshape))
|
||||
(do ((i (caar rshape) (+ 1 i)))
|
||||
((> i (cadar rshape)))
|
||||
(apply proc
|
||||
(map (lambda (ra)
|
||||
(apply array-ref ra (reverse (cons i inds)))) ras)))
|
||||
(let ((crshape (cdr rshape))
|
||||
(ll (cadar rshape)))
|
||||
(do ((i (caar rshape) (+ 1 i)))
|
||||
((> i ll))
|
||||
(rafe crshape (cons i inds))))))
|
||||
(rafe (array-shape (car ras)) '()))
|
||||
|
||||
(define (array-index-map! ra fun)
|
||||
(define (ramap rshape inds)
|
||||
(if (null? (cdr rshape))
|
||||
(do ((i (cadar rshape) (+ -1 i))
|
||||
(is (cons (cadar rshape) inds)
|
||||
(cons (+ -1 i) inds)))
|
||||
((< i (caar rshape)))
|
||||
(apply array-set! ra (apply fun is) is))
|
||||
(let ((crshape (cdr rshape))
|
||||
(ll (caar rshape)))
|
||||
(do ((i (cadar rshape) (+ -1 i)))
|
||||
((< i ll))
|
||||
(ramap crshape (cons i inds))))))
|
||||
(if (zero? (array-rank ra))
|
||||
(array-set! ra (fun))
|
||||
(ramap (reverse (array-shape ra)) '())))
|
||||
|
||||
(define (array-indexes ra)
|
||||
(let ((ra0 (apply make-array '() (array-shape ra))))
|
||||
(array-index-map! ra0 list)
|
||||
ra0))
|
||||
|
||||
(define (array-copy! source dest)
|
||||
(array-map! dest identity source))
|
|
@ -1,454 +0,0 @@
|
|||
;;; "batch.scm" Group and execute commands on various systems.
|
||||
;Copyright (C) 1994, 1995, 1997 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'line-i/o) ;Just for write-line
|
||||
(require 'parameters)
|
||||
(require 'database-utilities)
|
||||
(require 'string-port)
|
||||
(require 'tree)
|
||||
|
||||
(define system
|
||||
(if (provided? 'system)
|
||||
system
|
||||
(lambda (str) 1)))
|
||||
(define system:success?
|
||||
(case (software-type)
|
||||
((VMS) (lambda (int) (eqv? 1 int)))
|
||||
(else zero?)))
|
||||
;;(trace system system:success? exit quit slib:exit)
|
||||
|
||||
(define (batch:port parms)
|
||||
(let ((bp (parameter-list-ref parms 'batch-port)))
|
||||
(cond ((or (not (pair? bp)) (not (output-port? (car bp))))
|
||||
(slib:warn 'batch-line "missing batch-port parameter" bp)
|
||||
(current-output-port))
|
||||
(else (car bp)))))
|
||||
|
||||
(define (batch:dialect parms) ; was batch-family
|
||||
(car (parameter-list-ref parms 'batch-dialect)))
|
||||
|
||||
(define (write-batch-line str line-limit port)
|
||||
(cond ((and line-limit (>= (string-length str) line-limit))
|
||||
(slib:warn 'write-batch-line 'too-long
|
||||
(string-length str) '> line-limit)
|
||||
#f)
|
||||
(else (write-line str port) #t)))
|
||||
(define (batch-line parms str)
|
||||
(write-batch-line str (batch:line-length-limit parms) (batch:port parms)))
|
||||
|
||||
;;; add a Scheme batch-dialect?
|
||||
|
||||
(define (batch:try-chopped-command parms . args)
|
||||
(define args-but-last (batch:flatten (butlast args 1)))
|
||||
(define line-limit (batch:line-length-limit parms))
|
||||
(let loop ((fodder (car (last-pair args))))
|
||||
(let ((str (batch:glued-line parms
|
||||
(batch:flatten
|
||||
(append args-but-last (list fodder))))))
|
||||
(cond ((< (string-length str) line-limit)
|
||||
(batch:try-command parms str))
|
||||
((< (length fodder) 2)
|
||||
(slib:warn 'batch:try-chopped-command "can't fit in " line-limit
|
||||
(cons proc (append args-but-last (list fodder))))
|
||||
#f)
|
||||
(else (let ((hlen (quotient (length fodder) 2)))
|
||||
(and (loop (last fodder hlen))
|
||||
(loop (butlast fodder hlen)))))))))
|
||||
|
||||
(define (batch:glued-line parms strings)
|
||||
(case (batch:dialect parms)
|
||||
((vms) (apply string-join " " "$" strings))
|
||||
((unix dos amigados system *unknown*) (apply string-join " " strings))
|
||||
(else #f)))
|
||||
|
||||
(define (batch:try-command parms . strings)
|
||||
(set! strings (batch:flatten strings))
|
||||
(let ((line (batch:glued-line parms strings)))
|
||||
(and line
|
||||
(case (batch:dialect parms)
|
||||
((unix dos vms amigados) (batch-line parms line))
|
||||
((system)
|
||||
(let ((port (batch:port parms)))
|
||||
(write `(system ,line) port) (newline port)
|
||||
(and (provided? 'system) (system:success? (system line)))))
|
||||
((*unknown*)
|
||||
(let ((port (batch:port parms)))
|
||||
(write `(system ,line) port) (newline port) #t))
|
||||
(else #f)))))
|
||||
|
||||
(define (batch:command parms . strings)
|
||||
(cond ((apply batch:try-command parms strings))
|
||||
(else (slib:error 'batch:command 'failed strings))))
|
||||
|
||||
(define (batch:run-script parms name . strings)
|
||||
(case (batch:dialect parms strings)
|
||||
((vms) (batch:command parms (string-append "@" name) strings))
|
||||
(else (batch:command parms name strings))))
|
||||
|
||||
(define (batch:write-comment-line dialect line port)
|
||||
(case dialect
|
||||
((unix) (write-batch-line (string-append "# " line) #f port))
|
||||
((dos) (write-batch-line (string-append "rem " line) #f port))
|
||||
((vms) (write-batch-line (string-append "$! " line) #f port))
|
||||
((amigados) (write-batch-line (string-append "; " line) #f port))
|
||||
((system) (write-batch-line (string-append "; " line) #f port))
|
||||
((*unknown*) (write-batch-line (string-append ";;; " line) #f port)
|
||||
;;(newline port)
|
||||
#f)))
|
||||
|
||||
(define (batch:comment parms . lines)
|
||||
(define port (batch:port parms))
|
||||
(define dialect (batch:dialect parms))
|
||||
(set! lines (batch:flatten lines))
|
||||
(every (lambda (line)
|
||||
(batch:write-comment-line dialect line port))
|
||||
lines))
|
||||
|
||||
(define (batch:lines->file parms file . lines)
|
||||
(define port (batch:port parms))
|
||||
(set! lines (batch:flatten lines))
|
||||
(case (or (batch:dialect parms) '*unknown*)
|
||||
((unix) (batch-line parms (string-append "rm -f " file))
|
||||
(every
|
||||
(lambda (string)
|
||||
(batch-line parms (string-append "echo '" string "'>>" file)))
|
||||
lines))
|
||||
((dos) (batch-line parms (string-append "DEL " file))
|
||||
(every
|
||||
(lambda (string)
|
||||
(batch-line parms
|
||||
(string-append "ECHO" (if (equal? "" string) "." " ")
|
||||
string ">>" file)))
|
||||
lines))
|
||||
((vms) (and (batch-line parms (string-append "$DELETE " file))
|
||||
(batch-line parms (string-append "$CREATE " file))
|
||||
(batch-line parms (string-append "$DECK"))
|
||||
(every (lambda (string) (batch-line parms string))
|
||||
lines)
|
||||
(batch-line parms (string-append "$EOD"))))
|
||||
((amigados) (batch-line parms (string-append "delete force " file))
|
||||
(every
|
||||
(lambda (str)
|
||||
(letrec ((star-quote
|
||||
(lambda (str)
|
||||
(if (equal? "" str)
|
||||
str
|
||||
(let* ((ch (string-ref str 0))
|
||||
(s (if (char=? ch #\")
|
||||
(string #\* ch)
|
||||
(string ch))))
|
||||
(string-append
|
||||
s
|
||||
(star-quote
|
||||
(substring str 1 (string-length str)))))))))
|
||||
(batch-line parms (string-append "echo \"" (star-quote str)
|
||||
"\" >> " file))))
|
||||
lines))
|
||||
((system) (write `(delete-file ,file) port) (newline port)
|
||||
(delete-file file)
|
||||
(require 'pretty-print)
|
||||
(pretty-print `(call-with-output-file ,file
|
||||
(lambda (fp)
|
||||
(for-each
|
||||
(lambda (string) (write-line string fp))
|
||||
',lines)))
|
||||
port)
|
||||
(call-with-output-file file
|
||||
(lambda (fp) (for-each (lambda (string) (write-line string fp))
|
||||
lines)))
|
||||
#t)
|
||||
((*unknown*)
|
||||
(write `(delete-file ,file) port) (newline port)
|
||||
(require 'pretty-print)
|
||||
(pretty-print
|
||||
`(call-with-output-file ,file
|
||||
(lambda (fp)
|
||||
(for-each
|
||||
(lambda (string)
|
||||
(write-line string fp))
|
||||
,lines)))
|
||||
port)
|
||||
#f)))
|
||||
|
||||
(define (batch:delete-file parms file)
|
||||
(define port (batch:port parms))
|
||||
(case (batch:dialect parms)
|
||||
((unix) (batch-line parms (string-append "rm -f " file))
|
||||
#t)
|
||||
((dos) (batch-line parms (string-append "DEL " file))
|
||||
#t)
|
||||
((vms) (batch-line parms (string-append "$DELETE " file))
|
||||
#t)
|
||||
((amigados) (batch-line parms (string-append "delete force " file))
|
||||
#t)
|
||||
((system) (write `(delete-file ,file) port) (newline port)
|
||||
(delete-file file)) ; SLIB provides
|
||||
((*unknown*) (write `(delete-file ,file) port) (newline port)
|
||||
#f)))
|
||||
|
||||
(define (batch:rename-file parms old-name new-name)
|
||||
(define port (batch:port parms))
|
||||
(case (batch:dialect parms)
|
||||
((unix) (batch-line parms (string-join " " "mv -f" old-name new-name)))
|
||||
;;((dos) (batch-line parms (string-join " " "REN" old-name new-name)))
|
||||
((dos) (batch-line parms (string-join " " "MOVE" "/Y" old-name new-name)))
|
||||
((vms) (batch-line parms (string-join " " "$RENAME" old-name new-name)))
|
||||
((amigados) (batch-line parms (string-join " " "failat 21"))
|
||||
(batch-line parms (string-join " " "delete force" new-name))
|
||||
(batch-line parms (string-join " " "rename" old-name new-name)))
|
||||
((system) (batch:extender 'rename-file batch:rename-file))
|
||||
((*unknown*) (write `(rename-file ,old-name ,new-name) port)
|
||||
(newline port)
|
||||
#f)))
|
||||
|
||||
(define (batch:write-header-comment dialect name port)
|
||||
(batch:write-comment-line
|
||||
dialect
|
||||
(string-append (if (string? name)
|
||||
(string-append "\"" name "\"")
|
||||
(case dialect
|
||||
((system *unknown*) "Scheme")
|
||||
((vms) "VMS")
|
||||
((dos) "DOS")
|
||||
((default-for-platform) "??")
|
||||
(else (symbol->string dialect))))
|
||||
" script created by SLIB/batch "
|
||||
(cond ((provided? 'bignum)
|
||||
(require 'posix-time)
|
||||
(let ((ct (ctime (current-time))))
|
||||
(substring ct 0 (+ -1 (string-length ct)))))
|
||||
(else "")))
|
||||
port))
|
||||
|
||||
(define (batch:call-with-output-script parms name proc)
|
||||
(define dialect (batch:dialect parms))
|
||||
(case dialect
|
||||
((unix) ((cond ((and (string? name) (provided? 'system))
|
||||
(lambda (proc)
|
||||
(let ((ans (call-with-output-file name proc)))
|
||||
(system (string-append "chmod +x " name))
|
||||
ans)))
|
||||
((output-port? name) (lambda (proc) (proc name)))
|
||||
(else (lambda (proc) (proc (current-output-port)))))
|
||||
(lambda (port)
|
||||
(write-line "#!/bin/sh" port)
|
||||
(batch:write-header-comment dialect name port)
|
||||
(proc port))))
|
||||
|
||||
((dos) ((cond ((string? name)
|
||||
(lambda (proc)
|
||||
(call-with-output-file (string-append name ".bat") proc)))
|
||||
((output-port? name) (lambda (proc) (proc name)))
|
||||
(else (lambda (proc) (proc (current-output-port)))))
|
||||
(lambda (port)
|
||||
(batch:write-header-comment dialect name port)
|
||||
(proc port))))
|
||||
|
||||
((vms) ((cond ((string? name)
|
||||
(lambda (proc)
|
||||
(call-with-output-file (string-append name ".COM") proc)))
|
||||
((output-port? name) (lambda (proc) (proc name)))
|
||||
(else (lambda (proc) (proc (current-output-port)))))
|
||||
(lambda (port)
|
||||
(batch:write-header-comment dialect name port)
|
||||
;;(write-line "$DEFINE/USER SYS$OUTPUT BUILD.LOG" port)
|
||||
(proc port))))
|
||||
|
||||
((amigados) ((cond ((and (string? name) (provided? 'system))
|
||||
(lambda (proc)
|
||||
(let ((ans (call-with-output-file name proc)))
|
||||
(system (string-append "protect " name " rswd"))
|
||||
ans)))
|
||||
((output-port? name) (lambda (proc) (proc name)))
|
||||
(else (lambda (proc) (proc (current-output-port)))))
|
||||
(lambda (port)
|
||||
(batch:write-header-comment dialect name port)
|
||||
(proc port))))
|
||||
|
||||
((system) ((cond ((and (string? name) (provided? 'system))
|
||||
(lambda (proc)
|
||||
(let ((ans (call-with-output-file name
|
||||
(lambda (port) (proc name)))))
|
||||
(system (string-append "chmod +x " name))
|
||||
ans)))
|
||||
((output-port? name) (lambda (proc) (proc name)))
|
||||
(else (lambda (proc) (proc (current-output-port)))))
|
||||
(lambda (port)
|
||||
(batch:write-header-comment dialect name port)
|
||||
(proc port))))
|
||||
|
||||
((*unknown*) ((cond ((and (string? name) (provided? 'system))
|
||||
(lambda (proc)
|
||||
(let ((ans (call-with-output-file name
|
||||
(lambda (port) (proc name)))))
|
||||
(system (string-append "chmod +x " name))
|
||||
ans)))
|
||||
((output-port? name) (lambda (proc) (proc name)))
|
||||
(else (lambda (proc) (proc (current-output-port)))))
|
||||
(lambda (port)
|
||||
(batch:write-header-comment dialect name port)
|
||||
(proc port))))))
|
||||
|
||||
;;; This little ditty figures out how to use a Scheme extension or
|
||||
;;; SYSTEM to execute a command that is not available in the batch
|
||||
;;; mode chosen.
|
||||
|
||||
(define (batch:extender NAME BATCHER)
|
||||
(lambda (parms . args)
|
||||
(define port (batch:port parms))
|
||||
(cond
|
||||
((provided? 'i/o-extensions) ; SCM specific
|
||||
(write `(,NAME ,@args) port)
|
||||
(newline port)
|
||||
(apply (slib:eval NAME) args))
|
||||
((not (provided? 'system)) #f)
|
||||
(else
|
||||
(let ((pl (make-parameter-list (map car parms))))
|
||||
(adjoin-parameters!
|
||||
pl (cons 'batch-dialect (os->batch-dialect
|
||||
(parameter-list-ref parms 'platform))))
|
||||
(system
|
||||
(call-with-output-string
|
||||
(lambda (port)
|
||||
(batch:call-with-output-script
|
||||
port
|
||||
(lambda (batch-port)
|
||||
(define new-parms (copy-tree pl))
|
||||
(adjoin-parameters! new-parms (list 'batch-port batch-port))
|
||||
(apply BATCHER new-parms args)))))))))))
|
||||
|
||||
(define (truncate-up-to str chars)
|
||||
(define (tut str)
|
||||
(do ((i (string-length str) (+ -1 i)))
|
||||
((or (zero? i) (memv (string-ref str (+ -1 i)) chars))
|
||||
(substring str i (string-length str)))))
|
||||
(cond ((char? chars) (set! chars (list chars)))
|
||||
((string? chars) (set! chars (string->list chars))))
|
||||
(if (string? str) (tut str) (map tut str)))
|
||||
|
||||
(define (must-be-first firsts lst)
|
||||
(append (remove-if-not (lambda (i) (member i lst)) firsts)
|
||||
(remove-if (lambda (i) (member i firsts)) lst)))
|
||||
|
||||
(define (must-be-last lst lasts)
|
||||
(append (remove-if (lambda (i) (member i lasts)) lst)
|
||||
(remove-if-not (lambda (i) (member i lst)) lasts)))
|
||||
|
||||
(define (string-join joiner . args)
|
||||
(if (null? args) ""
|
||||
(apply string-append
|
||||
(car args)
|
||||
(map (lambda (s) (string-append joiner s)) (cdr args)))))
|
||||
|
||||
(define (batch:flatten strings)
|
||||
(apply
|
||||
append (map
|
||||
(lambda (obj)
|
||||
(cond ((eq? "" obj) '())
|
||||
((string? obj) (list obj))
|
||||
((eq? #f obj) '())
|
||||
((null? obj) '())
|
||||
((list? obj) (batch:flatten obj))
|
||||
(else (slib:error 'batch:flatten "unexpected type"
|
||||
obj "in" strings))))
|
||||
strings)))
|
||||
|
||||
(define batch:platform (software-type))
|
||||
(cond ((and (eq? 'unix batch:platform) (provided? 'system))
|
||||
(let ((file-name (tmpnam)))
|
||||
(system (string-append "uname > " file-name))
|
||||
(set! batch:platform (call-with-input-file file-name read))
|
||||
(delete-file file-name))))
|
||||
|
||||
(define batch:database #f)
|
||||
(define os->batch-dialect #f)
|
||||
(define batch-dialect->line-length-limit #f)
|
||||
|
||||
(define (batch:line-length-limit parms)
|
||||
(let ((bl (parameter-list-ref parms 'batch-line-length-limit)))
|
||||
(if bl (car bl) (batch-dialect->line-length-limit (batch:dialect parms)))))
|
||||
|
||||
(define (batch:initialize! database)
|
||||
(set! batch:database database)
|
||||
(define-tables database
|
||||
|
||||
'(batch-dialect
|
||||
((family atom))
|
||||
((line-length-limit number))
|
||||
((unix 1023)
|
||||
(dos 127)
|
||||
(vms 1023)
|
||||
(amigados 511)
|
||||
(system 1023)
|
||||
(*unknown* -1)))
|
||||
|
||||
'(operating-system
|
||||
((name symbol))
|
||||
((os-family batch-dialect))
|
||||
(;;(3b1 *unknown*)
|
||||
(*unknown* *unknown*)
|
||||
(acorn *unknown*)
|
||||
(aix unix)
|
||||
(alliant *unknown*)
|
||||
(amiga amigados)
|
||||
(apollo unix)
|
||||
(apple2 *unknown*)
|
||||
(arm *unknown*)
|
||||
(atari.st *unknown*)
|
||||
(cdc *unknown*)
|
||||
(celerity *unknown*)
|
||||
(concurrent *unknown*)
|
||||
(convex *unknown*)
|
||||
(encore *unknown*)
|
||||
(harris *unknown*)
|
||||
(hp-ux unix)
|
||||
(hp48 *unknown*)
|
||||
(irix unix)
|
||||
(isis *unknown*)
|
||||
(linux unix)
|
||||
(mac *unknown*)
|
||||
(masscomp unix)
|
||||
(mips *unknown*)
|
||||
(ms-dos dos)
|
||||
(ncr *unknown*)
|
||||
(newton *unknown*)
|
||||
(next unix)
|
||||
(novell *unknown*)
|
||||
(os/2 dos)
|
||||
(osf1 unix)
|
||||
(prime *unknown*)
|
||||
(psion *unknown*)
|
||||
(pyramid *unknown*)
|
||||
(sequent *unknown*)
|
||||
(sgi *unknown*)
|
||||
(stratus *unknown*)
|
||||
(sunos unix)
|
||||
(transputer *unknown*)
|
||||
(unicos unix)
|
||||
(unix unix)
|
||||
(vms vms)
|
||||
)))
|
||||
|
||||
((database 'add-domain) '(operating-system operating-system #f symbol #f))
|
||||
(set! os->batch-dialect (((batch:database 'open-table) 'operating-system #f)
|
||||
'get 'os-family))
|
||||
(set! batch-dialect->line-length-limit
|
||||
(((batch:database 'open-table) 'batch-dialect #f)
|
||||
'get 'line-length-limit))
|
||||
)
|
|
@ -1,263 +0,0 @@
|
|||
;; "bigloo.init" Initialization for SLIB for Bigloo -*-scheme-*-
|
||||
;; Copyright 1994 Robert Sanders
|
||||
;; Copyright 1991, 1992, 1993 Aubrey Jaffer
|
||||
;; Copyright 1991 David Love
|
||||
;;
|
||||
;; Permission to copy this software, to redistribute it, and to use it
|
||||
;; for any purpose is granted, subject to the following restrictions and
|
||||
;; understandings.
|
||||
;;
|
||||
;; 1. Any copy made of this software must include this copyright notice
|
||||
;; in full.
|
||||
;;
|
||||
;; 2. I have made no warrantee or representation that the operation of
|
||||
;; this software will be error-free, and I am under no obligation to
|
||||
;; provide any services, by way of maintenance, update, or otherwise.
|
||||
;;
|
||||
;; 3. In conjunction with products arising from the use of this
|
||||
;; material, there shall be no use of my name in any advertising,
|
||||
;; promotional, or sales literature without prior written consent in
|
||||
;; each case.
|
||||
|
||||
(define (software-type) 'UNIX)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'Bigloo)
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page)
|
||||
"http://kaolin.unice.fr/~serrano/bigloo/bigloo.html")
|
||||
|
||||
(define (scheme-implementation-version) "2.0c")
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define (implementation-vicinity)
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/unsup/lib/bigloo/")
|
||||
((VMS) "scheme$src:")
|
||||
((MSDOS) "C:\\scheme\\")))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(or
|
||||
;; Use this getenv if your implementation supports it.
|
||||
(getenv "SCHEME_LIBRARY_PATH")
|
||||
;; Use this path if your scheme does not support GETENV
|
||||
;; or if SCHEME_LIBRARY_PATH is not set.
|
||||
(case (software-type)
|
||||
((UNIX) "/home/bambam/leavens/unsup-src/scheme/scm/slib/")
|
||||
((VMS) "lib$scheme:")
|
||||
((MSDOS) "C:\\SLIB\\")
|
||||
(else "")))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define home-vicinity
|
||||
(let ((home-path (getenv "HOME")))
|
||||
(lambda () home-path)))
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. See Template.scm for the list of feature
|
||||
;;; names.
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
rev4-report ;conforms to
|
||||
rev3-report ;conforms to
|
||||
ieee-p1178 ;conforms to
|
||||
rev4-optional-procedures
|
||||
rev3-procedures
|
||||
multiarg/and-
|
||||
multiarg-apply
|
||||
rationalize
|
||||
object-hash
|
||||
delay
|
||||
promise
|
||||
with-file
|
||||
transcript
|
||||
ieee-floating-point
|
||||
eval
|
||||
pretty-print
|
||||
object->string
|
||||
string-case
|
||||
string-port
|
||||
system
|
||||
getenv
|
||||
defmacro
|
||||
;;full-continuation ;not without the -call/cc switch
|
||||
))
|
||||
|
||||
(define pretty-print pp)
|
||||
|
||||
(define (object->string x) (obj->string x))
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
|
||||
(define (1+ n) (+ n 1))
|
||||
(define (-1+ n) (+ n -1))
|
||||
(define 1- -1+)
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam
|
||||
(let ((cntr 100))
|
||||
(lambda ()
|
||||
(set! cntr (+ 1 cntr))
|
||||
(let ((tmp (string-append "slib_" (number->string cntr))))
|
||||
(if (file-exists? tmp) (tmpnam) tmp)))))
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port
|
||||
;;; use this definition if your system doesn't have such a procedure.
|
||||
(define (force-output . args)
|
||||
(flush-output-port (if (pair? args) (car args) (current-output-port))))
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-*PUT-FILE.
|
||||
(define (call-with-output-string f)
|
||||
(let ((outsp (open-output-string)))
|
||||
(f outsp)
|
||||
(close-output-port outsp)))
|
||||
|
||||
(define (call-with-input-string s f)
|
||||
(let* ((insp (open-input-string s))
|
||||
(res (f insp)))
|
||||
(close-input-port insp)
|
||||
res))
|
||||
|
||||
;;; "rationalize" adjunct procedures.
|
||||
(define (find-ratio x e)
|
||||
(let ((rat (rationalize x e)))
|
||||
(list (numerator rat) (denominator rat))))
|
||||
(define (find-ratio-between x y)
|
||||
(find-ratio (/ (+ x y) 2) (/ (- x y) 2)))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum 536870911)
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;; define an error procedure for the library
|
||||
|
||||
;;; If your implementation provides eval, SLIB:EVAL is single argument
|
||||
;;; eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
(define-macro (defmacro name . forms)
|
||||
`(define-macro (,name . ,(car forms)) ,@(cdr forms)))
|
||||
|
||||
(define (defmacro? m) (get-eval-expander m))
|
||||
(define (macroexpand-1 body) (expand-once body))
|
||||
(define (macroexpand body) (expand body))
|
||||
|
||||
(define (gentemp) (gensym))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
(define (slib:error . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(error 'slib:error "" args))
|
||||
|
||||
;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
;;; records
|
||||
(defmacro define-record forms
|
||||
(let* ((name (car forms))
|
||||
(maker-name (symbol-append 'make- name)))
|
||||
`(begin
|
||||
(define-struct ,name ,@(cadr forms))
|
||||
(define ,maker-name ,name))
|
||||
))
|
||||
|
||||
|
||||
(define (promise:force p) (force p))
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit (lambda args (exit 0)))
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define (slib:load-source f) (loadq (string-append f (scheme-file-suffix))))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled loadq)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
(define defmacro:eval slib:eval)
|
||||
(define defmacro:load slib:load)
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
||||
; eof
|
|
@ -1,149 +0,0 @@
|
|||
;;;; "break.scm" Breakpoints for debugging in Scheme.
|
||||
;;; Copyright (C) 1991, 1992, 1993, 1995 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'qp)
|
||||
|
||||
;;;; BREAKPOINTS
|
||||
|
||||
;;; Typing (init-debug) at top level sets up a continuation for
|
||||
;;; breakpoint. When (breakpoint arg1 ...) is then called it returns
|
||||
;;; from the top level continuation and pushes the continuation from
|
||||
;;; which it was called on breakpoint:continuation-stack. If
|
||||
;;; (continue) is later called, it pops the topmost continuation off
|
||||
;;; of breakpoint:continuation-stack and returns #f to it.
|
||||
|
||||
(define breakpoint:continuation-stack '())
|
||||
|
||||
(define debug:breakpoint
|
||||
(let ((call-with-current-continuation call-with-current-continuation)
|
||||
(apply apply) (qpn qpn)
|
||||
(cons cons) (length length))
|
||||
(lambda args
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(apply qpn "BREAKPOINT:" args)
|
||||
(let ((ans
|
||||
(call-with-current-continuation
|
||||
(lambda (x)
|
||||
(set! breakpoint:continuation-stack
|
||||
(cons x breakpoint:continuation-stack))
|
||||
(debug:top-continuation
|
||||
(length breakpoint:continuation-stack))))))
|
||||
(cond ((not (eq? ans breakpoint:continuation-stack)) ans))))))
|
||||
|
||||
(define debug:continue
|
||||
(let ((null? null?) (car car) (cdr cdr))
|
||||
(lambda args
|
||||
(cond ((null? breakpoint:continuation-stack)
|
||||
(display "; no break to continue from")
|
||||
(newline))
|
||||
(else
|
||||
(let ((cont (car breakpoint:continuation-stack)))
|
||||
(set! breakpoint:continuation-stack
|
||||
(cdr breakpoint:continuation-stack))
|
||||
(if (null? args) (cont #f)
|
||||
(apply cont args))))))))
|
||||
|
||||
(define debug:top-continuation
|
||||
(if (provided? 'abort)
|
||||
(lambda (val) (display val) (newline) (abort))
|
||||
(begin (display "; type (init-debug)") #f)))
|
||||
|
||||
(define (init-debug)
|
||||
(call-with-current-continuation
|
||||
(lambda (x) (set! debug:top-continuation x))))
|
||||
|
||||
(define breakpoint debug:breakpoint)
|
||||
(define bkpt debug:breakpoint)
|
||||
(define continue debug:continue)
|
||||
|
||||
(define breakf
|
||||
(let ((null? null?) ;These bindings are so that
|
||||
(not not) ;breakf will not break on parts
|
||||
(car car) (cdr cdr) ;of itself.
|
||||
(eq? eq?) (+ +) (zero? zero?) (modulo modulo)
|
||||
(apply apply) (display display) (breakpoint debug:breakpoint))
|
||||
(lambda (function . optname)
|
||||
;; (set! trace:indent 0)
|
||||
(let ((name (if (null? optname) function (car optname))))
|
||||
(lambda args
|
||||
(cond ((and (not (null? args))
|
||||
(eq? (car args) 'debug:unbreak-object)
|
||||
(null? (cdr args)))
|
||||
function)
|
||||
(else
|
||||
(breakpoint name args)
|
||||
(apply function args))))))))
|
||||
|
||||
;;; the reason I use a symbol for debug:unbreak-object is so
|
||||
;;; that functions can still be unbreaked if this file is read in twice.
|
||||
|
||||
(define (unbreakf function)
|
||||
;; (set! trace:indent 0)
|
||||
(function 'debug:unbreak-object))
|
||||
|
||||
;;;;The break: functions wrap around the debug: functions to provide
|
||||
;;; niceties like keeping track of breakd functions and dealing with
|
||||
;;; redefinition.
|
||||
|
||||
(require 'alist)
|
||||
(define break:adder (alist-associator eq?))
|
||||
(define break:deler (alist-remover eq?))
|
||||
|
||||
(define *breakd-procedures* '())
|
||||
(define (break:breakf fun sym)
|
||||
(cond ((not (procedure? fun))
|
||||
(display "WARNING: not a procedure " (current-error-port))
|
||||
(display sym (current-error-port))
|
||||
(newline (current-error-port))
|
||||
(set! *breakd-procedures* (break:deler *breakd-procedures* sym))
|
||||
fun)
|
||||
(else
|
||||
(let ((p (assq sym *breakd-procedures*)))
|
||||
(cond ((and p (eq? (cdr p) fun))
|
||||
fun)
|
||||
(else
|
||||
(let ((tfun (breakf fun sym)))
|
||||
(set! *breakd-procedures*
|
||||
(break:adder *breakd-procedures* sym tfun))
|
||||
tfun)))))))
|
||||
|
||||
(define (break:unbreakf fun sym)
|
||||
(let ((p (assq sym *breakd-procedures*)))
|
||||
(set! *breakd-procedures* (break:deler *breakd-procedures* sym))
|
||||
(cond ((not (procedure? fun)) fun)
|
||||
((not p) fun)
|
||||
((eq? (cdr p) fun)
|
||||
(unbreakf fun))
|
||||
(else fun))))
|
||||
|
||||
;;;; Finally, the macros break and unbreak
|
||||
|
||||
(defmacro break xs
|
||||
(if (null? xs)
|
||||
`(begin ,@(map (lambda (x) `(set! ,x (break:breakf ,x ',x)))
|
||||
(map car *breakd-procedures*))
|
||||
(map car *breakd-procedures*))
|
||||
`(begin ,@(map (lambda (x) `(set! ,x (break:breakf ,x ',x))) xs))))
|
||||
(defmacro unbreak xs
|
||||
(if (null? xs)
|
||||
(slib:eval
|
||||
`(begin ,@(map (lambda (x) `(set! ,x (break:unbreakf ,x ',x)))
|
||||
(map car *breakd-procedures*))
|
||||
'',(map car *breakd-procedures*)))
|
||||
`(begin ,@(map (lambda (x) `(set! ,x (break:unbreakf ,x ',x))) xs))))
|
|
@ -1,15 +0,0 @@
|
|||
;;; "byte.scm" small integers, not necessarily chars.
|
||||
|
||||
(define (byte-ref str ind) (char->integer (string-ref str ind)))
|
||||
(define (byte-set! str ind val) (string-set! str ind (integer->char val)))
|
||||
(define (make-bytes len . opt)
|
||||
(if (null? opt) (make-string len)
|
||||
(make-string len (integer->char (car opt)))))
|
||||
(define bytes-length string-length)
|
||||
(define (write-byte byt . opt) (apply write-char (integer->char byt) opt))
|
||||
(define (read-byte . opt)
|
||||
(let ((c (apply read-char opt)))
|
||||
(if (eof-object? c) c (char->integer c))))
|
||||
(define (bytes . args) (list->bytes args))
|
||||
(define (bytes->list bts) (map char->integer (string->list bts)))
|
||||
(define (list->bytes lst) (list->string (map integer->char lst)))
|
|
@ -1,150 +0,0 @@
|
|||
;;;; "chap.scm" Chapter ordering -*-scheme-*-
|
||||
;;; Copyright 1992, 1993, 1994 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; The CHAP: functions deal with strings which are ordered like
|
||||
;;; chapters in a book. For instance, a_9 < a_10 and 4c < 4aa. Each
|
||||
;;; section of the string consists of consecutive numeric or
|
||||
;;; consecutive aphabetic characters.
|
||||
|
||||
(define (chap:string<? s1 s2)
|
||||
(let ((l1 (string-length s1))
|
||||
(l2 (string-length s2)))
|
||||
(define (match-so-far i ctypep)
|
||||
(cond ((>= i l1) (not (>= i l2)))
|
||||
((>= i l2) #f)
|
||||
(else
|
||||
(let ((c1 (string-ref s1 i))
|
||||
(c2 (string-ref s2 i)))
|
||||
(cond ((char=? c1 c2)
|
||||
(if (ctypep c1)
|
||||
(match-so-far (+ 1 i) ctypep)
|
||||
(delimited i)))
|
||||
((ctypep c1)
|
||||
(if (ctypep c2)
|
||||
(length-race (+ 1 i) ctypep (char<? c1 c2))
|
||||
#f))
|
||||
((ctypep c2) #t)
|
||||
(else
|
||||
(let ((ctype1 (ctype c1)))
|
||||
(cond
|
||||
((and ctype1 (eq? ctype1 (ctype c2)))
|
||||
(length-race (+ 1 i) ctype1 (char<? c1 c2)))
|
||||
(else (char<? c1 c2))))))))))
|
||||
(define (length-race i ctypep def)
|
||||
(cond ((>= i l1) (if (>= i l2) def #t))
|
||||
((>= i l2) #f)
|
||||
(else
|
||||
(let ((c1 (string-ref s1 i))
|
||||
(c2 (string-ref s2 i)))
|
||||
(cond ((ctypep c1)
|
||||
(if (ctypep c2)
|
||||
(length-race (+ 1 i) ctypep def)
|
||||
#f))
|
||||
((ctypep c2) #t)
|
||||
(else def))))))
|
||||
(define (ctype c1)
|
||||
(cond
|
||||
((char-numeric? c1) char-numeric?)
|
||||
((char-lower-case? c1) char-lower-case?)
|
||||
((char-upper-case? c1) char-upper-case?)
|
||||
(else #f)))
|
||||
(define (delimited i)
|
||||
(cond ((>= i l1) (not (>= i l2)))
|
||||
((>= i l2) #f)
|
||||
(else
|
||||
(let* ((c1 (string-ref s1 i))
|
||||
(c2 (string-ref s2 i))
|
||||
(ctype1 (ctype c1)))
|
||||
(cond ((char=? c1 c2)
|
||||
(if ctype1 (match-so-far (+ i 1) ctype1)
|
||||
(delimited (+ i 1))))
|
||||
((and ctype1 (eq? ctype1 (ctype c2)))
|
||||
(length-race (+ 1 i) ctype1 (char<? c1 c2)))
|
||||
(else (char<? c1 c2)))))))
|
||||
(delimited 0)))
|
||||
|
||||
(define chap:char-incr (- (char->integer #\2) (char->integer #\1)))
|
||||
|
||||
(define (chap:inc-string s p)
|
||||
(let ((c (string-ref s p)))
|
||||
(cond ((char=? c #\z)
|
||||
(string-set! s p #\a)
|
||||
(cond ((zero? p) (string-append "a" s))
|
||||
((char-lower-case? (string-ref s (+ -1 p)))
|
||||
(chap:inc-string s (+ -1 p)))
|
||||
(else
|
||||
(string-append
|
||||
(substring s 0 p)
|
||||
"a"
|
||||
(substring s p (string-length s))))))
|
||||
((char=? c #\Z)
|
||||
(string-set! s p #\A)
|
||||
(cond ((zero? p) (string-append "A" s))
|
||||
((char-upper-case? (string-ref s (+ -1 p)))
|
||||
(chap:inc-string s (+ -1 p)))
|
||||
(else
|
||||
(string-append
|
||||
(substring s 0 p)
|
||||
"A"
|
||||
(substring s p (string-length s))))))
|
||||
((char=? c #\9)
|
||||
(string-set! s p #\0)
|
||||
(cond ((zero? p) (string-append "1" s))
|
||||
((char-numeric? (string-ref s (+ -1 p)))
|
||||
(chap:inc-string s (+ -1 p)))
|
||||
(else
|
||||
(string-append
|
||||
(substring s 0 p)
|
||||
"1"
|
||||
(substring s p (string-length s))))))
|
||||
((or (char-alphabetic? c) (char-numeric? c))
|
||||
(string-set! s p (integer->char
|
||||
(+ chap:char-incr
|
||||
(char->integer (string-ref s p)))))
|
||||
s)
|
||||
(else (slib:error "inc-string error" s p)))))
|
||||
|
||||
(define (chap:next-string s)
|
||||
(do ((i (+ -1 (string-length s)) (+ -1 i)))
|
||||
((or (negative? i)
|
||||
(char-numeric? (string-ref s i))
|
||||
(char-alphabetic? (string-ref s i)))
|
||||
(if (negative? i) (string-append s "0")
|
||||
(chap:inc-string (string-copy s) i)))))
|
||||
|
||||
;;; testing utilities
|
||||
;(define (ns s1) (chap:next-string s1))
|
||||
|
||||
;(define (ts s1 s2)
|
||||
; (let ((s< (chap:string<? s1 s2))
|
||||
; (s> (chap:string<? s2 s1)))
|
||||
; (cond (s<
|
||||
; (display s1)
|
||||
; (display " < ")
|
||||
; (display s2)
|
||||
; (newline)))
|
||||
; (cond (s>
|
||||
; (display s1)
|
||||
; (display " > ")
|
||||
; (display s2)
|
||||
; (newline)))))
|
||||
|
||||
(define (chap:string>? s1 s2) (chap:string<? s2 s1))
|
||||
(define (chap:string>=? s1 s2) (not (chap:string<? s1 s2)))
|
||||
(define (chap:string<=? s1 s2) (not (chap:string<? s2 s1)))
|
|
@ -1,171 +0,0 @@
|
|||
;;;; "charplot.scm", plotting on character devices for Scheme
|
||||
;;; Copyright (C) 1992, 1993 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'sort)
|
||||
(require 'printf)
|
||||
(require 'array)
|
||||
(require 'array-for-each)
|
||||
|
||||
(define charplot:rows 24)
|
||||
(define charplot:columns (output-port-width (current-output-port)))
|
||||
|
||||
(define charplot:xborder #\_)
|
||||
(define charplot:yborder #\|)
|
||||
(define charplot:xaxchar #\-)
|
||||
(define charplot:yaxchar #\:)
|
||||
(define charplot:curve1 #\*)
|
||||
(define charplot:xtick #\.)
|
||||
|
||||
(define charplot:height (- charplot:rows 5))
|
||||
(define charplot:width (- charplot:columns 15))
|
||||
|
||||
(define (charplot:printn! n char)
|
||||
(cond ((positive? n)
|
||||
(write-char char)
|
||||
(charplot:printn! (+ n -1) char))))
|
||||
|
||||
(define (charplot:center-print! str width)
|
||||
(let ((lpad (quotient (- width (string-length str)) 2)))
|
||||
(charplot:printn! lpad #\ )
|
||||
(display str)
|
||||
(charplot:printn! (- width (+ (string-length str) lpad)) #\ )))
|
||||
|
||||
(define (charplot:number->string x)
|
||||
(sprintf #f "%g" x))
|
||||
|
||||
(define (charplot:scale-it z scale)
|
||||
(if (and (exact? z) (integer? z))
|
||||
(quotient (* z (car scale)) (cadr scale))
|
||||
(inexact->exact (round (/ (* z (car scale)) (cadr scale))))))
|
||||
|
||||
(define (charplot:find-scale isize delta)
|
||||
(define (fs2)
|
||||
(cond ((< (* delta 8) isize) 8)
|
||||
((< (* delta 6) isize) 6)
|
||||
((< (* delta 5) isize) 5)
|
||||
((< (* delta 4) isize) 4)
|
||||
((< (* delta 3) isize) 3)
|
||||
((< (* delta 2) isize) 2)
|
||||
(else 1)))
|
||||
(cond ((zero? delta) (set! delta 1))
|
||||
((inexact? delta) (set! isize (exact->inexact isize))))
|
||||
(do ((d 1 (* d 10)))
|
||||
((<= delta isize)
|
||||
(do ((n 1 (* n 10)))
|
||||
((>= (* delta 10) isize)
|
||||
(list (* n (fs2)) d))
|
||||
(set! delta (* delta 10))))
|
||||
(set! isize (* isize 10))))
|
||||
|
||||
(define (charplot:iplot! data xlabel ylabel xmin xscale ymin yscale)
|
||||
(define xaxis (- (charplot:scale-it ymin yscale)))
|
||||
(define yaxis (- (charplot:scale-it xmin xscale)))
|
||||
(charplot:center-print! ylabel 11)
|
||||
(charplot:printn! (+ charplot:width 1) charplot:xborder)
|
||||
(newline)
|
||||
(set! data (sort! data (lambda (x y) (if (= (cdr x) (cdr y))
|
||||
(< (car x) (car y))
|
||||
(> (cdr x) (cdr y))))))
|
||||
(do ((ht (- charplot:height 1) (- ht 1)))
|
||||
((negative? ht))
|
||||
(let ((a (make-string (+ charplot:width 1)
|
||||
(if (= ht xaxis) charplot:xaxchar #\ )))
|
||||
(ystep (if (= 1 (gcd (car yscale) 3)) 2 3)))
|
||||
(string-set! a charplot:width charplot:yborder)
|
||||
(if (< -1 yaxis charplot:width) (string-set! a yaxis charplot:yaxchar))
|
||||
(do ()
|
||||
((or (null? data) (not (>= (cdar data) ht))))
|
||||
(string-set! a (caar data) charplot:curve1)
|
||||
(set! data (cdr data)))
|
||||
(if (zero? (modulo (- ht xaxis) ystep))
|
||||
(let* ((v (charplot:number->string (/ (* (- ht xaxis) (cadr yscale))
|
||||
(car yscale))))
|
||||
(l (string-length v)))
|
||||
(if (> l 10)
|
||||
(display (substring v 0 10))
|
||||
(begin
|
||||
(charplot:printn! (- 10 l) #\ )
|
||||
(display v)))
|
||||
(display charplot:yborder)
|
||||
(display charplot:xaxchar))
|
||||
(begin
|
||||
(charplot:printn! 10 #\ )
|
||||
(display charplot:yborder)
|
||||
(display #\ )))
|
||||
(display a) (newline)))
|
||||
(let* ((xstep (if (= 1 (gcd (car xscale) 3)) 10 12))
|
||||
(xstep/2 (quotient (- xstep 2) 2))
|
||||
(fudge (modulo yaxis xstep)))
|
||||
(charplot:printn! 10 #\ ) (display charplot:yborder)
|
||||
(charplot:printn! (+ 1 fudge) charplot:xborder)
|
||||
(display charplot:yaxchar)
|
||||
(do ((i fudge (+ i xstep)))
|
||||
((> (+ i xstep) charplot:width)
|
||||
(charplot:printn! (modulo (- charplot:width (+ i 1)) xstep)
|
||||
charplot:xborder))
|
||||
(charplot:printn! xstep/2 charplot:xborder)
|
||||
(display charplot:xtick)
|
||||
(charplot:printn! xstep/2 charplot:xborder)
|
||||
(display charplot:yaxchar))
|
||||
(display charplot:yborder) (newline)
|
||||
(charplot:center-print! xlabel (+ 12 fudge (- xstep/2)))
|
||||
(do ((i fudge (+ i xstep)))
|
||||
((>= i charplot:width))
|
||||
(charplot:center-print! (charplot:number->string
|
||||
(/ (* (- i yaxis) (cadr xscale))
|
||||
(car xscale)))
|
||||
xstep))
|
||||
(newline)))
|
||||
|
||||
(define (charplot:plot! data xlabel ylabel)
|
||||
(cond ((array? data)
|
||||
(case (array-rank data)
|
||||
((1) (set! data (map cons
|
||||
(let ((ra (apply make-array #f
|
||||
(array-shape data))))
|
||||
(array-index-map! ra identity)
|
||||
(array->list ra))
|
||||
(array->list data))))
|
||||
((2) (set! data (map (lambda (lst) (cons (car lst) (cadr lst)))
|
||||
(array->list data)))))))
|
||||
(let* ((xmax (apply max (map car data)))
|
||||
(xmin (apply min (map car data)))
|
||||
(xscale (charplot:find-scale charplot:width (- xmax xmin)))
|
||||
(ymax (apply max (map cdr data)))
|
||||
(ymin (apply min (map cdr data)))
|
||||
(yscale (charplot:find-scale charplot:height (- ymax ymin)))
|
||||
(ixmin (charplot:scale-it xmin xscale))
|
||||
(iymin (charplot:scale-it ymin yscale)))
|
||||
(charplot:iplot! (map (lambda (p)
|
||||
(cons (- (charplot:scale-it (car p) xscale) ixmin)
|
||||
(- (charplot:scale-it (cdr p) yscale) iymin)))
|
||||
data)
|
||||
xlabel ylabel xmin xscale ymin yscale)))
|
||||
|
||||
(define (plot-function! func vlo vhi . npts)
|
||||
(set! npts (if (null? npts) 100 (car npts)))
|
||||
(let ((dats (make-array 0.0 npts 2)))
|
||||
(array-index-map! (make-shared-array dats (lambda (idx) (list idx 0)) npts)
|
||||
(lambda (idx) (+ vlo (* (- vhi vlo) (/ idx npts)))))
|
||||
(array-map! (make-shared-array dats (lambda (idx) (list idx 1)) npts)
|
||||
func
|
||||
(make-shared-array dats (lambda (idx) (list idx 0)) npts))
|
||||
(charplot:plot! dats "" "")))
|
||||
|
||||
(define plot! charplot:plot!)
|
|
@ -1,396 +0,0 @@
|
|||
;;;"chez.init" Initialization file for SLIB for Chez Scheme 6.0a -*-scheme-*-
|
||||
;;; Authors: dorai@cs.rice.edu (Dorai Sitaram) and Aubrey Jaffer.
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
;;; Adapted to version 5.0c by stone@math.grin.edu (John David Stone) 1997
|
||||
;;; Adapted to version 6.0a by Gary T. Leavens <leavens@cs.iastate.edu>, 1999
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
;;; UNIX, VMS, MACOS, AMIGA and MS-DOS are supported.
|
||||
|
||||
(define (software-type) 'UNIX)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'chez)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page)
|
||||
"http://www.cs.indiana.edu/chezscheme/")
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-version) "6.0a")
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define implementation-vicinity
|
||||
(lambda () "/usr/unsup/scheme/chez/"))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(or
|
||||
;; Use this getenv if your implementation supports it.
|
||||
(getenv "SCHEME_LIBRARY_PATH")
|
||||
;; Use this path if your scheme does not support GETENV
|
||||
;; or if SCHEME_LIBRARY_PATH is not set.
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/local/lib/slib/")
|
||||
((VMS) "lib$scheme:")
|
||||
((MS-DOS) "C:\\SLIB\\")
|
||||
(else "")))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define home-vicinity
|
||||
(let ((home-path (getenv "HOME")))
|
||||
(lambda () home-path)))
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ; Chez Scheme can load Scheme source files, with the
|
||||
; command (slib:load-source "filename") -- see below.
|
||||
|
||||
compiled ; Chez Scheme can also load compiled Scheme files, with the
|
||||
; command (slib:load-compiled "filename") -- see below.
|
||||
rev4-report ;conforms to
|
||||
rev3-report ;conforms to
|
||||
ieee-p1178 ;conforms to
|
||||
; sicp ;runs code from Structure and
|
||||
;Interpretation of Computer
|
||||
;Programs by Abelson and Sussman.
|
||||
rev4-optional-procedures ;LIST-TAIL, STRING->LIST,
|
||||
;LIST->STRING, STRING-COPY,
|
||||
;STRING-FILL!, LIST->VECTOR,
|
||||
;VECTOR->LIST, and VECTOR-FILL!
|
||||
; rev2-procedures ;SUBSTRING-MOVE-LEFT!,
|
||||
;SUBSTRING-MOVE-RIGHT!,
|
||||
;SUBSTRING-FILL!,
|
||||
;STRING-NULL?, APPEND!, 1+,
|
||||
;-1+, <?, <=?, =?, >?, >=?
|
||||
multiarg/and- ;/ and - can take more than 2 args.
|
||||
multiarg-apply ;APPLY can take more than 2 args.
|
||||
rationalize
|
||||
delay ;has DELAY and FORCE
|
||||
with-file ;has WITH-INPUT-FROM-FILE and
|
||||
;WITH-OUTPUT-FROM-FILE
|
||||
string-port ;has CALL-WITH-INPUT-STRING and
|
||||
;CALL-WITH-OUTPUT-STRING
|
||||
transcript ;TRANSCRIPT-ON and TRANSCRIPT-OFF
|
||||
char-ready?
|
||||
macro ;has R4RS high level macros
|
||||
; defmacro ;has Common Lisp DEFMACRO
|
||||
eval ;R5RS two-argument eval
|
||||
record ;has user defined data structures
|
||||
values ;proposed multiple values
|
||||
dynamic-wind ;proposed dynamic-wind
|
||||
; ieee-floating-point ;conforms to
|
||||
full-continuation ;can return multiple times
|
||||
; object-hash ;has OBJECT-HASH
|
||||
|
||||
sort
|
||||
; queue ;queues
|
||||
pretty-print
|
||||
; object->string
|
||||
format
|
||||
trace ;has macros: TRACE and UNTRACE
|
||||
; compiler ;has (COMPILER)
|
||||
; ed ;(ED) is editor
|
||||
system ;posix (system <string>)
|
||||
getenv ;posix (getenv <string>)
|
||||
; program-arguments ;returns list of strings (argv)
|
||||
; Xwindows ;X support
|
||||
; curses ;screen management package
|
||||
; termcap ;terminal description package
|
||||
; terminfo ;sysV terminal description
|
||||
; current-time ;returns time in seconds since 1/1/1970
|
||||
fluid-let
|
||||
random
|
||||
rev3-procedures
|
||||
))
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>) returns the number of graphic characters
|
||||
;;; that can reliably be displayed on one line of the standard output port.
|
||||
|
||||
(define output-port-width
|
||||
(lambda arg
|
||||
(let ((env-width-string (getenv "COLUMNS")))
|
||||
(if (and env-width-string
|
||||
(let loop ((remaining (string-length env-width-string)))
|
||||
(or (zero? remaining)
|
||||
(let ((next (- remaining 1)))
|
||||
(and (char-numeric? (string-ref env-width-string
|
||||
next))
|
||||
(loop next))))))
|
||||
(- (string->number env-width-string) 1)
|
||||
79))))
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>) returns the number of lines of text that
|
||||
;;; can reliably be displayed simultaneously in the standard output port.
|
||||
|
||||
(define output-port-height
|
||||
(lambda arg
|
||||
(let ((env-height-string (getenv "LINES")))
|
||||
(if (and env-height-string
|
||||
(let loop ((remaining (string-length env-height-string)))
|
||||
(or (zero? remaining)
|
||||
(let ((next (- remaining 1)))
|
||||
(and (char-numeric? (string-ref env-height-string
|
||||
next))
|
||||
(loop next))))))
|
||||
(string->number env-height-string)
|
||||
24))))
|
||||
|
||||
;;; (CURRENT-ERROR-PORT)
|
||||
(define current-error-port
|
||||
(let ((port (console-output-port))) ; changed from current-output-port
|
||||
(lambda () port)))
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam
|
||||
(let ((cntr 100))
|
||||
(lambda ()
|
||||
(set! cntr (+ 1 cntr))
|
||||
(let ((tmp (string-append "slib_" (number->string cntr))))
|
||||
(if (file-exists? tmp) (tmpnam) tmp)))))
|
||||
|
||||
;;; (FILE-EXISTS? <string>) is built-in to Chez Scheme
|
||||
|
||||
;;; (DELETE-FILE <string>) is built-in to Chez Scheme
|
||||
|
||||
;; The FORCE-OUTPUT requires buffered output that has been written to a
|
||||
;; port to be transferred all the way out to its ultimate destination.
|
||||
(define force-output flush-output-port)
|
||||
|
||||
;;; "rationalize" adjunct procedures.
|
||||
(define (find-ratio x e)
|
||||
(let ((rat (rationalize x e)))
|
||||
(list (numerator rat) (denominator rat))))
|
||||
(define (find-ratio-between x y)
|
||||
(find-ratio (/ (+ x y) 2) (/ (- x y) 2)))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
;; Chez's MOST-POSITIVE-FIXNUM is a thunk rather than a number.
|
||||
|
||||
(if (procedure? most-positive-fixnum)
|
||||
(set! most-positive-fixnum (most-positive-fixnum)))
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
;;; define an error procedure for the library
|
||||
(define slib:error
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Error: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args)
|
||||
(error #f ""))))
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab #\tab)
|
||||
(define slib:form-feed #\page)
|
||||
|
||||
;;; Support for older versions of Scheme. Not enough code for its own file.
|
||||
;;; last-pair is built-in to Chez Scheme
|
||||
(define t #t)
|
||||
(define nil #f)
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
;;; 1+, -1+, and 1- are built-in to Chez Scheme
|
||||
;(define (1+ n) (+ n 1))
|
||||
;(define (-1+ n) (+ n -1))
|
||||
;(define 1- -1+)
|
||||
|
||||
;;; (IN-VICINITY <string>) is simply STRING-APPEND, conventionally used
|
||||
;;; to attach a directory pathname to the name of a file that is expected to
|
||||
;;; be in that directory.
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:chez:quit
|
||||
(let ((arg (call-with-current-continuation identity)))
|
||||
(cond ((procedure? arg) arg)
|
||||
(arg (exit))
|
||||
(else (exit 1)))))
|
||||
|
||||
(define slib:exit
|
||||
(lambda args
|
||||
(cond ((null? args) (slib:chez:quit #t))
|
||||
((eqv? #t (car args)) (slib:chez:quit #t))
|
||||
((eqv? #f (car args)) (slib:chez:quit #f))
|
||||
((zero? (car args)) (slib:chez:quit #t))
|
||||
(else (slib:chez:quit #f)))))
|
||||
|
||||
;;; For backward compatability, the SCHEME-FILE-SUFFIX procedure is defined
|
||||
;;; to return the string ".scm". Note, however, that ".ss" is a common Chez
|
||||
;;; file suffix.
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define (slib:load-source f) (load (string-append f ".scm")))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
;;; The following make procedures in Chez Scheme compatible with
|
||||
;;; the assumptions of SLIB.
|
||||
|
||||
;;; Chez's sorting routines take parameters in the order opposite to SLIB's.
|
||||
;;; The following definitions override the predefined procedures with the
|
||||
;;; parameters-reversed versions. See the SORT feature.
|
||||
|
||||
(define chez:sort sort)
|
||||
(define chez:sort! sort!)
|
||||
(define chez:merge merge)
|
||||
(define chez:merge! merge!)
|
||||
|
||||
(define sort
|
||||
(lambda (s p)
|
||||
(chez:sort p s)))
|
||||
(define sort!
|
||||
(lambda (s p)
|
||||
(chez:sort! p s)))
|
||||
(define merge
|
||||
(lambda (s1 s2 p)
|
||||
(chez:merge p s1 s2)))
|
||||
(define merge!
|
||||
(lambda (s1 s2 p)
|
||||
(chez:merge! p s1 s2)))
|
||||
|
||||
;;; Chez's (FORMAT F . A) corresponds to SLIB's (FORMAT #F F . A)
|
||||
;;; See the FORMAT feature.
|
||||
|
||||
(define chez:format format)
|
||||
|
||||
(define format
|
||||
(lambda (where how . args)
|
||||
(let ((str (apply chez:format how args)))
|
||||
(cond ((not where) str)
|
||||
((eq? where #t) (display str))
|
||||
(else (display str where))))))
|
||||
|
||||
;; The following definitions implement a few widely useful procedures that
|
||||
;; Chez Scheme does not provide or provides under a different name.
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-INPUT-FILE and CALL-WITH-OUTPUT-FILE.
|
||||
;;; See the STRING-PORT feature.
|
||||
|
||||
(define call-with-output-string
|
||||
(lambda (f)
|
||||
(let ((outsp (open-output-string)))
|
||||
(f outsp)
|
||||
(let ((s (get-output-string outsp)))
|
||||
(close-output-port outsp)
|
||||
s))))
|
||||
|
||||
(define call-with-input-string
|
||||
(lambda (s f)
|
||||
(let* ((insp (open-input-string s))
|
||||
(res (f insp)))
|
||||
(close-input-port insp)
|
||||
res)))
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
(define macro:eval slib:eval)
|
||||
;;; macro:load also needs the default suffix.
|
||||
(define macro:load slib:load-source)
|
||||
|
||||
(define *defmacros*
|
||||
(list (cons 'defmacro
|
||||
(lambda (name parms . body)
|
||||
`(set! *defmacros* (cons (cons ',name (lambda ,parms ,@body))
|
||||
*defmacros*))))))
|
||||
(define (defmacro? m) (and (assq m *defmacros*) #t))
|
||||
|
||||
(define (macroexpand-1 e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a) (set! a (assq a *defmacros*))
|
||||
(if a (apply (cdr a) (cdr e)) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define (macroexpand e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a)
|
||||
(set! a (assq a *defmacros*))
|
||||
(if a (macroexpand (apply (cdr a) (cdr e))) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
;;; According to Kent Dybvig, you can improve the Chez Scheme init
|
||||
;;; file by defining gentemp to be gensym in Chez Scheme.
|
||||
(define gentemp gensym)
|
||||
|
||||
(define base:eval slib:eval)
|
||||
(define (defmacro:eval x) (base:eval (defmacro:expand* x)))
|
||||
(define (defmacro:expand* x)
|
||||
(require 'defmacroexpand) (apply defmacro:expand* x '()))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;;; Load the REQUIRE package.
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
||||
|
||||
;; end of chez.init
|
|
@ -1,67 +0,0 @@
|
|||
;;;; "cltime.scm" Common-Lisp time conversion routines.
|
||||
;;; Copyright (C) 1994, 1997 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'values)
|
||||
(require 'time-zone)
|
||||
(require 'posix-time)
|
||||
|
||||
(define time:1900 (time:invert time:gmtime '#(0 0 0 1 0 0 #f #f 0 0 "GMT")))
|
||||
|
||||
(define (get-decoded-time)
|
||||
(decode-universal-time (get-universal-time)))
|
||||
|
||||
(define (get-universal-time)
|
||||
(difftime (current-time) time:1900))
|
||||
|
||||
(define (decode-universal-time utime . tzarg)
|
||||
(let ((tv (apply time:split
|
||||
(offset-time time:1900 utime)
|
||||
(if (null? tzarg)
|
||||
(tz:params utime (tzset))
|
||||
(list 0 (* 3600 (car tzarg)) "???")))))
|
||||
(values
|
||||
(vector-ref tv 0) ;second [0..59]
|
||||
(vector-ref tv 1) ;minute [0..59]
|
||||
(vector-ref tv 2) ;hour [0..23]
|
||||
(vector-ref tv 3) ;date [1..31]
|
||||
(+ 1 (vector-ref tv 4)) ;month [1..12]
|
||||
(+ 1900 (vector-ref tv 5)) ;year [0....]
|
||||
(modulo (+ -1 (vector-ref tv 6)) 7) ;day-of-week [0..6] (0 is Monday)
|
||||
(eqv? 1 (vector-ref tv 8)) ;daylight-saving-time?
|
||||
(if (provided? 'inexact)
|
||||
(inexact->exact (/ (vector-ref tv 9) 3600))
|
||||
(/ (vector-ref tv 9) 3600)) ;time-zone [-24..24]
|
||||
)))
|
||||
|
||||
(define (encode-universal-time second minute hour date month year . tzarg)
|
||||
(let* ((tz (if (null? tzarg)
|
||||
(tzset)
|
||||
(time-zone (string-append
|
||||
"???" (number->string (car tzarg))))))
|
||||
(tv (vector second
|
||||
minute
|
||||
hour
|
||||
date
|
||||
(+ -1 month)
|
||||
(+ -1900 year)
|
||||
#f ;ignored
|
||||
#f ;ignored
|
||||
)))
|
||||
(difftime (time:invert localtime tv) time:1900)))
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
;;"coerce.scm" Scheme Implementation of COMMON-LISP COERCE and TYPE-OF.
|
||||
; Copyright (C) 1995, 2001 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;@body
|
||||
;;Returns a symbol name for the type of @1.
|
||||
(define (type-of obj)
|
||||
(cond
|
||||
;;((null? obj) 'null)
|
||||
((boolean? obj) 'boolean)
|
||||
((char? obj) 'char)
|
||||
((number? obj) 'number)
|
||||
((string? obj) 'string)
|
||||
((symbol? obj) 'symbol)
|
||||
((input-port? obj) 'port)
|
||||
((output-port? obj) 'port)
|
||||
((procedure? obj) 'procedure)
|
||||
((eof-object? obj) 'eof-object)
|
||||
((list? obj) 'list)
|
||||
((pair? obj) 'pair)
|
||||
((and (provided? 'array) (array? obj)) 'array)
|
||||
((and (provided? 'record) (record? obj)) 'record)
|
||||
((vector? obj) 'vector)
|
||||
(else '?)))
|
||||
|
||||
;;@body
|
||||
;;Converts and returns @1 of type @code{char}, @code{number},
|
||||
;;@code{string}, @code{symbol}, @code{list}, or @code{vector} to
|
||||
;;@2 (which must be one of these symbols).
|
||||
(define (coerce obj result-type)
|
||||
(define (err) (slib:error 'coerce 'not obj '-> result-type))
|
||||
(define obj-type (type-of obj))
|
||||
(cond
|
||||
((eq? obj-type result-type) obj)
|
||||
(else
|
||||
(case obj-type
|
||||
((char) (case result-type
|
||||
((number integer) (char->integer obj))
|
||||
((string) (string obj))
|
||||
((symbol) (string->symbol (string obj)))
|
||||
((list) (list obj))
|
||||
((vector) (vector obj))
|
||||
(else (err))))
|
||||
((number) (case result-type
|
||||
((char) (integer->char obj))
|
||||
((atom) obj)
|
||||
((integer) obj)
|
||||
((string) (number->string obj))
|
||||
((symbol) (string->symbol (number->string obj)))
|
||||
((list) (string->list (number->string obj)))
|
||||
((vector) (list->vector (string->list (number->string obj))))
|
||||
(else (err))))
|
||||
((string) (case result-type
|
||||
((char) (if (= 1 (string-length obj)) (string-ref obj 0)
|
||||
(err)))
|
||||
((atom) (or (string->number obj) (string->symbol obj)))
|
||||
((number integer) (or (string->number obj) (err)))
|
||||
((symbol) (string->symbol obj))
|
||||
((list) (string->list obj))
|
||||
((vector) (list->vector (string->list obj)))
|
||||
(else (err))))
|
||||
((symbol) (case result-type
|
||||
((char) (coerce (symbol->string obj) 'char))
|
||||
((number integer) (coerce (symbol->string obj) 'number))
|
||||
((string) (symbol->string obj))
|
||||
((atom) obj)
|
||||
((list) (string->list (symbol->string obj)))
|
||||
((vector) (list->vector (string->list (symbol->string obj))))
|
||||
(else (err))))
|
||||
((list) (case result-type
|
||||
((char) (if (and (= 1 (length obj))
|
||||
(char? (car obj)))
|
||||
(car obj)
|
||||
(err)))
|
||||
((number integer)
|
||||
(or (string->number (list->string obj)) (err)))
|
||||
((string) (list->string obj))
|
||||
((symbol) (string->symbol (list->string obj)))
|
||||
((vector) (list->vector obj))
|
||||
(else (err))))
|
||||
((vector) (case result-type
|
||||
((char) (if (and (= 1 (vector-length obj))
|
||||
(char? (vector-ref obj 0)))
|
||||
(vector-ref obj 0)
|
||||
(err)))
|
||||
((number integer)
|
||||
(or (string->number (coerce obj string)) (err)))
|
||||
((string) (list->string (vector->list obj)))
|
||||
((symbol) (string->symbol (coerce obj string)))
|
||||
((list) (list->vector obj))
|
||||
(else (err))))
|
||||
(else (err))))))
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
@defun type-of obj
|
||||
|
||||
Returns a symbol name for the type of @var{obj}.
|
||||
@end defun
|
||||
|
||||
@defun coerce obj result-type
|
||||
|
||||
Converts and returns @var{obj} of type @code{char}, @code{number},
|
||||
@code{string}, @code{symbol}, @code{list}, or @code{vector} to
|
||||
@var{result-type} (which must be one of these symbols).
|
||||
@end defun
|
|
@ -1,236 +0,0 @@
|
|||
;"collect.scm" Sample collection operations
|
||||
; COPYRIGHT (c) Kenneth Dickey 1992
|
||||
;
|
||||
; This software may be used for any purpose whatever
|
||||
; without warrantee of any kind.
|
||||
; AUTHOR Ken Dickey
|
||||
; DATE 1992 September 1
|
||||
; LAST UPDATED 1992 September 2
|
||||
; NOTES Expository (optimizations & checks elided).
|
||||
; Requires YASOS (Yet Another Scheme Object System).
|
||||
|
||||
(require 'yasos)
|
||||
|
||||
(define-operation (collect:collection? obj)
|
||||
;; default
|
||||
(cond
|
||||
((or (list? obj) (vector? obj) (string? obj)) #t)
|
||||
(else #f)
|
||||
) )
|
||||
|
||||
(define (collect:empty? collection) (zero? (yasos:size collection)))
|
||||
|
||||
(define-operation (collect:gen-elts <collection>) ;; return element generator
|
||||
;; default behavior
|
||||
(cond ;; see utilities, below, for generators
|
||||
((vector? <collection>) (collect:vector-gen-elts <collection>))
|
||||
((list? <collection>) (collect:list-gen-elts <collection>))
|
||||
((string? <collection>) (collect:string-gen-elts <collection>))
|
||||
(else
|
||||
(slib:error "Operation not supported: GEN-ELTS " (yasos:print obj #f)))
|
||||
) )
|
||||
|
||||
(define-operation (collect:gen-keys collection)
|
||||
(if (or (vector? collection) (list? collection) (string? collection))
|
||||
(let ( (max+1 (yasos:size collection)) (index 0) )
|
||||
(lambda ()
|
||||
(cond
|
||||
((< index max+1)
|
||||
(set! index (collect:add1 index))
|
||||
(collect:sub1 index))
|
||||
(else (slib:error "no more keys in generator"))
|
||||
) ) )
|
||||
(slib:error "Operation not handled: GEN-KEYS " collection)
|
||||
) )
|
||||
|
||||
(define (collect:do-elts <proc> . <collections>)
|
||||
(let ( (max+1 (yasos:size (car <collections>)))
|
||||
(generators (map collect:gen-elts <collections>))
|
||||
)
|
||||
(let loop ( (counter 0) )
|
||||
(cond
|
||||
((< counter max+1)
|
||||
(apply <proc> (map (lambda (g) (g)) generators))
|
||||
(loop (collect:add1 counter))
|
||||
)
|
||||
(else 'unspecific) ; done
|
||||
) )
|
||||
) )
|
||||
|
||||
(define (collect:do-keys <proc> . <collections>)
|
||||
(let ( (max+1 (yasos:size (car <collections>)))
|
||||
(generators (map collect:gen-keys <collections>))
|
||||
)
|
||||
(let loop ( (counter 0) )
|
||||
(cond
|
||||
((< counter max+1)
|
||||
(apply <proc> (map (lambda (g) (g)) generators))
|
||||
(loop (collect:add1 counter))
|
||||
)
|
||||
(else 'unspecific) ; done
|
||||
) )
|
||||
) )
|
||||
|
||||
(define (collect:map-elts <proc> . <collections>)
|
||||
(let ( (max+1 (yasos:size (car <collections>)))
|
||||
(generators (map collect:gen-elts <collections>))
|
||||
(vec (make-vector (yasos:size (car <collections>))))
|
||||
)
|
||||
(let loop ( (index 0) )
|
||||
(cond
|
||||
((< index max+1)
|
||||
(vector-set! vec index (apply <proc> (map (lambda (g) (g)) generators)))
|
||||
(loop (collect:add1 index))
|
||||
)
|
||||
(else vec) ; done
|
||||
) )
|
||||
) )
|
||||
|
||||
(define (collect:map-keys <proc> . <collections>)
|
||||
(let ( (max+1 (yasos:size (car <collections>)))
|
||||
(generators (map collect:gen-keys <collections>))
|
||||
(vec (make-vector (yasos:size (car <collections>))))
|
||||
)
|
||||
(let loop ( (index 0) )
|
||||
(cond
|
||||
((< index max+1)
|
||||
(vector-set! vec index (apply <proc> (map (lambda (g) (g)) generators)))
|
||||
(loop (collect:add1 index))
|
||||
)
|
||||
(else vec) ; done
|
||||
) )
|
||||
) )
|
||||
|
||||
(define-operation (collect:for-each-key <collection> <proc>)
|
||||
;; default
|
||||
(collect:do-keys <proc> <collection>) ;; talk about lazy!
|
||||
)
|
||||
|
||||
(define-operation (collect:for-each-elt <collection> <proc>)
|
||||
(collect:do-elts <proc> <collection>)
|
||||
)
|
||||
|
||||
(define (collect:reduce <proc> <seed> . <collections>)
|
||||
(let ( (max+1 (yasos:size (car <collections>)))
|
||||
(generators (map collect:gen-elts <collections>))
|
||||
)
|
||||
(let loop ( (count 0) )
|
||||
(cond
|
||||
((< count max+1)
|
||||
(set! <seed>
|
||||
(apply <proc> <seed> (map (lambda (g) (g)) generators)))
|
||||
(loop (collect:add1 count))
|
||||
)
|
||||
(else <seed>)
|
||||
) )
|
||||
) )
|
||||
|
||||
|
||||
|
||||
;; pred true for every elt?
|
||||
(define (collect:every? <pred?> . <collections>)
|
||||
(let ( (max+1 (yasos:size (car <collections>)))
|
||||
(generators (map collect:gen-elts <collections>))
|
||||
)
|
||||
(let loop ( (count 0) )
|
||||
(cond
|
||||
((< count max+1)
|
||||
(if (apply <pred?> (map (lambda (g) (g)) generators))
|
||||
(loop (collect:add1 count))
|
||||
#f)
|
||||
)
|
||||
(else #t)
|
||||
) )
|
||||
) )
|
||||
|
||||
;; pred true for any elt?
|
||||
(define (collect:any? <pred?> . <collections>)
|
||||
(let ( (max+1 (yasos:size (car <collections>)))
|
||||
(generators (map collect:gen-elts <collections>))
|
||||
)
|
||||
(let loop ( (count 0) )
|
||||
(cond
|
||||
((< count max+1)
|
||||
(if (apply <pred?> (map (lambda (g) (g)) generators))
|
||||
#t
|
||||
(loop (collect:add1 count))
|
||||
))
|
||||
(else #f)
|
||||
) )
|
||||
) )
|
||||
|
||||
|
||||
;; MISC UTILITIES
|
||||
|
||||
(define (collect:add1 obj) (+ obj 1))
|
||||
(define (collect:sub1 obj) (- obj 1))
|
||||
|
||||
;; Nota Bene: list-set! is bogus for element 0
|
||||
|
||||
(define (collect:list-set! <list> <index> <value>)
|
||||
|
||||
(define (set-loop last this idx)
|
||||
(cond
|
||||
((zero? idx)
|
||||
(set-cdr! last (cons <value> (cdr this)))
|
||||
<list>
|
||||
)
|
||||
(else (set-loop (cdr last) (cdr this) (collect:sub1 idx)))
|
||||
) )
|
||||
|
||||
;; main
|
||||
(if (zero? <index>)
|
||||
(cons <value> (cdr <list>)) ;; return value
|
||||
(set-loop <list> (cdr <list>) (collect:sub1 <index>)))
|
||||
)
|
||||
|
||||
(add-setter list-ref collect:list-set!) ; for (setter list-ref)
|
||||
|
||||
|
||||
;; generator for list elements
|
||||
(define (collect:list-gen-elts <list>)
|
||||
(lambda ()
|
||||
(if (null? <list>)
|
||||
(slib:error "No more list elements in generator")
|
||||
(let ( (elt (car <list>)) )
|
||||
(set! <list> (cdr <list>))
|
||||
elt))
|
||||
) )
|
||||
|
||||
;; generator for vector elements
|
||||
(define (collect:make-vec-gen-elts <accessor>)
|
||||
(lambda (vec)
|
||||
(let ( (max+1 (yasos:size vec))
|
||||
(index 0)
|
||||
)
|
||||
(lambda ()
|
||||
(cond ((< index max+1)
|
||||
(set! index (collect:add1 index))
|
||||
(<accessor> vec (collect:sub1 index))
|
||||
)
|
||||
(else #f)
|
||||
) )
|
||||
) )
|
||||
)
|
||||
|
||||
(define collect:vector-gen-elts (collect:make-vec-gen-elts vector-ref))
|
||||
|
||||
(define collect:string-gen-elts (collect:make-vec-gen-elts string-ref))
|
||||
|
||||
;;; exports:
|
||||
|
||||
(define collection? collect:collection?)
|
||||
(define empty? collect:empty?)
|
||||
(define gen-keys collect:gen-keys)
|
||||
(define gen-elts collect:gen-elts)
|
||||
(define do-elts collect:do-elts)
|
||||
(define do-keys collect:do-keys)
|
||||
(define map-elts collect:map-elts)
|
||||
(define map-keys collect:map-keys)
|
||||
(define for-each-key collect:for-each-key)
|
||||
(define for-each-elt collect:for-each-elt)
|
||||
(define reduce collect:reduce) ; reduce is also in comlist.scm
|
||||
(define every? collect:every?)
|
||||
(define any? collect:any?)
|
||||
|
||||
;; --- E O F "collect.oo" --- ;;
|
|
@ -1,328 +0,0 @@
|
|||
;;"comlist.scm" Implementation of COMMON LISP list functions for Scheme
|
||||
; Copyright (C) 1991, 1993, 1995 Aubrey Jaffer.
|
||||
; Copyright (C) 2000 Colin Walters
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; Some of these functions may be already defined in your Scheme.
|
||||
;;; Comment out those definitions for functions which are already defined.
|
||||
|
||||
;;;; LIST FUNCTIONS FROM COMMON LISP
|
||||
|
||||
;;; Some tail-recursive optimizations made by
|
||||
;;; Colin Walters <walters@cis.ohio-state.edu>
|
||||
|
||||
;;;From: hugh@ear.mit.edu (Hugh Secker-Walker)
|
||||
(define (comlist:make-list k . init)
|
||||
(set! init (if (pair? init) (car init)))
|
||||
(do ((k k (+ -1 k))
|
||||
(result '() (cons init result)))
|
||||
((<= k 0) result)))
|
||||
|
||||
(define (comlist:copy-list lst) (append lst '()))
|
||||
|
||||
(define (comlist:adjoin e l) (if (memv e l) l (cons e l)))
|
||||
|
||||
(define (comlist:union l1 l2)
|
||||
(cond ((null? l1) l2)
|
||||
((null? l2) l1)
|
||||
(else (comlist:union (cdr l1) (comlist:adjoin (car l1) l2)))))
|
||||
|
||||
(define (comlist:intersection l1 l2)
|
||||
;; optimization
|
||||
(if (null? l2)
|
||||
l2
|
||||
(let build-intersection ((l1 l1)
|
||||
(result '()))
|
||||
(cond ((null? l1)
|
||||
result)
|
||||
((memv (car l1) l2) (build-intersection (cdr l1) (cons (car l1) result)))
|
||||
(else (build-intersection (cdr l1) result))))))
|
||||
|
||||
(define (comlist:set-difference l1 l2)
|
||||
;; optimization
|
||||
(if (null? l2)
|
||||
l1
|
||||
(let build-difference ((l1 l1)
|
||||
(result '()))
|
||||
(cond ((null? l1)
|
||||
result)
|
||||
((memv (car l1) l2) (build-difference (cdr l1) result))
|
||||
(else (build-difference (cdr l1) (cons (car l1) result)))))))
|
||||
|
||||
(define (comlist:position obj lst)
|
||||
(letrec ((pos (lambda (n lst)
|
||||
(cond ((null? lst) #f)
|
||||
((eqv? obj (car lst)) n)
|
||||
(else (pos (+ 1 n) (cdr lst)))))))
|
||||
(pos 0 lst)))
|
||||
|
||||
(define (comlist:reduce-init p init l)
|
||||
(if (null? l)
|
||||
init
|
||||
(comlist:reduce-init p (p init (car l)) (cdr l))))
|
||||
|
||||
(define (comlist:reduce p l)
|
||||
(cond ((null? l) l)
|
||||
((null? (cdr l)) (car l))
|
||||
(else (comlist:reduce-init p (car l) (cdr l)))))
|
||||
|
||||
(define (comlist:some pred l . rest)
|
||||
(cond ((null? rest)
|
||||
(let mapf ((l l))
|
||||
(and (not (null? l))
|
||||
(or (pred (car l)) (mapf (cdr l))))))
|
||||
(else (let mapf ((l l) (rest rest))
|
||||
(and (not (null? l))
|
||||
(or (apply pred (car l) (map car rest))
|
||||
(mapf (cdr l) (map cdr rest))))))))
|
||||
|
||||
(define (comlist:every pred l . rest)
|
||||
(cond ((null? rest)
|
||||
(let mapf ((l l))
|
||||
(or (null? l)
|
||||
(and (pred (car l)) (mapf (cdr l))))))
|
||||
(else (let mapf ((l l) (rest rest))
|
||||
(or (null? l)
|
||||
(and (apply pred (car l) (map car rest))
|
||||
(mapf (cdr l) (map cdr rest))))))))
|
||||
|
||||
(define (comlist:notany pred . ls) (not (apply comlist:some pred ls)))
|
||||
|
||||
(define (comlist:notevery pred . ls) (not (apply comlist:every pred ls)))
|
||||
|
||||
(define (comlist:list-of?? predicate . bound)
|
||||
(define (errout) (apply slib:error 'list-of?? predicate bound))
|
||||
(case (length bound)
|
||||
((0)
|
||||
(lambda (obj)
|
||||
(and (list? obj)
|
||||
(every predicate obj))))
|
||||
((1)
|
||||
(set! bound (car bound))
|
||||
(cond ((negative? bound)
|
||||
(set! bound (- bound))
|
||||
(lambda (obj)
|
||||
(and (list? obj)
|
||||
(<= bound (length obj))
|
||||
(every predicate obj))))
|
||||
(else
|
||||
(lambda (obj)
|
||||
(and (list? obj)
|
||||
(<= (length obj) bound)
|
||||
(every predicate obj))))))
|
||||
((2)
|
||||
(let ((low (car bound))
|
||||
(high (cadr bound)))
|
||||
(cond ((or (negative? low) (negative? high)) (errout))
|
||||
((< high low)
|
||||
(set! high (car bound))
|
||||
(set! low (cadr bound))))
|
||||
(lambda (obj)
|
||||
(and (list? obj)
|
||||
(<= low (length obj) high)
|
||||
(every predicate obj)))))
|
||||
(else (errout))))
|
||||
|
||||
(define (comlist:find-if t l)
|
||||
(cond ((null? l) #f)
|
||||
((t (car l)) (car l))
|
||||
(else (comlist:find-if t (cdr l)))))
|
||||
|
||||
(define (comlist:member-if t l)
|
||||
(cond ((null? l) #f)
|
||||
((t (car l)) l)
|
||||
(else (comlist:member-if t (cdr l)))))
|
||||
|
||||
(define (comlist:remove p l)
|
||||
(let remove ((l l)
|
||||
(result '()))
|
||||
(cond ((null? l) result)
|
||||
((eqv? p (car l)) (remove (cdr l) result))
|
||||
(else (remove (cdr l) (cons (car l) result))))))
|
||||
|
||||
(define (comlist:remove-if p l)
|
||||
(let remove-if ((l l)
|
||||
(result '()))
|
||||
(cond ((null? l) result)
|
||||
((p (car l)) (remove-if (cdr l) result))
|
||||
(else (remove-if (cdr l) (cons (car l) result))))))
|
||||
|
||||
(define (comlist:remove-if-not p l)
|
||||
(let remove-if-not ((l l)
|
||||
(result '()))
|
||||
(cond ((null? l) result)
|
||||
((p (car l)) (remove-if-not (cdr l) (cons (car l) result)))
|
||||
(else (remove-if-not (cdr l) result)))))
|
||||
|
||||
(define comlist:nconc
|
||||
(if (provided? 'rev2-procedures) append!
|
||||
(lambda args
|
||||
(cond ((null? args) '())
|
||||
((null? (cdr args)) (car args))
|
||||
((null? (car args)) (apply comlist:nconc (cdr args)))
|
||||
(else
|
||||
(set-cdr! (last-pair (car args))
|
||||
(apply comlist:nconc (cdr args)))
|
||||
(car args))))))
|
||||
|
||||
;;;From: hugh@ear.mit.edu (Hugh Secker-Walker)
|
||||
(define (comlist:nreverse rev-it)
|
||||
;;; Reverse order of elements of LIST by mutating cdrs.
|
||||
(cond ((null? rev-it) rev-it)
|
||||
((not (list? rev-it))
|
||||
(slib:error "nreverse: Not a list in arg1" rev-it))
|
||||
(else (do ((reved '() rev-it)
|
||||
(rev-cdr (cdr rev-it) (cdr rev-cdr))
|
||||
(rev-it rev-it rev-cdr))
|
||||
((begin (set-cdr! rev-it reved) (null? rev-cdr)) rev-it)))))
|
||||
|
||||
(define (comlist:last lst n)
|
||||
(comlist:nthcdr (- (length lst) n) lst))
|
||||
|
||||
(define (comlist:butlast lst n)
|
||||
(letrec ((l (- (length lst) n))
|
||||
(bl (lambda (lst n)
|
||||
(let build-until-zero ((lst lst)
|
||||
(n n)
|
||||
(result '()))
|
||||
(cond ((null? lst) (reverse result))
|
||||
((positive? n)
|
||||
(build-until-zero (cdr lst) (- n 1) (cons (car lst) result)))
|
||||
(else (reverse result)))))))
|
||||
(bl lst (if (negative? n)
|
||||
(slib:error "negative argument to butlast" n)
|
||||
l))))
|
||||
|
||||
(define (comlist:nthcdr n lst)
|
||||
(if (zero? n) lst (comlist:nthcdr (+ -1 n) (cdr lst))))
|
||||
|
||||
(define (comlist:butnthcdr n lst)
|
||||
(letrec ((bl (lambda (lst n)
|
||||
(let build-until-zero ((lst lst)
|
||||
(n n)
|
||||
(result '()))
|
||||
(cond ((null? lst) (reverse result))
|
||||
((positive? n)
|
||||
(build-until-zero (cdr lst) (- n 1) (cons (car lst) result)))
|
||||
(else (reverse result)))))))
|
||||
(bl lst (if (negative? n)
|
||||
(slib:error "negative argument to butnthcdr" n)
|
||||
n))))
|
||||
|
||||
;;;; CONDITIONALS
|
||||
|
||||
(define (comlist:and? . args)
|
||||
(cond ((null? args) #t)
|
||||
((car args) (apply comlist:and? (cdr args)))
|
||||
(else #f)))
|
||||
|
||||
(define (comlist:or? . args)
|
||||
(cond ((null? args) #f)
|
||||
((car args) #t)
|
||||
(else (apply comlist:or? (cdr args)))))
|
||||
|
||||
;;; Checks to see if a list has any duplicate MEMBERs.
|
||||
(define (comlist:has-duplicates? lst)
|
||||
(cond ((null? lst) #f)
|
||||
((member (car lst) (cdr lst)) #t)
|
||||
(else (comlist:has-duplicates? (cdr lst)))))
|
||||
|
||||
;;; remove duplicates of MEMBERs of a list
|
||||
(define (comlist:remove-duplicates lst)
|
||||
(letrec ((rem-dup
|
||||
(lambda (lst nlst)
|
||||
(cond ((null? lst) nlst)
|
||||
((member (car lst) nlst) (rem-dup (cdr lst) nlst))
|
||||
(else (rem-dup (cdr lst) (cons (car lst) nlst)))))))
|
||||
(rem-dup lst '())))
|
||||
|
||||
(define (comlist:list* x . y)
|
||||
(define (list*1 x)
|
||||
(if (null? (cdr x))
|
||||
(car x)
|
||||
(cons (car x) (list*1 (cdr x)))))
|
||||
(if (null? y)
|
||||
x
|
||||
(cons x (list*1 y))))
|
||||
|
||||
(define (comlist:atom? a)
|
||||
(not (pair? a)))
|
||||
|
||||
(define (comlist:delete obj list)
|
||||
(let delete ((list list))
|
||||
(cond ((null? list) '())
|
||||
((equal? obj (car list)) (delete (cdr list)))
|
||||
(else
|
||||
(set-cdr! list (delete (cdr list)))
|
||||
list))))
|
||||
|
||||
(define (comlist:delete-if pred list)
|
||||
(let delete-if ((list list))
|
||||
(cond ((null? list) '())
|
||||
((pred (car list)) (delete-if (cdr list)))
|
||||
(else
|
||||
(set-cdr! list (delete-if (cdr list)))
|
||||
list))))
|
||||
|
||||
(define (comlist:delete-if-not pred list)
|
||||
(let delete-if ((list list))
|
||||
(cond ((null? list) '())
|
||||
((not (pred (car list))) (delete-if (cdr list)))
|
||||
(else
|
||||
(set-cdr! list (delete-if (cdr list)))
|
||||
list))))
|
||||
|
||||
;;; exports
|
||||
|
||||
(define make-list comlist:make-list)
|
||||
(define copy-list comlist:copy-list)
|
||||
(define adjoin comlist:adjoin)
|
||||
(define union comlist:union)
|
||||
(define intersection comlist:intersection)
|
||||
(define set-difference comlist:set-difference)
|
||||
(define position comlist:position)
|
||||
(define reduce-init comlist:reduce-init)
|
||||
(define reduce comlist:reduce) ; reduce is also in collect.scm
|
||||
(define some comlist:some)
|
||||
(define every comlist:every)
|
||||
(define notevery comlist:notevery)
|
||||
(define notany comlist:notany)
|
||||
(define find-if comlist:find-if)
|
||||
(define member-if comlist:member-if)
|
||||
(define remove comlist:remove)
|
||||
(define remove-if comlist:remove-if)
|
||||
(define remove-if-not comlist:remove-if-not)
|
||||
(define nconc comlist:nconc)
|
||||
(define nreverse comlist:nreverse)
|
||||
(define last comlist:last)
|
||||
(define butlast comlist:butlast)
|
||||
(define nthcdr comlist:nthcdr)
|
||||
(define butnthcdr comlist:butnthcdr)
|
||||
(define and? comlist:and?)
|
||||
(define or? comlist:or?)
|
||||
(define has-duplicates? comlist:has-duplicates?)
|
||||
(define remove-duplicates comlist:remove-duplicates)
|
||||
|
||||
(define delete-if-not comlist:delete-if-not)
|
||||
(define delete-if comlist:delete-if)
|
||||
(define delete comlist:delete)
|
||||
(define comlist:atom comlist:atom?)
|
||||
(define atom comlist:atom?)
|
||||
(define atom? comlist:atom?)
|
||||
(define list* comlist:list*)
|
||||
(define list-of?? comlist:list-of??)
|
|
@ -1,99 +0,0 @@
|
|||
;;; "comparse.scm" Break command line into arguments.
|
||||
;Copyright (C) 1995, 1997 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;;; This is a simple command-line reader. It could be made fancier
|
||||
;;; to handle lots of `shell' syntaxes.
|
||||
|
||||
;;; Albert L. Ting points out that a similar process can be used for
|
||||
;;; reading files of options -- therefore READ-OPTIONS-FILE.
|
||||
|
||||
(require 'string-port)
|
||||
(define (read-command-from-port port nl-term?)
|
||||
(define argv '())
|
||||
(define obj "")
|
||||
(define chars '())
|
||||
(define readc (lambda () (read-char port)))
|
||||
(define peekc (lambda () (peek-char port)))
|
||||
(define s-expression
|
||||
(lambda ()
|
||||
(splice-arg (call-with-output-string
|
||||
(lambda (p) (display (slib:eval (read port)) p))))))
|
||||
(define backslash
|
||||
(lambda (goto)
|
||||
(readc)
|
||||
(let ((c (readc)))
|
||||
(cond ((eqv? #\newline c) (goto (peekc)))
|
||||
((and (char-whitespace? c) (eqv? #\newline (peekc))
|
||||
(eqv? 13 (char->integer c)))
|
||||
(readc) (goto (peekc)))
|
||||
(else (set! chars (cons c chars)) (build-token (peekc)))))))
|
||||
(define loop
|
||||
(lambda (c)
|
||||
(case c
|
||||
((#\\) (backslash loop))
|
||||
((#\") (splice-arg (read port)))
|
||||
((#\( #\') (s-expression))
|
||||
((#\#) (do ((c (readc) (readc)))
|
||||
((or (eof-object? c) (eqv? #\newline c))
|
||||
(if nl-term? c (loop (peekc))))))
|
||||
((#\;) (readc))
|
||||
((#\newline) (readc) (and (not nl-term?) (loop (peekc))))
|
||||
(else (cond ((eof-object? c) c)
|
||||
((char-whitespace? c) (readc) (loop (peekc)))
|
||||
(else (build-token c)))))))
|
||||
(define splice-arg
|
||||
(lambda (arg)
|
||||
(set! obj (string-append obj (list->string (reverse chars)) arg))
|
||||
(set! chars '())
|
||||
(build-token (peekc))))
|
||||
(define buildit
|
||||
(lambda ()
|
||||
(readc)
|
||||
(set! argv (cons (string-append obj (list->string (reverse chars)))
|
||||
argv))))
|
||||
(define build-token
|
||||
(lambda (c)
|
||||
(case c
|
||||
((#\") (splice-arg (read port)))
|
||||
((#\() (s-expression))
|
||||
((#\\) (backslash build-token))
|
||||
((#\;) (buildit))
|
||||
(else (cond ((or (eof-object? c) (char-whitespace? c))
|
||||
(buildit)
|
||||
(cond ((not (and nl-term? (eqv? c #\newline)))
|
||||
(set! obj "")
|
||||
(set! chars '())
|
||||
(loop (peekc)))))
|
||||
(else (set! chars (cons (readc) chars))
|
||||
(build-token (peekc))))))))
|
||||
(let ((c (loop (peekc))))
|
||||
(cond ((and (null? argv) (eof-object? c)) c)
|
||||
(else (reverse argv)))))
|
||||
|
||||
(define (read-command . port)
|
||||
(read-command-from-port (cond ((null? port) (current-input-port))
|
||||
((= 1 (length port)) (car port))
|
||||
(else
|
||||
(slib:error 'read-command
|
||||
"Wrong Number of ARGs:" port)))
|
||||
#t))
|
||||
|
||||
(define (read-options-file filename)
|
||||
(call-with-input-file filename
|
||||
(lambda (port) (read-command-from-port port #f))))
|
|
@ -1,470 +0,0 @@
|
|||
;;;"cring.scm" Extend Scheme numerics to any commutative ring.
|
||||
;Copyright (C) 1997, 1998 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'common-list-functions)
|
||||
(require 'relational-database)
|
||||
(require 'database-utilities)
|
||||
(require 'sort)
|
||||
|
||||
(define cring:db (create-database #f 'alist-table))
|
||||
(define (make-ruleset . rules)
|
||||
(define name #f)
|
||||
(cond ((and (not (null? rules)) (symbol? (car rules)))
|
||||
(set! name (car rules))
|
||||
(set! rules (cdr rules)))
|
||||
(else (set! name (gentemp))))
|
||||
(define-tables cring:db
|
||||
(list name
|
||||
'((op symbol)
|
||||
(sub-op1 symbol)
|
||||
(sub-op2 symbol))
|
||||
'((reduction expression))
|
||||
rules))
|
||||
(let ((table ((cring:db 'open-table) name #t)))
|
||||
(and table
|
||||
(list (table 'get 'reduction)
|
||||
(table 'row:update)
|
||||
table))))
|
||||
(define *ruleset* (make-ruleset 'default))
|
||||
(define (cring:define-rule . args)
|
||||
(if *ruleset*
|
||||
((cadr *ruleset*) args)
|
||||
(slib:warn "No ruleset in *ruleset*")))
|
||||
|
||||
(define (combined-rulesets . rulesets)
|
||||
(define name #f)
|
||||
(cond ((symbol? (car rulesets))
|
||||
(set! name (car rulesets))
|
||||
(set! rulesets (cdr rulesets)))
|
||||
(else (set! name (gentemp))))
|
||||
(apply make-ruleset name
|
||||
(apply append
|
||||
(map (lambda (ruleset) (((caddr ruleset) 'row:retrieve*)))
|
||||
rulesets))))
|
||||
|
||||
;;; Distribute * over + (and -)
|
||||
(define distribute*
|
||||
(make-ruleset
|
||||
'distribute*
|
||||
`(* + identity
|
||||
,(lambda (exp1 exp2)
|
||||
;;(print 'distributing '* '+ exp1 exp2 '==>)
|
||||
(apply + (map (lambda (trm) (* trm exp2)) (cdr exp1)))))
|
||||
`(* - identity
|
||||
,(lambda (exp1 exp2)
|
||||
;;(print 'distributing '* '- exp1 exp2 '==>)
|
||||
(apply - (map (lambda (trm) (* trm exp2)) (cdr exp1)))))))
|
||||
|
||||
;;; Distribute / over + (and -)
|
||||
(define distribute/
|
||||
(make-ruleset
|
||||
'distribute/
|
||||
`(/ + identity
|
||||
,(lambda (exp1 exp2)
|
||||
;;(print 'distributing '/ '+ exp1 exp2 '==>)
|
||||
(apply + (map (lambda (trm) (/ trm exp2)) (cdr exp1)))))
|
||||
`(/ - identity
|
||||
,(lambda (exp1 exp2)
|
||||
;;(print 'distributing '/ '- exp1 exp2 '==>)
|
||||
(apply - (map (lambda (trm) (/ trm exp2)) (cdr exp1)))))))
|
||||
|
||||
(define (symbol-alpha? sym)
|
||||
(char-alphabetic? (string-ref (symbol->string sym) 0)))
|
||||
(define (expression-< x y)
|
||||
(cond ((and (number? x) (number? y)) (> x y)) ;want negatives last
|
||||
((number? x) #t)
|
||||
((number? y) #f)
|
||||
((and (symbol? x) (symbol? y))
|
||||
(cond ((eqv? (symbol-alpha? x) (symbol-alpha? y))
|
||||
(string<? (symbol->string x) (symbol->string y)))
|
||||
(else (symbol-alpha? x))))
|
||||
((symbol? x) #t)
|
||||
((symbol? y) #f)
|
||||
((null? x) #t)
|
||||
((null? y) #f)
|
||||
((expression-< (car x) (car y)) #t)
|
||||
((expression-< (car y) (car x)) #f)
|
||||
(else (expression-< (cdr x) (cdr y)))))
|
||||
(define (expression-sort seq) (sort! seq expression-<))
|
||||
|
||||
(define number* *)
|
||||
(define number+ +)
|
||||
(define number- -)
|
||||
(define number/ /)
|
||||
(define number^ integer-expt)
|
||||
(define is-term-op? (lambda (term op) (and (pair? term) (eq? op (car term)))))
|
||||
;;(define (sign x) (if (positive? x) 1 (if (negative? x) -1 0)))
|
||||
(define number0? zero?)
|
||||
(define (zero? x) (and (number? x) (number0? x)))
|
||||
|
||||
;; To convert to CR internal form, NUMBER-op all the `numbers' in the
|
||||
;; argument list and remove them from the argument list. Collect the
|
||||
;; remaining arguments into equivalence classes, keeping track of the
|
||||
;; number of arguments in each class. The returned list is thus:
|
||||
;; (<numeric> (<expression1> . <exp1>) ...)
|
||||
|
||||
;;; Converts * argument list to CR internal form
|
||||
(define (cr*-args->fcts args)
|
||||
;;(print (cons 'cr*-args->fcts args) '==>)
|
||||
(let loop ((args args) (pow 1) (nums 1) (arg.exps '()))
|
||||
;;(print (list 'loop args pow nums denoms arg.exps) '==>)
|
||||
(cond ((null? args) (cons nums arg.exps))
|
||||
((number? (car args))
|
||||
(let ((num^pow (number^ (car args) (abs pow))))
|
||||
(if (negative? pow)
|
||||
(loop (cdr args) pow (number/ (number* num^pow nums))
|
||||
arg.exps)
|
||||
(loop (cdr args) pow (number* num^pow nums) arg.exps))))
|
||||
;; Associative Rule
|
||||
((is-term-op? (car args) '*) (loop (append (cdar args) (cdr args))
|
||||
pow nums arg.exps))
|
||||
;; Do singlet -
|
||||
((and (is-term-op? (car args) '-) (= 2 (length (car args))))
|
||||
;;(print 'got-here (car args))
|
||||
(set! arg.exps (loop (cdar args) pow (number- nums) arg.exps))
|
||||
(loop (cdr args) pow
|
||||
(car arg.exps)
|
||||
(cdr arg.exps)))
|
||||
((and (is-term-op? (car args) '/) (= 2 (length (car args))))
|
||||
;; Do singlet /
|
||||
;;(print 'got-here=cr+ (car args))
|
||||
(set! arg.exps (loop (cdar args) (number- pow) nums arg.exps))
|
||||
(loop (cdr args) pow
|
||||
(car arg.exps)
|
||||
(cdr arg.exps)))
|
||||
((is-term-op? (car args) '/)
|
||||
;; Do multi-arg /
|
||||
;;(print 'doing '/ (cddar args) (number- pow))
|
||||
(set! arg.exps
|
||||
(loop (cddar args) (number- pow) nums arg.exps))
|
||||
;;(print 'finishing '/ (cons (cadar args) (cdr args)) pow)
|
||||
(loop (cons (cadar args) (cdr args))
|
||||
pow
|
||||
(car arg.exps)
|
||||
(cdr arg.exps)))
|
||||
;; Pull out numeric exponents as powers
|
||||
((and (is-term-op? (car args) '^)
|
||||
(= 3 (length (car args)))
|
||||
(number? (caddar args)))
|
||||
(set! arg.exps (loop (list (cadar args))
|
||||
(number* pow (caddar args))
|
||||
nums
|
||||
arg.exps))
|
||||
(loop (cdr args) pow (car arg.exps) (cdr arg.exps)))
|
||||
;; combine with same terms
|
||||
((assoc (car args) arg.exps)
|
||||
=> (lambda (pair) (set-cdr! pair (number+ pow (cdr pair)))
|
||||
(loop (cdr args) pow nums arg.exps)))
|
||||
;; Add new term to arg.exps
|
||||
(else (loop (cdr args) pow nums
|
||||
(cons (cons (car args) pow) arg.exps))))))
|
||||
|
||||
;;; Converts + argument list to CR internal form
|
||||
(define (cr+-args->trms args)
|
||||
(let loop ((args args) (cof 1) (numbers 0) (arg.exps '()))
|
||||
(cond ((null? args) (cons numbers arg.exps))
|
||||
((number? (car args))
|
||||
(loop (cdr args)
|
||||
cof
|
||||
(number+ (number* (car args) cof) numbers)
|
||||
arg.exps))
|
||||
;; Associative Rule
|
||||
((is-term-op? (car args) '+) (loop (append (cdar args) (cdr args))
|
||||
cof
|
||||
numbers
|
||||
arg.exps))
|
||||
;; Idempotent singlet *
|
||||
((and (is-term-op? (car args) '*) (= 2 (length (car args))))
|
||||
(loop (cons (cadar args) (cdr args))
|
||||
cof
|
||||
numbers
|
||||
arg.exps))
|
||||
((and (is-term-op? (car args) '-) (= 2 (length (car args))))
|
||||
;; Do singlet -
|
||||
(set! arg.exps (loop (cdar args) (number- cof) numbers arg.exps))
|
||||
(loop (cdr args) cof (car arg.exps) (cdr arg.exps)))
|
||||
;; Pull out numeric factors as coefficients
|
||||
((and (is-term-op? (car args) '*) (some number? (cdar args)))
|
||||
;;(print 'got-here (car args) '=> (cons '* (remove-if number? (cdar args))))
|
||||
(set! arg.exps
|
||||
(loop (list (cons '* (remove-if number? (cdar args))))
|
||||
(apply number* cof (remove-if-not number? (cdar args)))
|
||||
numbers
|
||||
arg.exps))
|
||||
(loop (cdr args) cof (car arg.exps) (cdr arg.exps)))
|
||||
((is-term-op? (car args) '-)
|
||||
;; Do multi-arg -
|
||||
(set! arg.exps (loop (cddar args) (number- cof) numbers arg.exps))
|
||||
(loop (cons (cadar args) (cdr args))
|
||||
cof
|
||||
(car arg.exps)
|
||||
(cdr arg.exps)))
|
||||
;; combine with same terms
|
||||
((assoc (car args) arg.exps)
|
||||
=> (lambda (pair) (set-cdr! pair (number+ cof (cdr pair)))
|
||||
(loop (cdr args) cof numbers arg.exps)))
|
||||
;; Add new term to arg.exps
|
||||
(else (loop (cdr args) cof numbers
|
||||
(cons (cons (car args) cof) arg.exps))))))
|
||||
|
||||
;;; Converts + or * internal form to Scheme expression
|
||||
(define (cr-terms->form op ident inv-op higher-op res.cofs)
|
||||
(define (negative-cof? fct.cof)
|
||||
(negative? (cdr fct.cof)))
|
||||
(define (finish exprs)
|
||||
(if (null? exprs) ident
|
||||
(if (null? (cdr exprs))
|
||||
(car exprs)
|
||||
(cons op exprs))))
|
||||
(define (do-terms sign fct.cofs)
|
||||
(expression-sort
|
||||
(map (lambda (fct.cof)
|
||||
(define cof (number* sign (cdr fct.cof)))
|
||||
(cond ((eqv? 1 cof) (car fct.cof))
|
||||
((number? (car fct.cof)) (number* cof (car fct.cof)))
|
||||
((is-term-op? (car fct.cof) higher-op)
|
||||
(if (eq? higher-op '^)
|
||||
(list '^ (cadar fct.cof) (* cof (caddar fct.cof)))
|
||||
(cons higher-op (cons cof (cdar fct.cof)))))
|
||||
((eqv? -1 cof) (list inv-op (car fct.cof)))
|
||||
(else (list higher-op (car fct.cof) cof))))
|
||||
fct.cofs)))
|
||||
(let* ((all.cofs (remove-if (lambda (fct.cof)
|
||||
(or (zero? (cdr fct.cof))
|
||||
(eqv? ident (car fct.cof))))
|
||||
res.cofs))
|
||||
(cofs (map cdr all.cofs))
|
||||
(some-positive? (some positive? cofs)))
|
||||
;;(print op 'positive? some-positive? 'negative? (some negative? cofs) all.cofs)
|
||||
(cond ((and some-positive? (some negative? cofs))
|
||||
(append (list inv-op
|
||||
(finish (do-terms
|
||||
1 (remove-if negative-cof? all.cofs))))
|
||||
(do-terms -1 (remove-if-not negative-cof? all.cofs))))
|
||||
(some-positive? (finish (do-terms 1 all.cofs)))
|
||||
((not (some negative? cofs)) ident)
|
||||
(else (list inv-op (finish (do-terms -1 all.cofs)))))))
|
||||
|
||||
(define (* . args)
|
||||
(cond
|
||||
((null? args) 1)
|
||||
;;This next line is commented out so ^ will collapse numerical expressions.
|
||||
;;((null? (cdr args)) (car args))
|
||||
(else
|
||||
(let ((in (cr*-args->fcts args)))
|
||||
(cond
|
||||
((zero? (car in)) 0)
|
||||
(else
|
||||
(if (null? (cdr in))
|
||||
(set-cdr! in (list (cons 1 1))))
|
||||
(let* ((num #f)
|
||||
(ans (cr-terms->form
|
||||
'* 1 '/ '^
|
||||
(apply
|
||||
(lambda (numeric red.cofs res.cofs)
|
||||
(set! num numeric)
|
||||
(append
|
||||
;;(list (cons (abs numeric) 1))
|
||||
red.cofs
|
||||
res.cofs))
|
||||
(cr1 '* number* '^ '/ (car in) (cdr in))))))
|
||||
(cond ((number0? (+ -1 num)) ans)
|
||||
((number? ans) (number* num ans))
|
||||
((number0? (+ 1 num))
|
||||
(if (and (list? ans) (= 2 (length ans)) (eq? '- (car ans)))
|
||||
(cadr ans)
|
||||
(list '- ans)))
|
||||
((not (pair? ans)) (list '* num ans))
|
||||
(else
|
||||
(case (car ans)
|
||||
((*) (append (list '* num) (cdr ans)))
|
||||
((+) (apply + (map (lambda (mon) (* num mon)) (cdr ans))))
|
||||
((-) (apply - (map (lambda (mon) (* num mon)) (cdr ans))))
|
||||
(else (list '* num ans))))))))))))
|
||||
|
||||
(define (+ . args)
|
||||
(cond ((null? args) 0)
|
||||
;;((null? (cdr args)) (car args))
|
||||
(else
|
||||
(let ((in (cr+-args->trms args)))
|
||||
(if (null? (cdr in))
|
||||
(car in)
|
||||
(cr-terms->form
|
||||
'+ 0 '- '*
|
||||
(apply (lambda (numeric red.cofs res.cofs)
|
||||
(append
|
||||
(list (if (and (number? numeric)
|
||||
(negative? numeric))
|
||||
(cons (abs numeric) -1)
|
||||
(cons numeric 1)))
|
||||
red.cofs
|
||||
res.cofs))
|
||||
(cr1 '+ number+ '* '- (car in) (cdr in)))))))))
|
||||
|
||||
(define (- arg1 . args)
|
||||
(if (null? args)
|
||||
(if (number? arg1) (number- arg1)
|
||||
(* -1 arg1) ;(list '- arg1)
|
||||
)
|
||||
(+ arg1 (* -1 (apply + args)))))
|
||||
|
||||
;;(print `(/ ,arg1 ,@args) '=> )
|
||||
(define (/ arg1 . args)
|
||||
(if (null? args)
|
||||
(^ arg1 -1)
|
||||
(* arg1 (^ (apply * args) -1))))
|
||||
|
||||
(define (^ arg1 arg2)
|
||||
(cond ((and (number? arg2) (integer? arg2))
|
||||
(* (list '^ arg1 arg2)))
|
||||
(else (list '^ arg1 arg2))))
|
||||
|
||||
;; TRY-EACH-PAIR-ONCE algorithm. I think this does the minimum
|
||||
;; number of rule lookups given no information about how to sort
|
||||
;; terms.
|
||||
|
||||
;; Pick equivalence classes one at a time and move them into the
|
||||
;; result set of equivalence classes by searching for rules to
|
||||
;; multiply an element of the chosen class by itself (if multiple) and
|
||||
;; the element of each class already in the result group. Each
|
||||
;; (multiplicative) term resulting from rule application would be put
|
||||
;; in the result class, if that class exists; or put in an argument
|
||||
;; class if not.
|
||||
|
||||
(define (cr1 op number-op hop inv-op numeric in)
|
||||
(define red.pows '())
|
||||
(define res.pows '())
|
||||
(define (cring:apply-rule->terms exp1 exp2) ;(display op)
|
||||
(let ((ans (cring:apply-rule op exp1 exp2)))
|
||||
(cond ((not ans) #f)
|
||||
((number? ans) (list ans))
|
||||
(else (list (cons ans 1))))))
|
||||
(define (cring:apply-inv-rule->terms exp1 exp2) ;(display inv-op)
|
||||
(let ((ans (cring:apply-rule inv-op exp1 exp2)))
|
||||
(cond ((not ans) #f)
|
||||
((number? ans) (list ans))
|
||||
(else (list (cons ans 1))))))
|
||||
(let loop.arg.pow.s ((arg (caar in)) (pow (cdar in)) (arg.pows (cdr in)))
|
||||
(define (arg-loop arg.pows)
|
||||
(cond ((not (null? arg.pows))
|
||||
(loop.arg.pow.s (caar arg.pows) (cdar arg.pows) (cdr arg.pows)))
|
||||
(else (list numeric red.pows res.pows)))) ; Actually return!
|
||||
(define (merge-res tmp.pows multiplicity)
|
||||
(cond ((null? tmp.pows))
|
||||
((number? (car tmp.pows))
|
||||
(do ((m (number+ -1 (abs multiplicity)) (number+ -1 m))
|
||||
(n numeric (number-op n (abs (car tmp.pows)))))
|
||||
((negative? m) (set! numeric n)))
|
||||
(merge-res (cdr tmp.pows) multiplicity))
|
||||
((or (assoc (car tmp.pows) res.pows)
|
||||
(assoc (car tmp.pows) arg.pows))
|
||||
=> (lambda (pair)
|
||||
(set-cdr! pair (number+
|
||||
pow (number-op multiplicity (cdar tmp.pows))))
|
||||
(merge-res (cdr tmp.pows) multiplicity)))
|
||||
((assoc (car tmp.pows) red.pows)
|
||||
=> (lambda (pair)
|
||||
(set! arg.pows
|
||||
(cons (cons (caar tmp.pows)
|
||||
(number+
|
||||
(cdr pair)
|
||||
(number* multiplicity (cdar tmp.pows))))
|
||||
arg.pows))
|
||||
(set-cdr! pair 0)
|
||||
(merge-res (cdr tmp.pows) multiplicity)))
|
||||
(else (set! arg.pows
|
||||
(cons (cons (caar tmp.pows)
|
||||
(number* multiplicity (cdar tmp.pows)))
|
||||
arg.pows))
|
||||
(merge-res (cdr tmp.pows) multiplicity))))
|
||||
(define (try-fct.pow fct.pow)
|
||||
;;(print 'try-fct.pow fct.pow op 'arg arg 'pow pow)
|
||||
(cond ((or (zero? (cdr fct.pow)) (number? (car fct.pow))) #f)
|
||||
((not (and (number? pow) (number? (cdr fct.pow))
|
||||
(integer? pow) ;(integer? (cdr fct.pow))
|
||||
))
|
||||
#f)
|
||||
;;((zero? pow) (slib:error "Don't try exp-0 terms") #f)
|
||||
;;((or (number? arg) (number? (car fct.pow)))
|
||||
;; (slib:error 'found-number arg fct.pow) #f)
|
||||
((and (positive? pow) (positive? (cdr fct.pow))
|
||||
(or (cring:apply-rule->terms arg (car fct.pow))
|
||||
(cring:apply-rule->terms (car fct.pow) arg)))
|
||||
=> (lambda (terms)
|
||||
;;(print op op terms)
|
||||
(let ((multiplicity (min pow (cdr fct.pow))))
|
||||
(set-cdr! fct.pow (number- (cdr fct.pow) multiplicity))
|
||||
(set! pow (number- pow multiplicity))
|
||||
(merge-res terms multiplicity))))
|
||||
((and (negative? pow) (negative? (cdr fct.pow))
|
||||
(or (cring:apply-rule->terms arg (car fct.pow))
|
||||
(cring:apply-rule->terms (car fct.pow) arg)))
|
||||
=> (lambda (terms)
|
||||
;;(print inv-op inv-op terms)
|
||||
(let ((multiplicity (max pow (cdr fct.pow))))
|
||||
(set-cdr! fct.pow (number+ (cdr fct.pow) multiplicity))
|
||||
(set! pow (number+ pow multiplicity))
|
||||
(merge-res terms multiplicity))))
|
||||
((and (positive? pow) (negative? (cdr fct.pow))
|
||||
(cring:apply-inv-rule->terms arg (car fct.pow)))
|
||||
=> (lambda (terms)
|
||||
;;(print op inv-op terms)
|
||||
(let ((multiplicity (min pow (number- (cdr fct.pow)))))
|
||||
(set-cdr! fct.pow (number+ (cdr fct.pow) multiplicity))
|
||||
(set! pow (number- pow multiplicity))
|
||||
(merge-res terms multiplicity))))
|
||||
((and (negative? pow) (positive? (cdr fct.pow))
|
||||
(cring:apply-inv-rule->terms (car fct.pow) arg))
|
||||
=> (lambda (terms)
|
||||
;;(print inv-op op terms)
|
||||
(let ((multiplicity (max (number- pow) (cdr fct.pow))))
|
||||
(set-cdr! fct.pow (number- (cdr fct.pow) multiplicity))
|
||||
(set! pow (number+ pow multiplicity))
|
||||
(merge-res terms multiplicity))))
|
||||
(else #f)))
|
||||
;;(print op numeric 'arg arg 'pow pow 'arg.pows arg.pows 'red.pows red.pows 'res.pows res.pows)
|
||||
;;(trace arg-loop cring:apply-rule->terms merge-res try-fct.pow) (set! *qp-width* 333)
|
||||
(cond ((or (zero? pow) (eqv? 1 arg)) ;(number? arg) arg seems to always be 1
|
||||
(arg-loop arg.pows))
|
||||
((assoc arg res.pows) => (lambda (pair)
|
||||
(set-cdr! pair (number+ pow (cdr pair)))
|
||||
(arg-loop arg.pows)))
|
||||
((and (> (abs pow) 1) (cring:apply-rule->terms arg arg))
|
||||
=> (lambda (terms)
|
||||
(merge-res terms (quotient pow 2))
|
||||
(if (odd? pow)
|
||||
(loop.arg.pow.s arg 1 arg.pows)
|
||||
(arg-loop arg.pows))))
|
||||
((or (some try-fct.pow res.pows) (some try-fct.pow arg.pows))
|
||||
(loop.arg.pow.s arg pow arg.pows))
|
||||
(else (set! res.pows (cons (cons arg pow) res.pows))
|
||||
(arg-loop arg.pows)))))
|
||||
|
||||
(define (cring:try-rule op sop1 sop2 exp1 exp2)
|
||||
(and *ruleset*
|
||||
(let ((rule ((car *ruleset*) op sop1 sop2)))
|
||||
(and rule (rule exp1 exp2)))))
|
||||
|
||||
(define (cring:apply-rule op exp1 exp2)
|
||||
(and (pair? exp1)
|
||||
(or (and (pair? exp2)
|
||||
(cring:try-rule op (car exp1) (car exp2) exp1 exp2))
|
||||
(cring:try-rule op (car exp1) 'identity exp1 exp2))))
|
||||
|
||||
;;(begin (trace cr-terms->form) (set! *qp-width* 333))
|
|
@ -1,463 +0,0 @@
|
|||
;"db2html.scm" Convert relational database to hyperlinked pages.
|
||||
; Copyright 1997, 1998, 2000, 2001 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'uri)
|
||||
(require 'html-form)
|
||||
(require 'net-clients)
|
||||
(require 'string-search)
|
||||
|
||||
;;@code{(require 'db->html)}
|
||||
|
||||
;;@body
|
||||
(define (html:table options . rows)
|
||||
(apply string-append
|
||||
(sprintf #f "<TABLE %s>\\n" (or options ""))
|
||||
(append rows (list (sprintf #f "</TABLE>\\n")))))
|
||||
|
||||
;;@args caption align
|
||||
;;@args caption
|
||||
;;@2 can be @samp{top} or @samp{bottom}.
|
||||
(define (html:caption caption . align)
|
||||
(if (null? align)
|
||||
(sprintf #f " <CAPTION>%s</CAPTION>\\n"
|
||||
(html:plain caption))
|
||||
(sprintf #f " <CAPTION ALIGN=%s>%s</CAPTION>\\n"
|
||||
(car align)
|
||||
(html:plain caption))))
|
||||
|
||||
;;@body Outputs a heading row for the currently-started table.
|
||||
(define (html:heading columns)
|
||||
(sprintf #f " <TR VALIGN=\"TOP\">\\n%s </TR>\\n"
|
||||
(apply string-append
|
||||
(map (lambda (datum)
|
||||
(sprintf #f " <TH>%s</TH>\\n" (or datum "")))
|
||||
columns))))
|
||||
|
||||
;;@body Outputs a heading row with column-names @1 linked to URIs @2.
|
||||
(define (html:href-heading columns uris)
|
||||
(html:heading
|
||||
(map (lambda (column uri)
|
||||
(if uri
|
||||
(html:link uri column)
|
||||
column))
|
||||
columns uris)))
|
||||
|
||||
(define (row->anchor pkl row)
|
||||
(sprintf #f "<A NAME=\"%s\"></A>" (uri:make-path (butnthcdr pkl row))))
|
||||
|
||||
;;@args k foreigns
|
||||
;;
|
||||
;;The positive integer @1 is the primary-key-limit (number of
|
||||
;;primary-keys) of the table. @2 is a list of the filenames of
|
||||
;;foreign-key field pages and #f for non foreign-key fields.
|
||||
;;
|
||||
;;@0 returns a procedure taking a row for its single argument. This
|
||||
;;returned procedure returns the html string for that table row.
|
||||
(define (html:linked-row-converter pkl foreigns)
|
||||
(define idxs (do ((idx (length foreigns) (+ -1 idx))
|
||||
(nats '() (cons idx nats)))
|
||||
((not (positive? idx)) nats)))
|
||||
(require 'pretty-print)
|
||||
(lambda (row)
|
||||
(define (present datum)
|
||||
(if (or (string? datum) (symbol? datum))
|
||||
(html:plain datum)
|
||||
(let* ((str (pretty-print->string datum))
|
||||
(len (+ -1 (string-length str))))
|
||||
(cond ((eqv? (string-index str #\newline) len)
|
||||
(string-append "<TT>" (substring str 0 len) "</TT>"))
|
||||
(else (html:pre str))))))
|
||||
(sprintf #f " <TR VALIGN=TOP>\\n%s </TR>\\n"
|
||||
(apply string-append
|
||||
(map (lambda (idx datum foreign)
|
||||
(sprintf
|
||||
#f " <TD>%s%s</TD>\\n"
|
||||
(if (eqv? 1 idx) (row->anchor pkl row) "")
|
||||
(cond ((or (not datum) (null? datum)) "")
|
||||
((not foreign) (present datum))
|
||||
((equal? "catalog-data.html" foreign)
|
||||
(html:link (make-uri
|
||||
(table-name->filename datum)
|
||||
#f #f)
|
||||
(present datum)))
|
||||
(else (html:link (make-uri foreign #f datum)
|
||||
(present datum))))))
|
||||
idxs row foreigns)))))
|
||||
|
||||
;;@body
|
||||
;;Returns the symbol @1 converted to a filename.
|
||||
(define (table-name->filename table-name)
|
||||
(and table-name (string-append
|
||||
(string-subst (symbol->string table-name) "*" "" ":" "_")
|
||||
".html")))
|
||||
|
||||
(define (table-name->column-table-name db table-name)
|
||||
((((db 'open-table) '*catalog-data* #f) 'get 'coltab-name)
|
||||
table-name))
|
||||
|
||||
;;@args caption db table-name match-key1 @dots{}
|
||||
;;Returns HTML string for @2 table @3. Every foreign-key value is
|
||||
;;linked to the page (of the table) defining that key.
|
||||
;;
|
||||
;;The optional @4 @dots{} arguments restrict actions to a subset of
|
||||
;;the table. @xref{Table Operations, match-key}.
|
||||
(define (table->linked-html caption db table-name . args)
|
||||
(let* ((table ((db 'open-table) table-name #f))
|
||||
(foreigns (table 'column-foreigns))
|
||||
(tags (map table-name->filename foreigns))
|
||||
(names (table 'column-names))
|
||||
(primlim (table 'primary-limit)))
|
||||
(apply html:table "CELLSPACING=0 BORDER=1"
|
||||
(html:caption caption 'BOTTOM)
|
||||
(html:href-heading
|
||||
names
|
||||
(append (make-list primlim
|
||||
(table-name->filename
|
||||
(table-name->column-table-name db table-name)))
|
||||
(make-list (- (length names) primlim) #f)))
|
||||
(html:heading (table 'column-domains))
|
||||
(html:href-heading foreigns tags)
|
||||
(html:heading (table 'column-types))
|
||||
(map (html:linked-row-converter primlim tags)
|
||||
(apply (table 'row:retrieve*) args)))))
|
||||
|
||||
;;@body
|
||||
;;Returns a complete HTML page. The string @3 names the page which
|
||||
;;refers to this one.
|
||||
;;
|
||||
;;The optional @4 @dots{} arguments restrict actions to a subset of
|
||||
;;the table. @xref{Table Operations, match-key}.
|
||||
(define (table->linked-page db table-name index-filename . args)
|
||||
(string-append
|
||||
(if index-filename
|
||||
(html:head table-name
|
||||
(html:link (make-uri index-filename #f table-name)
|
||||
(html:plain table-name)))
|
||||
(html:head table-name))
|
||||
(html:body (apply table->linked-html table-name db table-name args))))
|
||||
|
||||
(define (html:catalog-row-converter row foreigns)
|
||||
(sprintf #f " <TR VALIGN=TOP>\\n%s </TR>\\n"
|
||||
(apply string-append
|
||||
(map (lambda (datum foreign)
|
||||
(sprintf #f " <TD>%s%s</TD>\\n"
|
||||
(html:anchor (sprintf #f "%s" datum))
|
||||
(html:link (make-uri foreign #f #f) datum)))
|
||||
row foreigns))))
|
||||
|
||||
;;@body
|
||||
;;Returns HTML string for the catalog table of @1.
|
||||
(define (catalog->html db caption . args)
|
||||
(apply html:table "BORDER=1"
|
||||
(html:caption caption 'BOTTOM)
|
||||
(html:heading '(table columns))
|
||||
(map (lambda (row)
|
||||
(cond ((and (eq? '*columns* (caddr row))
|
||||
(not (eq? '*columns* (car row))))
|
||||
"")
|
||||
(else (html:catalog-row-converter
|
||||
(list (car row) (caddr row))
|
||||
(list (table-name->filename (car row))
|
||||
(table-name->filename (caddr row)))))))
|
||||
(apply (((db 'open-table) '*catalog-data* #f) 'row:retrieve*)
|
||||
args))))
|
||||
|
||||
;;Returns complete HTML page (string) for the catalog table of @1.
|
||||
(define (catalog->page db caption . args)
|
||||
(string-append (html:head caption)
|
||||
(html:body (apply catalog->html db caption args))))
|
||||
|
||||
;;@subsection HTML editing tables
|
||||
|
||||
;;@noindent A client can modify one row of an editable table at a time.
|
||||
;;For any change submitted, these routines check if that row has been
|
||||
;;modified during the time the user has been editing the form. If so,
|
||||
;;an error page results.
|
||||
;;
|
||||
;;@noindent The behavior of edited rows is:
|
||||
;;
|
||||
;;@itemize @bullet
|
||||
;;@item
|
||||
;;If no fields are changed, then no change is made to the table.
|
||||
;;@item
|
||||
;;If the primary keys equal null-keys (parameter defaults), and no other
|
||||
;;user has modified that row, then that row is deleted.
|
||||
;;@item
|
||||
;;If only primary keys are changed, there are non-key fields, and no
|
||||
;;row with the new keys is in the table, then the old row is
|
||||
;;deleted and one with the new keys is inserted.
|
||||
;;@item
|
||||
;;If only non-key fields are changed, and that row has not been
|
||||
;;modified by another user, then the row is changed to reflect the
|
||||
;;fields.
|
||||
;;@item
|
||||
;;If both keys and non-key fields are changed, and no row with the
|
||||
;;new keys is in the table, then a row is created with the new
|
||||
;;keys and fields.
|
||||
;;@item
|
||||
;;If fields are changed, all fields are primary keys, and no row with
|
||||
;;the new keys is in the table, then a row is created with the new
|
||||
;;keys.
|
||||
;;@end itemize
|
||||
;;
|
||||
;;@noindent After any change to the table, a @code{sync-database} of the
|
||||
;;database is performed.
|
||||
|
||||
;;@args table-name null-keys update delete retrieve
|
||||
;;@args table-name null-keys update delete
|
||||
;;@args table-name null-keys update
|
||||
;;@args table-name null-keys
|
||||
;;
|
||||
;;Returns procedure (of @var{db}) which returns procedure to modify row
|
||||
;;of @1. @2 is the list of @dfn{null} keys which indicate that the row
|
||||
;;is to be deleted. Optional arguments @3, @4, and @5 default to the
|
||||
;;@code{row:update}, @code{row:delete}, and @code{row:retrieve} of @1 in
|
||||
;;@var{db}.
|
||||
(define (command:modify-table table-name null-keys . args)
|
||||
(define argc (length args))
|
||||
(lambda (rdb)
|
||||
(define table ((rdb 'open-table) table-name #t))
|
||||
(let ((table:update (or (and (> argc 0) (car args)) (table 'row:update)))
|
||||
(table:delete (or (and (> argc 1) (cadr args)) (table 'row:delete)))
|
||||
(table:retrieve (or (and (> argc 2) (caddr args)) (table 'row:retrieve)))
|
||||
(pkl (length null-keys)))
|
||||
(define ptypes (butnthcdr pkl (table 'column-types)))
|
||||
(if (> argc 4) (slib:error 'command:modify-table 'too-many-args
|
||||
table-name null-keys args))
|
||||
(lambda (*keys* *row-hash* . new-row)
|
||||
(let* ((new-pkeys (butnthcdr pkl new-row))
|
||||
(pkeys (uri:path->keys (uri:split-fields *keys* #\/) ptypes))
|
||||
(row (apply table:retrieve pkeys))
|
||||
(same-nonkeys? (equal? (nthcdr pkl new-row) (nthcdr pkl row))))
|
||||
(cond ((equal? pkeys new-pkeys) ;did not change keys
|
||||
(cond ((not row) '("Row deleted by other user"))
|
||||
((equal? (crc:hash-obj row) *row-hash*)
|
||||
(table:update new-row)
|
||||
((rdb 'sync-database)) #t)
|
||||
(else '("Row changed by other user"))))
|
||||
((equal? null-keys new-pkeys) ;blanked keys
|
||||
(cond ((not row) #t)
|
||||
((equal? (crc:hash-obj row) *row-hash*)
|
||||
;;(slib:warn (sprintf #f "Removing key: %#a => %#a" new-pkeys ))
|
||||
(apply table:delete pkeys)
|
||||
((rdb 'sync-database)) #t)
|
||||
(else '("Row changed by other user"))))
|
||||
(else ;changed keys
|
||||
(set! row (apply table:retrieve new-pkeys))
|
||||
(cond (row (list "Row already exists"
|
||||
(sprintf #f "%#a" row)))
|
||||
(else (table:update new-row)
|
||||
(if (and same-nonkeys?
|
||||
(not (null? (nthcdr pkl new-row))))
|
||||
(apply table:delete pkeys))
|
||||
((rdb 'sync-database)) #t)))))))))
|
||||
|
||||
;;@body Given @2 in @1, creates parameter and @code{*command*} tables
|
||||
;;for editing one row of @2 at a time. @0 returns a procedure taking a
|
||||
;;row argument which returns the HTML string for editing that row.
|
||||
;;
|
||||
;;Optional @3 are expressions (lists) added to the call to
|
||||
;;@code{command:modify-table}.
|
||||
;;
|
||||
;;The domain name of a column determines the expected arity of the data
|
||||
;;stored in that column. Domain names ending in:
|
||||
;;
|
||||
;;@table @samp
|
||||
;;@item *
|
||||
;;have arity @samp{nary};
|
||||
;;@item +
|
||||
;;have arity @samp{nary1}.
|
||||
;;@end table
|
||||
(define (command:make-editable-table rdb table-name . args)
|
||||
(define table ((rdb 'open-table) table-name #t))
|
||||
(let ((pkl (table 'primary-limit))
|
||||
(columns (table 'column-names))
|
||||
(domains (table 'column-domains))
|
||||
(types (table 'column-types))
|
||||
(idxs (do ((idx (length (table 'column-names)) (+ -1 idx))
|
||||
(nats '() (cons (+ 2 idx) nats)))
|
||||
((not (positive? idx)) nats)))
|
||||
(ftn (((rdb 'open-table) '*domains-data* #f) 'get 'foreign-table)))
|
||||
(define field-specs
|
||||
(map (lambda (idx column domain type)
|
||||
(let* ((dstr (symbol->string domain))
|
||||
(len (+ -1 (string-length dstr))))
|
||||
(define arity
|
||||
(case (string-ref dstr len)
|
||||
((#\*) 'nary)
|
||||
((#\+) 'nary1)
|
||||
(else 'single)))
|
||||
(case (string-ref dstr len)
|
||||
((#\* #\+)
|
||||
(set! type (string->symbol (substring dstr 0 len)))
|
||||
(set! domain type)))
|
||||
`(,idx ,column ,arity ,domain
|
||||
,(make-defaulter arity type) #f "")))
|
||||
idxs columns domains types))
|
||||
(define foreign-choice-lists
|
||||
(map (lambda (domain-name)
|
||||
(define tab-name (ftn domain-name))
|
||||
(if tab-name (get-foreign-choices (rdb-open tab-name #f)) '()))
|
||||
domains))
|
||||
(define-tables rdb
|
||||
`(,(symbol-append table-name '- 'params)
|
||||
*parameter-columns* *parameter-columns*
|
||||
((1 *keys* single string #f #f "")
|
||||
(2 *row-hash* single string #f #f "")
|
||||
,@field-specs))
|
||||
`(,(symbol-append table-name '- 'pname)
|
||||
((name string))
|
||||
((parameter-index uint)) ;should be address-params
|
||||
(("*keys*" 1)
|
||||
("*row-hash*" 2)
|
||||
,@(map (lambda (idx column) (list (symbol->string column) idx))
|
||||
idxs columns)))
|
||||
`(*commands*
|
||||
desc:*commands* desc:*commands*
|
||||
((,(symbol-append 'edit '- table-name)
|
||||
,(symbol-append table-name '- 'params)
|
||||
,(symbol-append table-name '- 'pname)
|
||||
(command:modify-table ',table-name
|
||||
',(map (lambda (fs)
|
||||
(caadr (caddar (cddddr fs))))
|
||||
(butnthcdr pkl field-specs))
|
||||
,@args)
|
||||
,(string-append "Modify " (symbol->string table-name))))))
|
||||
(let ((arities (map caddr field-specs)))
|
||||
(lambda (row)
|
||||
(define elements
|
||||
(map form:element
|
||||
columns
|
||||
arities
|
||||
(map (lambda (fld arity) (case arity
|
||||
((nary nary1) fld)
|
||||
(else (list fld))))
|
||||
row arities)
|
||||
foreign-choice-lists))
|
||||
(sprintf #f " <TR>\\n <TD>%s</TD>%s\\n </TR>\\n"
|
||||
(string-append
|
||||
(html:hidden '*row-hash* (crc:hash-obj row))
|
||||
(html:hidden '*keys* (uri:make-path (butnthcdr pkl row)))
|
||||
;; (html:hidden '*suggest* '<>)
|
||||
(car elements)
|
||||
(form:submit '<> (symbol-append 'edit '- table-name))
|
||||
;; (form:image "Modify Row" "/icons/bang.png")
|
||||
)
|
||||
(apply string-append
|
||||
(map (lambda (elt) (sprintf #f " <TD>%s</TD>\\n" elt))
|
||||
(cdr elements))))))))
|
||||
|
||||
;;@args k names edit-point edit-converter
|
||||
;;
|
||||
;;The positive integer @1 is the primary-key-limit (number of
|
||||
;;primary-keys) of the table. @2 is a list of the field-names. @3 is
|
||||
;;the list of primary-keys denoting the row to edit (or #f). @4 is the
|
||||
;;procedure called with @1, @2, and the row to edit.
|
||||
;;
|
||||
;;@0 returns a procedure taking a row for its single argument. This
|
||||
;;returned procedure returns the html string for that table row.
|
||||
;;
|
||||
;;Each HTML table constructed using @0 has first @1 fields (typically
|
||||
;;the primary key fields) of each row linked to a text encoding of these
|
||||
;;fields (the result of calling @code{row->anchor}). The page so
|
||||
;;referenced typically allows the user to edit fields of that row.
|
||||
(define (html:editable-row-converter pkl names edit-point edit-converter)
|
||||
(require 'pretty-print)
|
||||
(let ((idxs (do ((idx (length names) (+ -1 idx))
|
||||
(nats '() (cons idx nats)))
|
||||
((not (positive? idx)) nats)))
|
||||
(datum->html
|
||||
(lambda (datum)
|
||||
(if (or (string? datum) (symbol? datum))
|
||||
(html:plain datum)
|
||||
(let* ((str (pretty-print->string datum))
|
||||
(len (+ -1 (string-length str))))
|
||||
(cond ((eqv? (string-index str #\newline) len)
|
||||
(string-append "<B>" (substring str 0 len) "</B>"))
|
||||
(else (html:pre str))))))))
|
||||
(lambda (row)
|
||||
(string-append
|
||||
(sprintf #f " <TR VALIGN=TOP>\\n%s </TR>\\n"
|
||||
(apply string-append
|
||||
(map (lambda (idx datum foreign)
|
||||
(sprintf
|
||||
#f " <TD>%s%s</TD>\\n"
|
||||
(if (eqv? 1 idx) (row->anchor pkl row) "")
|
||||
(cond ((or (not datum) (null? datum)) "")
|
||||
((<= idx pkl)
|
||||
(let ((keystr (uri:make-path
|
||||
(butnthcdr pkl row))))
|
||||
(sprintf #f "<A HREF=\"%s#%s\">%s</A>"
|
||||
keystr keystr
|
||||
(datum->html datum))))
|
||||
(else (datum->html datum)))))
|
||||
idxs row names)))
|
||||
(if (and edit-point edit-converter
|
||||
(equal? (butnthcdr pkl edit-point) (butnthcdr pkl row)))
|
||||
(edit-converter row)
|
||||
"")))))
|
||||
|
||||
;;@subsection HTML databases
|
||||
|
||||
;;@body @1 must be a relational database. @2 must be #f or a
|
||||
;;non-empty string naming an existing sub-directory of the current
|
||||
;;directory.
|
||||
;;
|
||||
;;@0 creates an html page for each table in the database @1 in the
|
||||
;;sub-directory named @2, or the current directory if @2 is #f. The
|
||||
;;top level page with the catalog of tables (captioned @4) is written
|
||||
;;to a file named @3.
|
||||
(define (db->html-files db dir index-filename caption)
|
||||
(call-with-output-file (in-vicinity (if dir (sub-vicinity "" dir) "")
|
||||
index-filename)
|
||||
(lambda (port)
|
||||
(display (catalog->page db caption) port)))
|
||||
((((db 'open-table) '*catalog-data* #f) 'for-each-row)
|
||||
(lambda (row)
|
||||
(call-with-output-file
|
||||
(in-vicinity (sub-vicinity "" dir) (table-name->filename (car row)))
|
||||
(lambda (port)
|
||||
(display (table->linked-page db (car row) index-filename) port))))))
|
||||
|
||||
;;@args db dir index-filename
|
||||
;;@args db dir
|
||||
;;@1 must be a relational database. @2 must be a non-empty
|
||||
;;string naming an existing sub-directory of the current directory or
|
||||
;;one to be created. The optional string @3 names the filename of the
|
||||
;;top page, which defaults to @file{index.html}.
|
||||
;;
|
||||
;;@0 creates sub-directory @2 if neccessary, and calls
|
||||
;;@code{(db->html-files @1 @2 @3 @2)}. The @samp{file:} URI of @3 is
|
||||
;;returned.
|
||||
(define (db->html-directory db dir . index-filename)
|
||||
(set! index-filename (if (null? index-filename)
|
||||
"index.html"
|
||||
(car index-filename)))
|
||||
(if (symbol? dir) (set! dir (symbol->string dir)))
|
||||
(if (not (file-exists? dir)) (make-directory dir))
|
||||
(db->html-files db dir index-filename dir)
|
||||
(path->uri (in-vicinity (sub-vicinity "" dir) index-filename)))
|
||||
|
||||
;;@args db dir index-filename
|
||||
;;@args db dir
|
||||
;;@0 is just like @code{db->html-directory}, but calls
|
||||
;;@code{browse-url-netscape} with the uri for the top page after the
|
||||
;;pages are created.
|
||||
(define (db->netscape . args)
|
||||
(browse-url-netscape (apply db->html-directory args)))
|
|
@ -1,185 +0,0 @@
|
|||
@code{(require 'db->html)}
|
||||
|
||||
|
||||
@defun html:table options row @dots{}
|
||||
|
||||
@end defun
|
||||
|
||||
@defun html:caption caption align
|
||||
|
||||
|
||||
@defunx html:caption caption
|
||||
@var{align} can be @samp{top} or @samp{bottom}.
|
||||
@end defun
|
||||
|
||||
@defun html:heading columns
|
||||
Outputs a heading row for the currently-started table.
|
||||
@end defun
|
||||
|
||||
@defun html:href-heading columns uris
|
||||
Outputs a heading row with column-names @var{columns} linked to URIs @var{uris}.
|
||||
@end defun
|
||||
|
||||
@defun html:linked-row-converter k foreigns
|
||||
|
||||
|
||||
The positive integer @var{k} is the primary-key-limit (number of
|
||||
primary-keys) of the table. @var{foreigns} is a list of the filenames of
|
||||
foreign-key field pages and #f for non foreign-key fields.
|
||||
|
||||
@code{html:linked-row-converter} returns a procedure taking a row for its single argument. This
|
||||
returned procedure returns the html string for that table row.
|
||||
@end defun
|
||||
|
||||
@defun table-name->filename table-name
|
||||
|
||||
Returns the symbol @var{table-name} converted to a filename.
|
||||
@end defun
|
||||
|
||||
@defun table->linked-html caption db table-name match-key1 @dots{}
|
||||
|
||||
Returns HTML string for @var{db} table @var{table-name}. Every foreign-key value is
|
||||
linked to the page (of the table) defining that key.
|
||||
|
||||
The optional @var{match-key1} @dots{} arguments restrict actions to a subset of
|
||||
the table. @xref{Table Operations, match-key}.
|
||||
@end defun
|
||||
|
||||
@defun table->linked-page db table-name index-filename arg @dots{}
|
||||
|
||||
Returns a complete HTML page. The string @var{index-filename} names the page which
|
||||
refers to this one.
|
||||
|
||||
The optional @var{args} @dots{} arguments restrict actions to a subset of
|
||||
the table. @xref{Table Operations, match-key}.
|
||||
@end defun
|
||||
|
||||
@defun catalog->html db caption arg @dots{}
|
||||
|
||||
Returns HTML string for the catalog table of @var{db}.
|
||||
@end defun
|
||||
@subsection HTML editing tables
|
||||
|
||||
@noindent A client can modify one row of an editable table at a time.
|
||||
For any change submitted, these routines check if that row has been
|
||||
modified during the time the user has been editing the form. If so,
|
||||
an error page results.
|
||||
|
||||
@noindent The behavior of edited rows is:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
If no fields are changed, then no change is made to the table.
|
||||
@item
|
||||
If the primary keys equal null-keys (parameter defaults), and no other
|
||||
user has modified that row, then that row is deleted.
|
||||
@item
|
||||
If only primary keys are changed, there are non-key fields, and no
|
||||
row with the new keys is in the table, then the old row is
|
||||
deleted and one with the new keys is inserted.
|
||||
@item
|
||||
If only non-key fields are changed, and that row has not been
|
||||
modified by another user, then the row is changed to reflect the
|
||||
fields.
|
||||
@item
|
||||
If both keys and non-key fields are changed, and no row with the
|
||||
new keys is in the table, then a row is created with the new
|
||||
keys and fields.
|
||||
@item
|
||||
If fields are changed, all fields are primary keys, and no row with
|
||||
the new keys is in the table, then a row is created with the new
|
||||
keys.
|
||||
@end itemize
|
||||
|
||||
@noindent After any change to the table, a @code{sync-database} of the
|
||||
database is performed.
|
||||
|
||||
|
||||
@defun command:modify-table table-name null-keys update delete retrieve
|
||||
|
||||
|
||||
@defunx command:modify-table table-name null-keys update delete
|
||||
|
||||
@defunx command:modify-table table-name null-keys update
|
||||
|
||||
@defunx command:modify-table table-name null-keys
|
||||
|
||||
Returns procedure (of @var{db}) which returns procedure to modify row
|
||||
of @var{table-name}. @var{null-keys} is the list of @dfn{null} keys which indicate that the row
|
||||
@cindex null
|
||||
is to be deleted. Optional arguments @var{update}, @var{delete}, and @var{retrieve} default to the
|
||||
@code{row:update}, @code{row:delete}, and @code{row:retrieve} of @var{table-name} in
|
||||
@var{db}.
|
||||
@end defun
|
||||
|
||||
@defun command:make-editable-table rdb table-name arg @dots{}
|
||||
Given @var{table-name} in @var{rdb}, creates parameter and @code{*command*} tables
|
||||
for editing one row of @var{table-name} at a time. @code{command:make-editable-table} returns a procedure taking a
|
||||
row argument which returns the HTML string for editing that row.
|
||||
|
||||
Optional @var{args} are expressions (lists) added to the call to
|
||||
@code{command:modify-table}.
|
||||
|
||||
The domain name of a column determines the expected arity of the data
|
||||
stored in that column. Domain names ending in:
|
||||
|
||||
@table @samp
|
||||
@item *
|
||||
have arity @samp{nary};
|
||||
@item +
|
||||
have arity @samp{nary1}.
|
||||
@end table
|
||||
@end defun
|
||||
|
||||
@defun html:editable-row-converter k names edit-point edit-converter
|
||||
|
||||
|
||||
The positive integer @var{k} is the primary-key-limit (number of
|
||||
primary-keys) of the table. @var{names} is a list of the field-names. @var{edit-point} is
|
||||
the list of primary-keys denoting the row to edit (or #f). @var{edit-converter} is the
|
||||
procedure called with @var{k}, @var{names}, and the row to edit.
|
||||
|
||||
@code{html:editable-row-converter} returns a procedure taking a row for its single argument. This
|
||||
returned procedure returns the html string for that table row.
|
||||
|
||||
Each HTML table constructed using @code{html:editable-row-converter} has first @var{k} fields (typically
|
||||
the primary key fields) of each row linked to a text encoding of these
|
||||
fields (the result of calling @code{row->anchor}). The page so
|
||||
referenced typically allows the user to edit fields of that row.
|
||||
@end defun
|
||||
@subsection HTML databases
|
||||
|
||||
|
||||
@defun db->html-files db dir index-filename caption
|
||||
@var{db} must be a relational database. @var{dir} must be #f or a
|
||||
non-empty string naming an existing sub-directory of the current
|
||||
directory.
|
||||
|
||||
@code{db->html-files} creates an html page for each table in the database @var{db} in the
|
||||
sub-directory named @var{dir}, or the current directory if @var{dir} is #f. The
|
||||
top level page with the catalog of tables (captioned @var{caption}) is written
|
||||
to a file named @var{index-filename}.
|
||||
@end defun
|
||||
|
||||
@defun db->html-directory db dir index-filename
|
||||
|
||||
|
||||
@defunx db->html-directory db dir
|
||||
@var{db} must be a relational database. @var{dir} must be a non-empty
|
||||
string naming an existing sub-directory of the current directory or
|
||||
one to be created. The optional string @var{index-filename} names the filename of the
|
||||
top page, which defaults to @file{index.html}.
|
||||
|
||||
@code{db->html-directory} creates sub-directory @var{dir} if neccessary, and calls
|
||||
@code{(db->html-files @var{db} @var{dir} @var{index-filename} @var{dir})}. The @samp{file:} URI of @var{index-filename} is
|
||||
returned.
|
||||
@end defun
|
||||
|
||||
@defun db->netscape db dir index-filename
|
||||
|
||||
|
||||
@defunx db->netscape db dir
|
||||
@code{db->netscape} is just like @code{db->html-directory}, but calls
|
||||
@code{browse-url-netscape} with the uri for the top page after the
|
||||
pages are created.
|
||||
@end defun
|
|
@ -1,92 +0,0 @@
|
|||
;;; "dbrowse.scm" relational-database-browser
|
||||
; Copyright 1996, 1997, 1998 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'database-utilities)
|
||||
(require 'printf)
|
||||
|
||||
(define browse:db #f)
|
||||
|
||||
(define (browse . args)
|
||||
(define table-name #f)
|
||||
(cond ((null? args))
|
||||
((procedure? (car args))
|
||||
(set! browse:db (car args))
|
||||
(set! args (cdr args)))
|
||||
((string? (car args))
|
||||
(set! browse:db (open-database (car args)))
|
||||
(set! args (cdr args))))
|
||||
(cond ((null? args))
|
||||
(else (set! table-name (car args))))
|
||||
(let* ((open-table (browse:db 'open-table))
|
||||
(catalog (and open-table (open-table '*catalog-data* #f))))
|
||||
(cond ((not catalog)
|
||||
(slib:error 'browse "could not open catalog"))
|
||||
((not table-name)
|
||||
(browse:display-dir '*catalog-data* catalog))
|
||||
(else
|
||||
(let ((table (open-table table-name #f)))
|
||||
(cond (table (browse:display-table table-name table)
|
||||
(table 'close-table))
|
||||
(else (slib:error 'browse "could not open table"
|
||||
table-name))))))))
|
||||
|
||||
(define (browse:display-dir table-name table)
|
||||
(printf "%s Tables:\\n" table-name)
|
||||
((table 'for-each-row)
|
||||
(lambda (row) (printf "\\t%s\\n" (car row)))))
|
||||
|
||||
(define (browse:display-table table-name table)
|
||||
(let* ((width 18)
|
||||
(dw (string-append "%-" (number->string width)))
|
||||
(dwp (string-append "%-" (number->string width) "."
|
||||
(number->string (+ -1 width))))
|
||||
(dwp-string (string-append dwp "s"))
|
||||
(dwp-any (string-append dwp "a"))
|
||||
(dw-integer (string-append dw "d"))
|
||||
(underline (string-append (make-string (+ -1 width) #\=) " "))
|
||||
(form ""))
|
||||
(printf "Table: %s\\n" table-name)
|
||||
(for-each (lambda (name) (printf dwp-string name))
|
||||
(table 'column-names))
|
||||
(newline)
|
||||
(for-each (lambda (foreign) (printf dwp-any foreign))
|
||||
(table 'column-foreigns))
|
||||
(newline)
|
||||
(for-each (lambda (domain) (printf dwp-string domain))
|
||||
(table 'column-domains))
|
||||
(newline)
|
||||
(for-each (lambda (type)
|
||||
(case type
|
||||
((integer number uint base-id)
|
||||
(set! form (string-append form dw-integer)))
|
||||
((boolean domain expression atom)
|
||||
(set! form (string-append form dwp-any)))
|
||||
((string symbol)
|
||||
(set! form (string-append form dwp-string)))
|
||||
(else (slib:error 'browse:display-table "unknown type" type)))
|
||||
(printf dwp-string type))
|
||||
(table 'column-types))
|
||||
(newline)
|
||||
(set! form (string-append form "\\n"))
|
||||
(for-each (lambda (domain) (printf underline))
|
||||
(table 'column-domains))
|
||||
(newline)
|
||||
((table 'for-each-row)
|
||||
(lambda (row)
|
||||
(apply printf form row)))))
|
|
@ -1,313 +0,0 @@
|
|||
;;; "dbutil.scm" relational-database-utilities
|
||||
; Copyright 1994, 1995, 1997, 2000, 2001 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'relational-database)
|
||||
(require 'common-list-functions)
|
||||
|
||||
(define (db:base-type path)
|
||||
'alist-table) ; currently the only one.
|
||||
|
||||
(define (dbutil:wrap-command-interface rdb)
|
||||
(and rdb
|
||||
(let* ((rdms:commands ((rdb 'open-table) '*commands* #f))
|
||||
(command:get
|
||||
(and rdms:commands (rdms:commands 'get 'procedure))))
|
||||
(and command:get
|
||||
(letrec ((wdb (lambda (command)
|
||||
(let ((com (command:get command)))
|
||||
(cond (com ((slib:eval com) wdb))
|
||||
(else (rdb command)))))))
|
||||
(let ((init (wdb '*initialize*)))
|
||||
(if (procedure? init) init wdb)))))))
|
||||
|
||||
(define (dbutil:open-database! path . arg)
|
||||
(let ((type (if (null? arg) (db:base-type path) (car arg))))
|
||||
(require type)
|
||||
(dbutil:wrap-command-interface
|
||||
(((make-relational-system (slib:eval type)) 'open-database)
|
||||
path #t))))
|
||||
|
||||
(define (dbutil:open-database path . arg)
|
||||
(let ((type (if (null? arg) (db:base-type path) (car arg))))
|
||||
(require type)
|
||||
(dbutil:wrap-command-interface
|
||||
(((make-relational-system (slib:eval type)) 'open-database)
|
||||
path #f))))
|
||||
|
||||
(define (dbutil:check-domain rdb)
|
||||
(let* ((ro:domains ((rdb 'open-table) '*domains-data* #f))
|
||||
(ro:get-dir (ro:domains 'get 'domain-integrity-rule))
|
||||
(ro:for-tab (ro:domains 'get 'foreign-table)))
|
||||
(lambda (domain)
|
||||
(let ((fkname (ro:for-tab domain))
|
||||
(dir (slib:eval (ro:get-dir domain))))
|
||||
(if fkname (let* ((fktab ((rdb 'open-table) fkname #f))
|
||||
(p? (fktab 'get 1)))
|
||||
(if dir (lambda (e) (and (dir e) (p? e))) p?))
|
||||
dir)))))
|
||||
|
||||
(define (dbutil:create-database path type)
|
||||
(require type)
|
||||
(let ((rdb (((make-relational-system (slib:eval type)) 'create-database)
|
||||
path)))
|
||||
(dbutil:define-tables
|
||||
rdb
|
||||
'(type
|
||||
((name symbol))
|
||||
()
|
||||
((atom)
|
||||
(symbol)
|
||||
(string)
|
||||
(number)
|
||||
(money)
|
||||
(date-time)
|
||||
(boolean)
|
||||
(foreign-key)
|
||||
(expression)
|
||||
(virtual)))
|
||||
'(parameter-arity
|
||||
((name symbol))
|
||||
((predicate? expression)
|
||||
(procedure expression))
|
||||
((single (lambda (a) (and (pair? a) (null? (cdr a)))) car)
|
||||
(optional
|
||||
(lambda (lambda (a) (or (null? a) (and (pair? a) (null? (cdr a))))))
|
||||
identity)
|
||||
(boolean
|
||||
(lambda (a) (or (null? a)
|
||||
(and (pair? a) (null? (cdr a)) (boolean? (car a)))))
|
||||
(lambda (a) (if (null? a) #f (car a))))
|
||||
(nary (lambda (a) #t) identity)
|
||||
(nary1 (lambda (a) (not (null? a))) identity))))
|
||||
(for-each (((rdb 'open-table) '*domains-data* #t) 'row:insert)
|
||||
'((parameter-list *catalog-data* #f symbol 1)
|
||||
(parameter-name-translation *catalog-data* #f symbol 1)
|
||||
(parameter-arity parameter-arity #f symbol 1)
|
||||
(table *catalog-data* #f atom 1)))
|
||||
(dbutil:define-tables
|
||||
rdb
|
||||
'(*parameter-columns*
|
||||
*columns*
|
||||
*columns*
|
||||
((1 #t index #f uint)
|
||||
(2 #f name #f symbol)
|
||||
(3 #f arity #f parameter-arity)
|
||||
(4 #f domain #f domain)
|
||||
(5 #f defaulter #f expression)
|
||||
(6 #f expander #f expression)
|
||||
(7 #f documentation #f string)))
|
||||
'(no-parameters
|
||||
*parameter-columns*
|
||||
*parameter-columns*
|
||||
())
|
||||
'(no-parameter-names
|
||||
((name string))
|
||||
((parameter-index uint))
|
||||
())
|
||||
'(add-domain-params
|
||||
*parameter-columns*
|
||||
*parameter-columns*
|
||||
((1 domain-name single atom #f #f "new domain name")
|
||||
(2 foreign-table optional table #f #f
|
||||
"if present, domain-name must be existing key into this table")
|
||||
(3 domain-integrity-rule optional expression #f #f
|
||||
"returns #t if single argument is good")
|
||||
(4 type-id single type #f #f "base type of new domain")
|
||||
(5 type-param optional expression #f #f
|
||||
"which (key) field of the foreign-table")
|
||||
))
|
||||
'(add-domain-pnames
|
||||
((name string))
|
||||
((parameter-index uint)) ;should be add-domain-params
|
||||
(
|
||||
("n" 1) ("name" 1)
|
||||
("f" 2) ("foreign (key) table" 2)
|
||||
("r" 3) ("domain integrity rule" 3)
|
||||
("t" 4) ("type" 4)
|
||||
("p" 5) ("type param" 5)
|
||||
))
|
||||
'(del-domain-params
|
||||
*parameter-columns*
|
||||
*parameter-columns*
|
||||
((1 domain-name single domain #f #f "domain name")))
|
||||
'(del-domain-pnames
|
||||
((name string))
|
||||
((parameter-index uint)) ;should be del-domain-params
|
||||
(("n" 1) ("name" 1)))
|
||||
'(*commands*
|
||||
((name symbol))
|
||||
((parameters parameter-list)
|
||||
(parameter-names parameter-name-translation)
|
||||
(procedure expression)
|
||||
(documentation string))
|
||||
((domain-checker
|
||||
no-parameters
|
||||
no-parameter-names
|
||||
dbutil:check-domain
|
||||
"return procedure to check given domain name")
|
||||
|
||||
(add-domain
|
||||
add-domain-params
|
||||
add-domain-pnames
|
||||
(lambda (rdb)
|
||||
(((rdb 'open-table) '*domains-data* #t) 'row:update))
|
||||
"add a new domain")
|
||||
|
||||
(delete-domain
|
||||
del-domain-params
|
||||
del-domain-pnames
|
||||
(lambda (rdb)
|
||||
(((rdb 'open-table) '*domains-data* #t) 'row:remove))
|
||||
"delete a domain"))))
|
||||
(let* ((tab ((rdb 'open-table) '*domains-data* #t))
|
||||
(row ((tab 'row:retrieve) 'type)))
|
||||
(set-car! (cdr row) 'type)
|
||||
((tab 'row:update) row))
|
||||
(dbutil:wrap-command-interface rdb)))
|
||||
|
||||
(define (make-defaulter arity type)
|
||||
`(lambda (pl)
|
||||
',(case arity
|
||||
((optional nary) '())
|
||||
((boolean) #f)
|
||||
((single nary1)
|
||||
(case type
|
||||
((string) '(""))
|
||||
((symbol) '(nil))
|
||||
(else '(#f))))
|
||||
(else (slib:error 'make-defaulter 'unknown 'arity arity)))))
|
||||
|
||||
(define (get-foreign-choices tab)
|
||||
(define dlst ((tab 'get* 1)))
|
||||
(do ((dlst dlst (cdr dlst))
|
||||
(vlst (if (memq 'visible-name (tab 'column-names))
|
||||
((tab 'get* 'visible-name))
|
||||
dlst)
|
||||
(cdr vlst))
|
||||
(out '() (if (member (car dlst) (cdr dlst))
|
||||
out
|
||||
(cons (list (car dlst) (car vlst)) out))))
|
||||
((null? dlst) out)))
|
||||
|
||||
(define (make-command-server rdb command-table)
|
||||
(let* ((comtab ((rdb 'open-table) command-table #f))
|
||||
(names (comtab 'column-names))
|
||||
(row-ref (lambda (row name) (list-ref row (position name names))))
|
||||
(comgetrow (comtab 'row:retrieve)))
|
||||
(lambda (comname command-callback)
|
||||
(cond ((not comname) (set! comname '*default*)))
|
||||
(cond ((not (comgetrow comname))
|
||||
(slib:error 'command 'not 'known: comname)))
|
||||
(let* ((command:row (comgetrow comname))
|
||||
(parameter-table
|
||||
((rdb 'open-table) (row-ref command:row 'parameters) #f))
|
||||
(parameter-names
|
||||
((rdb 'open-table) (row-ref command:row 'parameter-names) #f))
|
||||
(comval ((slib:eval (row-ref command:row 'procedure)) rdb))
|
||||
(options ((parameter-table 'get* 'name)))
|
||||
(positions ((parameter-table 'get* 'index)))
|
||||
(arities ((parameter-table 'get* 'arity)))
|
||||
(defaulters (map slib:eval ((parameter-table 'get* 'defaulter))))
|
||||
(domains ((parameter-table 'get* 'domain)))
|
||||
(types (map (((rdb 'open-table) '*domains-data* #f) 'get 'type-id)
|
||||
domains))
|
||||
(dirs (map (rdb 'domain-checker) domains))
|
||||
(aliases
|
||||
(map list ((parameter-names 'get* 'name))
|
||||
(map (parameter-table 'get 'name)
|
||||
((parameter-names 'get* 'parameter-index))))))
|
||||
(command-callback comname comval options positions
|
||||
arities types defaulters dirs aliases)))))
|
||||
|
||||
(define (dbutil:define-tables rdb . spec-list)
|
||||
(define new-tables '())
|
||||
(define dom:typ (((rdb 'open-table) '*domains-data* #f) 'get 4))
|
||||
(define create-table (rdb 'create-table))
|
||||
(define open-table (rdb 'open-table))
|
||||
(define table-exists? (rdb 'table-exists?))
|
||||
(define (check-domain dname)
|
||||
(cond ((dom:typ dname))
|
||||
((member dname new-tables)
|
||||
(let* ((ftab (open-table
|
||||
(string->symbol
|
||||
(string-append "desc:" (symbol->string dname)))
|
||||
#f)))
|
||||
((((rdb 'open-table) '*domains-data* #t) 'row:insert)
|
||||
(list dname dname #f
|
||||
(dom:typ ((ftab 'get 'domain-name) 1)) 1))))))
|
||||
(define (define-table name prikeys slots data)
|
||||
(cond
|
||||
((table-exists? name)
|
||||
(let* ((tab (open-table name #t))
|
||||
(row:update (tab 'row:update)))
|
||||
(for-each row:update data)))
|
||||
((and (symbol? prikeys) (eq? prikeys slots))
|
||||
(cond ((not (table-exists? slots))
|
||||
(slib:error "Table doesn't exist:" slots)))
|
||||
(set! new-tables (cons name new-tables))
|
||||
(let* ((tab (create-table name slots))
|
||||
(row:insert (tab 'row:insert)))
|
||||
(for-each row:insert data)
|
||||
((tab 'close-table))))
|
||||
(else
|
||||
(let* ((descname
|
||||
(string->symbol (string-append "desc:" (symbol->string name))))
|
||||
(tab (create-table descname))
|
||||
(row:insert (tab 'row:insert))
|
||||
(j 0))
|
||||
(set! new-tables (cons name new-tables))
|
||||
(for-each (lambda (des)
|
||||
(set! j (+ 1 j))
|
||||
(check-domain (cadr des))
|
||||
(row:insert (list j #t (car des)
|
||||
(if (null? (cddr des)) #f (caddr des))
|
||||
(cadr des))))
|
||||
prikeys)
|
||||
(for-each (lambda (des)
|
||||
(set! j (+ 1 j))
|
||||
(check-domain (cadr des))
|
||||
(row:insert (list j #f (car des)
|
||||
(if (null? (cddr des)) #f (caddr des))
|
||||
(cadr des))))
|
||||
slots)
|
||||
((tab 'close-table))
|
||||
(set! tab (create-table name descname))
|
||||
(set! row:insert (tab 'row:insert))
|
||||
(for-each row:insert data)
|
||||
((tab 'close-table))))))
|
||||
(for-each (lambda (spec) (apply define-table spec)) spec-list))
|
||||
|
||||
(define (dbutil:list-table-definition rdb table-name)
|
||||
(cond (((rdb 'table-exists?) table-name)
|
||||
(let* ((table ((rdb 'open-table) table-name #f))
|
||||
(prilimit (table 'primary-limit))
|
||||
(coldefs (map list
|
||||
(table 'column-names)
|
||||
(table 'column-domains))))
|
||||
(list table-name
|
||||
(butnthcdr prilimit coldefs)
|
||||
(nthcdr prilimit coldefs)
|
||||
((table 'row:retrieve*)))))
|
||||
(else #f)))
|
||||
|
||||
(define create-database dbutil:create-database)
|
||||
(define open-database! dbutil:open-database!)
|
||||
(define open-database dbutil:open-database)
|
||||
(define define-tables dbutil:define-tables)
|
||||
(define list-table-definition dbutil:list-table-definition)
|
|
@ -1,98 +0,0 @@
|
|||
;;;; "debug.scm" Utility functions for debugging in Scheme.
|
||||
;;; Copyright (C) 1991, 1992, 1993, 1995, 1999 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'trace)
|
||||
(require 'break)
|
||||
(require 'line-i/o)
|
||||
|
||||
(define (for-each-top-level-definition-in-file file proc)
|
||||
(call-with-input-file
|
||||
file
|
||||
(lambda (port)
|
||||
(letrec
|
||||
((walk
|
||||
(lambda (exp)
|
||||
(cond
|
||||
((not (and (pair? exp) (list? exp))))
|
||||
((not (symbol? (car exp))))
|
||||
(else
|
||||
(case (car exp)
|
||||
((begin) (for-each walk (cdr exp)))
|
||||
((cond) (for-each
|
||||
(lambda (exp)
|
||||
(for-each walk
|
||||
(if (list? (car exp)) exp (cdr exp))))
|
||||
(cdr exp)))
|
||||
((if) (for-each
|
||||
walk (if (list? (cadr exp)) (cdr exp) (cddr exp))))
|
||||
((defmacro define-syntax) (proc exp))
|
||||
((define) (proc exp))))))))
|
||||
(if (eqv? #\# (peek-char port))
|
||||
(read-line port)) ;remove `magic-number'
|
||||
(do ((form (read port) (read port)))
|
||||
((eof-object? form))
|
||||
(walk form))))))
|
||||
|
||||
(define (for-each-top-level-defined-procedure-symbol-in-file file proc)
|
||||
(letrec ((get-defined-symbol
|
||||
(lambda (form)
|
||||
(if (pair? form)
|
||||
(get-defined-symbol (car form))
|
||||
form))))
|
||||
(for-each-top-level-definition-in-file
|
||||
file
|
||||
(lambda (form)
|
||||
(and (eqv? 'define (car form))
|
||||
(let ((sym (get-defined-symbol (cadr form))))
|
||||
(cond ((procedure? (slib:eval sym))
|
||||
(proc sym)))))))))
|
||||
|
||||
(define (trace-all file . ...)
|
||||
(for-each
|
||||
(lambda (file)
|
||||
(for-each-top-level-defined-procedure-symbol-in-file
|
||||
file
|
||||
(lambda (sym)
|
||||
(slib:eval `(set! ,sym (trace:trace-procedure 'trace ,sym ',sym))))))
|
||||
(cons file ...)))
|
||||
(define (track-all file . ...)
|
||||
(for-each
|
||||
(lambda (file)
|
||||
(for-each-top-level-defined-procedure-symbol-in-file
|
||||
file
|
||||
(lambda (sym)
|
||||
(slib:eval `(set! ,sym (trace:trace-procedure 'track ,sym ',sym))))))
|
||||
(cons file ...)))
|
||||
(define (stack-all file . ...)
|
||||
(for-each
|
||||
(lambda (file)
|
||||
(for-each-top-level-defined-procedure-symbol-in-file
|
||||
file
|
||||
(lambda (sym)
|
||||
(slib:eval `(set! ,sym (trace:trace-procedure 'stack ,sym ',sym))))))
|
||||
(cons file ...)))
|
||||
|
||||
(define (break-all file . ...)
|
||||
(for-each
|
||||
(lambda (file)
|
||||
(for-each-top-level-defined-procedure-symbol-in-file
|
||||
file
|
||||
(lambda (sym)
|
||||
(slib:eval `(set! ,sym (break:breakf ,sym ',sym))))))
|
||||
(cons file ...)))
|
|
@ -1,100 +0,0 @@
|
|||
;;;"defmacex.scm" defmacro:expand* for any Scheme dialect.
|
||||
;;;Copyright 1993-1994 Dorai Sitaram and Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;;expand thoroughly, not just topmost expression. While expanding
|
||||
;;;subexpressions, the primitive forms quote, lambda, set!, let/*/rec,
|
||||
;;;cond, case, do, quasiquote: need to be destructured properly. (if,
|
||||
;;;and, or, begin: don't need special treatment.)
|
||||
|
||||
(define (defmacro:iqq e depth)
|
||||
(letrec
|
||||
((map1 (lambda (f x)
|
||||
(if (pair? x) (cons (f (car x)) (map1 f (cdr x)))
|
||||
x)))
|
||||
(iqq (lambda (e depth)
|
||||
(if (pair? e)
|
||||
(case (car e)
|
||||
((quasiquote) (list (car e) (iqq (cadr e) (+ 1 depth))))
|
||||
((unquote unquote-splicing)
|
||||
(list (car e) (if (= 1 depth)
|
||||
(defmacro:expand* (cadr e))
|
||||
(iqq (cadr e) (+ -1 depth)))))
|
||||
(else (map1 (lambda (e) (iqq e depth)) e)))
|
||||
e))))
|
||||
(iqq e depth)))
|
||||
|
||||
(define (defmacro:expand* e)
|
||||
(if (pair? e)
|
||||
(let* ((c (macroexpand-1 e)))
|
||||
(if (not (eq? e c))
|
||||
(defmacro:expand* c)
|
||||
(case (car e)
|
||||
((quote) e)
|
||||
((quasiquote) (defmacro:iqq e 0))
|
||||
((lambda define set!)
|
||||
(cons (car e) (cons (cadr e) (map defmacro:expand* (cddr e)))))
|
||||
((let)
|
||||
(let ((b (cadr e)))
|
||||
(if (symbol? b) ;named let
|
||||
`(let ,b
|
||||
,(map (lambda (vv)
|
||||
`(,(car vv)
|
||||
,(defmacro:expand* (cadr vv))))
|
||||
(caddr e))
|
||||
,@(map defmacro:expand*
|
||||
(cdddr e)))
|
||||
`(let
|
||||
,(map (lambda (vv)
|
||||
`(,(car vv)
|
||||
,(defmacro:expand* (cadr vv))))
|
||||
b)
|
||||
,@(map defmacro:expand*
|
||||
(cddr e))))))
|
||||
((let* letrec)
|
||||
`(,(car e) ,(map (lambda (vv)
|
||||
`(,(car vv)
|
||||
,(defmacro:expand* (cadr vv))))
|
||||
(cadr e))
|
||||
,@(map defmacro:expand* (cddr e))))
|
||||
((cond)
|
||||
`(cond
|
||||
,@(map (lambda (c)
|
||||
(map defmacro:expand* c))
|
||||
(cdr e))))
|
||||
((case)
|
||||
`(case ,(defmacro:expand* (cadr e))
|
||||
,@(map (lambda (c)
|
||||
`(,(car c)
|
||||
,@(map defmacro:expand* (cdr c))))
|
||||
(cddr e))))
|
||||
((do)
|
||||
`(do ,(map
|
||||
(lambda (initsteps)
|
||||
`(,(car initsteps)
|
||||
,@(map defmacro:expand*
|
||||
(cdr initsteps))))
|
||||
(cadr e))
|
||||
,(map defmacro:expand* (caddr e))
|
||||
,@(map defmacro:expand* (cdddr e))))
|
||||
((defmacro)
|
||||
(cons (car e)
|
||||
(cons (cadr e)
|
||||
(cons (caddr e) (map defmacro:expand* (cdddr e))))))
|
||||
(else (map defmacro:expand* e)))))
|
||||
e))
|
|
@ -1,14 +0,0 @@
|
|||
;"determ.scm" Determinant
|
||||
|
||||
(define (determinant m)
|
||||
(define (butnth n lst)
|
||||
(if (zero? n) (cdr lst) (cons (car lst) (butnth (+ -1 n) (cdr lst)))))
|
||||
(define (minor m i j)
|
||||
(map (lambda (x) (butnth j x)) (butnth i m)))
|
||||
(define (cofactor m i j)
|
||||
(* (if (odd? (+ i j)) -1 1) (determinant (minor m i j))))
|
||||
(define n (length m))
|
||||
(if (eqv? 1 n) (caar m)
|
||||
(do ((j (+ -1 n) (+ -1 j))
|
||||
(ans 0 (+ ans (* (list-ref (car m) j) (cofactor m 0 j)))))
|
||||
((negative? j) ans))))
|
|
@ -1,80 +0,0 @@
|
|||
;;;; "dwindtst.scm", routines for characterizing dynamic-wind.
|
||||
;Copyright (C) 1992 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'dynamic-wind)
|
||||
|
||||
(define (dwtest n)
|
||||
(define cont #f)
|
||||
(display "testing escape from thunk") (display n) (newline)
|
||||
(display "visiting:") (newline)
|
||||
(call-with-current-continuation
|
||||
(lambda (x) (set! cont x)))
|
||||
(if n
|
||||
(dynamic-wind
|
||||
(lambda ()
|
||||
(display "thunk1") (newline)
|
||||
(if (eqv? n 1) (let ((ntmp n))
|
||||
(set! n #f)
|
||||
(cont ntmp))))
|
||||
(lambda ()
|
||||
(display "thunk2") (newline)
|
||||
(if (eqv? n 2) (let ((ntmp n))
|
||||
(set! n #f)
|
||||
(cont ntmp))))
|
||||
(lambda ()
|
||||
(display "thunk3") (newline)
|
||||
(if (eqv? n 3) (let ((ntmp n))
|
||||
(set! n #f)
|
||||
(cont ntmp)))))))
|
||||
(define (dwctest n)
|
||||
(define cont #f)
|
||||
(define ccont #f)
|
||||
(display "creating continuation thunk") (newline)
|
||||
(display "visiting:") (newline)
|
||||
(call-with-current-continuation
|
||||
(lambda (x) (set! cont x)))
|
||||
(if n (set! n (- n)))
|
||||
(if n
|
||||
(dynamic-wind
|
||||
(lambda ()
|
||||
(display "thunk1") (newline)
|
||||
(if (eqv? n 1) (let ((ntmp n))
|
||||
(set! n #f)
|
||||
(cont ntmp))))
|
||||
(lambda ()
|
||||
(call-with-current-continuation
|
||||
(lambda (x) (set! ccont x)))
|
||||
(display "thunk2") (newline)
|
||||
(if (eqv? n 2) (let ((ntmp n))
|
||||
(set! n #f)
|
||||
(cont ntmp))))
|
||||
(lambda ()
|
||||
(display "thunk3") (newline)
|
||||
(if (eqv? n 3) (let ((ntmp n))
|
||||
(set! n #f)
|
||||
(cont ntmp))))))
|
||||
(cond
|
||||
(n
|
||||
(set! n (- n))
|
||||
(display "testing escape from continuation thunk") (display n) (newline)
|
||||
(display "visiting:") (newline)
|
||||
(ccont #f))))
|
||||
|
||||
(dwtest 1) (dwtest 2) (dwtest 3)
|
||||
(dwctest 1) (dwctest 2) (dwctest 3)
|
|
@ -1,75 +0,0 @@
|
|||
; "dynamic.scm", DYNAMIC data type for Scheme
|
||||
; Copyright 1992 Andrew Wilcox.
|
||||
;
|
||||
; You may freely copy, redistribute and modify this package.
|
||||
|
||||
(require 'record)
|
||||
(require 'dynamic-wind)
|
||||
|
||||
(define dynamic-environment-rtd
|
||||
(make-record-type "dynamic environment" '(dynamic value parent)))
|
||||
(define make-dynamic-environment
|
||||
(record-constructor dynamic-environment-rtd))
|
||||
(define dynamic-environment:dynamic
|
||||
(record-accessor dynamic-environment-rtd 'dynamic))
|
||||
(define dynamic-environment:value
|
||||
(record-accessor dynamic-environment-rtd 'value))
|
||||
(define dynamic-environment:set-value!
|
||||
(record-modifier dynamic-environment-rtd 'value))
|
||||
(define dynamic-environment:parent
|
||||
(record-accessor dynamic-environment-rtd 'parent))
|
||||
|
||||
(define *current-dynamic-environment* #f)
|
||||
(define (extend-current-dynamic-environment dynamic obj)
|
||||
(set! *current-dynamic-environment*
|
||||
(make-dynamic-environment dynamic obj
|
||||
*current-dynamic-environment*)))
|
||||
|
||||
(define dynamic-rtd (make-record-type "dynamic" '()))
|
||||
(define make-dynamic
|
||||
(let ((dynamic-constructor (record-constructor dynamic-rtd)))
|
||||
(lambda (obj)
|
||||
(let ((dynamic (dynamic-constructor)))
|
||||
(extend-current-dynamic-environment dynamic obj)
|
||||
dynamic))))
|
||||
|
||||
(define dynamic? (record-predicate dynamic-rtd))
|
||||
(define (guarantee-dynamic dynamic)
|
||||
(or (dynamic? dynamic)
|
||||
(slib:error "Not a dynamic" dynamic)))
|
||||
|
||||
(define dynamic:errmsg
|
||||
"No value defined for this dynamic in the current dynamic environment")
|
||||
|
||||
(define (dynamic-ref dynamic)
|
||||
(guarantee-dynamic dynamic)
|
||||
(let loop ((env *current-dynamic-environment*))
|
||||
(cond ((not env)
|
||||
(slib:error dynamic:errmsg dynamic))
|
||||
((eq? (dynamic-environment:dynamic env) dynamic)
|
||||
(dynamic-environment:value env))
|
||||
(else
|
||||
(loop (dynamic-environment:parent env))))))
|
||||
|
||||
(define (dynamic-set! dynamic obj)
|
||||
(guarantee-dynamic dynamic)
|
||||
(let loop ((env *current-dynamic-environment*))
|
||||
(cond ((not env)
|
||||
(slib:error dynamic:errmsg dynamic))
|
||||
((eq? (dynamic-environment:dynamic env) dynamic)
|
||||
(dynamic-environment:set-value! env obj))
|
||||
(else
|
||||
(loop (dynamic-environment:parent env))))))
|
||||
|
||||
(define (call-with-dynamic-binding dynamic obj thunk)
|
||||
(let ((out-thunk-env #f)
|
||||
(in-thunk-env (make-dynamic-environment
|
||||
dynamic obj
|
||||
*current-dynamic-environment*)))
|
||||
(dynamic-wind (lambda ()
|
||||
(set! out-thunk-env *current-dynamic-environment*)
|
||||
(set! *current-dynamic-environment* in-thunk-env))
|
||||
thunk
|
||||
(lambda ()
|
||||
(set! in-thunk-env *current-dynamic-environment*)
|
||||
(set! *current-dynamic-environment* out-thunk-env)))))
|
|
@ -1,74 +0,0 @@
|
|||
; "dynwind.scm", wind-unwind-protect for Scheme
|
||||
; Copyright (c) 1992, 1993 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;This facility is a generalization of Common Lisp `unwind-protect',
|
||||
;designed to take into account the fact that continuations produced by
|
||||
;CALL-WITH-CURRENT-CONTINUATION may be reentered.
|
||||
|
||||
; (dynamic-wind <thunk1> <thunk2> <thunk3>) procedure
|
||||
|
||||
;The arguments <thunk1>, <thunk2>, and <thunk3> must all be procedures
|
||||
;of no arguments (thunks).
|
||||
|
||||
;DYNAMIC-WIND calls <thunk1>, <thunk2>, and then <thunk3>. The value
|
||||
;returned by <thunk2> is returned as the result of DYNAMIC-WIND.
|
||||
;<thunk3> is also called just before control leaves the dynamic
|
||||
;context of <thunk2> by calling a continuation created outside that
|
||||
;context. Furthermore, <thunk1> is called before reentering the
|
||||
;dynamic context of <thunk2> by calling a continuation created inside
|
||||
;that context. (Control is inside the context of <thunk2> if <thunk2>
|
||||
;is on the current return stack).
|
||||
|
||||
;;;WARNING: This code has no provision for dealing with errors or
|
||||
;;;interrupts. If an error or interrupt occurs while using
|
||||
;;;dynamic-wind, the dynamic environment will be that in effect at the
|
||||
;;;time of the error or interrupt.
|
||||
|
||||
(define dynamic:winds '())
|
||||
|
||||
(define (dynamic-wind <thunk1> <thunk2> <thunk3>)
|
||||
(<thunk1>)
|
||||
(set! dynamic:winds (cons (cons <thunk1> <thunk3>) dynamic:winds))
|
||||
(let ((ans (<thunk2>)))
|
||||
(set! dynamic:winds (cdr dynamic:winds))
|
||||
(<thunk3>)
|
||||
ans))
|
||||
|
||||
(define call-with-current-continuation
|
||||
(let ((oldcc call-with-current-continuation))
|
||||
(lambda (proc)
|
||||
(let ((winds dynamic:winds))
|
||||
(oldcc
|
||||
(lambda (cont)
|
||||
(proc (lambda (c2)
|
||||
(dynamic:do-winds winds (- (length dynamic:winds)
|
||||
(length winds)))
|
||||
(cont c2)))))))))
|
||||
|
||||
(define (dynamic:do-winds to delta)
|
||||
(cond ((eq? dynamic:winds to))
|
||||
((negative? delta)
|
||||
(dynamic:do-winds (cdr to) (+ 1 delta))
|
||||
((caar to))
|
||||
(set! dynamic:winds to))
|
||||
(else
|
||||
(let ((from (cdar dynamic:winds)))
|
||||
(set! dynamic:winds (cdr dynamic:winds))
|
||||
(from)
|
||||
(dynamic:do-winds to (+ -1 delta))))))
|
|
@ -1,303 +0,0 @@
|
|||
;;;"elk.init" Initialisation file for SLIB for ELK 2.1 -*- Scheme -*-
|
||||
;;; Author: Aubrey Jaffer
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
; No guarantees are given about the correctness of any of the
|
||||
; choices made below. Only enough work was done to get the require
|
||||
; mechanism to work correctly.
|
||||
;
|
||||
; Stephen J. Bevan <bevan@cs.man.ac.uk> 19920912 modified by Mike
|
||||
; Sperber to work correctly with statically-linked Elk and slib1d. Be
|
||||
; sure to change the library vicinities according to your local
|
||||
; configuration. If you're running MS-DOS (which is possible since
|
||||
; 2.1), you probably have to change this file to make everything work
|
||||
; correctly.
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
;;; UNIX, VMS, MACOS, AMIGA and MS-DOS are supported.
|
||||
|
||||
(define (software-type) 'UNIX)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'Elk)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page)
|
||||
"http://www.informatik.uni-bremen.de/~net/elk/")
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-version) "3.0")
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define (implementation-vicinity)
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/local/lib/elk-2.1/scm/")
|
||||
((VMS) "scheme$src:")
|
||||
((MS-DOS) "C:\\scheme\\")))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(require 'unix)
|
||||
(define getenv unix-getenv)
|
||||
(define system unix-system)
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(or (getenv "SCHEME_LIBRARY_PATH")
|
||||
;; Uses this path if SCHEME_LIBRARY_PATH is not defined.
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/local/lib/slib/")
|
||||
((VMS) "lib$scheme:")
|
||||
((MS-DOS) "C:\\SLIB\\")
|
||||
(else "")))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define home-vicinity
|
||||
(let ((home-path (getenv "HOME")))
|
||||
(lambda () home-path)))
|
||||
|
||||
;;; *features* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
rev4-report
|
||||
ieee-p1178
|
||||
sicp
|
||||
rev4-optional-procedures
|
||||
rev3-procedures
|
||||
rev2-procedures
|
||||
multiarg/and-
|
||||
multiarg-apply
|
||||
delay
|
||||
transcript
|
||||
full-continuation
|
||||
sort
|
||||
format
|
||||
system
|
||||
getenv
|
||||
program-arguments
|
||||
string-port
|
||||
))
|
||||
|
||||
;------------
|
||||
|
||||
(define program-arguments
|
||||
(lambda ()
|
||||
(cons "undefined-program-name" (command-line-args))))
|
||||
|
||||
; EXACT? appears to always return #f which isn't very useful.
|
||||
; Approximating it with INTEGER? at least means that some
|
||||
; of the code in the library will work correctly
|
||||
|
||||
(define exact? integer?) ; WARNING: redefining EXACT?
|
||||
|
||||
(define (inexact? arg)
|
||||
(not (exact? arg)))
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam
|
||||
(let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(let ((tmp (string-append "slib_" (number->string cntr))))
|
||||
(if (file-exists? tmp) (tmpnam) tmp)))))
|
||||
|
||||
; Pull in GENTENV and SYSTEM
|
||||
|
||||
;;; (FILE-EXISTS? <string>) already here.
|
||||
|
||||
;;; (DELETE-FILE <string>)
|
||||
(define (delete-file f) (system (string-append "rm " f)))
|
||||
|
||||
;------------
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (CURRENT-ERROR-PORT)
|
||||
;;; is already defined in Elk 2.1
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port
|
||||
;;; use this definition if your system doesn't have such a procedure.
|
||||
(define force-output flush-output-port)
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-*PUT-FILE.
|
||||
(define (call-with-output-string f)
|
||||
(let ((outsp (open-output-string)))
|
||||
(f outsp)
|
||||
(let ((s (get-output-string outsp)))
|
||||
(close-output-port outsp)
|
||||
s)))
|
||||
|
||||
(define (call-with-input-string s f)
|
||||
(let* ((insp (open-input-string s))
|
||||
(res (f insp)))
|
||||
(close-input-port insp)
|
||||
res))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum 8388608) ; 23 bit integers ?
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
(define *macros* '())
|
||||
(define (defmacro? m) (and (assq m *macros*) #t))
|
||||
|
||||
(define-macro (defmacro key pattern . body)
|
||||
`(begin
|
||||
(define-macro ,(cons key pattern) ,@body)
|
||||
(set! *macros* (cons (cons ',key (lambda ,pattern ,@body)) *macros*))))
|
||||
|
||||
(define (macroexpand-1 e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a) (set! a (assq a *macros*))
|
||||
(if a (apply (cdr a) (cdr e)) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define (macroexpand e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a)
|
||||
(set! a (assq a *macros*))
|
||||
(if a (macroexpand (apply (cdr a) (cdr e))) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define gentemp
|
||||
(let ((*gensym-counter* -1))
|
||||
(lambda ()
|
||||
(set! *gensym-counter* (+ *gensym-counter* 1))
|
||||
(string->symbol
|
||||
(string-append "slib:G" (number->string *gensym-counter*))))))
|
||||
|
||||
(define defmacro:eval slib:eval)
|
||||
(define defmacro:load load)
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;;; define an error procedure for the library
|
||||
(define slib:error
|
||||
(lambda args
|
||||
(define (slib:error . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(apply s48-error args))
|
||||
(let ((port (open-output-string))
|
||||
(err (if (and (pair? args) (symbol? (car args)))
|
||||
(car args) 'slib))
|
||||
(args (if (and (pair? args) (symbol? (car args)))
|
||||
(cdr args) args)))
|
||||
(for-each (lambda (x) (display x port) (display " " port)) args)
|
||||
(let ((str (get-output-string port)))
|
||||
(close-output-port port)
|
||||
(error err str)))))
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab #\tab)
|
||||
(define slib:form-feed #\formfeed)
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
|
||||
;(define (1+ n) (+ n 1))
|
||||
;(define (-1+ n) (+ n -1))
|
||||
;(define 1- -1+)
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit
|
||||
(lambda args
|
||||
(exit (cond ((null? args) 0)
|
||||
((eqv? #t (car args)) 0)
|
||||
((and (number? (car args)) (integer? (car args))) (car args))
|
||||
(else 1)))))
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
; Modify the already modified _load_ so that it copes with
|
||||
; environments correctly. The change involves using
|
||||
; _(global-environment)_ if none is explicitly specified.
|
||||
; If this is not done, definitions in files loaded by other files will
|
||||
; not be loaded in the correct environment.
|
||||
|
||||
(define slib:load-source
|
||||
(let ((primitive-load load))
|
||||
(lambda (<pathname> . rest)
|
||||
(let ((env (if (null? rest) (list (global-environment)) rest)))
|
||||
(apply primitive-load <pathname> env)))))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled
|
||||
(let ((primitive-load load))
|
||||
(lambda (<pathname> . rest)
|
||||
(apply primitive-load (string->symbol (string-append name ".o")) rest))))
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source) ;WARNING: redefining LOAD
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
|
@ -1,146 +0,0 @@
|
|||
; "eval.scm", Eval proposed by Guillermo (Bill) J. Rozas for R5RS.
|
||||
; Copyright (c) 1997, 1998 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; Rather than worry over the status of all the optional procedures,
|
||||
;;; just require as many as possible.
|
||||
|
||||
(require 'rev4-optional-procedures)
|
||||
(require 'dynamic-wind)
|
||||
(require 'transcript)
|
||||
(require 'with-file)
|
||||
(require 'values)
|
||||
|
||||
(define eval:make-environment
|
||||
(let ((eval-1 slib:eval))
|
||||
(lambda (identifiers)
|
||||
((lambda args args)
|
||||
#f
|
||||
identifiers
|
||||
(lambda (expression)
|
||||
(eval-1 `(lambda ,identifiers ,expression)))))))
|
||||
|
||||
(define eval:capture-environment!
|
||||
(let ((set-car! set-car!)
|
||||
(eval-1 slib:eval)
|
||||
(apply apply))
|
||||
(lambda (environment)
|
||||
(set-car!
|
||||
environment
|
||||
(apply (lambda (environment-values identifiers procedure)
|
||||
(eval-1 `((lambda args args) ,@identifiers)))
|
||||
environment)))))
|
||||
|
||||
(define interaction-environment
|
||||
(let ((env (eval:make-environment '())))
|
||||
(lambda () env)))
|
||||
|
||||
;;; null-environment is set by first call to scheme-report-environment at
|
||||
;;; the end of this file.
|
||||
(define null-environment #f)
|
||||
|
||||
(define scheme-report-environment
|
||||
(let* ((r4rs-procedures
|
||||
(append
|
||||
(cond ((provided? 'inexact)
|
||||
(append
|
||||
'(acos angle asin atan cos exact->inexact exp
|
||||
expt imag-part inexact->exact log magnitude
|
||||
make-polar make-rectangular real-part sin
|
||||
sqrt tan)
|
||||
(if (let ((n (string->number "1/3")))
|
||||
(and (number? n) (exact? n)))
|
||||
'(denominator numerator)
|
||||
'())))
|
||||
(else '()))
|
||||
(cond ((provided? 'rationalize)
|
||||
'(rationalize))
|
||||
(else '()))
|
||||
(cond ((provided? 'delay)
|
||||
'(force))
|
||||
(else '()))
|
||||
(cond ((provided? 'char-ready?)
|
||||
'(char-ready?))
|
||||
(else '()))
|
||||
'(* + - / < <= = > >= abs append apply assoc assq assv boolean?
|
||||
caaaar caaadr caaar caadar caaddr caadr caar cadaar cadadr cadar
|
||||
caddar cadddr caddr cadr call-with-current-continuation
|
||||
call-with-input-file call-with-output-file car cdaaar cdaadr
|
||||
cdaar cdadar cdaddr cdadr cdar cddaar cddadr cddar cdddar cddddr
|
||||
cdddr cddr cdr ceiling char->integer char-alphabetic? char-ci<=?
|
||||
char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase
|
||||
char-lower-case? char-numeric? char-upcase char-upper-case?
|
||||
char-whitespace? char<=? char<? char=? char>=? char>? char?
|
||||
close-input-port close-output-port complex? cons
|
||||
current-input-port current-output-port display eof-object? eq?
|
||||
equal? eqv? even? exact? floor for-each gcd inexact?
|
||||
input-port? integer->char integer? lcm length list list->string
|
||||
list->vector list-ref list-tail list? load make-string
|
||||
make-vector map max member memq memv min modulo negative?
|
||||
newline not null? number->string number? odd? open-input-file
|
||||
open-output-file output-port? pair? peek-char positive?
|
||||
procedure? quotient rational? read read-char real? remainder
|
||||
reverse round set-car! set-cdr! string string->list
|
||||
string->number string->symbol string-append string-ci<=?
|
||||
string-ci<? string-ci=? string-ci>=? string-ci>? string-copy
|
||||
string-fill! string-length string-ref string-set! string<=?
|
||||
string<? string=? string>=? string>? string? substring
|
||||
symbol->string symbol? transcript-off transcript-on truncate
|
||||
vector vector->list vector-fill! vector-length vector-ref
|
||||
vector-set! vector? with-input-from-file with-output-to-file
|
||||
write write-char zero?
|
||||
)))
|
||||
(r5rs-procedures
|
||||
(append
|
||||
'(call-with-values dynamic-wind eval interaction-environment
|
||||
null-environment scheme-report-environment values)
|
||||
r4rs-procedures))
|
||||
(r4rs-environment (eval:make-environment r4rs-procedures))
|
||||
(r5rs-environment (eval:make-environment r4rs-procedures)))
|
||||
(let ((car car))
|
||||
(lambda (version)
|
||||
(cond ((car r5rs-environment))
|
||||
(else
|
||||
(let ((null-env (eval:make-environment r5rs-procedures)))
|
||||
(set-car! null-env (map (lambda (i) #f) r5rs-procedures))
|
||||
(set! null-environment (lambda version null-env)))
|
||||
(eval:capture-environment! r4rs-environment)
|
||||
(eval:capture-environment! r5rs-environment)))
|
||||
(case version
|
||||
((4) r4rs-environment)
|
||||
((5) r5rs-environment)
|
||||
(else (slib:error 'eval 'version version 'not 'available)))))))
|
||||
|
||||
(define eval
|
||||
(let ((eval-1 slib:eval)
|
||||
(apply apply)
|
||||
(null? null?)
|
||||
(eq? eq?))
|
||||
(lambda (expression . environment)
|
||||
(if (null? environment) (eval-1 expression)
|
||||
(apply
|
||||
(lambda (environment)
|
||||
(if (eq? (interaction-environment) environment) (eval-1 expression)
|
||||
(apply (lambda (environment-values identifiers procedure)
|
||||
(apply (procedure expression) environment-values))
|
||||
environment)))
|
||||
environment)))))
|
||||
(set! slib:eval eval)
|
||||
|
||||
;;; Now that all the R5RS procedures are defined, capture r5rs-environment.
|
||||
(and (scheme-report-environment 5) #t)
|
|
@ -1,245 +0,0 @@
|
|||
;;;; "factor.scm" factorization, prime test and generation
|
||||
;;; Copyright (C) 1991, 1992, 1993, 1998 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'common-list-functions)
|
||||
(require 'modular)
|
||||
(require 'random)
|
||||
(require 'byte)
|
||||
|
||||
;;@body
|
||||
;;@0 is the random-state (@pxref{Random Numbers}) used by these
|
||||
;;procedures. If you call these procedures from more than one thread
|
||||
;;(or from interrupt), @code{random} may complain about reentrant
|
||||
;;calls.
|
||||
(define prime:prngs
|
||||
(make-random-state "repeatable seed for primes"))
|
||||
|
||||
|
||||
;;@emph{Note:} The prime test and generation procedures implement (or
|
||||
;;use) the Solovay-Strassen primality test. See
|
||||
;;
|
||||
;;@itemize @bullet
|
||||
;;@item Robert Solovay and Volker Strassen,
|
||||
;;@cite{A Fast Monte-Carlo Test for Primality},
|
||||
;;SIAM Journal on Computing, 1977, pp 84-85.
|
||||
;;@end itemize
|
||||
|
||||
;;; Solovay-Strassen Prime Test
|
||||
;;; if n is prime, then J(a,n) is congruent mod n to a**((n-1)/2)
|
||||
|
||||
;;; (modulo p 16) is because we care only about the low order bits.
|
||||
;;; The odd? tests are inline of (expt -1 ...)
|
||||
|
||||
(define (prime:jacobi-symbol p q)
|
||||
(cond ((zero? p) 0)
|
||||
((= 1 p) 1)
|
||||
((odd? p)
|
||||
(if (odd? (quotient (* (- (modulo p 16) 1) (- q 1)) 4))
|
||||
(- (prime:jacobi-symbol (modulo q p) p))
|
||||
(prime:jacobi-symbol (modulo q p) p)))
|
||||
(else
|
||||
(let ((qq (modulo q 16)))
|
||||
(if (odd? (quotient (- (* qq qq) 1) 8))
|
||||
(- (prime:jacobi-symbol (quotient p 2) q))
|
||||
(prime:jacobi-symbol (quotient p 2) q))))))
|
||||
;;@args p q
|
||||
;;Returns the value (+1, @minus{}1, or 0) of the Jacobi-Symbol of
|
||||
;;exact non-negative integer @1 and exact positive odd integer @2.
|
||||
(define jacobi-symbol prime:jacobi-symbol)
|
||||
|
||||
;;@body
|
||||
;;@0 the maxinum number of iterations of Solovay-Strassen that will
|
||||
;;be done to test a number for primality.
|
||||
(define prime:trials 30)
|
||||
|
||||
;;; checks if n is prime. Returns #f if not prime. #t if (probably) prime.
|
||||
;;; probability of a mistake = (expt 2 (- prime:trials))
|
||||
;;; choosing prime:trials=30 should be enough
|
||||
(define (Solovay-Strassen-prime? n)
|
||||
(do ((i prime:trials (- i 1))
|
||||
(a (+ 2 (random (- n 2) prime:prngs))
|
||||
(+ 2 (random (- n 2) prime:prngs))))
|
||||
((not (and (positive? i)
|
||||
(= (gcd a n) 1)
|
||||
(= (modulo (prime:jacobi-symbol a n) n)
|
||||
(modular:expt n a (quotient (- n 1) 2)))))
|
||||
(if (positive? i) #f #t))))
|
||||
|
||||
;;; prime:products are products of small primes.
|
||||
(define (primes-gcd? n comps)
|
||||
(comlist:notevery (lambda (prd) (= 1 (gcd n prd))) comps))
|
||||
(define prime:prime-sqr 121)
|
||||
(define prime:products '(105))
|
||||
(define prime:sieve (bytes 0 0 1 1 0 1 0 1 0 0 0))
|
||||
(letrec ((lp (lambda (comp comps primes nexp)
|
||||
(cond ((< comp (quotient most-positive-fixnum nexp))
|
||||
(let ((ncomp (* nexp comp)))
|
||||
(lp ncomp comps
|
||||
(cons nexp primes)
|
||||
(next-prime nexp (cons ncomp comps)))))
|
||||
((< (quotient comp nexp) (* nexp nexp))
|
||||
(set! prime:prime-sqr (* nexp nexp))
|
||||
(set! prime:sieve (make-bytes nexp 0))
|
||||
(for-each (lambda (prime)
|
||||
(byte-set! prime:sieve prime 1))
|
||||
primes)
|
||||
(set! prime:products (reverse (cons comp comps))))
|
||||
(else
|
||||
(lp nexp (cons comp comps)
|
||||
(cons nexp primes)
|
||||
(next-prime nexp (cons comp comps)))))))
|
||||
(next-prime (lambda (nexp comps)
|
||||
(set! comps (reverse comps))
|
||||
(do ((nexp (+ 2 nexp) (+ 2 nexp)))
|
||||
((not (primes-gcd? nexp comps)) nexp)))))
|
||||
(lp 3 '() '(2 3) 5))
|
||||
|
||||
(define (prime:prime? n)
|
||||
(set! n (abs n))
|
||||
(cond ((< n (bytes-length prime:sieve)) (positive? (byte-ref prime:sieve n)))
|
||||
((even? n) #f)
|
||||
((primes-gcd? n prime:products) #f)
|
||||
((< n prime:prime-sqr) #t)
|
||||
(else (Solovay-Strassen-prime? n))))
|
||||
;;@args n
|
||||
;;Returns @code{#f} if @1 is composite; @code{#t} if @1 is prime.
|
||||
;;There is a slight chance @code{(expt 2 (- prime:trials))} that a
|
||||
;;composite will return @code{#t}.
|
||||
(define prime? prime:prime?)
|
||||
(define probably-prime? prime:prime?) ;legacy
|
||||
|
||||
(define (prime:prime< start)
|
||||
(do ((nbr (+ -1 start) (+ -1 nbr)))
|
||||
((or (negative? nbr) (prime:prime? nbr))
|
||||
(if (negative? nbr) #f nbr))))
|
||||
|
||||
(define (prime:primes< start count)
|
||||
(do ((cnt (+ -2 count) (+ -1 cnt))
|
||||
(lst '() (cons prime lst))
|
||||
(prime (prime:prime< start) (prime:prime< prime)))
|
||||
((or (not prime) (negative? cnt))
|
||||
(if prime (cons prime lst) lst))))
|
||||
;;@args start count
|
||||
;;Returns a list of the first @2 prime numbers less than
|
||||
;;@1. If there are fewer than @var{count} prime numbers
|
||||
;;less than @var{start}, then the returned list will have fewer than
|
||||
;;@var{start} elements.
|
||||
(define primes< prime:primes<)
|
||||
|
||||
(define (prime:prime> start)
|
||||
(do ((nbr (+ 1 start) (+ 1 nbr)))
|
||||
((prime:prime? nbr) nbr)))
|
||||
|
||||
(define (prime:primes> start count)
|
||||
(set! start (max 0 start))
|
||||
(do ((cnt (+ -2 count) (+ -1 cnt))
|
||||
(lst '() (cons prime lst))
|
||||
(prime (prime:prime> start) (prime:prime> prime)))
|
||||
((negative? cnt)
|
||||
(reverse (cons prime lst)))))
|
||||
;;@args start count
|
||||
;;Returns a list of the first @2 prime numbers greater than @1.
|
||||
(define primes> prime:primes>)
|
||||
|
||||
;;;;Lankinen's recursive factoring algorithm:
|
||||
;From: ld231782@longs.LANCE.ColoState.EDU (L. Detweiler)
|
||||
|
||||
; | undefined if n<0,
|
||||
; | (u,v) if n=0,
|
||||
;Let f(u,v,b,n) := | [otherwise]
|
||||
; | f(u+b,v,2b,(n-v)/2) or f(u,v+b,2b,(n-u)/2) if n odd
|
||||
; | f(u,v,2b,n/2) or f(u+b,v+b,2b,(n-u-v-b)/2) if n even
|
||||
|
||||
;Thm: f(1,1,2,(m-1)/2) = (p,q) iff pq=m for odd m.
|
||||
|
||||
;It may be illuminating to consider the relation of the Lankinen function in
|
||||
;a `computational hierarchy' of other factoring functions.* Assumptions are
|
||||
;made herein on the basis of conventional digital (binary) computers. Also,
|
||||
;complexity orders are given for the worst case scenarios (when the number to
|
||||
;be factored is prime). However, all algorithms would probably perform to
|
||||
;the same constant multiple of the given orders for complete composite
|
||||
;factorizations.
|
||||
|
||||
;Thm: Eratosthenes' Sieve is very roughtly O(ln(n)/n) in time and
|
||||
; O(n*log2(n)) in space.
|
||||
;Pf: It works with all prime factors less than n (about ln(n)/n by the prime
|
||||
; number thm), requiring an array of size proportional to n with log2(n)
|
||||
; space for each entry.
|
||||
|
||||
;Thm: `Odd factors' is O((sqrt(n)/2)*log2(n)) in time and O(log2(n)) in
|
||||
; space.
|
||||
;Pf: It tests all odd factors less than the square root of n (about
|
||||
; sqrt(n)/2), with log2(n) time for each division. It requires only
|
||||
; log2(n) space for the number and divisors.
|
||||
|
||||
;Thm: Lankinen's algorithm is O(sqrt(n)/2) in time and O((sqrt(n)/2)*log2(n))
|
||||
; in space.
|
||||
;Pf: The algorithm is easily modified to seach only for factors p<q for all
|
||||
; pq=m. Then the recursive call tree forms a geometric progression
|
||||
; starting at one, and doubling until reaching sqrt(n)/2, or a length of
|
||||
; log2(sqrt(n)/2). From the formula for a geometric progression, there is
|
||||
; a total of about 2^log2(sqrt(n)/2) = sqrt(n)/2 calls. Assuming that
|
||||
; addition, subtraction, comparison, and multiplication/division by two
|
||||
; occur in constant time, this implies O(sqrt(n)/2) time and a
|
||||
; O((sqrt(n)/2)*log2(n)) requirement of stack space.
|
||||
|
||||
(define (prime:f u v b n)
|
||||
(if (<= n 0)
|
||||
(cond ((negative? n) #f)
|
||||
((= u 1) #f)
|
||||
((= v 1) #f)
|
||||
; Do both of these factors need to be factored?
|
||||
(else (append (or (prime:f 1 1 2 (quotient (- u 1) 2))
|
||||
(list u))
|
||||
(or (prime:f 1 1 2 (quotient (- v 1) 2))
|
||||
(list v)))))
|
||||
(if (even? n)
|
||||
(or (prime:f u v (+ b b) (quotient n 2))
|
||||
(prime:f (+ u b) (+ v b) (+ b b) (quotient (- n (+ u v b)) 2)))
|
||||
(or (prime:f (+ u b) v (+ b b) (quotient (- n v) 2))
|
||||
(prime:f u (+ v b) (+ b b) (quotient (- n u) 2))))))
|
||||
|
||||
(define (prime:fo m)
|
||||
(let* ((s (gcd m (car prime:products)))
|
||||
(r (quotient m s)))
|
||||
(if (= 1 s)
|
||||
(or (prime:f 1 1 2 (quotient (- m 1) 2)) (list m))
|
||||
(append
|
||||
(if (= 1 r) '()
|
||||
(or (prime:f 1 1 2 (quotient (- r 1) 2)) (list r)))
|
||||
(or (prime:f 1 1 2 (quotient (- s 1) 2)) (list s))))))
|
||||
|
||||
(define (prime:fe m)
|
||||
(if (even? m)
|
||||
(cons 2 (prime:fe (quotient m 2)))
|
||||
(if (eqv? 1 m)
|
||||
'()
|
||||
(prime:fo m))))
|
||||
|
||||
(define (prime:factor k)
|
||||
(case k
|
||||
((-1 0 1) (list k))
|
||||
(else (if (negative? k)
|
||||
(cons -1 (prime:fe (- k)))
|
||||
(prime:fe k)))))
|
||||
;;@args k
|
||||
;;Returns a list of the prime factors of @1. The order of the
|
||||
;;factors is unspecified. In order to obtain a sorted list do
|
||||
;;@code{(sort! (factor @var{k}) <)}.
|
||||
(define factor prime:factor)
|
|
@ -1,56 +0,0 @@
|
|||
|
||||
@defvar prime:prngs
|
||||
|
||||
@var{prime:prngs} is the random-state (@pxref{Random Numbers}) used by these
|
||||
procedures. If you call these procedures from more than one thread
|
||||
(or from interrupt), @code{random} may complain about reentrant
|
||||
calls.
|
||||
@end defvar
|
||||
@emph{Note:} The prime test and generation procedures implement (or
|
||||
use) the Solovay-Strassen primality test. See
|
||||
|
||||
@itemize @bullet
|
||||
@item Robert Solovay and Volker Strassen,
|
||||
@cite{A Fast Monte-Carlo Test for Primality},
|
||||
SIAM Journal on Computing, 1977, pp 84-85.
|
||||
@end itemize
|
||||
|
||||
|
||||
@defun jacobi-symbol p q
|
||||
|
||||
Returns the value (+1, @minus{}1, or 0) of the Jacobi-Symbol of
|
||||
exact non-negative integer @var{p} and exact positive odd integer @var{q}.
|
||||
@end defun
|
||||
|
||||
@defvar prime:trials
|
||||
|
||||
@var{prime:trials} the maxinum number of iterations of Solovay-Strassen that will
|
||||
be done to test a number for primality.
|
||||
@end defvar
|
||||
|
||||
@defun prime? n
|
||||
|
||||
Returns @code{#f} if @var{n} is composite; @code{#t} if @var{n} is prime.
|
||||
There is a slight chance @code{(expt 2 (- prime:trials))} that a
|
||||
composite will return @code{#t}.
|
||||
@end defun
|
||||
|
||||
@defun primes< start count
|
||||
|
||||
Returns a list of the first @var{count} prime numbers less than
|
||||
@var{start}. If there are fewer than @var{count} prime numbers
|
||||
less than @var{start}, then the returned list will have fewer than
|
||||
@var{start} elements.
|
||||
@end defun
|
||||
|
||||
@defun primes> start count
|
||||
|
||||
Returns a list of the first @var{count} prime numbers greater than @var{start}.
|
||||
@end defun
|
||||
|
||||
@defun factor k
|
||||
|
||||
Returns a list of the prime factors of @var{k}. The order of the
|
||||
factors is unspecified. In order to obtain a sorted list do
|
||||
@code{(sort! (factor @var{k}) <)}.
|
||||
@end defun
|
|
@ -1,70 +0,0 @@
|
|||
;;;"fft.scm" Fast Fourier Transform
|
||||
;Copyright (C) 1999 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;;; See:
|
||||
;;; Introduction to Algorithms (MIT Electrical
|
||||
;;; Engineering and Computer Science Series)
|
||||
;;; by Thomas H. Cormen, Charles E. Leiserson (Contributor),
|
||||
;;; Ronald L. Rivest (Contributor)
|
||||
;;; MIT Press; ISBN: 0-262-03141-8 (July 1990)
|
||||
|
||||
;;; http://www.astro.virginia.edu/~eww6n/math/DiscreteFourierTransform.html
|
||||
;;; differs in the direction of rotation of the complex unit vectors.
|
||||
|
||||
(require 'array)
|
||||
|
||||
(define (fft:shuffled&scaled ara n scale)
|
||||
(define lgn (integer-length (+ -1 n)))
|
||||
(define new (apply make-array 0 (array-dimensions ara)))
|
||||
(define bit-reverse (lambda (width in)
|
||||
(if (zero? width) 0
|
||||
(+ (bit-reverse (+ -1 width) (quotient in 2))
|
||||
(ash (modulo in 2) (+ -1 width))))))
|
||||
(if (not (eqv? n (expt 2 lgn)))
|
||||
(slib:error 'fft "array length not power of 2" n))
|
||||
(do ((k 0 (+ 1 k)))
|
||||
((>= k n) new)
|
||||
(array-set! new (* (array-ref ara k) scale) (bit-reverse lgn k))))
|
||||
|
||||
(define (dft! ara n dir)
|
||||
(define lgn (integer-length (+ -1 n)))
|
||||
(define pi2i (* 0+8i (atan 1)))
|
||||
(do ((s 1 (+ 1 s)))
|
||||
((> s lgn) ara)
|
||||
(let* ((m (expt 2 s))
|
||||
(w_m (exp (* dir (/ pi2i m))))
|
||||
(m/2-1 (+ (quotient m 2) -1)))
|
||||
(do ((j 0 (+ 1 j))
|
||||
(w 1 (* w w_m)))
|
||||
((> j m/2-1))
|
||||
(do ((k j (+ m k)))
|
||||
((>= k n))
|
||||
(let* ((k+m/2 (+ k m/2-1 1))
|
||||
(t (* w (array-ref ara k+m/2)))
|
||||
(u (array-ref ara k)))
|
||||
(array-set! ara (+ u t) k)
|
||||
(array-set! ara (- u t) k+m/2)))))))
|
||||
|
||||
(define (fft ara)
|
||||
(define n (car (array-dimensions ara)))
|
||||
(dft! (fft:shuffled&scaled ara n 1) n 1))
|
||||
|
||||
(define (fft-1 ara)
|
||||
(define n (car (array-dimensions ara)))
|
||||
(dft! (fft:shuffled&scaled ara n (/ n)) n -1))
|
|
@ -1,40 +0,0 @@
|
|||
; "fluidlet.scm", FLUID-LET for Scheme
|
||||
; Copyright (c) 1998, Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'dynamic-wind)
|
||||
(require 'common-list-functions) ;MAKE-LIST
|
||||
|
||||
(defmacro fluid-let (clauses . body)
|
||||
(let ((ids (map car clauses))
|
||||
(new-tmps (map (lambda (x) (gentemp)) clauses))
|
||||
(old-tmps (map (lambda (x) (gentemp)) clauses)))
|
||||
`(let (,@(map list new-tmps (map cadr clauses))
|
||||
,@(map list old-tmps (make-list (length clauses) #f)))
|
||||
(dynamic-wind
|
||||
(lambda ()
|
||||
,@(map (lambda (ot id) `(set! ,ot ,id))
|
||||
old-tmps ids)
|
||||
,@(map (lambda (id nt) `(set! ,id ,nt))
|
||||
ids new-tmps))
|
||||
(lambda () ,@body)
|
||||
(lambda ()
|
||||
,@(map (lambda (nt id) `(set! ,nt ,id))
|
||||
new-tmps ids)
|
||||
,@(map (lambda (id ot) `(set! ,id ,ot))
|
||||
ids old-tmps))))))
|
|
@ -1,434 +0,0 @@
|
|||
|
||||
@menu
|
||||
* Format Interface::
|
||||
* Format Specification::
|
||||
@end menu
|
||||
|
||||
@node Format Interface, Format Specification, Format, Format
|
||||
@subsection Format Interface
|
||||
|
||||
@defun format destination format-string . arguments
|
||||
An almost complete implementation of Common LISP format description
|
||||
according to the CL reference book @cite{Common LISP} from Guy L.
|
||||
Steele, Digital Press. Backward compatible to most of the available
|
||||
Scheme format implementations.
|
||||
|
||||
Returns @code{#t}, @code{#f} or a string; has side effect of printing
|
||||
according to @var{format-string}. If @var{destination} is @code{#t},
|
||||
the output is to the current output port and @code{#t} is returned. If
|
||||
@var{destination} is @code{#f}, a formatted string is returned as the
|
||||
result of the call. NEW: If @var{destination} is a string,
|
||||
@var{destination} is regarded as the format string; @var{format-string} is
|
||||
then the first argument and the output is returned as a string. If
|
||||
@var{destination} is a number, the output is to the current error port
|
||||
if available by the implementation. Otherwise @var{destination} must be
|
||||
an output port and @code{#t} is returned.@refill
|
||||
|
||||
@var{format-string} must be a string. In case of a formatting error
|
||||
format returns @code{#f} and prints a message on the current output or
|
||||
error port. Characters are output as if the string were output by the
|
||||
@code{display} function with the exception of those prefixed by a tilde
|
||||
(~). For a detailed description of the @var{format-string} syntax
|
||||
please consult a Common LISP format reference manual. For a test suite
|
||||
to verify this format implementation load @file{formatst.scm}. Please
|
||||
send bug reports to @code{lutzeb@@cs.tu-berlin.de}.
|
||||
|
||||
Note: @code{format} is not reentrant, i.e. only one @code{format}-call
|
||||
may be executed at a time.
|
||||
|
||||
@end defun
|
||||
|
||||
@node Format Specification, , Format Interface, Format
|
||||
@subsection Format Specification (Format version 3.0)
|
||||
|
||||
Please consult a Common LISP format reference manual for a detailed
|
||||
description of the format string syntax. For a demonstration of the
|
||||
implemented directives see @file{formatst.scm}.@refill
|
||||
|
||||
This implementation supports directive parameters and modifiers
|
||||
(@code{:} and @code{@@} characters). Multiple parameters must be
|
||||
separated by a comma (@code{,}). Parameters can be numerical parameters
|
||||
(positive or negative), character parameters (prefixed by a quote
|
||||
character (@code{'}), variable parameters (@code{v}), number of rest
|
||||
arguments parameter (@code{#}), empty and default parameters. Directive
|
||||
characters are case independent. The general form of a directive
|
||||
is:@refill
|
||||
|
||||
@noindent
|
||||
@var{directive} ::= ~@{@var{directive-parameter},@}[:][@@]@var{directive-character}
|
||||
|
||||
@noindent
|
||||
@var{directive-parameter} ::= [ [-|+]@{0-9@}+ | '@var{character} | v | # ]
|
||||
|
||||
|
||||
@subsubsection Implemented CL Format Control Directives
|
||||
|
||||
Documentation syntax: Uppercase characters represent the corresponding
|
||||
control directive characters. Lowercase characters represent control
|
||||
directive parameter descriptions.
|
||||
|
||||
@table @asis
|
||||
@item @code{~A}
|
||||
Any (print as @code{display} does).
|
||||
@table @asis
|
||||
@item @code{~@@A}
|
||||
left pad.
|
||||
@item @code{~@var{mincol},@var{colinc},@var{minpad},@var{padchar}A}
|
||||
full padding.
|
||||
@end table
|
||||
@item @code{~S}
|
||||
S-expression (print as @code{write} does).
|
||||
@table @asis
|
||||
@item @code{~@@S}
|
||||
left pad.
|
||||
@item @code{~@var{mincol},@var{colinc},@var{minpad},@var{padchar}S}
|
||||
full padding.
|
||||
@end table
|
||||
@item @code{~D}
|
||||
Decimal.
|
||||
@table @asis
|
||||
@item @code{~@@D}
|
||||
print number sign always.
|
||||
@item @code{~:D}
|
||||
print comma separated.
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar}D}
|
||||
padding.
|
||||
@end table
|
||||
@item @code{~X}
|
||||
Hexadecimal.
|
||||
@table @asis
|
||||
@item @code{~@@X}
|
||||
print number sign always.
|
||||
@item @code{~:X}
|
||||
print comma separated.
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar}X}
|
||||
padding.
|
||||
@end table
|
||||
@item @code{~O}
|
||||
Octal.
|
||||
@table @asis
|
||||
@item @code{~@@O}
|
||||
print number sign always.
|
||||
@item @code{~:O}
|
||||
print comma separated.
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar}O}
|
||||
padding.
|
||||
@end table
|
||||
@item @code{~B}
|
||||
Binary.
|
||||
@table @asis
|
||||
@item @code{~@@B}
|
||||
print number sign always.
|
||||
@item @code{~:B}
|
||||
print comma separated.
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar}B}
|
||||
padding.
|
||||
@end table
|
||||
@item @code{~@var{n}R}
|
||||
Radix @var{n}.
|
||||
@table @asis
|
||||
@item @code{~@var{n},@var{mincol},@var{padchar},@var{commachar}R}
|
||||
padding.
|
||||
@end table
|
||||
@item @code{~@@R}
|
||||
print a number as a Roman numeral.
|
||||
@item @code{~:@@R}
|
||||
print a number as an ``old fashioned'' Roman numeral.
|
||||
@item @code{~:R}
|
||||
print a number as an ordinal English number.
|
||||
@item @code{~R}
|
||||
print a number as a cardinal English number.
|
||||
@item @code{~P}
|
||||
Plural.
|
||||
@table @asis
|
||||
@item @code{~@@P}
|
||||
prints @code{y} and @code{ies}.
|
||||
@item @code{~:P}
|
||||
as @code{~P but jumps 1 argument backward.}
|
||||
@item @code{~:@@P}
|
||||
as @code{~@@P but jumps 1 argument backward.}
|
||||
@end table
|
||||
@item @code{~C}
|
||||
Character.
|
||||
@table @asis
|
||||
@item @code{~@@C}
|
||||
prints a character as the reader can understand it (i.e. @code{#\} prefixing).
|
||||
@item @code{~:C}
|
||||
prints a character as emacs does (eg. @code{^C} for ASCII 03).
|
||||
@end table
|
||||
@item @code{~F}
|
||||
Fixed-format floating-point (prints a flonum like @var{mmm.nnn}).
|
||||
@table @asis
|
||||
@item @code{~@var{width},@var{digits},@var{scale},@var{overflowchar},@var{padchar}F}
|
||||
@item @code{~@@F}
|
||||
If the number is positive a plus sign is printed.
|
||||
@end table
|
||||
@item @code{~E}
|
||||
Exponential floating-point (prints a flonum like @var{mmm.nnn}@code{E}@var{ee}).
|
||||
@table @asis
|
||||
@item @code{~@var{width},@var{digits},@var{exponentdigits},@var{scale},@var{overflowchar},@var{padchar},@var{exponentchar}E}
|
||||
@item @code{~@@E}
|
||||
If the number is positive a plus sign is printed.
|
||||
@end table
|
||||
@item @code{~G}
|
||||
General floating-point (prints a flonum either fixed or exponential).
|
||||
@table @asis
|
||||
@item @code{~@var{width},@var{digits},@var{exponentdigits},@var{scale},@var{overflowchar},@var{padchar},@var{exponentchar}G}
|
||||
@item @code{~@@G}
|
||||
If the number is positive a plus sign is printed.
|
||||
@end table
|
||||
@item @code{~$}
|
||||
Dollars floating-point (prints a flonum in fixed with signs separated).
|
||||
@table @asis
|
||||
@item @code{~@var{digits},@var{scale},@var{width},@var{padchar}$}
|
||||
@item @code{~@@$}
|
||||
If the number is positive a plus sign is printed.
|
||||
@item @code{~:@@$}
|
||||
A sign is always printed and appears before the padding.
|
||||
@item @code{~:$}
|
||||
The sign appears before the padding.
|
||||
@end table
|
||||
@item @code{~%}
|
||||
Newline.
|
||||
@table @asis
|
||||
@item @code{~@var{n}%}
|
||||
print @var{n} newlines.
|
||||
@end table
|
||||
@item @code{~&}
|
||||
print newline if not at the beginning of the output line.
|
||||
@table @asis
|
||||
@item @code{~@var{n}&}
|
||||
prints @code{~&} and then @var{n-1} newlines.
|
||||
@end table
|
||||
@item @code{~|}
|
||||
Page Separator.
|
||||
@table @asis
|
||||
@item @code{~@var{n}|}
|
||||
print @var{n} page separators.
|
||||
@end table
|
||||
@item @code{~~}
|
||||
Tilde.
|
||||
@table @asis
|
||||
@item @code{~@var{n}~}
|
||||
print @var{n} tildes.
|
||||
@end table
|
||||
@item @code{~}<newline>
|
||||
Continuation Line.
|
||||
@table @asis
|
||||
@item @code{~:}<newline>
|
||||
newline is ignored, white space left.
|
||||
@item @code{~@@}<newline>
|
||||
newline is left, white space ignored.
|
||||
@end table
|
||||
@item @code{~T}
|
||||
Tabulation.
|
||||
@table @asis
|
||||
@item @code{~@@T}
|
||||
relative tabulation.
|
||||
@item @code{~@var{colnum,colinc}T}
|
||||
full tabulation.
|
||||
@end table
|
||||
@item @code{~?}
|
||||
Indirection (expects indirect arguments as a list).
|
||||
@table @asis
|
||||
@item @code{~@@?}
|
||||
extracts indirect arguments from format arguments.
|
||||
@end table
|
||||
@item @code{~(@var{str}~)}
|
||||
Case conversion (converts by @code{string-downcase}).
|
||||
@table @asis
|
||||
@item @code{~:(@var{str}~)}
|
||||
converts by @code{string-capitalize}.
|
||||
@item @code{~@@(@var{str}~)}
|
||||
converts by @code{string-capitalize-first}.
|
||||
@item @code{~:@@(@var{str}~)}
|
||||
converts by @code{string-upcase}.
|
||||
@end table
|
||||
@item @code{~*}
|
||||
Argument Jumping (jumps 1 argument forward).
|
||||
@table @asis
|
||||
@item @code{~@var{n}*}
|
||||
jumps @var{n} arguments forward.
|
||||
@item @code{~:*}
|
||||
jumps 1 argument backward.
|
||||
@item @code{~@var{n}:*}
|
||||
jumps @var{n} arguments backward.
|
||||
@item @code{~@@*}
|
||||
jumps to the 0th argument.
|
||||
@item @code{~@var{n}@@*}
|
||||
jumps to the @var{n}th argument (beginning from 0)
|
||||
@end table
|
||||
@item @code{~[@var{str0}~;@var{str1}~;...~;@var{strn}~]}
|
||||
Conditional Expression (numerical clause conditional).
|
||||
@table @asis
|
||||
@item @code{~@var{n}[}
|
||||
take argument from @var{n}.
|
||||
@item @code{~@@[}
|
||||
true test conditional.
|
||||
@item @code{~:[}
|
||||
if-else-then conditional.
|
||||
@item @code{~;}
|
||||
clause separator.
|
||||
@item @code{~:;}
|
||||
default clause follows.
|
||||
@end table
|
||||
@item @code{~@{@var{str}~@}}
|
||||
Iteration (args come from the next argument (a list)).
|
||||
@table @asis
|
||||
@item @code{~@var{n}@{}
|
||||
at most @var{n} iterations.
|
||||
@item @code{~:@{}
|
||||
args from next arg (a list of lists).
|
||||
@item @code{~@@@{}
|
||||
args from the rest of arguments.
|
||||
@item @code{~:@@@{}
|
||||
args from the rest args (lists).
|
||||
@end table
|
||||
@item @code{~^}
|
||||
Up and out.
|
||||
@table @asis
|
||||
@item @code{~@var{n}^}
|
||||
aborts if @var{n} = 0
|
||||
@item @code{~@var{n},@var{m}^}
|
||||
aborts if @var{n} = @var{m}
|
||||
@item @code{~@var{n},@var{m},@var{k}^}
|
||||
aborts if @var{n} <= @var{m} <= @var{k}
|
||||
@end table
|
||||
@end table
|
||||
|
||||
|
||||
@subsubsection Not Implemented CL Format Control Directives
|
||||
|
||||
@table @asis
|
||||
@item @code{~:A}
|
||||
print @code{#f} as an empty list (see below).
|
||||
@item @code{~:S}
|
||||
print @code{#f} as an empty list (see below).
|
||||
@item @code{~<~>}
|
||||
Justification.
|
||||
@item @code{~:^}
|
||||
(sorry I don't understand its semantics completely)
|
||||
@end table
|
||||
|
||||
|
||||
@subsubsection Extended, Replaced and Additional Control Directives
|
||||
|
||||
@table @asis
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}D}
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}X}
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}O}
|
||||
@item @code{~@var{mincol},@var{padchar},@var{commachar},@var{commawidth}B}
|
||||
@item @code{~@var{n},@var{mincol},@var{padchar},@var{commachar},@var{commawidth}R}
|
||||
@var{commawidth} is the number of characters between two comma characters.
|
||||
@end table
|
||||
|
||||
@table @asis
|
||||
@item @code{~I}
|
||||
print a R4RS complex number as @code{~F~@@Fi} with passed parameters for
|
||||
@code{~F}.
|
||||
@item @code{~Y}
|
||||
Pretty print formatting of an argument for scheme code lists.
|
||||
@item @code{~K}
|
||||
Same as @code{~?.}
|
||||
@item @code{~!}
|
||||
Flushes the output if format @var{destination} is a port.
|
||||
@item @code{~_}
|
||||
Print a @code{#\space} character
|
||||
@table @asis
|
||||
@item @code{~@var{n}_}
|
||||
print @var{n} @code{#\space} characters.
|
||||
@end table
|
||||
@item @code{~/}
|
||||
Print a @code{#\tab} character
|
||||
@table @asis
|
||||
@item @code{~@var{n}/}
|
||||
print @var{n} @code{#\tab} characters.
|
||||
@end table
|
||||
@item @code{~@var{n}C}
|
||||
Takes @var{n} as an integer representation for a character. No arguments
|
||||
are consumed. @var{n} is converted to a character by
|
||||
@code{integer->char}. @var{n} must be a positive decimal number.@refill
|
||||
@item @code{~:S}
|
||||
Print out readproof. Prints out internal objects represented as
|
||||
@code{#<...>} as strings @code{"#<...>"} so that the format output can always
|
||||
be processed by @code{read}.
|
||||
@refill
|
||||
@item @code{~:A}
|
||||
Print out readproof. Prints out internal objects represented as
|
||||
@code{#<...>} as strings @code{"#<...>"} so that the format output can always
|
||||
be processed by @code{read}.
|
||||
@item @code{~Q}
|
||||
Prints information and a copyright notice on the format implementation.
|
||||
@table @asis
|
||||
@item @code{~:Q}
|
||||
prints format version.
|
||||
@end table
|
||||
@refill
|
||||
@item @code{~F, ~E, ~G, ~$}
|
||||
may also print number strings, i.e. passing a number as a string and
|
||||
format it accordingly.
|
||||
@end table
|
||||
|
||||
@subsubsection Configuration Variables
|
||||
|
||||
Format has some configuration variables at the beginning of
|
||||
@file{format.scm} to suit the systems and users needs. There should be
|
||||
no modification necessary for the configuration that comes with SLIB.
|
||||
If modification is desired the variable should be set after the format
|
||||
code is loaded. Format detects automatically if the running scheme
|
||||
system implements floating point numbers and complex numbers.
|
||||
|
||||
@table @asis
|
||||
|
||||
@item @var{format:symbol-case-conv}
|
||||
Symbols are converted by @code{symbol->string} so the case type of the
|
||||
printed symbols is implementation dependent.
|
||||
@code{format:symbol-case-conv} is a one arg closure which is either
|
||||
@code{#f} (no conversion), @code{string-upcase}, @code{string-downcase}
|
||||
or @code{string-capitalize}. (default @code{#f})
|
||||
|
||||
@item @var{format:iobj-case-conv}
|
||||
As @var{format:symbol-case-conv} but applies for the representation of
|
||||
implementation internal objects. (default @code{#f})
|
||||
|
||||
@item @var{format:expch}
|
||||
The character prefixing the exponent value in @code{~E} printing. (default
|
||||
@code{#\E})
|
||||
|
||||
@end table
|
||||
|
||||
@subsubsection Compatibility With Other Format Implementations
|
||||
|
||||
@table @asis
|
||||
@item SLIB format 2.x:
|
||||
See @file{format.doc}.
|
||||
|
||||
@item SLIB format 1.4:
|
||||
Downward compatible except for padding support and @code{~A}, @code{~S},
|
||||
@code{~P}, @code{~X} uppercase printing. SLIB format 1.4 uses C-style
|
||||
@code{printf} padding support which is completely replaced by the CL
|
||||
@code{format} padding style.
|
||||
|
||||
@item MIT C-Scheme 7.1:
|
||||
Downward compatible except for @code{~}, which is not documented
|
||||
(ignores all characters inside the format string up to a newline
|
||||
character). (7.1 implements @code{~a}, @code{~s},
|
||||
~@var{newline}, @code{~~}, @code{~%}, numerical and variable
|
||||
parameters and @code{:/@@} modifiers in the CL sense).@refill
|
||||
|
||||
@item Elk 1.5/2.0:
|
||||
Downward compatible except for @code{~A} and @code{~S} which print in
|
||||
uppercase. (Elk implements @code{~a}, @code{~s}, @code{~~}, and
|
||||
@code{~%} (no directive parameters or modifiers)).@refill
|
||||
|
||||
@item Scheme->C 01nov91:
|
||||
Downward compatible except for an optional destination parameter: S2C
|
||||
accepts a format call without a destination which returns a formatted
|
||||
string. This is equivalent to a #f destination in S2C. (S2C implements
|
||||
@code{~a}, @code{~s}, @code{~c}, @code{~%}, and @code{~~} (no directive
|
||||
parameters or modifiers)).@refill
|
||||
|
||||
@end table
|
||||
|
||||
This implementation of format is solely useful in the SLIB context
|
||||
because it requires other components provided by SLIB.@refill
|
File diff suppressed because it is too large
Load diff
|
@ -1,647 +0,0 @@
|
|||
;; "formatst.scm" SLIB FORMAT Version 3.0 conformance test
|
||||
; Written by Dirk Lutzebaeck (lutzeb@cs.tu-berlin.de)
|
||||
;
|
||||
; This code is in the public domain.
|
||||
|
||||
;; Test run: (slib:load "formatst")
|
||||
|
||||
; Failure reports for various scheme interpreters:
|
||||
;
|
||||
; SCM4d
|
||||
; None.
|
||||
; Elk 2.2:
|
||||
; None.
|
||||
; MIT C-Scheme 7.1:
|
||||
; The empty list is always evaluated as a boolean and consequently
|
||||
; represented as `#f'.
|
||||
; Scheme->C 01nov91:
|
||||
; None, if format:symbol-case-conv and format:iobj-case-conv are set
|
||||
; to string-downcase.
|
||||
|
||||
(require 'format)
|
||||
(if (not (string=? format:version "3.0"))
|
||||
(begin
|
||||
(display "You have format version ")
|
||||
(display format:version)
|
||||
(display ". This test is for format version 3.0!")
|
||||
(newline)
|
||||
(format:abort)))
|
||||
|
||||
(define fails 0)
|
||||
(define total 0)
|
||||
(define test-verbose #f) ; shows each test performed
|
||||
|
||||
(define (test format-args out-str)
|
||||
(set! total (+ total 1))
|
||||
(if (not test-verbose)
|
||||
(if (zero? (modulo total 10))
|
||||
(begin
|
||||
(display total)
|
||||
(display ",")
|
||||
(force-output (current-output-port)))))
|
||||
(let ((format-out (apply format `(#f ,@format-args))))
|
||||
(if (string=? out-str format-out)
|
||||
(if test-verbose
|
||||
(begin
|
||||
(display "Verified ")
|
||||
(write format-args)
|
||||
(display " returns ")
|
||||
(write out-str)
|
||||
(newline)))
|
||||
(begin
|
||||
(set! fails (+ fails 1))
|
||||
(if (not test-verbose) (newline))
|
||||
(display "*Failed* ")
|
||||
(write format-args)
|
||||
(newline)
|
||||
(display " returns ")
|
||||
(write format-out)
|
||||
(newline)
|
||||
(display " expected ")
|
||||
(write out-str)
|
||||
(newline)))))
|
||||
|
||||
; ensure format default configuration
|
||||
|
||||
(set! format:symbol-case-conv #f)
|
||||
(set! format:iobj-case-conv #f)
|
||||
(set! format:read-proof #f)
|
||||
|
||||
(format #t "~q")
|
||||
|
||||
(format #t "This implementation has~@[ no~] flonums ~
|
||||
~:[but no~;and~] complex numbers~%"
|
||||
(not format:floats) format:complex-numbers)
|
||||
|
||||
; any object test
|
||||
|
||||
(test '("abc") "abc")
|
||||
(test '("~a" 10) "10")
|
||||
(test '("~a" -1.2) "-1.2")
|
||||
(test '("~a" a) "a")
|
||||
(test '("~a" #t) "#t")
|
||||
(test '("~a" #f) "#f")
|
||||
(test '("~a" "abc") "abc")
|
||||
(test '("~a" #(1 2 3)) "#(1 2 3)")
|
||||
(test '("~a" ()) "()")
|
||||
(test '("~a" (a)) "(a)")
|
||||
(test '("~a" (a b)) "(a b)")
|
||||
(test '("~a" (a (b c) d)) "(a (b c) d)")
|
||||
(test '("~a" (a . b)) "(a . b)")
|
||||
(test '("~a" (a (b c . d))) "(a (b . (c . d)))") ; this is ugly
|
||||
(test `("~a" ,display) (format:iobj->str display))
|
||||
(test `("~a" ,(current-input-port)) (format:iobj->str (current-input-port)))
|
||||
(test `("~a" ,(current-output-port)) (format:iobj->str (current-output-port)))
|
||||
|
||||
; # argument test
|
||||
|
||||
(test '("~a ~a" 10 20) "10 20")
|
||||
(test '("~a abc ~a def" 10 20) "10 abc 20 def")
|
||||
|
||||
; numerical test
|
||||
|
||||
(test '("~d" 100) "100")
|
||||
(test '("~x" 100) "64")
|
||||
(test '("~o" 100) "144")
|
||||
(test '("~b" 100) "1100100")
|
||||
(test '("~@d" 100) "+100")
|
||||
(test '("~@d" -100) "-100")
|
||||
(test '("~@x" 100) "+64")
|
||||
(test '("~@o" 100) "+144")
|
||||
(test '("~@b" 100) "+1100100")
|
||||
(test '("~10d" 100) " 100")
|
||||
(test '("~:d" 123) "123")
|
||||
(test '("~:d" 1234) "1,234")
|
||||
(test '("~:d" 12345) "12,345")
|
||||
(test '("~:d" 123456) "123,456")
|
||||
(test '("~:d" 12345678) "12,345,678")
|
||||
(test '("~:d" -123) "-123")
|
||||
(test '("~:d" -1234) "-1,234")
|
||||
(test '("~:d" -12345) "-12,345")
|
||||
(test '("~:d" -123456) "-123,456")
|
||||
(test '("~:d" -12345678) "-12,345,678")
|
||||
(test '("~10:d" 1234) " 1,234")
|
||||
(test '("~10:d" -1234) " -1,234")
|
||||
(test '("~10,'*d" 100) "*******100")
|
||||
(test '("~10,,'|:d" 12345678) "12|345|678")
|
||||
(test '("~10,,,2:d" 12345678) "12,34,56,78")
|
||||
(test '("~14,'*,'|,4:@d" 12345678) "****+1234|5678")
|
||||
(test '("~10r" 100) "100")
|
||||
(test '("~2r" 100) "1100100")
|
||||
(test '("~8r" 100) "144")
|
||||
(test '("~16r" 100) "64")
|
||||
(test '("~16,10,'*r" 100) "********64")
|
||||
|
||||
; roman numeral test
|
||||
|
||||
(test '("~@r" 4) "IV")
|
||||
(test '("~@r" 19) "XIX")
|
||||
(test '("~@r" 50) "L")
|
||||
(test '("~@r" 100) "C")
|
||||
(test '("~@r" 1000) "M")
|
||||
(test '("~@r" 99) "XCIX")
|
||||
(test '("~@r" 1994) "MCMXCIV")
|
||||
|
||||
; old roman numeral test
|
||||
|
||||
(test '("~:@r" 4) "IIII")
|
||||
(test '("~:@r" 5) "V")
|
||||
(test '("~:@r" 10) "X")
|
||||
(test '("~:@r" 9) "VIIII")
|
||||
|
||||
; cardinal/ordinal English number test
|
||||
|
||||
(test '("~r" 4) "four")
|
||||
(test '("~r" 10) "ten")
|
||||
(test '("~r" 19) "nineteen")
|
||||
(test '("~r" 1984) "one thousand, nine hundred eighty-four")
|
||||
(test '("~:r" -1984) "minus one thousand, nine hundred eighty-fourth")
|
||||
|
||||
; character test
|
||||
|
||||
(test '("~c" #\a) "a")
|
||||
(test '("~@c" #\a) "#\\a")
|
||||
(test `("~@c" ,(integer->char 32)) "#\\space")
|
||||
(test `("~@c" ,(integer->char 0)) "#\\nul")
|
||||
(test `("~@c" ,(integer->char 27)) "#\\esc")
|
||||
(test `("~@c" ,(integer->char 127)) "#\\del")
|
||||
(test `("~@c" ,(integer->char 128)) "#\\200")
|
||||
(test `("~@c" ,(integer->char 255)) "#\\377")
|
||||
(test '("~65c") "A")
|
||||
(test '("~7@c") "#\\bel")
|
||||
(test '("~:c" #\a) "a")
|
||||
(test `("~:c" ,(integer->char 1)) "^A")
|
||||
(test `("~:c" ,(integer->char 27)) "^[")
|
||||
(test '("~7:c") "^G")
|
||||
(test `("~:c" ,(integer->char 128)) "#\\200")
|
||||
(test `("~:c" ,(integer->char 127)) "#\\177")
|
||||
(test `("~:c" ,(integer->char 255)) "#\\377")
|
||||
|
||||
|
||||
; plural test
|
||||
|
||||
(test '("test~p" 1) "test")
|
||||
(test '("test~p" 2) "tests")
|
||||
(test '("test~p" 0) "tests")
|
||||
(test '("tr~@p" 1) "try")
|
||||
(test '("tr~@p" 2) "tries")
|
||||
(test '("tr~@p" 0) "tries")
|
||||
(test '("~a test~:p" 10) "10 tests")
|
||||
(test '("~a test~:p" 1) "1 test")
|
||||
|
||||
; tilde test
|
||||
|
||||
(test '("~~~~") "~~")
|
||||
(test '("~3~") "~~~")
|
||||
|
||||
; whitespace character test
|
||||
|
||||
(test '("~%") "
|
||||
")
|
||||
(test '("~3%") "
|
||||
|
||||
|
||||
")
|
||||
(test '("~&") "")
|
||||
(test '("abc~&") "abc
|
||||
")
|
||||
(test '("abc~&def") "abc
|
||||
def")
|
||||
(test '("~&") "
|
||||
")
|
||||
(test '("~3&") "
|
||||
|
||||
")
|
||||
(test '("abc~3&") "abc
|
||||
|
||||
|
||||
")
|
||||
(test '("~|") (string slib:form-feed))
|
||||
(test '("~_~_~_") " ")
|
||||
(test '("~3_") " ")
|
||||
(test '("~/") (string slib:tab))
|
||||
(test '("~3/") (make-string 3 slib:tab))
|
||||
|
||||
; tabulate test
|
||||
|
||||
(test '("~0&~3t") " ")
|
||||
(test '("~0&~10t") " ")
|
||||
(test '("~10t") "")
|
||||
(test '("~0&1234567890~,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~0,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~1,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~2,8tABC") "1234567890ABC")
|
||||
(test '("~0&1234567890~3,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~4,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~5,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~6,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~7,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~8,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~9,8tABC") "1234567890 ABC")
|
||||
(test '("~0&1234567890~10,8tABC") "1234567890ABC")
|
||||
(test '("~0&1234567890~11,8tABC") "1234567890 ABC")
|
||||
(test '("~0&12345~,8tABCDE~,8tXYZ") "12345 ABCDE XYZ")
|
||||
(test '("~,8t+++~,8t===") " +++ ===")
|
||||
(test '("~0&ABC~,8,'.tDEF") "ABC......DEF")
|
||||
(test '("~0&~3,8@tABC") " ABC")
|
||||
(test '("~0&1234~3,8@tABC") "1234 ABC")
|
||||
(test '("~0&12~3,8@tABC~3,8@tDEF") "12 ABC DEF")
|
||||
|
||||
; indirection test
|
||||
|
||||
(test '("~a ~? ~a" 10 "~a ~a" (20 30) 40) "10 20 30 40")
|
||||
(test '("~a ~@? ~a" 10 "~a ~a" 20 30 40) "10 20 30 40")
|
||||
|
||||
; field test
|
||||
|
||||
(test '("~10a" "abc") "abc ")
|
||||
(test '("~10@a" "abc") " abc")
|
||||
(test '("~10a" "0123456789abc") "0123456789abc")
|
||||
(test '("~10@a" "0123456789abc") "0123456789abc")
|
||||
|
||||
; pad character test
|
||||
|
||||
(test '("~10,,,'*a" "abc") "abc*******")
|
||||
(test '("~10,,,'Xa" "abc") "abcXXXXXXX")
|
||||
(test '("~10,,,42a" "abc") "abc*******")
|
||||
(test '("~10,,,'*@a" "abc") "*******abc")
|
||||
(test '("~10,,3,'*a" "abc") "abc*******")
|
||||
(test '("~10,,3,'*a" "0123456789abc") "0123456789abc***") ; min. padchar length
|
||||
(test '("~10,,3,'*@a" "0123456789abc") "***0123456789abc")
|
||||
|
||||
; colinc, minpad padding test
|
||||
|
||||
(test '("~10,8,0,'*a" 123) "123********")
|
||||
(test '("~10,9,0,'*a" 123) "123*********")
|
||||
(test '("~10,10,0,'*a" 123) "123**********")
|
||||
(test '("~10,11,0,'*a" 123) "123***********")
|
||||
(test '("~8,1,0,'*a" 123) "123*****")
|
||||
(test '("~8,2,0,'*a" 123) "123******")
|
||||
(test '("~8,3,0,'*a" 123) "123******")
|
||||
(test '("~8,4,0,'*a" 123) "123********")
|
||||
(test '("~8,5,0,'*a" 123) "123*****")
|
||||
(test '("~8,1,3,'*a" 123) "123*****")
|
||||
(test '("~8,1,5,'*a" 123) "123*****")
|
||||
(test '("~8,1,6,'*a" 123) "123******")
|
||||
(test '("~8,1,9,'*a" 123) "123*********")
|
||||
|
||||
; slashify test
|
||||
|
||||
(test '("~s" "abc") "\"abc\"")
|
||||
(test '("~s" "abc \\ abc") "\"abc \\\\ abc\"")
|
||||
(test '("~a" "abc \\ abc") "abc \\ abc")
|
||||
(test '("~s" "abc \" abc") "\"abc \\\" abc\"")
|
||||
(test '("~a" "abc \" abc") "abc \" abc")
|
||||
(test '("~s" #\space) "#\\space")
|
||||
(test '("~s" #\newline) "#\\newline")
|
||||
(test `("~s" ,slib:tab) "#\\ht")
|
||||
(test '("~s" #\a) "#\\a")
|
||||
(test '("~a" (a "b" c)) "(a \"b\" c)")
|
||||
|
||||
; symbol case force test
|
||||
|
||||
(define format:old-scc format:symbol-case-conv)
|
||||
(set! format:symbol-case-conv string-upcase)
|
||||
(test '("~a" abc) "ABC")
|
||||
(set! format:symbol-case-conv string-downcase)
|
||||
(test '("~s" abc) "abc")
|
||||
(set! format:symbol-case-conv string-capitalize)
|
||||
(test '("~s" abc) "Abc")
|
||||
(set! format:symbol-case-conv format:old-scc)
|
||||
|
||||
; read proof test
|
||||
|
||||
(test `("~:s" ,display)
|
||||
(begin
|
||||
(set! format:read-proof #t)
|
||||
(format:iobj->str display)))
|
||||
(test `("~:a" ,display)
|
||||
(begin
|
||||
(set! format:read-proof #t)
|
||||
(format:iobj->str display)))
|
||||
(test `("~:a" (1 2 ,display))
|
||||
(begin
|
||||
(set! format:read-proof #t)
|
||||
(string-append "(1 2 " (format:iobj->str display) ")")))
|
||||
(test '("~:a" "abc") "abc")
|
||||
(set! format:read-proof #f)
|
||||
|
||||
; internal object case type force test
|
||||
|
||||
(set! format:iobj-case-conv string-upcase)
|
||||
(test `("~a" ,display) (string-upcase (format:iobj->str display)))
|
||||
(set! format:iobj-case-conv string-downcase)
|
||||
(test `("~s" ,display) (string-downcase (format:iobj->str display)))
|
||||
(set! format:iobj-case-conv string-capitalize)
|
||||
(test `("~s" ,display) (string-capitalize (format:iobj->str display)))
|
||||
(set! format:iobj-case-conv #f)
|
||||
|
||||
; continuation line test
|
||||
|
||||
(test '("abc~
|
||||
123") "abc123")
|
||||
(test '("abc~
|
||||
123") "abc123")
|
||||
(test '("abc~
|
||||
") "abc")
|
||||
(test '("abc~:
|
||||
def") "abc def")
|
||||
(test '("abc~@
|
||||
def")
|
||||
"abc
|
||||
def")
|
||||
|
||||
; flush output (can't test it here really)
|
||||
|
||||
(test '("abc ~! xyz") "abc xyz")
|
||||
|
||||
; string case conversion
|
||||
|
||||
(test '("~a ~(~a~) ~a" "abc" "HELLO WORLD" "xyz") "abc hello world xyz")
|
||||
(test '("~a ~:(~a~) ~a" "abc" "HELLO WORLD" "xyz") "abc Hello World xyz")
|
||||
(test '("~a ~@(~a~) ~a" "abc" "HELLO WORLD" "xyz") "abc Hello world xyz")
|
||||
(test '("~a ~:@(~a~) ~a" "abc" "hello world" "xyz") "abc HELLO WORLD xyz")
|
||||
(test '("~:@(~a~)" (a b c)) "(A B C)")
|
||||
(test '("~:@(~x~)" 255) "FF")
|
||||
(test '("~:@(~p~)" 2) "S")
|
||||
(test `("~:@(~a~)" ,display) (string-upcase (format:iobj->str display)))
|
||||
(test '("~:(~a ~a ~a~) ~a" "abc" "xyz" "123" "world") "Abc Xyz 123 world")
|
||||
|
||||
; variable parameter
|
||||
|
||||
(test '("~va" 10 "abc") "abc ")
|
||||
(test '("~v,,,va" 10 42 "abc") "abc*******")
|
||||
|
||||
; number of remaining arguments as parameter
|
||||
|
||||
(test '("~#,,,'*@a ~a ~a ~a" 1 1 1 1) "***1 1 1 1")
|
||||
|
||||
; argument jumping
|
||||
|
||||
(test '("~a ~* ~a" 10 20 30) "10 30")
|
||||
(test '("~a ~2* ~a" 10 20 30 40) "10 40")
|
||||
(test '("~a ~:* ~a" 10) "10 10")
|
||||
(test '("~a ~a ~2:* ~a ~a" 10 20) "10 20 10 20")
|
||||
(test '("~a ~a ~@* ~a ~a" 10 20) "10 20 10 20")
|
||||
(test '("~a ~a ~4@* ~a ~a" 10 20 30 40 50 60) "10 20 50 60")
|
||||
|
||||
; conditionals
|
||||
|
||||
(test '("~[abc~;xyz~]" 0) "abc")
|
||||
(test '("~[abc~;xyz~]" 1) "xyz")
|
||||
(test '("~[abc~;xyz~:;456~]" 99) "456")
|
||||
(test '("~0[abc~;xyz~:;456~]") "abc")
|
||||
(test '("~1[abc~;xyz~:;456~] ~a" 100) "xyz 100")
|
||||
(test '("~#[no arg~;~a~;~a and ~a~;~a, ~a and ~a~]") "no arg")
|
||||
(test '("~#[no arg~;~a~;~a and ~a~;~a, ~a and ~a~]" 10) "10")
|
||||
(test '("~#[no arg~;~a~;~a and ~a~;~a, ~a and ~a~]" 10 20) "10 and 20")
|
||||
(test '("~#[no arg~;~a~;~a and ~a~;~a, ~a and ~a~]" 10 20 30) "10, 20 and 30")
|
||||
(test '("~:[hello~;world~] ~a" #t 10) "world 10")
|
||||
(test '("~:[hello~;world~] ~a" #f 10) "hello 10")
|
||||
(test '("~@[~a tests~]" #f) "")
|
||||
(test '("~@[~a tests~]" 10) "10 tests")
|
||||
(test '("~@[~a test~:p~] ~a" 10 done) "10 tests done")
|
||||
(test '("~@[~a test~:p~] ~a" 1 done) "1 test done")
|
||||
(test '("~@[~a test~:p~] ~a" 0 done) "0 tests done")
|
||||
(test '("~@[~a test~:p~] ~a" #f done) " done")
|
||||
(test '("~@[ level = ~d~]~@[ length = ~d~]" #f 5) " length = 5")
|
||||
(test '("~[abc~;~[4~;5~;6~]~;xyz~]" 0) "abc") ; nested conditionals (irrghh)
|
||||
(test '("~[abc~;~[4~;5~;6~]~;xyz~]" 2) "xyz")
|
||||
(test '("~[abc~;~[4~;5~;6~]~;xyz~]" 1 2) "6")
|
||||
|
||||
; iteration
|
||||
|
||||
(test '("~{ ~a ~}" (a b c)) " a b c ")
|
||||
(test '("~{ ~a ~}" ()) "")
|
||||
(test '("~{ ~a ~5,,,'*a~}" (a b c d)) " a b**** c d****")
|
||||
(test '("~{ ~a,~a ~}" (a 1 b 2 c 3)) " a,1 b,2 c,3 ")
|
||||
(test '("~2{ ~a,~a ~}" (a 1 b 2 c 3)) " a,1 b,2 ")
|
||||
(test '("~3{~a ~} ~a" (a b c d e) 100) "a b c 100")
|
||||
(test '("~0{~a ~} ~a" (a b c d e) 100) " 100")
|
||||
(test '("~:{ ~a,~a ~}" ((a b) (c d e f) (g h))) " a,b c,d g,h ")
|
||||
(test '("~2:{ ~a,~a ~}" ((a b) (c d e f) (g h))) " a,b c,d ")
|
||||
(test '("~@{ ~a,~a ~}" a 1 b 2 c 3) " a,1 b,2 c,3 ")
|
||||
(test '("~2@{ ~a,~a ~} <~a|~a>" a 1 b 2 c 3) " a,1 b,2 <c|3>")
|
||||
(test '("~:@{ ~a,~a ~}" (a 1) (b 2) (c 3)) " a,1 b,2 c,3 ")
|
||||
(test '("~2:@{ ~a,~a ~} ~a" (a 1) (b 2) (c 3)) " a,1 b,2 (c 3)")
|
||||
(test '("~{~}" "<~a,~a>" (a 1 b 2 c 3)) "<a,1><b,2><c,3>")
|
||||
(test '("~{ ~a ~{<~a>~}~} ~a" (a (1 2) b (3 4)) 10) " a <1><2> b <3><4> 10")
|
||||
|
||||
; up and out
|
||||
|
||||
(test '("abc ~^ xyz") "abc ")
|
||||
(test '("~@(abc ~^ xyz~) ~a" 10) "ABC xyz 10")
|
||||
(test '("done. ~^ ~d warning~:p. ~^ ~d error~:p.") "done. ")
|
||||
(test '("done. ~^ ~d warning~:p. ~^ ~d error~:p." 10) "done. 10 warnings. ")
|
||||
(test '("done. ~^ ~d warning~:p. ~^ ~d error~:p." 10 1)
|
||||
"done. 10 warnings. 1 error.")
|
||||
(test '("~{ ~a ~^<~a>~} ~a" (a b c d e f) 10) " a <b> c <d> e <f> 10")
|
||||
(test '("~{ ~a ~^<~a>~} ~a" (a b c d e) 10) " a <b> c <d> e 10")
|
||||
(test '("abc~0^ xyz") "abc")
|
||||
(test '("abc~9^ xyz") "abc xyz")
|
||||
(test '("abc~7,4^ xyz") "abc xyz")
|
||||
(test '("abc~7,7^ xyz") "abc")
|
||||
(test '("abc~3,7,9^ xyz") "abc")
|
||||
(test '("abc~8,7,9^ xyz") "abc xyz")
|
||||
(test '("abc~3,7,5^ xyz") "abc xyz")
|
||||
|
||||
; complexity tests (oh my god, I hardly understand them myself (see CL std))
|
||||
|
||||
(define fmt "Items:~#[ none~; ~a~; ~a and ~a~:;~@{~#[~; and~] ~a~^,~}~].")
|
||||
|
||||
(test `(,fmt ) "Items: none.")
|
||||
(test `(,fmt foo) "Items: foo.")
|
||||
(test `(,fmt foo bar) "Items: foo and bar.")
|
||||
(test `(,fmt foo bar baz) "Items: foo, bar, and baz.")
|
||||
(test `(,fmt foo bar baz zok) "Items: foo, bar, baz, and zok.")
|
||||
|
||||
; fixed floating points
|
||||
|
||||
(cond
|
||||
(format:floats
|
||||
(test '("~6,2f" 3.14159) " 3.14")
|
||||
(test '("~6,1f" 3.14159) " 3.1")
|
||||
(test '("~6,0f" 3.14159) " 3.")
|
||||
(test '("~5,1f" 0) " 0.0")
|
||||
(test '("~10,7f" 3.14159) " 3.1415900")
|
||||
(test '("~10,7f" -3.14159) "-3.1415900")
|
||||
(test '("~10,7@f" 3.14159) "+3.1415900")
|
||||
(test '("~6,3f" 0.0) " 0.000")
|
||||
(test '("~6,4f" 0.007) "0.0070")
|
||||
(test '("~6,3f" 0.007) " 0.007")
|
||||
(test '("~6,2f" 0.007) " 0.01")
|
||||
(test '("~3,2f" 0.007) ".01")
|
||||
(test '("~3,2f" -0.007) "-.01")
|
||||
(test '("~6,2,,,'*f" 3.14159) "**3.14")
|
||||
(test '("~6,3,,'?f" 12345.56789) "??????")
|
||||
(test '("~6,3f" 12345.6789) "12345.679")
|
||||
(test '("~,3f" 12345.6789) "12345.679")
|
||||
(test '("~,3f" 9.9999) "10.000")
|
||||
(test '("~6f" 23.4) " 23.4")
|
||||
(test '("~6f" 1234.5) "1234.5")
|
||||
(test '("~6f" 12345678) "12345678.0")
|
||||
(test '("~6,,,'?f" 12345678) "??????")
|
||||
(test '("~6f" 123.56789) "123.57")
|
||||
(test '("~6f" 123.0) " 123.0")
|
||||
(test '("~6f" -123.0) "-123.0")
|
||||
(test '("~6f" 0.0) " 0.0")
|
||||
(test '("~3f" 3.141) "3.1")
|
||||
(test '("~2f" 3.141) "3.")
|
||||
(test '("~1f" 3.141) "3.141")
|
||||
(test '("~f" 123.56789) "123.56789")
|
||||
(test '("~f" -314.0) "-314.0")
|
||||
(test '("~f" 1e4) "10000.0")
|
||||
(test '("~f" -1.23e10) "-12300000000.0")
|
||||
(test '("~f" 1e-4) "0.0001")
|
||||
(test '("~f" -1.23e-10) "-0.000000000123")
|
||||
(test '("~@f" 314.0) "+314.0")
|
||||
(test '("~,,3f" 0.123456) "123.456")
|
||||
(test '("~,,-3f" -123.456) "-0.123456")
|
||||
(test '("~5,,3f" 0.123456) "123.5")
|
||||
))
|
||||
|
||||
; exponent floating points
|
||||
|
||||
(cond
|
||||
(format:floats
|
||||
(test '("~e" 3.14159) "3.14159E+0")
|
||||
(test '("~e" 0.00001234) "1.234E-5")
|
||||
(test '("~,,,0e" 0.00001234) "0.1234E-4")
|
||||
(test '("~,3e" 3.14159) "3.142E+0")
|
||||
(test '("~,3@e" 3.14159) "+3.142E+0")
|
||||
(test '("~,3@e" 0.0) "+0.000E+0")
|
||||
(test '("~,0e" 3.141) "3.E+0")
|
||||
(test '("~,3,,0e" 3.14159) "0.314E+1")
|
||||
(test '("~,5,3,-2e" 3.14159) "0.00314E+003")
|
||||
(test '("~,5,3,-5e" -3.14159) "-0.00000E+006")
|
||||
(test '("~,5,2,2e" 3.14159) "31.4159E-01")
|
||||
(test '("~,5,2,,,,'ee" 0.0) "0.00000e+00")
|
||||
(test '("~12,3e" -3.141) " -3.141E+0")
|
||||
(test '("~12,3,,,,'#e" -3.141) "###-3.141E+0")
|
||||
(test '("~10,2e" -1.236e-4) " -1.24E-4")
|
||||
(test '("~5,3e" -3.141) "-3.141E+0")
|
||||
(test '("~5,3,,,'*e" -3.141) "*****")
|
||||
(test '("~3e" 3.14159) "3.14159E+0")
|
||||
(test '("~4e" 3.14159) "3.14159E+0")
|
||||
(test '("~5e" 3.14159) "3.E+0")
|
||||
(test '("~5,,,,'*e" 3.14159) "3.E+0")
|
||||
(test '("~6e" 3.14159) "3.1E+0")
|
||||
(test '("~7e" 3.14159) "3.14E+0")
|
||||
(test '("~7e" -3.14159) "-3.1E+0")
|
||||
(test '("~8e" 3.14159) "3.142E+0")
|
||||
(test '("~9e" 3.14159) "3.1416E+0")
|
||||
(test '("~9,,,,,,'ee" 3.14159) "3.1416e+0")
|
||||
(test '("~10e" 3.14159) "3.14159E+0")
|
||||
(test '("~11e" 3.14159) " 3.14159E+0")
|
||||
(test '("~12e" 3.14159) " 3.14159E+0")
|
||||
(test '("~13,6,2,-5e" 3.14159) " 0.000003E+06")
|
||||
(test '("~13,6,2,-4e" 3.14159) " 0.000031E+05")
|
||||
(test '("~13,6,2,-3e" 3.14159) " 0.000314E+04")
|
||||
(test '("~13,6,2,-2e" 3.14159) " 0.003142E+03")
|
||||
(test '("~13,6,2,-1e" 3.14159) " 0.031416E+02")
|
||||
(test '("~13,6,2,0e" 3.14159) " 0.314159E+01")
|
||||
(test '("~13,6,2,1e" 3.14159) " 3.141590E+00")
|
||||
(test '("~13,6,2,2e" 3.14159) " 31.41590E-01")
|
||||
(test '("~13,6,2,3e" 3.14159) " 314.1590E-02")
|
||||
(test '("~13,6,2,4e" 3.14159) " 3141.590E-03")
|
||||
(test '("~13,6,2,5e" 3.14159) " 31415.90E-04")
|
||||
(test '("~13,6,2,6e" 3.14159) " 314159.0E-05")
|
||||
(test '("~13,6,2,7e" 3.14159) " 3141590.E-06")
|
||||
(test '("~13,6,2,8e" 3.14159) "31415900.E-07")
|
||||
(test '("~7,3,,-2e" 0.001) ".001E+0")
|
||||
(test '("~8,3,,-2@e" 0.001) "+.001E+0")
|
||||
(test '("~8,3,,-2@e" -0.001) "-.001E+0")
|
||||
(test '("~8,3,,-2e" 0.001) "0.001E+0")
|
||||
(test '("~7,,,-2e" 0.001) "0.00E+0")
|
||||
(test '("~12,3,1e" 3.14159e12) " 3.142E+12")
|
||||
(test '("~12,3,1,,'*e" 3.14159e12) "************")
|
||||
(test '("~5,3,1e" 3.14159e12) "3.142E+12")
|
||||
))
|
||||
|
||||
; general floating point (this test is from Steele's CL book)
|
||||
|
||||
(cond
|
||||
(format:floats
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
0.0314159 0.0314159 0.0314159 0.0314159)
|
||||
" 3.14E-2|314.2$-04|0.314E-01| 3.14E-2")
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
0.314159 0.314159 0.314159 0.314159)
|
||||
" 0.31 |0.314 |0.314 | 0.31 ")
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
3.14159 3.14159 3.14159 3.14159)
|
||||
" 3.1 | 3.14 | 3.14 | 3.1 ")
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
31.4159 31.4159 31.4159 31.4159)
|
||||
" 31. | 31.4 | 31.4 | 31. ")
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
314.159 314.159 314.159 314.159)
|
||||
" 3.14E+2| 314. | 314. | 3.14E+2")
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
3141.59 3141.59 3141.59 3141.59)
|
||||
" 3.14E+3|314.2$+01|0.314E+04| 3.14E+3")
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
3.14E12 3.14E12 3.14E12 3.14E12)
|
||||
"*********|314.0$+10|0.314E+13| 3.14E+12")
|
||||
(test '("~9,2,1,,'*g|~9,3,2,3,'?,,'$g|~9,3,2,0,'%g|~9,2g"
|
||||
3.14E120 3.14E120 3.14E120 3.14E120)
|
||||
"*********|?????????|%%%%%%%%%|3.14E+120")
|
||||
|
||||
(test '("~g" 0.0) "0.0 ") ; further ~g tests
|
||||
(test '("~g" 0.1) "0.1 ")
|
||||
(test '("~g" 0.01) "1.0E-2")
|
||||
(test '("~g" 123.456) "123.456 ")
|
||||
(test '("~g" 123456.7) "123456.7 ")
|
||||
(test '("~g" 123456.78) "123456.78 ")
|
||||
(test '("~g" 0.9282) "0.9282 ")
|
||||
(test '("~g" 0.09282) "9.282E-2")
|
||||
(test '("~g" 1) "1.0 ")
|
||||
(test '("~g" 12) "12.0 ")
|
||||
))
|
||||
|
||||
; dollar floating point
|
||||
|
||||
(cond
|
||||
(format:floats
|
||||
(test '("~$" 1.23) "1.23")
|
||||
(test '("~$" 1.2) "1.20")
|
||||
(test '("~$" 0.0) "0.00")
|
||||
(test '("~$" 9.999) "10.00")
|
||||
(test '("~3$" 9.9999) "10.000")
|
||||
(test '("~,4$" 3.2) "0003.20")
|
||||
(test '("~,4$" 10000.2) "10000.20")
|
||||
(test '("~,4,10$" 3.2) " 0003.20")
|
||||
(test '("~,4,10@$" 3.2) " +0003.20")
|
||||
(test '("~,4,10:@$" 3.2) "+ 0003.20")
|
||||
(test '("~,4,10:$" -3.2) "- 0003.20")
|
||||
(test '("~,4,10$" -3.2) " -0003.20")
|
||||
(test '("~,,10@$" 3.2) " +3.20")
|
||||
(test '("~,,10:@$" 3.2) "+ 3.20")
|
||||
(test '("~,,10:@$" -3.2) "- 3.20")
|
||||
(test '("~,,10,'_@$" 3.2) "_____+3.20")
|
||||
(test '("~,,4$" 1234.4) "1234.40")
|
||||
))
|
||||
|
||||
; complex numbers
|
||||
|
||||
(cond
|
||||
(format:complex-numbers
|
||||
(test '("~i" 3.0) "3.0+0.0i")
|
||||
(test '("~,3i" 3.0) "3.000+0.000i")
|
||||
(test `("~7,2i" ,(string->number "3.0+5.0i")) " 3.00 +5.00i")
|
||||
(test `("~7,2,1i" ,(string->number "3.0+5.0i")) " 30.00 +50.00i")
|
||||
(test `("~7,2@i" ,(string->number "3.0+5.0i")) " +3.00 +5.00i")
|
||||
(test `("~7,2,,,'*@i" ,(string->number "3.0+5.0i")) "**+3.00**+5.00i")
|
||||
)) ; note: some parsers choke syntactically on reading a complex
|
||||
; number though format:complex is #f; this is why we put them in
|
||||
; strings
|
||||
|
||||
; inquiry test
|
||||
|
||||
(test '("~:q") format:version)
|
||||
|
||||
(if (not test-verbose) (display "done."))
|
||||
|
||||
(format #t "~%~a Test~:p completed. (~a failure~:p)~2%" total fails)
|
||||
|
||||
; eof
|
|
@ -1,301 +0,0 @@
|
|||
;;;"gambit.init" Initialization for SLIB for Gambit -*-scheme-*-
|
||||
;;; Author: Aubrey Jaffer
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
;;; Updated 1992 February 1 for Gambit v1.71 -- by Ken Dickey
|
||||
;;; Date: Wed, 12 Jan 1994 15:03:12 -0500
|
||||
;;; From: barnett@armadillo.urich.edu (Lewis Barnett)
|
||||
;;; Relative pathnames for Slib in MacGambit
|
||||
;;; Hacked yet again for Gambit v2.4, Jan 1997, by Mike Pope
|
||||
|
||||
(define (software-type) 'MACOS) ; for MacGambit.
|
||||
(define (software-type) 'UNIX) ; for Unix platforms.
|
||||
|
||||
(define (scheme-implementation-type) 'gambit)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page)
|
||||
"http://www.iro.umontreal.ca/~gambit/index.html")
|
||||
|
||||
(define (scheme-implementation-version) "3.0")
|
||||
;;; Jefferson R. Lowrey reports that in Gambit Version 3.0
|
||||
;;; (argv) returns '("").
|
||||
(define argv
|
||||
(if (equal? '("") (argv)) ;Fix only if it is broken.
|
||||
(lambda () '("Lowrey HD:Development:MacGambit 3.0:Interpreter"))
|
||||
argv))
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define implementation-vicinity
|
||||
(case (software-type)
|
||||
((UNIX) (lambda () "/usr/local/src/scheme/"))
|
||||
((VMS) (lambda () "scheme$src:"))
|
||||
((MS-DOS) (lambda () "C:\\scheme\\"))
|
||||
((WINDOWS) (lambda () "c:/scheme/"))
|
||||
((MACOS)
|
||||
(let ((arg0 (list-ref (argv) 0)))
|
||||
(let loop ((i (- (string-length arg0) 1)))
|
||||
(cond ((negative? i) "")
|
||||
((char=? #\: (string-ref arg0 i))
|
||||
(set! arg0 (substring arg0 0 (+ i 1)))
|
||||
(lambda () arg0))
|
||||
(else (loop (- i 1)))))))))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
;;; This assumes that the slib files are in a folder
|
||||
;;; called slib in the same directory as the MacGambit Interpreter.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(case (software-type)
|
||||
((UNIX) "/usr/local/lib/slib/")
|
||||
((MACOS) (string-append (implementation-vicinity) "slib:"))
|
||||
((AMIGA) "dh0:scm/Library/")
|
||||
((VMS) "lib$scheme:")
|
||||
((WINDOWS MS-DOS) "C:\\SLIB\\")
|
||||
(else ""))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define (home-vicinity) #f)
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
rev4-report ;conforms to
|
||||
; rev3-report ;conforms to
|
||||
ieee-p1178 ;conforms to
|
||||
sicp ;runs code from Structure and
|
||||
;Interpretation of Computer
|
||||
;Programs by Abelson and Sussman.
|
||||
rev4-optional-procedures ;LIST-TAIL, STRING->LIST,
|
||||
;LIST->STRING, STRING-COPY,
|
||||
;STRING-FILL!, LIST->VECTOR,
|
||||
;VECTOR->LIST, and VECTOR-FILL!
|
||||
; rev2-procedures ;SUBSTRING-MOVE-LEFT!,
|
||||
;SUBSTRING-MOVE-RIGHT!,
|
||||
;SUBSTRING-FILL!,
|
||||
;STRING-NULL?, APPEND!, 1+,
|
||||
;-1+, <?, <=?, =?, >?, >=?
|
||||
multiarg/and- ;/ and - can take more than 2 args.
|
||||
multiarg-apply ;APPLY can take more than 2 args.
|
||||
rationalize
|
||||
delay ;has DELAY and FORCE
|
||||
with-file ;has WITH-INPUT-FROM-FILE and
|
||||
;WITH-OUTPUT-FROM-FILE
|
||||
string-port ;has CALL-WITH-INPUT-STRING and
|
||||
;CALL-WITH-OUTPUT-STRING
|
||||
transcript ;TRANSCRIPT-ON and TRANSCRIPT-OFF
|
||||
char-ready?
|
||||
; macro ;has R4RS high level macros
|
||||
defmacro ;has Common Lisp DEFMACRO
|
||||
; record ;has user defined data structures
|
||||
; values ;proposed multiple values
|
||||
; dynamic-wind ;proposed dynamic-wind
|
||||
ieee-floating-point ;conforms to
|
||||
full-continuation ;can return multiple times
|
||||
; object-hash ;has OBJECT-HASH
|
||||
|
||||
; sort
|
||||
; queue ;queues
|
||||
pretty-print
|
||||
; object->string
|
||||
; format
|
||||
trace ;has macros: TRACE and UNTRACE
|
||||
; compiler ;has (COMPILER)
|
||||
; ed ;(ED) is editor
|
||||
system ;posix (system <string>)
|
||||
; getenv ;posix (getenv <string>)
|
||||
program-arguments ;returns list of strings (argv)
|
||||
; Xwindows ;X support
|
||||
; curses ;screen management package
|
||||
; termcap ;terminal description package
|
||||
; terminfo ;sysV terminal description
|
||||
; current-time ;returns time in seconds since 1/1/1970
|
||||
))
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (CURRENT-ERROR-PORT)
|
||||
(define current-error-port
|
||||
(let ((port (current-output-port)))
|
||||
(lambda () port)))
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam (let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(string-append "slib_" (number->string cntr)))))
|
||||
|
||||
;;; Gambit supports SYSTEM as an "Unstable Addition"; Watch for changes.
|
||||
(define system ##shell-command)
|
||||
|
||||
;;; (FILE-EXISTS? <string>)
|
||||
;(define (file-exists? f) #f)
|
||||
|
||||
;;; (DELETE-FILE <string>)
|
||||
(define (delete-file f) #f)
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port
|
||||
;;; use this definition if your system doesn't have such a procedure.
|
||||
(define force-output flush-output)
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-*PUT-FILE.
|
||||
|
||||
;;; "rationalize" adjunct procedures.
|
||||
(define (find-ratio x e)
|
||||
(let ((rat (rationalize x e)))
|
||||
(list (numerator rat) (denominator rat))))
|
||||
(define (find-ratio-between x y)
|
||||
(find-ratio (/ (+ x y) 2) (/ (- x y) 2)))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum #x1FFFFFFF) ; 3-bit tag for 68K
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
; Define program-arguments as argv
|
||||
(define program-arguments argv)
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
; Set up defmacro in terms of gambit's define-macro
|
||||
(define-macro (defmacro name args . body)
|
||||
`(define-macro (,name ,@args) ,@body))
|
||||
|
||||
(define *defmacros*
|
||||
(list (cons 'defmacro
|
||||
(lambda (name parms . body)
|
||||
`(set! *defmacros* (cons (cons ',name (lambda ,parms ,@body))
|
||||
*defmacros*))))))
|
||||
(define (defmacro? m) (and (assq m *defmacros*) #t))
|
||||
|
||||
(define (macroexpand-1 e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a) (set! a (assq a *defmacros*))
|
||||
(if a (apply (cdr a) (cdr e)) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define (macroexpand e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a)
|
||||
(set! a (assq a *defmacros*))
|
||||
(if a (macroexpand (apply (cdr a) (cdr e))) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define gentemp
|
||||
(let ((*gensym-counter* -1))
|
||||
(lambda ()
|
||||
(set! *gensym-counter* (+ *gensym-counter* 1))
|
||||
(string->symbol
|
||||
(string-append "slib:G" (number->string *gensym-counter*))))))
|
||||
|
||||
(define base:eval slib:eval)
|
||||
(define defmacro:eval base:eval)
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;; define an error procedure for the library
|
||||
(define (slib:error . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(apply error args))
|
||||
|
||||
;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
;;; Support for older versions of Scheme. Not enough code for its own file.
|
||||
(define (last-pair l) (if (pair? (cdr l)) (last-pair (cdr l)) l))
|
||||
(define t #t)
|
||||
(define nil #f)
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
|
||||
(define (1+ n) (+ n 1))
|
||||
(define (-1+ n) (- n 1))
|
||||
(define 1- -1+)
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit (lambda args (exit)))
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define slib:load-source load)
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
|
@ -1,266 +0,0 @@
|
|||
;;"genwrite.scm" generic write used by pretty-print and truncated-print.
|
||||
;; Copyright (c) 1991, Marc Feeley
|
||||
;; Author: Marc Feeley (feeley@iro.umontreal.ca)
|
||||
;; Distribution restrictions: none
|
||||
|
||||
(define genwrite:newline-str (make-string 1 #\newline))
|
||||
|
||||
(define (generic-write obj display? width output)
|
||||
|
||||
(define (read-macro? l)
|
||||
(define (length1? l) (and (pair? l) (null? (cdr l))))
|
||||
(let ((head (car l)) (tail (cdr l)))
|
||||
(case head
|
||||
((quote quasiquote unquote unquote-splicing) (length1? tail))
|
||||
(else #f))))
|
||||
|
||||
(define (read-macro-body l)
|
||||
(cadr l))
|
||||
|
||||
(define (read-macro-prefix l)
|
||||
(let ((head (car l)) (tail (cdr l)))
|
||||
(case head
|
||||
((quote) "'")
|
||||
((quasiquote) "`")
|
||||
((unquote) ",")
|
||||
((unquote-splicing) ",@"))))
|
||||
|
||||
(define (out str col)
|
||||
(and col (output str) (+ col (string-length str))))
|
||||
|
||||
(define (wr obj col)
|
||||
|
||||
(define (wr-expr expr col)
|
||||
(if (read-macro? expr)
|
||||
(wr (read-macro-body expr) (out (read-macro-prefix expr) col))
|
||||
(wr-lst expr col)))
|
||||
|
||||
(define (wr-lst l col)
|
||||
(if (pair? l)
|
||||
(let loop ((l (cdr l))
|
||||
(col (and col (wr (car l) (out "(" col)))))
|
||||
(cond ((not col) col)
|
||||
((pair? l)
|
||||
(loop (cdr l) (wr (car l) (out " " col))))
|
||||
((null? l) (out ")" col))
|
||||
(else (out ")" (wr l (out " . " col))))))
|
||||
(out "()" col)))
|
||||
|
||||
(cond ((pair? obj) (wr-expr obj col))
|
||||
((null? obj) (wr-lst obj col))
|
||||
((vector? obj) (wr-lst (vector->list obj) (out "#" col)))
|
||||
((boolean? obj) (out (if obj "#t" "#f") col))
|
||||
((number? obj) (out (number->string obj) col))
|
||||
((symbol? obj) (out (symbol->string obj) col))
|
||||
((procedure? obj) (out "#[procedure]" col))
|
||||
((string? obj) (if display?
|
||||
(out obj col)
|
||||
(let loop ((i 0) (j 0) (col (out "\"" col)))
|
||||
(if (and col (< j (string-length obj)))
|
||||
(let ((c (string-ref obj j)))
|
||||
(if (or (char=? c #\\)
|
||||
(char=? c #\"))
|
||||
(loop j
|
||||
(+ j 1)
|
||||
(out "\\"
|
||||
(out (substring obj i j)
|
||||
col)))
|
||||
(loop i (+ j 1) col)))
|
||||
(out "\""
|
||||
(out (substring obj i j) col))))))
|
||||
((char? obj) (if display?
|
||||
(out (make-string 1 obj) col)
|
||||
(out (case obj
|
||||
((#\space) "space")
|
||||
((#\newline) "newline")
|
||||
(else (make-string 1 obj)))
|
||||
(out "#\\" col))))
|
||||
((input-port? obj) (out "#[input-port]" col))
|
||||
((output-port? obj) (out "#[output-port]" col))
|
||||
((eof-object? obj) (out "#[eof-object]" col))
|
||||
(else (out "#[unknown]" col))))
|
||||
|
||||
(define (pp obj col)
|
||||
|
||||
(define (spaces n col)
|
||||
(if (> n 0)
|
||||
(if (> n 7)
|
||||
(spaces (- n 8) (out " " col))
|
||||
(out (substring " " 0 n) col))
|
||||
col))
|
||||
|
||||
(define (indent to col)
|
||||
(and col
|
||||
(if (< to col)
|
||||
(and (out genwrite:newline-str col) (spaces to 0))
|
||||
(spaces (- to col) col))))
|
||||
|
||||
(define (pr obj col extra pp-pair)
|
||||
(if (or (pair? obj) (vector? obj)) ; may have to split on multiple lines
|
||||
(let ((result '())
|
||||
(left (min (+ (- (- width col) extra) 1) max-expr-width)))
|
||||
(generic-write obj display? #f
|
||||
(lambda (str)
|
||||
(set! result (cons str result))
|
||||
(set! left (- left (string-length str)))
|
||||
(> left 0)))
|
||||
(if (> left 0) ; all can be printed on one line
|
||||
(out (reverse-string-append result) col)
|
||||
(if (pair? obj)
|
||||
(pp-pair obj col extra)
|
||||
(pp-list (vector->list obj) (out "#" col) extra pp-expr))))
|
||||
(wr obj col)))
|
||||
|
||||
(define (pp-expr expr col extra)
|
||||
(if (read-macro? expr)
|
||||
(pr (read-macro-body expr)
|
||||
(out (read-macro-prefix expr) col)
|
||||
extra
|
||||
pp-expr)
|
||||
(let ((head (car expr)))
|
||||
(if (symbol? head)
|
||||
(let ((proc (style head)))
|
||||
(if proc
|
||||
(proc expr col extra)
|
||||
(if (> (string-length (symbol->string head))
|
||||
max-call-head-width)
|
||||
(pp-general expr col extra #f #f #f pp-expr)
|
||||
(pp-call expr col extra pp-expr))))
|
||||
(pp-list expr col extra pp-expr)))))
|
||||
|
||||
; (head item1
|
||||
; item2
|
||||
; item3)
|
||||
(define (pp-call expr col extra pp-item)
|
||||
(let ((col* (wr (car expr) (out "(" col))))
|
||||
(and col
|
||||
(pp-down (cdr expr) col* (+ col* 1) extra pp-item))))
|
||||
|
||||
; (item1
|
||||
; item2
|
||||
; item3)
|
||||
(define (pp-list l col extra pp-item)
|
||||
(let ((col (out "(" col)))
|
||||
(pp-down l col col extra pp-item)))
|
||||
|
||||
(define (pp-down l col1 col2 extra pp-item)
|
||||
(let loop ((l l) (col col1))
|
||||
(and col
|
||||
(cond ((pair? l)
|
||||
(let ((rest (cdr l)))
|
||||
(let ((extra (if (null? rest) (+ extra 1) 0)))
|
||||
(loop rest
|
||||
(pr (car l) (indent col2 col) extra pp-item)))))
|
||||
((null? l)
|
||||
(out ")" col))
|
||||
(else
|
||||
(out ")"
|
||||
(pr l
|
||||
(indent col2 (out "." (indent col2 col)))
|
||||
(+ extra 1)
|
||||
pp-item)))))))
|
||||
|
||||
(define (pp-general expr col extra named? pp-1 pp-2 pp-3)
|
||||
|
||||
(define (tail1 rest col1 col2 col3)
|
||||
(if (and pp-1 (pair? rest))
|
||||
(let* ((val1 (car rest))
|
||||
(rest (cdr rest))
|
||||
(extra (if (null? rest) (+ extra 1) 0)))
|
||||
(tail2 rest col1 (pr val1 (indent col3 col2) extra pp-1) col3))
|
||||
(tail2 rest col1 col2 col3)))
|
||||
|
||||
(define (tail2 rest col1 col2 col3)
|
||||
(if (and pp-2 (pair? rest))
|
||||
(let* ((val1 (car rest))
|
||||
(rest (cdr rest))
|
||||
(extra (if (null? rest) (+ extra 1) 0)))
|
||||
(tail3 rest col1 (pr val1 (indent col3 col2) extra pp-2)))
|
||||
(tail3 rest col1 col2)))
|
||||
|
||||
(define (tail3 rest col1 col2)
|
||||
(pp-down rest col2 col1 extra pp-3))
|
||||
|
||||
(let* ((head (car expr))
|
||||
(rest (cdr expr))
|
||||
(col* (wr head (out "(" col))))
|
||||
(if (and named? (pair? rest))
|
||||
(let* ((name (car rest))
|
||||
(rest (cdr rest))
|
||||
(col** (wr name (out " " col*))))
|
||||
(tail1 rest (+ col indent-general) col** (+ col** 1)))
|
||||
(tail1 rest (+ col indent-general) col* (+ col* 1)))))
|
||||
|
||||
(define (pp-expr-list l col extra)
|
||||
(pp-list l col extra pp-expr))
|
||||
|
||||
(define (pp-LAMBDA expr col extra)
|
||||
(pp-general expr col extra #f pp-expr-list #f pp-expr))
|
||||
|
||||
(define (pp-IF expr col extra)
|
||||
(pp-general expr col extra #f pp-expr #f pp-expr))
|
||||
|
||||
(define (pp-COND expr col extra)
|
||||
(pp-call expr col extra pp-expr-list))
|
||||
|
||||
(define (pp-CASE expr col extra)
|
||||
(pp-general expr col extra #f pp-expr #f pp-expr-list))
|
||||
|
||||
(define (pp-AND expr col extra)
|
||||
(pp-call expr col extra pp-expr))
|
||||
|
||||
(define (pp-LET expr col extra)
|
||||
(let* ((rest (cdr expr))
|
||||
(named? (and (pair? rest) (symbol? (car rest)))))
|
||||
(pp-general expr col extra named? pp-expr-list #f pp-expr)))
|
||||
|
||||
(define (pp-BEGIN expr col extra)
|
||||
(pp-general expr col extra #f #f #f pp-expr))
|
||||
|
||||
(define (pp-DO expr col extra)
|
||||
(pp-general expr col extra #f pp-expr-list pp-expr-list pp-expr))
|
||||
|
||||
; define formatting style (change these to suit your style)
|
||||
|
||||
(define indent-general 2)
|
||||
|
||||
(define max-call-head-width 5)
|
||||
|
||||
(define max-expr-width 50)
|
||||
|
||||
(define (style head)
|
||||
(case head
|
||||
((lambda let* letrec define) pp-LAMBDA)
|
||||
((if set!) pp-IF)
|
||||
((cond) pp-COND)
|
||||
((case) pp-CASE)
|
||||
((and or) pp-AND)
|
||||
((let) pp-LET)
|
||||
((begin) pp-BEGIN)
|
||||
((do) pp-DO)
|
||||
(else #f)))
|
||||
|
||||
(pr obj col 0 pp-expr))
|
||||
|
||||
(if width
|
||||
(out genwrite:newline-str (pp obj 0))
|
||||
(wr obj 0)))
|
||||
|
||||
; (reverse-string-append l) = (apply string-append (reverse l))
|
||||
|
||||
(define (reverse-string-append l)
|
||||
|
||||
(define (rev-string-append l i)
|
||||
(if (pair? l)
|
||||
(let* ((str (car l))
|
||||
(len (string-length str))
|
||||
(result (rev-string-append (cdr l) (+ i len))))
|
||||
(let loop ((j 0) (k (- (- (string-length result) i) len)))
|
||||
(if (< j len)
|
||||
(begin
|
||||
(string-set! result k (string-ref str j))
|
||||
(loop (+ j 1) (+ k 1)))
|
||||
result)))
|
||||
(make-string i)))
|
||||
|
||||
(rev-string-append l 0))
|
|
@ -1,80 +0,0 @@
|
|||
;;; "getopt.scm" POSIX command argument processing
|
||||
;Copyright (C) 1993, 1994 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(define getopt:scan #f)
|
||||
(define getopt:char #\-)
|
||||
(define getopt:opt #f)
|
||||
(define *optind* 1)
|
||||
(define *optarg* 0)
|
||||
|
||||
(define (getopt argc argv optstring)
|
||||
(let ((opts (string->list optstring))
|
||||
(place #f)
|
||||
(arg #f)
|
||||
(argref (lambda () ((if (vector? argv) vector-ref list-ref)
|
||||
argv *optind*))))
|
||||
(and
|
||||
(cond ((and getopt:scan (not (string=? "" getopt:scan))) #t)
|
||||
((>= *optind* argc) #f)
|
||||
(else
|
||||
(set! arg (argref))
|
||||
(cond ((or (<= (string-length arg) 1)
|
||||
(not (char=? (string-ref arg 0) getopt:char)))
|
||||
#f)
|
||||
((and (= (string-length arg) 2)
|
||||
(char=? (string-ref arg 1) getopt:char))
|
||||
(set! *optind* (+ *optind* 1))
|
||||
#f)
|
||||
(else
|
||||
(set! getopt:scan
|
||||
(substring arg 1 (string-length arg)))
|
||||
#t))))
|
||||
(begin
|
||||
(set! getopt:opt (string-ref getopt:scan 0))
|
||||
(set! getopt:scan
|
||||
(substring getopt:scan 1 (string-length getopt:scan)))
|
||||
(if (string=? "" getopt:scan) (set! *optind* (+ *optind* 1)))
|
||||
(set! place (member getopt:opt opts))
|
||||
(cond ((not place) #\?)
|
||||
((or (null? (cdr place)) (not (char=? #\: (cadr place))))
|
||||
getopt:opt)
|
||||
((not (string=? "" getopt:scan))
|
||||
(set! *optarg* getopt:scan)
|
||||
(set! *optind* (+ *optind* 1))
|
||||
(set! getopt:scan #f)
|
||||
getopt:opt)
|
||||
((< *optind* argc)
|
||||
(set! *optarg* (argref))
|
||||
(set! *optind* (+ *optind* 1))
|
||||
getopt:opt)
|
||||
((and (not (null? opts)) (char=? #\: (car opts))) #\:)
|
||||
(else #\?))))))
|
||||
|
||||
(define (getopt-- argc argv optstring)
|
||||
(let* ((opt (getopt argc argv (string-append optstring "-:")))
|
||||
(optarg *optarg*))
|
||||
(cond ((eqv? #\- opt) ;long option
|
||||
(do ((l (string-length *optarg*))
|
||||
(i 0 (+ 1 i)))
|
||||
((or (>= i l) (char=? #\= (string-ref optarg i)))
|
||||
(cond
|
||||
((>= i l) (set! *optarg* #f) optarg)
|
||||
(else (set! *optarg* (substring optarg (+ 1 i) l))
|
||||
(substring optarg 0 i))))))
|
||||
(else opt))))
|
|
@ -1,213 +0,0 @@
|
|||
;;; "getparam.scm" convert getopt to passing parameters by name.
|
||||
; Copyright 1995, 1996, 1997, 2001 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'getopt)
|
||||
(require 'coerce)
|
||||
|
||||
(define (getopt->parameter-list argc argv optnames arities types aliases
|
||||
. description)
|
||||
(define (can-take-arg? opt)
|
||||
(not (eq? 'boolean (list-ref arities (position opt optnames)))))
|
||||
(let ((progname (list-ref argv (+ -1 *optind*)))
|
||||
(optlist '())
|
||||
(long-opt-list '())
|
||||
(optstring #f)
|
||||
(pos-args '())
|
||||
(parameter-list (make-parameter-list optnames))
|
||||
(curopt '*unclaimed-argument*)
|
||||
(positional? (assv 0 aliases))
|
||||
(unclaimeds '()))
|
||||
(define (adjoin-val val curopt)
|
||||
(define ntyp (list-ref types (position curopt optnames)))
|
||||
(adjoin-parameters! parameter-list
|
||||
(list curopt (case ntyp
|
||||
((expression) val)
|
||||
(else (coerce val ntyp))))))
|
||||
(define (finish)
|
||||
(cond
|
||||
(positional?
|
||||
(set! unclaimeds (reverse unclaimeds))
|
||||
(do ((idx 2 (+ 1 idx))
|
||||
(alias+ (assv 1 aliases) (assv idx aliases))
|
||||
(alias- (assv -1 aliases) (assv (- idx) aliases)))
|
||||
((or (not (or alias+ alias-)) (null? unclaimeds)))
|
||||
(set! unclaimeds (reverse unclaimeds))
|
||||
(cond (alias-
|
||||
(set! curopt (cadr alias-))
|
||||
(adjoin-val (car unclaimeds) curopt)
|
||||
(set! unclaimeds (cdr unclaimeds))))
|
||||
(set! unclaimeds (reverse unclaimeds))
|
||||
(cond ((and alias+ (not (null? unclaimeds)))
|
||||
(set! curopt (cadr alias+))
|
||||
(adjoin-val (car unclaimeds) curopt)
|
||||
(set! unclaimeds (cdr unclaimeds)))))
|
||||
(let ((alias (assv '0 aliases)))
|
||||
(cond (alias
|
||||
(set! curopt (cadr alias))
|
||||
(for-each (lambda (unc) (adjoin-val unc curopt)) unclaimeds)
|
||||
(set! unclaimeds '()))))))
|
||||
(cond ((not (null? unclaimeds))
|
||||
(slib:warn 'getopt->parameter-list 'arguments 'unclaimed unclaimeds)
|
||||
(apply parameter-list->getopt-usage
|
||||
progname optnames arities types aliases description))
|
||||
(else parameter-list)))
|
||||
(set! aliases
|
||||
(map (lambda (alias)
|
||||
(cond ((string? (car alias))
|
||||
(let ((str (string-copy (car alias))))
|
||||
(do ((i (+ -1 (string-length str)) (+ -1 i)))
|
||||
((negative? i) (cons str (cdr alias)))
|
||||
(cond ((char=? #\ (string-ref str i))
|
||||
(string-set! str i #\-))))))
|
||||
((number? (car alias))
|
||||
(set! positional? (car alias))
|
||||
alias)
|
||||
(else alias)))
|
||||
aliases))
|
||||
(for-each
|
||||
(lambda (alias)
|
||||
(define opt (car alias))
|
||||
(cond ((number? opt) (set! pos-args (cons opt pos-args)))
|
||||
((not (string? opt)))
|
||||
((< 1 (string-length opt))
|
||||
(set! long-opt-list (cons opt long-opt-list)))
|
||||
((not (= 1 (string-length opt))))
|
||||
((can-take-arg? (cadr alias))
|
||||
(set! optlist (cons (string-ref opt 0) (cons #\: optlist))))
|
||||
(else (set! optlist (cons (string-ref opt 0) optlist)))))
|
||||
aliases)
|
||||
(set! optstring (list->string (cons #\: optlist)))
|
||||
(let loop ()
|
||||
(let ((opt (getopt-- argc argv optstring)))
|
||||
(case opt
|
||||
((#\: #\?)
|
||||
(slib:warn 'getopt->parameter-list
|
||||
(case opt
|
||||
((#\:) "argument missing after")
|
||||
((#\?) "unrecognized option"))
|
||||
(string #\- getopt:opt))
|
||||
(apply parameter-list->getopt-usage
|
||||
progname optnames arities types aliases description))
|
||||
((#f)
|
||||
(cond ((and (< *optind* argc)
|
||||
(string=? "-" (list-ref argv *optind*)))
|
||||
(set! *optind* (+ 1 *optind*))
|
||||
(finish))
|
||||
((< *optind* argc)
|
||||
(let ((topt (assoc curopt aliases)))
|
||||
(if topt (set! curopt (cadr topt)))
|
||||
(cond
|
||||
((and positional? (not topt))
|
||||
(set! unclaimeds
|
||||
(cons (list-ref argv *optind*) unclaimeds))
|
||||
(set! *optind* (+ 1 *optind*)) (loop))
|
||||
((and (member curopt optnames)
|
||||
(adjoin-val (list-ref argv *optind*) curopt))
|
||||
(set! *optind* (+ 1 *optind*)) (loop))
|
||||
(else (slib:error 'getopt->parameter-list curopt
|
||||
(list-ref argv *optind*)
|
||||
'not 'supported)))))
|
||||
(else (finish))))
|
||||
(else
|
||||
(cond ((char? opt) (set! opt (string opt))))
|
||||
(let ((topt (assoc opt aliases)))
|
||||
(if topt (set! topt (cadr topt)))
|
||||
(cond
|
||||
((not topt)
|
||||
(slib:warn "Option not recognized -" opt)
|
||||
(apply parameter-list->getopt-usage
|
||||
progname optnames arities types aliases description))
|
||||
((not (can-take-arg? topt))
|
||||
(adjoin-parameters! parameter-list (list topt #t))
|
||||
(loop))
|
||||
(*optarg* (set! curopt topt) (adjoin-val *optarg* curopt) (loop))
|
||||
(else
|
||||
;;; (slib:warn 'getopt->parameter-list "= missing for option--" opt)
|
||||
(set! curopt topt) (loop))))))))))
|
||||
|
||||
(define (parameter-list->getopt-usage comname optnames arities types aliases
|
||||
. description)
|
||||
(require 'printf)
|
||||
(require 'common-list-functions)
|
||||
(let ((aliast (map list optnames))
|
||||
(strlen=1? (lambda (s) (= 1 (string-length s))))
|
||||
(cep (current-error-port)))
|
||||
(for-each (lambda (alias)
|
||||
(let ((apr (assq (cadr alias) aliast)))
|
||||
(set-cdr! apr (cons (car alias) (cdr apr)))))
|
||||
aliases)
|
||||
(fprintf cep "Usage: %s [OPTION ARGUMENT ...] ..." comname)
|
||||
(do ((pos+ '()) (pos- '())
|
||||
(idx 2 (+ 1 idx))
|
||||
(alias+ (assv 1 aliases) (assv idx aliases))
|
||||
(alias- (assv -1 aliases) (assv (- idx) aliases)))
|
||||
((not (or alias+ alias-))
|
||||
(for-each (lambda (alias) (fprintf cep " <%s>" (cadr alias)))
|
||||
(reverse pos+))
|
||||
(let ((alias (assv 0 aliases)))
|
||||
(if alias (fprintf cep " <%s> ..." (cadr alias))))
|
||||
(for-each (lambda (alias) (fprintf cep " <%s>" (cadr alias)))
|
||||
pos-))
|
||||
(cond (alias- (set! pos- (cons alias- pos-))))
|
||||
(cond (alias+ (set! pos+ (cons alias+ pos+)))))
|
||||
(fprintf cep "\\n\\n")
|
||||
(for-each
|
||||
(lambda (optname arity aliat)
|
||||
(let loop ((initials (remove-if-not strlen=1? (remove-if number? (cdr aliat))))
|
||||
(longname (remove-if strlen=1? (remove-if number? (cdr aliat)))))
|
||||
(cond ((and (null? initials) (null? longname)))
|
||||
(else (fprintf cep
|
||||
(case arity
|
||||
((boolean) " %3s %s\\n")
|
||||
(else " %3s %s<%s> %s\\n"))
|
||||
(if (null? initials)
|
||||
""
|
||||
(string-append "-" (car initials)
|
||||
(if (null? longname) " " ",")))
|
||||
(if (null? longname)
|
||||
" "
|
||||
(string-append "--" (car longname)
|
||||
(case arity
|
||||
((boolean) " ")
|
||||
(else "="))))
|
||||
(case arity
|
||||
((boolean) "")
|
||||
(else optname))
|
||||
(case arity
|
||||
((nary nary1) "...")
|
||||
(else "")))
|
||||
(loop (if (null? initials) '() (cdr initials))
|
||||
(if (null? longname) '() (cdr longname)))))))
|
||||
optnames arities aliast)
|
||||
(for-each (lambda (desc) (fprintf cep " %s\\n" desc)) description))
|
||||
#f)
|
||||
|
||||
(define (getopt->arglist argc argv optnames positions
|
||||
arities types defaulters checks aliases . description)
|
||||
(define progname (list-ref argv (+ -1 *optind*)))
|
||||
(let* ((params (apply getopt->parameter-list
|
||||
argc argv optnames arities types aliases description))
|
||||
(fparams (and params (fill-empty-parameters defaulters params))))
|
||||
(cond ((and (list? params)
|
||||
(check-parameters checks fparams)
|
||||
(parameter-list->arglist positions arities fparams)))
|
||||
(params (apply parameter-list->getopt-usage
|
||||
progname optnames arities types aliases description))
|
||||
(else #f))))
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
;;; "glob.scm" String matching for filenames (a la BASH).
|
||||
;;; Copyright (C) 1998 Radey Shouman.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;$Header: /home/ludo/src/guile/gitification/guile-cvs/guile/guile/guile-vm/module/slib/glob.scm,v 1.1 2001/04/14 11:24:45 kei Exp $
|
||||
;;$Name: $
|
||||
|
||||
(define (glob:pattern->tokens pat)
|
||||
(cond
|
||||
((string? pat)
|
||||
(let loop ((i 0)
|
||||
(toks '()))
|
||||
(if (>= i (string-length pat))
|
||||
(reverse toks)
|
||||
(let ((pch (string-ref pat i)))
|
||||
(case pch
|
||||
((#\? #\*)
|
||||
(loop (+ i 1)
|
||||
(cons (substring pat i (+ i 1)) toks)))
|
||||
((#\[)
|
||||
(let ((j
|
||||
(let search ((j (+ i 2)))
|
||||
(cond
|
||||
((>= j (string-length pat))
|
||||
(slib:error 'glob:make-matcher
|
||||
"unmatched [" pat))
|
||||
((char=? #\] (string-ref pat j))
|
||||
(if (and (< (+ j 1) (string-length pat))
|
||||
(char=? #\] (string-ref pat (+ j 1))))
|
||||
(+ j 1)
|
||||
j))
|
||||
(else (search (+ j 1)))))))
|
||||
(loop (+ j 1) (cons (substring pat i (+ j 1)) toks))))
|
||||
(else
|
||||
(let search ((j (+ i 1)))
|
||||
(cond ((= j (string-length pat))
|
||||
(loop j (cons (substring pat i j) toks)))
|
||||
((memv (string-ref pat j) '(#\? #\* #\[))
|
||||
(loop j (cons (substring pat i j) toks)))
|
||||
(else (search (+ j 1)))))))))))
|
||||
((pair? pat)
|
||||
(for-each (lambda (elt) (or (string? elt)
|
||||
(slib:error 'glob:pattern->tokens
|
||||
"bad pattern" pat)))
|
||||
pat)
|
||||
pat)
|
||||
(else (slib:error 'glob:pattern->tokens "bad pattern" pat))))
|
||||
|
||||
(define (glob:make-matcher pat ch=? ch<=?)
|
||||
(define (match-end str k kmatch)
|
||||
(and (= k (string-length str)) (reverse (cons k kmatch))))
|
||||
(define (match-str pstr nxt)
|
||||
(let ((plen (string-length pstr)))
|
||||
(lambda (str k kmatch)
|
||||
(and (<= (+ k plen) (string-length str))
|
||||
(let loop ((i 0))
|
||||
(cond ((= i plen)
|
||||
(nxt str (+ k plen) (cons k kmatch)))
|
||||
((ch=? (string-ref pstr i)
|
||||
(string-ref str (+ k i)))
|
||||
(loop (+ i 1)))
|
||||
(else #f)))))))
|
||||
(define (match-? nxt)
|
||||
(lambda (str k kmatch)
|
||||
(and (< k (string-length str))
|
||||
(nxt str (+ k 1) (cons k kmatch)))))
|
||||
(define (match-set1 chrs)
|
||||
(let recur ((i 0))
|
||||
(cond ((= i (string-length chrs))
|
||||
(lambda (ch) #f))
|
||||
((and (< (+ i 2) (string-length chrs))
|
||||
(char=? #\- (string-ref chrs (+ i 1))))
|
||||
(let ((nxt (recur (+ i 3))))
|
||||
(lambda (ch)
|
||||
(or (and (ch<=? ch (string-ref chrs (+ i 2)))
|
||||
(ch<=? (string-ref chrs i) ch))
|
||||
(nxt ch)))))
|
||||
(else
|
||||
(let ((nxt (recur (+ i 1)))
|
||||
(chrsi (string-ref chrs i)))
|
||||
(lambda (ch)
|
||||
(or (ch=? chrsi ch) (nxt ch))))))))
|
||||
(define (match-set tok nxt)
|
||||
(let ((chrs (substring tok 1 (- (string-length tok) 1))))
|
||||
(if (and (positive? (string-length chrs))
|
||||
(memv (string-ref chrs 0) '(#\^ #\!)))
|
||||
(let ((pred (match-set1 (substring chrs 1 (string-length chrs)))))
|
||||
(lambda (str k kmatch)
|
||||
(and (< k (string-length str))
|
||||
(not (pred (string-ref str k)))
|
||||
(nxt str (+ k 1) (cons k kmatch)))))
|
||||
(let ((pred (match-set1 chrs)))
|
||||
(lambda (str k kmatch)
|
||||
(and (< k (string-length str))
|
||||
(pred (string-ref str k))
|
||||
(nxt str (+ k 1) (cons k kmatch))))))))
|
||||
(define (match-* nxt)
|
||||
(lambda (str k kmatch)
|
||||
(let ((kmatch (cons k kmatch)))
|
||||
(let loop ((kk (string-length str)))
|
||||
(and (>= kk k)
|
||||
(or (nxt str kk kmatch)
|
||||
(loop (- kk 1))))))))
|
||||
|
||||
(let ((matcher
|
||||
(let recur ((toks (glob:pattern->tokens pat)))
|
||||
(if (null? toks)
|
||||
match-end
|
||||
(let ((pch (or (string=? (car toks) "")
|
||||
(string-ref (car toks) 0))))
|
||||
(case pch
|
||||
((#\?) (match-? (recur (cdr toks))))
|
||||
((#\*) (match-* (recur (cdr toks))))
|
||||
((#\[) (match-set (car toks) (recur (cdr toks))))
|
||||
(else (match-str (car toks) (recur (cdr toks))))))))))
|
||||
(lambda (str) (matcher str 0 '()))))
|
||||
|
||||
(define (glob:caller-with-matches pat proc ch=? ch<=?)
|
||||
(define (glob:wildcard? pat)
|
||||
(cond ((string=? pat "") #f)
|
||||
((memv (string-ref pat 0) '(#\* #\? #\[)) #t)
|
||||
(else #f)))
|
||||
(let* ((toks (glob:pattern->tokens pat))
|
||||
(wild? (map glob:wildcard? toks))
|
||||
(matcher (glob:make-matcher toks ch=? ch<=?)))
|
||||
(lambda (str)
|
||||
(let loop ((inds (matcher str))
|
||||
(wild? wild?)
|
||||
(res '()))
|
||||
(cond ((not inds) #f)
|
||||
((null? wild?)
|
||||
(apply proc (reverse res)))
|
||||
((car wild?)
|
||||
(loop (cdr inds)
|
||||
(cdr wild?)
|
||||
(cons (substring str (car inds) (cadr inds)) res)))
|
||||
(else
|
||||
(loop (cdr inds) (cdr wild?) res)))))))
|
||||
|
||||
(define (glob:make-substituter pattern template ch=? ch<=?)
|
||||
(define (wildcard? pat)
|
||||
(cond ((string=? pat "") #f)
|
||||
((memv (string-ref pat 0) '(#\* #\? #\[)) #t)
|
||||
(else #f)))
|
||||
(define (countq val lst)
|
||||
(do ((lst lst (cdr lst))
|
||||
(c 0 (if (eq? val (car lst)) (+ c 1) c)))
|
||||
((null? lst) c)))
|
||||
(let ((tmpl-literals (map (lambda (tok)
|
||||
(if (wildcard? tok) #f tok))
|
||||
(glob:pattern->tokens template)))
|
||||
(pat-wild? (map wildcard? (glob:pattern->tokens pattern)))
|
||||
(matcher (glob:make-matcher pattern ch=? ch<=?)))
|
||||
(or (= (countq #t pat-wild?) (countq #f tmpl-literals))
|
||||
(slib:error 'glob:make-substituter
|
||||
"number of wildcards doesn't match" pattern template))
|
||||
(lambda (str)
|
||||
(let ((indices (matcher str)))
|
||||
(and indices
|
||||
(let loop ((inds indices)
|
||||
(wild? pat-wild?)
|
||||
(lits tmpl-literals)
|
||||
(res '()))
|
||||
(cond
|
||||
((null? lits)
|
||||
(apply string-append (reverse res)))
|
||||
((car lits)
|
||||
(loop inds wild? (cdr lits) (cons (car lits) res)))
|
||||
((null? wild?) ;this should never happen.
|
||||
(loop '() '() lits res))
|
||||
((car wild?)
|
||||
(loop (cdr inds) (cdr wild?) (cdr lits)
|
||||
(cons (substring str (car inds) (cadr inds))
|
||||
res)))
|
||||
(else
|
||||
(loop (cdr inds) (cdr wild?) lits res)))))))))
|
||||
|
||||
|
||||
(define (glob:match?? pat)
|
||||
(glob:make-matcher pat char=? char<=?))
|
||||
(define (glob:match-ci?? pat)
|
||||
(glob:make-matcher pat char-ci=? char-ci<=?))
|
||||
(define filename:match?? glob:match??)
|
||||
(define filename:match-ci?? glob:match-ci??)
|
||||
|
||||
(define (glob:substitute?? pat templ)
|
||||
(cond ((procedure? templ)
|
||||
(glob:caller-with-matches pat templ char=? char<=?))
|
||||
((string? templ)
|
||||
(glob:make-substituter pat templ char=? char<=?))
|
||||
(else
|
||||
(slib:error 'glob:substitute "bad second argument" templ))))
|
||||
(define (glob:substitute-ci?? pat templ)
|
||||
(cond ((procedure? templ)
|
||||
(glob:caller-with-matches pat templ char-ci=? char-ci<=?))
|
||||
((string? templ)
|
||||
(glob:make-substituter pat templ char-ci=? char-ci<=?))
|
||||
(else
|
||||
(slib:error 'glob:substitute "bad second argument" templ))))
|
||||
(define filename:substitute?? glob:substitute??)
|
||||
(define filename:substitute-ci?? glob:substitute-ci??)
|
||||
|
||||
(define (replace-suffix str old new)
|
||||
(let* ((f (glob:make-substituter (list "*" old) (list "*" new)
|
||||
char=? char<=?))
|
||||
(g (lambda (st)
|
||||
(or (f st)
|
||||
(slib:error 'replace-suffix "suffix doesn't match:"
|
||||
old st)))))
|
||||
(if (pair? str)
|
||||
(map g str)
|
||||
(g str))))
|
|
@ -1,232 +0,0 @@
|
|||
;;; "guile.init" configuration template of *features* for Scheme -*-scheme-*-
|
||||
;;; Author: Aubrey Jaffer
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
;;; UNIX, VMS, MACOS, AMIGA and MS-DOS are supported.
|
||||
|
||||
(define (software-type) 'UNIX)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'Guile)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page) "http://www.gnu.org/software/guile/")
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define scheme-implementation-version version)
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define implementation-vicinity
|
||||
(let ((path (string-append (%package-data-dir) "/")))
|
||||
(lambda () path)))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(or
|
||||
;; Use this getenv if your implementation supports it.
|
||||
(getenv "SCHEME_LIBRARY_PATH")
|
||||
;; Use this path if your scheme does not support GETENV
|
||||
;; or if SCHEME_LIBRARY_PATH is not set.
|
||||
(let ((this-file (port-filename (current-load-port))))
|
||||
(substring this-file 0 (- (string-length this-file) 10))))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define home-vicinity
|
||||
(let ((home-path (getenv "HOME")))
|
||||
(lambda () home-path)))
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
rev4-report ;conforms to
|
||||
rev3-report ;conforms to
|
||||
ieee-p1178 ;conforms to
|
||||
; sicp ;runs code from Structure and
|
||||
;Interpretation of Computer
|
||||
;Programs by Abelson and Sussman.
|
||||
rev4-optional-procedures ;LIST-TAIL, STRING->LIST,
|
||||
;LIST->STRING, STRING-COPY,
|
||||
;STRING-FILL!, LIST->VECTOR,
|
||||
;VECTOR->LIST, and VECTOR-FILL!
|
||||
rev2-procedures ;SUBSTRING-MOVE-LEFT!,
|
||||
;SUBSTRING-MOVE-RIGHT!,
|
||||
;SUBSTRING-FILL!,
|
||||
;STRING-NULL?, APPEND!, 1+,
|
||||
;-1+, <?, <=?, =?, >?, >=?
|
||||
multiarg/and- ;/ and - can take more than 2 args.
|
||||
multiarg-apply ;APPLY can take more than 2 args.
|
||||
; rationalize
|
||||
delay ;has DELAY and FORCE
|
||||
with-file ;has WITH-INPUT-FROM-FILE and
|
||||
;WITH-OUTPUT-FROM-FILE
|
||||
string-port ;has CALL-WITH-INPUT-STRING and
|
||||
;CALL-WITH-OUTPUT-STRING
|
||||
; transcript ;TRANSCRIPT-ON and TRANSCRIPT-OFF
|
||||
char-ready?
|
||||
; macro ;has R4RS high level macros
|
||||
; macro-by-example
|
||||
defmacro ;has Common Lisp DEFMACRO
|
||||
eval ;R5RS two-argument eval
|
||||
record ;has user defined data structures
|
||||
values ;proposed multiple values
|
||||
dynamic-wind ;proposed dynamic-wind
|
||||
ieee-floating-point ;conforms to
|
||||
full-continuation ;can return multiple times
|
||||
; object-hash ;has OBJECT-HASH
|
||||
|
||||
sort
|
||||
; queue ;queues
|
||||
; pretty-print
|
||||
object->string
|
||||
; format
|
||||
; trace ;has macros: TRACE and UNTRACE
|
||||
; compiler ;has (COMPILER)
|
||||
; ed ;(ED) is editor
|
||||
system ;posix (system <string>)
|
||||
getenv ;posix (getenv <string>)
|
||||
program-arguments ;returns list of strings (argv)
|
||||
; Xwindows ;X support
|
||||
; curses ;screen management package
|
||||
; termcap ;terminal description package
|
||||
; terminfo ;sysV terminal description
|
||||
current-time ;returns time in seconds since 1/1/1970
|
||||
|
||||
abort
|
||||
array
|
||||
array-for-each
|
||||
random
|
||||
hash
|
||||
hash-table
|
||||
line-i/o
|
||||
logical
|
||||
promise
|
||||
string-case
|
||||
; syntax-case
|
||||
))
|
||||
|
||||
;; time
|
||||
(define difftime -)
|
||||
(define offset-time +)
|
||||
|
||||
;; random
|
||||
(define (make-random-state . args)
|
||||
(let ((seed (if (null? args) *random-state* (car args))))
|
||||
(cond ((string? seed))
|
||||
((number? seed) (set! seed (number->string seed)))
|
||||
(else (let ()
|
||||
(require 'object->string)
|
||||
(set! seed (object->limited-string seed 50)))))
|
||||
(seed->random-state seed)))
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; "rationalize" adjunct procedures.
|
||||
;;(define (find-ratio x e)
|
||||
;; (let ((rat (rationalize x e)))
|
||||
;; (list (numerator rat) (denominator rat))))
|
||||
;;(define (find-ratio-between x y)
|
||||
;; (find-ratio (/ (+ x y) 2) (/ (- x y) 2)))
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
(define (slib:eval x)
|
||||
(eval x (interaction-environment)))
|
||||
|
||||
(define base:eval slib:eval)
|
||||
(define (defmacro:eval x) (base:eval (defmacro:expand* x)))
|
||||
(define (defmacro:expand* x)
|
||||
(require 'defmacroexpand) (apply defmacro:expand* x '()))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;;; define an error procedure for the library
|
||||
(define (slib:error . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(apply error args))
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
;;; Support for older versions of Scheme. Not enough code for its own file.
|
||||
(define t #t)
|
||||
(define nil #f)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit quit)
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define (slib:load-source f) (load (string-append f (scheme-file-suffix))))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define (slib:load-compiled f) (load-compiled-file (string-append f ".go")))
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load)
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
|
@ -1,153 +0,0 @@
|
|||
; "hash.scm", hashing functions for Scheme.
|
||||
; Copyright (c) 1992, 1993, 1995 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(define (hash:hash-char-ci char n)
|
||||
(modulo (char->integer (char-downcase char)) n))
|
||||
|
||||
(define hash:hash-char hash:hash-char-ci)
|
||||
|
||||
(define (hash:hash-symbol sym n)
|
||||
(hash:hash-string (symbol->string sym) n))
|
||||
|
||||
;;; This can overflow on implemenatations where inexacts have a larger
|
||||
;;; range than exact integers.
|
||||
(define hash:hash-number
|
||||
(if (provided? 'inexact)
|
||||
(lambda (num n)
|
||||
(if (integer? num)
|
||||
(modulo (if (exact? num) num (inexact->exact num)) n)
|
||||
(hash:hash-string-ci
|
||||
(number->string (if (exact? num) (exact->inexact num) num))
|
||||
n)))
|
||||
(lambda (num n)
|
||||
(if (integer? num)
|
||||
(modulo num n)
|
||||
(hash:hash-string-ci (number->string num) n)))))
|
||||
|
||||
(define (hash:hash-string-ci str n)
|
||||
(let ((len (string-length str)))
|
||||
(if (> len 5)
|
||||
(let loop ((h (modulo 264 n)) (i 5))
|
||||
(if (positive? i)
|
||||
(loop (modulo (+ (* h 256)
|
||||
(char->integer
|
||||
(char-downcase
|
||||
(string-ref str (modulo h len)))))
|
||||
n)
|
||||
(- i 1))
|
||||
h))
|
||||
(let loop ((h 0) (i (- len 1)))
|
||||
(if (>= i 0)
|
||||
(loop (modulo (+ (* h 256)
|
||||
(char->integer
|
||||
(char-downcase (string-ref str i))))
|
||||
n)
|
||||
(- i 1))
|
||||
h)))))
|
||||
|
||||
(define hash:hash-string hash:hash-string-ci)
|
||||
|
||||
(define (hash:hash obj n)
|
||||
(let hs ((d 10) (obj obj))
|
||||
(cond
|
||||
((number? obj) (hash:hash-number obj n))
|
||||
((char? obj) (modulo (char->integer (char-downcase obj)) n))
|
||||
((symbol? obj) (hash:hash-symbol obj n))
|
||||
((string? obj) (hash:hash-string obj n))
|
||||
((vector? obj)
|
||||
(let ((len (vector-length obj)))
|
||||
(if (> len 5)
|
||||
(let lp ((h 1) (i (quotient d 2)))
|
||||
(if (positive? i)
|
||||
(lp (modulo (+ (* h 256)
|
||||
(hs 2 (vector-ref obj (modulo h len))))
|
||||
n)
|
||||
(- i 1))
|
||||
h))
|
||||
(let loop ((h (- n 1)) (i (- len 1)))
|
||||
(if (>= i 0)
|
||||
(loop (modulo (+ (* h 256) (hs (quotient d len)
|
||||
(vector-ref obj i)))
|
||||
n)
|
||||
(- i 1))
|
||||
h)))))
|
||||
((pair? obj)
|
||||
(if (positive? d) (modulo (+ (hs (quotient d 2) (car obj))
|
||||
(hs (quotient d 2) (cdr obj)))
|
||||
n)
|
||||
1))
|
||||
(else
|
||||
(modulo
|
||||
(cond
|
||||
((null? obj) 256)
|
||||
((boolean? obj) (if obj 257 258))
|
||||
((eof-object? obj) 259)
|
||||
((input-port? obj) 260)
|
||||
((output-port? obj) 261)
|
||||
((procedure? obj) 262)
|
||||
((and (provided? 'RECORD) (record? obj))
|
||||
(let* ((rtd (record-type-descriptor obj))
|
||||
(fns (record-type-field-names rtd))
|
||||
(len (length fns)))
|
||||
(if (> len 5)
|
||||
(let lp ((h (modulo 266 n)) (i (quotient d 2)))
|
||||
(if (positive? i)
|
||||
(lp (modulo
|
||||
(+ (* h 256)
|
||||
(hs 2 ((record-accessor
|
||||
rtd (list-ref fns (modulo h len)))
|
||||
obj)))
|
||||
n)
|
||||
(- i 1))
|
||||
h))
|
||||
(let loop ((h (- n 1)) (i (- len 1)))
|
||||
(if (>= i 0)
|
||||
(loop (modulo
|
||||
(+ (* h 256)
|
||||
(hs (quotient d len)
|
||||
((record-accessor
|
||||
rtd (list-ref fns (modulo h len)))
|
||||
obj)))
|
||||
n)
|
||||
(- i 1))
|
||||
h)))))
|
||||
(else 263))
|
||||
n)))))
|
||||
|
||||
(define hash hash:hash)
|
||||
(define hashv hash:hash)
|
||||
|
||||
;;; Object-hash is somewhat expensive on copying GC systems (like
|
||||
;;; PC-Scheme and MITScheme). We use it only on strings, pairs,
|
||||
;;; vectors, and records. This also allows us to use it for both
|
||||
;;; hashq and hashv.
|
||||
|
||||
(if (provided? 'object-hash)
|
||||
(set! hashv
|
||||
(if (provided? 'record)
|
||||
(lambda (obj k)
|
||||
(if (or (string? obj) (pair? obj) (vector? obj) (record? obj))
|
||||
(modulo (object-hash obj) k)
|
||||
(hash:hash obj k)))
|
||||
(lambda (obj k)
|
||||
(if (or (string? obj) (pair? obj) (vector? obj))
|
||||
(modulo (object-hash obj) k)
|
||||
(hash:hash obj k))))))
|
||||
|
||||
(define hashq hashv)
|
|
@ -1,79 +0,0 @@
|
|||
; "hashtab.scm", hash tables for Scheme.
|
||||
; Copyright (c) 1992, 1993 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'hash)
|
||||
(require 'alist)
|
||||
|
||||
(define (predicate->hash pred)
|
||||
(cond ((eq? pred eq?) hashq)
|
||||
((eq? pred eqv?) hashv)
|
||||
((eq? pred equal?) hash)
|
||||
((eq? pred =) hashv)
|
||||
((eq? pred char=?) hashv)
|
||||
((eq? pred char-ci=?) hashv)
|
||||
((eq? pred string=?) hash)
|
||||
((eq? pred string-ci=?) hash)
|
||||
(else (slib:error "unknown predicate for hash" pred))))
|
||||
|
||||
(define (make-hash-table k) (make-vector k '()))
|
||||
|
||||
(define (predicate->hash-asso pred)
|
||||
(let ((hashfun (predicate->hash pred))
|
||||
(asso (predicate->asso pred)))
|
||||
(lambda (key hashtab)
|
||||
(asso key
|
||||
(vector-ref hashtab (hashfun key (vector-length hashtab)))))))
|
||||
|
||||
(define (hash-inquirer pred)
|
||||
(let ((hashfun (predicate->hash pred))
|
||||
(ainq (alist-inquirer pred)))
|
||||
(lambda (hashtab key)
|
||||
(ainq (vector-ref hashtab (hashfun key (vector-length hashtab)))
|
||||
key))))
|
||||
|
||||
(define (hash-associator pred)
|
||||
(let ((hashfun (predicate->hash pred))
|
||||
(asso (alist-associator pred)))
|
||||
(lambda (hashtab key val)
|
||||
(let* ((num (hashfun key (vector-length hashtab))))
|
||||
(vector-set! hashtab num
|
||||
(asso (vector-ref hashtab num) key val)))
|
||||
hashtab)))
|
||||
|
||||
(define (hash-remover pred)
|
||||
(let ((hashfun (predicate->hash pred))
|
||||
(arem (alist-remover pred)))
|
||||
(lambda (hashtab key)
|
||||
(let* ((num (hashfun key (vector-length hashtab))))
|
||||
(vector-set! hashtab num
|
||||
(arem (vector-ref hashtab num) key)))
|
||||
hashtab)))
|
||||
|
||||
(define (hash-map proc ht)
|
||||
(define nht (make-vector (vector-length ht)))
|
||||
(do ((i (+ -1 (vector-length ht)) (+ -1 i)))
|
||||
((negative? i) nht)
|
||||
(vector-set!
|
||||
nht i
|
||||
(alist-map proc (vector-ref ht i)))))
|
||||
|
||||
(define (hash-for-each proc ht)
|
||||
(do ((i (+ -1 (vector-length ht)) (+ -1 i)))
|
||||
((negative? i))
|
||||
(alist-for-each proc (vector-ref ht i))))
|
|
@ -1,448 +0,0 @@
|
|||
;;; "htmlform.scm" Generate HTML 2.0 forms. -*-scheme-*-
|
||||
; Copyright 1997, 1998, 2000, 2001 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'sort)
|
||||
(require 'printf)
|
||||
(require 'parameters)
|
||||
(require 'object->string)
|
||||
(require 'string-search)
|
||||
(require 'database-utilities)
|
||||
(require 'common-list-functions)
|
||||
|
||||
;;;;@code{(require 'html-form)}
|
||||
(define html:blank (string->symbol ""))
|
||||
|
||||
;;@body Returns a string with character substitutions appropriate to
|
||||
;;send @1 as an @dfn{attribute-value}.
|
||||
(define (html:atval txt) ; attribute-value
|
||||
(if (symbol? txt) (set! txt (symbol->string txt)))
|
||||
(if (number? txt)
|
||||
(number->string txt)
|
||||
(string-subst (if (string? txt) txt (object->string txt))
|
||||
"&" "&"
|
||||
"\"" """
|
||||
"<" "<"
|
||||
">" ">")))
|
||||
|
||||
;;@body Returns a string with character substitutions appropriate to
|
||||
;;send @1 as an @dfn{plain-text}.
|
||||
(define (html:plain txt) ; plain-text `Data Characters'
|
||||
(cond ((eq? html:blank txt) " ")
|
||||
(else
|
||||
(if (symbol? txt) (set! txt (symbol->string txt)))
|
||||
(if (number? txt)
|
||||
(number->string txt)
|
||||
(string-subst (if (string? txt) txt (object->string txt))
|
||||
"&" "&"
|
||||
"<" "<"
|
||||
">" ">")))))
|
||||
|
||||
;;@body Returns a tag of meta-information suitable for passing as the
|
||||
;;third argument to @code{html:head}. The tag produced is @samp{<META
|
||||
;;NAME="@1" CONTENT="@2">}. The string or symbol @1 can be
|
||||
;;@samp{author}, @samp{copyright}, @samp{keywords}, @samp{description},
|
||||
;;@samp{date}, @samp{robots}, @dots{}.
|
||||
(define (html:meta name content)
|
||||
(sprintf #f "\n<META NAME=\"%s\" CONTENT=\"%s\">" name (html:atval content)))
|
||||
|
||||
;;@body Returns a tag of HTTP information suitable for passing as the
|
||||
;;third argument to @code{html:head}. The tag produced is @samp{<META
|
||||
;;HTTP-EQUIV="@1" CONTENT="@2">}. The string or symbol @1 can be
|
||||
;;@samp{Expires}, @samp{PICS-Label}, @samp{Content-Type},
|
||||
;;@samp{Refresh}, @dots{}.
|
||||
(define (html:http-equiv name content)
|
||||
(sprintf #f "\n<META HTTP-EQUIV=\"%s\" CONTENT=\"%s\">"
|
||||
name (html:atval content)))
|
||||
|
||||
;;@args delay uri
|
||||
;;@args delay
|
||||
;;
|
||||
;;Returns a tag suitable for passing as the third argument to
|
||||
;;@code{html:head}. If @2 argument is supplied, then @1 seconds after
|
||||
;;displaying the page with this tag, Netscape or IE browsers will fetch
|
||||
;;and display @2. Otherwise, @1 seconds after displaying the page with
|
||||
;;this tag, Netscape or IE browsers will fetch and redisplay this page.
|
||||
(define (html:meta-refresh delay . uri)
|
||||
(if (null? uri)
|
||||
(sprintf #f "\n<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d\">" delay)
|
||||
(sprintf #f "\n<META HTTP-EQUIV=\"Refresh\" CONTENT=\"%d;URL=%s\">"
|
||||
delay (car uri))))
|
||||
|
||||
;;@args title backlink tags ...
|
||||
;;@args title backlink
|
||||
;;@args title
|
||||
;;
|
||||
;;Returns header string for an HTML page named @1. If @2 is a string,
|
||||
;;it is used verbatim between the @samp{H1} tags; otherwise @1 is
|
||||
;;used. If string arguments @3 ... are supplied, then they are
|
||||
;;included verbatim within the @t{<HEAD>} section.
|
||||
(define (html:head title . args)
|
||||
(define backlink (if (null? args) #f (car args)))
|
||||
(if (not (null? args)) (set! args (cdr args)))
|
||||
(string-append
|
||||
(sprintf #f "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\\n")
|
||||
(sprintf #f "<HTML>\\n")
|
||||
(sprintf #f "%s"
|
||||
(html:comment "HTML by SLIB"
|
||||
"http://swissnet.ai.mit.edu/~jaffer/SLIB.html"))
|
||||
(sprintf #f " <HEAD>\\n <TITLE>%s</TITLE>\\n %s\\n </HEAD>\\n"
|
||||
(html:plain title) (apply string-append args))
|
||||
(sprintf #f "<BODY><H1>%s</H1>\\n" (or backlink (html:plain title)))))
|
||||
|
||||
;;@body Returns HTML string to end a page.
|
||||
(define (html:body . body)
|
||||
(apply string-append
|
||||
(append body (list (sprintf #f "</BODY>\\n</HTML>\\n")))))
|
||||
|
||||
;;@body Returns the strings @1, @2 as @dfn{PRE}formmated plain text
|
||||
;;(rendered in fixed-width font). Newlines are inserted between @1,
|
||||
;;@2. HTML tags (@samp{<tag>}) within @2 will be visible verbatim.
|
||||
(define (html:pre line1 . lines)
|
||||
(sprintf #f "<PRE>\\n%s%s</PRE>"
|
||||
(html:plain line1)
|
||||
(string-append
|
||||
(apply string-append
|
||||
(map (lambda (line) (sprintf #f "\\n%s" (html:plain line)))
|
||||
lines)))))
|
||||
|
||||
;;@body Returns the strings @1 as HTML comments.
|
||||
(define (html:comment line1 . lines)
|
||||
(string-append
|
||||
(apply string-append
|
||||
(if (substring? "--" line1)
|
||||
(slib:error 'html:comment "line contains --" line1)
|
||||
(sprintf #f "<!--%s--" line1))
|
||||
(map (lambda (line)
|
||||
(if (substring? "--" line)
|
||||
(slib:error 'html:comment "line contains --" line)
|
||||
(sprintf #f "\\n --%s--" line)))
|
||||
lines))
|
||||
(sprintf #f ">\\n")))
|
||||
|
||||
(define (html:strong-doc name doc)
|
||||
(set! name (if name (html:plain name) ""))
|
||||
(set! doc (if doc (html:plain doc) ""))
|
||||
(if (equal? "" doc)
|
||||
(if (equal? "" name)
|
||||
""
|
||||
(sprintf #f "<STRONG>%s</STRONG>" (html:plain name)))
|
||||
(sprintf #f "<STRONG>%s</STRONG> (%s)"
|
||||
(html:plain name) (html:plain doc))))
|
||||
|
||||
;;@section HTML Forms
|
||||
|
||||
;;@body The symbol @1 is either @code{get}, @code{head}, @code{post},
|
||||
;;@code{put}, or @code{delete}. The strings @3 form the body of the
|
||||
;;form. @0 returns the HTML @dfn{form}.
|
||||
(define (html:form method action . body)
|
||||
(cond ((not (memq method '(get head post put delete)))
|
||||
(slib:error 'html:form "method unknown:" method)))
|
||||
(string-append
|
||||
(apply string-append
|
||||
(sprintf #f "<FORM METHOD=%#a ACTION=%#a>\\n"
|
||||
(html:atval method) (html:atval action))
|
||||
body)
|
||||
(sprintf #f "</FORM>\\n")))
|
||||
|
||||
;;@body Returns HTML string which will cause @1=@2 in form.
|
||||
(define (html:hidden name value)
|
||||
(sprintf #f "<INPUT TYPE=HIDDEN NAME=%#a VALUE=%#a>"
|
||||
(html:atval name) (html:atval value)))
|
||||
|
||||
;;@body Returns HTML string for check box.
|
||||
(define (html:checkbox pname default)
|
||||
(sprintf #f "<INPUT TYPE=CHECKBOX NAME=%#a %s>"
|
||||
(html:atval pname)
|
||||
(if default "CHECKED" "")))
|
||||
|
||||
;;@body Returns HTML string for one-line text box.
|
||||
(define (html:text pname default . size)
|
||||
(set! size (if (null? size) #f (car size)))
|
||||
(cond (default
|
||||
(sprintf #f "<INPUT NAME=%#a SIZE=%d VALUE=%#a>"
|
||||
(html:atval pname)
|
||||
(or size
|
||||
(max 5
|
||||
(min 20 (string-length
|
||||
(if (symbol? default)
|
||||
(symbol->string default) default)))))
|
||||
(html:atval default)))
|
||||
(size (sprintf #f "<INPUT NAME=%#a SIZE=%d>" (html:atval pname) size))
|
||||
(else (sprintf #f "<INPUT NAME=%#a>" (html:atval pname)))))
|
||||
|
||||
;;@body Returns HTML string for multi-line text box.
|
||||
(define (html:text-area pname default-list)
|
||||
(set! default-list (map (lambda (d) (sprintf #f "%a" d)) default-list))
|
||||
(string-append
|
||||
(sprintf #f "<TEXTAREA NAME=%#a ROWS=%d COLS=%d>\\n"
|
||||
(html:atval pname) (max 1 (length default-list))
|
||||
(min 32 (apply max 5 (map string-length default-list))))
|
||||
(let* ((str (apply string-append
|
||||
(map (lambda (line)
|
||||
(sprintf #f "%s\\n" (html:plain line)))
|
||||
default-list)))
|
||||
(len (+ -1 (string-length str))))
|
||||
(if (positive? len) (substring str 0 len) str))
|
||||
(sprintf #f "</TEXTAREA>\\n")))
|
||||
|
||||
(define (html:s<? s1 s2)
|
||||
(if (and (number? s1) (number? s2))
|
||||
(< s1 s2)
|
||||
(string<? (if (symbol? s1) (symbol->string s1) s1)
|
||||
(if (symbol? s2) (symbol->string s2) s2))))
|
||||
|
||||
(define (by-car proc)
|
||||
(lambda (s1 s2) (proc (car s1) (car s2))))
|
||||
|
||||
;;@body Returns HTML string for pull-down menu selector.
|
||||
(define (html:select pname arity default-list foreign-values)
|
||||
(set! foreign-values (sort foreign-values (by-car html:s<?)))
|
||||
(let ((value-list (map car foreign-values))
|
||||
(visibles (map cadr foreign-values)))
|
||||
(string-append
|
||||
(sprintf #f "<SELECT NAME=%#a SIZE=%d%s>"
|
||||
(html:atval pname)
|
||||
(case arity
|
||||
((single optional) 1)
|
||||
((nary nary1) 5))
|
||||
(case arity
|
||||
((nary nary1) " MULTIPLE")
|
||||
(else "")))
|
||||
(apply string-append
|
||||
(map (lambda (value visible)
|
||||
(sprintf #f "<OPTION VALUE=%#a%s>%s"
|
||||
(html:atval value)
|
||||
(if (member value default-list) " SELECTED" "")
|
||||
(html:plain visible)))
|
||||
(case arity
|
||||
((optional nary) (cons html:blank value-list))
|
||||
(else value-list))
|
||||
(case arity
|
||||
((optional nary) (cons html:blank visibles))
|
||||
(else visibles))))
|
||||
(sprintf #f "</SELECT>"))))
|
||||
|
||||
;;@body Returns HTML string for any-of selector.
|
||||
(define (html:buttons pname arity default-list foreign-values)
|
||||
(set! foreign-values (sort foreign-values (by-car html:s<?)))
|
||||
(let ((value-list (map car foreign-values))
|
||||
(visibles (map cadr foreign-values)))
|
||||
(string-append
|
||||
(sprintf #f "<MENU>")
|
||||
(case arity
|
||||
((single optional)
|
||||
(apply
|
||||
string-append
|
||||
(map (lambda (value visible)
|
||||
(sprintf #f
|
||||
"<LI><INPUT TYPE=RADIO NAME=%#a VALUE=%#a%s> %s\\n"
|
||||
(html:atval pname) (html:atval value)
|
||||
(if (member value default-list) " CHECKED" "")
|
||||
(html:plain visible)))
|
||||
value-list
|
||||
visibles)))
|
||||
((nary nary1)
|
||||
(apply
|
||||
string-append
|
||||
(map (lambda (value visible)
|
||||
(sprintf #f
|
||||
"<LI><INPUT TYPE=CHECKBOX NAME=%#a VALUE=%#a%s> %s\\n"
|
||||
(html:atval pname) (html:atval value)
|
||||
(if (member value default-list) " CHECKED" "")
|
||||
(html:plain visible)))
|
||||
value-list
|
||||
visibles))))
|
||||
(sprintf #f "</MENU>"))))
|
||||
|
||||
;;@args submit-label command
|
||||
;;@args submit-label
|
||||
;;
|
||||
;;The string or symbol @1 appears on the button which submits the form.
|
||||
;;If the optional second argument @2 is given, then @code{*command*=@2}
|
||||
;;and @code{*button*=@1} are set in the query. Otherwise,
|
||||
;;@code{*command*=@1} is set in the query.
|
||||
(define (form:submit submit-label . command)
|
||||
(if (null? command)
|
||||
(sprintf #f "<INPUT TYPE=SUBMIT NAME=%#a VALUE=%#a>"
|
||||
(html:atval '*command*)
|
||||
(html:atval submit-label))
|
||||
(sprintf #f "%s<INPUT TYPE=SUBMIT NAME=%#a VALUE=%#a>"
|
||||
(html:hidden '*command* (car command))
|
||||
(html:atval '*button*)
|
||||
(html:atval submit-label))))
|
||||
|
||||
;;@body The @2 appears on the button which submits the form.
|
||||
(define (form:image submit-label image-src)
|
||||
(sprintf #f "<INPUT TYPE=IMAGE NAME=%#a SRC=%#a>"
|
||||
(html:atval submit-label)
|
||||
(html:atval image-src)))
|
||||
|
||||
;;@body Returns a string which generates a @dfn{reset} button.
|
||||
(define (form:reset) "<INPUT TYPE=RESET>")
|
||||
|
||||
(define (html:delimited-list . rows)
|
||||
(apply string-append
|
||||
"<DL>"
|
||||
(append rows '("</DL>"))))
|
||||
|
||||
;;@body Returns a string which generates an INPUT element for the field
|
||||
;;named @1. The element appears in the created form with its
|
||||
;;representation determined by its @2 and domain. For domains which
|
||||
;;are foreign-keys:
|
||||
;;
|
||||
;;@table @code
|
||||
;;@item single
|
||||
;;select menu
|
||||
;;@item optional
|
||||
;;select menu
|
||||
;;@item nary
|
||||
;;check boxes
|
||||
;;@item nary1
|
||||
;;check boxes
|
||||
;;@end table
|
||||
;;
|
||||
;;If the foreign-key table has a field named @samp{visible-name}, then
|
||||
;;the contents of that field are the names visible to the user for
|
||||
;;those choices. Otherwise, the foreign-key itself is visible.
|
||||
;;
|
||||
;;For other types of domains:
|
||||
;;
|
||||
;;@table @code
|
||||
;;@item single
|
||||
;;text area
|
||||
;;@item optional
|
||||
;;text area
|
||||
;;@item boolean
|
||||
;;check box
|
||||
;;@item nary
|
||||
;;text area
|
||||
;;@item nary1
|
||||
;;text area
|
||||
;;@end table
|
||||
(define (form:element pname arity default-list foreign-values)
|
||||
(define dflt (if (null? default-list) #f
|
||||
(sprintf #f "%a" (car default-list))))
|
||||
;;(print 'form:element pname arity default-list foreign-values)
|
||||
(case (length foreign-values)
|
||||
((0) (case arity
|
||||
((boolean)
|
||||
(html:checkbox pname dflt))
|
||||
((single optional)
|
||||
(html:text pname (if (car default-list) dflt "")))
|
||||
(else (html:text-area pname default-list))))
|
||||
((1) (html:checkbox pname dflt))
|
||||
(else ((case arity
|
||||
((single optional) html:select)
|
||||
(else html:buttons))
|
||||
pname arity default-list foreign-values))))
|
||||
|
||||
;;@body
|
||||
;;
|
||||
;;Returns a HTML string for a form element embedded in a line of a
|
||||
;;delimited list. Apply map @0 to the list returned by
|
||||
;;@code{command->p-specs}.
|
||||
(define (form:delimited pname doc aliat arity default-list foreign-values)
|
||||
(define longname
|
||||
(remove-if (lambda (s) (= 1 (string-length s))) (cdr aliat)))
|
||||
(set! longname (if (null? longname) #f (car longname)))
|
||||
(if longname
|
||||
(string-append
|
||||
"<DT>" (html:strong-doc longname doc) "<DD>"
|
||||
(form:element pname arity default-list foreign-values))
|
||||
""))
|
||||
|
||||
;;@body
|
||||
;;
|
||||
;;The symbol @2 names a command table in the @1 relational database.
|
||||
;;The symbol @3 names a key in @2.
|
||||
;;
|
||||
;;@0 returns a list of lists of @var{pname}, @var{doc}, @var{aliat},
|
||||
;;@var{arity}, @var{default-list}, and @var{foreign-values}. The
|
||||
;;returned list has one element for each parameter of command @3.
|
||||
;;
|
||||
;;This example demonstrates how to create a HTML-form for the @samp{build}
|
||||
;;command.
|
||||
;;
|
||||
;;@example
|
||||
;;(require (in-vicinity (implementation-vicinity) "build.scm"))
|
||||
;;(call-with-output-file "buildscm.html"
|
||||
;; (lambda (port)
|
||||
;; (display
|
||||
;; (string-append
|
||||
;; (html:head 'commands)
|
||||
;; (html:body
|
||||
;; (sprintf #f "<H2>%s:</H2><BLOCKQUOTE>%s</BLOCKQUOTE>\\n"
|
||||
;; (html:plain 'build)
|
||||
;; (html:plain ((comtab 'get 'documentation) 'build)))
|
||||
;; (html:form
|
||||
;; 'post
|
||||
;; (or "http://localhost:8081/buildscm" "/cgi-bin/build.cgi")
|
||||
;; (apply html:delimited-list
|
||||
;; (apply map form:delimited
|
||||
;; (command->p-specs build '*commands* 'build)))
|
||||
;; (form:submit 'build)
|
||||
;; (form:reset))))
|
||||
;; port)))
|
||||
;;@end example
|
||||
(define (command->p-specs rdb command-table command)
|
||||
(define rdb-open (rdb 'open-table))
|
||||
(define (row-refer idx) (lambda (row) (list-ref row idx)))
|
||||
(let ((comtab (rdb-open command-table #f))
|
||||
;;(domain->type ((rdb-open '*domains-data* #f) 'get 'type-id))
|
||||
(get-foreign-values
|
||||
(let ((ftn ((rdb-open '*domains-data* #f) 'get 'foreign-table)))
|
||||
(lambda (domain-name)
|
||||
(define tab-name (ftn domain-name))
|
||||
(if tab-name
|
||||
(get-foreign-choices (rdb-open tab-name #f))
|
||||
'())))))
|
||||
(define row-ref
|
||||
(let ((names (comtab 'column-names)))
|
||||
(lambda (row name) (list-ref row (position name names)))))
|
||||
(let* ((command:row ((comtab 'row:retrieve) command))
|
||||
(parameter-table (rdb-open (row-ref command:row 'parameters) #f))
|
||||
(pcnames (parameter-table 'column-names))
|
||||
(param-rows (sort! ((parameter-table 'row:retrieve*))
|
||||
(lambda (r1 r2) (< (car r1) (car r2))))))
|
||||
(let ((domains (map (row-refer (position 'domain pcnames)) param-rows))
|
||||
(parameter-names (rdb-open (row-ref command:row 'parameter-names) #f))
|
||||
(pnames (map (row-refer (position 'name pcnames)) param-rows)))
|
||||
(define foreign-values (map get-foreign-values domains))
|
||||
(define aliast (map list pnames))
|
||||
(for-each (lambda (alias)
|
||||
(if (> (string-length (car alias)) 1)
|
||||
(let ((apr (assq (cadr alias) aliast)))
|
||||
(set-cdr! apr (cons (car alias) (cdr apr))))))
|
||||
(map list
|
||||
((parameter-names 'get* 'name))
|
||||
(map (parameter-table 'get 'name)
|
||||
((parameter-names 'get* 'parameter-index)))))
|
||||
(list pnames
|
||||
(map (row-refer (position 'documentation pcnames)) param-rows)
|
||||
aliast
|
||||
(map (row-refer (position 'arity pcnames)) param-rows)
|
||||
;;(map domain->type domains)
|
||||
(map cdr ;(lambda (lst) (if (null? lst) lst (cdr lst)))
|
||||
(fill-empty-parameters
|
||||
(map slib:eval
|
||||
(map (row-refer (position 'defaulter pcnames))
|
||||
param-rows))
|
||||
(make-parameter-list
|
||||
(map (row-refer (position 'name pcnames)) param-rows))))
|
||||
foreign-values)))))
|
|
@ -1,204 +0,0 @@
|
|||
@code{(require 'html-form)}
|
||||
|
||||
|
||||
@defun html:atval txt
|
||||
Returns a string with character substitutions appropriate to
|
||||
send @var{txt} as an @dfn{attribute-value}.
|
||||
@cindex attribute-value
|
||||
@end defun
|
||||
|
||||
@defun html:plain txt
|
||||
Returns a string with character substitutions appropriate to
|
||||
send @var{txt} as an @dfn{plain-text}.
|
||||
@cindex plain-text
|
||||
@end defun
|
||||
|
||||
@defun html:meta name content
|
||||
Returns a tag of meta-information suitable for passing as the
|
||||
third argument to @code{html:head}. The tag produced is @samp{<META
|
||||
NAME="@var{name}" CONTENT="@var{content}">}. The string or symbol @var{name} can be
|
||||
@samp{author}, @samp{copyright}, @samp{keywords}, @samp{description},
|
||||
@samp{date}, @samp{robots}, @dots{}.
|
||||
@end defun
|
||||
|
||||
@defun html:http-equiv name content
|
||||
Returns a tag of HTTP information suitable for passing as the
|
||||
third argument to @code{html:head}. The tag produced is @samp{<META
|
||||
HTTP-EQUIV="@var{name}" CONTENT="@var{content}">}. The string or symbol @var{name} can be
|
||||
@samp{Expires}, @samp{PICS-Label}, @samp{Content-Type},
|
||||
@samp{Refresh}, @dots{}.
|
||||
@end defun
|
||||
|
||||
@defun html:meta-refresh delay uri
|
||||
|
||||
|
||||
@defunx html:meta-refresh delay
|
||||
|
||||
Returns a tag suitable for passing as the third argument to
|
||||
@code{html:head}. If @var{uri} argument is supplied, then @var{delay} seconds after
|
||||
displaying the page with this tag, Netscape or IE browsers will fetch
|
||||
and display @var{uri}. Otherwise, @var{delay} seconds after displaying the page with
|
||||
this tag, Netscape or IE browsers will fetch and redisplay this page.
|
||||
@end defun
|
||||
|
||||
@defun html:head title backlink tags @dots{}
|
||||
|
||||
|
||||
@defunx html:head title backlink
|
||||
|
||||
@defunx html:head title
|
||||
|
||||
Returns header string for an HTML page named @var{title}. If @var{backlink} is a string,
|
||||
it is used verbatim between the @samp{H1} tags; otherwise @var{title} is
|
||||
used. If string arguments @var{tags} ... are supplied, then they are
|
||||
included verbatim within the @t{<HEAD>} section.
|
||||
@end defun
|
||||
|
||||
@defun html:body body @dots{}
|
||||
Returns HTML string to end a page.
|
||||
@end defun
|
||||
|
||||
@defun html:pre line1 line @dots{}
|
||||
Returns the strings @var{line1}, @var{lines} as @dfn{PRE}formmated plain text
|
||||
@cindex PRE
|
||||
(rendered in fixed-width font). Newlines are inserted between @var{line1},
|
||||
@var{lines}. HTML tags (@samp{<tag>}) within @var{lines} will be visible verbatim.
|
||||
@end defun
|
||||
|
||||
@defun html:comment line1 line @dots{}
|
||||
Returns the strings @var{line1} as HTML comments.
|
||||
@end defun
|
||||
@section HTML Forms
|
||||
|
||||
|
||||
@defun html:form method action body @dots{}
|
||||
The symbol @var{method} is either @code{get}, @code{head}, @code{post},
|
||||
@code{put}, or @code{delete}. The strings @var{body} form the body of the
|
||||
form. @code{html:form} returns the HTML @dfn{form}.
|
||||
@cindex form
|
||||
@end defun
|
||||
|
||||
@defun html:hidden name value
|
||||
Returns HTML string which will cause @var{name}=@var{value} in form.
|
||||
@end defun
|
||||
|
||||
@defun html:checkbox pname default
|
||||
Returns HTML string for check box.
|
||||
@end defun
|
||||
|
||||
@defun html:text pname default size @dots{}
|
||||
Returns HTML string for one-line text box.
|
||||
@end defun
|
||||
|
||||
@defun html:text-area pname default-list
|
||||
Returns HTML string for multi-line text box.
|
||||
@end defun
|
||||
|
||||
@defun html:select pname arity default-list foreign-values
|
||||
Returns HTML string for pull-down menu selector.
|
||||
@end defun
|
||||
|
||||
@defun html:buttons pname arity default-list foreign-values
|
||||
Returns HTML string for any-of selector.
|
||||
@end defun
|
||||
|
||||
@defun form:submit submit-label command
|
||||
|
||||
|
||||
@defunx form:submit submit-label
|
||||
|
||||
The string or symbol @var{submit-label} appears on the button which submits the form.
|
||||
If the optional second argument @var{command} is given, then @code{*command*=@var{command}}
|
||||
and @code{*button*=@var{submit-label}} are set in the query. Otherwise,
|
||||
@code{*command*=@var{submit-label}} is set in the query.
|
||||
@end defun
|
||||
|
||||
@defun form:image submit-label image-src
|
||||
The @var{image-src} appears on the button which submits the form.
|
||||
@end defun
|
||||
|
||||
@defun form:reset
|
||||
Returns a string which generates a @dfn{reset} button.
|
||||
@cindex reset
|
||||
@end defun
|
||||
|
||||
@defun form:element pname arity default-list foreign-values
|
||||
Returns a string which generates an INPUT element for the field
|
||||
named @var{pname}. The element appears in the created form with its
|
||||
representation determined by its @var{arity} and domain. For domains which
|
||||
are foreign-keys:
|
||||
|
||||
@table @code
|
||||
@item single
|
||||
select menu
|
||||
@item optional
|
||||
select menu
|
||||
@item nary
|
||||
check boxes
|
||||
@item nary1
|
||||
check boxes
|
||||
@end table
|
||||
|
||||
If the foreign-key table has a field named @samp{visible-name}, then
|
||||
the contents of that field are the names visible to the user for
|
||||
those choices. Otherwise, the foreign-key itself is visible.
|
||||
|
||||
For other types of domains:
|
||||
|
||||
@table @code
|
||||
@item single
|
||||
text area
|
||||
@item optional
|
||||
text area
|
||||
@item boolean
|
||||
check box
|
||||
@item nary
|
||||
text area
|
||||
@item nary1
|
||||
text area
|
||||
@end table
|
||||
@end defun
|
||||
|
||||
@defun form:delimited pname doc aliat arity default-list foreign-values
|
||||
|
||||
|
||||
Returns a HTML string for a form element embedded in a line of a
|
||||
delimited list. Apply map @code{form:delimited} to the list returned by
|
||||
@code{command->p-specs}.
|
||||
@end defun
|
||||
|
||||
@defun command->p-specs rdb command-table command
|
||||
|
||||
|
||||
The symbol @var{command-table} names a command table in the @var{rdb} relational database.
|
||||
The symbol @var{command} names a key in @var{command-table}.
|
||||
|
||||
@code{command->p-specs} returns a list of lists of @var{pname}, @var{doc}, @var{aliat},
|
||||
@var{arity}, @var{default-list}, and @var{foreign-values}. The
|
||||
returned list has one element for each parameter of command @var{command}.
|
||||
|
||||
This example demonstrates how to create a HTML-form for the @samp{build}
|
||||
command.
|
||||
|
||||
@example
|
||||
(require (in-vicinity (implementation-vicinity) "build.scm"))
|
||||
(call-with-output-file "buildscm.html"
|
||||
(lambda (port)
|
||||
(display
|
||||
(string-append
|
||||
(html:head 'commands)
|
||||
(html:body
|
||||
(sprintf #f "<H2>%s:</H2><BLOCKQUOTE>%s</BLOCKQUOTE>\\n"
|
||||
(html:plain 'build)
|
||||
(html:plain ((comtab 'get 'documentation) 'build)))
|
||||
(html:form
|
||||
'post
|
||||
(or "http://localhost:8081/buildscm" "/cgi-bin/build.cgi")
|
||||
(apply html:delimited-list
|
||||
(apply map form:delimited
|
||||
(command->p-specs build '*commands* 'build)))
|
||||
(form:submit 'build)
|
||||
(form:reset))))
|
||||
port)))
|
||||
@end example
|
||||
@end defun
|
|
@ -1,438 +0,0 @@
|
|||
;;; "http-cgi.scm" service HTTP or CGI requests. -*-scheme-*-
|
||||
; Copyright 1997, 1998, 2000, 2001 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'uri)
|
||||
(require 'scanf)
|
||||
(require 'printf)
|
||||
(require 'coerce)
|
||||
(require 'line-i/o)
|
||||
(require 'html-form)
|
||||
(require 'parameters)
|
||||
(require 'string-case)
|
||||
|
||||
;;@code{(require 'http)} or @code{(require 'cgi)}
|
||||
|
||||
(define http:crlf (string (integer->char 13) #\newline))
|
||||
(define (http:read-header port)
|
||||
(define alist '())
|
||||
(do ((line (read-line port) (read-line port)))
|
||||
((or (zero? (string-length line))
|
||||
(and (= 1 (string-length line))
|
||||
(char-whitespace? (string-ref line 0)))
|
||||
(eof-object? line))
|
||||
(if (and (= 1 (string-length line))
|
||||
(char-whitespace? (string-ref line 0)))
|
||||
(set! http:crlf (string (string-ref line 0) #\newline)))
|
||||
(if (eof-object? line) line alist))
|
||||
(let ((len (string-length line))
|
||||
(idx (string-index line #\:)))
|
||||
(if (char-whitespace? (string-ref line (+ -1 len)))
|
||||
(set! len (+ -1 len)))
|
||||
(and idx (do ((idx2 (+ idx 1) (+ idx2 1)))
|
||||
((or (>= idx2 len)
|
||||
(not (char-whitespace? (string-ref line idx2))))
|
||||
(set! alist
|
||||
(cons
|
||||
(cons (string-ci->symbol (substring line 0 idx))
|
||||
(substring line idx2 len))
|
||||
alist)))))
|
||||
;;Else -- ignore malformed line
|
||||
;;(else (slib:error 'http:read-header 'malformed-input line))
|
||||
)))
|
||||
|
||||
(define (http:read-query-string request-line header port)
|
||||
(case (car request-line)
|
||||
((get head)
|
||||
(let* ((request-uri (cadr request-line))
|
||||
(len (string-length request-uri)))
|
||||
(and (> len 3)
|
||||
(string-index request-uri #\?)
|
||||
(substring request-uri
|
||||
(+ 1 (string-index request-uri #\?))
|
||||
(if (eqv? #\/ (string-ref request-uri (+ -1 len)))
|
||||
(+ -1 len)
|
||||
len)))))
|
||||
((post put delete)
|
||||
(let ((content-length (assq 'content-length header)))
|
||||
(and content-length
|
||||
(set! content-length (string->number (cdr content-length))))
|
||||
(and content-length
|
||||
(let ((str (make-string content-length #\ )))
|
||||
(do ((idx 0 (+ idx 1)))
|
||||
((>= idx content-length)
|
||||
(if (>= idx (string-length str)) str (substring str 0 idx)))
|
||||
(let ((chr (read-char port)))
|
||||
(if (char? chr)
|
||||
(string-set! str idx chr)
|
||||
(set! content-length idx))))))))
|
||||
(else #f)))
|
||||
|
||||
(define (http:status-line status-code reason)
|
||||
(sprintf #f "HTTP/1.1 %d %s%s" status-code reason http:crlf))
|
||||
|
||||
;;@body Returns a string containing lines for each element of @1; the
|
||||
;;@code{car} of which is followed by @samp{: }, then the @code{cdr}.
|
||||
(define (http:header alist)
|
||||
(string-append
|
||||
(apply string-append
|
||||
(map (lambda (pair)
|
||||
(sprintf #f "%s: %s%s" (car pair) (cdr pair) http:crlf))
|
||||
alist))
|
||||
http:crlf))
|
||||
|
||||
;;@body Returns the concatenation of strings @2 with the
|
||||
;;@code{(http:header @1)} and the @samp{Content-Length} prepended.
|
||||
(define (http:content alist . body)
|
||||
(define hunk (apply string-append body))
|
||||
(string-append (http:header
|
||||
(cons (cons "Content-Length"
|
||||
(number->string (string-length hunk)))
|
||||
alist))
|
||||
hunk))
|
||||
|
||||
;;@body String appearing at the bottom of error pages.
|
||||
(define *http:byline* #f)
|
||||
|
||||
;;@body @1 and @2 should be an integer and string as specified in
|
||||
;;@cite{RFC 2068}. The returned page (string) will show the @1 and @2
|
||||
;;and any additional @3 @dots{}; with @var{*http:byline*} or SLIB's
|
||||
;;default at the bottom.
|
||||
(define (http:error-page status-code reason-phrase . html-strings)
|
||||
(define byline
|
||||
(or
|
||||
*http:byline*
|
||||
(sprintf
|
||||
#f
|
||||
"<A HREF=http://swissnet.ai.mit.edu/~jaffer/SLIB.html>SLIB</A> %s server"
|
||||
(if (getenv "SERVER_PROTOCOL") "CGI/1.1" "HTTP/1.1"))))
|
||||
(string-append (http:status-line status-code reason-phrase)
|
||||
(http:content
|
||||
'(("Content-Type" . "text/html"))
|
||||
(html:head (sprintf #f "%d %s" status-code reason-phrase))
|
||||
(apply html:body
|
||||
(append html-strings
|
||||
(list (sprintf #f "<HR>\\n%s\\n" byline)))))))
|
||||
|
||||
;;@body The string or symbol @1 is the page title. @2 is a non-negative
|
||||
;;integer. The @4 @dots{} are typically used to explain to the user why
|
||||
;;this page is being forwarded.
|
||||
;;
|
||||
;;@0 returns an HTML string for a page which automatically forwards to
|
||||
;;@3 after @2 seconds. The returned page (string) contains any @4
|
||||
;;@dots{} followed by a manual link to @3, in case the browser does not
|
||||
;;forward automatically.
|
||||
(define (http:forwarding-page title delay uri . html-strings)
|
||||
(string-append
|
||||
(html:head title #f (html:meta-refresh delay uri))
|
||||
(apply html:body
|
||||
(append html-strings
|
||||
(list (sprintf #f "\\n\\n<HR>\\nReturn to %s.\\n"
|
||||
(html:link uri title)))))))
|
||||
|
||||
;;@body reads the @dfn{URI} and @dfn{query-string} from @2. If the
|
||||
;;query is a valid @samp{"POST"} or @samp{"GET"} query, then @0 calls
|
||||
;;@1 with three arguments, the @var{request-line}, @var{query-string},
|
||||
;;and @var{header-alist}. Otherwise, @0 calls @1 with the
|
||||
;;@var{request-line}, #f, and @var{header-alist}.
|
||||
;;
|
||||
;;If @1 returns a string, it is sent to @3. If @1 returns a list,
|
||||
;;then an error page with number 525 and strings from the list. If @1
|
||||
;;returns #f, then a @samp{Bad Request} (400) page is sent to @3.
|
||||
;;
|
||||
;;Otherwise, @0 replies (to @3) with appropriate HTML describing the
|
||||
;;problem.
|
||||
(define (http:serve-query serve-proc input-port output-port)
|
||||
(let* ((request-line (http:read-request-line input-port))
|
||||
(header (and request-line (http:read-header input-port)))
|
||||
(query-string (and header (http:read-query-string
|
||||
request-line header input-port))))
|
||||
(display (http:service serve-proc request-line query-string header)
|
||||
output-port)))
|
||||
|
||||
(define (http:service serve-proc request-line query-string header)
|
||||
(cond ((not request-line) (http:error-page 400 "Bad Request."))
|
||||
((string? (car request-line))
|
||||
(http:error-page 501 "Not Implemented" (html:plain request-line)))
|
||||
((not (memq (car request-line) '(get post)))
|
||||
(http:error-page 405 "Method Not Allowed" (html:plain request-line)))
|
||||
((serve-proc request-line query-string header) =>
|
||||
(lambda (reply)
|
||||
(cond ((string? reply)
|
||||
(string-append (http:status-line 200 "OK")
|
||||
reply))
|
||||
((and (pair? reply) (list? reply))
|
||||
(if (number? (car reply))
|
||||
(apply http:error-page reply)
|
||||
(apply http:error-page 525 reply)))
|
||||
(else (http:error-page 500 "Internal Server Error")))))
|
||||
((not query-string)
|
||||
(http:error-page 400 "Bad Request" (html:plain request-line)))
|
||||
(else
|
||||
(http:error-page 500 "Internal Server Error" (html:plain header)))))
|
||||
|
||||
;;@
|
||||
;;
|
||||
;;This example services HTTP queries from @var{port-number}:
|
||||
;;@example
|
||||
;;
|
||||
;;(define socket (make-stream-socket AF_INET 0))
|
||||
;;(and (socket:bind socket port-number) ; AF_INET INADDR_ANY
|
||||
;; (socket:listen socket 10) ; Queue up to 10 requests.
|
||||
;; (dynamic-wind
|
||||
;; (lambda () #f)
|
||||
;; (lambda ()
|
||||
;; (do ((port (socket:accept socket) (socket:accept socket)))
|
||||
;; (#f)
|
||||
;; (let ((iport (duplicate-port port "r"))
|
||||
;; (oport (duplicate-port port "w")))
|
||||
;; (http:serve-query build:serve iport oport)
|
||||
;; (close-port iport)
|
||||
;; (close-port oport))
|
||||
;; (close-port port)))
|
||||
;; (lambda () (close-port socket))))
|
||||
;;@end example
|
||||
|
||||
(define (http:read-start-line port)
|
||||
(do ((line (read-line port) (read-line port)))
|
||||
((or (not (equal? "" line)) (eof-object? line)) line)))
|
||||
|
||||
;; @body
|
||||
;; Request lines are a list of three itmes:
|
||||
;;
|
||||
;; @enumerate 0
|
||||
;;
|
||||
;; @item Method
|
||||
;;
|
||||
;; A symbol (@code{options}, @code{get}, @code{head}, @code{post},
|
||||
;; @code{put}, @code{delete}, @code{trace} @dots{}).
|
||||
;;
|
||||
;; @item Request-URI
|
||||
;;
|
||||
;; A string. For direct HTTP, at the minimum it will be the string
|
||||
;; @samp{"/"}.
|
||||
;;
|
||||
;; @item HTTP-Version
|
||||
;;
|
||||
;; A string. For example, @samp{HTTP/1.0}.
|
||||
;; @end enumerate
|
||||
(define (http:read-request-line port)
|
||||
(let ((lst (scanf-read-list "%s %s %s %s" (http:read-start-line port))))
|
||||
(and (list? lst)
|
||||
(= 3 (length lst))
|
||||
(cons (string-ci->symbol (car lst)) (cdr lst)))))
|
||||
(define (cgi:request-line)
|
||||
(define method (getenv "REQUEST_METHOD"))
|
||||
(and method
|
||||
(list (string-ci->symbol method)
|
||||
(getenv "SCRIPT_NAME")
|
||||
(getenv "SERVER_PROTOCOL"))))
|
||||
|
||||
(define (cgi:query-header)
|
||||
(define assqs '())
|
||||
(cond ((and (getenv "SERVER_NAME") (getenv "SERVER_PORT"))
|
||||
(set! assqs (cons (cons 'host (string-append (getenv "SERVER_NAME")
|
||||
":"
|
||||
(getenv "SERVER_PORT")))
|
||||
assqs))))
|
||||
(for-each
|
||||
(lambda (envar)
|
||||
(define valstr (getenv envar))
|
||||
(if valstr (set! assqs
|
||||
(cons (cons (string-ci->symbol
|
||||
(string-subst envar "HTTP_" "" "_" "-"))
|
||||
valstr)
|
||||
assqs))))
|
||||
'(
|
||||
;;"AUTH_TYPE"
|
||||
"CONTENT_LENGTH"
|
||||
"CONTENT_TYPE"
|
||||
"DOCUMENT_ROOT"
|
||||
"GATEWAY_INTERFACE"
|
||||
"HTTP_ACCEPT"
|
||||
"HTTP_ACCEPT_CHARSET"
|
||||
"HTTP_ACCEPT_ENCODING"
|
||||
"HTTP_ACCEPT_LANGUAGE"
|
||||
"HTTP_CONNECTION"
|
||||
"HTTP_HOST"
|
||||
;;"HTTP_PRAGMA"
|
||||
"HTTP_REFERER"
|
||||
"HTTP_USER_AGENT"
|
||||
"PATH_INFO"
|
||||
"PATH_TRANSLATED"
|
||||
"QUERY_STRING"
|
||||
"REMOTE_ADDR"
|
||||
"REMOTE_HOST"
|
||||
;;"REMOTE_IDENT"
|
||||
;;"REMOTE_USER"
|
||||
"REQUEST_URI"
|
||||
"SCRIPT_FILENAME"
|
||||
"SCRIPT_NAME"
|
||||
;;"SERVER_SIGNATURE"
|
||||
;;"SERVER_SOFTWARE"
|
||||
))
|
||||
assqs)
|
||||
|
||||
;; @body Reads the @dfn{query-string} from @code{(current-input-port)}.
|
||||
;; @0 reads a @samp{"POST"} or @samp{"GET"} queries, depending on the
|
||||
;; value of @code{(getenv "REQUEST_METHOD")}.
|
||||
(define (cgi:read-query-string)
|
||||
(define request-method (getenv "REQUEST_METHOD"))
|
||||
(cond ((and request-method (string-ci=? "GET" request-method))
|
||||
(getenv "QUERY_STRING"))
|
||||
((and request-method (string-ci=? "POST" request-method))
|
||||
(let ((content-length (getenv "CONTENT_LENGTH")))
|
||||
(and content-length
|
||||
(set! content-length (string->number content-length)))
|
||||
(and content-length
|
||||
(let ((str (make-string content-length #\ )))
|
||||
(do ((idx 0 (+ idx 1)))
|
||||
((>= idx content-length)
|
||||
(if (>= idx (string-length str))
|
||||
str
|
||||
(substring str 0 idx)))
|
||||
(let ((chr (read-char)))
|
||||
(if (char? chr)
|
||||
(string-set! str idx chr)
|
||||
(set! content-length idx))))))))
|
||||
(else #f)))
|
||||
|
||||
;;@body reads the @dfn{URI} and @dfn{query-string} from
|
||||
;;@code{(current-input-port)}. If the query is a valid @samp{"POST"}
|
||||
;;or @samp{"GET"} query, then @0 calls @1 with three arguments, the
|
||||
;;@var{request-line}, @var{query-string}, and @var{header-alist}.
|
||||
;;Otherwise, @0 calls @1 with the @var{request-line}, #f, and
|
||||
;;@var{header-alist}.
|
||||
;;
|
||||
;;If @1 returns a string, it is sent to @code{(current-input-port)}.
|
||||
;;If @1 returns a list, then an error page with number 525 and strings
|
||||
;;from the list. If @1 returns #f, then a @samp{Bad Request} (400)
|
||||
;;page is sent to @code{(current-input-port)}.
|
||||
;;
|
||||
;;Otherwise, @0 replies (to @code{(current-input-port)}) with
|
||||
;;appropriate HTML describing the problem.
|
||||
(define (cgi:serve-query serve-proc)
|
||||
(let* ((script-name (getenv "SCRIPT_NAME"))
|
||||
(request-line (cgi:request-line))
|
||||
(header (and request-line (cgi:query-header)))
|
||||
(query-string (and header (cgi:read-query-string)))
|
||||
(reply (http:service serve-proc request-line query-string header)))
|
||||
(display (if (and script-name
|
||||
(not (eqv? 0 (substring? "nph-" script-name))))
|
||||
;; Eat http status line.
|
||||
(substring reply (+ 2 (substring? http:crlf reply))
|
||||
(string-length reply))
|
||||
reply))))
|
||||
|
||||
(define (coerce->list str type)
|
||||
(case type
|
||||
((expression)
|
||||
(slib:warn 'coerce->list 'unsafe 'read)
|
||||
(do ((tok (read port) (read port))
|
||||
(lst '() (cons tok lst)))
|
||||
((or (null? tok) (eof-object? tok)) lst)))
|
||||
((symbol)
|
||||
(call-with-input-string str
|
||||
(lambda (port)
|
||||
(do ((tok (scanf-read-list " %s" port)
|
||||
(scanf-read-list " %s" port))
|
||||
(lst '() (cons (string-ci->symbol (car tok)) lst)))
|
||||
((or (null? tok) (eof-object? tok)) lst)))))
|
||||
(else
|
||||
(call-with-input-string str
|
||||
(lambda (port)
|
||||
(do ((tok (scanf-read-list " %s" port)
|
||||
(scanf-read-list " %s" port))
|
||||
(lst '() (cons (coerce (car tok) type) lst)))
|
||||
((or (null? tok) (eof-object? tok)) lst)))))))
|
||||
|
||||
(define (query-alist->parameter-list alist optnames arities types)
|
||||
(let ((parameter-list (make-parameter-list optnames)))
|
||||
(for-each
|
||||
(lambda (lst)
|
||||
(let* ((value (cadr lst))
|
||||
(name (car lst))
|
||||
(opt-pos (position name optnames)))
|
||||
(cond ((not opt-pos)
|
||||
(slib:warn 'query-alist->parameter-list
|
||||
'unknown 'parameter name))
|
||||
((eq? (list-ref arities opt-pos) 'boolean)
|
||||
(adjoin-parameters! parameter-list (list name #t)))
|
||||
((and (equal? value "")
|
||||
(not (memq (list-ref types opt-pos) '(expression string))))
|
||||
(adjoin-parameters! parameter-list (list name #f)))
|
||||
(value
|
||||
(adjoin-parameters!
|
||||
parameter-list
|
||||
(cons name
|
||||
(case (list-ref arities opt-pos)
|
||||
((nary nary1)
|
||||
(coerce->list value (list-ref types opt-pos)))
|
||||
(else
|
||||
(list (coerce value (list-ref types opt-pos)))))))))))
|
||||
alist)
|
||||
parameter-list))
|
||||
|
||||
;;@args rdb command-table
|
||||
;;@args rdb command-table #t
|
||||
;;
|
||||
;;Returns a procedure of one argument. When that procedure is called
|
||||
;;with a @var{query-alist} (as returned by @code{uri:decode-query}, the
|
||||
;;value of the @samp{*command*} association will be the command invoked
|
||||
;;in @2. If @samp{*command*} is not in the @var{query-alist} then the
|
||||
;;value of @samp{*suggest*} is tried. If neither name is in the
|
||||
;;@var{query-alist}, then the literal value @samp{*default*} is tried in
|
||||
;;@2.
|
||||
;;
|
||||
;;If optional third argument is non-false, then the command is called
|
||||
;;with just the parameter-list; otherwise, command is called with the
|
||||
;;arguments described in its table.
|
||||
(define (make-query-alist-command-server rdb command-table . just-params?)
|
||||
(define comsrvcal (make-command-server rdb command-table))
|
||||
(set! just-params? (if (null? just-params?) #f (car just-params?)))
|
||||
(lambda (query-alist)
|
||||
(define comnam #f)
|
||||
(define find-command?
|
||||
(lambda (cname)
|
||||
(define tryp (parameter-list-ref query-alist cname))
|
||||
(cond ((not tryp) #f)
|
||||
(comnam
|
||||
(set! query-alist (remove-parameter cname query-alist)))
|
||||
(else
|
||||
(set! query-alist (remove-parameter cname query-alist))
|
||||
(set! comnam (string-ci->symbol (car tryp)))))))
|
||||
(find-command? '*command*)
|
||||
(find-command? '*suggest*)
|
||||
(find-command? '*button*)
|
||||
(cond ((not comnam) (set! comnam '*default*)))
|
||||
(cond
|
||||
(comnam
|
||||
(comsrvcal comnam
|
||||
(lambda (comname comval options positions
|
||||
arities types defaulters dirs aliases)
|
||||
(let* ((params (query-alist->parameter-list
|
||||
query-alist options arities types))
|
||||
(fparams (fill-empty-parameters defaulters params)))
|
||||
(and (list? fparams)
|
||||
(check-parameters dirs fparams)
|
||||
(if just-params?
|
||||
(comval fparams)
|
||||
(let ((arglist (parameter-list->arglist
|
||||
positions arities fparams)))
|
||||
(and arglist
|
||||
(apply comval arglist))))))))))))
|
|
@ -1,110 +0,0 @@
|
|||
@code{(require 'http)} or @code{(require 'cgi)}
|
||||
|
||||
|
||||
@defun http:header alist
|
||||
Returns a string containing lines for each element of @var{alist}; the
|
||||
@code{car} of which is followed by @samp{: }, then the @code{cdr}.
|
||||
@end defun
|
||||
|
||||
@defun http:content alist body @dots{}
|
||||
Returns the concatenation of strings @var{body} with the
|
||||
@code{(http:header @var{alist})} and the @samp{Content-Length} prepended.
|
||||
@end defun
|
||||
|
||||
@defvar *http:byline*
|
||||
String appearing at the bottom of error pages.
|
||||
@end defvar
|
||||
|
||||
@defun http:error-page status-code reason-phrase html-string @dots{}
|
||||
@var{status-code} and @var{reason-phrase} should be an integer and string as specified in
|
||||
@cite{RFC 2068}. The returned page (string) will show the @var{status-code} and @var{reason-phrase}
|
||||
and any additional @var{html-strings} @dots{}; with @var{*http:byline*} or SLIB's
|
||||
default at the bottom.
|
||||
@end defun
|
||||
|
||||
@defun http:forwarding-page title delay uri html-string @dots{}
|
||||
The string or symbol @var{title} is the page title. @var{delay} is a non-negative
|
||||
integer. The @var{html-strings} @dots{} are typically used to explain to the user why
|
||||
this page is being forwarded.
|
||||
|
||||
@code{http:forwarding-page} returns an HTML string for a page which automatically forwards to
|
||||
@var{uri} after @var{delay} seconds. The returned page (string) contains any @var{html-strings}
|
||||
@dots{} followed by a manual link to @var{uri}, in case the browser does not
|
||||
forward automatically.
|
||||
@end defun
|
||||
|
||||
@defun http:serve-query serve-proc input-port output-port
|
||||
reads the @dfn{URI} and @dfn{query-string} from @var{input-port}. If the
|
||||
@cindex URI
|
||||
@cindex query-string
|
||||
query is a valid @samp{"POST"} or @samp{"GET"} query, then @code{http:serve-query} calls
|
||||
@var{serve-proc} with three arguments, the @var{request-line}, @var{query-string},
|
||||
and @var{header-alist}. Otherwise, @code{http:serve-query} calls @var{serve-proc} with the
|
||||
@var{request-line}, #f, and @var{header-alist}.
|
||||
|
||||
If @var{serve-proc} returns a string, it is sent to @var{output-port}. If @var{serve-proc} returns a list,
|
||||
then an error page with number 525 and strings from the list. If @var{serve-proc}
|
||||
returns #f, then a @samp{Bad Request} (400) page is sent to @var{output-port}.
|
||||
|
||||
Otherwise, @code{http:serve-query} replies (to @var{output-port}) with appropriate HTML describing the
|
||||
problem.
|
||||
@end defun
|
||||
|
||||
|
||||
This example services HTTP queries from @var{port-number}:
|
||||
@example
|
||||
|
||||
(define socket (make-stream-socket AF_INET 0))
|
||||
(and (socket:bind socket port-number) ; AF_INET INADDR_ANY
|
||||
(socket:listen socket 10) ; Queue up to 10 requests.
|
||||
(dynamic-wind
|
||||
(lambda () #f)
|
||||
(lambda ()
|
||||
(do ((port (socket:accept socket) (socket:accept socket)))
|
||||
(#f)
|
||||
(let ((iport (duplicate-port port "r"))
|
||||
(oport (duplicate-port port "w")))
|
||||
(http:serve-query build:serve iport oport)
|
||||
(close-port iport)
|
||||
(close-port oport))
|
||||
(close-port port)))
|
||||
(lambda () (close-port socket))))
|
||||
@end example
|
||||
|
||||
|
||||
@defun cgi:serve-query serve-proc
|
||||
reads the @dfn{URI} and @dfn{query-string} from
|
||||
@cindex URI
|
||||
@cindex query-string
|
||||
@code{(current-input-port)}. If the query is a valid @samp{"POST"}
|
||||
or @samp{"GET"} query, then @code{cgi:serve-query} calls @var{serve-proc} with three arguments, the
|
||||
@var{request-line}, @var{query-string}, and @var{header-alist}.
|
||||
Otherwise, @code{cgi:serve-query} calls @var{serve-proc} with the @var{request-line}, #f, and
|
||||
@var{header-alist}.
|
||||
|
||||
If @var{serve-proc} returns a string, it is sent to @code{(current-input-port)}.
|
||||
If @var{serve-proc} returns a list, then an error page with number 525 and strings
|
||||
from the list. If @var{serve-proc} returns #f, then a @samp{Bad Request} (400)
|
||||
page is sent to @code{(current-input-port)}.
|
||||
|
||||
Otherwise, @code{cgi:serve-query} replies (to @code{(current-input-port)}) with
|
||||
appropriate HTML describing the problem.
|
||||
@end defun
|
||||
|
||||
@defun make-query-alist-command-server rdb command-table
|
||||
|
||||
|
||||
@defunx make-query-alist-command-server rdb command-table #t
|
||||
|
||||
Returns a procedure of one argument. When that procedure is called
|
||||
with a @var{query-alist} (as returned by @code{uri:decode-query}, the
|
||||
value of the @samp{*command*} association will be the command invoked
|
||||
in @var{command-table}. If @samp{*command*} is not in the @var{query-alist} then the
|
||||
value of @samp{*suggest*} is tried. If neither name is in the
|
||||
@var{query-alist}, then the literal value @samp{*default*} is tried in
|
||||
@var{command-table}.
|
||||
|
||||
If optional third argument is non-false, then the command is called
|
||||
with just the parameter-list; otherwise, command is called with the
|
||||
arguments described in its table.
|
||||
@end defun
|
|
@ -1,82 +0,0 @@
|
|||
; "lineio.scm", line oriented input/output functions for Scheme.
|
||||
; Copyright (c) 1992, 1993 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
|
||||
;;@args
|
||||
;;@args port
|
||||
;;Returns a string of the characters up to, but not including a
|
||||
;;newline or end of file, updating @var{port} to point to the
|
||||
;;character following the newline. If no characters are available, an
|
||||
;;end of file object is returned. The @var{port} argument may be
|
||||
;;omitted, in which case it defaults to the value returned by
|
||||
;;@code{current-input-port}.
|
||||
(define (read-line . port)
|
||||
(let* ((char (apply read-char port)))
|
||||
(if (eof-object? char)
|
||||
char
|
||||
(do ((char char (apply read-char port))
|
||||
(clist '() (cons char clist)))
|
||||
((or (eof-object? char) (char=? #\newline char))
|
||||
(list->string (reverse clist)))))))
|
||||
|
||||
;;@args string
|
||||
;;@args string port
|
||||
;;Fills @1 with characters up to, but not including a newline or end
|
||||
;;of file, updating the @var{port} to point to the last character read
|
||||
;;or following the newline if it was read. If no characters are
|
||||
;;available, an end of file object is returned. If a newline or end
|
||||
;;of file was found, the number of characters read is returned.
|
||||
;;Otherwise, @code{#f} is returned. The @var{port} argument may be
|
||||
;;omitted, in which case it defaults to the value returned by
|
||||
;;@code{current-input-port}.
|
||||
(define (read-line! str . port)
|
||||
(let* ((char (apply read-char port))
|
||||
(midx (+ -1 (string-length str))))
|
||||
(if (eof-object? char)
|
||||
char
|
||||
(do ((char char (apply read-char port))
|
||||
(i 0 (+ 1 i)))
|
||||
((or (eof-object? char)
|
||||
(char=? #\newline char)
|
||||
(> i midx))
|
||||
(if (> i midx) #f i))
|
||||
(string-set! str i char)))))
|
||||
|
||||
;;@args string
|
||||
;;@args string port
|
||||
;;Writes @1 followed by a newline to the given @var{port} and returns
|
||||
;;an unspecified value. The @var{Port} argument may be omitted, in
|
||||
;;which case it defaults to the value returned by
|
||||
;;@code{current-input-port}.@refill
|
||||
(define (write-line str . port)
|
||||
(apply display str port)
|
||||
(apply newline port))
|
||||
|
||||
;;@args path
|
||||
;;@args path port
|
||||
;;Displays the contents of the file named by @1 to @var{port}. The
|
||||
;;@var{port} argument may be ommited, in which case it defaults to the
|
||||
;;value returned by @code{current-output-port}.
|
||||
(define (display-file path . port)
|
||||
(set! port (if (null? port) (current-output-port) (car port)))
|
||||
(call-with-input-file path
|
||||
(lambda (inport)
|
||||
(do ((line (read-line inport) (read-line inport)))
|
||||
((eof-object? line))
|
||||
(write-line line port)))))
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
@defun read-line
|
||||
|
||||
|
||||
@defunx read-line port
|
||||
Returns a string of the characters up to, but not including a
|
||||
newline or end of file, updating @var{port} to point to the
|
||||
character following the newline. If no characters are available, an
|
||||
end of file object is returned. The @var{port} argument may be
|
||||
omitted, in which case it defaults to the value returned by
|
||||
@code{current-input-port}.
|
||||
@end defun
|
||||
|
||||
@defun read-line! string
|
||||
|
||||
|
||||
@defunx read-line! string port
|
||||
Fills @var{string} with characters up to, but not including a newline or end
|
||||
of file, updating the @var{port} to point to the last character read
|
||||
or following the newline if it was read. If no characters are
|
||||
available, an end of file object is returned. If a newline or end
|
||||
of file was found, the number of characters read is returned.
|
||||
Otherwise, @code{#f} is returned. The @var{port} argument may be
|
||||
omitted, in which case it defaults to the value returned by
|
||||
@code{current-input-port}.
|
||||
@end defun
|
||||
|
||||
@defun write-line string
|
||||
|
||||
|
||||
@defunx write-line string port
|
||||
Writes @var{string} followed by a newline to the given @var{port} and returns
|
||||
an unspecified value. The @var{Port} argument may be omitted, in
|
||||
which case it defaults to the value returned by
|
||||
@code{current-input-port}.@refill
|
||||
@end defun
|
||||
|
||||
@defun display-file path
|
||||
|
||||
|
||||
@defunx display-file path port
|
||||
Displays the contents of the file named by @var{path} to @var{port}. The
|
||||
@var{port} argument may be ommited, in which case it defaults to the
|
||||
value returned by @code{current-output-port}.
|
||||
@end defun
|
|
@ -1,168 +0,0 @@
|
|||
;;;; "logical.scm", bit access and operations for integers for Scheme
|
||||
;;; Copyright (C) 1991, 1993 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(define logical:integer-expt
|
||||
(if (provided? 'inexact)
|
||||
expt
|
||||
(lambda (n k)
|
||||
(logical:ipow-by-squaring n k 1 *))))
|
||||
|
||||
(define (logical:ipow-by-squaring x k acc proc)
|
||||
(cond ((zero? k) acc)
|
||||
((= 1 k) (proc acc x))
|
||||
(else (logical:ipow-by-squaring (proc x x)
|
||||
(quotient k 2)
|
||||
(if (even? k) acc (proc acc x))
|
||||
proc))))
|
||||
|
||||
(define (logical:logand n1 n2)
|
||||
(cond ((= n1 n2) n1)
|
||||
((zero? n1) 0)
|
||||
((zero? n2) 0)
|
||||
(else
|
||||
(+ (* (logical:logand (logical:ash-4 n1) (logical:ash-4 n2)) 16)
|
||||
(vector-ref (vector-ref logical:boole-and (modulo n1 16))
|
||||
(modulo n2 16))))))
|
||||
|
||||
(define (logical:logior n1 n2)
|
||||
(cond ((= n1 n2) n1)
|
||||
((zero? n1) n2)
|
||||
((zero? n2) n1)
|
||||
(else
|
||||
(+ (* (logical:logior (logical:ash-4 n1) (logical:ash-4 n2)) 16)
|
||||
(- 15 (vector-ref (vector-ref logical:boole-and
|
||||
(- 15 (modulo n1 16)))
|
||||
(- 15 (modulo n2 16))))))))
|
||||
|
||||
(define (logical:logxor n1 n2)
|
||||
(cond ((= n1 n2) 0)
|
||||
((zero? n1) n2)
|
||||
((zero? n2) n1)
|
||||
(else
|
||||
(+ (* (logical:logxor (logical:ash-4 n1) (logical:ash-4 n2)) 16)
|
||||
(vector-ref (vector-ref logical:boole-xor (modulo n1 16))
|
||||
(modulo n2 16))))))
|
||||
|
||||
(define (logical:lognot n) (- -1 n))
|
||||
|
||||
(define (logical:logtest int1 int2)
|
||||
(not (zero? (logical:logand int1 int2))))
|
||||
|
||||
(define (logical:logbit? index int)
|
||||
(logical:logtest (logical:integer-expt 2 index) int))
|
||||
|
||||
(define (logical:copy-bit index to bool)
|
||||
(if bool
|
||||
(logical:logior to (logical:ash 1 index))
|
||||
(logical:logand to (logical:lognot (logical:ash 1 index)))))
|
||||
|
||||
(define (logical:bit-field n start end)
|
||||
(logical:logand (- (logical:integer-expt 2 (- end start)) 1)
|
||||
(logical:ash n (- start))))
|
||||
|
||||
(define (logical:bitwise-if mask n0 n1)
|
||||
(logical:logior (logical:logand mask n0)
|
||||
(logical:logand (logical:lognot mask) n1)))
|
||||
|
||||
(define (logical:copy-bit-field to start end from)
|
||||
(logical:bitwise-if
|
||||
(logical:ash (- (logical:integer-expt 2 (- end start)) 1) start)
|
||||
(logical:ash from start)
|
||||
to))
|
||||
|
||||
(define (logical:ash int cnt)
|
||||
(if (negative? cnt)
|
||||
(let ((n (logical:integer-expt 2 (- cnt))))
|
||||
(if (negative? int)
|
||||
(+ -1 (quotient (+ 1 int) n))
|
||||
(quotient int n)))
|
||||
(* (logical:integer-expt 2 cnt) int)))
|
||||
|
||||
(define (logical:ash-4 x)
|
||||
(if (negative? x)
|
||||
(+ -1 (quotient (+ 1 x) 16))
|
||||
(quotient x 16)))
|
||||
|
||||
(define (logical:logcount n)
|
||||
(cond ((zero? n) 0)
|
||||
((negative? n) (logical:logcount (logical:lognot n)))
|
||||
(else
|
||||
(+ (logical:logcount (logical:ash-4 n))
|
||||
(vector-ref '#(0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4)
|
||||
(modulo n 16))))))
|
||||
|
||||
(define (logical:integer-length n)
|
||||
(case n
|
||||
((0 -1) 0)
|
||||
((1 -2) 1)
|
||||
((2 3 -3 -4) 2)
|
||||
((4 5 6 7 -5 -6 -7 -8) 3)
|
||||
(else (+ 4 (logical:integer-length (logical:ash-4 n))))))
|
||||
|
||||
(define logical:boole-xor
|
||||
'#(#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
|
||||
#(1 0 3 2 5 4 7 6 9 8 11 10 13 12 15 14)
|
||||
#(2 3 0 1 6 7 4 5 10 11 8 9 14 15 12 13)
|
||||
#(3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12)
|
||||
#(4 5 6 7 0 1 2 3 12 13 14 15 8 9 10 11)
|
||||
#(5 4 7 6 1 0 3 2 13 12 15 14 9 8 11 10)
|
||||
#(6 7 4 5 2 3 0 1 14 15 12 13 10 11 8 9)
|
||||
#(7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8)
|
||||
#(8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7)
|
||||
#(9 8 11 10 13 12 15 14 1 0 3 2 5 4 7 6)
|
||||
#(10 11 8 9 14 15 12 13 2 3 0 1 6 7 4 5)
|
||||
#(11 10 9 8 15 14 13 12 3 2 1 0 7 6 5 4)
|
||||
#(12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3)
|
||||
#(13 12 15 14 9 8 11 10 5 4 7 6 1 0 3 2)
|
||||
#(14 15 12 13 10 11 8 9 6 7 4 5 2 3 0 1)
|
||||
#(15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)))
|
||||
|
||||
(define logical:boole-and
|
||||
'#(#(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
|
||||
#(0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1)
|
||||
#(0 0 2 2 0 0 2 2 0 0 2 2 0 0 2 2)
|
||||
#(0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3)
|
||||
#(0 0 0 0 4 4 4 4 0 0 0 0 4 4 4 4)
|
||||
#(0 1 0 1 4 5 4 5 0 1 0 1 4 5 4 5)
|
||||
#(0 0 2 2 4 4 6 6 0 0 2 2 4 4 6 6)
|
||||
#(0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7)
|
||||
#(0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8)
|
||||
#(0 1 0 1 0 1 0 1 8 9 8 9 8 9 8 9)
|
||||
#(0 0 2 2 0 0 2 2 8 8 10 10 8 8 10 10)
|
||||
#(0 1 2 3 0 1 2 3 8 9 10 11 8 9 10 11)
|
||||
#(0 0 0 0 4 4 4 4 8 8 8 8 12 12 12 12)
|
||||
#(0 1 0 1 4 5 4 5 8 9 8 9 12 13 12 13)
|
||||
#(0 0 2 2 4 4 6 6 8 8 10 10 12 12 14 14)
|
||||
#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))
|
||||
|
||||
(define logand logical:logand)
|
||||
(define logior logical:logior)
|
||||
(define logxor logical:logxor)
|
||||
(define lognot logical:lognot)
|
||||
(define logtest logical:logtest)
|
||||
(define logbit? logical:logbit?)
|
||||
(define copy-bit logical:copy-bit)
|
||||
(define ash logical:ash)
|
||||
(define logcount logical:logcount)
|
||||
(define integer-length logical:integer-length)
|
||||
(define bit-field logical:bit-field)
|
||||
(define bit-extract logical:bit-field)
|
||||
(define copy-bit-field logical:copy-bit-field)
|
||||
(define ipow-by-squaring logical:ipow-by-squaring)
|
||||
(define integer-expt logical:integer-expt)
|
|
@ -1,54 +0,0 @@
|
|||
;;;"macrotst.scm" Test for R4RS Macros
|
||||
;;; From Revised^4 Report on the Algorithmic Language Scheme
|
||||
;;; Editors: William Clinger and Jonathon Rees
|
||||
;
|
||||
; We intend this report to belong to the entire Scheme community, and so
|
||||
; we grant permission to copy it in whole or in part without fee. In
|
||||
; particular, we encourage implementors of Scheme to use this report as
|
||||
; a starting point for manuals and other documentation, modifying it as
|
||||
; necessary.
|
||||
|
||||
;;; To run this code type
|
||||
;;; (require 'macro)
|
||||
;;; (macro:load "macrotst.scm")
|
||||
|
||||
(write "this code should print now, outer, and 7") (newline)
|
||||
|
||||
(write
|
||||
(let-syntax ((when (syntax-rules ()
|
||||
((when test stmt1 stmt2 ...)
|
||||
(if test
|
||||
(begin stmt1
|
||||
stmt2 ...))))))
|
||||
(let ((if #t))
|
||||
(when if (set! if 'now))
|
||||
if)))
|
||||
(newline)
|
||||
;;; ==> now
|
||||
|
||||
(write
|
||||
(let ((x 'outer))
|
||||
(let-syntax ((m (syntax-rules () ((m) x))))
|
||||
(let ((x 'inner))
|
||||
(m)))))
|
||||
(newline)
|
||||
;;; ==> outer
|
||||
(write
|
||||
(letrec-syntax
|
||||
((or (syntax-rules ()
|
||||
((or) #f)
|
||||
((or e) e)
|
||||
((or e1 e2 ...)
|
||||
(let ((temp e1))
|
||||
(if temp temp (or e2 ...)))))))
|
||||
(let ((x #f)
|
||||
(y 7)
|
||||
(temp 8)
|
||||
(let odd?)
|
||||
(if even?))
|
||||
(or x
|
||||
(let temp)
|
||||
(if y)
|
||||
y))))
|
||||
(newline)
|
||||
;;; ==> 7
|
|
@ -1,276 +0,0 @@
|
|||
;;;"macscheme.init" Configuration of *features* for MacScheme -*-scheme-*-
|
||||
;;; Author: Aubrey Jaffer
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
;;; From: jjb@isye.gatech.edu (John Bartholdi)
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
;;; UNIX, VMS, MACOS, AMIGA and MS-DOS are supported.
|
||||
|
||||
(define (software-type) 'MACOS)
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'MacScheme)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page) #f)
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-version) "4.2")
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define (implementation-vicinity) "Macintosh.HD:MacScheme 4.2:")
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define (library-vicinity) "Macintosh.HD:MacScheme 4.2:slib:")
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define (home-vicinity) #f)
|
||||
|
||||
;;; *FEATURES* should be set to a list of symbols describing features
|
||||
;;; of this implementation. Suggestions for features are:
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
; compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
rev4-report ;conforms to
|
||||
rev3-report ;conforms to
|
||||
ieee-p1178 ;conforms to
|
||||
; sicp ;runs code from Structure and
|
||||
;Interpretation of Computer
|
||||
;Programs by Abelson and Sussman.
|
||||
rev4-optional-procedures ;LIST-TAIL, STRING->LIST,
|
||||
;LIST->STRING, STRING-COPY,
|
||||
;STRING-FILL!, LIST->VECTOR,
|
||||
;VECTOR->LIST, and VECTOR-FILL!
|
||||
rev3-procedures ;LAST-PAIR, T, and NIL
|
||||
; rev2-procedures ;SUBSTRING-MOVE-LEFT!,
|
||||
;SUBSTRING-MOVE-RIGHT!,
|
||||
;SUBSTRING-FILL!,
|
||||
;STRING-NULL?, APPEND!, 1+,
|
||||
;-1+, <?, <=?, =?, >?, >=?
|
||||
multiarg/and- ;/ and - can take more than 2 args.
|
||||
multiarg-apply ;APPLY can take more than 2 args.
|
||||
rationalize
|
||||
delay ;has DELAY and FORCE
|
||||
with-file ;has WITH-INPUT-FROM-FILE and
|
||||
;WITH-OUTPUT-FROM-FILE
|
||||
string-port ;has CALL-WITH-INPUT-STRING and
|
||||
;CALL-WITH-OUTPUT-STRING
|
||||
; transcript ;TRANSCRIPT-ON and TRANSCRIPT-OFF
|
||||
; char-ready?
|
||||
; macro ;has R4RS high level macros
|
||||
; defmacro ;has Common Lisp DEFMACRO
|
||||
; record ;has user defined data structures
|
||||
; values ;proposed multiple values
|
||||
; dynamic-wind ;proposed dynamic-wind
|
||||
ieee-floating-point ;conforms to
|
||||
full-continuation ;can return multiple times
|
||||
; object-hash ;has OBJECT-HASH
|
||||
|
||||
; sort
|
||||
; queue ;queues
|
||||
pretty-print
|
||||
; object->string
|
||||
; format
|
||||
; trace ;has macros: TRACE and UNTRACE
|
||||
compiler ;has (COMPILER)
|
||||
; ed ;(ED) is editor
|
||||
; system ;posix (system <string>)
|
||||
; getenv ;posix (getenv <string>)
|
||||
; program-arguments ;returns list of strings (argv)
|
||||
; Xwindows ;X support
|
||||
; curses ;screen management package
|
||||
; termcap ;terminal description package
|
||||
; terminfo ;sysV terminal description
|
||||
))
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define (output-port-width . arg) 79)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (CURRENT-ERROR-PORT)
|
||||
(define current-error-port
|
||||
(let ((port (current-output-port)))
|
||||
(lambda () port)))
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam (let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(string-append "slib_" (number->string cntr)))))
|
||||
|
||||
;;; (FILE-EXISTS? <string>)
|
||||
(define (file-exists? f) #f)
|
||||
|
||||
;;; (DELETE-FILE <string>)
|
||||
(define (delete-file f) #f)
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port
|
||||
;;; use this definition if your system doesn't have such a procedure.
|
||||
(define (force-output . arg) #t)
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-*PUT-FILE.
|
||||
(define (call-with-output-string f)
|
||||
(let ((outsp (open-output-string)))
|
||||
(f outsp)
|
||||
(let ((s (get-output-string outsp)))
|
||||
(close-output-port outsp)
|
||||
s)))
|
||||
|
||||
(define (call-with-input-string s f)
|
||||
(let* ((insp (open-input-string s))
|
||||
(res (f insp)))
|
||||
(close-input-port insp)
|
||||
res))
|
||||
|
||||
;;; "rationalize" adjunct procedures.
|
||||
(define (find-ratio x e)
|
||||
(let ((rat (rationalize x e)))
|
||||
(list (numerator rat) (denominator rat))))
|
||||
(define (find-ratio-between x y)
|
||||
(find-ratio (/ (+ x y) 2) (/ (- x y) 2)))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum 536870911)
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
(define *defmacros*
|
||||
(list (cons 'defmacro
|
||||
(lambda (name parms . body)
|
||||
`(set! *defmacros* (cons (cons ',name (lambda ,parms ,@body))
|
||||
*defmacros*))))))
|
||||
(define (defmacro? m) (and (assq m *defmacros*) #t))
|
||||
|
||||
(define (macroexpand-1 e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a) (set! a (assq a *defmacros*))
|
||||
(if a (apply (cdr a) (cdr e)) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define (macroexpand e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(cond ((symbol? a)
|
||||
(set! a (assq a *defmacros*))
|
||||
(if a (macroexpand (apply (cdr a) (cdr e))) e))
|
||||
(else e)))
|
||||
e))
|
||||
|
||||
(define gentemp
|
||||
(let ((*gensym-counter* -1))
|
||||
(lambda ()
|
||||
(set! *gensym-counter* (+ *gensym-counter* 1))
|
||||
(string->symbol
|
||||
(string-append "slib:G" (number->string *gensym-counter*))))))
|
||||
|
||||
(define base:eval slib:eval)
|
||||
(define (defmacro:eval x) (base:eval (defmacro:expand* x)))
|
||||
(define (defmacro:expand* x)
|
||||
(require 'defmacroexpand) (apply defmacro:expand* x '()))
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;;; define an error procedure for the library
|
||||
(define slib:error
|
||||
(lambda args
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(cerror "Error: " args)))
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab #\tab)
|
||||
(define slib:form-feed #\page)
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
|
||||
;(define (1+ n) (+ n 1))
|
||||
;(define (-1+ n) (+ n -1))
|
||||
;(define 1- -1+)
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
; MacScheme does not return a value when it exits,
|
||||
; so simply invoke system procedure exit with 0 args.
|
||||
(define slib:exit (lambda args (exit)))
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
;(define slib:load-source load)
|
||||
(define (slib:load-source f) (load (string-append f (scheme-file-suffix))))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
|
@ -1,126 +0,0 @@
|
|||
;;;; "macwork.scm": Will Clinger's macros that work. -*- Scheme -*-
|
||||
;Copyright 1992 William Clinger
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
; I also request that you send me a copy of any improvements that you
|
||||
; make to this software so that they may be incorporated within it to
|
||||
; the benefit of the Scheme community.
|
||||
|
||||
(slib:load (in-vicinity (program-vicinity) "mwexpand"))
|
||||
|
||||
;;;; Miscellaneous routines.
|
||||
|
||||
(define (mw:warn msg . more)
|
||||
(display "WARNING from macro expander:")
|
||||
(newline)
|
||||
(display msg)
|
||||
(newline)
|
||||
(for-each (lambda (x) (write x) (newline))
|
||||
more))
|
||||
|
||||
(define (mw:error msg . more)
|
||||
(display "ERROR detected during macro expansion:")
|
||||
(newline)
|
||||
(display msg)
|
||||
(newline)
|
||||
(for-each (lambda (x) (write x) (newline))
|
||||
more)
|
||||
(mw:quit #f))
|
||||
|
||||
(define (mw:bug msg . more)
|
||||
(display "BUG in macro expander: ")
|
||||
(newline)
|
||||
(display msg)
|
||||
(newline)
|
||||
(for-each (lambda (x) (write x) (newline))
|
||||
more)
|
||||
(mw:quit #f))
|
||||
|
||||
; Given a <formals>, returns a list of bound variables.
|
||||
|
||||
(define (mw:make-null-terminated x)
|
||||
(cond ((null? x) '())
|
||||
((pair? x)
|
||||
(cons (car x) (mw:make-null-terminated (cdr x))))
|
||||
(else (list x))))
|
||||
|
||||
; Returns the length of the given list, or -1 if the argument
|
||||
; is not a list. Does not check for circular lists.
|
||||
|
||||
(define (mw:safe-length x)
|
||||
(define (loop x n)
|
||||
(cond ((null? x) n)
|
||||
((pair? x) (loop (cdr x) (+ n 1)))
|
||||
(else -1)))
|
||||
(loop x 0))
|
||||
|
||||
(require 'common-list-functions)
|
||||
|
||||
; Given an association list, copies the association pairs.
|
||||
|
||||
(define (mw:syntax-copy alist)
|
||||
(map (lambda (x) (cons (car x) (cdr x)))
|
||||
alist))
|
||||
|
||||
;;;; Implementation-dependent parameters and preferences that determine
|
||||
; how identifiers are represented in the output of the macro expander.
|
||||
;
|
||||
; The basic problem is that there are no reserved words, so the
|
||||
; syntactic keywords of core Scheme that are used to express the
|
||||
; output need to be represented by data that cannot appear in the
|
||||
; input. This file defines those data.
|
||||
|
||||
; The following definitions assume that identifiers of mixed case
|
||||
; cannot appear in the input.
|
||||
|
||||
;(define mw:begin1 (string->symbol "Begin"))
|
||||
;(define mw:define1 (string->symbol "Define"))
|
||||
;(define mw:quote1 (string->symbol "Quote"))
|
||||
;(define mw:lambda1 (string->symbol "Lambda"))
|
||||
;(define mw:if1 (string->symbol "If"))
|
||||
;(define mw:set!1 (string->symbol "Set!"))
|
||||
|
||||
(define mw:begin1 'begin)
|
||||
(define mw:define1 'define)
|
||||
(define mw:quote1 'quote)
|
||||
(define mw:lambda1 'lambda)
|
||||
(define mw:if1 'if)
|
||||
(define mw:set!1 'set!)
|
||||
|
||||
; The following defines an implementation-dependent expression
|
||||
; that evaluates to an undefined (not unspecified!) value, for
|
||||
; use in expanding the (define x) syntax.
|
||||
|
||||
(define mw:undefined (list (string->symbol "Undefined")))
|
||||
|
||||
; A variable is renamed by suffixing a vertical bar followed by a unique
|
||||
; integer. In IEEE and R4RS Scheme, a vertical bar cannot appear as part
|
||||
; of an identifier, but presumably this is enforced by the reader and not
|
||||
; by the compiler. Any other character that cannot appear as part of an
|
||||
; identifier may be used instead of the vertical bar.
|
||||
|
||||
(define mw:suffix-character #\|)
|
||||
|
||||
(slib:load (in-vicinity (program-vicinity) "mwdenote"))
|
||||
(slib:load (in-vicinity (program-vicinity) "mwsynrul"))
|
||||
|
||||
(define macro:expand macwork:expand)
|
||||
|
||||
;;; Here are EVAL, EVAL! and LOAD which expand macros. You can replace the
|
||||
;;; implementation's eval and load with them if you like.
|
||||
(define base:eval slib:eval)
|
||||
(define base:load load)
|
||||
|
||||
(define (macwork:eval x) (base:eval (macwork:expand x)))
|
||||
(define macro:eval macwork:eval)
|
||||
|
||||
(define (macwork:load <pathname>)
|
||||
(slib:eval-load <pathname> macwork:eval))
|
||||
(define macro:load macwork:load)
|
||||
|
||||
(provide 'macros-that-work)
|
||||
(provide 'macro)
|
|
@ -1,96 +0,0 @@
|
|||
;;;; "makcrc.scm" Compute Cyclic Checksums
|
||||
;;; Copyright (C) 1995, 1996, 1997, 2001 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'byte)
|
||||
(require 'logical)
|
||||
|
||||
(define (make-port-crc . margs)
|
||||
(define (make-mask hibit)
|
||||
(+ (ash (+ -1 (ash 1 (+ 1 (- hibit 2)))) 1) 1))
|
||||
(define chunk-bits (integer-length (+ -1 char-code-limit)))
|
||||
(define accum-bits #f)
|
||||
(define generator #f)
|
||||
(case (length margs)
|
||||
((0) #t)
|
||||
((1) (if (< (car margs) 128)
|
||||
(set! accum-bits (car margs))
|
||||
(set! generator (car margs))))
|
||||
((2)
|
||||
(set! accum-bits (car margs))
|
||||
(set! generator (cadr margs)))
|
||||
(else (slib:error 'make-port-crc 'args margs)))
|
||||
(cond ((not generator)
|
||||
(case accum-bits
|
||||
((#f 32) (set! accum-bits 32)
|
||||
(set! generator #b00000100110000010001110110110111)) ; CRC-32
|
||||
((16) (set! generator #b0001000000001011)) ; CRC-16
|
||||
;;((16) (set! generator #b0001000000100001)) ; CRC-CCIT
|
||||
;;((08) (set! generator #b101011))
|
||||
(else (slib:error 'make-port-crc "no default polynomial for"
|
||||
accum-bits "bits"))))
|
||||
((not accum-bits)
|
||||
(set! accum-bits (+ -1 (integer-length generator)))))
|
||||
(set! generator (logand generator (lognot (ash 1 accum-bits))))
|
||||
(cond ((>= (integer-length generator) accum-bits)
|
||||
(slib:error 'make-port-crc
|
||||
"generator longer than" accum-bits "bits")))
|
||||
(let* ((chunk-mask (make-mask chunk-bits))
|
||||
(crctab (make-vector (+ 1 chunk-mask))))
|
||||
(define (accum src)
|
||||
`(set!
|
||||
crc
|
||||
(logxor (ash (logand ,(make-mask (- accum-bits chunk-bits)) crc)
|
||||
,chunk-bits)
|
||||
(vector-ref crctab
|
||||
(logand ,chunk-mask
|
||||
(logxor
|
||||
(ash crc ,(- chunk-bits accum-bits))
|
||||
,src))))))
|
||||
(define (make-crc-table)
|
||||
(letrec ((r (make-vector chunk-bits))
|
||||
(remd (lambda (m)
|
||||
(define rem 0)
|
||||
(do ((i 0 (+ 1 i)))
|
||||
((>= i chunk-bits) rem)
|
||||
(if (logbit? i m)
|
||||
(set! rem (logxor rem (vector-ref r i))))))))
|
||||
(vector-set! r 0 generator)
|
||||
(do ((i 1 (+ 1 i)))
|
||||
((>= i chunk-bits))
|
||||
(let ((r-1 (vector-ref r (+ -1 i)))
|
||||
(m-1 (make-mask (+ -1 accum-bits))))
|
||||
(vector-set! r i (if (logbit? (+ -1 accum-bits) r-1)
|
||||
(logxor (ash (logand m-1 r-1) 1) generator)
|
||||
(ash (logand m-1 r-1) 1)))))
|
||||
(do ((i 0 (+ 1 i)))
|
||||
((> i chunk-mask))
|
||||
(vector-set! crctab i (remd i)))))
|
||||
(make-crc-table)
|
||||
`(lambda (port)
|
||||
(define crc 0)
|
||||
(define byte-count 0)
|
||||
(define crctab ',crctab)
|
||||
(do ((ci (read-byte port) (read-byte port)))
|
||||
((eof-object? ci))
|
||||
,(accum 'ci)
|
||||
(set! byte-count (+ 1 byte-count)))
|
||||
(do ((byte-count byte-count (ash byte-count ,(- chunk-bits))))
|
||||
((zero? byte-count))
|
||||
,(accum 'byte-count))
|
||||
(logxor ,(make-mask accum-bits) crc))))
|
|
@ -1,443 +0,0 @@
|
|||
;;;; "mbe.scm" "Macro by Example" (Eugene Kohlbecker, R4RS)
|
||||
;;; From: Dorai Sitaram, dorai@cs.rice.edu, 1991, 1999
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; revised Dec. 6, 1993 to R4RS syntax (if not semantics).
|
||||
;;; revised Mar. 2 1994 for SLIB (jaffer@ai.mit.edu).
|
||||
;;; corrections, Apr. 24, 1997.
|
||||
;;; corr., Jan. 30, 1999. (mflatt@cs.rice.edu, dorai@cs.rice.edu)
|
||||
|
||||
;;; A vanilla implementation of hygienic macro-by-example as described
|
||||
;;; by Eugene Kohlbecker and in R4RS Appendix. This file requires
|
||||
;;; defmacro.
|
||||
|
||||
(require 'common-list-functions) ;nconc, some, every
|
||||
;(require 'rev2-procedures) ;append! alternate for nconc
|
||||
(require 'rev4-optional-procedures) ;list-tail
|
||||
(require 'defmacroexpand)
|
||||
|
||||
(define hyg:rassq
|
||||
(lambda (k al)
|
||||
(let loop ((al al))
|
||||
(if (null? al) #f
|
||||
(let ((c (car al)))
|
||||
(if (eq? (cdr c) k) c
|
||||
(loop (cdr al))))))))
|
||||
|
||||
(define hyg:tag
|
||||
(lambda (e kk al)
|
||||
(cond ((pair? e)
|
||||
(let* ((a-te-al (hyg:tag (car e) kk al))
|
||||
(d-te-al (hyg:tag (cdr e) kk (cdr a-te-al))))
|
||||
(cons (cons (car a-te-al) (car d-te-al))
|
||||
(cdr d-te-al))))
|
||||
((vector? e)
|
||||
(list->vector
|
||||
(hyg:tag (vector->list e) kk al)))
|
||||
((symbol? e)
|
||||
(cond ((eq? e '...) (cons '... al))
|
||||
((memq e kk) (cons e al))
|
||||
((hyg:rassq e al) =>
|
||||
(lambda (c)
|
||||
(cons (car c) al)))
|
||||
(else
|
||||
(let ((te (gentemp)))
|
||||
(cons te (cons (cons te e) al))))))
|
||||
(else (cons e al)))))
|
||||
|
||||
;;untagging
|
||||
|
||||
(define hyg:untag
|
||||
(lambda (e al tmps)
|
||||
(if (pair? e)
|
||||
(let ((a (hyg:untag (car e) al tmps)))
|
||||
(if (list? e)
|
||||
(case a
|
||||
((quote) (hyg:untag-no-tags e al))
|
||||
((quasiquote) (list a (hyg:untag-quasiquote (cadr e) al tmps)))
|
||||
((if begin)
|
||||
`(,a ,@(map (lambda (e1)
|
||||
(hyg:untag e1 al tmps)) (cdr e))))
|
||||
((set! define)
|
||||
`(,a ,(hyg:untag-vanilla (cadr e) al tmps)
|
||||
,@(map (lambda (e1)
|
||||
(hyg:untag e1 al tmps)) (cddr e))))
|
||||
((lambda) (hyg:untag-lambda (cadr e) (cddr e) al tmps))
|
||||
((letrec) (hyg:untag-letrec (cadr e) (cddr e) al tmps))
|
||||
((let)
|
||||
(let ((e2 (cadr e)))
|
||||
(if (symbol? e2)
|
||||
(hyg:untag-named-let e2 (caddr e) (cdddr e) al tmps)
|
||||
(hyg:untag-let e2 (cddr e) al tmps))))
|
||||
((let*) (hyg:untag-let* (cadr e) (cddr e) al tmps))
|
||||
((do) (hyg:untag-do (cadr e) (caddr e) (cdddr e) al tmps))
|
||||
((case)
|
||||
`(case ,(hyg:untag-vanilla (cadr e) al tmps)
|
||||
,@(map
|
||||
(lambda (c)
|
||||
`(,(hyg:untag-vanilla (car c) al tmps)
|
||||
,@(hyg:untag-list (cdr c) al tmps)))
|
||||
(cddr e))))
|
||||
((cond)
|
||||
`(cond ,@(map
|
||||
(lambda (c)
|
||||
(hyg:untag-list c al tmps))
|
||||
(cdr e))))
|
||||
(else (cons a (hyg:untag-list (cdr e) al tmps))))
|
||||
(cons a (hyg:untag-list* (cdr e) al tmps))))
|
||||
(hyg:untag-vanilla e al tmps))))
|
||||
|
||||
(define hyg:untag-list
|
||||
(lambda (ee al tmps)
|
||||
(map (lambda (e)
|
||||
(hyg:untag e al tmps)) ee)))
|
||||
|
||||
(define hyg:untag-list*
|
||||
(lambda (ee al tmps)
|
||||
(let loop ((ee ee))
|
||||
(if (pair? ee)
|
||||
(cons (hyg:untag (car ee) al tmps)
|
||||
(loop (cdr ee)))
|
||||
(hyg:untag ee al tmps)))))
|
||||
|
||||
(define hyg:untag-no-tags
|
||||
(lambda (e al)
|
||||
(cond ((pair? e)
|
||||
(cons (hyg:untag-no-tags (car e) al)
|
||||
(hyg:untag-no-tags (cdr e) al)))
|
||||
((vector? e)
|
||||
(list->vector
|
||||
(hyg:untag-no-tags (vector->list e) al)))
|
||||
((not (symbol? e)) e)
|
||||
((assq e al) => cdr)
|
||||
(else e))))
|
||||
|
||||
(define hyg:untag-quasiquote
|
||||
(lambda (form al tmps)
|
||||
(let qq ((x form) (level 0))
|
||||
(cond
|
||||
((pair? x)
|
||||
(let ((first (qq (car x) level)))
|
||||
(cond
|
||||
((and (eq? first 'unquote) (list? x))
|
||||
(let ((rest (cdr x)))
|
||||
(if (or (not (pair? rest))
|
||||
(not (null? (cdr rest))))
|
||||
(slib:error 'unquote 'takes-exactly-one-expression)
|
||||
(if (zero? level)
|
||||
(list 'unquote (hyg:untag (car rest) al tmps))
|
||||
(cons first (qq rest (sub1 level)))))))
|
||||
((and (eq? first 'quasiquote) (list? x))
|
||||
(cons 'quasiquote (qq (cdr x) (add1 level))))
|
||||
((and (eq? first 'unquote-splicing) (list? x))
|
||||
(slib:error 'unquote-splicing 'invalid-context-within-quasiquote))
|
||||
((pair? first)
|
||||
(let ((car-first (qq (car first) level)))
|
||||
(if (and (eq? car-first 'unquote-splicing)
|
||||
(list? first))
|
||||
(let ((rest (cdr first)))
|
||||
(if (or (not (pair? rest))
|
||||
(not (null? (cdr rest))))
|
||||
(slib:error 'unquote-splicing
|
||||
'takes-exactly-one-expression)
|
||||
(list (list 'unquote-splicing
|
||||
(if (zero? level)
|
||||
(hyg:untag (cadr rest) al tmps)
|
||||
(qq (cadr rest) (sub1 level)))
|
||||
(qq (cdr x) level)))))
|
||||
(cons (cons car-first
|
||||
(qq (cdr first) level))
|
||||
(qq (cdr x) level)))))
|
||||
(else
|
||||
(cons first (qq (cdr x) level))))))
|
||||
((vector? x)
|
||||
(list->vector
|
||||
(qq (vector->list x) level)))
|
||||
(else (hyg:untag-no-tags x al))))))
|
||||
|
||||
(define hyg:untag-lambda
|
||||
(lambda (bvv body al tmps)
|
||||
(let ((tmps2 (nconc (hyg:flatten bvv) tmps)))
|
||||
`(lambda ,bvv
|
||||
,@(hyg:untag-list body al tmps2)))))
|
||||
|
||||
(define hyg:untag-letrec
|
||||
(lambda (varvals body al tmps)
|
||||
(let ((tmps (nconc (map car varvals) tmps)))
|
||||
`(letrec
|
||||
,(map
|
||||
(lambda (varval)
|
||||
`(,(car varval)
|
||||
,(hyg:untag (cadr varval) al tmps)))
|
||||
varvals)
|
||||
,@(hyg:untag-list body al tmps)))))
|
||||
|
||||
(define hyg:untag-let
|
||||
(lambda (varvals body al tmps)
|
||||
(let ((tmps2 (nconc (map car varvals) tmps)))
|
||||
`(let
|
||||
,(map
|
||||
(lambda (varval)
|
||||
`(,(car varval)
|
||||
,(hyg:untag (cadr varval) al tmps)))
|
||||
varvals)
|
||||
,@(hyg:untag-list body al tmps2)))))
|
||||
|
||||
(define hyg:untag-named-let
|
||||
(lambda (lname varvals body al tmps)
|
||||
(let ((tmps2 (cons lname (nconc (map car varvals) tmps))))
|
||||
`(let ,lname
|
||||
,(map
|
||||
(lambda (varval)
|
||||
`(,(car varval)
|
||||
,(hyg:untag (cadr varval) al tmps)))
|
||||
varvals)
|
||||
,@(hyg:untag-list body al tmps2)))))
|
||||
|
||||
(define hyg:untag-let*
|
||||
(lambda (varvals body al tmps)
|
||||
(let ((tmps2 (nconc (nreverse (map car varvals)) tmps)))
|
||||
`(let*
|
||||
,(let loop ((varvals varvals)
|
||||
(i (length varvals)))
|
||||
(if (null? varvals) '()
|
||||
(let ((varval (car varvals)))
|
||||
(cons `(,(car varval)
|
||||
,(hyg:untag (cadr varval)
|
||||
al (list-tail tmps2 i)))
|
||||
(loop (cdr varvals) (- i 1))))))
|
||||
,@(hyg:untag-list body al tmps2)))))
|
||||
|
||||
(define hyg:untag-do
|
||||
(lambda (varinistps exit-test body al tmps)
|
||||
(let ((tmps2 (nconc (map car varinistps) tmps)))
|
||||
`(do
|
||||
,(map
|
||||
(lambda (varinistp)
|
||||
(let ((var (car varinistp)))
|
||||
`(,var ,@(hyg:untag-list (cdr varinistp) al
|
||||
(cons var tmps)))))
|
||||
varinistps)
|
||||
,(hyg:untag-list exit-test al tmps2)
|
||||
,@(hyg:untag-list body al tmps2)))))
|
||||
|
||||
(define hyg:untag-vanilla
|
||||
(lambda (e al tmps)
|
||||
(cond ((pair? e)
|
||||
(cons (hyg:untag-vanilla (car e) al tmps)
|
||||
(hyg:untag-vanilla (cdr e) al tmps)))
|
||||
((vector? e)
|
||||
(list->vector
|
||||
(hyg:untag-vanilla (vector->list e) al tmps)))
|
||||
((not (symbol? e)) e)
|
||||
((memq e tmps) e)
|
||||
((assq e al) => cdr)
|
||||
(else e))))
|
||||
|
||||
(define hyg:flatten
|
||||
(lambda (e)
|
||||
(let loop ((e e) (r '()))
|
||||
(cond ((pair? e) (loop (car e)
|
||||
(loop (cdr e) r)))
|
||||
((null? e) r)
|
||||
(else (cons e r))))))
|
||||
|
||||
;;;; End of hygiene filter.
|
||||
|
||||
|
||||
;;; finds the leftmost index of list l where something equal to x
|
||||
;;; occurs
|
||||
(define mbe:position
|
||||
(lambda (x l)
|
||||
(let loop ((l l) (i 0))
|
||||
(cond ((not (pair? l)) #f)
|
||||
((equal? (car l) x) i)
|
||||
(else (loop (cdr l) (+ i 1)))))))
|
||||
|
||||
;;; (mbe:append-map f l) == (apply append (map f l))
|
||||
|
||||
(define mbe:append-map
|
||||
(lambda (f l)
|
||||
(let loop ((l l))
|
||||
(if (null? l) '()
|
||||
(append (f (car l)) (loop (cdr l)))))))
|
||||
|
||||
;;; tests if expression e matches pattern p where k is the list of
|
||||
;;; keywords
|
||||
(define mbe:matches-pattern?
|
||||
(lambda (p e k)
|
||||
(cond ((mbe:ellipsis? p)
|
||||
(and (or (null? e) (pair? e))
|
||||
(let* ((p-head (car p))
|
||||
(p-tail (cddr p))
|
||||
(e-head=e-tail (mbe:split-at-ellipsis e p-tail)))
|
||||
(and e-head=e-tail
|
||||
(let ((e-head (car e-head=e-tail))
|
||||
(e-tail (cdr e-head=e-tail)))
|
||||
(and (every
|
||||
(lambda (x) (mbe:matches-pattern? p-head x k))
|
||||
e-head)
|
||||
(mbe:matches-pattern? p-tail e-tail k)))))))
|
||||
((pair? p)
|
||||
(and (pair? e)
|
||||
(mbe:matches-pattern? (car p) (car e) k)
|
||||
(mbe:matches-pattern? (cdr p) (cdr e) k)))
|
||||
((symbol? p) (if (memq p k) (eq? p e) #t))
|
||||
(else (equal? p e)))))
|
||||
|
||||
;;; gets the bindings of pattern variables of pattern p for
|
||||
;;; expression e;
|
||||
;;; k is the list of keywords
|
||||
(define mbe:get-bindings
|
||||
(lambda (p e k)
|
||||
(cond ((mbe:ellipsis? p)
|
||||
(let* ((p-head (car p))
|
||||
(p-tail (cddr p))
|
||||
(e-head=e-tail (mbe:split-at-ellipsis e p-tail))
|
||||
(e-head (car e-head=e-tail))
|
||||
(e-tail (cdr e-head=e-tail)))
|
||||
(cons (cons (mbe:get-ellipsis-nestings p-head k)
|
||||
(map (lambda (x) (mbe:get-bindings p-head x k))
|
||||
e-head))
|
||||
(mbe:get-bindings p-tail e-tail k))))
|
||||
((pair? p)
|
||||
(append (mbe:get-bindings (car p) (car e) k)
|
||||
(mbe:get-bindings (cdr p) (cdr e) k)))
|
||||
((symbol? p)
|
||||
(if (memq p k) '() (list (cons p e))))
|
||||
(else '()))))
|
||||
|
||||
;;; expands pattern p using environment r;
|
||||
;;; k is the list of keywords
|
||||
(define mbe:expand-pattern
|
||||
(lambda (p r k)
|
||||
(cond ((mbe:ellipsis? p)
|
||||
(append (let* ((p-head (car p))
|
||||
(nestings (mbe:get-ellipsis-nestings p-head k))
|
||||
(rr (mbe:ellipsis-sub-envs nestings r)))
|
||||
(map (lambda (r1)
|
||||
(mbe:expand-pattern p-head (append r1 r) k))
|
||||
rr))
|
||||
(mbe:expand-pattern (cddr p) r k)))
|
||||
((pair? p)
|
||||
(cons (mbe:expand-pattern (car p) r k)
|
||||
(mbe:expand-pattern (cdr p) r k)))
|
||||
((symbol? p)
|
||||
(if (memq p k) p
|
||||
(let ((x (assq p r)))
|
||||
(if x (cdr x) p))))
|
||||
(else p))))
|
||||
|
||||
;;; returns a list that nests a pattern variable as deeply as it
|
||||
;;; is ellipsed
|
||||
(define mbe:get-ellipsis-nestings
|
||||
(lambda (p k)
|
||||
(let sub ((p p))
|
||||
(cond ((mbe:ellipsis? p) (cons (sub (car p)) (sub (cddr p))))
|
||||
((pair? p) (append (sub (car p)) (sub (cdr p))))
|
||||
((symbol? p) (if (memq p k) '() (list p)))
|
||||
(else '())))))
|
||||
|
||||
;;; finds the subenvironments in r corresponding to the ellipsed
|
||||
;;; variables in nestings
|
||||
|
||||
(define mbe:ellipsis-sub-envs
|
||||
(lambda (nestings r)
|
||||
(let ((sub-envs-list
|
||||
(let loop ((r r) (sub-envs-list '()))
|
||||
(if (null? r) (nreverse sub-envs-list)
|
||||
(let ((c (car r)))
|
||||
(loop (cdr r)
|
||||
(if (mbe:contained-in? nestings (car c))
|
||||
(cons (cdr c) sub-envs-list)
|
||||
sub-envs-list)))))))
|
||||
(case (length sub-envs-list)
|
||||
((0) #f)
|
||||
((1) (car sub-envs-list))
|
||||
(else
|
||||
(let loop ((sub-envs-list sub-envs-list) (final-sub-envs '()))
|
||||
(if (some null? sub-envs-list) (nreverse final-sub-envs)
|
||||
(loop (map cdr sub-envs-list)
|
||||
(cons (mbe:append-map car sub-envs-list)
|
||||
final-sub-envs)))))))))
|
||||
|
||||
;;; checks if nestings v and y have an intersection
|
||||
(define mbe:contained-in?
|
||||
(lambda (v y)
|
||||
(if (or (symbol? v) (symbol? y)) (eq? v y)
|
||||
(some (lambda (v_i)
|
||||
(some (lambda (y_j)
|
||||
(mbe:contained-in? v_i y_j))
|
||||
y))
|
||||
v))))
|
||||
|
||||
;;; split expression e so that its second half matches with
|
||||
;;; pattern p-tail
|
||||
(define mbe:split-at-ellipsis
|
||||
(lambda (e p-tail)
|
||||
(if (null? p-tail) (cons e '())
|
||||
(let ((i (mbe:position (car p-tail) e)))
|
||||
(if i (cons (butlast e (- (length e) i))
|
||||
(list-tail e i))
|
||||
(slib:error 'mbe:split-at-ellipsis 'bad-arg))))))
|
||||
|
||||
;;; tests if x is an ellipsing pattern, i.e., of the form
|
||||
;;; (blah ... . blah2)
|
||||
(define mbe:ellipsis?
|
||||
(lambda (x)
|
||||
(and (pair? x) (pair? (cdr x)) (eq? (cadr x) '...))))
|
||||
|
||||
;define-syntax
|
||||
|
||||
(defmacro define-syntax (macro-name syn-rules)
|
||||
(if (or (not (pair? syn-rules))
|
||||
(not (eq? (car syn-rules) 'syntax-rules)))
|
||||
(slib:error 'define-syntax 'not-an-r4rs-high-level-macro
|
||||
macro-name syn-rules)
|
||||
(let ((keywords (cons macro-name (cadr syn-rules)))
|
||||
(clauses (cddr syn-rules)))
|
||||
`(defmacro ,macro-name macro-arg
|
||||
(let ((macro-arg (cons ',macro-name macro-arg))
|
||||
(keywords ',keywords))
|
||||
(cond ,@(map
|
||||
(lambda (clause)
|
||||
(let ((in-pattern (car clause))
|
||||
(out-pattern (cadr clause)))
|
||||
`((mbe:matches-pattern? ',in-pattern macro-arg
|
||||
keywords)
|
||||
(let ((tagged-out-pattern+alist
|
||||
(hyg:tag
|
||||
',out-pattern
|
||||
(nconc (hyg:flatten ',in-pattern)
|
||||
keywords) '())))
|
||||
(hyg:untag
|
||||
(mbe:expand-pattern
|
||||
(car tagged-out-pattern+alist)
|
||||
(mbe:get-bindings ',in-pattern macro-arg
|
||||
keywords)
|
||||
keywords)
|
||||
(cdr tagged-out-pattern+alist)
|
||||
'())))))
|
||||
clauses)
|
||||
(else (slib:error ',macro-name 'no-matching-clause
|
||||
',clauses))))))))
|
||||
|
||||
(define macro:eval slib:eval)
|
||||
(define macro:load slib:load)
|
||||
(provide 'macro)
|
||||
;eof
|
|
@ -1,114 +0,0 @@
|
|||
;;; "minimize.scm" finds minimum f(x) for x0 <= x <= x1.
|
||||
;;; Author: Lars Arvestad
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
;;@noindent
|
||||
;;
|
||||
;;The Golden Section Search
|
||||
;;@footnote{David Kahaner, Cleve Moler, and Stephen Nash
|
||||
;;@cite{Numerical Methods and Software}
|
||||
;;Prentice-Hall, 1989, ISBN 0-13-627258-4}
|
||||
;;algorithm finds minima of functions which
|
||||
;;are expensive to compute or for which derivatives are not available.
|
||||
;;Although optimum for the general case, convergence is slow,
|
||||
;;requiring nearly 100 iterations for the example (x^3-2x-5).
|
||||
;;
|
||||
;;@noindent
|
||||
;;
|
||||
;;If the derivative is available, Newton-Raphson is probably a better
|
||||
;;choice. If the function is inexpensive to compute, consider
|
||||
;;approximating the derivative.
|
||||
|
||||
;;@body
|
||||
;;
|
||||
;;@var{x_0} are @var{x_1} real numbers. The (single argument)
|
||||
;;procedure @var{f} is unimodal over the open interval (@var{x_0},
|
||||
;;@var{x_1}). That is, there is exactly one point in the interval for
|
||||
;;which the derivative of @var{f} is zero.
|
||||
;;
|
||||
;;@0 returns a pair (@var{x} . @var{f}(@var{x})) where @var{f}(@var{x})
|
||||
;;is the minimum. The @var{prec} parameter is the stop criterion. If
|
||||
;;@var{prec} is a positive number, then the iteration continues until
|
||||
;;@var{x} is within @var{prec} from the true value. If @var{prec} is
|
||||
;;a negative integer, then the procedure will iterate @var{-prec}
|
||||
;;times or until convergence. If @var{prec} is a procedure of seven
|
||||
;;arguments, @var{x0}, @var{x1}, @var{a}, @var{b}, @var{fa}, @var{fb},
|
||||
;;and @var{count}, then the iterations will stop when the procedure
|
||||
;;returns @code{#t}.
|
||||
;;
|
||||
;;Analytically, the minimum of x^3-2x-5 is 0.816497.
|
||||
;;@example
|
||||
;;(define func (lambda (x) (+ (* x (+ (* x x) -2)) -5)))
|
||||
;;(golden-section-search func 0 1 (/ 10000))
|
||||
;; ==> (816.4883855245578e-3 . -6.0886621077391165)
|
||||
;;(golden-section-search func 0 1 -5)
|
||||
;; ==> (819.6601125010515e-3 . -6.088637561916407)
|
||||
;;(golden-section-search func 0 1
|
||||
;; (lambda (a b c d e f g ) (= g 500)))
|
||||
;; ==> (816.4965933140557e-3 . -6.088662107903635)
|
||||
;;@end example
|
||||
|
||||
(define golden-section-search
|
||||
(let ((gss 'golden-section-search:)
|
||||
(r (/ (- (sqrt 5) 1) 2))) ; 1 / golden-section
|
||||
(lambda (f x0 x1 prec)
|
||||
(cond ((not (procedure? f)) (slib:error gss 'procedure? f))
|
||||
((not (number? x0)) (slib:error gss 'number? x0))
|
||||
((not (number? x1)) (slib:error gss 'number? x1))
|
||||
((>= x0 x1) (slib:error gss x0 'not '< x1)))
|
||||
(let ((stop?
|
||||
(cond
|
||||
((procedure? prec) prec)
|
||||
((number? prec)
|
||||
(if (>= prec 0)
|
||||
(lambda (x0 x1 a b fa fb count) (<= (abs (- x1 x0)) prec))
|
||||
(if (integer? prec)
|
||||
(lambda (x0 x1 a b fa fb count) (>= count (- prec)))
|
||||
(slib:error gss 'integer? prec))))
|
||||
(else (slib:error gss 'procedure? prec))))
|
||||
(a0 (+ x0 (* (- x1 x0) (- 1 r))))
|
||||
(b0 (+ x0 (* (- x1 x0) r)))
|
||||
(delta #f)
|
||||
(fmax #f)
|
||||
(fmin #f))
|
||||
(let loop ((left x0)
|
||||
(right x1)
|
||||
(a a0)
|
||||
(b b0)
|
||||
(fa (f a0))
|
||||
(fb (f b0))
|
||||
(count 1))
|
||||
(define finish
|
||||
(lambda (x fx)
|
||||
(if (> fx fmin) (slib:warn gss fx 'not 'min (list '> fmin)))
|
||||
(if (and (> count 9) (or (eqv? x0 left) (eqv? x1 right)))
|
||||
(slib:warn gss 'min 'not 'found))
|
||||
(cons x fx)))
|
||||
(case count
|
||||
((1)
|
||||
(set! fmax (max fa fb))
|
||||
(set! fmin (min fa fb)))
|
||||
((2)
|
||||
(set! fmin (min fmin fa fb))
|
||||
(if (eqv? fmax fa fb) (slib:error gss 'flat? fmax)))
|
||||
(else
|
||||
(set! fmin (min fmin fa fb))))
|
||||
(cond ((stop? left right a b fa fb count)
|
||||
(if (< fa fb)
|
||||
(finish a fa)
|
||||
(finish b fb)))
|
||||
((< fa fb)
|
||||
(let ((a-next (+ left (* (- b left) (- 1 r)))))
|
||||
(cond ((and delta (< delta (- b a)))
|
||||
(finish a fa))
|
||||
(else (set! delta (- b a))
|
||||
(loop left b a-next a (f a-next) fa
|
||||
(+ 1 count))))))
|
||||
(else
|
||||
(let ((b-next (+ a (* (- right a) r))))
|
||||
(cond ((and delta (< delta (- b a)))
|
||||
(finish b fb))
|
||||
(else (set! delta (- b a))
|
||||
(loop a right b b-next fb (f b-next)
|
||||
(+ 1 count))))))))))))
|
|
@ -1,48 +0,0 @@
|
|||
@noindent
|
||||
|
||||
The Golden Section Search
|
||||
@footnote{David Kahaner, Cleve Moler, and Stephen Nash
|
||||
@cite{Numerical Methods and Software}
|
||||
Prentice-Hall, 1989, ISBN 0-13-627258-4}
|
||||
algorithm finds minima of functions which
|
||||
are expensive to compute or for which derivatives are not available.
|
||||
Although optimum for the general case, convergence is slow,
|
||||
requiring nearly 100 iterations for the example (x^3-2x-5).
|
||||
|
||||
@noindent
|
||||
|
||||
If the derivative is available, Newton-Raphson is probably a better
|
||||
choice. If the function is inexpensive to compute, consider
|
||||
approximating the derivative.
|
||||
|
||||
|
||||
@defun golden-section-search f x0 x1 prec
|
||||
|
||||
|
||||
@var{x_0} are @var{x_1} real numbers. The (single argument)
|
||||
procedure @var{f} is unimodal over the open interval (@var{x_0},
|
||||
@var{x_1}). That is, there is exactly one point in the interval for
|
||||
which the derivative of @var{f} is zero.
|
||||
|
||||
@code{golden-section-search} returns a pair (@var{x} . @var{f}(@var{x})) where @var{f}(@var{x})
|
||||
is the minimum. The @var{prec} parameter is the stop criterion. If
|
||||
@var{prec} is a positive number, then the iteration continues until
|
||||
@var{x} is within @var{prec} from the true value. If @var{prec} is
|
||||
a negative integer, then the procedure will iterate @var{-prec}
|
||||
times or until convergence. If @var{prec} is a procedure of seven
|
||||
arguments, @var{x0}, @var{x1}, @var{a}, @var{b}, @var{fa}, @var{fb},
|
||||
and @var{count}, then the iterations will stop when the procedure
|
||||
returns @code{#t}.
|
||||
|
||||
Analytically, the minimum of x^3-2x-5 is 0.816497.
|
||||
@example
|
||||
(define func (lambda (x) (+ (* x (+ (* x x) -2)) -5)))
|
||||
(golden-section-search func 0 1 (/ 10000))
|
||||
==> (816.4883855245578e-3 . -6.0886621077391165)
|
||||
(golden-section-search func 0 1 -5)
|
||||
==> (819.6601125010515e-3 . -6.088637561916407)
|
||||
(golden-section-search func 0 1
|
||||
(lambda (a b c d e f g ) (= g 500)))
|
||||
==> (816.4965933140557e-3 . -6.088662107903635)
|
||||
@end example
|
||||
@end defun
|
File diff suppressed because it is too large
Load diff
|
@ -1,283 +0,0 @@
|
|||
;;;"mitscheme.init" Initialization for SLIB for MITScheme -*-scheme-*-
|
||||
;;; Author: Aubrey Jaffer
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
;;; Make this part of your ~/.scheme.init file.
|
||||
|
||||
(define getenv get-environment-variable)
|
||||
|
||||
;;; (software-type) should be set to the generic operating system type.
|
||||
(define (software-type) (if (getenv "HOMEDRIVE") 'MS-DOS 'UNIX))
|
||||
|
||||
;;; (scheme-implementation-type) should return the name of the scheme
|
||||
;;; implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-type) 'MITScheme)
|
||||
|
||||
;;; (scheme-implementation-home-page) should return a (string) URI
|
||||
;;; (Uniform Resource Identifier) for this scheme implementation's home
|
||||
;;; page; or false if there isn't one.
|
||||
|
||||
(define (scheme-implementation-home-page)
|
||||
"http://swissnet.ai.mit.edu/scheme-home.html")
|
||||
|
||||
;;; (scheme-implementation-version) should return a string describing
|
||||
;;; the version the scheme implementation loading this file.
|
||||
|
||||
(define (scheme-implementation-version)
|
||||
(let* ((str (with-output-to-string identify-world))
|
||||
(beg (+ (string-search-forward "Release " str) 8))
|
||||
(rst (substring str beg (string-length str)))
|
||||
(end (string-find-next-char-in-set
|
||||
rst
|
||||
(predicate->char-set char-whitespace?))))
|
||||
(substring rst 0 end)))
|
||||
|
||||
;;; (implementation-vicinity) should be defined to be the pathname of
|
||||
;;; the directory where any auxillary files to your Scheme
|
||||
;;; implementation reside.
|
||||
|
||||
(define (implementation-vicinity)
|
||||
(case (software-type)
|
||||
((MS-DOS) "c:\\scheme\\")
|
||||
((UNIX) "/usr/local/lib/mit-scheme/")
|
||||
((VMS) "scheme$src:")))
|
||||
|
||||
;;; (library-vicinity) should be defined to be the pathname of the
|
||||
;;; directory where files of Scheme library functions reside.
|
||||
|
||||
(define library-vicinity
|
||||
(let ((library-path
|
||||
(or (getenv "SCHEME_LIBRARY_PATH")
|
||||
;; Use this path if your scheme does not support GETENV.
|
||||
(case (software-type)
|
||||
((MS-DOS) "c:\\slib\\")
|
||||
((UNIX) "/usr/local/lib/slib/")
|
||||
((VMS) "lib$scheme:")
|
||||
(else "")))))
|
||||
(lambda () library-path)))
|
||||
|
||||
;;; (home-vicinity) should return the vicinity of the user's HOME
|
||||
;;; directory, the directory which typically contains files which
|
||||
;;; customize a computer environment for a user.
|
||||
|
||||
(define home-vicinity
|
||||
(let ((home-path (getenv "HOME")))
|
||||
(lambda () home-path)))
|
||||
|
||||
;;; *features* should be set to a list of symbols describing features
|
||||
;;; of this implementation. See Template.scm for the list of feature
|
||||
;;; names.
|
||||
|
||||
(define *features*
|
||||
'(
|
||||
source ;can load scheme source files
|
||||
;(slib:load-source "filename")
|
||||
compiled ;can load compiled files
|
||||
;(slib:load-compiled "filename")
|
||||
rev4-report
|
||||
ieee-p1178
|
||||
sicp
|
||||
rev4-optional-procedures
|
||||
rev3-procedures
|
||||
rev2-procedures
|
||||
multiarg/and-
|
||||
multiarg-apply
|
||||
rationalize
|
||||
object-hash
|
||||
delay
|
||||
with-file
|
||||
string-port
|
||||
transcript
|
||||
char-ready?
|
||||
record
|
||||
values
|
||||
dynamic-wind
|
||||
ieee-floating-point
|
||||
full-continuation
|
||||
; sort
|
||||
queue
|
||||
pretty-print
|
||||
object->string
|
||||
trace ;has macros: TRACE and UNTRACE
|
||||
defmacro
|
||||
compiler
|
||||
getenv
|
||||
Xwindows
|
||||
current-time
|
||||
))
|
||||
|
||||
(define current-time current-file-time)
|
||||
(define difftime -)
|
||||
(define offset-time +)
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
(define output-port-width output-port/x-size)
|
||||
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
(define (output-port-height . arg) 24)
|
||||
|
||||
;;; (CURRENT-ERROR-PORT)
|
||||
(define current-error-port
|
||||
(let ((port console-output-port))
|
||||
(lambda () port)))
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam
|
||||
(let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(let ((tmp (string-append "slib_" (number->string cntr))))
|
||||
(if (file-exists? tmp) (tmpnam) tmp)))))
|
||||
|
||||
;;; FORCE-OUTPUT flushes any pending output on optional arg output port.
|
||||
(define force-output flush-output)
|
||||
;;; MITScheme 7.2 is missing flush-output. Use this instead
|
||||
;(define (force-output . arg) #t)
|
||||
|
||||
;;; CALL-WITH-INPUT-STRING and CALL-WITH-OUTPUT-STRING are the string
|
||||
;;; port versions of CALL-WITH-*PUT-FILE.
|
||||
(define (call-with-output-string proc)
|
||||
(let ((co (current-output-port)))
|
||||
(with-output-to-string
|
||||
(lambda ()
|
||||
(let ((port (current-output-port)))
|
||||
(with-output-to-port co
|
||||
(lambda () (proc port))))))))
|
||||
|
||||
(define (call-with-input-string string proc)
|
||||
(let ((ci (current-input-port)))
|
||||
(with-input-from-string string
|
||||
(lambda ()
|
||||
(let ((port (current-input-port)))
|
||||
(with-input-from-port ci
|
||||
(lambda () (proc port))))))))
|
||||
|
||||
(define object->string write-to-string)
|
||||
(define object->limited-string write-to-string)
|
||||
|
||||
;;; "rationalize" adjunct procedures.
|
||||
(define (find-ratio x e)
|
||||
(let ((rat (rationalize x e)))
|
||||
(list (numerator rat) (denominator rat))))
|
||||
(define (find-ratio-between x y)
|
||||
(find-ratio (/ (+ x y) 2) (/ (- x y) 2)))
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER. It is defined incorrectly (65536)
|
||||
;;; by MITScheme version 8.0.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
(define most-positive-fixnum #x03FFFFFF)
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
;(define (slib:eval form) (eval form (repl/environment (nearest-repl))))
|
||||
(define (slib:eval form) (eval form user-initial-environment))
|
||||
|
||||
(define *macros* '(defmacro))
|
||||
(define (defmacro? m) (and (memq m *macros*) #t))
|
||||
|
||||
(syntax-table-define system-global-syntax-table 'defmacro
|
||||
(macro defmacargs
|
||||
(let ((macname (car defmacargs)) (macargs (cadr defmacargs))
|
||||
(macbdy (cddr defmacargs)))
|
||||
`(begin
|
||||
(set! *macros* (cons ',macname *macros*))
|
||||
(syntax-table-define system-global-syntax-table ',macname
|
||||
(macro ,macargs ,@macbdy))))))
|
||||
|
||||
(define (macroexpand-1 e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(if (and (symbol? a) (defmacro? a))
|
||||
(apply (syntax-table-ref system-global-syntax-table a)
|
||||
(cdr e))
|
||||
e))
|
||||
e))
|
||||
|
||||
(define (macroexpand e)
|
||||
(if (pair? e) (let ((a (car e)))
|
||||
(if (and (symbol? a) (defmacro? a))
|
||||
(macroexpand
|
||||
(apply (syntax-table-ref system-global-syntax-table a)
|
||||
(cdr e)))
|
||||
e))
|
||||
e))
|
||||
|
||||
(define gentemp
|
||||
(let ((*gensym-counter* -1))
|
||||
(lambda ()
|
||||
(set! *gensym-counter* (+ *gensym-counter* 1))
|
||||
(string->symbol
|
||||
(string-append "slib:G" (number->string *gensym-counter*))))))
|
||||
|
||||
(define defmacro:eval slib:eval)
|
||||
(define defmacro:load load)
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define record-modifier record-updater) ;some versions need this?
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((cep (current-error-port)))
|
||||
(if (provided? 'trace) (print-call-stack cep))
|
||||
(display "Warn: " cep)
|
||||
(for-each (lambda (x) (display x cep)) args))))
|
||||
|
||||
;; define an error procedure for the library
|
||||
(define (slib:error . args)
|
||||
(if (provided? 'trace) (print-call-stack (current-error-port)))
|
||||
(apply error-procedure (append args (list (the-environment)))))
|
||||
|
||||
;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit
|
||||
(lambda args
|
||||
(cond ((null? args) (exit))
|
||||
((eqv? #t (car args)) (exit))
|
||||
((and (number? (car args)) (integer? (car args))) (exit (car args)))
|
||||
(else (exit 1)))))
|
||||
|
||||
;;; Here for backward compatability
|
||||
|
||||
(define (scheme-file-suffix) ".scm")
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define slib:load-source load)
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
(slib:load (in-vicinity (library-vicinity) "require.scm"))
|
|
@ -1,198 +0,0 @@
|
|||
;"mklibcat.scm" Build catalog for SLIB
|
||||
;Copyright (C) 1997 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(call-with-output-file (in-vicinity (implementation-vicinity) "slibcat")
|
||||
(lambda (op)
|
||||
(display ";\"slibcat\" SLIB catalog for " op)
|
||||
(display (scheme-implementation-type) op)
|
||||
(display (scheme-implementation-version) op)
|
||||
(display ". -*-scheme-*-" op) (newline op)
|
||||
(display ";" op) (newline op)
|
||||
(display "; DO NOT EDIT THIS FILE -- it is automagically generated" op)
|
||||
(newline op) (newline op)
|
||||
|
||||
(display "(" op) (newline op)
|
||||
(for-each
|
||||
(lambda (asp) (display " " op) (write asp op) (newline op))
|
||||
(append
|
||||
(list (cons 'schelog
|
||||
(in-vicinity (sub-vicinity (library-vicinity) "schelog")
|
||||
"schelog"))
|
||||
(cons 'portable-scheme-debugger
|
||||
(in-vicinity (sub-vicinity (library-vicinity) "psd")
|
||||
"psd-slib"))
|
||||
(cons 'jfilter
|
||||
(in-vicinity (sub-vicinity (library-vicinity) "jfilter")
|
||||
"jfilter")))
|
||||
(map (lambda (p)
|
||||
(if (symbol? (cdr p)) p
|
||||
(cons
|
||||
(car p)
|
||||
(if (pair? (cdr p))
|
||||
(cons
|
||||
(cadr p)
|
||||
(in-vicinity (library-vicinity) (cddr p)))
|
||||
(in-vicinity (library-vicinity) (cdr p))))))
|
||||
'(
|
||||
(rev4-optional-procedures . "sc4opt")
|
||||
(rev2-procedures . "sc2")
|
||||
(multiarg/and- . "mularg")
|
||||
(multiarg-apply . "mulapply")
|
||||
(rationalize . "ratize")
|
||||
(transcript . "trnscrpt")
|
||||
(with-file . "withfile")
|
||||
(dynamic-wind . "dynwind")
|
||||
(dynamic . "dynamic")
|
||||
(fluid-let defmacro . "fluidlet")
|
||||
(alist . "alist")
|
||||
(hash . "hash")
|
||||
(sierpinski . "sierpinski")
|
||||
(soundex . "soundex")
|
||||
(hash-table . "hashtab")
|
||||
(logical . "logical")
|
||||
(random . "random")
|
||||
(random-inexact . "randinex")
|
||||
(modular . "modular")
|
||||
(factor . "factor")
|
||||
(primes . factor)
|
||||
(charplot . "charplot")
|
||||
(sort . "sort")
|
||||
(tsort . topological-sort)
|
||||
(topological-sort . "tsort")
|
||||
(common-list-functions . "comlist")
|
||||
(tree . "tree")
|
||||
(coerce . "coerce")
|
||||
(format . "format")
|
||||
(generic-write . "genwrite")
|
||||
(pretty-print . "pp")
|
||||
(pprint-file . "ppfile")
|
||||
(object->string . "obj2str")
|
||||
(string-case . "strcase")
|
||||
(stdio . "stdio")
|
||||
(printf . "printf")
|
||||
(scanf . "scanf")
|
||||
(line-i/o . "lineio")
|
||||
(string-port . "strport")
|
||||
(getopt . "getopt")
|
||||
(debug . "debug")
|
||||
(qp . "qp")
|
||||
(break defmacro . "break")
|
||||
(trace defmacro . "trace")
|
||||
(eval . "eval")
|
||||
(record . "record")
|
||||
(promise . "promise")
|
||||
(synchk . "synchk")
|
||||
(defmacroexpand . "defmacex")
|
||||
(macro-by-example defmacro . "mbe")
|
||||
(syntax-case . "scainit")
|
||||
(syntactic-closures . "scmacro")
|
||||
(macros-that-work . "macwork")
|
||||
(macro . macro-by-example)
|
||||
(object . "object")
|
||||
(yasos macro . "yasyn")
|
||||
(oop . yasos)
|
||||
(collect macro . "collect")
|
||||
(struct defmacro . "struct")
|
||||
(structure syntax-case . "structure")
|
||||
(values . "values")
|
||||
(queue . "queue")
|
||||
(priority-queue . "priorque")
|
||||
(array . "array")
|
||||
(array-for-each . "arraymap")
|
||||
(repl . "repl")
|
||||
(process . "process")
|
||||
(chapter-order . "chap")
|
||||
(posix-time . "psxtime")
|
||||
(common-lisp-time . "cltime")
|
||||
(time-zone . "timezone")
|
||||
(relational-database . "rdms")
|
||||
(database-utilities . "dbutil")
|
||||
(database-browse . "dbrowse")
|
||||
(html-form . "htmlform")
|
||||
(alist-table . "alistab")
|
||||
(parameters . "paramlst")
|
||||
(getopt-parameters . "getparam")
|
||||
(read-command . "comparse")
|
||||
(batch . "batch")
|
||||
(glob . "glob")
|
||||
(filename . glob)
|
||||
(make-crc . "makcrc")
|
||||
(fft . "fft")
|
||||
(wt-tree . "wttree")
|
||||
(string-search . "strsrch")
|
||||
(root . "root")
|
||||
(minimize . "minimize")
|
||||
(precedence-parse . "prec")
|
||||
(parse . precedence-parse)
|
||||
(commutative-ring . "cring")
|
||||
(self-set . "selfset")
|
||||
(determinant . "determ")
|
||||
(byte . "byte")
|
||||
(tzfile . "tzfile")
|
||||
(schmooz . "schmooz")
|
||||
(net-clients . "nclients")
|
||||
(db->html . "db2html")
|
||||
(http . "http-cgi")
|
||||
(cgi . http)
|
||||
(uri . "uri")
|
||||
(uniform-resource-identifier . uri)
|
||||
(pnm . "pnm")
|
||||
(metric-units . "simetrix")
|
||||
(new-catalog . "mklibcat")
|
||||
))))
|
||||
(display " " op)
|
||||
|
||||
(let* ((req (in-vicinity (library-vicinity)
|
||||
(string-append "require" (scheme-file-suffix)))))
|
||||
(write (cons '*SLIB-VERSION* (or (require:version req) *SLIB-VERSION*))
|
||||
op))
|
||||
(newline op)
|
||||
(display ")" op) (newline op)
|
||||
|
||||
(let ((load-if-exists
|
||||
(lambda (path)
|
||||
(cond ((not (file-exists? path))
|
||||
(set! path (string-append path (scheme-file-suffix)))))
|
||||
(cond ((file-exists? path)
|
||||
(slib:load-source path))))))
|
||||
;;(load-if-exists (in-vicinity (implementation-vicinity) "mksitcat"))
|
||||
(load-if-exists (in-vicinity (implementation-vicinity) "mkimpcat")))
|
||||
|
||||
(let ((catcat
|
||||
(lambda (vicinity name specificity)
|
||||
(let ((path (in-vicinity vicinity name)))
|
||||
(and (file-exists? path)
|
||||
(call-with-input-file path
|
||||
(lambda (ip)
|
||||
(newline op)
|
||||
(display "; " op)
|
||||
(write path op)
|
||||
(display " SLIB " op)
|
||||
(display specificity op)
|
||||
(display "-specific catalog additions" op)
|
||||
(newline op) (newline op)
|
||||
(do ((c (read-char ip) (read-char ip)))
|
||||
((eof-object? c))
|
||||
(write-char c op)))))))))
|
||||
(catcat (library-vicinity) "sitecat" "site")
|
||||
(catcat (implementation-vicinity) "implcat" "implementation")
|
||||
(catcat (implementation-vicinity) "sitecat" "site"))
|
||||
))
|
||||
|
||||
(set! *catalog* #f)
|
|
@ -1,158 +0,0 @@
|
|||
;;;; "modular.scm", modular fixnum arithmetic for Scheme
|
||||
;;; Copyright (C) 1991, 1993, 1995 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(define (symmetric:modulus n)
|
||||
(cond ((or (not (number? n)) (not (positive? n)) (even? n))
|
||||
(slib:error 'symmetric:modulus n))
|
||||
(else (quotient (+ -1 n) -2))))
|
||||
|
||||
(define (modulus->integer m)
|
||||
(cond ((negative? m) (- 1 m m))
|
||||
((zero? m) #f)
|
||||
(else m)))
|
||||
|
||||
(define (modular:normalize m k)
|
||||
(cond ((positive? m) (modulo k m))
|
||||
((zero? m) k)
|
||||
((<= m k (- m)) k)
|
||||
((or (provided? 'bignum)
|
||||
(<= m (quotient (+ -1 most-positive-fixnum) 2)))
|
||||
(let* ((pm (+ 1 (* -2 m)))
|
||||
(s (modulo k pm)))
|
||||
(if (<= s (- m)) s (- s pm))))
|
||||
((positive? k) (+ (+ (+ k -1) m) m))
|
||||
(else (- (- (+ k 1) m) m))))
|
||||
|
||||
;;;; NOTE: The rest of these functions assume normalized arguments!
|
||||
|
||||
(require 'logical)
|
||||
|
||||
(define (modular:extended-euclid x y)
|
||||
(define q 0)
|
||||
(do ((r0 x r1) (r1 y (remainder r0 r1))
|
||||
(u0 1 u1) (u1 0 (- u0 (* q u1)))
|
||||
(v0 0 v1) (v1 1 (- v0 (* q v1))))
|
||||
;; (assert (= r0 (+ (* u0 x) (* v0 y))))
|
||||
;; (assert (= r1 (+ (* u1 x) (* v1 y))))
|
||||
((zero? r1) (list r0 u0 v0))
|
||||
(set! q (quotient r0 r1))))
|
||||
|
||||
(define (modular:invertable? m a)
|
||||
(eqv? 1 (gcd (or (modulus->integer m) 0) a)))
|
||||
|
||||
(define (modular:invert m a)
|
||||
(cond ((eqv? 1 (abs a)) a) ; unit
|
||||
(else
|
||||
(let ((pm (modulus->integer m)))
|
||||
(cond
|
||||
(pm
|
||||
(let ((d (modular:extended-euclid (modular:normalize pm a) pm)))
|
||||
(if (= 1 (car d))
|
||||
(modular:normalize m (cadr d))
|
||||
(slib:error 'modular:invert "can't invert" m a))))
|
||||
(else (slib:error 'modular:invert "can't invert" m a)))))))
|
||||
|
||||
(define (modular:negate m a)
|
||||
(if (zero? a) 0
|
||||
(if (negative? m) (- a)
|
||||
(- m a))))
|
||||
|
||||
;;; Being careful about overflow here
|
||||
(define (modular:+ m a b)
|
||||
(cond ((positive? m)
|
||||
(modulo (+ (- a m) b) m))
|
||||
((zero? m) (+ a b))
|
||||
((negative? a)
|
||||
(if (negative? b)
|
||||
(let ((s (+ (- a m) b)))
|
||||
(if (negative? s)
|
||||
(- s -1 m)
|
||||
(+ s m)))
|
||||
(+ a b)))
|
||||
((negative? b) (+ a b))
|
||||
(else (let ((s (+ (+ a m) b)))
|
||||
(if (positive? s)
|
||||
(+ s -1 m)
|
||||
(- s m))))))
|
||||
|
||||
(define (modular:- m a b)
|
||||
(cond ((positive? m) (modulo (- a b) m))
|
||||
((zero? m) (- a b))
|
||||
(else (modular:+ m a (- b)))))
|
||||
|
||||
;;; See: L'Ecuyer, P. and Cote, S. "Implementing a Random Number Package
|
||||
;;; with Splitting Facilities." ACM Transactions on Mathematical
|
||||
;;; Software, 17:98-111 (1991)
|
||||
|
||||
;;; modular:r = 2**((nb-2)/2) where nb = number of bits in a word.
|
||||
(define modular:r
|
||||
(ash 1 (quotient (integer-length most-positive-fixnum) 2)))
|
||||
(define modular:*
|
||||
(if (provided? 'bignum)
|
||||
(lambda (m a b)
|
||||
(cond ((zero? m) (* a b))
|
||||
((positive? m) (modulo (* a b) m))
|
||||
(else (modular:normalize m (* a b)))))
|
||||
(lambda (m a b)
|
||||
(let ((a0 a)
|
||||
(p 0))
|
||||
(cond
|
||||
((zero? m) (* a b))
|
||||
((negative? m)
|
||||
"This doesn't work for the full range of modulus M;"
|
||||
"Someone please create or convert the following"
|
||||
"algorighm to work with symmetric representation"
|
||||
(modular:normalize m (* a b)))
|
||||
(else
|
||||
(cond
|
||||
((< a modular:r))
|
||||
((< b modular:r) (set! a b) (set! b a0) (set! a0 a))
|
||||
(else
|
||||
(set! a0 (modulo a modular:r))
|
||||
(let ((a1 (quotient a modular:r))
|
||||
(qh (quotient m modular:r))
|
||||
(rh (modulo m modular:r)))
|
||||
(cond ((>= a1 modular:r)
|
||||
(set! a1 (- a1 modular:r))
|
||||
(set! p (modulo (- (* modular:r (modulo b qh))
|
||||
(* (quotient b qh) rh)) m))))
|
||||
(cond ((not (zero? a1))
|
||||
(let ((q (quotient m a1)))
|
||||
(set! p (- p (* (quotient b q) (modulo m a1))))
|
||||
(set! p (modulo (+ (if (positive? p) (- p m) p)
|
||||
(* a1 (modulo b q))) m)))))
|
||||
(set! p (modulo (- (* modular:r (modulo p qh))
|
||||
(* (quotient p qh) rh)) m)))))
|
||||
(if (zero? a0)
|
||||
p
|
||||
(let ((q (quotient m a0)))
|
||||
(set! p (- p (* (quotient b q) (modulo m a0))))
|
||||
(modulo (+ (if (positive? p) (- p m) p)
|
||||
(* a0 (modulo b q))) m)))))))))
|
||||
|
||||
(define (modular:expt m a b)
|
||||
(cond ((= a 1) 1)
|
||||
((= a (- m 1)) (if (odd? b) a 1))
|
||||
((zero? a) 0)
|
||||
((zero? m) (integer-expt a b))
|
||||
(else
|
||||
(logical:ipow-by-squaring a b 1
|
||||
(lambda (c d) (modular:* m c d))))))
|
||||
|
||||
(define extended-euclid modular:extended-euclid)
|
|
@ -1,28 +0,0 @@
|
|||
; "mulapply.scm" Redefine APPLY take more than 2 arguments.
|
||||
;Copyright (C) 1991 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(define two-arg:apply apply)
|
||||
(define apply
|
||||
(lambda args
|
||||
(two-arg:apply (car args) (apply:append-to-last (cdr args)))))
|
||||
|
||||
(define (apply:append-to-last lst)
|
||||
(if (null? (cdr lst))
|
||||
(car lst)
|
||||
(cons (car lst) (apply:append-to-last (cdr lst)))))
|
|
@ -1,12 +0,0 @@
|
|||
;;; "mularg.scm" Redefine - and / to take more than 2 arguments.
|
||||
|
||||
(define / /)
|
||||
(define - -)
|
||||
(let ((maker
|
||||
(lambda (op)
|
||||
(lambda (d1 . ds)
|
||||
(cond ((null? ds) (op d1))
|
||||
((null? (cdr ds)) (op d1 (car ds)))
|
||||
(else (for-each (lambda (d) (set! d1 (op d1 d))) ds) d1))))))
|
||||
(set! / (maker /))
|
||||
(set! - (maker -)))
|
|
@ -1,289 +0,0 @@
|
|||
;"mwdenote.scm" Syntactic Environments
|
||||
; Copyright 1992 William Clinger
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
; I also request that you send me a copy of any improvements that you
|
||||
; make to this software so that they may be incorporated within it to
|
||||
; the benefit of the Scheme community.
|
||||
|
||||
;;;; Syntactic environments.
|
||||
|
||||
; A syntactic environment maps identifiers to denotations,
|
||||
; where a denotation is one of
|
||||
;
|
||||
; (special <special>)
|
||||
; (macro <rules> <env>)
|
||||
; (identifier <id>)
|
||||
;
|
||||
; and where <special> is one of
|
||||
;
|
||||
; quote
|
||||
; lambda
|
||||
; if
|
||||
; set!
|
||||
; begin
|
||||
; define
|
||||
; define-syntax
|
||||
; let-syntax
|
||||
; letrec-syntax
|
||||
; syntax-rules
|
||||
;
|
||||
; and where <rules> is a compiled <transformer spec> (see R4RS),
|
||||
; <env> is a syntactic environment, and <id> is an identifier.
|
||||
|
||||
(define mw:standard-syntax-environment
|
||||
'((quote . (special quote))
|
||||
(lambda . (special lambda))
|
||||
(if . (special if))
|
||||
(set! . (special set!))
|
||||
(begin . (special begin))
|
||||
(define . (special define))
|
||||
(case . (special case)) ;; @@ added wdc
|
||||
(let . (special let)) ;; @@ added KAD
|
||||
(let* . (special let*)) ;; @@ "
|
||||
(letrec . (special letrec)) ;; @@ "
|
||||
(quasiquote . (special quasiquote)) ;; @@ "
|
||||
(unquote . (special unquote)) ;; @@ "
|
||||
(unquote-splicing . (special unquote-splicing)) ; @@ "
|
||||
(do . (special do)) ;; @@ "
|
||||
(define-syntax . (special define-syntax))
|
||||
(let-syntax . (special let-syntax))
|
||||
(letrec-syntax . (special letrec-syntax))
|
||||
(syntax-rules . (special syntax-rules))
|
||||
(... . (identifier ...))
|
||||
(::: . (identifier :::))))
|
||||
|
||||
; An unforgeable synonym for lambda, used to expand definitions.
|
||||
|
||||
(define mw:lambda0 (string->symbol " lambda "))
|
||||
|
||||
; The mw:global-syntax-environment will always be a nonempty
|
||||
; association list since there is no way to remove the entry
|
||||
; for mw:lambda0. That entry is used as a header by destructive
|
||||
; operations.
|
||||
|
||||
(define mw:global-syntax-environment
|
||||
(cons (cons mw:lambda0
|
||||
(cdr (assq 'lambda mw:standard-syntax-environment)))
|
||||
(mw:syntax-copy mw:standard-syntax-environment)))
|
||||
|
||||
(define (mw:global-syntax-environment-set! env)
|
||||
(set-cdr! mw:global-syntax-environment env))
|
||||
|
||||
(define (mw:syntax-bind-globally! id denotation)
|
||||
(if (and (mw:identifier? denotation)
|
||||
(eq? id (mw:identifier-name denotation)))
|
||||
(letrec ((remove-bindings-for-id
|
||||
(lambda (bindings)
|
||||
(cond ((null? bindings) '())
|
||||
((eq? (caar bindings) id)
|
||||
(remove-bindings-for-id (cdr bindings)))
|
||||
(else (cons (car bindings)
|
||||
(remove-bindings-for-id (cdr bindings))))))))
|
||||
(mw:global-syntax-environment-set!
|
||||
(remove-bindings-for-id (cdr mw:global-syntax-environment))))
|
||||
(let ((x (assq id mw:global-syntax-environment)))
|
||||
(if x
|
||||
(set-cdr! x denotation)
|
||||
(mw:global-syntax-environment-set!
|
||||
(cons (cons id denotation)
|
||||
(cdr mw:global-syntax-environment)))))))
|
||||
|
||||
(define (mw:syntax-divert env1 env2)
|
||||
(append env2 env1))
|
||||
|
||||
(define (mw:syntax-extend env ids denotations)
|
||||
(mw:syntax-divert env (map cons ids denotations)))
|
||||
|
||||
(define (mw:syntax-lookup-raw env id)
|
||||
(let ((entry (assq id env)))
|
||||
(if entry
|
||||
(cdr entry)
|
||||
#f)))
|
||||
|
||||
(define (mw:syntax-lookup env id)
|
||||
(or (mw:syntax-lookup-raw env id)
|
||||
(mw:make-identifier-denotation id)))
|
||||
|
||||
(define (mw:syntax-assign! env id denotation)
|
||||
(let ((entry (assq id env)))
|
||||
(if entry
|
||||
(set-cdr! entry denotation)
|
||||
(mw:bug "Bug detected in mw:syntax-assign!" env id denotation))))
|
||||
|
||||
(define mw:denote-of-quote
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'quote))
|
||||
|
||||
(define mw:denote-of-lambda
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'lambda))
|
||||
|
||||
(define mw:denote-of-if
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'if))
|
||||
|
||||
(define mw:denote-of-set!
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'set!))
|
||||
|
||||
(define mw:denote-of-begin
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'begin))
|
||||
|
||||
(define mw:denote-of-define
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'define))
|
||||
|
||||
(define mw:denote-of-define-syntax
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'define-syntax))
|
||||
|
||||
(define mw:denote-of-let-syntax
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'let-syntax))
|
||||
|
||||
(define mw:denote-of-letrec-syntax
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'letrec-syntax))
|
||||
|
||||
(define mw:denote-of-syntax-rules
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'syntax-rules))
|
||||
|
||||
(define mw:denote-of-...
|
||||
(mw:syntax-lookup mw:standard-syntax-environment '...))
|
||||
|
||||
(define mw:denote-of-:::
|
||||
(mw:syntax-lookup mw:standard-syntax-environment ':::))
|
||||
|
||||
(define mw:denote-of-case
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'case)) ;; @@ wdc
|
||||
|
||||
(define mw:denote-of-let
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'let)) ;; @@ KenD
|
||||
|
||||
(define mw:denote-of-let*
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'let*)) ;; @@ KenD
|
||||
|
||||
(define mw:denote-of-letrec
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'letrec)) ;; @@ KenD
|
||||
|
||||
(define mw:denote-of-quasiquote
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'quasiquote)) ;; @@ KenD
|
||||
|
||||
(define mw:denote-of-unquote
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'unquote)) ;; @@ KenD
|
||||
|
||||
(define mw:denote-of-unquote-splicing
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'unquote-splicing)) ;@@ KenD
|
||||
|
||||
(define mw:denote-of-do
|
||||
(mw:syntax-lookup mw:standard-syntax-environment 'do)) ;; @@ KenD
|
||||
|
||||
(define mw:denote-class car)
|
||||
|
||||
;(define (mw:special? denotation)
|
||||
; (eq? (mw:denote-class denotation) 'special))
|
||||
|
||||
;(define (mw:macro? denotation)
|
||||
; (eq? (mw:denote-class denotation) 'macro))
|
||||
|
||||
(define (mw:identifier? denotation)
|
||||
(eq? (mw:denote-class denotation) 'identifier))
|
||||
|
||||
(define (mw:make-identifier-denotation id)
|
||||
(list 'identifier id))
|
||||
|
||||
(define macwork:rules cadr)
|
||||
(define macwork:env caddr)
|
||||
(define mw:identifier-name cadr)
|
||||
|
||||
(define (mw:same-denotation? d1 d2)
|
||||
(or (eq? d1 d2)
|
||||
(and (mw:identifier? d1)
|
||||
(mw:identifier? d2)
|
||||
(eq? (mw:identifier-name d1)
|
||||
(mw:identifier-name d2)))))
|
||||
|
||||
; Renaming of variables.
|
||||
|
||||
; Given a datum, strips the suffixes from any symbols that appear within
|
||||
; the datum, trying not to copy any more of the datum than necessary.
|
||||
|
||||
; @@ rewrote to strip *all* suffixes -- wdc
|
||||
|
||||
(define mw:strip
|
||||
(letrec ((original-symbol
|
||||
(lambda (x)
|
||||
(let ((s (symbol->string x)))
|
||||
(loop x s 0 (string-length s)))))
|
||||
(loop
|
||||
(lambda (sym s i n)
|
||||
(cond ((= i n) sym)
|
||||
((char=? (string-ref s i)
|
||||
mw:suffix-character)
|
||||
(string->symbol (substring s 0 i)))
|
||||
(else
|
||||
(loop sym s (+ i 1) n))))))
|
||||
(lambda (x)
|
||||
(cond ((symbol? x)
|
||||
(original-symbol x))
|
||||
((pair? x)
|
||||
(let ((y (mw:strip (car x)))
|
||||
(z (mw:strip (cdr x))))
|
||||
(if (and (eq? y (car x))
|
||||
(eq? z (cdr x)))
|
||||
x
|
||||
(cons y z))))
|
||||
((vector? x)
|
||||
(list->vector (map mw:strip (vector->list x))))
|
||||
(else x)))))
|
||||
|
||||
; Given a list of identifiers, returns an alist that associates each
|
||||
; identifier with a fresh identifier.
|
||||
|
||||
(define (mw:rename-vars vars)
|
||||
(set! mw:renaming-counter (+ mw:renaming-counter 1))
|
||||
(let ((suffix (string-append (string mw:suffix-character)
|
||||
(number->string mw:renaming-counter))))
|
||||
(map (lambda (var)
|
||||
(if (symbol? var)
|
||||
(cons var
|
||||
(string->symbol
|
||||
(string-append (symbol->string var) suffix)))
|
||||
(slib:error "Illegal variable" var)))
|
||||
vars)))
|
||||
|
||||
; Given a syntactic environment env to be extended, an alist returned
|
||||
; by mw:rename-vars, and a syntactic environment env2, extends env by
|
||||
; binding the fresh identifiers to the denotations of the original
|
||||
; identifiers in env2.
|
||||
|
||||
(define (mw:syntax-alias env alist env2)
|
||||
(mw:syntax-divert
|
||||
env
|
||||
(map (lambda (name-pair)
|
||||
(let ((old-name (car name-pair))
|
||||
(new-name (cdr name-pair)))
|
||||
(cons new-name
|
||||
(mw:syntax-lookup env2 old-name))))
|
||||
alist)))
|
||||
|
||||
; Given a syntactic environment and an alist returned by mw:rename-vars,
|
||||
; extends the environment by binding the old identifiers to the fresh
|
||||
; identifiers.
|
||||
|
||||
(define (mw:syntax-rename env alist)
|
||||
(mw:syntax-divert env
|
||||
(map (lambda (old new)
|
||||
(cons old (mw:make-identifier-denotation new)))
|
||||
(map car alist)
|
||||
(map cdr alist))))
|
||||
|
||||
; Given a <formals> and an alist returned by mw:rename-vars that contains
|
||||
; a new name for each formal identifier in <formals>, renames the
|
||||
; formal identifiers.
|
||||
|
||||
(define (mw:rename-formals formals alist)
|
||||
(cond ((null? formals) '())
|
||||
((pair? formals)
|
||||
(cons (cdr (assq (car formals) alist))
|
||||
(mw:rename-formals (cdr formals) alist)))
|
||||
(else (cdr (assq formals alist)))))
|
||||
|
||||
(define mw:renaming-counter 0)
|
|
@ -1,565 +0,0 @@
|
|||
;"mwexpand.scm" macro expander
|
||||
; Copyright 1992 William Clinger
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
; I also request that you send me a copy of any improvements that you
|
||||
; make to this software so that they may be incorporated within it to
|
||||
; the benefit of the Scheme community.
|
||||
|
||||
; The external entry points and kernel of the macro expander.
|
||||
;
|
||||
; Part of this code is snarfed from the Twobit macro expander.
|
||||
|
||||
(define mw:define-syntax-scope
|
||||
(let ((flag 'letrec))
|
||||
(lambda args
|
||||
(cond ((null? args) flag)
|
||||
((not (null? (cdr args)))
|
||||
(apply mw:warn
|
||||
"Too many arguments passed to define-syntax-scope"
|
||||
args))
|
||||
((memq (car args) '(letrec letrec* let*))
|
||||
(set! flag (car args)))
|
||||
(else (mw:warn "Unrecognized argument to define-syntax-scope"
|
||||
(car args)))))))
|
||||
|
||||
(define mw:quit ; assigned by macwork:expand
|
||||
(lambda (v) v))
|
||||
|
||||
(define (macwork:expand def-or-exp)
|
||||
(call-with-current-continuation
|
||||
(lambda (k)
|
||||
(set! mw:quit k)
|
||||
(set! mw:renaming-counter 0)
|
||||
(mw:desugar-definitions def-or-exp mw:global-syntax-environment))))
|
||||
|
||||
(define (mw:desugar-definitions exp env)
|
||||
(letrec
|
||||
((define-loop
|
||||
(lambda (exp rest first)
|
||||
(cond ((and (pair? exp)
|
||||
(eq? (mw:syntax-lookup env (car exp))
|
||||
mw:denote-of-begin)
|
||||
(pair? (cdr exp)))
|
||||
(define-loop (cadr exp) (append (cddr exp) rest) first))
|
||||
((and (pair? exp)
|
||||
(eq? (mw:syntax-lookup env (car exp))
|
||||
mw:denote-of-define))
|
||||
(let ((exp (desugar-define exp env)))
|
||||
(cond ((and (null? first) (null? rest))
|
||||
exp)
|
||||
((null? rest)
|
||||
(cons mw:begin1 (reverse (cons exp first))))
|
||||
(else (define-loop (car rest)
|
||||
(cdr rest)
|
||||
(cons exp first))))))
|
||||
((and (pair? exp)
|
||||
(eq? (mw:syntax-lookup env (car exp))
|
||||
mw:denote-of-define-syntax)
|
||||
(null? first))
|
||||
(define-syntax-loop exp rest))
|
||||
((and (null? first) (null? rest))
|
||||
(mw:expand exp env))
|
||||
((null? rest)
|
||||
(cons mw:begin1 (reverse (cons (mw:expand exp env) first))))
|
||||
(else (cons mw:begin1
|
||||
(append (reverse first)
|
||||
(map (lambda (exp) (mw:expand exp env))
|
||||
(cons exp rest))))))))
|
||||
|
||||
(desugar-define
|
||||
(lambda (exp env)
|
||||
(cond
|
||||
((null? (cdr exp)) (mw:error "Malformed definition" exp))
|
||||
; (define foo) syntax is transformed into (define foo (undefined)).
|
||||
((null? (cddr exp))
|
||||
(let ((id (cadr exp)))
|
||||
(redefinition id)
|
||||
(mw:syntax-bind-globally! id (mw:make-identifier-denotation id))
|
||||
(list mw:define1 id mw:undefined)))
|
||||
((pair? (cadr exp))
|
||||
; mw:lambda0 is an unforgeable lambda, needed here because the
|
||||
; lambda expression will undergo further expansion.
|
||||
(desugar-define `(,mw:define1 ,(car (cadr exp))
|
||||
(,mw:lambda0 ,(cdr (cadr exp))
|
||||
,@(cddr exp)))
|
||||
env))
|
||||
((> (length exp) 3) (mw:error "Malformed definition" exp))
|
||||
(else (let ((id (cadr exp)))
|
||||
(redefinition id)
|
||||
(mw:syntax-bind-globally! id (mw:make-identifier-denotation id))
|
||||
`(,mw:define1 ,id ,(mw:expand (caddr exp) env)))))))
|
||||
|
||||
(define-syntax-loop
|
||||
(lambda (exp rest)
|
||||
(cond ((and (pair? exp)
|
||||
(eq? (mw:syntax-lookup env (car exp))
|
||||
mw:denote-of-begin)
|
||||
(pair? (cdr exp)))
|
||||
(define-syntax-loop (cadr exp) (append (cddr exp) rest)))
|
||||
((and (pair? exp)
|
||||
(eq? (mw:syntax-lookup env (car exp))
|
||||
mw:denote-of-define-syntax))
|
||||
(if (pair? (cdr exp))
|
||||
(redefinition (cadr exp)))
|
||||
(if (null? rest)
|
||||
(mw:define-syntax exp env)
|
||||
(begin (mw:define-syntax exp env)
|
||||
(define-syntax-loop (car rest) (cdr rest)))))
|
||||
((null? rest)
|
||||
(mw:expand exp env))
|
||||
(else (cons mw:begin1
|
||||
(map (lambda (exp) (mw:expand exp env))
|
||||
(cons exp rest)))))))
|
||||
|
||||
(redefinition
|
||||
(lambda (id)
|
||||
(if (symbol? id)
|
||||
(if (not (mw:identifier?
|
||||
(mw:syntax-lookup mw:global-syntax-environment id)))
|
||||
(mw:warn "Redefining keyword" id))
|
||||
(mw:error "Malformed variable or keyword" id)))))
|
||||
|
||||
; body of letrec
|
||||
|
||||
(define-loop exp '() '())))
|
||||
|
||||
; Given an expression and a syntactic environment,
|
||||
; returns an expression in core Scheme.
|
||||
|
||||
(define (mw:expand exp env)
|
||||
(if (not (pair? exp))
|
||||
(mw:atom exp env)
|
||||
(let ((keyword (mw:syntax-lookup env (car exp))))
|
||||
(case (mw:denote-class keyword)
|
||||
((special)
|
||||
(cond
|
||||
((eq? keyword mw:denote-of-quote) (mw:quote exp))
|
||||
((eq? keyword mw:denote-of-lambda) (mw:lambda exp env))
|
||||
((eq? keyword mw:denote-of-if) (mw:if exp env))
|
||||
((eq? keyword mw:denote-of-set!) (mw:set exp env))
|
||||
((eq? keyword mw:denote-of-begin) (mw:begin exp env))
|
||||
((eq? keyword mw:denote-of-let-syntax) (mw:let-syntax exp env))
|
||||
((eq? keyword mw:denote-of-letrec-syntax)
|
||||
(mw:letrec-syntax exp env))
|
||||
; @@ case has a nontrivial syntax also -- wdc
|
||||
((eq? keyword mw:denote-of-case) (mw:case exp env))
|
||||
; @@ let, let*, letrec, paint within quasiquotation -- kend
|
||||
((eq? keyword mw:denote-of-let) (mw:let exp env))
|
||||
((eq? keyword mw:denote-of-let*) (mw:let* exp env))
|
||||
((eq? keyword mw:denote-of-letrec) (mw:letrec exp env))
|
||||
((eq? keyword mw:denote-of-quasiquote) (mw:quasiquote exp env))
|
||||
((eq? keyword mw:denote-of-do) (mw:do exp env))
|
||||
((or (eq? keyword mw:denote-of-define)
|
||||
(eq? keyword mw:denote-of-define-syntax))
|
||||
;; slight hack to allow expansion into defines -KenD
|
||||
(if mw:in-define?
|
||||
(mw:error "Definition out of context" exp)
|
||||
(begin
|
||||
(set! mw:in-define? #t)
|
||||
(let ( (result (mw:desugar-definitions exp env)) )
|
||||
(set! mw:in-define? #f)
|
||||
result))
|
||||
))
|
||||
(else (mw:bug "Bug detected in mw:expand" exp env))))
|
||||
((macro) (mw:macro exp env))
|
||||
((identifier) (mw:application exp env))
|
||||
(else (mw:bug "Bug detected in mw:expand" exp env))
|
||||
) )
|
||||
) )
|
||||
|
||||
(define mw:in-define? #f) ; should be fluid
|
||||
|
||||
(define (mw:atom exp env)
|
||||
(cond ((not (symbol? exp))
|
||||
; Here exp ought to be a boolean, number, character, or string,
|
||||
; but I'll allow for non-standard extensions by passing exp
|
||||
; to the underlying Scheme system without further checking.
|
||||
exp)
|
||||
(else (let ((denotation (mw:syntax-lookup env exp)))
|
||||
(case (mw:denote-class denotation)
|
||||
((special macro)
|
||||
(mw:error "Syntactic keyword used as a variable" exp env))
|
||||
((identifier) (mw:identifier-name denotation))
|
||||
(else (mw:bug "Bug detected by mw:atom" exp env)))))))
|
||||
|
||||
(define (mw:quote exp)
|
||||
(if (= (mw:safe-length exp) 2)
|
||||
(list mw:quote1 (mw:strip (cadr exp)))
|
||||
(mw:error "Malformed quoted constant" exp)))
|
||||
|
||||
(define (mw:lambda exp env)
|
||||
(if (> (mw:safe-length exp) 2)
|
||||
(let* ((formals (cadr exp))
|
||||
(alist (mw:rename-vars (mw:make-null-terminated formals)))
|
||||
(env (mw:syntax-rename env alist))
|
||||
(body (cddr exp)))
|
||||
(list mw:lambda1
|
||||
(mw:rename-formals formals alist)
|
||||
(mw:body body env)))
|
||||
(mw:error "Malformed lambda expression" exp)))
|
||||
|
||||
(define (mw:body body env)
|
||||
(define (loop body env defs)
|
||||
(if (null? body)
|
||||
(mw:error "Empty body"))
|
||||
(let ((exp (car body)))
|
||||
(if (and (pair? exp)
|
||||
(symbol? (car exp)))
|
||||
(let ((denotation (mw:syntax-lookup env (car exp))))
|
||||
(case (mw:denote-class denotation)
|
||||
((special)
|
||||
(cond ((eq? denotation mw:denote-of-begin)
|
||||
(loop (append (cdr exp) (cdr body)) env defs))
|
||||
((eq? denotation mw:denote-of-define)
|
||||
(loop (cdr body) env (cons exp defs)))
|
||||
(else (mw:finalize-body body env defs))))
|
||||
((macro)
|
||||
(mw:transcribe exp
|
||||
env
|
||||
(lambda (exp env)
|
||||
(loop (cons exp (cdr body))
|
||||
env
|
||||
defs))))
|
||||
((identifier)
|
||||
(mw:finalize-body body env defs))
|
||||
(else (mw:bug "Bug detected in mw:body" body env))))
|
||||
(mw:finalize-body body env defs))))
|
||||
(loop body env '()))
|
||||
|
||||
(define (mw:finalize-body body env defs)
|
||||
(if (null? defs)
|
||||
(let ((body (map (lambda (exp) (mw:expand exp env))
|
||||
body)))
|
||||
(if (null? (cdr body))
|
||||
(car body)
|
||||
(cons mw:begin1 body)))
|
||||
(let* ((alist (mw:rename-vars '(quote lambda set!)))
|
||||
(env (mw:syntax-alias env alist mw:standard-syntax-environment))
|
||||
(new-quote (cdr (assq 'quote alist)))
|
||||
(new-lambda (cdr (assq 'lambda alist)))
|
||||
(new-set! (cdr (assq 'set! alist))))
|
||||
(define (desugar-definition def)
|
||||
(if (> (mw:safe-length def) 2)
|
||||
(cond ((pair? (cadr def))
|
||||
(desugar-definition
|
||||
`(,(car def)
|
||||
,(car (cadr def))
|
||||
(,new-lambda
|
||||
,(cdr (cadr def))
|
||||
,@(cddr def)))))
|
||||
((= (length def) 3)
|
||||
(cdr def))
|
||||
(else (mw:error "Malformed definition" def env)))
|
||||
(mw:error "Malformed definition" def env)))
|
||||
(mw:letrec
|
||||
`(letrec ,(map desugar-definition (reverse defs)) ,@body)
|
||||
env)))
|
||||
)
|
||||
|
||||
(define (mw:if exp env)
|
||||
(let ((n (mw:safe-length exp)))
|
||||
(if (or (= n 3) (= n 4))
|
||||
(cons mw:if1 (map (lambda (exp) (mw:expand exp env)) (cdr exp)))
|
||||
(mw:error "Malformed if expression" exp env))))
|
||||
|
||||
(define (mw:set exp env)
|
||||
(if (= (mw:safe-length exp) 3)
|
||||
`(,mw:set!1 ,(mw:expand (cadr exp) env) ,(mw:expand (caddr exp) env))
|
||||
(mw:error "Malformed assignment" exp env)))
|
||||
|
||||
(define (mw:begin exp env)
|
||||
(if (positive? (mw:safe-length exp))
|
||||
`(,mw:begin1 ,@(map (lambda (exp) (mw:expand exp env)) (cdr exp)))
|
||||
(mw:error "Malformed begin expression" exp env)))
|
||||
|
||||
(define (mw:application exp env)
|
||||
(if (> (mw:safe-length exp) 0)
|
||||
(map (lambda (exp) (mw:expand exp env))
|
||||
exp)
|
||||
(mw:error "Malformed application")))
|
||||
|
||||
; I think the environment argument should always be global here.
|
||||
|
||||
(define (mw:define-syntax exp env)
|
||||
(cond ((and (= (mw:safe-length exp) 3)
|
||||
(symbol? (cadr exp)))
|
||||
(mw:define-syntax1 (cadr exp)
|
||||
(caddr exp)
|
||||
env
|
||||
(mw:define-syntax-scope)))
|
||||
((and (= (mw:safe-length exp) 4)
|
||||
(symbol? (cadr exp))
|
||||
(memq (caddr exp) '(letrec letrec* let*)))
|
||||
(mw:define-syntax1 (cadr exp)
|
||||
(cadddr exp)
|
||||
env
|
||||
(caddr exp)))
|
||||
(else (mw:error "Malformed define-syntax" exp env))))
|
||||
|
||||
(define (mw:define-syntax1 keyword spec env scope)
|
||||
(case scope
|
||||
((letrec) (mw:define-syntax-letrec keyword spec env))
|
||||
((letrec*) (mw:define-syntax-letrec* keyword spec env))
|
||||
((let*) (mw:define-syntax-let* keyword spec env))
|
||||
(else (mw:bug "Weird scope" scope)))
|
||||
(list mw:quote1 keyword))
|
||||
|
||||
(define (mw:define-syntax-letrec keyword spec env)
|
||||
(mw:syntax-bind-globally!
|
||||
keyword
|
||||
(mw:compile-transformer-spec spec env)))
|
||||
|
||||
(define (mw:define-syntax-letrec* keyword spec env)
|
||||
(let* ((env (mw:syntax-extend (mw:syntax-copy env)
|
||||
(list keyword)
|
||||
'((fake denotation))))
|
||||
(transformer (mw:compile-transformer-spec spec env)))
|
||||
(mw:syntax-assign! env keyword transformer)
|
||||
(mw:syntax-bind-globally! keyword transformer)))
|
||||
|
||||
(define (mw:define-syntax-let* keyword spec env)
|
||||
(mw:syntax-bind-globally!
|
||||
keyword
|
||||
(mw:compile-transformer-spec spec (mw:syntax-copy env))))
|
||||
|
||||
(define (mw:let-syntax exp env)
|
||||
(if (and (> (mw:safe-length exp) 2)
|
||||
(comlist:every (lambda (binding)
|
||||
(and (pair? binding)
|
||||
(symbol? (car binding))
|
||||
(pair? (cdr binding))
|
||||
(null? (cddr binding))))
|
||||
(cadr exp)))
|
||||
(mw:body (cddr exp)
|
||||
(mw:syntax-extend env
|
||||
(map car (cadr exp))
|
||||
(map (lambda (spec)
|
||||
(mw:compile-transformer-spec
|
||||
spec
|
||||
env))
|
||||
(map cadr (cadr exp)))))
|
||||
(mw:error "Malformed let-syntax" exp env)))
|
||||
|
||||
(define (mw:letrec-syntax exp env)
|
||||
(if (and (> (mw:safe-length exp) 2)
|
||||
(comlist:every (lambda (binding)
|
||||
(and (pair? binding)
|
||||
(symbol? (car binding))
|
||||
(pair? (cdr binding))
|
||||
(null? (cddr binding))))
|
||||
(cadr exp)))
|
||||
(let ((env (mw:syntax-extend env
|
||||
(map car (cadr exp))
|
||||
(map (lambda (id)
|
||||
'(fake denotation))
|
||||
(cadr exp)))))
|
||||
(for-each (lambda (id spec)
|
||||
(mw:syntax-assign!
|
||||
env
|
||||
id
|
||||
(mw:compile-transformer-spec spec env)))
|
||||
(map car (cadr exp))
|
||||
(map cadr (cadr exp)))
|
||||
(mw:body (cddr exp) env))
|
||||
(mw:error "Malformed let-syntax" exp env)))
|
||||
|
||||
(define (mw:macro exp env)
|
||||
(mw:transcribe exp
|
||||
env
|
||||
(lambda (exp env)
|
||||
(mw:expand exp env))))
|
||||
|
||||
; To do:
|
||||
; Clean up alist hacking et cetera.
|
||||
|
||||
;;-----------------------------------------------------------------
|
||||
;; The following was added to allow expansion without flattening
|
||||
;; LETs to LAMBDAs so that the origianl structure of the program
|
||||
;; is preserved by macro expansion. I.e. so that usual.scm is not
|
||||
;; required. -- added KenD
|
||||
|
||||
(define (mw:process-let-bindings alist binding-list env) ;; helper proc
|
||||
(map (lambda (bind)
|
||||
(list (cdr (assq (car bind) alist)) ; renamed name
|
||||
(mw:body (cdr bind) env))) ; alpha renamed value expression
|
||||
binding-list)
|
||||
)
|
||||
|
||||
(define (mw:strip-begin exp) ;; helper proc: mw:body sometimes puts one in
|
||||
(if (and (pair? exp) (eq? (car exp) 'begin))
|
||||
(cdr exp)
|
||||
exp)
|
||||
)
|
||||
|
||||
; CASE -- added by wdc
|
||||
(define (mw:case exp env)
|
||||
(let ((expand (lambda (exp)
|
||||
(mw:expand exp env))))
|
||||
(if (< (mw:safe-length exp) 3)
|
||||
(mw:error "Malformed case expression" exp env)
|
||||
`(case ,(expand (cadr exp))
|
||||
,@(map (lambda (clause)
|
||||
(if (< (mw:safe-length exp) 2)
|
||||
(mw:error "Malformed case clause" exp env)
|
||||
(cons (mw:strip (car clause))
|
||||
(map expand (cdr clause)))))
|
||||
(cddr exp))))))
|
||||
|
||||
|
||||
; LET
|
||||
(define (mw:let exp env)
|
||||
(let* ( (name (if (or (pair? (cadr exp)) (null? (cadr exp)))
|
||||
#f
|
||||
(cadr exp))) ; named let?
|
||||
(binds (if name (caddr exp) (cadr exp)))
|
||||
(body (if name (cdddr exp) (cddr exp)))
|
||||
(vars (if (null? binds) #f (map car binds)))
|
||||
(alist (if vars (mw:rename-vars vars) #f))
|
||||
(newenv (if alist (mw:syntax-rename env alist) env))
|
||||
)
|
||||
(if name ;; extend env with new name
|
||||
(let ( (rename (mw:rename-vars (list name))) )
|
||||
(set! alist (append rename alist))
|
||||
(set! newenv (mw:syntax-rename newenv rename))
|
||||
) )
|
||||
`(let
|
||||
,@(if name (list (cdr (assq name alist))) '())
|
||||
,(mw:process-let-bindings alist binds env)
|
||||
,(mw:body body newenv))
|
||||
) )
|
||||
|
||||
|
||||
; LETREC differs from LET in that the binding values are processed in the
|
||||
; new rather than the original environment.
|
||||
|
||||
(define (mw:letrec exp env)
|
||||
(let* ( (binds (cadr exp))
|
||||
(body (cddr exp))
|
||||
(vars (if (null? binds) #f (map car binds)))
|
||||
(alist (if vars (mw:rename-vars vars) #f))
|
||||
(newenv (if alist (mw:syntax-rename env alist) env))
|
||||
)
|
||||
`(letrec
|
||||
,(mw:process-let-bindings alist binds newenv)
|
||||
,(mw:body body newenv))
|
||||
) )
|
||||
|
||||
|
||||
; LET* adds to ENV for each new binding.
|
||||
|
||||
(define (mw:let* exp env)
|
||||
(let ( (binds (cadr exp))
|
||||
(body (cddr exp))
|
||||
)
|
||||
(let bind-loop ( (bindings binds) (newbinds '()) (newenv env) )
|
||||
(if (null? bindings)
|
||||
`(let* ,(reverse newbinds) ,(mw:body body newenv))
|
||||
(let* ( (bind (car bindings))
|
||||
(var (car bind))
|
||||
(valexp (cdr bind))
|
||||
(rename (mw:rename-vars (list var)))
|
||||
(next-newenv (mw:syntax-rename newenv rename))
|
||||
)
|
||||
(bind-loop (cdr bindings)
|
||||
(cons (list (cdr (assq var rename))
|
||||
(mw:body valexp newenv))
|
||||
newbinds)
|
||||
next-newenv))
|
||||
) ) ) )
|
||||
|
||||
|
||||
; DO
|
||||
|
||||
(define (mw:process-do-bindings var-init-steps alist oldenv newenv) ;; helper proc
|
||||
(map (lambda (vis)
|
||||
(let ( (v (car vis))
|
||||
(i (cadr vis))
|
||||
(s (if (null? (cddr vis)) (car vis) (caddr vis))))
|
||||
`( ,(cdr (assq v alist)) ; renamed name
|
||||
,(mw:body (list i) oldenv) ; init in outer/old env
|
||||
,(mw:body (list s) newenv) ))) ; step in letrec/inner/new env
|
||||
var-init-steps)
|
||||
)
|
||||
|
||||
(define (mw:do exp env)
|
||||
(let* ( (vis (cadr exp)) ; (Var Init Step ...)
|
||||
(ts (caddr exp)) ; (Test Sequence ...)
|
||||
(com (cdddr exp)) ; (COMmand ...)
|
||||
(vars (if (null? vis) #f (map car vis)))
|
||||
(rename (if vars (mw:rename-vars vars) #f))
|
||||
(newenv (if vars (mw:syntax-rename env rename) env))
|
||||
)
|
||||
`(do ,(if vars (mw:process-do-bindings vis rename env newenv) '())
|
||||
,(if (null? ts) '() (mw:strip-begin (mw:body (list ts) newenv)))
|
||||
,@(if (null? com) '() (list (mw:body com newenv))))
|
||||
) )
|
||||
|
||||
;
|
||||
; Quasiquotation (backquote)
|
||||
;
|
||||
; At level 0, unquoted forms are left painted (not mw:strip'ed).
|
||||
; At higher levels, forms which are unquoted to level 0 are painted.
|
||||
; This includes forms within quotes. E.g.:
|
||||
; (lambda (a)
|
||||
; (quasiquote
|
||||
; (a (unquote a) b (quasiquote (a (unquote (unquote a)) b)))))
|
||||
;or equivalently:
|
||||
; (lambda (a) `(a ,a b `(a ,,a b)))
|
||||
;=>
|
||||
; (lambda (a|1) `(a ,a|1 b `(a ,,a|1 b)))
|
||||
|
||||
(define (mw:quasiquote exp env)
|
||||
|
||||
(define (mw:atom exp env)
|
||||
(if (not (symbol? exp))
|
||||
exp
|
||||
(let ((denotation (mw:syntax-lookup env exp)))
|
||||
(case (mw:denote-class denotation)
|
||||
((special macro identifier) (mw:identifier-name denotation))
|
||||
(else (mw:bug "Bug detected by mw:atom" exp env))))
|
||||
) )
|
||||
|
||||
(define (quasi subexp level)
|
||||
(cond
|
||||
((null? subexp) subexp)
|
||||
((not (or (pair? subexp) (vector? subexp)))
|
||||
(if (zero? level) (mw:atom subexp env) subexp) ; the work is here
|
||||
)
|
||||
((vector? subexp)
|
||||
(let* ((l (vector-length subexp))
|
||||
(v (make-vector l)))
|
||||
(do ((i 0 (+ i 1)))
|
||||
((= i l) v)
|
||||
(vector-set! v i (quasi (vector-ref subexp i) level))
|
||||
)
|
||||
)
|
||||
)
|
||||
(else
|
||||
(let ( (keyword (mw:syntax-lookup env (car subexp))) )
|
||||
(cond
|
||||
((eq? keyword mw:denote-of-unquote)
|
||||
(cons 'unquote (quasi (cdr subexp) (- level 1)))
|
||||
)
|
||||
((eq? keyword mw:denote-of-unquote-splicing)
|
||||
(cons 'unquote-splicing (quasi (cdr subexp) (- level 1)))
|
||||
)
|
||||
((eq? keyword mw:denote-of-quasiquote)
|
||||
(cons 'quasiquote (quasi (cdr subexp) (+ level 1)))
|
||||
)
|
||||
(else
|
||||
(cons (quasi (car subexp) level) (quasi (cdr subexp) level))
|
||||
)
|
||||
)
|
||||
) ) ; end else, let
|
||||
) ; end cond
|
||||
)
|
||||
|
||||
(quasi exp 0) ; need to unquote to level 0 to paint
|
||||
)
|
||||
|
||||
;; --- E O F ---
|
|
@ -1,343 +0,0 @@
|
|||
; "mwsynrul.scm" Compiler for a <transformer spec>.
|
||||
; Copyright 1992 William Clinger
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
; I also request that you send me a copy of any improvements that you
|
||||
; make to this software so that they may be incorporated within it to
|
||||
; the benefit of the Scheme community.
|
||||
|
||||
;;;; Compiler for a <transformer spec>.
|
||||
|
||||
;;; The input is a <transformer spec> and a syntactic environment.
|
||||
;;; Syntactic environments are described in another file.
|
||||
|
||||
;;; Transormer specs are in slib.texi.
|
||||
|
||||
(define mw:pattern-variable-flag (list 'v))
|
||||
(define mw:ellipsis-pattern-flag (list 'e))
|
||||
(define mw:ellipsis-template-flag mw:ellipsis-pattern-flag)
|
||||
|
||||
(define (mw:make-patternvar v rank)
|
||||
(vector mw:pattern-variable-flag v rank))
|
||||
(define (mw:make-ellipsis-pattern P vars)
|
||||
(vector mw:ellipsis-pattern-flag P vars))
|
||||
(define (mw:make-ellipsis-template T vars)
|
||||
(vector mw:ellipsis-template-flag T vars))
|
||||
|
||||
(define (mw:patternvar? x)
|
||||
(and (vector? x)
|
||||
(= (vector-length x) 3)
|
||||
(eq? (vector-ref x 0) mw:pattern-variable-flag)))
|
||||
|
||||
(define (mw:ellipsis-pattern? x)
|
||||
(and (vector? x)
|
||||
(= (vector-length x) 3)
|
||||
(eq? (vector-ref x 0) mw:ellipsis-pattern-flag)))
|
||||
|
||||
(define (mw:ellipsis-template? x)
|
||||
(and (vector? x)
|
||||
(= (vector-length x) 3)
|
||||
(eq? (vector-ref x 0) mw:ellipsis-template-flag)))
|
||||
|
||||
(define (mw:patternvar-name V) (vector-ref V 1))
|
||||
(define (mw:patternvar-rank V) (vector-ref V 2))
|
||||
(define (mw:ellipsis-pattern P) (vector-ref P 1))
|
||||
(define (mw:ellipsis-pattern-vars P) (vector-ref P 2))
|
||||
(define (mw:ellipsis-template T) (vector-ref T 1))
|
||||
(define (mw:ellipsis-template-vars T) (vector-ref T 2))
|
||||
|
||||
(define (mw:pattern-variable v vars)
|
||||
(cond ((null? vars) #f)
|
||||
((eq? v (mw:patternvar-name (car vars)))
|
||||
(car vars))
|
||||
(else (mw:pattern-variable v (cdr vars)))))
|
||||
|
||||
; Given a <transformer spec> and a syntactic environment,
|
||||
; returns a macro denotation.
|
||||
;
|
||||
; A macro denotation is of the form
|
||||
;
|
||||
; (macro (<rule> ...) env)
|
||||
;
|
||||
; where each <rule> has been compiled as described above.
|
||||
|
||||
(define (mw:compile-transformer-spec spec env)
|
||||
(if (and (> (mw:safe-length spec) 1)
|
||||
(eq? (mw:syntax-lookup env (car spec))
|
||||
mw:denote-of-syntax-rules))
|
||||
(let ((literals (cadr spec))
|
||||
(rules (cddr spec)))
|
||||
(if (or (not (list? literals))
|
||||
(not (comlist:every (lambda (rule)
|
||||
(and (= (mw:safe-length rule) 2)
|
||||
(pair? (car rule))))
|
||||
rules)))
|
||||
(mw:error "Malformed syntax-rules" spec))
|
||||
(list 'macro
|
||||
(map (lambda (rule)
|
||||
(mw:compile-rule rule literals env))
|
||||
rules)
|
||||
env))
|
||||
(mw:error "Malformed syntax-rules" spec)))
|
||||
|
||||
(define (mw:compile-rule rule literals env)
|
||||
(mw:compile-pattern (cdr (car rule))
|
||||
literals
|
||||
env
|
||||
(lambda (compiled-rule patternvars)
|
||||
; should check uniqueness of pattern variables here!!!!!
|
||||
(cons compiled-rule
|
||||
(mw:compile-template
|
||||
(cadr rule)
|
||||
patternvars
|
||||
env)))))
|
||||
|
||||
(define (mw:compile-pattern P literals env k)
|
||||
(define (loop P vars rank k)
|
||||
(cond ((symbol? P)
|
||||
(if (memq P literals)
|
||||
(k P vars)
|
||||
(let ((var (mw:make-patternvar P rank)))
|
||||
(k var (cons var vars)))))
|
||||
((null? P) (k '() vars))
|
||||
((pair? P)
|
||||
(if (and (pair? (cdr P))
|
||||
(symbol? (cadr P))
|
||||
(eq? (mw:syntax-lookup env (cadr P))
|
||||
mw:denote-of-...))
|
||||
(if (null? (cddr P))
|
||||
(loop (car P)
|
||||
'()
|
||||
(+ rank 1)
|
||||
(lambda (P vars1)
|
||||
(k (mw:make-ellipsis-pattern P vars1)
|
||||
(comlist:union vars1 vars))))
|
||||
(mw:error "Malformed pattern" P))
|
||||
(loop (car P)
|
||||
vars
|
||||
rank
|
||||
(lambda (P1 vars)
|
||||
(loop (cdr P)
|
||||
vars
|
||||
rank
|
||||
(lambda (P2 vars)
|
||||
(k (cons P1 P2) vars)))))))
|
||||
((vector? P)
|
||||
(loop (vector->list P)
|
||||
vars
|
||||
rank
|
||||
(lambda (P vars)
|
||||
(k (vector P) vars))))
|
||||
(else (k P vars))))
|
||||
(loop P '() 0 k))
|
||||
|
||||
(define (mw:compile-template T vars env)
|
||||
|
||||
(define (loop T inserted referenced rank escaped? k)
|
||||
(cond ((symbol? T)
|
||||
(let ((x (mw:pattern-variable T vars)))
|
||||
(if x
|
||||
(if (>= rank (mw:patternvar-rank x))
|
||||
(k x inserted (cons x referenced))
|
||||
(mw:error
|
||||
"Too few ellipses follow pattern variable in template"
|
||||
(mw:patternvar-name x)))
|
||||
(k T (cons T inserted) referenced))))
|
||||
((null? T) (k '() inserted referenced))
|
||||
((pair? T)
|
||||
(cond ((and (not escaped?)
|
||||
(symbol? (car T))
|
||||
(eq? (mw:syntax-lookup env (car T))
|
||||
mw:denote-of-:::)
|
||||
(pair? (cdr T))
|
||||
(null? (cddr T)))
|
||||
(loop (cadr T) inserted referenced rank #t k))
|
||||
((and (not escaped?)
|
||||
(pair? (cdr T))
|
||||
(symbol? (cadr T))
|
||||
(eq? (mw:syntax-lookup env (cadr T))
|
||||
mw:denote-of-...))
|
||||
(loop1 T inserted referenced rank escaped? k))
|
||||
(else
|
||||
(loop (car T)
|
||||
inserted
|
||||
referenced
|
||||
rank
|
||||
escaped?
|
||||
(lambda (T1 inserted referenced)
|
||||
(loop (cdr T)
|
||||
inserted
|
||||
referenced
|
||||
rank
|
||||
escaped?
|
||||
(lambda (T2 inserted referenced)
|
||||
(k (cons T1 T2) inserted referenced))))))))
|
||||
((vector? T)
|
||||
(loop (vector->list T)
|
||||
inserted
|
||||
referenced
|
||||
rank
|
||||
escaped?
|
||||
(lambda (T inserted referenced)
|
||||
(k (vector T) inserted referenced))))
|
||||
(else (k T inserted referenced))))
|
||||
|
||||
(define (loop1 T inserted referenced rank escaped? k)
|
||||
(loop (car T)
|
||||
inserted
|
||||
'()
|
||||
(+ rank 1)
|
||||
escaped?
|
||||
(lambda (T1 inserted referenced1)
|
||||
(loop (cddr T)
|
||||
inserted
|
||||
(append referenced1 referenced)
|
||||
rank
|
||||
escaped?
|
||||
(lambda (T2 inserted referenced)
|
||||
(k (cons (mw:make-ellipsis-template
|
||||
T1
|
||||
(comlist:remove-if-not
|
||||
(lambda (var) (> (mw:patternvar-rank var)
|
||||
rank))
|
||||
referenced1))
|
||||
T2)
|
||||
inserted
|
||||
referenced))))))
|
||||
|
||||
(loop T
|
||||
'()
|
||||
'()
|
||||
0
|
||||
#f
|
||||
(lambda (T inserted referenced)
|
||||
(list T inserted))))
|
||||
|
||||
; The pattern matcher.
|
||||
;
|
||||
; Given an input, a pattern, and two syntactic environments,
|
||||
; returns a pattern variable environment (represented as an alist)
|
||||
; if the input matches the pattern, otherwise returns #f.
|
||||
|
||||
(define mw:empty-pattern-variable-environment
|
||||
(list (mw:make-patternvar (string->symbol "") 0)))
|
||||
|
||||
(define (mw:match F P env-def env-use)
|
||||
|
||||
(define (match F P answer rank)
|
||||
(cond ((null? P)
|
||||
(and (null? F) answer))
|
||||
((pair? P)
|
||||
(and (pair? F)
|
||||
(let ((answer (match (car F) (car P) answer rank)))
|
||||
(and answer (match (cdr F) (cdr P) answer rank)))))
|
||||
((symbol? P)
|
||||
(and (symbol? F)
|
||||
(mw:same-denotation? (mw:syntax-lookup env-def P)
|
||||
(mw:syntax-lookup env-use F))
|
||||
answer))
|
||||
((mw:patternvar? P)
|
||||
(cons (cons P F) answer))
|
||||
((mw:ellipsis-pattern? P)
|
||||
(match1 F P answer (+ rank 1)))
|
||||
((vector? P)
|
||||
(and (vector? F)
|
||||
(match (vector->list F) (vector-ref P 0) answer rank)))
|
||||
(else (and (equal? F P) answer))))
|
||||
|
||||
(define (match1 F P answer rank)
|
||||
(cond ((not (list? F)) #f)
|
||||
((null? F)
|
||||
(append (map (lambda (var) (cons var '()))
|
||||
(mw:ellipsis-pattern-vars P))
|
||||
answer))
|
||||
(else
|
||||
(let* ((P1 (mw:ellipsis-pattern P))
|
||||
(answers (map (lambda (F) (match F P1 answer rank))
|
||||
F)))
|
||||
(if (comlist:every identity answers)
|
||||
(append (map (lambda (var)
|
||||
(cons var
|
||||
(map (lambda (answer)
|
||||
(cdr (assq var answer)))
|
||||
answers)))
|
||||
(mw:ellipsis-pattern-vars P))
|
||||
answer)
|
||||
#f)))))
|
||||
|
||||
(match F P mw:empty-pattern-variable-environment 0))
|
||||
|
||||
(define (mw:rewrite T alist)
|
||||
|
||||
(define (rewrite T alist rank)
|
||||
(cond ((null? T) '())
|
||||
((pair? T)
|
||||
((if (mw:ellipsis-pattern? (car T))
|
||||
append
|
||||
cons)
|
||||
(rewrite (car T) alist rank)
|
||||
(rewrite (cdr T) alist rank)))
|
||||
((symbol? T) (cdr (assq T alist)))
|
||||
((mw:patternvar? T) (cdr (assq T alist)))
|
||||
((mw:ellipsis-template? T)
|
||||
(rewrite1 T alist (+ rank 1)))
|
||||
((vector? T)
|
||||
(list->vector (rewrite (vector-ref T 0) alist rank)))
|
||||
(else T)))
|
||||
|
||||
(define (rewrite1 T alist rank)
|
||||
(let* ((T1 (mw:ellipsis-template T))
|
||||
(vars (mw:ellipsis-template-vars T))
|
||||
(rows (map (lambda (var) (cdr (assq var alist)))
|
||||
vars)))
|
||||
(map (lambda (alist) (rewrite T1 alist rank))
|
||||
(make-columns vars rows alist))))
|
||||
|
||||
(define (make-columns vars rows alist)
|
||||
(define (loop rows)
|
||||
(if (null? (car rows))
|
||||
'()
|
||||
(cons (append (map (lambda (var row)
|
||||
(cons var (car row)))
|
||||
vars
|
||||
rows)
|
||||
alist)
|
||||
(loop (map cdr rows)))))
|
||||
(if (or (null? (cdr rows))
|
||||
(apply = (map length rows)))
|
||||
(loop rows)
|
||||
(mw:error "Use of macro is not consistent with definition"
|
||||
vars
|
||||
rows)))
|
||||
|
||||
(rewrite T alist 0))
|
||||
|
||||
; Given a use of a macro, the syntactic environment of the use,
|
||||
; and a continuation that expects a transcribed expression and
|
||||
; a new environment in which to continue expansion,
|
||||
; does the right thing.
|
||||
|
||||
(define (mw:transcribe exp env-use k)
|
||||
(let* ((m (mw:syntax-lookup env-use (car exp)))
|
||||
(rules (macwork:rules m))
|
||||
(env-def (macwork:env m))
|
||||
(F (cdr exp)))
|
||||
(define (loop rules)
|
||||
(if (null? rules)
|
||||
(mw:error "Use of macro does not match definition" exp)
|
||||
(let* ((rule (car rules))
|
||||
(pattern (car rule))
|
||||
(alist (mw:match F pattern env-def env-use)))
|
||||
(if alist
|
||||
(let* ((template (cadr rule))
|
||||
(inserted (caddr rule))
|
||||
(alist2 (mw:rename-vars inserted))
|
||||
(newexp (mw:rewrite template (append alist2 alist))))
|
||||
(k newexp
|
||||
(mw:syntax-alias env-use alist2 env-def)))
|
||||
(loop (cdr rules))))))
|
||||
(loop rules)))
|
|
@ -1,385 +0,0 @@
|
|||
;;; "nclients.scm" Interface to net-client programs.
|
||||
; Copyright 1997, 1998 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'string-search)
|
||||
(require 'line-i/o)
|
||||
(require 'system)
|
||||
(require 'printf)
|
||||
(require 'scanf)
|
||||
|
||||
;;@args proc
|
||||
;;@args proc k
|
||||
;;Calls @1 with @var{k} arguments, strings returned by successive
|
||||
;;calls to @code{tmpnam}. If @1 returns, then any files named by the
|
||||
;;arguments to @1 are deleted automatically and the value(s) yielded
|
||||
;;by the @1 is(are) returned. @var{k} may be ommited, in which case
|
||||
;;it defaults to @code{1}.
|
||||
(define (call-with-tmpnam proc . k)
|
||||
(do ((cnt (if (null? k) 0 (+ -1 (car k))) (+ -1 cnt))
|
||||
(paths '() (cons (tmpnam) paths)))
|
||||
((negative? cnt)
|
||||
(let ((ans (apply proc paths)))
|
||||
(for-each (lambda (path) (if (file-exists? path) (delete-file path)))
|
||||
paths)
|
||||
ans))))
|
||||
|
||||
;;@args
|
||||
;;@0 returns a string of the form @samp{username@r{@@}hostname}. If
|
||||
;;this e-mail address cannot be obtained, #f is returned.
|
||||
(define user-email-address
|
||||
(let ((user (or (getenv "USER") (getenv "USERNAME")))
|
||||
(hostname (getenv "HOSTNAME"))) ;with domain
|
||||
(lambda ()
|
||||
(if (not (and user hostname))
|
||||
(call-with-tmpnam
|
||||
(lambda (tmp)
|
||||
(define command->string
|
||||
(lambda (command)
|
||||
(and (zero? (system (string-append command " >" tmp)))
|
||||
(file-exists? tmp)
|
||||
(let ((res #f))
|
||||
(call-with-input-file tmp
|
||||
(lambda (port)
|
||||
(and (eqv? 1 (fscanf port "%s" res)) res)))))))
|
||||
(case (software-type)
|
||||
;;((AMIGA) )
|
||||
;;((MACOS THINKC) )
|
||||
((MS-DOS WINDOWS OS/2 ATARIST)
|
||||
(let ((compname (getenv "COMPUTERNAME")) ;without domain
|
||||
(workgroup #f)
|
||||
(netdir (or (getenv "windir")
|
||||
(getenv "winbootdir")
|
||||
(and (getenv "SYSTEMROOT")
|
||||
(string-append (getenv "SYSTEMROOT")
|
||||
"\\system32"))
|
||||
"C:\\windows")))
|
||||
(define (net . cmd)
|
||||
(zero? (system (apply string-append
|
||||
(or netdir "")
|
||||
(if netdir "\\" "")
|
||||
"NET " cmd))))
|
||||
(and (not (and user hostname))
|
||||
(zero? (system (string-append
|
||||
(or netdir "")
|
||||
(if netdir "\\" "")
|
||||
"IPCONFIG /ALL > " tmp " ")))
|
||||
(file-exists? tmp)
|
||||
;;(print tmp '=) (display-file tmp)
|
||||
(call-with-input-file tmp
|
||||
(lambda (port)
|
||||
(find-string-from-port? "Host Name" port)
|
||||
(fscanf port " %*[. ]: %s" hostname)
|
||||
(delete-file tmp))))
|
||||
(and (not (and user hostname))
|
||||
(net "START /LIST >" tmp)
|
||||
(file-exists? tmp)
|
||||
(not (eof-object? (call-with-input-file tmp read-char)))
|
||||
(cond
|
||||
((call-with-input-file tmp
|
||||
(lambda (port)
|
||||
(find-string-from-port? "o network servic" port)))
|
||||
(and (net "CONFIG /YES >" tmp)
|
||||
(net "STOP /YES")))
|
||||
(else (net "CONFIG /YES >" tmp)))
|
||||
(call-with-input-file tmp
|
||||
(lambda (port)
|
||||
(do ((line (read-line port) (read-line port)))
|
||||
((eof-object? line))
|
||||
(sscanf line " Workstation root directory %s"
|
||||
netdir)
|
||||
(sscanf line " Computer name \\\\%s" compname)
|
||||
(sscanf line " Workstation Domain %s" workgroup)
|
||||
(sscanf line " Workgroup %s" workgroup)
|
||||
(sscanf line " User name %s" user)))))
|
||||
(and netdir (not (and user hostname))
|
||||
(set! netdir (string-append netdir "\\system.ini"))
|
||||
(file-exists? netdir)
|
||||
(call-with-input-file netdir
|
||||
(lambda (port)
|
||||
(and (find-string-from-port? "[DNS]" port)
|
||||
(read-line port) ;past newline
|
||||
(do ((line (read-line port) (read-line port)))
|
||||
((not (and (string? line)
|
||||
(string-index line #\=))))
|
||||
(sscanf line "HostName=%s" compname)
|
||||
(sscanf line "DomainName=%s" workgroup)))))
|
||||
(not user)
|
||||
(call-with-input-file netdir
|
||||
(lambda (port)
|
||||
(and (find-string-from-port? "[Network]" port)
|
||||
(read-line port) ;past newline
|
||||
(do ((line (read-line port) (read-line port)))
|
||||
((not (and (string? line)
|
||||
(string-index line #\=))))
|
||||
(sscanf line "UserName=%s" user))))))
|
||||
(if (and compname (not hostname))
|
||||
(set! hostname
|
||||
(string-append
|
||||
compname "." (or workgroup "localnet"))))))
|
||||
;;((NOSVE) )
|
||||
;;((VMS) )
|
||||
((UNIX COHERENT)
|
||||
(if (not user)
|
||||
(set! user (command->string "whoami")))
|
||||
(if (not hostname)
|
||||
(set! hostname (command->string "hostname")))))
|
||||
(if (not user) (set! user "John_Doe"))
|
||||
(if (not hostname) (set! hostname "localhost")))))
|
||||
(string-append user "@" hostname))))
|
||||
|
||||
;;@args
|
||||
;;@0 returns a string containing the absolute file name representing
|
||||
;;the current working directory. If this string cannot be obtained,
|
||||
;;#f is returned.
|
||||
;;
|
||||
;;If @0 cannot be supported by the platform, the value of @0 is
|
||||
;;#f.
|
||||
(define current-directory
|
||||
(case (software-type)
|
||||
;;((AMIGA) )
|
||||
;;((MACOS THINKC) )
|
||||
((MS-DOS WINDOWS ATARIST OS/2)
|
||||
(lambda ()
|
||||
(call-with-tmpnam
|
||||
(lambda (tmp)
|
||||
(and (zero? (system (string-append "cd >" tmp)))
|
||||
(file-exists? tmp)
|
||||
(call-with-input-file tmp
|
||||
(lambda (port)
|
||||
(let ((lst (scanf-read-list "%[^:]%[:] %s" port)))
|
||||
(and (pair? lst)
|
||||
(eqv? 3 (length lst))
|
||||
(apply string-append lst))))))))))
|
||||
;;((NOSVE) )
|
||||
((UNIX COHERENT)
|
||||
(lambda ()
|
||||
(call-with-tmpnam
|
||||
(lambda (tmp)
|
||||
(and (zero? (system (string-append "pwd >" tmp)))
|
||||
(file-exists? tmp)
|
||||
(let ((path (call-with-input-file tmp read-line)))
|
||||
(and (string? path) path)))))))
|
||||
;;((VMS) )
|
||||
(else #f)))
|
||||
|
||||
;;@body
|
||||
;;Creates a sub-directory @1 of the current-directory. If successful,
|
||||
;;@0 returns #t; otherwise #f.
|
||||
(define (make-directory name)
|
||||
(zero? (system (string-append "mkdir " name))))
|
||||
|
||||
;;@body
|
||||
;;Returns #t if changing directory to @1 makes the current working
|
||||
;;directory the same as it is before changing directory; otherwise
|
||||
;;returns #f.
|
||||
(define (null-directory? file-name)
|
||||
(member file-name '("" "." "./" ".\\")))
|
||||
|
||||
;;@body
|
||||
;;Returns #t if @1 is a fully specified pathname (does not depend on
|
||||
;;the current working directory); otherwise returns #f.
|
||||
(define (absolute-path? file-name)
|
||||
(and (string? file-name)
|
||||
(positive? (string-length file-name))
|
||||
(memv (string-ref file-name 0) '(#\\ #\/))))
|
||||
|
||||
|
||||
;;@body Returns #t if the string @1 contains characters used for
|
||||
;;specifying glob patterns, namely @samp{*}, @samp{?}, or @samp{[}.
|
||||
(define (glob-pattern? str)
|
||||
(let loop ((idx (+ -1 (string-length str))))
|
||||
(if (negative? idx)
|
||||
#f
|
||||
(case (string-ref str idx)
|
||||
((#\* #\[ #\?) #t)
|
||||
(else (loop (+ -1 idx)))))))
|
||||
|
||||
;;@body
|
||||
;;Returns a list of the decoded FTP @1; or #f if indecipherable. FTP
|
||||
;;@dfn{Uniform Resource Locator}, @dfn{ange-ftp}, and @dfn{getit}
|
||||
;;formats are handled. The returned list has four elements which are
|
||||
;;strings or #f:
|
||||
;;
|
||||
;;@enumerate 0
|
||||
;;@item
|
||||
;;username
|
||||
;;@item
|
||||
;;password
|
||||
;;@item
|
||||
;;remote-site
|
||||
;;@item
|
||||
;;remote-directory
|
||||
;;@end enumerate
|
||||
(define (parse-ftp-address uri)
|
||||
(define length? (lambda (len lst) (and (eqv? len (length lst)) lst)))
|
||||
(cond
|
||||
((not uri) #f)
|
||||
((length? 1 (scanf-read-list " ftp://%s %s" uri))
|
||||
=> (lambda (host)
|
||||
(let ((login #f) (path #f) (dross #f))
|
||||
(sscanf (car host) "%[^/]/%[^@]%s" login path dross)
|
||||
(and login
|
||||
(append (cond
|
||||
((length? 2 (scanf-read-list "%[^@]@%[^@]%s" login))
|
||||
=> (lambda (userpass@hostport)
|
||||
(append
|
||||
(cond ((length? 2 (scanf-read-list
|
||||
"%[^:]:%[^@/]%s"
|
||||
(car userpass@hostport))))
|
||||
(else (list (car userpass@hostport) #f)))
|
||||
(cdr userpass@hostport))))
|
||||
(else (list "anonymous" #f login)))
|
||||
(list path))))))
|
||||
(else
|
||||
(let ((user@site #f) (colon #f) (path #f) (dross #f))
|
||||
(case (sscanf uri " %[^:]%[:]%[^@] %s" user@site colon path dross)
|
||||
((2 3)
|
||||
(let ((user #f) (site #f))
|
||||
(cond ((or (eqv? 2 (sscanf user@site "/%[^@/]@%[^@]%s"
|
||||
user site dross))
|
||||
(eqv? 2 (sscanf user@site "%[^@/]@%[^@]%s"
|
||||
user site dross)))
|
||||
(list user #f site path))
|
||||
((eqv? 1 (sscanf user@site "@%[^@]%s" site dross))
|
||||
(list #f #f site path))
|
||||
(else (list #f #f user@site path)))))
|
||||
(else
|
||||
(let ((site (scanf-read-list " %[^@/] %s" uri)))
|
||||
(and (length? 1 site) (list #f #f (car site) #f)))))))))
|
||||
|
||||
;;@body
|
||||
;;@3 must be a non-empty string or #f. @1 must be a non-empty list
|
||||
;;of pathnames or Glob patterns (@pxref{Filenames}) matching files to
|
||||
;;transfer.
|
||||
;;
|
||||
;;@0 puts the files specified by @1 into the @5 directory of FTP @4
|
||||
;;using name @2 with (optional) @3.
|
||||
;;
|
||||
;;If @3 is #f and @2 is not @samp{ftp} or @samp{anonymous}, then @2 is
|
||||
;;ignored; FTP takes the username and password from the @file{.netrc}
|
||||
;;or equivalent file.
|
||||
(define (ftp-upload paths user password remote-site remote-dir)
|
||||
(call-with-tmpnam
|
||||
(lambda (script logfile)
|
||||
(define local-path (current-directory))
|
||||
(define passwd (or password (user-email-address)))
|
||||
(dynamic-wind
|
||||
(lambda () #f)
|
||||
(lambda ()
|
||||
(call-with-current-continuation
|
||||
(lambda (exit)
|
||||
(define (run-ftp-script paths)
|
||||
(call-with-output-file script
|
||||
(lambda (port)
|
||||
(define lcd "")
|
||||
(cond ((or (member user '(ftp anonymous "ftp" "anonymous"))
|
||||
password)
|
||||
(fprintf port "user %s %s\n" user passwd)))
|
||||
(fprintf port "binary\n") ; Turn binary ON for all transfers
|
||||
;;(fprintf port "prompt\n") ; Turn prompt OFF for possible mget
|
||||
(if (not (null-directory? remote-dir))
|
||||
(fprintf port "cd %s\n" remote-dir))
|
||||
(for-each
|
||||
(lambda (path-name)
|
||||
(let* ((r/i (string-reverse-index path-name #\/))
|
||||
(dir (if r/i (substring path-name 0 (+ 1 r/i)) ""))
|
||||
(file-name (if r/i
|
||||
(substring path-name (+ 1 r/i)
|
||||
(string-length path-name))
|
||||
path-name)))
|
||||
(cond ((and r/i (glob-pattern? dir))
|
||||
(slib:warn
|
||||
"Wildcard not allowed in directory component "
|
||||
path-name)
|
||||
(exit #f))
|
||||
((and (not (glob-pattern? file-name))
|
||||
(not (file-exists? path-name)))
|
||||
(slib:warn " file doesn't exist:" path-name)
|
||||
(exit #f))
|
||||
((equal? lcd dir))
|
||||
((absolute-path? dir)
|
||||
(fprintf port "lcd %s\n" dir))
|
||||
((eqv? 0 (substring? lcd dir))
|
||||
(fprintf port "lcd %s\n"
|
||||
(substring dir (string-length lcd)
|
||||
(string-length dir))))
|
||||
(else
|
||||
(fprintf port "lcd %s\n" local-path)
|
||||
(if (not (null-directory? dir))
|
||||
(fprintf port "lcd %s\n" dir))))
|
||||
(set! lcd dir)
|
||||
(cond ((glob-pattern? file-name)
|
||||
(fprintf port "mput %s\n" file-name))
|
||||
(else
|
||||
(fprintf port "put %s\n" file-name)))))
|
||||
paths)))
|
||||
;;(display-file script)
|
||||
(cond
|
||||
((zero? (system
|
||||
(string-append
|
||||
"ftp "
|
||||
(if (or (member user '(ftp anonymous "ftp" "anonymous"))
|
||||
password)
|
||||
"-inv" "-iv")
|
||||
" " remote-site
|
||||
" <" script
|
||||
" >" logfile)))
|
||||
(file-exists? logfile)
|
||||
(call-with-input-file logfile
|
||||
(lambda (port)
|
||||
(do ((line (read-line port) (read-line port)))
|
||||
((or (eof-object? line)
|
||||
(substring-ci? "Unknown host" line)
|
||||
(substring-ci? "Not connected" line)
|
||||
(and (memv (string-ref line 0) '(#\4 #\5))
|
||||
(not (substring-ci? "bytes" line))))
|
||||
(cond ((eof-object? line) #t)
|
||||
(else (slib:warn line) #f)))
|
||||
;;(write-line line)
|
||||
))))
|
||||
(else (slib:warn 'ftp 'failed) #f)))
|
||||
(cond ((or local-path (every? absolute-file? paths))
|
||||
(run-ftp-script paths))
|
||||
(else (for-each (lambda (path) (run-ftp-script (list path)))
|
||||
paths))))))
|
||||
(lambda ()
|
||||
(if (file-exists? script) (delete-file script))
|
||||
(if (file-exists? logfile) (delete-file logfile)))))
|
||||
2))
|
||||
|
||||
;;@body
|
||||
;;Returns a URI-string for @1 on the local host.
|
||||
(define (path->uri path)
|
||||
(if (absolute-path? path)
|
||||
(sprintf #f "file:%s" path)
|
||||
(sprintf #f "file:%s/%s" (current-directory) path)))
|
||||
|
||||
;;@body
|
||||
;;If a @samp{netscape} browser is running, @0 causes the browser to
|
||||
;;display the page specified by string @1 and returns #t.
|
||||
;;
|
||||
;;If the browser is not running, @0 runs @samp{netscape} with the
|
||||
;;argument @1. If the browser starts as a background job, @0 returns
|
||||
;;#t immediately; if the browser starts as a foreground job, then @0
|
||||
;;returns #t when the browser exits; otherwise it returns #f.
|
||||
(define (browse-url-netscape url)
|
||||
(or (eqv? 0 (system (sprintf #f "netscape-remote -remote 'openURL(%s)'" url)))
|
||||
(eqv? 0 (system (sprintf #f "netscape -remote 'openURL(%s)'" url)))
|
||||
(eqv? 0 (system (sprintf #f "netscape '%s'&" url)))
|
||||
(eqv? 0 (system (sprintf #f "netscape '%s'" url)))))
|
|
@ -1,103 +0,0 @@
|
|||
|
||||
@defun call-with-tmpnam proc
|
||||
|
||||
|
||||
@defunx call-with-tmpnam proc k
|
||||
Calls @var{proc} with @var{k} arguments, strings returned by successive
|
||||
calls to @code{tmpnam}. If @var{proc} returns, then any files named by the
|
||||
arguments to @var{proc} are deleted automatically and the value(s) yielded
|
||||
by the @var{proc} is(are) returned. @var{k} may be ommited, in which case
|
||||
it defaults to @code{1}.
|
||||
@end defun
|
||||
|
||||
@defun user-email-address
|
||||
|
||||
@code{user-email-address} returns a string of the form @samp{username@r{@@}hostname}. If
|
||||
this e-mail address cannot be obtained, #f is returned.
|
||||
@end defun
|
||||
|
||||
@defun current-directory
|
||||
|
||||
@code{current-directory} returns a string containing the absolute file name representing
|
||||
the current working directory. If this string cannot be obtained,
|
||||
#f is returned.
|
||||
|
||||
If @code{current-directory} cannot be supported by the platform, the value of @code{current-directory} is
|
||||
#f.
|
||||
@end defun
|
||||
|
||||
@defun make-directory name
|
||||
|
||||
Creates a sub-directory @var{name} of the current-directory. If successful,
|
||||
@code{make-directory} returns #t; otherwise #f.
|
||||
@end defun
|
||||
|
||||
@defun null-directory? file-name
|
||||
|
||||
Returns #t if changing directory to @var{file-name} makes the current working
|
||||
directory the same as it is before changing directory; otherwise
|
||||
returns #f.
|
||||
@end defun
|
||||
|
||||
@defun absolute-path? file-name
|
||||
|
||||
Returns #t if @var{file-name} is a fully specified pathname (does not depend on
|
||||
the current working directory); otherwise returns #f.
|
||||
@end defun
|
||||
|
||||
@defun glob-pattern? str
|
||||
Returns #t if the string @var{str} contains characters used for
|
||||
specifying glob patterns, namely @samp{*}, @samp{?}, or @samp{[}.
|
||||
@end defun
|
||||
|
||||
@defun parse-ftp-address uri
|
||||
|
||||
Returns a list of the decoded FTP @var{uri}; or #f if indecipherable. FTP
|
||||
@dfn{Uniform Resource Locator}, @dfn{ange-ftp}, and @dfn{getit}
|
||||
@cindex Uniform Resource Locator
|
||||
@cindex ange-ftp
|
||||
@cindex getit
|
||||
formats are handled. The returned list has four elements which are
|
||||
strings or #f:
|
||||
|
||||
@enumerate 0
|
||||
@item
|
||||
username
|
||||
@item
|
||||
password
|
||||
@item
|
||||
remote-site
|
||||
@item
|
||||
remote-directory
|
||||
@end enumerate
|
||||
@end defun
|
||||
|
||||
@defun ftp-upload paths user password remote-site remote-dir
|
||||
|
||||
@var{password} must be a non-empty string or #f. @var{paths} must be a non-empty list
|
||||
of pathnames or Glob patterns (@pxref{Filenames}) matching files to
|
||||
transfer.
|
||||
|
||||
@code{ftp-upload} puts the files specified by @var{paths} into the @var{remote-dir} directory of FTP @var{remote-site}
|
||||
using name @var{user} with (optional) @var{password}.
|
||||
|
||||
If @var{password} is #f and @var{user} is not @samp{ftp} or @samp{anonymous}, then @var{user} is
|
||||
ignored; FTP takes the username and password from the @file{.netrc}
|
||||
or equivalent file.
|
||||
@end defun
|
||||
|
||||
@defun path->uri path
|
||||
|
||||
Returns a URI-string for @var{path} on the local host.
|
||||
@end defun
|
||||
|
||||
@defun browse-url-netscape url
|
||||
|
||||
If a @samp{netscape} browser is running, @code{browse-url-netscape} causes the browser to
|
||||
display the page specified by string @var{url} and returns #t.
|
||||
|
||||
If the browser is not running, @code{browse-url-netscape} runs @samp{netscape} with the
|
||||
argument @var{url}. If the browser starts as a background job, @code{browse-url-netscape} returns
|
||||
#t immediately; if the browser starts as a foreground job, then @code{browse-url-netscape}
|
||||
returns #t when the browser exits; otherwise it returns #f.
|
||||
@end defun
|
|
@ -1,63 +0,0 @@
|
|||
;;; "obj2str.scm", write objects to a string.
|
||||
;Copyright (C) 1993, 1994 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'string-port)
|
||||
|
||||
;;@body Returns the textual representation of @1 as a string.
|
||||
(define (object->string obj)
|
||||
(cond ((symbol? obj) (symbol->string obj))
|
||||
((number? obj) (number->string obj))
|
||||
(else
|
||||
(call-with-output-string
|
||||
(lambda (port) (write obj port))))))
|
||||
|
||||
; File: "obj2str.scm" (c) 1991, Marc Feeley
|
||||
|
||||
;(require 'generic-write)
|
||||
|
||||
; (object->string obj) returns the textual representation of 'obj' as a
|
||||
; string.
|
||||
;
|
||||
; Note: (write obj) = (display (object->string obj))
|
||||
|
||||
;(define (object->string obj)
|
||||
; (let ((result '()))
|
||||
; (generic-write obj #f #f (lambda (str) (set! result (cons str result)) #t))
|
||||
; (reverse-string-append result)))
|
||||
|
||||
; (object->limited-string obj limit) returns a string containing the first
|
||||
; 'limit' characters of the textual representation of 'obj'.
|
||||
|
||||
;;@body Returns the textual representation of @1 as a string of length
|
||||
;;at most @2.
|
||||
(define (object->limited-string obj limit)
|
||||
(require 'generic-write)
|
||||
(let ((result '()) (left limit))
|
||||
(generic-write obj #f #f
|
||||
(lambda (str)
|
||||
(let ((len (string-length str)))
|
||||
(cond ((> len left)
|
||||
(set! result (cons (substring str 0 left) result))
|
||||
(set! left 0)
|
||||
#f)
|
||||
(else
|
||||
(set! result (cons str result))
|
||||
(set! left (- left len))
|
||||
#t)))))
|
||||
(reverse-string-append result)))
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
@defun object->string obj
|
||||
Returns the textual representation of @var{obj} as a string.
|
||||
@end defun
|
||||
|
||||
@defun object->limited-string obj limit
|
||||
Returns the textual representation of @var{obj} as a string of length
|
||||
at most @var{limit}.
|
||||
@end defun
|
|
@ -1,238 +0,0 @@
|
|||
|
||||
@code{(require 'object)}
|
||||
@ftindex object
|
||||
|
||||
This is the Macroless Object System written by Wade Humeniuk
|
||||
(whumeniu@@datap.ca). Conceptual Tributes: @ref{Yasos}, MacScheme's
|
||||
%object, CLOS, Lack of R4RS macros.
|
||||
|
||||
@subsection Concepts
|
||||
@table @asis
|
||||
|
||||
@item OBJECT
|
||||
An object is an ordered association-list (by @code{eq?}) of methods
|
||||
(procedures). Methods can be added (@code{make-method!}), deleted
|
||||
(@code{unmake-method!}) and retrieved (@code{get-method}). Objects may
|
||||
inherit methods from other objects. The object binds to the environment
|
||||
it was created in, allowing closures to be used to hide private
|
||||
procedures and data.
|
||||
|
||||
@item GENERIC-METHOD
|
||||
A generic-method associates (in terms of @code{eq?}) object's method.
|
||||
This allows scheme function style to be used for objects. The calling
|
||||
scheme for using a generic method is @code{(generic-method object param1
|
||||
param2 ...)}.
|
||||
|
||||
@item METHOD
|
||||
A method is a procedure that exists in the object. To use a method
|
||||
get-method must be called to look-up the method. Generic methods
|
||||
implement the get-method functionality. Methods may be added to an
|
||||
object associated with any scheme obj in terms of eq?
|
||||
|
||||
@item GENERIC-PREDICATE
|
||||
A generic method that returns a boolean value for any scheme obj.
|
||||
|
||||
@item PREDICATE
|
||||
A object's method asscociated with a generic-predicate. Returns
|
||||
@code{#t}.
|
||||
@end table
|
||||
|
||||
@subsection Procedures
|
||||
|
||||
@defun make-object ancestor @dots{}
|
||||
Returns an object. Current object implementation is a tagged vector.
|
||||
@var{ancestor}s are optional and must be objects in terms of object?.
|
||||
@var{ancestor}s methods are included in the object. Multiple
|
||||
@var{ancestor}s might associate the same generic-method with a method.
|
||||
In this case the method of the @var{ancestor} first appearing in the
|
||||
list is the one returned by @code{get-method}.
|
||||
@end defun
|
||||
|
||||
@defun object? obj
|
||||
Returns boolean value whether @var{obj} was created by make-object.
|
||||
@end defun
|
||||
|
||||
@defun make-generic-method exception-procedure
|
||||
Returns a procedure which be associated with an object's methods. If
|
||||
@var{exception-procedure} is specified then it is used to process
|
||||
non-objects.
|
||||
@end defun
|
||||
|
||||
@defun make-generic-predicate
|
||||
Returns a boolean procedure for any scheme object.
|
||||
@end defun
|
||||
|
||||
@defun make-method! object generic-method method
|
||||
Associates @var{method} to the @var{generic-method} in the object. The
|
||||
@var{method} overrides any previous association with the
|
||||
@var{generic-method} within the object. Using @code{unmake-method!}
|
||||
will restore the object's previous association with the
|
||||
@var{generic-method}. @var{method} must be a procedure.
|
||||
@end defun
|
||||
|
||||
@defun make-predicate! object generic-preciate
|
||||
Makes a predicate method associated with the @var{generic-predicate}.
|
||||
@end defun
|
||||
|
||||
@defun unmake-method! object generic-method
|
||||
Removes an object's association with a @var{generic-method} .
|
||||
@end defun
|
||||
|
||||
@defun get-method object generic-method
|
||||
Returns the object's method associated (if any) with the
|
||||
@var{generic-method}. If no associated method exists an error is
|
||||
flagged.
|
||||
@end defun
|
||||
|
||||
@subsection Examples
|
||||
|
||||
@example
|
||||
(require 'object)
|
||||
@ftindex object
|
||||
|
||||
(define instantiate (make-generic-method))
|
||||
|
||||
(define (make-instance-object . ancestors)
|
||||
(define self (apply make-object
|
||||
(map (lambda (obj) (instantiate obj)) ancestors)))
|
||||
(make-method! self instantiate (lambda (self) self))
|
||||
self)
|
||||
|
||||
(define who (make-generic-method))
|
||||
(define imigrate! (make-generic-method))
|
||||
(define emigrate! (make-generic-method))
|
||||
(define describe (make-generic-method))
|
||||
(define name (make-generic-method))
|
||||
(define address (make-generic-method))
|
||||
(define members (make-generic-method))
|
||||
|
||||
(define society
|
||||
(let ()
|
||||
(define self (make-instance-object))
|
||||
(define population '())
|
||||
(make-method! self imigrate!
|
||||
(lambda (new-person)
|
||||
(if (not (eq? new-person self))
|
||||
(set! population (cons new-person population)))))
|
||||
(make-method! self emigrate!
|
||||
(lambda (person)
|
||||
(if (not (eq? person self))
|
||||
(set! population
|
||||
(comlist:remove-if (lambda (member)
|
||||
(eq? member person))
|
||||
population)))))
|
||||
(make-method! self describe
|
||||
(lambda (self)
|
||||
(map (lambda (person) (describe person)) population)))
|
||||
(make-method! self who
|
||||
(lambda (self) (map (lambda (person) (name person))
|
||||
population)))
|
||||
(make-method! self members (lambda (self) population))
|
||||
self))
|
||||
|
||||
(define (make-person %name %address)
|
||||
(define self (make-instance-object society))
|
||||
(make-method! self name (lambda (self) %name))
|
||||
(make-method! self address (lambda (self) %address))
|
||||
(make-method! self who (lambda (self) (name self)))
|
||||
(make-method! self instantiate
|
||||
(lambda (self)
|
||||
(make-person (string-append (name self) "-son-of")
|
||||
%address)))
|
||||
(make-method! self describe
|
||||
(lambda (self) (list (name self) (address self))))
|
||||
(imigrate! self)
|
||||
self)
|
||||
@end example
|
||||
|
||||
@subsubsection Inverter Documentation
|
||||
Inheritance:
|
||||
@lisp
|
||||
<inverter>::(<number> <description>)
|
||||
@end lisp
|
||||
Generic-methods
|
||||
@lisp
|
||||
<inverter>::value @result{} <number>::value
|
||||
<inverter>::set-value! @result{} <number>::set-value!
|
||||
<inverter>::describe @result{} <description>::describe
|
||||
<inverter>::help
|
||||
<inverter>::invert
|
||||
<inverter>::inverter?
|
||||
@end lisp
|
||||
|
||||
@subsubsection Number Documention
|
||||
Inheritance
|
||||
@lisp
|
||||
<number>::()
|
||||
@end lisp
|
||||
Slots
|
||||
@lisp
|
||||
<number>::<x>
|
||||
@end lisp
|
||||
Generic Methods
|
||||
@lisp
|
||||
<number>::value
|
||||
<number>::set-value!
|
||||
@end lisp
|
||||
|
||||
@subsubsection Inverter code
|
||||
@example
|
||||
(require 'object)
|
||||
@ftindex object
|
||||
|
||||
(define value (make-generic-method (lambda (val) val)))
|
||||
(define set-value! (make-generic-method))
|
||||
(define invert (make-generic-method
|
||||
(lambda (val)
|
||||
(if (number? val)
|
||||
(/ 1 val)
|
||||
(error "Method not supported:" val)))))
|
||||
(define noop (make-generic-method))
|
||||
(define inverter? (make-generic-predicate))
|
||||
(define describe (make-generic-method))
|
||||
(define help (make-generic-method))
|
||||
|
||||
(define (make-number x)
|
||||
(define self (make-object))
|
||||
(make-method! self value (lambda (this) x))
|
||||
(make-method! self set-value!
|
||||
(lambda (this new-value) (set! x new-value)))
|
||||
self)
|
||||
|
||||
(define (make-description str)
|
||||
(define self (make-object))
|
||||
(make-method! self describe (lambda (this) str))
|
||||
(make-method! self help (lambda (this) "Help not available"))
|
||||
self)
|
||||
|
||||
(define (make-inverter)
|
||||
(let* ((self (make-object
|
||||
(make-number 1)
|
||||
(make-description "A number which can be inverted")))
|
||||
(<value> (get-method self value)))
|
||||
(make-method! self invert (lambda (self) (/ 1 (<value> self))))
|
||||
(make-predicate! self inverter?)
|
||||
(unmake-method! self help)
|
||||
(make-method! self help
|
||||
(lambda (self)
|
||||
(display "Inverter Methods:") (newline)
|
||||
(display " (value inverter) ==> n") (newline)))
|
||||
self))
|
||||
|
||||
;;;; Try it out
|
||||
|
||||
(define invert! (make-generic-method))
|
||||
|
||||
(define x (make-inverter))
|
||||
|
||||
(make-method! x invert! (lambda (x) (set-value! x (/ 1 (value x)))))
|
||||
|
||||
(value x) @result{} 1
|
||||
(set-value! x 33) @result{} undefined
|
||||
(invert! x) @result{} undefined
|
||||
(value x) @result{} 1/33
|
||||
|
||||
(unmake-method! x invert!) @result{} undefined
|
||||
|
||||
(invert! x) @error{} ERROR: Method not supported: x
|
||||
@end example
|
|
@ -1,97 +0,0 @@
|
|||
;;; "object.scm" Macroless Object System
|
||||
;;;From: whumeniu@datap.ca (Wade Humeniuk)
|
||||
|
||||
;;;Date: February 15, 1994
|
||||
|
||||
;; Object Construction:
|
||||
;; 0 1 2 3 4
|
||||
;; #(object-tag get-method make-method! unmake-method! get-all-methods)
|
||||
|
||||
(define object:tag "object")
|
||||
|
||||
;;; This might be better done using COMLIST:DELETE-IF.
|
||||
(define (object:removeq obj alist)
|
||||
(if (null? alist)
|
||||
alist
|
||||
(if (eq? (caar alist) obj)
|
||||
(cdr alist)
|
||||
(cons (car alist) (object:removeq obj (cdr alist))))))
|
||||
|
||||
(define (get-all-methods obj)
|
||||
(if (object? obj)
|
||||
((vector-ref obj 4))
|
||||
(slib:error "Cannot get methods on non-object: " obj)))
|
||||
|
||||
(define (object? obj)
|
||||
(and (vector? obj)
|
||||
(eq? object:tag (vector-ref obj 0))))
|
||||
|
||||
(define (make-method! obj generic-method method)
|
||||
(if (object? obj)
|
||||
(if (procedure? method)
|
||||
(begin
|
||||
((vector-ref obj 2) generic-method method)
|
||||
method)
|
||||
(slib:error "Method must be a procedure: " method))
|
||||
(slib:error "Cannot make method on non-object: " obj)))
|
||||
|
||||
(define (get-method obj generic-method)
|
||||
(if (object? obj)
|
||||
((vector-ref obj 1) generic-method)
|
||||
(slib:error "Cannot get method on non-object: " obj)))
|
||||
|
||||
(define (unmake-method! obj generic-method)
|
||||
(if (object? obj)
|
||||
((vector-ref obj 3) generic-method)
|
||||
(slib:error "Cannot unmake method on non-object: " obj)))
|
||||
|
||||
(define (make-predicate! obj generic-predicate)
|
||||
(if (object? obj)
|
||||
((vector-ref obj 2) generic-predicate (lambda (self) #t))
|
||||
(slib:error "Cannot make predicate on non-object: " obj)))
|
||||
|
||||
(define (make-generic-method . exception-procedure)
|
||||
(define generic-method
|
||||
(lambda (obj . operands)
|
||||
(if (object? obj)
|
||||
(let ((object-method ((vector-ref obj 1) generic-method)))
|
||||
(if object-method
|
||||
(apply object-method (cons obj operands))
|
||||
(slib:error "Method not supported: " obj)))
|
||||
(apply exception-procedure (cons obj operands)))))
|
||||
|
||||
(if (not (null? exception-procedure))
|
||||
(if (procedure? (car exception-procedure))
|
||||
(set! exception-procedure (car exception-procedure))
|
||||
(slib:error "Exception Handler Not Procedure:"))
|
||||
(set! exception-procedure
|
||||
(lambda (obj . params)
|
||||
(slib:error "Operation not supported: " obj))))
|
||||
generic-method)
|
||||
|
||||
(define (make-generic-predicate)
|
||||
(define generic-predicate
|
||||
(lambda (obj)
|
||||
(if (object? obj)
|
||||
(if ((vector-ref obj 1) generic-predicate)
|
||||
#t
|
||||
#f)
|
||||
#f)))
|
||||
generic-predicate)
|
||||
|
||||
(define (make-object . ancestors)
|
||||
(define method-list
|
||||
(apply append (map (lambda (obj) (get-all-methods obj)) ancestors)))
|
||||
(define (make-method! generic-method method)
|
||||
(set! method-list (cons (cons generic-method method) method-list))
|
||||
method)
|
||||
(define (unmake-method! generic-method)
|
||||
(set! method-list (object:removeq generic-method method-list))
|
||||
#t)
|
||||
(define (all-methods) method-list)
|
||||
(define (get-method generic-method)
|
||||
(let ((method-def (assq generic-method method-list)))
|
||||
(if method-def (cdr method-def) #f)))
|
||||
(vector object:tag get-method make-method! unmake-method! all-methods))
|
||||
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
;;; "paramlst.scm" passing parameters by name.
|
||||
; Copyright 1995, 1996, 1997, 2001 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; Format of arity-spec: (name predicate conversion)
|
||||
|
||||
(require 'common-list-functions)
|
||||
|
||||
(define arity->arity-spec
|
||||
(let ((table
|
||||
`((nary
|
||||
,(lambda (a) #t)
|
||||
,identity)
|
||||
(nary1
|
||||
,(lambda (a) (not (null? a)))
|
||||
,identity)
|
||||
(single
|
||||
,(lambda (a) (and (pair? a) (null? (cdr a))))
|
||||
,car)
|
||||
(optional
|
||||
,(lambda (a) (or (null? a) (and (pair? a) (null? (cdr a)))))
|
||||
,identity)
|
||||
(boolean
|
||||
,(lambda (a)
|
||||
(or (null? a)
|
||||
(and (pair? a) (null? (cdr a)) (boolean? (car a)))))
|
||||
,(lambda (a) (if (null? a) #f (car a)))))))
|
||||
(lambda (arity)
|
||||
(assq arity table))))
|
||||
|
||||
(define (fill-empty-parameters defaulters parameter-list)
|
||||
(map (lambda (defaulter parameter)
|
||||
(cond ((null? (cdr parameter))
|
||||
(cons (car parameter)
|
||||
(if defaulter (defaulter parameter-list) '())))
|
||||
(else parameter)))
|
||||
defaulters parameter-list))
|
||||
|
||||
(define (check-parameters checks parameter-list)
|
||||
(and (every (lambda (check parameter)
|
||||
(every
|
||||
(lambda (p)
|
||||
(let ((good? (not (and check (not (check p))))))
|
||||
(if (not good?) (slib:warn (car parameter) 'parameter? p))
|
||||
good?))
|
||||
(cdr parameter)))
|
||||
checks parameter-list)
|
||||
parameter-list))
|
||||
|
||||
(define (check-arities arity-specs parameter-list)
|
||||
(every (lambda (arity-spec param)
|
||||
(cond ((not arity-spec) (slib:warn 'missing 'arity arity-specs) #f)
|
||||
(((cadr arity-spec) (cdr param)) #t)
|
||||
((null? (cdr param)) (slib:warn param 'missing) #f)
|
||||
(else (slib:warn param 'not (car arity-spec)) #f)))
|
||||
arity-specs parameter-list))
|
||||
|
||||
(define (parameter-list->arglist positions arities parameter-list)
|
||||
(and (= (length arities) (length positions) (length parameter-list))
|
||||
(let ((arity-specs (map arity->arity-spec arities))
|
||||
(ans (make-vector (length positions) #f)))
|
||||
(and (check-arities arity-specs parameter-list)
|
||||
(for-each
|
||||
(lambda (pos arity-spec param)
|
||||
(vector-set! ans (+ -1 pos)
|
||||
((caddr arity-spec) (cdr param))))
|
||||
positions arity-specs parameter-list)
|
||||
(vector->list ans)))))
|
||||
|
||||
(define (make-parameter-list parameter-names)
|
||||
(map list parameter-names))
|
||||
|
||||
(define (parameter-list-ref parameter-list i)
|
||||
(let ((ans (assoc i parameter-list)))
|
||||
(and ans (cdr ans))))
|
||||
|
||||
(define (parameter-list-expand expanders parms)
|
||||
(do ((lens (map length parms) (map length parms))
|
||||
(olens '() lens))
|
||||
((equal? lens olens))
|
||||
(for-each (lambda (expander parm)
|
||||
(cond
|
||||
(expander
|
||||
(for-each
|
||||
(lambda (news)
|
||||
(cond ((adjoin-parameters! parms news))
|
||||
(else (slib:error
|
||||
"expanded feature unknown: " news))))
|
||||
(apply append
|
||||
(map (lambda (p)
|
||||
(cond ((expander p))
|
||||
((not '()) '())
|
||||
(else (slib:error
|
||||
"couldn't expand feature: " p))))
|
||||
(cdr parm)))))))
|
||||
expanders
|
||||
parms)))
|
||||
|
||||
(define (adjoin-parameters! parameter-list . parameters)
|
||||
(let ((apairs (map (lambda (param)
|
||||
(cond ((pair? param)
|
||||
(assoc (car param) parameter-list))
|
||||
(else (assoc param parameter-list))))
|
||||
parameters)))
|
||||
(and (every identity apairs) ;same as APPLY AND?
|
||||
(for-each
|
||||
(lambda (apair param)
|
||||
(cond ((pair? param)
|
||||
(for-each (lambda (o)
|
||||
(if (not (member o (cdr apair)))
|
||||
(set-cdr! apair (cons o (cdr apair)))))
|
||||
(cdr param)))
|
||||
(else (if (not (memv #t (cdr apair)))
|
||||
(set-cdr! apair (cons #t (cdr apair)))))))
|
||||
apairs parameters)
|
||||
parameter-list)))
|
||||
|
||||
(define (remove-parameter pname parameter-list)
|
||||
(define found? #f)
|
||||
(remove-if (lambda (elt)
|
||||
(cond ((not (and (pair? elt) (eqv? pname (car elt)))) #f)
|
||||
(found?
|
||||
(slib:error
|
||||
'remove-parameter 'multiple pname 'in parameter-list))
|
||||
(else (set! found? #t) #t)))
|
||||
parameter-list))
|
|
@ -1,47 +0,0 @@
|
|||
;"plottest.scm" test charplot.scm
|
||||
;Copyright (C) 1992 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'charplot)
|
||||
(require 'random)
|
||||
|
||||
(define strophoid
|
||||
(let ((l '()))
|
||||
(do ((x -1.0 (+ x 0.05)))
|
||||
((> x 4.0))
|
||||
(let* ((a (/ (- 2 x) (+ 2 x))))
|
||||
(if (>= a 0.0)
|
||||
(let* ((y (* x (sqrt a))))
|
||||
(set! l (cons (cons x y) l))
|
||||
(set! l (cons (cons x (- y)) l))))))
|
||||
l))
|
||||
|
||||
(plot! strophoid "x" "y") (newline)
|
||||
|
||||
(define unif
|
||||
(let* ((l 6)
|
||||
(v (make-vector l)))
|
||||
(do ((i (- l 1) (- i 1)))
|
||||
((negative? i))
|
||||
(vector-set! v i (cons i 0)))
|
||||
(do ((i 24 (- i 1))
|
||||
(r (random l) (random l)))
|
||||
((zero? i) (vector->list v))
|
||||
(set-cdr! (vector-ref v r) (+ 1 (cdr (vector-ref v r)))))))
|
||||
|
||||
(plot! unif "n" "occur")
|
|
@ -1,213 +0,0 @@
|
|||
;;; "pnm.scm" Read PNM image files.
|
||||
; Copyright 2000 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'scanf)
|
||||
(require 'printf)
|
||||
(require 'array)
|
||||
(require 'array-for-each)
|
||||
(require 'byte)
|
||||
(require 'line-i/o)
|
||||
|
||||
(define (pnm:read+integer port)
|
||||
(define uint #f)
|
||||
(do ((chr (peek-char port) (peek-char port)))
|
||||
((not (and (char? chr) (or (char-whitespace? chr) (eqv? #\# chr)))))
|
||||
(if (eqv? #\# chr)
|
||||
(read-line port)
|
||||
(read-char port)))
|
||||
(if (eof-object? (peek-char port))
|
||||
(peek-char port)
|
||||
(and (eqv? 1 (fscanf port " %u" uint)) uint)))
|
||||
|
||||
(define (pnm:type-dimensions port)
|
||||
(if (input-port? port)
|
||||
(let* ((c1 (read-char port))
|
||||
(c2 (read-char port)))
|
||||
(cond
|
||||
((and (eqv? #\P c1)
|
||||
(char? c2)
|
||||
(char-numeric? c2)
|
||||
(char-whitespace? (peek-char port)))
|
||||
(let* ((format (string->symbol (string #\p c2)))
|
||||
(width (pnm:read+integer port))
|
||||
(height (pnm:read+integer port))
|
||||
(ret
|
||||
(case format
|
||||
((p1) (list 'pbm width height 1))
|
||||
((p4) (list 'pbm-raw width height 1))
|
||||
((p2) (list 'pgm width height (pnm:read+integer port)))
|
||||
((p5) (list 'pgm-raw width height (pnm:read+integer port)))
|
||||
((p3) (list 'ppm width height (pnm:read+integer port)))
|
||||
((p6) (list 'ppm-raw width height (pnm:read+integer port)))
|
||||
(else #f))))
|
||||
(and (char-whitespace? (read-char port)) ret)))
|
||||
(else #f)))
|
||||
(call-with-input-file port pnm:type-dimensions)))
|
||||
|
||||
(define (pnm:read-binary! array port)
|
||||
(array-map! array (lambda () (read-byte port))))
|
||||
|
||||
(define (pnm:image-file->array path . array)
|
||||
(set! array (and (not (null? array)) (car array)))
|
||||
(call-with-input-file path
|
||||
(lambda (port)
|
||||
(apply (lambda (type width height max-pixel)
|
||||
(define (read-binary)
|
||||
(pnm:read-binary! array port)
|
||||
(if (eof-object? (peek-char port)) array
|
||||
(slib:error type 'not 'at 'file 'end)))
|
||||
(define (read-text)
|
||||
(array-map! array (lambda () (pnm:read+integer port)))
|
||||
(if (eof-object? (pnm:read+integer port)) array
|
||||
(slib:error type 'not 'at 'file 'end)))
|
||||
(define (read-pbm)
|
||||
(array-map! array (lambda () (eqv? 1 (pnm:read+integer port))))
|
||||
(if (eof-object? (pnm:read+integer port)) array
|
||||
(slib:error type 'not 'at 'file 'end)))
|
||||
(case type
|
||||
((pbm)
|
||||
(or array
|
||||
(set! array (make-array #t height width)))
|
||||
(read-pbm))
|
||||
((pgm)
|
||||
(or array
|
||||
(set! array (make-array max-pixel height width)))
|
||||
(read-text))
|
||||
((ppm)
|
||||
(or array
|
||||
(set! array (make-array max-pixel height width 3)))
|
||||
(read-text))
|
||||
((pbm-raw)
|
||||
(or array
|
||||
(set! array (make-array #t height (quotient width 8))))
|
||||
(read-binary))
|
||||
((pgm-raw)
|
||||
(or array
|
||||
(set! array (make-array max-pixel height width)))
|
||||
(read-binary))
|
||||
((ppm-raw)
|
||||
(or array
|
||||
(set! array (make-array max-pixel height width 3)))
|
||||
(read-binary))))
|
||||
(pnm:type-dimensions port)))))
|
||||
|
||||
(define (pnm:image-file->uniform-array path . array)
|
||||
(fluid-let ((make-array make-uniform-array)
|
||||
(pnm:read-binary!
|
||||
(lambda (ra port)
|
||||
(if (array? ra #t)
|
||||
(error 'pnm:image-file->array
|
||||
"pbm-raw support unimplemented")
|
||||
(let ((bytes (apply make-uniform-array #\a
|
||||
(array-dimensions ra))))
|
||||
(uniform-array-read! bytes port)
|
||||
(array-map! ra char->integer bytes))))))
|
||||
(apply pnm:image-file->array path array)))
|
||||
|
||||
;; ARRAY is required to be zero-based.
|
||||
(define (pnm:array-write type array maxval port)
|
||||
(define (write-header type height width maxval)
|
||||
(let ((magic
|
||||
(case type
|
||||
((pbm) "P1")
|
||||
((pgm) "P2")
|
||||
((ppm) "P3")
|
||||
((pbm-raw) "P4")
|
||||
((pgm-raw) "P5")
|
||||
((ppm-raw) "P6")
|
||||
(else (error 'pnm:array-write "bad type" type)))))
|
||||
(fprintf port "%s\n%d %d" magic width height)
|
||||
(if maxval (fprintf port "\n%d" maxval))))
|
||||
(define (write-pixels type array maxval)
|
||||
(let* ((shp (array-dimensions array))
|
||||
(height (car shp))
|
||||
(width (cadr shp)))
|
||||
(case type
|
||||
((pbm-raw)
|
||||
(newline port)
|
||||
(if (array? array #t)
|
||||
(uniform-array-write array port)
|
||||
(error 'pnm:array-write "expected bit-array" array)))
|
||||
((pgm-raw ppm-raw)
|
||||
(newline port)
|
||||
;;; (let ((bytes (apply make-uniform-array #\a shp)))
|
||||
;;; (array-map! bytes integer->char array)
|
||||
;;; (uniform-array-write bytes port))
|
||||
(uniform-array-write array port))
|
||||
((pbm)
|
||||
(do ((i 0 (+ i 1)))
|
||||
((>= i height))
|
||||
(do ((j 0 (+ j 1)))
|
||||
((>= j width))
|
||||
(display (if (zero? (remainder j 35)) #\newline #\space) port)
|
||||
(display (if (array-ref array i j) #\1 #\0) port)))
|
||||
(newline port))
|
||||
((pgm)
|
||||
(do ((i 0 (+ i 1)))
|
||||
((>= i height))
|
||||
(do ((j 0 (+ j 1)))
|
||||
((>= j width))
|
||||
(display (if (zero? (remainder j 17)) #\newline #\space) port)
|
||||
(display (array-ref array i j) port)))
|
||||
(newline port))
|
||||
((ppm)
|
||||
(do ((i 0 (+ i 1)))
|
||||
((>= i height))
|
||||
(do ((j 0 (+ j 1)))
|
||||
((>= j width))
|
||||
(display (if (zero? (remainder j 5)) #\newline " ") port)
|
||||
(display (array-ref array i j 0) port)
|
||||
(display #\space port)
|
||||
(display (array-ref array i j 1) port)
|
||||
(display #\space port)
|
||||
(display (array-ref array i j 2) port)))
|
||||
(newline port)))))
|
||||
|
||||
(if (output-port? port)
|
||||
(let ((rnk (array-rank array))
|
||||
(shp (array-dimensions array)))
|
||||
(case type
|
||||
((pbm pbm-raw)
|
||||
(or (and (eqv? 2 rnk)
|
||||
(integer? (car shp))
|
||||
(integer? (cadr shp)))
|
||||
(error 'pnm:array-write "bad shape" type array))
|
||||
(or (eqv? 1 maxval)
|
||||
(error 'pnm:array-write "maxval supplied not 1" type))
|
||||
(write-header type (car shp) (cadr shp) #f)
|
||||
(write-pixels type array 1))
|
||||
((pgm pgm-raw)
|
||||
(or (and (eqv? 2 rnk)
|
||||
(integer? (car shp))
|
||||
(integer? (cadr shp)))
|
||||
(error 'pnm:array-write "bad shape" type array))
|
||||
(write-header type (car shp) (cadr shp) maxval)
|
||||
(write-pixels type array maxval))
|
||||
((ppm ppm-raw)
|
||||
(or (and (eqv? 3 rnk)
|
||||
(integer? (car shp))
|
||||
(integer? (cadr shp))
|
||||
(eqv? 3 (caddr shp)))
|
||||
(error 'pnm:array-write "bad shape" type array))
|
||||
(write-header type (car shp) (cadr shp) maxval)
|
||||
(write-pixels type array maxval))
|
||||
(else (error 'pnm:array-write type 'unrecognized 'type))))
|
||||
(call-with-output-file port
|
||||
(lambda (port)
|
||||
(pnm:array-write type array maxval port)))))
|
|
@ -1,15 +0,0 @@
|
|||
;"pp.scm" Pretty-Print
|
||||
(require 'generic-write)
|
||||
|
||||
(define (pp:pretty-print obj . opt)
|
||||
(let ((port (if (pair? opt) (car opt) (current-output-port))))
|
||||
(generic-write obj #f (output-port-width port)
|
||||
(lambda (s) (display s port) #t))))
|
||||
|
||||
(define (pretty-print->string obj . width)
|
||||
(define result '())
|
||||
(generic-write obj #f (if (null? width) (output-port-width) (car width))
|
||||
(lambda (str) (set! result (cons str result)) #t))
|
||||
(reverse-string-append result))
|
||||
|
||||
(define pretty-print pp:pretty-print)
|
|
@ -1,70 +0,0 @@
|
|||
;;;; "ppfile.scm". Pretty print a Scheme file.
|
||||
;Copyright (C) 1993, 1994 Aubrey Jaffer
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'pretty-print)
|
||||
|
||||
(define (pprint-filter-file inport filter . optarg)
|
||||
((lambda (fun)
|
||||
(if (input-port? inport)
|
||||
(fun inport)
|
||||
(call-with-input-file inport fun)))
|
||||
(lambda (port)
|
||||
((lambda (fun)
|
||||
(let ((outport
|
||||
(if (null? optarg) (current-output-port) (car optarg))))
|
||||
(if (output-port? outport)
|
||||
(fun outport)
|
||||
(call-with-output-file outport fun))))
|
||||
(lambda (export)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* inport)
|
||||
(letrec ((lp (lambda (c)
|
||||
(cond ((eof-object? c))
|
||||
((char-whitespace? c)
|
||||
(display (read-char port) export)
|
||||
(lp (peek-char port)))
|
||||
((char=? #\; c)
|
||||
(cmt c))
|
||||
(else (sx)))))
|
||||
(cmt (lambda (c)
|
||||
(cond ((eof-object? c))
|
||||
((char=? #\newline c)
|
||||
(display (read-char port) export)
|
||||
(lp (peek-char port)))
|
||||
(else
|
||||
(display (read-char port) export)
|
||||
(cmt (peek-char port))))))
|
||||
(sx (lambda ()
|
||||
(let ((o (read port)))
|
||||
(cond ((eof-object? o))
|
||||
(else
|
||||
(pretty-print (filter o) export)
|
||||
;; pretty-print seems to have extra newline
|
||||
(let ((c (peek-char port)))
|
||||
(cond ((eqv? #\newline c)
|
||||
(read-char port)
|
||||
(set! c (peek-char port))))
|
||||
(lp c))))))))
|
||||
(lp (peek-char port)))
|
||||
(set! *load-pathname* old-load-pathname)))))))
|
||||
|
||||
(define (pprint-file ifile . optarg)
|
||||
(pprint-filter-file ifile
|
||||
(lambda (x) x)
|
||||
(if (null? optarg) (current-output-port) (car optarg))))
|
|
@ -1,448 +0,0 @@
|
|||
; "prec.scm", dynamically extensible parser/tokenizer -*-scheme-*-
|
||||
; Copyright 1989, 1990, 1991, 1992, 1993, 1995, 1997 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
; This file implements:
|
||||
; * a Pratt style parser.
|
||||
; * a tokenizer which congeals tokens according to assigned classes of
|
||||
; constituent characters.
|
||||
;
|
||||
; This module is a significant improvement because grammar can be
|
||||
; changed dynamically from rulesets which don't need compilation.
|
||||
; Theoretically, all possibilities of bad input are handled and return
|
||||
; as much structure as was parsed when the error occured; The symbol
|
||||
; `?' is substituted for missing input.
|
||||
|
||||
; References for the parser are:
|
||||
|
||||
; Pratt, V. R.
|
||||
; Top Down Operator Precendence.
|
||||
; SIGACT/SIGPLAN
|
||||
; Symposium on Principles of Programming Languages,
|
||||
; Boston, 1973, 41-51
|
||||
|
||||
; WORKING PAPER 121
|
||||
; CGOL - an Alternative External Representation For LISP users
|
||||
; Vaughan R. Pratt
|
||||
; MIT Artificial Intelligence Lab.
|
||||
; March 1976
|
||||
|
||||
; Mathlab Group,
|
||||
; MACSYMA Reference Manual, Version Ten,
|
||||
; Laboratory for Computer Science, MIT, 1983
|
||||
|
||||
(require 'fluid-let)
|
||||
(require 'string-search)
|
||||
(require 'string-port)
|
||||
(require 'delay)
|
||||
|
||||
(define *syn-defs* #f)
|
||||
(define *syn-rules* #f) ;Dynamically bound
|
||||
(define *prec:port* #f) ;Dynamically bound
|
||||
|
||||
;; keeps track of input column so we can generate useful error displays.
|
||||
(define tok:column 0)
|
||||
(define (tok:peek-char) (peek-char *prec:port*))
|
||||
(define (tok:read-char)
|
||||
(let ((c (read-char *prec:port*)))
|
||||
(if (or (eqv? c #\newline) (eof-object? c))
|
||||
(set! tok:column 0)
|
||||
(set! tok:column (+ 1 tok:column)))
|
||||
c))
|
||||
(define (tok:bump-column pos . ports)
|
||||
((lambda (thunk)
|
||||
(cond ((null? ports) (thunk))
|
||||
(else (fluid-let ((*prec:port* (car ports))) (thunk)))))
|
||||
(lambda ()
|
||||
(cond ((eqv? #\newline (tok:peek-char))
|
||||
(tok:read-char))) ;to do newline
|
||||
(set! tok:column (+ tok:column pos)))))
|
||||
(define (prec:warn . msgs)
|
||||
(do ((j (+ -1 tok:column) (+ -8 j)))
|
||||
((> 8 j)
|
||||
(do ((i j (+ -1 i)))
|
||||
((>= 0 i))
|
||||
(display #\ )))
|
||||
(display slib:tab))
|
||||
(display "^ ")
|
||||
(newline)
|
||||
(for-each (lambda (x) (write x) (display #\ )) msgs)
|
||||
(newline))
|
||||
|
||||
;; Structure of lexical records.
|
||||
(define tok:make-rec cons)
|
||||
(define tok:cc car)
|
||||
(define tok:sfp cdr)
|
||||
|
||||
(define (tok:lookup alist char)
|
||||
(if (eof-object? char)
|
||||
#f
|
||||
(let ((pair (assv char alist)))
|
||||
(and pair (cdr pair)))))
|
||||
|
||||
(define (tok:char-group group chars chars-proc)
|
||||
(map (lambda (token)
|
||||
;;; (let ((oldlexrec (tok:lookup *syn-defs* token)))
|
||||
;;; (cond ((or (not oldlexrec) (eqv? (tok:cc oldlexrec) group)))
|
||||
;;; (else (math:warn 'cc-of token 'redefined-to- group))))
|
||||
(cons token (tok:make-rec group chars-proc)))
|
||||
(cond ((string? chars) (string->list chars))
|
||||
((char? chars) (list chars))
|
||||
(else chars))))
|
||||
|
||||
(define (tokenize)
|
||||
(let* ((char (tok:read-char))
|
||||
(rec (tok:lookup *syn-rules* char))
|
||||
(proc (and rec (tok:cc rec)))
|
||||
(clist (list char)))
|
||||
(cond
|
||||
((not proc) char)
|
||||
((procedure? proc)
|
||||
(do ((cl clist (begin (set-cdr! cl (list (tok:read-char))) (cdr cl))))
|
||||
((proc (tok:peek-char))
|
||||
((or (tok:sfp rec) list->string) clist))))
|
||||
((eqv? 0 proc) (tokenize))
|
||||
(else
|
||||
(do ((cl clist (begin (set-cdr! cl (list (tok:read-char))) (cdr cl))))
|
||||
((not (let* ((prec (tok:lookup *syn-rules* (tok:peek-char)))
|
||||
(cclass (and prec (tok:cc prec))))
|
||||
(or (eqv? cclass proc)
|
||||
(eqv? cclass (+ -1 proc)))))
|
||||
((tok:sfp rec) clist)))))))
|
||||
|
||||
;;; PREC:NUD is the null denotation (function and arguments to call when no
|
||||
;;; unclaimed tokens).
|
||||
;;; PREC:LED is the left denotation (function and arguments to call when
|
||||
;;; unclaimed token is on left).
|
||||
;;; PREC:LBP is the left binding power of this LED. It is the first
|
||||
;;; argument position of PREC:LED
|
||||
|
||||
(define (prec:nudf alist self)
|
||||
(let ((pair (assoc (cons 'nud self) alist)))
|
||||
(and pair (cdr pair))))
|
||||
(define (prec:ledf alist self)
|
||||
(let ((pair (assoc (cons 'led self) alist)))
|
||||
(and pair (cdr pair))))
|
||||
(define (prec:lbp alist self)
|
||||
(let ((pair (assoc (cons 'led self) alist)))
|
||||
(and pair (cadr pair))))
|
||||
|
||||
(define (prec:call-or-list proc . args)
|
||||
(prec:apply-or-cons proc args))
|
||||
(define (prec:apply-or-cons proc args)
|
||||
(if (procedure? proc) (apply proc args) (cons (or proc '?) args)))
|
||||
|
||||
;;; PREC:SYMBOLFY and PREC:DE-SYMBOLFY are not exact inverses.
|
||||
(define (prec:symbolfy obj)
|
||||
(cond ((symbol? obj) obj)
|
||||
((string? obj) (string->symbol obj))
|
||||
((char? obj) (string->symbol (string obj)))
|
||||
(else obj)))
|
||||
|
||||
(define (prec:de-symbolfy obj)
|
||||
(cond ((symbol? obj) (symbol->string obj))
|
||||
(else obj)))
|
||||
|
||||
;;;Calls to set up tables.
|
||||
|
||||
(define (prec:define-grammar . synlsts)
|
||||
(set! *syn-defs* (append (apply append synlsts) *syn-defs*)))
|
||||
|
||||
(define (prec:make-led toks . args)
|
||||
(map (lambda (tok)
|
||||
(cons (cons 'led (prec:de-symbolfy tok))
|
||||
args))
|
||||
(if (pair? toks) toks (list toks))))
|
||||
(define (prec:make-nud toks . args)
|
||||
(map (lambda (tok)
|
||||
(cons (cons 'nud (prec:de-symbolfy tok))
|
||||
args))
|
||||
(if (pair? toks) toks (list toks))))
|
||||
|
||||
;;; Produce dynamically augmented grammars.
|
||||
(define (prec:process-binds binds rules)
|
||||
(if (and #f (not (null? binds)) (eq? #t (car binds)))
|
||||
(cdr binds)
|
||||
(append binds rules)))
|
||||
|
||||
;;(define (prec:replace-rules) some-sort-of-magic-cookie)
|
||||
|
||||
;;; Here are the procedures to define high-level grammar, along with
|
||||
;;; utility functions called during parsing. The utility functions
|
||||
;;; (prec:parse-*) could be incorportated into the defining commands,
|
||||
;;; but tracing these functions is useful for debugging.
|
||||
|
||||
(define (prec:delim tk)
|
||||
(prec:make-led tk 0 #f))
|
||||
|
||||
(define (prec:nofix tk sop . binds)
|
||||
(prec:make-nud tk prec:parse-nofix sop (apply append binds)))
|
||||
(define (prec:parse-nofix self sop binds)
|
||||
(set! *syn-rules* (prec:process-binds binds *syn-rules*))
|
||||
(prec:call-or-list (or sop (prec:symbolfy self))))
|
||||
|
||||
(define (prec:prefix tk sop bp . binds)
|
||||
(prec:make-nud tk prec:parse-prefix sop bp (apply append binds)))
|
||||
(define (prec:parse-prefix self sop bp binds)
|
||||
(fluid-let ((*syn-rules* (prec:process-binds binds *syn-rules*)))
|
||||
(prec:call-or-list (or sop (prec:symbolfy self)) (prec:parse1 bp))))
|
||||
|
||||
(define (prec:infix tk sop lbp bp . binds)
|
||||
(prec:make-led tk lbp prec:parse-infix sop bp (apply append binds)))
|
||||
(define (prec:parse-infix left self lbp sop bp binds)
|
||||
(fluid-let ((*syn-rules* (prec:process-binds binds *syn-rules*)))
|
||||
(prec:call-or-list (or sop (prec:symbolfy self)) left (prec:parse1 bp))))
|
||||
|
||||
(define (prec:nary tk sop bp)
|
||||
(prec:make-led tk bp prec:parse-nary sop bp))
|
||||
(define (prec:parse-nary left self lbp sop bp)
|
||||
(prec:apply-or-cons (or sop (prec:symbolfy self))
|
||||
(cons left (prec:parse-list self bp))))
|
||||
|
||||
(define (prec:postfix tk sop lbp . binds)
|
||||
(prec:make-led tk lbp prec:parse-postfix sop (apply append binds)))
|
||||
(define (prec:parse-postfix left self lbp sop binds)
|
||||
(set! *syn-rules* (prec:process-binds binds *syn-rules*))
|
||||
(prec:call-or-list (or sop (prec:symbolfy self)) left))
|
||||
|
||||
(define (prec:prestfix tk sop bp . binds)
|
||||
(prec:make-nud tk prec:parse-rest sop bp (apply append binds)))
|
||||
(define (prec:parse-rest self sop bp binds)
|
||||
(fluid-let ((*syn-rules* (prec:process-binds binds *syn-rules*)))
|
||||
(prec:apply-or-cons (or sop (prec:symbolfy self)) (prec:parse-list #f bp))))
|
||||
|
||||
(define (prec:commentfix tk stp match . binds)
|
||||
(append
|
||||
(prec:make-nud tk prec:parse-nudcomment stp match (apply append binds))
|
||||
(prec:make-led tk 220 prec:parse-ledcomment stp match (apply append binds))))
|
||||
(define (prec:parse-nudcomment self stp match binds)
|
||||
(fluid-let ((*syn-rules* (prec:process-binds binds *syn-rules*)))
|
||||
(tok:read-through-comment stp match)
|
||||
(prec:advance)
|
||||
(cond ((prec:delim? (force prec:token)) #f)
|
||||
(else (prec:parse1 prec:bp)))))
|
||||
(define (prec:parse-ledcomment left lbp self stp match binds)
|
||||
(fluid-let ((*syn-rules* (prec:process-binds binds *syn-rules*)))
|
||||
(tok:read-through-comment stp match)
|
||||
(prec:advance)
|
||||
left))
|
||||
(define (tok:read-through-comment stp match)
|
||||
(set! match (if (char? match)
|
||||
(string match)
|
||||
(prec:de-symbolfy match)))
|
||||
(cond ((procedure? stp)
|
||||
(let* ((len #f)
|
||||
(str (call-with-output-string
|
||||
(lambda (sp)
|
||||
(set! len (find-string-from-port?
|
||||
match *prec:port*
|
||||
(lambda (c) (display c sp) #f)))))))
|
||||
(stp (and len (substring str 0 (- len (string-length match)))))))
|
||||
(else (find-string-from-port? match *prec:port*))))
|
||||
|
||||
(define (prec:matchfix tk sop sep match . binds)
|
||||
(define sep-lbp 0)
|
||||
(prec:make-nud tk prec:parse-matchfix
|
||||
sop sep-lbp sep match
|
||||
(apply append (prec:delim match) binds)))
|
||||
(define (prec:parse-matchfix self sop sep-lbp sep match binds)
|
||||
(fluid-let ((*syn-rules* (prec:process-binds binds *syn-rules*)))
|
||||
(cond (sop (prec:apply-or-cons
|
||||
sop (prec:parse-delimited sep sep-lbp match)))
|
||||
((equal? (force prec:token) match)
|
||||
(prec:warn 'expression-missing)
|
||||
(prec:advance)
|
||||
'?)
|
||||
(else (let ((ans (prec:parse1 0))) ;just parenthesized expression
|
||||
(cond ((equal? (force prec:token) match)
|
||||
(prec:advance))
|
||||
((prec:delim? (force prec:token))
|
||||
(prec:warn 'mismatched-delimiter (force prec:token)
|
||||
'not match)
|
||||
(prec:advance))
|
||||
(else (prec:warn 'delimiter-expected--ignoring-rest
|
||||
(force prec:token) 'expected match
|
||||
'or-delimiter)
|
||||
(do () ((prec:delim? (force prec:token)))
|
||||
(prec:parse1 0))))
|
||||
ans)))))
|
||||
|
||||
(define (prec:inmatchfix tk sop sep match lbp . binds)
|
||||
(define sep-lbp 0)
|
||||
(prec:make-led tk lbp prec:parse-inmatchfix
|
||||
sop sep-lbp sep match
|
||||
(apply append (prec:delim match) binds)))
|
||||
(define (prec:parse-inmatchfix left self lbp sop sep-lbp sep match binds)
|
||||
(fluid-let ((*syn-rules* (prec:process-binds binds *syn-rules*)))
|
||||
(prec:apply-or-cons
|
||||
sop (cons left (prec:parse-delimited sep sep-lbp match)))))
|
||||
|
||||
;;;; Here is the code which actually parses.
|
||||
|
||||
(define prec:bp #f) ;dynamically bound
|
||||
(define prec:token #f)
|
||||
(define (prec:advance)
|
||||
(set! prec:token (delay (tokenize))))
|
||||
(define (prec:advance-return-last)
|
||||
(let ((last (and prec:token (force prec:token))))
|
||||
(prec:advance)
|
||||
last))
|
||||
|
||||
(define (prec:nudcall self)
|
||||
(let ((pob (prec:nudf *syn-rules* self)))
|
||||
(cond
|
||||
(pob (let ((proc (car pob)))
|
||||
(cond ((procedure? proc) (apply proc self (cdr pob)))
|
||||
(proc (cons proc (cdr pob)))
|
||||
(else '?))))
|
||||
((char? self) (prec:warn 'extra-separator)
|
||||
(prec:advance)
|
||||
(prec:nudcall (force prec:token)))
|
||||
((string? self) (string->symbol self))
|
||||
(else self))))
|
||||
|
||||
(define (prec:ledcall left self)
|
||||
(let* ((pob (prec:ledf *syn-rules* self)))
|
||||
(apply (cadr pob) left self (cdr pob))))
|
||||
|
||||
;;; PREC:PARSE1 is the heart.
|
||||
(define (prec:parse1 bp)
|
||||
(fluid-let ((prec:bp bp))
|
||||
(do ((left (prec:nudcall (prec:advance-return-last))
|
||||
(prec:ledcall left (prec:advance-return-last))))
|
||||
((or (>= bp 200) ;to avoid unneccesary lookahead
|
||||
(>= bp (or (prec:lbp *syn-rules* (force prec:token)) 0))
|
||||
(not left))
|
||||
left))))
|
||||
|
||||
(define (prec:delim? token)
|
||||
(or (eof-object? token) (<= (or (prec:lbp *syn-rules* token) 220) 0)))
|
||||
|
||||
(define (prec:parse-list sep bp)
|
||||
(cond ((prec:delim? (force prec:token))
|
||||
(prec:warn 'expression-missing)
|
||||
'(?))
|
||||
(else
|
||||
(let ((f (prec:parse1 bp)))
|
||||
(cons f (cond ((equal? (force prec:token) sep)
|
||||
(prec:advance)
|
||||
(cond ((equal? (force prec:token) sep)
|
||||
(prec:warn 'expression-missing)
|
||||
(prec:advance)
|
||||
(cons '? (prec:parse-list sep bp)))
|
||||
((prec:delim? (force prec:token))
|
||||
(prec:warn 'expression-missing)
|
||||
'(?))
|
||||
(else (prec:parse-list sep bp))))
|
||||
((prec:delim? (force prec:token)) '())
|
||||
((not sep) (prec:parse-list sep bp))
|
||||
((prec:delim? sep) (prec:warn 'separator-missing)
|
||||
(prec:parse-list sep bp))
|
||||
(else '())))))))
|
||||
|
||||
(define (prec:parse-delimited sep bp delim)
|
||||
(cond ((equal? (force prec:token) sep)
|
||||
(prec:warn 'expression-missing)
|
||||
(prec:advance)
|
||||
(cons '? (prec:parse-delimited sep delim)))
|
||||
((prec:delim? (force prec:token))
|
||||
(if (not (equal? (force prec:token) delim))
|
||||
(prec:warn 'mismatched-delimiter (force prec:token)
|
||||
'expected delim))
|
||||
(if (not sep) (prec:warn 'expression-missing))
|
||||
(prec:advance)
|
||||
(if sep '() '(?)))
|
||||
(else (let ((ans (prec:parse-list sep bp)))
|
||||
(cond ((equal? (force prec:token) delim))
|
||||
((prec:delim? (force prec:token))
|
||||
(prec:warn 'mismatched-delimiter (force prec:token)
|
||||
'expecting delim))
|
||||
(else (prec:warn 'delimiter-expected--ignoring-rest
|
||||
(force prec:token) '...)
|
||||
(do () ((prec:delim? (force prec:token)))
|
||||
(prec:parse1 bp))))
|
||||
(prec:advance)
|
||||
ans))))
|
||||
|
||||
(define (prec:parse grammar delim . port)
|
||||
(set! delim (prec:de-symbolfy delim))
|
||||
(fluid-let ((*syn-rules* (append (prec:delim delim) grammar))
|
||||
(*prec:port* (if (null? port) (current-input-port) (car port))))
|
||||
(prec:advance) ; setup prec:token with first token
|
||||
(cond ((eof-object? (force prec:token)) (force prec:token))
|
||||
((equal? (force prec:token) delim) #f)
|
||||
(else
|
||||
(let ((ans (prec:parse1 0)))
|
||||
(cond ((eof-object? (force prec:token)))
|
||||
((equal? (force prec:token) delim))
|
||||
(else (prec:warn 'delimiter-expected--ignoring-rest
|
||||
(force prec:token) 'not delim)
|
||||
(do () ((or (equal? (force prec:token) delim)
|
||||
(eof-object? (force prec:token))))
|
||||
(prec:advance))))
|
||||
ans)))))
|
||||
|
||||
(define tok:decimal-digits "0123456789")
|
||||
(define tok:upper-case "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
(define tok:lower-case "abcdefghijklmnopqrstuvwxyz")
|
||||
(define tok:whitespaces
|
||||
(do ((i (+ -1 (min 256 char-code-limit)) (+ -1 i))
|
||||
(ws "" (if (char-whitespace? (integer->char i))
|
||||
(string-append ws (string (integer->char i)))
|
||||
ws)))
|
||||
((negative? i) ws)))
|
||||
|
||||
;;;;The parse tables.
|
||||
;;; Definitions accumulate in top-level variable *SYN-DEFS*.
|
||||
(set! *syn-defs* '()) ;Make sure *SYN-DEFS* is empty.
|
||||
|
||||
;;; Ignore Whitespace characters.
|
||||
(prec:define-grammar (tok:char-group 0 tok:whitespaces #f))
|
||||
|
||||
;;; On MS-DOS systems, <ctrl>-Z (26) needs to be ignored in order to
|
||||
;;; avoid problems at end of files.
|
||||
(case (software-type)
|
||||
((MSDOS)
|
||||
(if (not (char-whitespace? (integer->char 26)))
|
||||
(prec:define-grammar (tok:char-group 0 (integer->char 26) #f))
|
||||
)))
|
||||
|
||||
;;; Save these convenient definitions.
|
||||
(define *syn-ignore-whitespace* *syn-defs*)
|
||||
(set! *syn-defs* '())
|
||||
|
||||
(define (prec:trace)
|
||||
(require 'trace)
|
||||
(trace prec:parse prec:parse1
|
||||
prec:parse-delimited prec:parse-list
|
||||
prec:call-or-list prec:apply-or-cons
|
||||
;;tokenize prec:advance-return-last prec:advance
|
||||
prec:nudcall prec:ledcall
|
||||
prec:parse-nudcomment prec:parse-ledcomment
|
||||
prec:parse-delimited prec:parse-list
|
||||
prec:parse-nary prec:parse-rest
|
||||
prec:parse-matchfix prec:parse-inmatchfix
|
||||
prec:parse-prefix prec:parse-infix prec:parse-postfix
|
||||
;;prec:delim?
|
||||
;;prec:ledf prec:nudf prec:lbp
|
||||
)
|
||||
(set! *qp-width* 333))
|
||||
|
||||
;;(begin (trace-all "prec.scm") (set! *qp-width* 333))
|
||||
;;(pretty-print (grammar-read-tab (get-grammar 'standard)))
|
||||
;;(prec:trace)
|
|
@ -1,584 +0,0 @@
|
|||
;;;; "printf.scm" Implementation of standard C functions for Scheme
|
||||
;;; Copyright (C) 1991-1993, 1996 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'string-case)
|
||||
|
||||
;; Parse the output of NUMBER->STRING.
|
||||
;; Returns a list: (sign-character digit-string exponent-integer)
|
||||
;; SIGN-CHAR will be either #\+ or #\-, DIGIT-STRING will always begin
|
||||
;; with a "0", after which a decimal point should be understood.
|
||||
;; If STR denotes a non-real number, 3 additional elements for the
|
||||
;; complex part are appended.
|
||||
(define (stdio:parse-float str)
|
||||
(let ((n (string-length str))
|
||||
(iend 0))
|
||||
(letrec ((prefix
|
||||
(lambda (i rest)
|
||||
(if (and (< i (- n 1))
|
||||
(char=? #\# (string-ref str i)))
|
||||
(case (string-ref str (+ i 1))
|
||||
((#\d #\i #\e) (prefix (+ i 2) rest))
|
||||
((#\.) (rest i))
|
||||
(else (parse-error)))
|
||||
(rest i))))
|
||||
(sign
|
||||
(lambda (i rest)
|
||||
(if (< i n)
|
||||
(let ((c (string-ref str i)))
|
||||
(case c
|
||||
((#\- #\+) (cons c (rest (+ i 1))))
|
||||
(else (cons #\+ (rest i))))))))
|
||||
(digits
|
||||
(lambda (i rest)
|
||||
(do ((j i (+ j 1)))
|
||||
((or (>= j n)
|
||||
(not (or (char-numeric? (string-ref str j))
|
||||
(char=? #\# (string-ref str j)))))
|
||||
(cons
|
||||
(if (= i j) "0" (substring str i j))
|
||||
(rest j))))))
|
||||
(point
|
||||
(lambda (i rest)
|
||||
(if (and (< i n)
|
||||
(char=? #\. (string-ref str i)))
|
||||
(rest (+ i 1))
|
||||
(rest i))))
|
||||
(exp
|
||||
(lambda (i)
|
||||
(if (< i n)
|
||||
(case (string-ref str i)
|
||||
((#\e #\s #\f #\d #\l #\E #\S #\F #\D #\L)
|
||||
(let ((s (sign (+ i 1) (lambda (i) (digits i end!)))))
|
||||
(list
|
||||
(if (char=? #\- (car s))
|
||||
(- (string->number (cadr s)))
|
||||
(string->number (cadr s))))))
|
||||
(else (end! i)
|
||||
'(0)))
|
||||
(begin (end! i)
|
||||
'(0)))))
|
||||
(end!
|
||||
(lambda (i)
|
||||
(set! iend i)
|
||||
'()))
|
||||
(real
|
||||
(lambda (i)
|
||||
(let ((parsed
|
||||
(prefix
|
||||
i
|
||||
(lambda (i)
|
||||
(sign
|
||||
i
|
||||
(lambda (i)
|
||||
(digits
|
||||
i
|
||||
(lambda (i)
|
||||
(point
|
||||
i
|
||||
(lambda (i)
|
||||
(digits i exp)))))))))))
|
||||
(and
|
||||
parsed
|
||||
(apply
|
||||
(lambda (sgn idigs fdigs exp)
|
||||
(let* ((digs (string-append "0" idigs fdigs))
|
||||
(n (string-length digs)))
|
||||
(let loop ((i 1)
|
||||
(exp (+ exp (string-length idigs))))
|
||||
(if (< i n)
|
||||
(if (char=? #\0 (string-ref digs i))
|
||||
(loop (+ i 1) (- exp 1))
|
||||
(list sgn (substring digs (- i 1) n) exp))
|
||||
;;Zero
|
||||
(list sgn "0" 1)))))
|
||||
parsed)))))
|
||||
(parse-error
|
||||
(lambda () #f)))
|
||||
(let ((realpart (real 0)))
|
||||
(cond ((= iend n) realpart)
|
||||
((memv (string-ref str iend) '(#\+ #\-))
|
||||
(let ((complexpart (real iend)))
|
||||
(and (= iend (- n 1))
|
||||
(char-ci=? #\i (string-ref str iend))
|
||||
(append realpart complexpart))))
|
||||
((eqv? (string-ref str iend) #\@)
|
||||
;; Polar form: No point in parsing the angle ourselves,
|
||||
;; since some transcendental approximation is unavoidable.
|
||||
(let ((num (string->number str)))
|
||||
(and num
|
||||
(let ((realpart
|
||||
(stdio:parse-float
|
||||
(number->string (real-part num))))
|
||||
(imagpart
|
||||
(if (real? num)
|
||||
'()
|
||||
(stdio:parse-float
|
||||
(number->string (imag-part num))))))
|
||||
(and realpart imagpart
|
||||
(append realpart imagpart))))))
|
||||
(else #f))))))
|
||||
|
||||
;; STR is a digit string representing a floating point mantissa, STR must
|
||||
;; begin with "0", after which a decimal point is understood.
|
||||
;; The output is a digit string rounded to NDIGS digits after the decimal
|
||||
;; point implied between chars 0 and 1.
|
||||
;; If STRIP-0S is not #F then trailing zeros will be stripped from the result.
|
||||
;; In this case, STRIP-0S should be the minimum number of digits required
|
||||
;; after the implied decimal point.
|
||||
(define (stdio:round-string str ndigs strip-0s)
|
||||
(let* ((n (- (string-length str) 1))
|
||||
(res
|
||||
(cond ((< ndigs 0) "")
|
||||
((= n ndigs) str)
|
||||
((< n ndigs)
|
||||
(let ((padlen (max 0 (- (or strip-0s ndigs) n))))
|
||||
(if (zero? padlen)
|
||||
str
|
||||
(string-append str
|
||||
(make-string padlen
|
||||
(if (char-numeric?
|
||||
(string-ref str n))
|
||||
#\0 #\#))))))
|
||||
(else
|
||||
(let ((res (substring str 0 (+ ndigs 1)))
|
||||
(dig (lambda (i)
|
||||
(let ((c (string-ref str i)))
|
||||
(if (char-numeric? c)
|
||||
(string->number (string c))
|
||||
0)))))
|
||||
(let ((ldig (dig (+ 1 ndigs))))
|
||||
(if (or (> ldig 5)
|
||||
(and (= ldig 5)
|
||||
(let loop ((i (+ 2 ndigs)))
|
||||
(if (> i n) (odd? (dig ndigs))
|
||||
(if (zero? (dig i))
|
||||
(loop (+ i 1))
|
||||
#t)))))
|
||||
(let inc! ((i ndigs))
|
||||
(let ((d (dig i)))
|
||||
(if (< d 9)
|
||||
(string-set! res i
|
||||
(string-ref
|
||||
(number->string (+ d 1)) 0))
|
||||
(begin
|
||||
(string-set! res i #\0)
|
||||
(inc! (- i 1))))))))
|
||||
res)))))
|
||||
(if strip-0s
|
||||
(let loop ((i (- (string-length res) 1)))
|
||||
(if (or (<= i strip-0s)
|
||||
(not (char=? #\0 (string-ref res i))))
|
||||
(substring res 0 (+ i 1))
|
||||
(loop (- i 1))))
|
||||
res)))
|
||||
|
||||
(define (stdio:iprintf out format-string . args)
|
||||
(cond
|
||||
((not (equal? "" format-string))
|
||||
(let ((pos -1)
|
||||
(fl (string-length format-string))
|
||||
(fc (string-ref format-string 0)))
|
||||
|
||||
(define (advance)
|
||||
(set! pos (+ 1 pos))
|
||||
(cond ((>= pos fl) (set! fc #f))
|
||||
(else (set! fc (string-ref format-string pos)))))
|
||||
(define (must-advance)
|
||||
(set! pos (+ 1 pos))
|
||||
(cond ((>= pos fl) (incomplete))
|
||||
(else (set! fc (string-ref format-string pos)))))
|
||||
(define (end-of-format?)
|
||||
(>= pos fl))
|
||||
(define (incomplete)
|
||||
(slib:error 'printf "conversion specification incomplete"
|
||||
format-string))
|
||||
(define (wna)
|
||||
(slib:error 'printf "wrong number of arguments"
|
||||
(length args)
|
||||
format-string))
|
||||
|
||||
(let loop ((args args))
|
||||
(advance)
|
||||
(cond
|
||||
((end-of-format?)
|
||||
;;(or (null? args) (wna)) ;Extra arguments are *not* a bug.
|
||||
)
|
||||
((eqv? #\\ fc);;Emulating C strings may not be a good idea.
|
||||
(must-advance)
|
||||
(and (case fc
|
||||
((#\n #\N) (out #\newline))
|
||||
((#\t #\T) (out slib:tab))
|
||||
;;((#\r #\R) (out #\return))
|
||||
((#\f #\F) (out slib:form-feed))
|
||||
((#\newline) #t)
|
||||
(else (out fc)))
|
||||
(loop args)))
|
||||
((eqv? #\% fc)
|
||||
(must-advance)
|
||||
(let ((left-adjust #f) ;-
|
||||
(signed #f) ;+
|
||||
(blank #f)
|
||||
(alternate-form #f) ;#
|
||||
(leading-0s #f) ;0
|
||||
(width 0)
|
||||
(precision -1)
|
||||
(type-modifier #f)
|
||||
(read-format-number
|
||||
(lambda ()
|
||||
(cond
|
||||
((eqv? #\* fc) ; GNU extension
|
||||
(must-advance)
|
||||
(let ((ans (car args)))
|
||||
(set! args (cdr args))
|
||||
ans))
|
||||
(else
|
||||
(do ((c fc fc)
|
||||
(accum 0 (+ (* accum 10)
|
||||
(string->number (string c)))))
|
||||
((not (char-numeric? fc)) accum)
|
||||
(must-advance)))))))
|
||||
(define (pad pre . strs)
|
||||
(let loop ((len (string-length pre))
|
||||
(ss strs))
|
||||
(cond ((>= len width) (apply string-append pre strs))
|
||||
((null? ss)
|
||||
(cond (left-adjust
|
||||
(apply string-append
|
||||
pre
|
||||
(append strs
|
||||
(list (make-string
|
||||
(- width len) #\space)))))
|
||||
(leading-0s
|
||||
(apply string-append
|
||||
pre
|
||||
(make-string (- width len) #\0)
|
||||
strs))
|
||||
(else
|
||||
(apply string-append
|
||||
(make-string (- width len) #\space)
|
||||
pre strs))))
|
||||
(else
|
||||
(loop (+ len (string-length (car ss))) (cdr ss))))))
|
||||
(define integer-convert
|
||||
(lambda (s radix)
|
||||
(cond ((not (negative? precision))
|
||||
(set! leading-0s #f)
|
||||
(if (and (zero? precision)
|
||||
(eqv? 0 s))
|
||||
(set! s ""))))
|
||||
(set! s (cond ((symbol? s) (symbol->string s))
|
||||
((number? s) (number->string s radix))
|
||||
((or (not s) (null? s)) "0")
|
||||
((string? s) s)
|
||||
(else "1")))
|
||||
(let ((pre (cond ((equal? "" s) "")
|
||||
((eqv? #\- (string-ref s 0))
|
||||
(set! s (substring s 1 (string-length s)))
|
||||
"-")
|
||||
(signed "+")
|
||||
(blank " ")
|
||||
(alternate-form
|
||||
(case radix
|
||||
((8) "0")
|
||||
((16) "0x")
|
||||
(else "")))
|
||||
(else ""))))
|
||||
(pad pre
|
||||
(if (< (string-length s) precision)
|
||||
(make-string
|
||||
(- precision (string-length s)) #\0)
|
||||
"")
|
||||
s))))
|
||||
(define (float-convert num fc)
|
||||
(define (f digs exp strip-0s)
|
||||
(let ((digs (stdio:round-string
|
||||
digs (+ exp precision) (and strip-0s exp))))
|
||||
(cond ((>= exp 0)
|
||||
(let* ((i0 (cond ((zero? exp) 0)
|
||||
((char=? #\0 (string-ref digs 0)) 1)
|
||||
(else 0)))
|
||||
(i1 (max 1 (+ 1 exp)))
|
||||
(idigs (substring digs i0 i1))
|
||||
(fdigs (substring digs i1
|
||||
(string-length digs))))
|
||||
(cons idigs
|
||||
(if (and (string=? fdigs "")
|
||||
(not alternate-form))
|
||||
'()
|
||||
(list "." fdigs)))))
|
||||
((zero? precision)
|
||||
(list (if alternate-form "0." "0")))
|
||||
((and strip-0s (string=? digs "") (list "0")))
|
||||
(else
|
||||
(list "0."
|
||||
(make-string (min precision (- -1 exp)) #\0)
|
||||
digs)))))
|
||||
(define (e digs exp strip-0s)
|
||||
(let* ((digs (stdio:round-string
|
||||
digs (+ 1 precision) (and strip-0s 0)))
|
||||
(istrt (if (char=? #\0 (string-ref digs 0)) 1 0))
|
||||
(fdigs (substring
|
||||
digs (+ 1 istrt) (string-length digs)))
|
||||
(exp (if (zero? istrt) exp (- exp 1))))
|
||||
(list
|
||||
(substring digs istrt (+ 1 istrt))
|
||||
(if (and (string=? fdigs "") (not alternate-form))
|
||||
"" ".")
|
||||
fdigs
|
||||
(if (char-upper-case? fc) "E" "e")
|
||||
(if (negative? exp) "-" "+")
|
||||
(if (< -10 exp 10) "0" "")
|
||||
(number->string (abs exp)))))
|
||||
(define (g digs exp)
|
||||
(let ((strip-0s (not alternate-form)))
|
||||
(set! alternate-form #f)
|
||||
(cond ((<= (- 1 precision) exp precision)
|
||||
(set! precision (- precision exp))
|
||||
(f digs exp strip-0s))
|
||||
(else
|
||||
(set! precision (- precision 1))
|
||||
(e digs exp strip-0s)))))
|
||||
(define (k digs exp sep)
|
||||
(let* ((units '#("y" "z" "a" "f" "p" "n" "u" "m" ""
|
||||
"k" "M" "G" "T" "P" "E" "Z" "Y"))
|
||||
(base 8) ;index of ""
|
||||
(uind (let ((i (if (negative? exp)
|
||||
(quotient (- exp 3) 3)
|
||||
(quotient (- exp 1) 3))))
|
||||
(and
|
||||
(< -1 (+ i base) (vector-length units))
|
||||
i))))
|
||||
(cond (uind
|
||||
(set! exp (- exp (* 3 uind)))
|
||||
(set! precision (max 0 (- precision exp)))
|
||||
(append
|
||||
(f digs exp #f)
|
||||
(list sep
|
||||
(vector-ref units (+ uind base)))))
|
||||
(else
|
||||
(g digs exp)))))
|
||||
|
||||
(cond ((negative? precision)
|
||||
(set! precision 6))
|
||||
((and (zero? precision)
|
||||
(char-ci=? fc #\g))
|
||||
(set! precision 1)))
|
||||
(let* ((str
|
||||
(cond ((number? num)
|
||||
(number->string (exact->inexact num)))
|
||||
((string? num) num)
|
||||
((symbol? num) (symbol->string num))
|
||||
(else "???")))
|
||||
(parsed (stdio:parse-float str)))
|
||||
(letrec ((format-real
|
||||
(lambda (signed? sgn digs exp . rest)
|
||||
(if (null? rest)
|
||||
(cons
|
||||
(if (char=? #\- sgn) "-"
|
||||
(if signed? "+" (if blank " " "")))
|
||||
(case fc
|
||||
((#\e #\E) (e digs exp #f))
|
||||
((#\f #\F) (f digs exp #f))
|
||||
((#\g #\G) (g digs exp))
|
||||
((#\k) (k digs exp ""))
|
||||
((#\K) (k digs exp " "))))
|
||||
(append (format-real signed? sgn digs exp)
|
||||
(apply format-real #t rest)
|
||||
'("i"))))))
|
||||
(if parsed
|
||||
(apply pad (apply format-real signed parsed))
|
||||
(pad "???")))))
|
||||
(do ()
|
||||
((case fc
|
||||
((#\-) (set! left-adjust #t) #f)
|
||||
((#\+) (set! signed #t) #f)
|
||||
((#\ ) (set! blank #t) #f)
|
||||
((#\#) (set! alternate-form #t) #f)
|
||||
((#\0) (set! leading-0s #t) #f)
|
||||
(else #t)))
|
||||
(must-advance))
|
||||
(cond (left-adjust (set! leading-0s #f)))
|
||||
(cond (signed (set! blank #f)))
|
||||
|
||||
(set! width (read-format-number))
|
||||
(cond ((negative? width)
|
||||
(set! left-adjust #t)
|
||||
(set! width (- width))))
|
||||
(cond ((eqv? #\. fc)
|
||||
(must-advance)
|
||||
(set! precision (read-format-number))))
|
||||
(case fc ;Ignore these specifiers
|
||||
((#\l #\L #\h)
|
||||
(set! type-modifier fc)
|
||||
(must-advance)))
|
||||
|
||||
;;At this point fc completely determines the format to use.
|
||||
(if (null? args)
|
||||
(if (memv (char-downcase fc)
|
||||
'(#\c #\s #\a #\d #\i #\u #\o #\x #\b
|
||||
#\f #\e #\g #\k))
|
||||
(wna)))
|
||||
|
||||
(case fc
|
||||
;; only - is allowed between % and c
|
||||
((#\c #\C) ; C is enhancement
|
||||
(and (out (string (car args))) (loop (cdr args))))
|
||||
|
||||
;; only - flag, no type-modifiers
|
||||
((#\s #\S) ; S is enhancement
|
||||
(let ((s (cond
|
||||
((symbol? (car args)) (symbol->string (car args)))
|
||||
((not (car args)) "(NULL)")
|
||||
(else (car args)))))
|
||||
(cond ((not (or (negative? precision)
|
||||
(>= precision (string-length s))))
|
||||
(set! s (substring s 0 precision))))
|
||||
(and (out (cond
|
||||
((<= width (string-length s)) s)
|
||||
(left-adjust
|
||||
(string-append
|
||||
s (make-string (- width (string-length s)) #\ )))
|
||||
(else
|
||||
(string-append
|
||||
(make-string (- width (string-length s))
|
||||
(if leading-0s #\0 #\ )) s))))
|
||||
(loop (cdr args)))))
|
||||
|
||||
;; SLIB extension
|
||||
((#\a #\A) ;#\a #\A are pretty-print
|
||||
(require 'generic-write)
|
||||
(let ((os "") (pr precision))
|
||||
(generic-write
|
||||
(car args) (not alternate-form) #f
|
||||
(cond ((and left-adjust (negative? pr))
|
||||
(set! pr 0)
|
||||
(lambda (s)
|
||||
(set! pr (+ pr (string-length s)))
|
||||
(out s)))
|
||||
(left-adjust
|
||||
(lambda (s)
|
||||
(define sl (- pr (string-length s)))
|
||||
(set! pr (cond ((negative? sl)
|
||||
(out (substring s 0 pr)) 0)
|
||||
(else (out s) sl)))
|
||||
(positive? sl)))
|
||||
((negative? pr)
|
||||
(set! pr width)
|
||||
(lambda (s)
|
||||
(set! pr (- pr (string-length s)))
|
||||
(cond ((not os) (out s))
|
||||
((negative? pr)
|
||||
(out os)
|
||||
(set! os #f)
|
||||
(out s))
|
||||
(else (set! os (string-append os s))))
|
||||
#t))
|
||||
(else
|
||||
(lambda (s)
|
||||
(define sl (- pr (string-length s)))
|
||||
(cond ((negative? sl)
|
||||
(set! os (string-append
|
||||
os (substring s 0 pr))))
|
||||
(else (set! os (string-append os s))))
|
||||
(set! pr sl)
|
||||
(positive? sl)))))
|
||||
(cond ((and left-adjust (negative? precision))
|
||||
(cond
|
||||
((> width pr) (out (make-string (- width pr) #\ )))))
|
||||
(left-adjust
|
||||
(cond
|
||||
((> width (- precision pr))
|
||||
(out (make-string (- width (- precision pr)) #\ )))))
|
||||
((not os))
|
||||
((<= width (string-length os)) (out os))
|
||||
(else (and (out (make-string
|
||||
(- width (string-length os)) #\ ))
|
||||
(out os)))))
|
||||
(loop (cdr args)))
|
||||
((#\d #\D #\i #\I #\u #\U)
|
||||
(and (out (integer-convert (car args) 10)) (loop (cdr args))))
|
||||
((#\o #\O)
|
||||
(and (out (integer-convert (car args) 8)) (loop (cdr args))))
|
||||
((#\x #\X)
|
||||
(and (out ((if (char-upper-case? fc)
|
||||
string-upcase string-downcase)
|
||||
(integer-convert (car args) 16)))
|
||||
(loop (cdr args))))
|
||||
((#\b #\B)
|
||||
(and (out (integer-convert (car args) 2)) (loop (cdr args))))
|
||||
((#\%) (and (out #\%) (loop args)))
|
||||
((#\f #\F #\e #\E #\g #\G #\k #\K)
|
||||
(and (out (float-convert (car args) fc)) (loop (cdr args))))
|
||||
(else
|
||||
(cond ((end-of-format?) (incomplete))
|
||||
(else (and (out #\%) (out fc) (out #\?) (loop args))))))))
|
||||
(else (and (out fc) (loop args)))))))))
|
||||
|
||||
(define (stdio:fprintf port format . args)
|
||||
(let ((cnt 0))
|
||||
(apply stdio:iprintf
|
||||
(lambda (x)
|
||||
(cond ((string? x)
|
||||
(set! cnt (+ (string-length x) cnt)) (display x port) #t)
|
||||
(else (set! cnt (+ 1 cnt)) (display x port) #t)))
|
||||
format args)
|
||||
cnt))
|
||||
|
||||
(define (stdio:printf format . args)
|
||||
(apply stdio:fprintf (current-output-port) format args))
|
||||
|
||||
(define (stdio:sprintf str format . args)
|
||||
(let* ((cnt 0)
|
||||
(s (cond ((string? str) str)
|
||||
((number? str) (make-string str))
|
||||
((not str) (make-string 100))
|
||||
(else (slib:error 'sprintf "first argument not understood"
|
||||
str))))
|
||||
(end (string-length s)))
|
||||
(apply stdio:iprintf
|
||||
(lambda (x)
|
||||
(cond ((string? x)
|
||||
(if (or str (>= (- end cnt) (string-length x)))
|
||||
(do ((lend (min (string-length x) (- end cnt)))
|
||||
(i 0 (+ i 1)))
|
||||
((>= i lend))
|
||||
(string-set! s cnt (string-ref x i))
|
||||
(set! cnt (+ cnt 1)))
|
||||
(let ()
|
||||
(set! s (string-append (substring s 0 cnt) x))
|
||||
(set! cnt (string-length s))
|
||||
(set! end cnt))))
|
||||
((and str (>= cnt end)))
|
||||
(else (cond ((and (not str) (>= cnt end))
|
||||
(set! s (string-append s (make-string 100)))
|
||||
(set! end (string-length s))))
|
||||
(string-set! s cnt (if (char? x) x #\?))
|
||||
(set! cnt (+ cnt 1))))
|
||||
(not (and str (>= cnt end))))
|
||||
format
|
||||
args)
|
||||
(cond ((string? str) cnt)
|
||||
((eqv? end cnt) s)
|
||||
(else (substring s 0 cnt)))))
|
||||
|
||||
(define printf stdio:printf)
|
||||
(define fprintf stdio:fprintf)
|
||||
(define sprintf stdio:sprintf)
|
||||
|
||||
;;(do ((i 0 (+ 1 i))) ((> i 50)) (printf "%s\n" (sprintf i "%#-13a:%#13a:%-13.8a:" "123456789" "123456789" "123456789")))
|
|
@ -1,136 +0,0 @@
|
|||
;;;; "priorque.scm" priority queues for Scheme.
|
||||
;;; Copyright (C) 1992, 1993, 1994, 1995, 1997 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
;;; Algorithm from:
|
||||
;;; Introduction to Algorithms by T. Cormen, C. Leiserson, R. Rivest.
|
||||
;;; 1989 MIT Press.
|
||||
|
||||
(require 'record)
|
||||
|
||||
;; Record type.
|
||||
(define heap:rtd (make-record-type "heap" '(array size heap<?)))
|
||||
|
||||
;; Constructor.
|
||||
(define heap:make-heap
|
||||
(let ((cstr (record-constructor heap:rtd)))
|
||||
(lambda (pred<?)
|
||||
(cstr (make-vector 4) 0 pred<?))))
|
||||
|
||||
;; Reference an element.
|
||||
(define heap:ref
|
||||
(let ((ra (record-accessor heap:rtd 'array)))
|
||||
(lambda (a i)
|
||||
(vector-ref (ra a) (+ -1 i)))))
|
||||
|
||||
;; Set an element.
|
||||
(define heap:set!
|
||||
(let ((ra (record-accessor heap:rtd 'array)))
|
||||
(lambda (a i v)
|
||||
(vector-set! (ra a) (+ -1 i) v))))
|
||||
|
||||
;; Exchange two elements.
|
||||
(define heap:exchange
|
||||
(let ((aa (record-accessor heap:rtd 'array)))
|
||||
(lambda (a i j)
|
||||
(set! i (+ -1 i))
|
||||
(set! j (+ -1 j))
|
||||
(let* ((ra (aa a))
|
||||
(tmp (vector-ref ra i)))
|
||||
(vector-set! ra i (vector-ref ra j))
|
||||
(vector-set! ra j tmp)))))
|
||||
|
||||
|
||||
;; Get length.
|
||||
(define heap:length (record-accessor heap:rtd 'size))
|
||||
|
||||
(define heap:heap<? (record-accessor heap:rtd 'heap<?))
|
||||
|
||||
(define heap:set-size!
|
||||
(let ((aa (record-accessor heap:rtd 'array))
|
||||
(am (record-modifier heap:rtd 'array))
|
||||
(sm (record-modifier heap:rtd 'size)))
|
||||
(lambda (a s)
|
||||
(let ((ra (aa a)))
|
||||
(if (> s (vector-length ra))
|
||||
(let ((nra (make-vector (+ s (quotient s 2)))))
|
||||
(do ((i (+ -1 (vector-length ra)) (+ -1 i)))
|
||||
((negative? i) (am a nra))
|
||||
(vector-set! nra i (vector-ref ra i)))))
|
||||
(sm a s)))))
|
||||
|
||||
(define (heap:parent i) (quotient i 2))
|
||||
(define (heap:left i) (* 2 i))
|
||||
(define (heap:right i) (+ 1 (* 2 i)))
|
||||
|
||||
(define (heap:heapify a i)
|
||||
(let* ((l (heap:left i))
|
||||
(r (heap:right i))
|
||||
(largest (if (and (<= l (heap:length a))
|
||||
((heap:heap<? a) (heap:ref a i) (heap:ref a l)))
|
||||
l
|
||||
i)))
|
||||
(cond ((and (<= r (heap:length a))
|
||||
((heap:heap<? a) (heap:ref a largest) (heap:ref a r)))
|
||||
(set! largest r)))
|
||||
(cond ((not (= largest i))
|
||||
(heap:exchange a i largest)
|
||||
(heap:heapify a largest)))))
|
||||
|
||||
(define (heap:insert! a key)
|
||||
(define i (+ 1 (heap:length a)))
|
||||
(heap:set-size! a i)
|
||||
(do ()
|
||||
((not (and (> i 1)
|
||||
((heap:heap<? a) (heap:ref a (heap:parent i)) key))))
|
||||
(heap:set! a i (heap:ref a (heap:parent i)))
|
||||
(set! i (heap:parent i)))
|
||||
(heap:set! a i key))
|
||||
|
||||
(define (heap:extract-max! a)
|
||||
(if (< (heap:length a) 1)
|
||||
(slib:error "heap underflow" a))
|
||||
(let ((max (heap:ref a 1)))
|
||||
(heap:set! a 1 (heap:ref a (heap:length a)))
|
||||
(heap:set-size! a (+ -1 (heap:length a)))
|
||||
(heap:heapify a 1)
|
||||
max))
|
||||
|
||||
;;
|
||||
;; Externals.
|
||||
;;
|
||||
(define make-heap heap:make-heap)
|
||||
(define heap-insert! heap:insert!)
|
||||
(define heap-extract-max! heap:extract-max!)
|
||||
(define heap-length heap:length)
|
||||
|
||||
(define (heap:test)
|
||||
(require 'debug)
|
||||
(let ((heap #f))
|
||||
(set! heap (make-heap char>?))
|
||||
(heap-insert! heap #\A)
|
||||
(heap-insert! heap #\Z)
|
||||
(heap-insert! heap #\G)
|
||||
(heap-insert! heap #\B)
|
||||
(heap-insert! heap #\G)
|
||||
(heap-insert! heap #\Q)
|
||||
(heap-insert! heap #\S)
|
||||
(heap-insert! heap #\R)
|
||||
(do ((i 7 (+ -1 i)))
|
||||
((negative? i))
|
||||
(write (heap-extract-max! heap)) (newline))))
|
|
@ -1,68 +0,0 @@
|
|||
;;;; "process.scm", Multi-Processing for Scheme
|
||||
;;; Copyright (C) 1992, 1993 Aubrey Jaffer.
|
||||
;
|
||||
;Permission to copy this software, to redistribute it, and to use it
|
||||
;for any purpose is granted, subject to the following restrictions and
|
||||
;understandings.
|
||||
;
|
||||
;1. Any copy made of this software must include this copyright notice
|
||||
;in full.
|
||||
;
|
||||
;2. I have made no warrantee or representation that the operation of
|
||||
;this software will be error-free, and I am under no obligation to
|
||||
;provide any services, by way of maintenance, update, or otherwise.
|
||||
;
|
||||
;3. In conjunction with products arising from the use of this
|
||||
;material, there shall be no use of my name in any advertising,
|
||||
;promotional, or sales literature without prior written consent in
|
||||
;each case.
|
||||
|
||||
(require 'full-continuation)
|
||||
(require 'queue)
|
||||
|
||||
(define (add-process! thunk1)
|
||||
(cond ((procedure? thunk1)
|
||||
(defer-ints)
|
||||
(enqueue! process:queue thunk1)
|
||||
(allow-ints))
|
||||
(else (slib:error "add-process!: wrong type argument " thunk1))))
|
||||
|
||||
(define (process:schedule!)
|
||||
(defer-ints)
|
||||
(cond ((queue-empty? process:queue) (allow-ints)
|
||||
'still-running)
|
||||
(else (call-with-current-continuation
|
||||
(lambda (cont)
|
||||
(enqueue! process:queue cont)
|
||||
(let ((proc (dequeue! process:queue)))
|
||||
(allow-ints)
|
||||
(proc 'run))
|
||||
(kill-process!))))))
|
||||
|
||||
(define (kill-process!)
|
||||
(defer-ints)
|
||||
(cond ((queue-empty? process:queue) (allow-ints)
|
||||
(slib:exit))
|
||||
(else (let ((proc (dequeue! process:queue)))
|
||||
(allow-ints)
|
||||
(proc 'run))
|
||||
(kill-process!))))
|
||||
|
||||
(define ints-disabled #f)
|
||||
(define alarm-deferred #f)
|
||||
|
||||
(define (defer-ints) (set! ints-disabled #t))
|
||||
|
||||
(define (allow-ints)
|
||||
(set! ints-disabled #f)
|
||||
(cond (alarm-deferred
|
||||
(set! alarm-deferred #f)
|
||||
(alarm-interrupt))))
|
||||
|
||||
;;; Make THE process queue.
|
||||
(define process:queue (make-queue))
|
||||
|
||||
(define (alarm-interrupt)
|
||||
(alarm 1)
|
||||
(if ints-disabled (set! alarm-deferred #t)
|
||||
(process:schedule!)))
|
|
@ -1,29 +0,0 @@
|
|||
;;;"promise.scm" promise for force and delay
|
||||
;;; From Revised^4 Report on the Algorithmic Language Scheme
|
||||
;;; Editors: William Clinger and Jonathon Rees
|
||||
;
|
||||
; We intend this report to belong to the entire Scheme community, and so
|
||||
; we grant permission to copy it in whole or in part without fee. In
|
||||
; particular, we encourage implementors of Scheme to use this report as
|
||||
; a starting point for manuals and other documentation, modifying it as
|
||||
; necessary.
|
||||
|
||||
(define promise:force (lambda (object) (object)))
|
||||
|
||||
(define make-promise
|
||||
(lambda (proc)
|
||||
(let ((result-ready? #f)
|
||||
(result #f))
|
||||
(lambda ()
|
||||
(if result-ready?
|
||||
result
|
||||
(let ((x (proc)))
|
||||
(if result-ready?
|
||||
result
|
||||
(begin (set! result-ready? #t)
|
||||
(set! result x)
|
||||
result))))))))
|
||||
|
||||
;;; change occurences of (DELAY <expression>) to
|
||||
;;; (MAKE-PROMISE (LAMBDA () <expression>))
|
||||
;;; and (define force promise:force)
|
|
@ -1,206 +0,0 @@
|
|||
;;; "pscheme.init" SLIB init file for Pocket Scheme -*-scheme-*-
|
||||
;;; Author: Ben Goetter <goetter@mazama.net>
|
||||
;;; last revised for 1.1.0 on 16 October 2000
|
||||
;;; Initial work for 0.2.3 by Robert Goldman (goldman@htc.honeywell.com)
|
||||
;;; SLIB orig Author: Aubrey Jaffer (jaffer@ai.mit.edu)
|
||||
;;;
|
||||
;;; This code is in the public domain.
|
||||
|
||||
; best fit for Windows CE?
|
||||
(define (software-type) 'MS-DOS)
|
||||
|
||||
(define (scheme-implementation-type) 'Pocket-Scheme)
|
||||
(define (scheme-implementation-version)
|
||||
(let ((v (version)))
|
||||
(string-append
|
||||
(number->string (car v)) "."
|
||||
(number->string (cadr v)) "."
|
||||
(number->string (caddr v)))))
|
||||
(define (scheme-implementation-home-page) "http://www.mazama.net/scheme/pscheme.htm")
|
||||
|
||||
|
||||
(define in-vicinity string-append)
|
||||
|
||||
(define (implementation-vicinity) "\\Program Files\\Pocket Scheme\\")
|
||||
(define (library-vicinity) (in-vicinity (implementation-vicinity) "slib\\"))
|
||||
(define (home-vicinity) "\\My Documents\\")
|
||||
|
||||
;(define (implementation-vicinity) "D:\\SRC\\PSCHEME\\BUILD\\TARGET\\X86\\NT\\DBG\\")
|
||||
;(define (library-vicinity) "D:\\SRC\\SLIB\\")
|
||||
;(define (home-vicinity) "D:\\SRC\\PSCHEME\\")
|
||||
|
||||
(define *features*
|
||||
'(source
|
||||
rev4-report
|
||||
ieee-p1178
|
||||
rev4-optional-procedures
|
||||
multiarg/and-
|
||||
multiarg-apply
|
||||
with-file
|
||||
char-ready?
|
||||
defmacro
|
||||
rationalize
|
||||
delay
|
||||
eval
|
||||
dynamic-wind
|
||||
full-continuation
|
||||
; Undef this to get the SLIB TRACE macros
|
||||
; trace
|
||||
system
|
||||
string-port
|
||||
))
|
||||
|
||||
|
||||
;;; (OUTPUT-PORT-WIDTH <port>)
|
||||
;;; (OUTPUT-PORT-HEIGHT <port>)
|
||||
;; $BUGBUG completely bogus values.
|
||||
(define (output-port-width . arg) 79)
|
||||
(define (output-port-height . arg) 12)
|
||||
|
||||
;;; (TMPNAM) makes a temporary file name.
|
||||
(define tmpnam (let ((cntr 100))
|
||||
(lambda () (set! cntr (+ 1 cntr))
|
||||
(string-append "slib_" (number->string cntr)))))
|
||||
|
||||
;;; (FILE-EXISTS? <string>)
|
||||
(define (file-exists? f)
|
||||
(with-handlers (((lambda (x) #t) (lambda (x) #f)))
|
||||
(close-input-port (open-input-file f))
|
||||
#t))
|
||||
|
||||
;; pscheme: current-error-port, delete-file, force-output already defined
|
||||
|
||||
;;; CHAR-CODE-LIMIT is one greater than the largest integer which can
|
||||
;;; be returned by CHAR->INTEGER.
|
||||
;(define char-code-limit
|
||||
; (with-handlers (
|
||||
; ((lambda (x) #t) (lambda (x) 256))
|
||||
; )
|
||||
; (integer->char 65535)
|
||||
; 65536))
|
||||
;;; Currently there are only three clients of this symbol.
|
||||
;;; Following observations relate to PScheme 0.3.5, JACAL 1a9, SLIB 2c5.
|
||||
;;; JACAL: crashes when set to 65536.
|
||||
;;; make-crc: extremely inefficient when set to 65536, spending forever in init
|
||||
;;; precedence-parse: ignores any setting in excess of 256
|
||||
;;; So we patch it to 256.
|
||||
(define char-code-limit 256)
|
||||
|
||||
;;; MOST-POSITIVE-FIXNUM is used in modular.scm
|
||||
;;; This is the most positive immediate-value fixnum in PScheme.
|
||||
(define most-positive-fixnum #x07FFFFFF)
|
||||
|
||||
;;; Return argument
|
||||
(define (identity x) x)
|
||||
|
||||
;;; SLIB:EVAL is single argument eval using the top-level (user) environment.
|
||||
(define slib:eval eval)
|
||||
|
||||
;;; If your implementation provides R4RS macros:
|
||||
;(define macro:eval slib:eval)
|
||||
;(define macro:load load)
|
||||
|
||||
; Define defmacro in terms of our define-macro
|
||||
(define-macro (defmacro name args . body)
|
||||
`(define-macro (,name ,@args) ,@body))
|
||||
|
||||
; following defns removed in 0.6.3 while I rethink macro support
|
||||
;(define defmacro? macro?)
|
||||
;(define macroexpand expand-macro)
|
||||
;(define macroexpand-1 expand-macro-1)
|
||||
|
||||
(define gentemp gensym)
|
||||
|
||||
(define base:eval slib:eval)
|
||||
(define defmacro:eval slib:eval)
|
||||
|
||||
(define (slib:eval-load <pathname> evl)
|
||||
(if (not (file-exists? <pathname>))
|
||||
(set! <pathname> (string-append <pathname> (scheme-file-suffix))))
|
||||
(call-with-input-file <pathname>
|
||||
(lambda (port)
|
||||
(let ((old-load-pathname *load-pathname*))
|
||||
(set! *load-pathname* <pathname>)
|
||||
(do ((o (read port) (read port)))
|
||||
((eof-object? o))
|
||||
(evl o))
|
||||
(set! *load-pathname* old-load-pathname)))))
|
||||
|
||||
(define (defmacro:load <pathname>)
|
||||
(slib:eval-load <pathname> defmacro:eval))
|
||||
|
||||
(define slib:warn
|
||||
(lambda args
|
||||
(let ((port (current-error-port)))
|
||||
(display "Warn: " port)
|
||||
(for-each (lambda (x) (display x port)) args))))
|
||||
|
||||
;;; Define an error procedure for the library
|
||||
(define slib:error error)
|
||||
|
||||
;;; As announced by feature string-port
|
||||
(define (call-with-output-string t)
|
||||
(let* ((p (open-output-string))
|
||||
(r (t p))
|
||||
(s (get-output-string p)))
|
||||
(close-output-port p)
|
||||
s))
|
||||
|
||||
(define (call-with-input-string s t)
|
||||
(let* ((p (open-input-string s))
|
||||
(r (t p)))
|
||||
(close-input-port p)
|
||||
r))
|
||||
|
||||
;;; define these as appropriate for your system.
|
||||
(define slib:tab (integer->char 9))
|
||||
(define slib:form-feed (integer->char 12))
|
||||
|
||||
;;; Support for older versions of Scheme. Not enough code for its own file.
|
||||
(define (last-pair l) (if (pair? (cdr l)) (last-pair (cdr l)) l))
|
||||
(define t #t)
|
||||
(define nil #f)
|
||||
|
||||
;;; Define these if your implementation's syntax can support it and if
|
||||
;;; they are not already defined.
|
||||
|
||||
(define (1+ n) (+ n 1))
|
||||
(define (-1+ n) (+ n -1))
|
||||
(define 1- -1+)
|
||||
|
||||
;;; Define SLIB:EXIT to be the implementation procedure to exit or
|
||||
;;; return if exitting not supported.
|
||||
(define slib:exit exit)
|
||||
|
||||
;;; Here for backward compatability
|
||||
(define scheme-file-suffix
|
||||
(let ((suffix (case (software-type)
|
||||
((NOSVE) "_scm")
|
||||
(else ".scm"))))
|
||||
(lambda () suffix)))
|
||||
|
||||
;;; (SLIB:LOAD-SOURCE "foo") should load "foo.scm" or with whatever
|
||||
;;; suffix all the module files in SLIB have. See feature 'SOURCE.
|
||||
|
||||
(define (slib:load-source f)
|
||||
(if (not (file-exists? f))
|
||||
(set! f (string-append f (scheme-file-suffix))))
|
||||
(load f))
|
||||
|
||||
;;; (SLIB:LOAD-COMPILED "foo") should load the file that was produced
|
||||
;;; by compiling "foo.scm" if this implementation can compile files.
|
||||
;;; See feature 'COMPILED.
|
||||
|
||||
(define slib:load-compiled load)
|
||||
|
||||
;;; At this point SLIB:LOAD must be able to load SLIB files.
|
||||
|
||||
(define slib:load slib:load-source)
|
||||
|
||||
;;; Pscheme and SLIB both define REQUIRE, so dispatch on argument type.
|
||||
;;; The SLIB REQUIRE does accept strings, though this facility seems never to be used.
|
||||
(define pscheme:require require)
|
||||
(slib:load (in-vicinity (library-vicinity) "require"))
|
||||
(define slib:require require)
|
||||
(define (require x)
|
||||
(if (string? x) (pscheme:require x) (slib:require x)))
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue