From: oz@ursa.sis.yorku.ca (Ozan Yigit)
Subject: announcement: vscm - another scheme implementation
Organization: York U. Student Information Systems Project
Date: Tue, 8 Sep 1992 17:50:43 GMT

Matthias Blume's VSCM [vscm92Sep7.tar.Z] is now available from the
implementations section  [pub/scheme/imp] of the Scheme Repository,
currently hosted at nexus.yorku.ca [130.63.9.66] for anonymous ftp.

Matthias Blume may be reached as blume@cs.princeton.edu.

I include VSCM README below.

enjoy.	oz
---
ps: as an internetworking courtesy, please try to avoid having ftp
    sessions during the peak working hours, i.e. 9.00am-5:00pm EST.
---

VSCM - A Scheme Implementation

Abstract:
	Vscm is a fairly complete implementation of the Scheme language,
	as described in the ``Revised^4 Report of the Algorithmic Language
	Scheme'' (R4RS).

Primary goals:
	The primary goal for developing this Scheme implementation was
	to get a reliable and small, portable Scheme system, which
	may run on a variety of different hardware platforms and
	under control of most common operating systems.
	It should be well understood (at least by myself :-), so I can
	do any kind of improvement, if there is the need to do so.
	Therefore, in the beginning this implementation was intended
	for use by myself and in my research projects only.  But now I feel,
	that I should give a working release of this program to the
	Scheme community in order to receive feedback from other people.
	Do anything you like with this system, I'm happy to receive
	your comments!

Design decisions:
	The system is divided into two main parts: a virtual machine (VM),
	running some kind of byte code, and a compiler (written in scheme
	itself) running on the virtual machine and producing code for
	this virtual machine.  The compiler can compile its own source,
	so there is the opportunity of bootstrapping.
	To keep the compiler small and simple, there is heavy support
	from the underlying VM for most sophisticated features of Scheme:
	for instance, there is no need to do CPS-conversion, because the
	structure of the VM provides the concept of the continuation for free.

	To obtain a highly portable system, of course, there is the need
	to have a highly portable VM.  Scheme programs should always
	be portable, at least, if they obey the rules oulined in R4RS.
	In order to achieve this level of portability for the VM as well,
	I decided to use ANSI-C.  I tried very hard to ban all
	non-ANSI idioms from my program.  The program has proven to work
	on several platforms using several different compilers.
	(One known violation of my rules is: I use the fileno-feature
	from stdio.h, which is not ANSI.  It can easily be eliminated,
	because its use is not necessary for the systems operation.)

	The system is designed to produce ``memory dumps'' on demand.
	These dumps represent a description of the layout of the heap
	at the time of the dump.  Because no binary data is ever written
	into such memory dumps, they may be used across
	a machine architectures boundaries without change.
	In fact, the VM is not really a Scheme system.  ``Booting''
	from the right memory dump can turn it into one!

How unspecified details from R4RS are implemented:
	-- #f and () differ.  () is truish, only #f counts as FALSE.
	-- if you escape from calls to procedures by means of
	   escape procedures (continuations) and you
	   continue later using a continuation that has been captured
	   before the escape, then the current input and output files,
	   the current error handler, the current gc-strategy and the
	   current interrupt-handler are the same, as at the moment at which
	   the continuation has been captured.  In effect, these
	   properties are inherent properties of the continuation
	   an not any kind of ``global system state''.

Current restrictions:
	-- all numbers are integers (of virtually unlimited range).
	-- string->number, number->string are not implemented.
	-- no macro facility.
	-- char-ready? writes a warning and returns #f, without
	   really checking anything.  Unfortunately, testing for the
	   presence of input is inherently non-portable, so I was not
	   able to include working code for char-ready?.

