Michele,

The distinction you make between "compiler semantics" and "interpreter semantics" is not accurate. Allow me to explain.

Compiler semantics (aka phased semantics) means that a piece of code is processed in two steps: first, it is fully expanded yielding code with no macro definitions and macro uses, *then* the resulting code is evaluated (using an interpreter, compiler, or whatever).

Interpreter semantics (aka unphased semantics) means that expansion and evaluation happen simultaneously, or more accurately, expansion and evaluation steps are interleaved.

The examples you give in the article, and all the systems you compare follow the phased semantics, and I have not seen any Scheme systems that still uses interpreter semantics (with the exception of SCM maybe but I haven't used it so I can't say much about it). So, how do these systems (Ypsilon, Ikarus, and PLT) differ? And how does the Ikarus/Ypsilon REPL differ from the R6RS-script mode?

It's the granularity, or size of the compilation unit that makes the difference between the repl and the script modes. In the repl, the compilation unit is one single expression or definition entered into the repl. That unit is expanded, then evaluated, and the result is printed to the console (or saved in case of definitions) before the repl accepts a new expression. In case of scripts, the whole program is first expanded then evaluated as a whole unit.

In your example, you have a procedure definition:
  (define (distinct? eq? ls) ---)
and a syntax definition that uses it:
  (def-syntax (assert-distinct arg ...) --- distinct? ---)

In phased semantics, you want the definition of distinct? to be available (already processed, evaluated, whatever) *before* it is used in the syntax definition, so, it has to be in a separate compilation unit. In the Ikarus/Ypsilon repl, it is sufficient to enter the first definition into the repl to have it available for syntax definitions. In a script (a whole compilation unit), you cannot do that, so you define distinct? in a separate compilation unit (a library) to get around the limitation.

Now compiler and interpreter semantics as described above differ when you try to do:

(let ()
  (define (distinct? eq? ls) ---)
  (def-syntax (assert-distinct arg ...) --- distinct? ---)
  ---)

or even a simpler one:

(let ()
  (define var 12)
  (define-syntax syn (lambda (hukarez) var))
  (syn))

Here, the whole let expression is a single compilation unit. So, regardless of whether you enter it into the repl, or have it in a script, a system that uses compiler/phased semantics is going to reject it (with an "identifier out of context" error), and a system that uses interpreter semantics is going to accept it just fine.

The reason why I'm making this distinction is because the conclusion of the article says (among other things) that "In such [interpreter] semantics everything happens at runtime, and there is no phase separation at all". While the statement is true, none of the systems discussed in the article uses interpreter semantics where everything happens at run time and there is no phase separation at all.

Makes sense?  No?

Aziz,,,

[PS. Posting to the list since I thought this is probably useful information for everybody. I usually try to keep my comments private.]


On Apr 25, 2009, at 8:14 AM, Michele Simionato wrote:

Just for the people in this list:

http://www.phyast.pitt.edu/~micheles/scheme/scheme20.html

This episode  - as well as all the episodes about the module system -
are based on the help I got from this list, so if I am presenting
your words incorrectly, please do chastize me.

Reply via email to