| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- TinySCHEME Version 1.38
- "Safe if used as prescribed"
- -- Philip K. Dick, "Ubik"
- This software is open source, covered by a BSD-style license.
- Please read accompanying file COPYING.
- -------------------------------------------------------------------------------
- This Scheme interpreter is based on MiniSCHEME version 0.85k4
- (see miniscm.tar.gz in the Scheme Repository)
- Original credits in file MiniSCHEMETribute.txt.
- D. Souflis (dsouflis@acm.org)
- -------------------------------------------------------------------------------
- What is TinyScheme?
- -------------------
- TinyScheme is a lightweight Scheme interpreter that implements as large
- a subset of R5RS as was possible without getting very large and
- complicated. It is meant to be used as an embedded scripting interpreter
- for other programs. As such, it does not offer IDEs or extensive toolkits
- although it does sport a small top-level loop, included conditionally.
- A lot of functionality in TinyScheme is included conditionally, to allow
- developers freedom in balancing features and footprint.
- As an embedded interpreter, it allows multiple interpreter states to
- coexist in the same program, without any interference between them.
- Programmatically, foreign functions in C can be added and values
- can be defined in the Scheme environment. Being a quite small program,
- it is easy to comprehend, get to grips with, and use.
- Known bugs
- ----------
- TinyScheme is known to misbehave when memory is exhausted.
- Things that keep missing, or that need fixing
- ---------------------------------------------
- There are no hygienic macros. No rational or
- complex numbers. No unwind-protect and call-with-values.
- Maybe (a subset of) SLIB will work with TinySCHEME...
- Decent debugging facilities are missing. Only tracing is supported
- natively.
- Scheme Reference
- ----------------
- If something seems to be missing, please refer to the code and
- "init.scm", since some are library functions. Refer to the MiniSCHEME
- readme as a last resort.
- Environments
- (interaction-environment)
- See R5RS. In TinySCHEME, immutable list of association lists.
- (current-environment)
- The environment in effect at the time of the call. An example of its
- use and its utility can be found in the sample code that implements
- packages in "init.scm":
- (macro (package form)
- `(apply (lambda ()
- ,@(cdr form)
- (current-environment))))
- The environment containing the (local) definitions inside the closure
- is returned as an immutable value.
- (defined? <symbol>) (defined? <symbol> <environment>)
- Checks whether the given symbol is defined in the current (or given)
- environment.
- Symbols
- (gensym)
- Returns a new interned symbol each time. Will probably move to the
- library when string->symbol is implemented.
- Directives
- (gc)
- Performs garbage collection immediatelly.
- (gcverbose) (gcverbose <bool>)
- The argument (defaulting to #t) controls whether GC produces
- visible outcome.
- (quit) (quit <num>)
- Stops the interpreter and sets the 'retcode' internal field (defaults
- to 0). When standalone, 'retcode' is returned as exit code to the OS.
- (tracing <num>)
- 1, turns on tracing. 0 turns it off. (Only when USE_TRACING is 1).
- Mathematical functions
- Since rationals and complexes are absent, the respective functions
- are also missing.
- Supported: exp, log, sin, cos, tan, asin, acos, atan, floor, ceiling,
- trunc, round and also sqrt and expt when USE_MATH=1.
- Number-theoretical quotient, remainder and modulo, gcd, lcm.
- Library: exact?, inexact?, odd?, even?, zero?, positive?, negative?,
- exact->inexact. inexact->exact is a core function.
- Type predicates
- boolean?,eof-object?,symbol?,number?,string?,integer?,real?,list?,null?,
- char?,port?,input-port?,output-port?,procedure?,pair?,environment?',
- vector?. Also closure?, macro?.
- Types
- Types supported:
- Numbers (integers and reals)
- Symbols
- Pairs
- Strings
- Characters
- Ports
- Eof object
- Environments
- Vectors
- Literals
- String literals can contain escaped quotes \" as usual, but also
- \n, \r, \t, \xDD (hex representations) and \DDD (octal representations).
- Note also that it is possible to include literal newlines in string
- literals, e.g.
- (define s "String with newline here
- and here
- that can function like a HERE-string")
- Character literals contain #\space and #\newline and are supplemented
- with #\return and #\tab, with obvious meanings. Hex character
- representations are allowed (e.g. #\x20 is #\space).
- When USE_ASCII_NAMES is defined, various control characters can be
- refered to by their ASCII name.
- 0 #\nul 17 #\dc1
- 1 #\soh 18 #\dc2
- 2 #\stx 19 #\dc3
- 3 #\etx 20 #\dc4
- 4 #\eot 21 #\nak
- 5 #\enq 22 #\syn
- 6 #\ack 23 #\etv
- 7 #\bel 24 #\can
- 8 #\bs 25 #\em
- 9 #\ht 26 #\sub
- 10 #\lf 27 #\esc
- 11 #\vt 28 #\fs
- 12 #\ff 29 #\gs
- 13 #\cr 30 #\rs
- 14 #\so 31 #\us
- 15 #\si
- 16 #\dle 127 #\del
-
- Numeric literals support #x #o #b and #d. Flonums are currently read only
- in decimal notation. Full grammar will be supported soon.
- Quote, quasiquote etc.
- As usual.
- Immutable values
- Immutable pairs cannot be modified by set-car! and set-cdr!.
- Immutable strings cannot be modified via string-set!
- I/O
- As per R5RS, plus String Ports (see below).
- current-input-port, current-output-port,
- close-input-port, close-output-port, input-port?, output-port?,
- open-input-file, open-output-file.
- read, write, display, newline, write-char, read-char, peek-char.
- char-ready? returns #t only for string ports, because there is no
- portable way in stdio to determine if a character is available.
- Also open-input-output-file, set-input-port, set-output-port (not R5RS)
- Library: call-with-input-file, call-with-output-file,
- with-input-from-file, with-output-from-file and
- with-input-output-from-to-files, close-port and input-output-port?
- (not R5RS).
- String Ports: open-input-string, open-output-string,
- open-input-output-string. Strings can be used with I/O routines.
- Vectors
- make-vector, vector, vector-length, vector-ref, vector-set!, list->vector,
- vector-fill!, vector->list, vector-equal? (auxiliary function, not R5RS)
- Strings
- string, make-string, list->string, string-length, string-ref, string-set!,
- substring, string->list, string-fill!, string-append, string-copy.
- string=?, string<?, string>?, string>?, string<=?, string>=?.
- (No string-ci*? yet). string->number, number->string. Also atom->string,
- string->atom (not R5RS).
- Symbols
- symbol->string, string->symbol
- Characters
- integer->char, char->integer.
- char=?, char<?, char>?, char<=?, char>=?.
- (No char-ci*?)
- Pairs & Lists
- cons, car, cdr, list, length, map, for-each, foldr, list-tail,
- list-ref, last-pair, reverse, append.
- Also member, memq, memv, based on generic-member, assoc, assq, assv
- based on generic-assoc.
- Streams
- head, tail, cons-stream
- Control features
- Apart from procedure?, also macro? and closure?
- map, for-each, force, delay, call-with-current-continuation (or call/cc),
- eval, apply. 'Forcing' a value that is not a promise produces the value.
- There is no call-with-values, values, nor dynamic-wind. Dynamic-wind in
- the presence of continuations would require support from the abstract
- machine itself.
- Property lists
- TinyScheme inherited from MiniScheme property lists for symbols.
- put, get.
- Dynamically-loaded extensions
- (load-extension <filename without extension>)
- Loads a DLL declaring foreign procedures.
-
- Esoteric procedures
- (oblist)
- Returns the oblist, an immutable list of all the symbols.
- (macro-expand <form>)
- Returns the expanded form of the macro call denoted by the argument
- (define-with-return (<procname> <args>...) <body>)
- Like plain 'define', but makes the continuation available as 'return'
- inside the procedure. Handy for imperative programs.
- (new-segment <num>)
- Allocates more memory segments.
- defined?
- See "Environments"
- (get-closure-code <closure>)
- Gets the code as scheme data.
- (make-closure <code> <environment>)
- Makes a new closure in the given environment.
- Obsolete procedures
- (print-width <object>)
-
- Programmer's Reference
- ----------------------
- The interpreter state is initialized with "scheme_init".
- Custom memory allocation routines can be installed with an alternate
- initialization function: "scheme_init_custom_alloc".
- Files can be loaded with "scheme_load_file". Strings containing Scheme
- code can be loaded with "scheme_load_string". It is a good idea to
- "scheme_load" init.scm before anything else.
- External data for keeping external state (of use to foreign functions)
- can be installed with "scheme_set_external_data".
- Foreign functions are installed with "assign_foreign". Additional
- definitions can be added to the interpreter state, with "scheme_define"
- (this is the way HTTP header data and HTML form data are passed to the
- Scheme script in the Altera SQL Server). If you wish to define the
- foreign function in a specific environment (to enhance modularity),
- use "assign_foreign_env".
- The procedure "scheme_apply0" has been added with persistent scripts in
- mind. Persistent scripts are loaded once, and every time they are needed
- to produce HTTP output, appropriate data are passed through global
- definitions and function "main" is called to do the job. One could
- add easily "scheme_apply1" etc.
- The interpreter state should be deinitialized with "scheme_deinit".
- DLLs containing foreign functions should define a function named
- init_<base-name>. E.g. foo.dll should define init_foo, and bar.so
- should define init_bar. This function should assign_foreign any foreign
- function contained in the DLL.
- The first dynamically loaded extension available for TinyScheme is
- a regular expression library. Although it's by no means an
- established standard, this library is supposed to be installed in
- a directory mirroring its name under the TinyScheme location.
-
- Foreign Functions
- -----------------
- The user can add foreign functions in C. For example, a function
- that squares its argument:
- pointer square(scheme *sc, pointer args) {
- if(args!=sc->NIL) {
- if(sc->isnumber(sc->pair_car(args))) {
- double v=sc->rvalue(sc->pair_car(args));
- return sc->mk_real(sc,v*v);
- }
- }
- return sc->NIL;
- }
- Foreign functions are now defined as closures:
- sc->interface->scheme_define(
- sc,
- sc->global_env,
- sc->interface->mk_symbol(sc,"square"),
- sc->interface->mk_foreign_func(sc, square));
- Foreign functions can use the external data in the "scheme" struct
- to implement any kind of external state.
- External data are set with the following function:
- void scheme_set_external_data(scheme *sc, void *p);
- As of v.1.17, the canonical way for a foreign function in a DLL to
- manipulate Scheme data is using the function pointers in sc->interface.
- Standalone
- ----------
- Usage: tinyscheme -?
- or: tinyscheme [<file1> <file2> ...]
- followed by
- -1 <file> [<arg1> <arg2> ...]
- -c <Scheme commands> [<arg1> <arg2> ...]
- assuming that the executable is named tinyscheme.
- Use - in the place of a filename to denote stdin.
- The -1 flag is meant for #! usage in shell scripts. If you specify
- #! /somewhere/tinyscheme -1
- then tinyscheme will be called to process the file. For example, the
- following script echoes the Scheme list of its arguments.
- #! /somewhere/tinyscheme -1
- (display *args*)
- The -c flag permits execution of arbitrary Scheme code.
- Error Handling
- --------------
- Errors are recovered from without damage. The user can install his
- own handler for system errors, by defining *error-hook*. Defining
- to '() gives the default behavior, which is equivalent to "error".
- USE_ERROR_HOOK must be defined.
- A simple exception handling mechanism can be found in "init.scm".
- A new syntactic form is introduced:
- (catch <expr returned exceptionally>
- <expr1> <expr2> ... <exprN>)
- "Catch" establishes a scope spanning multiple call-frames
- until another "catch" is encountered.
- Exceptions are thrown with:
- (throw "message")
- If used outside a (catch ...), reverts to (error "message").
- Example of use:
- (define (foo x) (write x) (newline) (/ x 0))
- (catch (begin (display "Error!\n") 0)
- (write "Before foo ... ")
- (foo 5)
- (write "After foo"))
- The exception mechanism can be used even by system errors, by
- (define *error-hook* throw)
- which makes use of the error hook described above.
- If necessary, the user can devise his own exception mechanism with
- tagged exceptions etc.
- Reader extensions
- -----------------
- When encountering an unknown character after '#', the user-specified
- procedure *sharp-hook* (if any), is called to read the expression.
- This can be used to extend the reader to handle user-defined constants
- or whatever. It should be a procedure without arguments, reading from
- the current input port (which will be the load-port).
- Colon Qualifiers - Packages
- ---------------------------
- When USE_COLON_HOOK=1:
- The lexer now recognizes the construction <qualifier>::<symbol> and
- transforms it in the following manner (T is the transformation function):
- T(<qualifier>::<symbol>) = (*colon-hook* 'T(<symbol>) <qualifier>)
- where <qualifier> is a symbol not containing any double-colons.
- As the definition is recursive, qualifiers can be nested.
- The user can define his own *colon-hook*, to handle qualified names.
- By default, "init.scm" defines *colon-hook* as EVAL. Consequently,
- the qualifier must denote a Scheme environment, such as one returned
- by (interaction-environment). "Init.scm" defines a new syntantic form,
- PACKAGE, as a simple example. It is used like this:
- (define toto
- (package
- (define foo 1)
- (define bar +)))
- foo ==> Error, "foo" undefined
- (eval 'foo) ==> Error, "foo" undefined
- (eval 'foo toto) ==> 1
- toto::foo ==> 1
- ((eval 'bar toto) 2 (eval 'foo toto)) ==> 3
- (toto::bar 2 toto::foo) ==> 3
- (eval (bar 2 foo) toto) ==> 3
- If the user installs another package infrastructure, he must define
- a new 'package' procedure or macro to retain compatibility with supplied
- code.
- Note: Older versions used ':' as a qualifier. Unfortunately, the use
- of ':' as a pseudo-qualifier in existing code (i.e. SLIB) essentially
- precludes its use as a real qualifier.
|