Extensions:
	-- (quit [status]) kills Scheme, returns status to the operating
	   system environment (default: 0).
	-- (dump "filename")	writes a memory dump (see above) into the
	   named file "filename" and returns #t.
	   If you use this file later in a shell command line like in
		scheme -b filename
	   then you are ``booting'' scheme using the saved state, including
	   information about the current continuation.  The system
	   behaves, as if it would return from the call to
	   dump, now returning #f instead of #t.
	   This is reminicent of the behaviour of fork(2) in the UNIX
	   operating system.  When booting, scheme reconnects
	   stdin, stdout and stderr to the corresponding port objects.
	   Other port objects remain closed, even if they had been open
	   at the time of the dump-call.
	   Note, that you can use files, which have been produced by dump,
	   across different architectures.
	-- (system "shellcommand") as in C.
	   If system(2) returns 0, system returns #t, otherwise the value is
	   #f.
	-- (with-error-handler proc thunk)
	   This call invokes thunk, which must be a procedure without
	   arguments.  If it returns a value, then the entire call returns
	   that value.  If, however, an error condition is raised during
	   the execution thunk's body (and it does not get caught by
	   a nested error handler), then this results in a call to proc,
	   which is called the ``error handler''.
	   proc takes two arguments: the error message (a string),
	   and the continuation of the execution at the time when the error
	   occured.  The continuation is intended for error tracing purposes
	   only (-> inspect).
	   If proc is ever called, then this call is NOT PART of any other
	   continuation.  This means, that returning from proc is useless
	   and causes a system reset.
	   Equally, you must not call the continuation object passed to proc,
	   though this might be useful.  It does not contain all the
	   information which is necessary to recover from the error, and
	   causes a system reset as well.
	   Of course, you can escape from an error handler by calling
	   a previously captured continuation.
	-- (with-interrupt-handler proc thunk)
	   Both, proc and thunk, are procedures without arguments.
	   The procedure calls thunk and yields the value obtained from
	   the call to thunk.  If an interrupt (SIGINT) occurs during the
	   execution of thunk, then the execution will be suspended and
	   proc will be called. If proc returns, then the execution of
	   thunk resumes as if nothing happened.  One exception: if the
	   interrupt occurs during a call to read, then read will not
	   resume, but instead return the END-OF-FILE-object.
	-- (with-gc-strategy proc thunk)
	   The thunk (a procedure without arguments) will be called and its
	   value is the result of the entire expression.  If, however,
	   the system has to perform garbage collection during the execution
	   of thunk, then (as with interrupts) the execution of thunk
	   will be suspended, and proc will be called with seven (!) arguments.
	   These arguments (integers) contain useful information about the
	   latest run of the garbage collector.
		(proc gbc nobj min pmin tot used time)
	   gbc: total count of calls to the internal routine getbytes.
	   nobj: total count of living objects in the heap
	   min: minimum size of the heap (heap overflows with heap sizes
	        less than min don't trigger garbage collection).
	   pmin: min during the gc-run before the last.
	         If this is greater than min, it shows, that there is not
		 enough space to fulfill the demand expressed by min.
	   tot: total heap size.
	   used: used space of the heap.
	   time: time in millisoconds spent on this gc-run.
	     Note: the garbage collector uses stop&copy GC. Therefore
		   it switches between two separate heaps.
	   The return value of proc will be interpreted as follows:
		#f - give up -- this triggers a system reset.
		an integer -- becomes the new min
		anything else -- ignored
	-- (standard-port number) must be called with either 0, 1 or 2.
	   It returns the port objects for stdin, stdout or stderr,
	   respectively.
	-- (cons-quotient-remainder x y) yields the same
	   as (cons (quotient x y) (remainder x y)), but divides only
	   once.
	-- (error "message") raises an error condition with the message
	   "message".
	-- (clock) returns the current cpu time of the running scheme.
	   The unit is milliseconds.  The value may be incorrect due to
	   limitations of the ANSI-C library.
	-- (gc-clock) returns the time, that the current scheme process spent
	   on garbage collection. The unit is milliseconds.  The same
	   limitations as for (clock) apply.
	-- (inspect cont n) fetches information about the n-th activation
	   record from the continuation object cont.  This is very
	   dangerous, because the result contains actual control
	   information of the VM, which may easily be destroyed.  The code
	   of the compiler shows possible uses of inspect, but it is
	   subject to change without any notice.
	-- (define-asm ...)
	   (execute-asm ...)
	   These procedures are low-level primitives used by the compiler
	   to create and execute compiled code.

To build the system:
	-- Edit Makefile (look at the comments there).
	   You will need ANSI-C and ANSI-C libraries.
	-- make
	   - Usually, this should build the system without errors or
	     warnings (at least using gcc).  Warnings may occur due to
	     inconsistent libraries or conversions between char * and
	     unsigned char *.
	-- scheme

	Note: If there appears a question during ``make'' about
	      scmcomp/boot.asm, which looks like ``DO YOU WANT TO CONTINUE'',
	      then answer ``y''!  But beware of changes to scmcomp/boot-c.scm!

Notes:
	Vscm is able to read assembly code (for its bytecode-machine).
	If you boot scheme using the command line
		scheme -b scmcomp/cfilt.boot
	you obtain a Scheme->Assemblycode filter.  Its use is restricted
	to function definitions.  This may be used to compile the compiler.
	If you don't use the -b command line switch, scheme will boot from
	a file, the name of which is given by the environment variable
	VSCMBOOT and which defaults to ``.scheme-boot''.