Formal syntax and semantics

This chapter provides formal descriptions of what has already been described informally in previous chapters of this report.

7.1  Formal syntax

This section provides a formal syntax for Scheme written in an extended BNF.

All spaces in the grammar are for legibility. Case is not significant except in the definitions of <letter>, <character name> and <mnemonic escape>; for example, #x1A and #X1a are equivalent, but foo and Foo and #\space and #\Space are distinct. <empty> stands for the empty string.

The following extensions to BNF are used to make the description more concise: <thing>* means zero or more occurrences of <thing>; and <thing>+ means at least one <thing>.

7.1.1  Lexical structure

This section describes how individual tokens(identifiers, numbers, etc.) are formed from sequences of characters. The following sections describe how expressions and programs are formed from sequences of tokens.

<Intertoken space> can occur on either side of any token, but not within a token.

Identifiers that do not begin with a vertical line are terminated by a <delimiter> or by the end of the input. So are dot, numbers, characters, and booleans. Identifiers that begin with a vertical line are terminated by another vertical line.

The following four characters from the ASCII repertoire are reserved for future extensions to the language: [ ] { }

In addition to the identifier characters of the ASCII repertoire specified below, Scheme implementations may permit any additional repertoire of non-ASCII Unicode characters to be employed in identifiers, provided that each such character has a Unicode general category of Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl, No, Pd, Pc, Po, Sc, Sm, Sk, So, or Co, or is U+200C or U+200D (the zero-width non-joiner and joiner, respectively, which are needed for correct spelling in Persian, Hindi, and other languages). However, it is an error for the first character to have a general category of Nd, Mc, or Me. It is also an error to use a non-Unicode character in symbols or identifiers.

All Scheme implementations must permit the escape sequence \x<hexdigits>; to appear in Scheme identifiers that are enclosed in vertical lines. If the character with the given Unicode scalar value is supported by the implementation, identifiers containing such a sequence are equivalent to identifiers containing the corresponding character.

<token> ⟶<identifier> ∣<boolean> ∣<number> ∣<character> ∣<string>
∣( ∣) ∣#( ∣#u8( ∣'` ∣, ∣,@ ∣.
<delimiter> ⟶<whitespace> ∣<vertical line>
∣( ∣) ∣" ∣;
<intraline whitespace> ⟶<space or tab>
<whitespace> ⟶<intraline whitespace> ∣<line ending>
<vertical line> ⟶|
<line ending> ⟶<newline> ∣<return> <newline>
∣<return>
<comment> ⟶; ⟨all subsequent characters up to a
​ ​line ending⟩   ∣<nested comment>
∣#; <intertoken space> <datum>
<nested comment> ⟶#| <comment text>
<comment cont>* |#
<comment text> ⟶⟨character sequence not containing
​ ​#| or |#
<comment cont> ⟶<nested comment> <comment text>
<directive> ⟶#!fold-case ∣#!no-fold-case
Note that it is ungrammatical to follow a <directive> with anything but a <delimiter> or the end of file.

<atmosphere> ⟶<whitespace> ∣<comment> ∣<directive>
<intertoken space> ⟶<atmosphere>*

Note that +i, -i and <infnan> below are exceptions to the <peculiar identifier> rule; they are parsed as numbers, not identifiers.

<identifier> ⟶<initial> <subsequent>*
∣<vertical line> <symbol element>* <vertical line>
∣<peculiar identifier>
<initial> ⟶<letter> ∣<special initial>
<letter> ⟶a ∣b ∣c ∣... ∣z
∣A ∣B ∣C ∣... ∣Z
<special initial> ⟶! ∣$ ∣% ∣& ∣* ∣/ ∣: ∣< ∣=
∣> ∣? ∣@ ∣^_~
<subsequent> ⟶<initial> ∣<digit>
∣<special subsequent>
<digit> ⟶0 ∣1 ∣2 ∣3 ∣4 ∣5 ∣6 ∣7 ∣8 ∣9
<hex digit> ⟶<digit> ∣a ∣b ∣c ∣d ∣e ∣f
<explicit sign> ⟶+ ∣-
<special subsequent> ⟶<explicit sign> ∣. ∣@
<inline hex escape> ⟶\x<hex scalar value>;
<hex scalar value> ⟶<hex digit>+
<mnemonic escape> ⟶\a ∣\b ∣\t ∣\n ∣\r
<peculiar identifier> ⟶<explicit sign>
∣<explicit sign> <sign subsequent> <subsequent>*
∣<explicit sign> . <dot subsequent> <subsequent>*
∣. <dot subsequent> <subsequent>*
<dot subsequent> ⟶<sign subsequent> ∣.
<sign subsequent> ⟶<initial> ∣<explicit sign> ∣@
<symbol element> ⟶ <any character other than <vertical line> or \>
∣<inline hex escape> ∣<mnemonic escape> ∣\|
<boolean> ⟶#t#f#true#false

