Wayback 20070813200916

www.stripedgazelle.org/joey/dream.html
This commit is contained in:
Lassi Kortela 2023-02-22 15:58:57 +02:00
parent dc049a99ba
commit cd3e2f553a
1 changed files with 23 additions and 31 deletions

View File

@ -1,21 +1,24 @@
<html>
<title>The 'dream' Scheme Interpreter</title>
<div style="color:black; font-family:sans-serif;">
<h1>The 'dream' Scheme Interpreter</h1>
by David Joseph Stith
<p>
I am proud to announce the premier production version of my Scheme interpreter, 'dream', written entirely in assembly language (GAS syntax.) :-)
All essential syntax and procedures from the <a href="http://www.swiss.ai.mit.edu/~jaffer/r4rs_toc.html">R4RS standard</a> are implemented.
The interpreter is properly tail recursive and passes all applicable tests from the 'r4rstest.scm' test suite.
Rational arithmetic with 32 bit numerator and denominator is supported, but no Real or Complex numbers.
My overarching goal has been SIMPLICITY.
I have chosen a design and implementation that is as straightforward and direct as I could imagine.
The result is an executable that is quite small and, for an interpreter, quite fast as well. :-)
</p>
<dd>Download source (gcc on PowerPC): <a href="/cgi-bin/wiki_joey/dreamppc.tar.gz">dreamppc.tar.gz</a></dd>
<dd>Download source (gcc on x86): <a href="/cgi-bin/wiki_joey/dreamx86.tar.gz">dreamx86.tar.gz</a></dd>
<dd>Download source and executable for Windows (gcc-mingw on x86): <a href="/cgi-bin/wiki_joey/dreamx86mingw.zip">dreamx86mingw.zip</a></dd>
<hr>
<h1>Notes on the Design of the 'dream' Scheme Interpreter</h1>
<b>Welcome to the home of my Scheme interpreter, 'dream', written entirely in assembly language. :-)</b>
<br />
All essential syntax and procedures from the <a href="http://www.swiss.ai.mit.edu/~jaffer/r4rs_toc.html">R4RS standard</a> are implemented.
<br />
The interpreter is properly tail recursive and passes all applicable tests from the 'r4rstest.scm' test suite.
<br />
Rational arithmetic with 32 bit numerator and denominator is supported, but no Real or Complex numbers.
<hr>
Dream is compiled using an x86 assembler I have written in scheme, with a syntax very similar to GAS.
<br />
Consequently Dream can compile itself and depends only on the Linux kernel. :-)
<hr>
<b>Download source and executable for Linux on x86:</b> <a href="/cgi-bin/wiki_joey/dreamer.tar.gz">dreamer.tar.gz</a>
<hr>
<h2>Notes on the Design</h2>
<p>
The design for the 'dream' Scheme interpreter began with the design given in Abelson and Sussman's <a href="http://mitpress.mit.edu/sicp/full-text/book/book.html">Structure and Interpretation of Computer Programs</a>.
</p>
@ -58,40 +61,29 @@ This and all other objects which require more than a quad-word of storage simply
</p>
<p>
Special forms and built-in procedures store an address to branch to in the second double-word.
When combinations are evaluated, if the 'car' of the combination is a symbol of the type MEMOIZABLE_SYMBOL bound to a special form or built-in procedure (in the top-level environment), then the 'car' of the combination is set! to the special form or built-in procedure to which the symbol was bound.
This way, each time this combination is evaluated afterwards, the symbol lookup in the top-level environment will no longer be necessary, and the efficiency of the interpreter is greatly enhanced.
However, the R4RS standard for scheme requires that these symbols, bound to built-in procedures, may be redefined, and we may presume that any redefinition should then be effective retroactively for all occurences of the symbol within the same environment.
The memoizing technique described above is inconsistent with this requirement.
Therefore, symbols of the type MEMOIZABLE_SYMBOL are allowed by <a href="http://www.swiss.ai.mit.edu/~jaffer/r4rs_toc.html">R4RS</a> to be bound only to special forms.
Consequently, we make this standards compliant behavior the default, but for efficiency's sake we provide memoization of built-in procedures as a conditional compilation option.
</p>
<p>
Number types are distinguished by the high byte of the low word, which increases as the complexity of the type of number ascends the numeric tower. Integers simply store their 32 bit signed value in the second half of the quad-word. Rationals are stored as a pair of integers, thus the low bit in the high byte of the low word of their type is set so that the garbage collector will see the pair. Inexactness of a number is indicated by setting the lowest bit of the high word of the number's type. Note, however, that all internal representations of numbers are exact (no floating point numbers are used), and so inexactness is given only as an auxiliary property of the number.
</p>
<p>
</p>
Input ports use the low byte of the high word of the type field to store the last character read by the (peek) procedure. The second half of the quad-word for both input and output ports holds the FILE* pointer associated with the port.
Input ports use the low byte of the high word of the type field to store the last character read by the (peek) procedure. The second half of the quad-word for both input and output ports holds the file descriptor associated with the port.
The ports returned by (current-input-port) and (current-output-port) are stored internally for efficiency's sake.
They therefore must be treated by the garbage collector as if they were registers (which indeed they are in the register-rich PowerPC version).
They therefore must be treated by the garbage collector as if they were registers.
<h2>The Stack</h2>
<p>
The scheme object stack is maintained as a scheme list (dynamically allocated as pairs).
The garbage collector, when it runs, begins at the root of this scheme list.
Hence when garbage collection commences, only the registers and the current input and output ports need be pushed on to this scheme object stack and popped off afterwards to insure that all reachable objects are retained thoughout the garbage collection process.
On x86 machines, the stack pointed to by the %esp register is used for the flow of continuation control.
The native stack (pointed to by the %esp register) is used for the flow of continuation control.
Consequently when call-with-current-continuation is invoked, this native stack is copied to a scheme list with each address represented as a special form.
</p>
<h2>Scheme Registers</h2>
<p>
The registers denoted by EXP, ENV, UNEV, ARGL, VAL, FREE, OLD, NEW, and SCAN in <a href="http://mitpress.mit.edu/sicp/full-text/book/book.html">Structure and Interpretation of Computer Programs</a> are defined via preprocessor macros to the machine registers that implement them.
EXP, ENV, UNEV, ARGL, and VAL must point to a valid scheme object (or null) when the garbage collector is invoked.
</p>
<h2>Input/Output</h2>
<p>
The standard C library is used for file input and output in order facilitate portability.
Specifically, only fgetc, fputc, fprintf, fopen, and fclose are used.
The registers denoted by EXP, ENV, UNEV, ARGL, VAL, and FREE in <a href="http://mitpress.mit.edu/sicp/full-text/book/book.html">Structure and Interpretation of Computer Programs</a> are implemented by the machine registers EDX, EBP, ESI, EDI, EAX, and EBX respectively.
The registers EXP, ENV, UNEV, ARGL, and VAL must point to a valid scheme object (or null) when the garbage collector is invoked.
Likewise, the garbage collector registers OLD, NEW, and SCAN are implemented by the machine registers ESI, EDI, and EAX respectively.
</p>
<hr>
<a href="home.html">home</a>
</html>
</div></html>