<character> ⟶#\ <any character>
∣#\ <character name>
∣#\x<hex scalar value>
<character name> ⟶alarm ∣backspace ∣delete
∣escape ∣newline ∣null ∣return ∣space ∣tab

<string> ⟶" <string element>* "
<string element> ⟶<any character other than " or \>
∣<mnemonic escape> ∣\"\\\|
\<intraline whitespace>*<line ending>
   <intraline whitespace>*
∣<inline hex escape>
<bytevector> ⟶#u8(<byte>*)
<byte> ⟶<any exact integer between 0 and 255>

<number> ⟶<num 2> ∣<num 8>
∣<num 10> ∣<num 16>
The following rules for <num R>, <complex R>, <real R>, <ureal R>, <uinteger R>, and <prefix R> are implicitly replicated for R = 2, 8, 10, and 16. There are no rules for <decimal 2>, <decimal 8>, and <decimal 16>, which means that numbers containing decimal points or exponents are always in decimal radix. Although not shown below, all alphabetic characters used in the grammar of numbers can appear in either upper or lower case. <num R> ⟶<prefix R> <complex R>
<complex R> ⟶<real R> ∣<real R> @ <real R>
∣<real R> + <ureal R> i ∣<real R> - <ureal R> i
∣<real R> + i ∣<real R> - i ∣<real R> <infnan> i
∣+ <ureal R> i ∣- <ureal R> i
∣<infnan> i ∣+ i ∣- i
<real R> ⟶<sign> <ureal R>
∣<infnan>
<ureal R> ⟶<uinteger R>
∣<uinteger R> / <uinteger R>
∣<decimal R>
<decimal 10> ⟶<uinteger 10> <suffix>
∣. <digit 10>+ <suffix>
∣<digit 10>+ . <digit 10>* <suffix>
<uinteger R> ⟶<digit R>+
<prefix R> ⟶<radix R> <exactness>
∣<exactness> <radix R>
<infnan> ⟶+inf.0 ∣-inf.0 ∣+nan.0 ∣-nan.0
<suffix> ⟶<empty>
∣<exponent marker> <sign> <digit 10>+
<exponent marker> ⟶e
<sign> ⟶<empty> ∣+ ∣-
<exactness> ⟶<empty> ∣#i∣#e<radix 2> ⟶#b<radix 8> ⟶#o<radix 10> ⟶<empty> ∣#d
<radix 16> ⟶#x<digit 2> ⟶0 ∣1
<digit 8> ⟶0 ∣1 ∣2 ∣3 ∣4 ∣5 ∣6 ∣7
<digit 10> ⟶<digit>
<digit 16> ⟶<digit 10> ∣a ∣b ∣c ∣d ∣e ∣f

7.1.2  External representations

<Datum> is what the read procedure (section 6.13.2) successfully parses. Note that any string that parses as an <expression> will also parse as a <datum>.

<datum> ⟶<simple datum> ∣<compound datum>
∣<label> = <datum> ∣<label> #
<simple datum> ⟶<boolean> ∣<number>
∣<character> ∣<string> ∣<symbol> ∣<bytevector>
<symbol> ⟶<identifier>
<compound datum> ⟶<list> ∣<vector> ∣<abbreviation>
<list> ⟶(<datum>*) ∣(<datum>+ .​ ​<datum>)
<abbreviation> ⟶<abbrev prefix> <datum>
<abbrev prefix> ⟶' ∣` ∣, ∣,@
<vector> ⟶#(<datum>*)
<label> ⟶# <uinteger 10>

7.1.3  Expressions

The definitions in this and the following subsections assume that all the syntax keywords defined in this report have been properly imported from their libraries, and that none of them have been redefined or shadowed.

<expression> ⟶<identifier>
∣<literal>
∣<procedure call>
∣<lambda expression>
∣<conditional>
∣<assignment>
∣<derived expression>
∣<macro use>
∣<macro block>
∣<includer>
<literal> ⟶<quotation> ∣<self-evaluating>
<self-evaluating> ⟶<boolean> ∣<number> ∣<vector>
∣<character> ∣<string> ∣<bytevector>
<quotation> ⟶'<datum> ∣(quote <datum>)
<procedure call> ⟶(<operator> <operand>*)
<operator> ⟶<expression>
<operand> ⟶<expression>
<lambda expression> ⟶(lambda <formals> <body>)
<formals> ⟶(<identifier>*) ∣<identifier>
∣(<identifier>+ .​ ​<identifier>)
<body> ⟶<definition>* <sequence>
<sequence> ⟶<command>* <expression>
<command> ⟶<expression>
<conditional> ⟶(if <test> <consequent> <alternate>)
<test> ⟶<expression>
<consequent> ⟶<expression>
<alternate> ⟶<expression> ∣<empty>
<assignment> ⟶(set! <identifier> <expression>)
<derived expression> ⟶    (cond <cond clause>+)
∣(cond <cond clause>* (else <sequence>))
∣(case <expression>
   <case clause>+)
∣(case <expression>
   <case clause>*
   (else <sequence>))
∣(case <expression>
   <case clause>*
   (else => <recipient>))
∣(and <test>*)
∣(or <test>*)
∣(when <test> <sequence>)
∣(unless <test> <sequence>)
∣(let (<binding spec>*) <body>)
∣(let <identifier> (<binding spec>*) <body>)
∣(let* (<binding spec>*) <body>)
∣(letrec (<binding spec>*) <body>)
∣(letrec* (<binding spec>*) <body>)
∣(let-values (<mv binding spec>*) <body>)
∣(let*-values (<mv binding spec>*) <body>)
∣(begin <sequence>)
∣(do (<iteration spec>*)
      (<test> <do result>)
   <command>*)
∣(delay <expression>)
∣(delay-force <expression>)
∣(parameterize ((<expression> <expression>)*)
   <body>)
∣(guard (<identifier> <cond clause>*) <body>)
∣<quasiquotation>
∣(case-lambda <case-lambda clause>*)
<cond clause> ⟶(<test> <sequence>)
∣(<test>)
∣(<test> => <recipient>)
<recipient> ⟶<expression>
<case clause> ⟶((<datum>*) <sequence>)
∣((<datum>*) => <recipient>)
<binding spec> ⟶(<identifier> <expression>)
<mv binding spec> ⟶(<formals> <expression>)
<iteration spec> ⟶(<identifier> <init> <step>)
∣(<identifier> <init>)
<case-lambda clause> ⟶(<formals> <body>)
<init> ⟶<expression>
<step> ⟶<expression>
<do result> ⟶<sequence> ∣<empty>
<macro use> ⟶(<keyword> <datum>*)
<keyword> ⟶<identifier>
<macro block> ⟶ (let-syntax (<syntax spec>*) <body>)
∣(letrec-syntax (<syntax spec>*) <body>)
<syntax spec> ⟶(<keyword> <transformer spec>)
<includer> ⟶ ∣(include <string>+)
∣(include-ci <string>+)

7.1.4  Quasiquotations

The following grammar for quasiquote expressions is not context-free. It is presented as a recipe for generating an infinite number of production rules. Imagine a copy of the following rules for D = 1, 2, 3, …, where D is the nesting depth.

<quasiquotation> ⟶<quasiquotation 1>
<qq template 0> ⟶<expression>
<quasiquotation D> ⟶`<qq template D>
∣(quasiquote <qq template D>)
<qq template D> ⟶<simple datum>
∣<list qq template D>
∣<vector qq template D>
∣<unquotation D>
<list qq template D> ⟶(<qq template or splice D>*)
∣(<qq template or splice D>+ .​ ​<qq template D>)
∣'<qq template D>
∣<quasiquotation D + 1>
<vector qq template D> ⟶#(<qq template or splice D>*)
<unquotation D> ⟶,<qq template D−1>
∣(unquote <qq template D−1>)
<qq template or splice D> ⟶<qq template D>
∣<splicing unquotation D>
<splicing unquotation D> ⟶,@<qq template D−1>
∣(unquote-splicing <qq template D−1>)
In <quasiquotation>s, a <list qq template D> can sometimes be confused with either an <unquotation D> or a <splicing unquotation D>. The interpretation as an <unquotation> or <splicing unquotation D> takes precedence.

7.1.5  Transformers

Note: Though this grammar does not say so, a top-level syntax-rules pattern must be a list pattern, not a vector pattern or an identifier pattern.
<transformer spec> ⟶ (syntax-rules (<identifier>*) <syntax rule>*)
∣(syntax-rules <identifier> (<identifier>*)
   ​ ​​ ​<syntax rule>*)
<syntax rule> ⟶(<pattern> <template>)
<pattern> ⟶<pattern identifier>
∣<underscore>
∣(<pattern>*)
∣(<pattern>+ . <pattern>)
∣(<pattern>* <pattern> <ellipsis> <pattern>*)
∣(<pattern>* <pattern> <ellipsis> <pattern>*
   ​ ​​ ​. <pattern>)
∣#(<pattern>*)
∣#(<pattern>* <pattern> <ellipsis> <pattern>*)
∣<pattern datum>
<pattern datum> ⟶<string>
∣<character>
∣<boolean>
∣<number>
∣<bytevector>
<template> ⟶<pattern identifier>
∣(<template element>*)
∣(<template element>+ .​ ​<template>)
∣#(<template element>*)
∣<template datum>
<template element> ⟶<template>
∣<template> <ellipsis>
<template datum> ⟶<pattern datum>
<pattern identifier> ⟶<any identifier except ...>
<ellipsis> ⟶<an identifier defaulting to ...>
<underscore> ⟶<the identifier _>

7.1.6  Programs and definitions

<program> ⟶ <import declaration>+
<command or definition>+
<command or definition> ⟶<command>
∣<definition>
∣(begin <command or definition>+)
<definition> ⟶(define <identifier> <expression>)
∣(define (<identifier> <def formals>) <body>)
∣<syntax definition>
∣(define-values <formals> <body>)
∣(define-record-type <identifier>
   ​ ​​ ​<constructor> <identifier> <field spec>*)
∣(begin <definition>*)
<def formals> ⟶<identifier>*
∣<identifier>* .​ ​<identifier>
<constructor> ⟶(<identifier> <field name>*)
<field spec> ⟶(<field name> <accessor>)
∣(<field name> <accessor> <mutator>)
<field name> ⟶<identifier>
<accessor> ⟶<identifier>
<mutator> ⟶<identifier>
<syntax definition> ⟶ (define-syntax <keyword> <transformer spec>)

7.1.7  Libraries

<library> ⟶ (define-library <library name>
   <library declaration>*)
<library name> ⟶(<library name part>+)
<library name part> ⟶<identifier> ∣<uinteger 10>
<library declaration> ⟶(export <export spec>*)
∣<import declaration>
∣(begin <command or definition>*)
∣<includer>
∣(include-library-declarations <string>+)
∣(cond-expand <cond-expand clause>+)
∣(cond-expand <cond-expand clause>+
0     ​ ​(else <library declaration>*))
<import declaration> ⟶(import <import set>+)
<export spec> ⟶<identifier>
∣(rename <identifier> <identifier>)
<import set> ⟶<library name>
∣(only <import set> <identifier>+)
∣(except <import set> <identifier>+)
∣(prefix <import set> <identifier>)
∣(rename <import set> (<identifier> <identifier>)+)
<cond-expand clause> ⟶ (<feature requirement> <library declaration>*)
<feature requirement> ⟶<identifier>
∣(library <library name>)
∣(and <feature requirement>*)
∣(or <feature requirement>*)
∣(not <feature requirement>)

7.2  Formal semantics

This section provides a formal denotational semantics for the primitive expressions of Scheme and selected built-in procedures. The concepts and notation used here are described in [36]; the definition of dynamic-wind is taken from [39]. The notation is summarized below:

[r7rs-Z-G-1.png]

The reason that expression continuations take sequences of values instead of single values is to simplify the formal treatment of procedure calls and multiple return values.

The boolean flag associated with pairs, vectors, and strings will be true for mutable objects and false for immutable objects.

The order of evaluation within a call is unspecified. We mimic that here by applying arbitrary permutations permute and unpermute, which must be inverses, to the arguments in a call before and after they are evaluated. This is not quite right since it suggests, incorrectly, that the order of evaluation is constant throughout a program (for any given number of arguments), but it is a closer approximation to the intended semantics than a left-to-right evaluation would be.

The storage allocator new is implementation-dependent, but it must obey the following axiom: if new σ L, then σ (new σ ∣ L)↓2 = false.

The definition of calK is omitted because an accurate definition of calK would complicate the semantics without being very interesting.

If P is a program in which all variables are defined before being referenced or assigned, then the meaning of P is

calE
[ [
((lambda (I*) P’) <undefined> …)
] ]

where I* is the sequence of variables defined in P, P′ is the sequence of expressions obtained by replacing every definition in P by an assignment, <undefined> is an expression that evaluates to undefined, and calE is the semantic function that assigns meaning to expressions.

7.2.1  Abstract syntax

[r7rs-Z-G-2.png]

[r7rs-Z-G-3.png]

7.2.2  Domain equations

[r7rs-Z-G-4.png]

7.2.3  Semantic functions

[r7rs-Z-G-5.png]

Definition of calK deliberately omitted.

[r7rs-Z-G-6.png]

[r7rs-Z-G-7.png]

[r7rs-Z-G-8.png]

[r7rs-Z-G-9.png]

[r7rs-Z-G-10.png]

[r7rs-Z-G-11.png]

[r7rs-Z-G-12.png]

[r7rs-Z-G-13.png]

Here and elsewhere, any expressed value other than undefined may be used in place of unspecified.

[r7rs-Z-G-14.png]

[r7rs-Z-G-15.png]

[r7rs-Z-G-16.png]

[r7rs-Z-G-17.png]

[r7rs-Z-G-18.png]

7.2.4  Auxiliary functions

[r7rs-Z-G-19.png]

[r7rs-Z-G-20.png]

[r7rs-Z-G-21.png]

[r7rs-Z-G-22.png]

[r7rs-Z-G-23.png]

[r7rs-Z-G-24.png]

[r7rs-Z-G-25.png]

[r7rs-Z-G-26.png]

[r7rs-Z-G-27.png]

[r7rs-Z-G-28.png]

[r7rs-Z-G-29.png]

[r7rs-Z-G-30.png]

[r7rs-Z-G-31.png]

[r7rs-Z-G-32.png]

[r7rs-Z-G-33.png]

[r7rs-Z-G-34.png]

[r7rs-Z-G-35.png]

[r7rs-Z-G-36.png]

[r7rs-Z-G-37.png]

[r7rs-Z-G-38.png]

[r7rs-Z-G-39.png]

[r7rs-Z-G-40.png]

[r7rs-Z-G-41.png]

[r7rs-Z-G-42.png]

[r7rs-Z-G-43.png]

[r7rs-Z-G-44.png]

[r7rs-Z-G-45.png]

[r7rs-Z-G-46.png]

[r7rs-Z-G-47.png]

[r7rs-Z-G-48.png]

[r7rs-Z-G-49.png]

[r7rs-Z-G-50.png]

[r7rs-Z-G-51.png]

[r7rs-Z-G-52.png]

[r7rs-Z-G-53.png]

[r7rs-Z-G-54.png]

[r7rs-Z-G-55.png]

[r7rs-Z-G-56.png]

[r7rs-Z-G-57.png]

[r7rs-Z-G-58.png]

[r7rs-Z-G-59.png]

[r7rs-Z-G-60.png]

[r7rs-Z-G-61.png]

7.3  Derived expression types

This section gives syntax definitions for the derived expression types in terms of the primitive expression types (literal, variable, call, lambda, if, and set!), except for quasiquote.

Conditional derived syntax types:

(define-syntax cond
  (syntax-rules (else =>)
    ((cond (else result1 result2 ...))
     (begin result1 result2 ...))
    ((cond (test => result))
     (let ((temp test))
       (if temp (result temp))))
    ((cond (test => result) clause1 clause2 ...)
     (let ((temp test))
       (if temp
           (result temp)
           (cond clause1 clause2 ...))))
    ((cond (test)) test)
    ((cond (test) clause1 clause2 ...)
     (let ((temp test))
       (if temp
           temp
           (cond clause1 clause2 ...))))
    ((cond (test result1 result2 ...))
     (if test (begin result1 result2 ...)))
    ((cond (test result1 result2 ...)
           clause1 clause2 ...)
     (if test
         (begin result1 result2 ...)
         (cond clause1 clause2 ...)))))
(define-syntax case
  (syntax-rules (else =>)
    ((case (key ...)
       clauses ...)
     (let ((atom-key (key ...)))
       (case atom-key clauses ...)))
    ((case key
       (else => result))
     (result key))
    ((case key
       (else result1 result2 ...))
     (begin result1 result2 ...))
    ((case key
       ((atoms ...) => result))
     (if (memv key '(atoms ...))
         (result key)))
    ((case key
       ((atoms ...) result1 result2 ...))
     (if (memv key '(atoms ...))
         (begin result1 result2 ...)))
    ((case key
       ((atoms ...) => result)
       clause clauses ...)
     (if (memv key '(atoms ...))
         (result key)
         (case key clause clauses ...)))
    ((case key
       ((atoms ...) result1 result2 ...)
       clause clauses ...)
     (if (memv key '(atoms ...))
         (begin result1 result2 ...)
         (case key clause clauses ...)))))
(define-syntax and
  (syntax-rules ()
    ((and) #t)
    ((and test) test)
    ((and test1 test2 ...)
     (if test1 (and test2 ...) #f))))
(define-syntax or
  (syntax-rules ()
    ((or) #f)
    ((or test) test)
    ((or test1 test2 ...)
     (let ((x test1))
       (if x x (or test2 ...))))))
(define-syntax when
  (syntax-rules ()
    ((when test result1 result2 ...)
     (if test
         (begin result1 result2 ...)))))
(define-syntax unless
  (syntax-rules ()
    ((unless test result1 result2 ...)
     (if (not test)
         (begin result1 result2 ...)))))
Binding constructs:

(define-syntax let
  (syntax-rules ()
    ((let ((name val) ...) body1 body2 ...)
     ((lambda (name ...) body1 body2 ...)
      val ...))
    ((let tag ((name val) ...) body1 body2 ...)
     ((letrec ((tag (lambda (name ...)
                      body1 body2 ...)))
        tag)
      val ...))))
(define-syntax let*
  (syntax-rules ()
    ((let* () body1 body2 ...)
     (let () body1 body2 ...))
    ((let* ((name1 val1) (name2 val2) ...)
       body1 body2 ...)
     (let ((name1 val1))
       (let* ((name2 val2) ...)
         body1 body2 ...)))))
The following letrec macro uses the symbol <undefined> in place of an expression which returns something that when stored in a location makes it an error to try to obtain the value stored in the location. (No such expression is defined in Scheme.) A trick is used to generate the temporary names needed to avoid specifying the order in which the values are evaluated. This could also be accomplished by using an auxiliary macro.

(define-syntax letrec
  (syntax-rules ()
    ((letrec ((var1 init1) ...) body ...)
     (letrec "generate_temp_names"
       (var1 ...)
       ()
       ((var1 init1) ...)
       body ...))
    ((letrec "generate_temp_names"
       ()
       (temp1 ...)
       ((var1 init1) ...)
       body ...)
     (let ((var1 <undefined>) ...)
       (let ((temp1 init1) ...)
         (set! var1 temp1)
         ...
         body ...)))
    ((letrec "generate_temp_names"
       (x y ...)
       (temp ...)
       ((var1 init1) ...)
       body ...)
     (letrec "generate_temp_names"
       (y ...)
       (newtemp temp ...)
       ((var1 init1) ...)
       body ...))))
(define-syntax letrec*
  (syntax-rules ()
    ((letrec* ((var1 init1) ...) body1 body2 ...)
     (let ((var1 <undefined>) ...)
       (set! var1 init1)
       ...
       (let () body1 body2 ...)))))
(define-syntax let-values
  (syntax-rules ()
    ((let-values (binding ...) body0 body1 ...)
     (let-values "bind"
         (binding ...) () (begin body0 body1 ...)))
    
    ((let-values "bind" () tmps body)
     (let tmps body))
    
    ((let-values "bind" ((b0 e0)
         binding ...) tmps body)
     (let-values "mktmp" b0 e0 ()
         (binding ...) tmps body))
    
    ((let-values "mktmp" () e0 args
         bindings tmps body)
     (call-with-values 
       (lambda () e0)
       (lambda args
         (let-values "bind"
             bindings tmps body))))
    
    ((let-values "mktmp" (a . b) e0 (arg ...)
         bindings (tmp ...) body)
     (let-values "mktmp" b e0 (arg ... x)
         bindings (tmp ... (a x)) body))
    
    ((let-values "mktmp" a e0 (arg ...)
        bindings (tmp ...) body)
     (call-with-values
       (lambda () e0)
       (lambda (arg ... . x)
         (let-values "bind"
             bindings (tmp ... (a x)) body))))))
(define-syntax let*-values
  (syntax-rules ()
    ((let*-values () body0 body1 ...)
     (let () body0 body1 ...))

    ((let*-values (binding0 binding1 ...)
         body0 body1 ...)
     (let-values (binding0)
       (let*-values (binding1 ...)
         body0 body1 ...)))))
(define-syntax define-values
  (syntax-rules ()
    ((define-values () expr)
     (define dummy
       (call-with-values (lambda () expr)
                         (lambda args #f))))
    ((define-values (var) expr)
     (define var expr))
    ((define-values (var0 var1 ... varn) expr)
     (begin
       (define var0
         (call-with-values (lambda () expr)
                           list))
       (define var1
         (let ((v (cadr var0)))
           (set-cdr! var0 (cddr var0))
           v)) ...
       (define varn
         (let ((v (cadr var0)))
           (set! var0 (car var0))
           v))))
    ((define-values (var0 var1 ... . varn) expr)
     (begin
       (define var0
         (call-with-values (lambda () expr)
                           list))
       (define var1
         (let ((v (cadr var0)))
           (set-cdr! var0 (cddr var0))
           v)) ...
       (define varn
         (let ((v (cdr var0)))
           (set! var0 (car var0))
           v))))
    ((define-values var expr)
     (define var
       (call-with-values (lambda () expr)
                         list)))))
(define-syntax begin
  (syntax-rules ()
    ((begin exp ...)
     ((lambda () exp ...)))))
The following alternative expansion for begin does not make use of the ability to write more than one expression in the body of a lambda expression. In any case, note that these rules apply only if the body of the begin contains no definitions.

(define-syntax begin
  (syntax-rules ()
    ((begin exp)
     exp)
    ((begin exp1 exp2 ...)
     (call-with-values
         (lambda () exp1)
       (lambda args
         (begin exp2 ...))))))
The following syntax definition of do uses a trick to expand the variable clauses. As with letrec above, an auxiliary macro would also work. The expression (if #f #f) is used to obtain an unspecific value.

(define-syntax do
  (syntax-rules ()
    ((do ((var init step ...) ...)
         (test expr ...)
         command ...)
     (letrec
       ((loop
         (lambda (var ...)
           (if test
               (begin
                 (if #f #f)
                 expr ...)
               (begin
                 command
                 ...
                 (loop (do "step" var step ...)
                       ...))))))
       (loop init ...)))
    ((do "step" x)
     x)
    ((do "step" x y)
     y)))
Here is a possible implementation of delay, force and delay-force. We define the expression

(delay-force <expression>) to have the same meaning as the procedure call

(make-promise #f (lambda () <expression>)) as follows

(define-syntax delay-force
  (syntax-rules ()
    ((delay-force expression) 
     (make-promise #f (lambda () expression)))))
and we define the expression

(delay <expression>) to have the same meaning as:

(delay-force (make-promise #t <expression>)) as follows

(define-syntax delay
  (syntax-rules ()
    ((delay expression)
     (delay-force (make-promise #t expression)))))
where make-promise is defined as follows:

(define make-promise
  (lambda (done? proc)
    (list (cons done? proc))))
Finally, we define force to call the procedure expressions in promises iteratively using a trampoline technique following [38] until a non-lazy result (i.e. a value created by delay instead of delay-force) is returned, as follows:

(define (force promise)
  (if (promise-done? promise)
      (promise-value promise)
      (let ((promise* ((promise-value promise))))
        (unless (promise-done? promise)
          (promise-update! promise* promise))
        (force promise))))
with the following promise accessors:

(define promise-done?
  (lambda (x) (car (car x))))
(define promise-value
  (lambda (x) (cdr (car x))))
(define promise-update!
  (lambda (new old)
    (set-car! (car old) (promise-done? new))
    (set-cdr! (car old) (promise-value new))
    (set-car! new (car old))))
The following implementation of make-parameter and parameterize is suitable for an implementation with no threads. Parameter objects are implemented here as procedures, using two arbitrary unique objects <param-set!> and <param-convert>:

(define (make-parameter init . o)
  (let* ((converter
          (if (pair? o) (car o) (lambda (x) x)))
         (value (converter init)))
    (lambda args
      (cond
       ((null? args)
        value)
       ((eq? (car args) <param-set!>)
        (set! value (cadr args)))
       ((eq? (car args) <param-convert>)
        converter)
       (else
        (error "bad parameter syntax"))))))
Then parameterize uses dynamic-wind to dynamically rebind the associated value:

(define-syntax parameterize
  (syntax-rules ()
    ((parameterize ("step")
                   ((param value p old new) ...)
                   ()
                   body)
     (let ((p param) ...)
       (let ((old (p)) ...
             (new ((p <param-convert>) value)) ...)
         (dynamic-wind
          (lambda () (p <param-set!> new) ...)
          (lambda () . body)
          (lambda () (p <param-set!> old) ...)))))
    ((parameterize ("step")
                   args
                   ((param value) . rest)
                   body)
     (parameterize ("step")
                   ((param value p old new) . args)
                   rest
                   body))
    ((parameterize ((param value) ...) . body)
     (parameterize ("step")
                   ()
                   ((param value) ...)
                   body))))
The following implementation of guard depends on an auxiliary macro, here called guard-aux.

(define-syntax guard
  (syntax-rules ()
    ((guard (var clause ...) e1 e2 ...)
     ((call/cc
       (lambda (guard-k)
         (with-exception-handler
          (lambda (condition)
            ((call/cc
               (lambda (handler-k)
                 (guard-k
                  (lambda ()
                    (let ((var condition))
                      (guard-aux
                        (handler-k
                          (lambda ()
                            (raise-continuable condition)))
                        clause ...))))))))
          (lambda ()
            (call-with-values
             (lambda () e1 e2 ...)
             (lambda args
               (guard-k
                 (lambda ()
                   (apply values args)))))))))))))

(define-syntax guard-aux
  (syntax-rules (else =>)
    ((guard-aux reraise (else result1 result2 ...))
     (begin result1 result2 ...))
    ((guard-aux reraise (test => result))
     (let ((temp test))
       (if temp 
           (result temp)
           reraise)))
    ((guard-aux reraise (test => result)
                clause1 clause2 ...)
     (let ((temp test))
       (if temp
           (result temp)
           (guard-aux reraise clause1 clause2 ...))))
    ((guard-aux reraise (test))
     (or test reraise))
    ((guard-aux reraise (test) clause1 clause2 ...)
     (let ((temp test))
       (if temp
           temp
           (guard-aux reraise clause1 clause2 ...))))
    ((guard-aux reraise (test result1 result2 ...))
     (if test
         (begin result1 result2 ...)
         reraise))
    ((guard-aux reraise
                (test result1 result2 ...)
                clause1 clause2 ...)
     (if test
         (begin result1 result2 ...)
         (guard-aux reraise clause1 clause2 ...)))))
(define-syntax case-lambda
  (syntax-rules ()
    ((case-lambda (params body0 ...) ...)
     (lambda args
       (let ((len (length args)))
         (letrec-syntax
             ((cl (syntax-rules ::: ()
                    ((cl)
                     (error "no matching clause"))
                    ((cl ((p :::) . body) . rest)
                     (if (= len (length '(p :::)))
                         (apply (lambda (p :::)
                                  . body)
                                args)
                         (cl . rest)))
                    ((cl ((p ::: . tail) . body)
                         . rest)
                     (if (>= len (length '(p :::)))
                         (apply
                          (lambda (p ::: . tail)
                            . body)
                          args)
                         (cl . rest))))))
           (cl (params body0 ...) ...)))))))

This definition of cond-expand does not interact with the features procedure. It requires that each feature identifier provided by the implementation be explicitly mentioned.

(define-syntax cond-expand
  ;; Extend this to mention all feature ids and libraries
  (syntax-rules (and or not else r7rs library scheme base)
    ((cond-expand)
     (syntax-error "Unfulfilled cond-expand"))
    ((cond-expand (else body ...))
     (begin body ...))
    ((cond-expand ((and) body ...) more-clauses ...)
     (begin body ...))
    ((cond-expand ((and req1 req2 ...) body ...)
                  more-clauses ...)
     (cond-expand
       (req1
         (cond-expand
           ((and req2 ...) body ...)
           more-clauses ...))
       more-clauses ...))
    ((cond-expand ((or) body ...) more-clauses ...)
     (cond-expand more-clauses ...))
    ((cond-expand ((or req1 req2 ...) body ...)
                  more-clauses ...)
     (cond-expand
       (req1
        (begin body ...))
       (else
        (cond-expand
           ((or req2 ...) body ...)
           more-clauses ...))))
    ((cond-expand ((not req) body ...)
                  more-clauses ...)
     (cond-expand
       (req
         (cond-expand more-clauses ...))
       (else body ...)))
    ((cond-expand (r7rs body ...)
                  more-clauses ...)
       (begin body ...))
    ;; Add clauses here for each
    ;; supported feature identifier.
    ;; Samples:
    ;; ((cond-expand (exact-closed body ...)
    ;;               more-clauses ...)
    ;;   (begin body ...))
    ;; ((cond-expand (ieee-float body ...)
    ;;               more-clauses ...)
    ;;   (begin body ...))
    ((cond-expand ((library (scheme base))
                   body ...)
                  more-clauses ...)
      (begin body ...))
    ;; Add clauses here for each library
    ((cond-expand (feature-id body ...)
                  more-clauses ...)
       (cond-expand more-clauses ...))
    ((cond-expand ((library (name ...))
                   body ...)
                  more-clauses ...)
       (cond-expand more-clauses ...))))