$\newcommand{\unicode}[1]{U{+}\code{#1}}$ $\newcommand{\outcome}{\mlvar{outcome}}$ $\DeclareMathOperator{\lex}{lex}$ $\DeclareMathOperator{\pat}{pat}$ $\DeclareMathOperator{\spread}{spread}$ $\DeclareMathOperator{\serialform}{serial-form}$ $\DeclareMathOperator{\iftestform}{if-test-form}$ $\DeclareMathOperator{\foreachfunctionform}{\_for-each-function-form}$ $\DeclareMathOperator{\foreachlistform}{\_for-each-list-form}$ $\DeclareMathOperator{\foreachinvocation}{\_for-each-invocation}$ $\DeclareMathOperator{\setvalueform}{set-value-form}$ $\DeclareMathOperator{\blockserialforms}{block-serial-forms}$ $\DeclareMathOperator{\returnfromvaluesform}{return-from-values-form}$ $\DeclareMathOperator{\catchexittagform}{catch-exit-tag-form}$ $\DeclareMathOperator{\catchserialforms}{catch-serial-forms}$ $\DeclareMathOperator{\throwexittagform}{throw-exit-tag-form}$ $\DeclareMathOperator{\throwvaluesform}{throw-values-form}$ $\DeclareMathOperator{\handlerbindhandlerform}{\_handler-bind-handler-form}$ $\DeclareMathOperator{\handlerbindserialforms}{\_handler-bind-serial-forms}$ $\DeclareMathOperator{\handlerbindinvocation}{\_handler-bind-invocation}$ $\DeclareMathOperator{\unwindprotectprotectedform}{unwind-protect-protected-form}$ $\DeclareMathOperator{\unwindprotectcleanupforms}{unwind-protect-cleanup-forms}$ $\DeclareMathOperator{\functioncalloperatorform}{function-call-operator-form}$ $\DeclareMathOperator{\functioncalloperandform}{function-call-operand-form}$ $\DeclareMathOperator{\macro}{macro}$ $\DeclareMathOperator{\evalserialforms}{eval-serial-forms}$ $\DeclareMathOperator{\evalserialformforms}{eval-serial-form-forms}$ $\DeclareMathOperator{\foreach}{\_for-each}$ $\DeclareMathOperator{\evaloperandforms}{eval-operand-forms}$ $\DeclareMathOperator{\invoke}{invoke}$

Reference Manual

The reference manual provides a detailed account of the programming language. It supplements and amends the user manual (particularly the sections “Programming Language” and “Listener Buffers”) and the tutorial.

Syntax

Introduction

Listener Buffers

Let us examine what happens when the form (+ 123 456) is evaluated in a listener buffer:

> (+ 123 456)
579

The process can be broken down into the following five steps:

Step 1 The sequence of characters (+ 123 456) is read from the listener buffer.

Step 2 The reader converts the sequence of characters (+ 123 456) into the list (+ 123 456). (The sequence of characters is a readable representation of the list.) This step can be broken down into the following two substeps:

Step 2.1 A component of the reader called the tokenizer converts the sequence of characters (+ 123 456) into a sequence of tokens. A token consists of the following pieces of information bundled together: a category and, if required by the category, a value. Each token category has an associated pattern and each token has an associated lexeme. A lexeme is a sequence of contiguous characters extracted from the input sequence of characters. The lexeme associated with a token must match the pattern associated with the token's category and the sequence of characters resulting from the concatenation of the lexemes associated with the tokens must match the input sequence of characters. The sequence of characters (+ 123 456) is converted into the following sequence of tokens:

Note that some whitespace is needed to separate the lexeme + from the lexeme 123 and the lexeme 123 from the lexeme 456 but no whitespace is needed to separate the lexeme ( from the lexeme + or the lexeme 456 from the lexeme ).

Step 2.2 A component of the reader called the parser converts the sequence of tokens from step 2.1 (minus the tokens of category whitespace, which are ignored by the parser) into a cons whose car is the variable from step 2.1 and whose cdr is a cons whose car is the first number from step 2.1 and whose cdr is a cons whose car is the second number from step 2.1 and whose cdr is the empty list. Together, those three conses represent the list (+ 123 456).

Step 3 The evaluator evaluates the list (+ 123 456) to the number 579. The evaluation of the top-level form (+ 123 456) entails the evaluation of other non-top-level forms. Each form must be analyzed in order to determine how it should be evaluated. The form (+ 123 456) is analyzed as a plain function call. The variable + is treated as an abbreviation for the form (fref +). The form (fref +) is analyzed as an fref form. The forms 123 and 456 are analyzed as self-evaluating objects. Because the global function + is a closure, its invocation entails the evaluation (and thus the analysis) of other forms. The component of the evaluator responsible for analyzing forms is called the form analyzer.

Step 4 The printer converts the number 579 into the sequence of characters 579. (The sequence of characters is the printable representation of the number.)

Step 5 The sequence of characters 579 is written into the listener buffer.

EVLambda has three levels of syntax:

Each level of syntax is described later in its own section.

EVLambda Source Files

The reader is used not only to convert the characters typed into a listener buffer into an object but also to convert the characters contained inside an EVLambda source file into a sequence of objects.

EVLambda source files come in two varieties: the plain EVLambda source files, which only contain EVLambda source code, and the documented EVLambda source files, which contain a mix of EVLambda source code and documentation in XML format.

Here is an example of a plain EVLambda source file:

(fdef fact (n)
(if (= n 0)
1
(* n (fact (- n 1)))))

(test 1 (fact 0))
(test 120 (fact 5))
(test 3628800 (fact 10))

(fdef fib (n)
(if (= n 0)
0
(if (= n 1)
1
(+ (fib (- n 1)) (fib (- n 2))))))

(test 0 (fib 0))
(test 5 (fib 5))
(test 55 (fib 10))

Here is an example of a documented EVLambda source file:

<chapter>
<title>Recursive Functions</title>
<p>...para...</p>
<p>...para...</p>
<section>
<title>Factorial Function</title>
<p>...para...</p>
<p>...para...</p>
(fdef fact (n)
<p>...block...</p>
<p>...block...</p>
(if (= n 0)
1 <comment>...eol...</comment>
(* n (fact (- n 1))))) <comment>...eoll...</comment>

(test 1 (fact 0))
(test 120 (fact 5))
(test 3628800 (fact 10))
</section>
<section>
<title>Fibonacci Sequence</title>
<p>...para...</p>
<p>...para...</p>
(fdef fib (n)
<p>...block...</p>
<p>...block...</p>
(if (= n 0)
0 <comment>...eol...</comment>
(if (= n 1)
1 <comment>...eol...</comment>
(+ (fib (- n 1)) (fib (- n 2)))))) <comment>...eoll...</comment>

(test 0 (fib 0))
(test 5 (fib 5))
(test 55 (fib 10))
</section>
</chapter>

Documented EVLambda source files can be converted to HTML by a component of the programming language called the documentation generator.

Extensible Markup Language (XML)

An extensible markup language (XML) document is a annotated text document. An XML document is divided into two intermingled parts: the character data (the content) and the markup (the annotations). Markup can take many forms. Documented EVLambda source files use the following forms of markup:

start tags (without attributes)
<chapter>, <section>, <title>, <p>, <comment>, …
end tags
</chapter>, </section>, </title>, </p>, </comment>, …
empty-element tags (without attributes)
<br/>, …
comments
<!-- FIXME -->, …
entity references
&lt; (refers to the character <), &gt; (refers to the character >), &amp; (refers to the character &), …
character references (decimal representation)
&#9166; (refers to the character ⏎), …
character references (hexadecimal representation)
&#x23CE; (refers to the character ⏎), …

Many constraints must be satisfied for an XML document to be well-formed. The main well-formedness constraints are noted below.

Well-formedness constraint: Start tags and end tags must appear in pairs. In each pair, the start tag must precede the end tag and both tags must have the same name.

An element is a sequence of characters delimited by a pair of start and end tags or by an empty-element tag. The characters of the delimiting tags or tag belong to the element. The characters that belong to an element but not to its delimiting tags or tag constitute the content of the element. The content of an element delimited by an empty-element tag is empty. The name of an element is the name of its delimiting tags or tag.

Well-formedness constraint: Elements must not overlap. Let $X$ and $Y$ be two distinct elements. One of the following conditions must be true: $X$ precedes $Y$, $Y$ precedes $X$, $X$ is inside the content of $Y$, or $Y$ is inside the content of $X$.

Let $X$ and $Y$ be two elements. If $X$ is inside the content of $Y$ and there does not exist a third element $Z$ such that $X$ is inside the content of $Z$ and $Z$ is inside the content of $Y$, then $X$ is called a child of $Y$.

Let $X$, $Y$, and $Z$ be three elements. If $X$ is a child of $Y$ and $Z$, then $Y$ and $Z$ are the same element. That element is called the parent of $X$.

Not all elements have a parent. An element that has no parent is called a root element.

Well-formedness constraint: There must exist exactly one root element.

Well-formedness constraint: The characters < and & must not appear literally inside character data. They must be escaped using an entity reference or a character reference.

Documented EVLambda source files are structured as follows:

Because the characters < and & can appear inside EVLambda source code, a documented EVLambda source file is not always a well-formed XML document.

Documentation Generator

The documentation generator converts a documented EVLambda source file to HTML in two steps:

Step 1 The characters < and & appearing inside EVLambda source code are escaped and some tags are added to better delimit the code from the surrounding documentation and the comments from the surrounding code. The resulting file is a well-formed XML document.

Step 2 The resulting file from step 1 is converted to HTML by an XSLT stylesheet.

Unicode

The characters contained inside listener buffers and EVLambda source files are Unicode characters. Unicode is a character set containing, as of version 17.0, $159801$ characters. Each Unicode character is uniquely identified by a nonnegative integer called its code point. Code points range from $0$ to $1114111$ in decimal and from 0 to 10FFFF in hexadecimal. (Not all code points are assigned to a character.) The notation $U{+}\mlvar{hex}$ denotes the Unicode character whose code point is represented by the hexadecimal numeral $\mlvar{hex}$. The order on integers directly translates into an order on Unicode characters. With respect to that order, the Unicode character $c_1$ precedes the Unicode character $c_2$ if and only if the code point of $c_1$ is strictly less than the code point of $c_2$. That order can be used to define ranges of Unicode characters.

The range from $0$ to $1114111$ is divided into $17$ planes each containing $65536$ code points. The first plane is called the basic multilingual plane (BMP) and the other planes are called the supplementary planes. Most of the characters in common use in the world are located in the BMP.

An encoding form is a mapping that maps a character to a sequence of $n$-bit words called code units. The following encoding forms are in common use:

An encoding scheme is a mapping that maps a character to a sequence of bytes. (A byte is an $8$-bit word.) The following encoding schemes are in common use:

Contrary to what was said in the user manual, an object of type character represents a UTF-$16$ code unit (instead of a Unicode character) and an object of type string represents an indexed sequence of UTF-$16$ code units (instead of an indexed sequence of Unicode characters).

Each Unicode character has a name (“LATIN CAPITAL LETTER A” for instance) and a set of properties. An important property is the general category. The general category property can take the following values:

LuUppercase_Letteruppercase letters
LlLowercase_Letterlowercase letters
LtTitlecase_Letterdigraphs whose first constituent is an uppercase letter
LCCased_LetterLu, Ll, or Lt
LmModifier_Letternoncombining modifier letters
LoOther_Letterletters from unicase alphabets and ideographs
LLetterLu, Ll, Lt, Lm, or Lo
MnNonspacing_Marknonspacing combining marks (accents, …)
McSpacing_Markspacing combining marks
MeEnclosing_Markenclosing combining marks
MMarkMn, Mc, or Me
NdDecimal_Numberdecimal digits
NlLetter_Numberletterlike numeric characters (Roman numerals, …)
NoOther_Numberother numeric characters (fractions, …)
NNumberNd, Nl, or No
PcConnector_Punctuationconnecting punctuation marks (underscore, …)
PdDash_Punctuationdashlike punctuation marks (hyphen, dashes, …)
PsOpen_Punctuationopening punctuation marks (opening parenthesis, …)
PeClose_Punctuationclosing punctuation marks (closing parenthesis, …)
PiInitial_Punctuationinitial quotation marks
PfFinal_Punctuationfinal quotation marks
PoOther_Punctuationother punctuation marks (period, comma, colon, semicolon, …)
PPunctuationPc, Pd, Ps, Pe, Pi, Pf, or Po
SmMath_Symbolmathematical symbols
ScCurrency_Symbolcurrency symbols
SkModifier_Symbolnoncombining modifier symbols
SoOther_Symbolother symbols (Emojis, …)
SSymbolSm, Sc, Sk, or So
ZsSpace_Separatorspace characters
ZlLine_Separatorline separator character
ZpParagraph_Separatorparagraph separator character
ZSeparatorZs, Zl, or Zp
CcControlC0 and C1 control characters (horizontal tab, line feed, carriage return, …)
CfFormatformat control characters (left-to-right and right-to-left marks, …)
CsSurrogatesurrogate code points
CoPrivate_Useprivate-use characters
CnUnassignednoncharacters and unassigned code points
COtherCc, Cf, Cs, Co, or Cn

Most Unicode characters have associated visual representations called glyphs. For instance, the Unicode character “LATIN CAPITAL LETTER A” ($\unicode{0041}$) has the following associated glyphs (and infinitely more considering all possible variations in font, size, weight, style, etc.):

In general, the association is not between Unicode characters and glyphs but between sequences of Unicode characters and glyphs and it is possible for different sequences of Unicode characters to have the same associated glyphs. For example, the sequence of one Unicode character “LATIN CAPITAL LETTER A WITH DIAERESIS” ($\unicode{00C4}$) and the sequence of two Unicode characters “LATIN CAPITAL LETTER A” ($\unicode{0041}$) “COMBINING DIAERESIS” ($\unicode{0308}$) have the same associated glyphs:

Regular Expressions

The tokenizer uses regular expressions to specify the patterns associated with the token categories.

The following table summarizes the syntax of the regular expressions used in this document:

SyntaxMeaning
'…'literal string (literal single quotes and backslashes must be escaped)
"…"literal string (literal double quotes and backslashes must be escaped)
[…]positive character class (literal carets, hyphens, closing square brackets, and backslashes must be escaped)
[^…]negative character class (literal carets, hyphens, closing square brackets, and backslashes must be escaped)
$\mlvar{char}_1$-$\mlvar{char}_2$range of characters (inside character classes)
$\mlvar{re}_1\mlvar{re}_2$concatenation operation
$\mlvar{re}_1$|$\mlvar{re}_2$union (alternation) operation
$\mlvar{re}_1$-$\mlvar{re}_2$difference operation
$\mlvar{re}$*zero-or-more-times (Kleene star) operation
$\mlvar{re}$+one-or-more-times (Kleene plus) operation
$\mlvar{re}$?zero-or-one-time (optional) operation
$\metavar{name}\Coloneq\mlvar{re}$definition of a named regular expression

Literal strings can contain the following escape sequences:

Escape sequenceMeaning
\\\\the backslash
\'the single quote
\"the double quote
\U{$\mlvar{hex}$}the Unicode character whose code point is represented by the hexadecimal numeral $\mlvar{hex}$

Character classes can contain the following escape sequences:

Escape sequenceMeaning
\\\\the backslash
\^the caret
\-the hyphen
\]the closing square bracket
\U{$\mlvar{hex}$}the Unicode character whose code point is represented by the hexadecimal numeral $\mlvar{hex}$
\C{$\mlvar{cat}$}the Unicode characters whose general categories are $\mlvar{cat}$

The zero-or-more-times, one-or-more-times, and zero-or-one-time operations have precedence over the concatenation operation and the concatenation operation has precedence over the union and difference operations. All operations are left associative. Parenthesis can be added to override those precedence and associativity rules.

References to named regular expressions can be used wherever regular expressions can be used. References to named regular expressions denoting classes of characters can also be used inside character classes. Circular definitions are not allowed.

Except for the parts referencing named regular expressions, regular expressions are typeset in a monospaced typeface. Spaces can be added freely outside literal strings and character classes without modifying the meaning of a regular expression.

Extended Backus-Naur Form (EBNF)

The parser and the form analyzer use a variant of the extended Backus-Naur form (EBNF) notation to define various context-free grammars.

The following table summarizes the syntax of the variant of the EBNF notation used in this document:

SyntaxMeaning
$\mlvar{lhs}$ $\Coloneq$ $\mlvar{rhs}$definition of a production rule
$\metavar{nonterminal}$nonterminal symbol
terminalterminal symbol
$\epsilon$empty sequence of symbols
$\mlvar{rhs}_1$ | … | $\mlvar{rhs}_n$union (alternation) operation
$\mlvar{symbol}$*zero-or-more-times (Kleene star) operation
$\mlvar{symbol}$+one-or-more-times (Kleene plus) operation
$\mlvar{symbol}$?zero-or-one-time (optional) operation
{$\mlvar{rhs}$}group
??special sequence

A left-hand-side ($\mlvar{lhs}$) consists of a nonterminal symbol. A right-hand-side ($\mlvar{rhs}$) consists of a sequence of zero or more nonterminal and/or terminal symbols. A group can be used wherever a symbol can be used. A special sequence is a free-form text specifying a set of terminal symbols.

Tokenizer

The tokenizer converts an input sequence of Unicode characters into a sequence of tokens in two steps. During the first step, the tokenizer converts the input sequence of Unicode characters into a provisional sequence of tokens. During the second step, the tokenizer converts the provisional sequence of tokens into a final sequence of tokens.

Character Classes

Let us first define the following named regular expressions:

$\metavar{valid-char}$ $\Coloneq$ [\C{L}\C{M}\C{N}\C{P}\C{S}\C{Z}\U{0009}-\U{000D}\U{0085}\C{Cf}\C{Co}]
$\metavar{whitespace-char}$ $\Coloneq$ [\U{0009}-\U{000D}\U{0020}\U{0085}\U{200E}\U{200F}\U{2028}\U{2029}]
$\metavar{syntax-char}$ $\Coloneq$ ['`,"()#]
$\metavar{xml-name-char}$ $\Coloneq$ [a-z]

Each of those named regular expressions specifies a class of Unicode characters.

The whitespace characters are the following characters:

In Linux and macOS operating systems, an end of line is represented by an LF character. In Windows operating systems, an end of line is represented by a CR character followed by an LF character.

From the definition of $\metavar{valid-char}$, we can infer that the input sequence of Unicode characters must not contain any of the following characters and code points:

The unassigned code points are actually allowed by the current version of the code.

Tokenization First Step

During the first step, the tokenizer converts the input sequence of Unicode characters into a provisional sequence of tokens of the following categories (patterns are regular expressions):

whitespace
Pattern: $\metavar{whitespace-char}$+
Value: N/A
quote
Pattern: "'"
Value: N/A
quasiquote
Pattern: '`'
Value: N/A
unquote
Pattern: ','
Value: N/A
unquote-splicing
Pattern: ',@'
Value: N/A
string
Pattern: '"' (($\metavar{valid-char}$ - ["\\\\]) | ('\\\\' [\\\\"tnvfr]) | ('\\\\U{' [a-fA-F0-9]+ '}'))* '"'
Value: The backslash plays the role of an escape character. The escape sequences are interpreted as specified in the table below. The value is an object of type string representing the sequence of UTF-16 code units encoding the sequence of Unicode characters delimited by the double quotes (after interpretation of the escape sequences).
opening-parenthesis
Pattern: '('
Value: N/A
closing-parenthesis
Pattern: ')'
Value: N/A
hash-opening-parenthesis
Pattern: '#('
Value: N/A
hash-plus
Pattern: '#+'
Value: N/A
hash-minus
Pattern: '#-'
Value: N/A
void
Pattern: '#v'
Value: The value is the single object of type void.
boolean
Pattern: '#t' | '#f'
Value: If the lexeme matches '#t', then the value is the single object of type boolean representing true. If the lexeme matches '#f', then the value is the single object of type boolean representing false.
hash-string
Pattern: '#' [0-9]* '"' (($\metavar{valid-char}$ - ["\\\\]) | ('\\\\' [\\\\"tnvfr]) | ('\\\\U{' [a-fA-F0-9]+ '}'))* '"'
Value: The backslash plays the role of an escape character. The escape sequences are interpreted as specified in the table below. The value is the sequence of UTF-16 code units encoding the sequence of Unicode characters delimited by the double quotes (after interpretation of the escape sequences). An optional decimal numeral can be provided between the hash and the opening double quote.
xml-start-tag
Pattern: '<' $\metavar{xml-name-char}$+ '>'
Value: N/A
xml-end-tag
Pattern: '</' $\metavar{xml-name-char}$+ '>'
Value: N/A
xml-empty-element-tag
Pattern: '<' $\metavar{xml-name-char}$+ '/>'
Value: N/A
xml-comment
Pattern: '<!--' (($\metavar{valid-char}$ - '-') | ('-' ($\metavar{valid-char}$ - '-')))* '-->'
Value: N/A
proto-token
Pattern: (($\metavar{valid-char}$ - ($\metavar{whitespace-char}$ | $\metavar{syntax-char}$ | '\\\\')) | ('\\\\' [\\\\<]) | ('\\\\U{' [a-fA-F0-9]+ '}'))+
Value: The backslash plays the role of an escape character. The escape sequences are interpreted as specified in the table below. The value is the lexeme after interpretation of the escape sequences.

Escape sequences in lexemes associated with tokens of categories string and hash-string are interpreted as follows:

Escape sequenceMeaning
\\\\the backslash
\"the double quote
\tthe horizontal tab control character
\nthe line feed control character
\vthe vertical tab control character
\fthe form feed control character
\rthe carriage return control character
\U{$\mlvar{hex}$}the Unicode character whose code point is represented by the hexadecimal numeral $\mlvar{hex}$

Escape sequences in lexemes associated with tokens of category proto-token are interpreted as follows:

Escape sequenceMeaning
\\\\the backslash
\<the less-than sign
\U{$\mlvar{hex}$}the Unicode character whose code point is represented by the hexadecimal numeral $\mlvar{hex}$

Let $\mlvar{input}$ be the input sequence of Unicode characters. For any token $T$, let us denote by $\lex(T)$ the lexeme associated with $T$ and by $\pat(T)$ the pattern associated with $T$'s category. The tokenizer must find a sequence of tokens $\langle T_1,\ldots,T_n\rangle$ such that the following conditions are satisfied:

Because the meaning of a program cannot be ambiguous, there cannot exist more than one sequence of tokens satisfying the previous conditions for any given input. As the following examples demonstrate, the patterns alone do not provide this guarantee:

The tokenizer uses additional rules to resolve the ambiguities. Those additional rules are embedded into the algorithm provided below.

EVLambda source code can only be found outside any XML element (this is the case in listener buffers and plain EVLambda source files) or directly inside a chapter or section XML element (this is the case in documented EVLambda source files). A context that cannot contain EVLambda source code is called a pure-xml context. When processing a pure-xml context, the tokenizer only recognizes tokens of the following categories: whitespace (any character data is treated as whitespace when processing a pure-xml context), xml-start-tag, xml-end-tag, xml-empty-element-tag, and xml-comment. The tokenizer uses a stack of XML element names to determine if it is processing a pure-xml context. The tokenizer is processing a pure-xml context when the stack is not empty and the name at the top of the stack is neither chapter nor section.

Here is the algorithm used by the tokenizer to convert the input sequence of Unicode characters into a provisional sequence of tokens (control normally flows from one step to the next and it is assumed that the stack of XML element names is initially empty):

Tokenization Second Step

During the second step, the tokenizer converts the provisional sequence of tokens into a final sequence of tokens as follows:

Ninjas

This section illustrates the use of the hash-string construct.

The Unicode character “NINJA” ($\unicode{1F977}$, high-surrogate $\unicode{D83E}$, low-surrogate $\unicode{DD77}$) represents a ninja with a nonrealistic skin tone:

> '(#"🥷")
(#"\U{D83E}" #"\U{DD77}")

> #0"🥷"
#"\U{D83E}"

> #1"🥷"
#"\U{DD77}"

It is possible to obtain a ninja with a realistic skin tone by combining the Unicode character "NINJA" with one of the following skin-tone modifiers:

NameCode PointHigh-SurrogateLow-SurrogateSample
EMOJI MODIFIER FITZPATRICK TYPE-1-2$\unicode{1F3FB}$$\unicode{D83C}$$\unicode{DFFB}$🏻
EMOJI MODIFIER FITZPATRICK TYPE-3$\unicode{1F3FC}$$\unicode{D83C}$$\unicode{DFFC}$🏼
EMOJI MODIFIER FITZPATRICK TYPE-4$\unicode{1F3FD}$$\unicode{D83C}$$\unicode{DFFD}$🏽
EMOJI MODIFIER FITZPATRICK TYPE-5$\unicode{1F3FE}$$\unicode{D83C}$$\unicode{DFFE}$🏾
EMOJI MODIFIER FITZPATRICK TYPE-6$\unicode{1F3FF}$$\unicode{D83C}$$\unicode{DFFF}$🏿

Here is the result of combining the Unicode character “NINJA” with the different skin-tone modifiers:

> '(#"🥷🏻")
(#"\U{D83E}" #"\U{DD77}" #"\U{D83C}" #"\U{DFFB}")

> '(#"🥷🏼")
(#"\U{D83E}" #"\U{DD77}" #"\U{D83C}" #"\U{DFFC}")

> '(#"🥷🏽")
(#"\U{D83E}" #"\U{DD77}" #"\U{D83C}" #"\U{DFFD}")

> '(#"🥷🏾")
(#"\U{D83E}" #"\U{DD77}" #"\U{D83C}" #"\U{DFFE}")

> '(#"🥷🏿")
(#"\U{D83E}" #"\U{DD77}" #"\U{D83C}" #"\U{DFFF}")

Parser

The parser uses a context-free grammar to convert the sequence of tokens produced by the tokenizer into a sequence of objects. The conversion is conceptually a two-step process. During the first step, the parser converts the sequence of tokens into a derivation tree. During the second step, the parser assigns a meaning to the derivation tree.

The construction of the derivation tree is directed by the context-free grammar. Because the parser ignores the tokens' values and only takes into account the tokens' categories when constructing the derivation tree, the terminal symbols of the context-free grammar are the names of the token categories.

The production rule describing the whole sequence of tokens produced by the tokenizer depends on the origin of the input sequence of characters.

When the origin of the input sequence of characters is a listener buffer, the whole sequence of tokens is described by the following production rule:

$\metavar{input}$ $\Coloneq$ $\metavar{object}$

When the origin of the input sequence of characters is a plain EVLambda source file, the whole sequence of tokens is described by the following production rule:

$\metavar{input}$ $\Coloneq$ $\metavar{object}$*

When the origin of the input sequence of characters is a documented EVLambda source file, the whole sequence of tokens is described by the following production rule (the XML element is a chapter element):

$\metavar{input}$ $\Coloneq$ $\metavar{xml-comment}$* $\metavar{xml-element}$ $\metavar{xml-comment}$*

The rest of the context-free grammar, which does not depend on the origin of the input sequence of characters, is defined as follows:

$\metavar{xml-markup}$ $\Coloneq$ $\metavar{xml-element}$ | $\metavar{xml-comment}$
$\metavar{xml-element}$ $\Coloneq$ xml-start-tag $\metavar{xml-element-content}$* xml-end-tag | xml-empty-element-tag
$\metavar{xml-element-content}$ $\Coloneq$ $\metavar{xml-markup}$ | $\metavar{object}$
$\metavar{xml-comment}$ $\Coloneq$ xml-comment
$\metavar{object}$ $\Coloneq$ void | boolean | number | character | string | keyword | variable | $\metavar{abbreviation}$ | $\metavar{list}$ | $\metavar{vector}$
$\metavar{abbreviation}$ $\Coloneq$ $\metavar{quotation}$ | $\metavar{quasiquotation}$ | $\metavar{unquotation}$ | $\metavar{splicing-unquotation}$
$\metavar{quotation}$ $\Coloneq$ quote $\metavar{xml-markup}$* $\metavar{object}$
$\metavar{quasiquotation}$ $\Coloneq$ quasiquote $\metavar{xml-markup}$* $\metavar{object}$
$\metavar{unquotation}$ $\Coloneq$ unquote $\metavar{xml-markup}$* $\metavar{object}$
$\metavar{splicing-unquotation}$ $\Coloneq$ unquote-splicing $\metavar{xml-markup}$* $\metavar{object}$
$\metavar{list}$ $\Coloneq$ $\metavar{proper-list}$ | $\metavar{dotted-list}$
$\metavar{proper-list}$ $\Coloneq$ left-parenthesis {$\metavar{xml-markup}$* $\metavar{object}$}* $\metavar{xml-markup}$* right-parenthesis
$\metavar{dotted-list}$ $\Coloneq$ left-parenthesis {$\metavar{xml-markup}$* $\metavar{object}$}+ $\metavar{xml-markup}$* dot $\metavar{xml-markup}$* $\metavar{object}$ $\metavar{xml-markup}$* right-parenthesis
$\metavar{vector}$ $\Coloneq$ hash-left-parenthesis {$\metavar{xml-markup}$* $\metavar{object}$}* $\metavar{xml-markup}$* right-parenthesis

Let us denote by $\mathcal{M}$ the function assigning a meaning to a derivation tree. The function $\mathcal{M}$ is defined by specifying, for each production rule, how the meaning of the nonterminal symbol on the left-hand side is computed from (1) the meanings of the nonterminal symbols on the right-hand side and (2) the terminal symbols on the right-hand side. Here is the definition of the function $\mathcal{M}$, where a pair of square brackets denotes sequence formation and $\|$ denotes sequence concatenation):

$\metavar{input}\Coloneq$ $\metavar{object}$
$\mathcal{M}(\metavar{input})=[\mathcal{M}(\metavar{object})]$
$\metavar{input}\Coloneq$ $\metavar{object}_1\ldots\metavar{object}_{n\ge0}$
$\mathcal{M}(\metavar{input})=[\mathcal{M}(\metavar{object}_1),\ldots,\mathcal{M}(\metavar{object}_n)]$
$\metavar{input}\Coloneq$ $\metavar{cmt}_1\ldots\metavar{cmt}_{n\ge0}$ $\metavar{xml-element}$ $\metavar{cmt}'_1\ldots\metavar{cmt}'_{n'\ge0}$
$\mathcal{M}(\metavar{input})=\mathcal{M}(\metavar{cmt}_1)\|\cdots\|\mathcal{M}(\metavar{cmt}_n)\|\mathcal{M}(\metavar{xml-element})\|\mathcal{M}(\metavar{cmt}'_1)\|\cdots\|\mathcal{M}(\metavar{cmt}'_{n'})$
$\metavar{xml-markup}\Coloneq$ $\metavar{xml-element}$
$\mathcal{M}(\metavar{xml-markup})=\mathcal{M}(\metavar{xml-element})$
$\metavar{xml-markup}\Coloneq$ $\metavar{xml-comment}$
$\mathcal{M}(\metavar{xml-markup})=\mathcal{M}(\metavar{xml-comment})$
$\metavar{xml-element}\Coloneq$ xml-start-tag $\metavar{xml-element-content}_1\ldots\metavar{xml-element-content}_{n\ge0}$ xml-end-tag
$\mathcal{M}(\metavar{xml-element})=\mathcal{M}(\metavar{xml-element-content}_1)\|\cdots\|\mathcal{M}(\metavar{xml-element-content}_n)$
$\metavar{xml-element}\Coloneq$ xml-empty-element-tag
$\mathcal{M}(\metavar{xml-element})=[]$
$\metavar{xml-element-content}\Coloneq$ $\metavar{xml-markup}$
$\mathcal{M}(\metavar{xml-element-content})=\mathcal{M}(\metavar{xml-markup})$
$\metavar{xml-element-content}\Coloneq$ $\metavar{object}$
$\mathcal{M}(\metavar{xml-element-content})=[\mathcal{M}(\metavar{object})]$
$\metavar{xml-comment}\Coloneq$ xml-comment
$\mathcal{M}(\metavar{xml-comment})=[]$
$\metavar{object}\Coloneq$ void
$\mathcal{M}(\metavar{object})=$ the value of the token of category void
$\metavar{object}\Coloneq$ boolean
$\mathcal{M}(\metavar{object})=$ the value of the token of category boolean
$\metavar{object}\Coloneq$ number
$\mathcal{M}(\metavar{object})=$ the value of the token of category number
$\metavar{object}\Coloneq$ character
$\mathcal{M}(\metavar{object})=$ the value of the token of category character
$\metavar{object}\Coloneq$ string
$\mathcal{M}(\metavar{object})=$ the value of the token of category string
$\metavar{object}\Coloneq$ keyword
$\mathcal{M}(\metavar{object})=$ the value of the token of category keyword
$\metavar{object}\Coloneq$ variable
$\mathcal{M}(\metavar{object})=$ the value of the token of category variable
$\metavar{object}\Coloneq$ $\metavar{abbreviation}$
$\mathcal{M}(\metavar{object})=\mathcal{M}(\metavar{abbreviation})$
$\metavar{object}\Coloneq$ $\metavar{list}$
$\mathcal{M}(\metavar{object})=\mathcal{M}(\metavar{list})$
$\metavar{object}\Coloneq$ $\metavar{vector}$
$\mathcal{M}(\metavar{object})=\mathcal{M}(\metavar{vector})$
$\metavar{abbreviation}\Coloneq$ $\metavar{quotation}$
$\mathcal{M}(\metavar{abbreviation})=\mathcal{M}(\metavar{quotation})$
$\metavar{abbreviation}\Coloneq$ $\metavar{quasiquotation}$
$\mathcal{M}(\metavar{abbreviation})=\mathcal{M}(\metavar{quasiquotation})$
$\metavar{abbreviation}\Coloneq$ $\metavar{unquotation}$
$\mathcal{M}(\metavar{abbreviation})=\mathcal{M}(\metavar{unquotation})$
$\metavar{abbreviation}\Coloneq$ $\metavar{splicing-unquotation}$
$\mathcal{M}(\metavar{abbreviation})=\mathcal{M}(\metavar{splicing-unquotation})$
$\metavar{quotation}\Coloneq$ quote $\metavar{object}$
$\mathcal{M}(\metavar{quotation})=$ a cons whose car is the variable quote and whose cdr is a cons whose car is $\mathcal{M}(\metavar{object})$ and whose cdr is the empty list
$\metavar{quasiquotation}\Coloneq$ quasiquote $\metavar{object}$
$\mathcal{M}(\metavar{quasiquotation})=$ a cons whose car is the variable quasiquote and whose cdr is a cons whose car is $\mathcal{M}(\metavar{object})$ and whose cdr is the empty list
$\metavar{unquotation}\Coloneq$ unquote $\metavar{object}$
$\mathcal{M}(\metavar{unquotation})=$ a cons whose car is the variable unquote and whose cdr is a cons whose car is $\mathcal{M}(\metavar{object})$ and whose cdr is the empty list
$\metavar{splicing-unquotation}\Coloneq$ unquote-splicing $\metavar{object}$
$\mathcal{M}(\metavar{splicing-unquotation})=$ a cons whose car is the variable unquote-splicing and whose cdr is a cons whose car is $\mathcal{M}(\metavar{object})$ and whose cdr is the empty list
$\metavar{list}\Coloneq$ $\metavar{proper-list}$
$\mathcal{M}(\metavar{list})=\mathcal{M}(\metavar{proper-list})$
$\metavar{list}\Coloneq$ $\metavar{dotted-list}$
$\mathcal{M}(\metavar{list})=\mathcal{M}(\metavar{dotted-list})$
$\metavar{proper-list}\Coloneq$ left-parenthesis right-parenthesis
$\mathcal{M}(\metavar{proper-list})=$ the empty list
$\metavar{proper-list}\Coloneq$ left-parenthesis $\metavar{object}_1\ldots\metavar{object}_{n\ge1}$ right-parenthesis
$\mathcal{M}(\metavar{proper-list})=$ the first cons of a chain of $n$ conses $\cons_1,\ldots,\cons_n$ such that the car of $\cons_i$ is $\mathcal{M}(\metavar{object}_i)$, the cdr of $\cons_{i\lt n}$ is $\cons_{i+1}$, and the cdr of $\cons_n$ is the empty list
$\metavar{dotted-list}\Coloneq$ left-parenthesis $\metavar{object}_1\ldots\metavar{object}_{n\ge1}$ dot $\metavar{object}_{n+1}$ right-parenthesis
$\mathcal{M}(\metavar{dotted-list})=$ the first cons of a chain of $n$ conses $\cons_1,\ldots,\cons_n$ such that the car of $\cons_i$ is $\mathcal{M}(\metavar{object}_i)$, the cdr of $\cons_{i\lt n}$ is $\cons_{i+1}$, and the cdr of $\cons_n$ is $\mathcal{M}(\metavar{object}_{n+1})$
$\metavar{vector}\Coloneq$ hash-left-parenthesis $\metavar{object}_1\ldots\metavar{object}_{n\ge0}$ right-parenthesis
$\mathcal{M}(\metavar{vector})=$ a vector of $n$ elements $\mlvar{elem}_1,\ldots,\mlvar{elem}_n$ such that $\mlvar{elem}_i$ is $\mathcal{M}(\metavar{object}_i)$

Note that the XML markup inside abbreviations, lists, and vectors cannot produce objects and has therefore been omitted from the definition of the function $\mathcal{M}$.

Pattern Language and Template Languages

The pattern language is a context-free language whose sentences are patterns meant to be matched against objects. The pattern language can be used to specify a set of objects $S$ as follows:

The language specified by a grammar such as $G$ is called a template language. Template languages will be used to specify the forms recognized by the form analyzer, to specify template macro calls, to specify data structures, …

Here are the terminal symbols of the context-free grammar specifying the pattern language:

Here are the production rules of the context-free grammar specifying the pattern language:

$\metavar{pattern}$ $\Coloneq$ $\metavar{type}$ | $\metavar{void}$ | $\metavar{boolean}$ | $\metavar{number}$ | $\metavar{character}$ | $\metavar{string}$ | $\metavar{keyword}$ | $\metavar{variable}$ | $\metavar{list}$ | $\metavar{vector}$
$\metavar{type}$ $\Coloneq$ $\object$ | $\void$ | $\boolean$ | $\number$ | $\character$ | $\string$ | $symbol$ | $\keyword$ | $\variable$ | $\list$ | $\emptylist$ | $\cons$ | $\vector$ | $\function$ | $\primitivefunction$ | $\closure$
$\metavar{void}$ $\Coloneq$ ? any readable representation of an object of type void ?
$\metavar{boolean}$ $\Coloneq$ ? any readable representation of an object of type boolean ?
$\metavar{number}$ $\Coloneq$ ? any readable representation of an object of type number ?
$\metavar{character}$ $\Coloneq$ ? any readable representation of an object of type character ?
$\metavar{string}$ $\Coloneq$ ? any readable representation of an object of type string ?
$\metavar{keyword}$ $\Coloneq$ ? any readable representation of an object of type keyword ?
$\metavar{variable}$ $\Coloneq$ ? any readable representation of an object of type variable ?
$\metavar{list}$ $\Coloneq$ $\metavar{proper-list}$ | $\metavar{dotted-list}$
$\metavar{proper-list}$ $\Coloneq$ ($\metavar{pattern}$*)
$\metavar{dotted-list}$ $\Coloneq$ ($\metavar{pattern}$+ . $\metavar{pattern}$)
$\metavar{vector}$ $\Coloneq$ #($\metavar{pattern}$*)

The rules specifying whether an object matches a pattern are the following:

By way of example, let us consider the template language specified by the following context-free grammar:

$\metavar{association-list}$ $\Coloneq$ ({($\metavar{key}$ . $\metavar{value}$)}*)
$\metavar{key}$ $\Coloneq$ $\object$
$\metavar{value}$ $\Coloneq$ $\object$

The sentences of the example template language are the following:

The objects specified by the example template language (= the objects matching at least one sentence of the example template language) are the proper lists of conses of arbitrary objects. As suggested by the names of the nonterminal symbols, the first object of each cons operates as a key, the second object of each cons operates as a value, and the proper list as a whole is called an association list.

Read-Time Conditionalization Facility

A feature is a symbol associated with a property of the implementation. The feature list is the proper list of features that is the value of the global variable *features*. For each feature, the meanings of the presence of the feature on the feature list and the absence of the feature from the feature list must be specified.

Each evaluator has an associated feature:

FeatureMeaning
directstyleThe feature is present on the feature list if and only if the evaluator is an instance of the direct style evaluator.
cpsThe feature is present on the feature list if and only if the evaluator is an instance of the continuation passing style evaluator.
oocpsThe feature is present on the feature list if and only if the evaluator is an instance of the object-oriented CPS evaluator.
sboocpsThe feature is present on the feature list if and only if the evaluator is an instance of the stack-based object-oriented CPS evaluator.
trampolineThe feature is present on the feature list if and only if the evaluator is an instance of the trampoline evaluator.
trampolineppThe feature is present on the feature list if and only if the evaluator is an instance of the trampoline++ evaluator.

The purpose of the read-time conditionalization facility is to alter the flow of tokens according to whether or not some features belong or do not belong to the feature list. Because the facility is conceptually located between the tokenizer and the parser, its associated syntax does not belong to the context-free grammar used by the parser. It is however convenient to specify the syntax of a read-time conditional by the following production rule:

$\metavar{read-time-conditional}$ $\Coloneq$ {hash-plus | hash-minus} $\metavar{xml-markup}$* $\metavar{object}$ $\metavar{xml-markup}$* $\metavar{object}$

The first object is called the feature expression and the second object is called the conditionalized object.

When the facility encounters a hash-plus or a hash-minus token, it instructs the parser to parse, hand over, and discard the feature expression. The feature expression is then evaluated by the facility according to the rules stated below. If the read-time conditional starts with a hash-plus token and the feature expression evaluates to true or the read-time conditional starts with a hash-minus token and the feature expression evaluates to false, then the facility ends its processing of the read-time conditional by instructing the parser to parse and retain the conditionalized object. (The net effect is the same as if only the tokens of the conditionalized object had existed.) If the read-time conditional starts with a hash-plus token and the feature expression evaluates to false or the read-time conditional starts with a hash-minus token and the feature expression evaluates to true, then the facility ends its processing of the read-time conditional by instructing the parser to parse and discard the conditionalized object. (The net effect is the same as if the tokens of the read-time conditional had not existed.)

Feature expressions must belong to the set of objects specified by the template language specified by the following context-free grammar:

$\metavar{feature-expression}$ $\Coloneq$ $\metavar{feature}$ | (not $\metavar{operand}$) | (and $\metavar{operand}$*) | (or $\metavar{operand}$*)
$\metavar{feature}$ $\Coloneq$ $\symbol$
$\metavar{operand}$ $\Coloneq$ $\metavar{feature-expression}$

Feature expressions are evaluated as follows:

$\metavar{feature-expression}\Coloneq$ $\metavar{feature}$
The feature expression evaluates to true if the feature belongs to the feature list and to false otherwise.
$\metavar{feature-expression}\Coloneq$ (not $\metavar{operand}$)
The feature expression evaluates to true if its operand evaluates to false and to false otherwise.
$\metavar{feature-expression}\Coloneq$ (and $\metavar{operand}_1\ldots\metavar{operand}_{n\ge0}$)
The feature expression evaluates to true if all its operands evaluate to true and to false otherwise.
$\metavar{feature-expression}\Coloneq$ (or $\metavar{operand}_1\ldots\metavar{operand}_{n\ge0}$)
The feature expression evaluates to false if all its operands evaluate to false and to true otherwise.

By way of example, let us consider the following sequence of characters:

(1 . #+foo 2 #-foo 3)

If the feature foo belongs to the feature list, then the sequence of characters is parsed as the dotted list (1 . 2). Otherwise, the sequence of characters is parsed as the dotted list (1 . 3).

Form Analyzer

A form is any object submitted to the evaluator. A top-level form is a form submitted to the evaluator by an entity other than the evaluator, the IDE for instance. A non-top-level form is a form submitted to the evaluator by the evaluator in the course of the evaluation of a top-level form.

Analyzing a form is the first step in evaluating a form. If a form is not recognized by the form analyzer, then the evaluation of the form completes abruptly for a reason of type error. The forms recognized by the form analyzer are specified by the template language specified by the following context-free grammar ($\metavar{form}$ is a misnomer as any object submitted to the evaluator is a form):

$\metavar{form}$ $\Coloneq$ $\metavar{special-form}$ | $\metavar{macro-call}$ | $\metavar{plain-function-call}$ | $\metavar{self-evaluating-object}$
$\metavar{special-form}$ $\Coloneq$ $\metavar{quote-form}$ | $\metavar{progn-form}$ | $\metavar{if-form}$ | $\metavar{\_for-each-form}$ | $\metavar{lambda-abstraction}$ | $\metavar{variable-reference}$ | $\metavar{variable-assignment}$ | $\metavar{block-form}$ | $\metavar{return-from-form}$ | $\metavar{catch-form}$ | $\metavar{throw-form}$ | $\metavar{\_handler-bind-form}$ | $\metavar{unwind-protect-form}$ | $\metavar{apply-form}$ | $\metavar{multiple-value-call-form}$ | $\metavar{multiple-value-apply-form}$
$\metavar{quote-form}$ $\Coloneq$ (quote $\metavar{literal}$)
$\metavar{literal}$ $\Coloneq$ $\object$
$\metavar{progn-form}$ $\Coloneq$ (progn $\metavar{serial-form}$*)
$\metavar{serial-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{if-form}$ $\Coloneq$ (if $\metavar{test-form}$ $\metavar{then-form}$ $\metavar{else-form}$)
$\metavar{test-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{then-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{else-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{\_for-each-form}$ $\Coloneq$ (_for-each $\metavar{function-form}$ $\metavar{list-form}$)
$\metavar{function-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{list-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{lambda-abstraction}$ $\Coloneq$ $\metavar{\_vlambda-form}$ | $\metavar{\_mlambda-form}$ | $\metavar{\_flambda-form}$ | $\metavar{\_dlambda-form}$
$\metavar{\_vlambda-form}$ $\Coloneq$ (_vlambda $\metavar{parameter-list}$ $\metavar{body}$)
$\metavar{\_mlambda-form}$ $\Coloneq$ (_mlambda $\metavar{parameter-list}$ $\metavar{body}$)
$\metavar{\_flambda-form}$ $\Coloneq$ (_flambda $\metavar{parameter-list}$ $\metavar{body}$)
$\metavar{\_dlambda-form}$ $\Coloneq$ (_dlambda $\metavar{parameter-list}$ $\metavar{body}$)
$\metavar{parameter-list}$ $\Coloneq$ $\variable$ | ($\variable$*) | ($\variable$+ . $\variable$)
$\metavar{body}$ $\Coloneq$ $\metavar{serial-form}$*
$\metavar{variable-reference}$ $\Coloneq$ $\variable$ | $\metavar{vref-form}$ | $\metavar{fref-form}$ | $\metavar{dref-form}$
$\metavar{vref-form}$ $\Coloneq$ (vref $\variable$)
$\metavar{fref-form}$ $\Coloneq$ (fref $\variable$)
$\metavar{dref-form}$ $\Coloneq$ (dref $\variable$)
$\metavar{variable-assignment}$ $\Coloneq$ $\metavar{vset-form}$ | $\metavar{fset-form}$ | $\metavar{dset-form}$
$\metavar{vset-form}$ $\Coloneq$ (vset! $\variable$ $\metavar{value-form}$)
$\metavar{fset-form}$ $\Coloneq$ (fset! $\variable$ $\metavar{value-form}$)
$\metavar{dset-form}$ $\Coloneq$ (dset! $\variable$ $\metavar{value-form}$)
$\metavar{value-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{block-form}$ $\Coloneq$ (block $\metavar{block-name}$ $\metavar{serial-form}$*)
$\metavar{return-from-form}$ $\Coloneq$ (return-from $\metavar{block-name}$ $\metavar{values-form}$)
$\metavar{catch-form}$ $\Coloneq$ (catch $\metavar{exit-tag-form}$ $\metavar{serial-form}$*)
$\metavar{throw-form}$ $\Coloneq$ (throw $\metavar{exit-tag-form}$ $\metavar{values-form}$)
$\metavar{block-name}$ $\Coloneq$ $\variable$
$\metavar{exit-tag-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{values-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{\_handler-bind-form}$ $\Coloneq$ (_handler-bind $\metavar{handler-form}$ $\metavar{serial-form}$*)
$\metavar{handler-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{unwind-protect-form}$ $\Coloneq$ (unwind-protect $\metavar{protected-form}$ $\metavar{cleanup-form}$*)
$\metavar{protected-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{cleanup-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{apply-form}$ $\Coloneq$ (apply $\metavar{operator-form}$ $\metavar{operand-form}$*)
$\metavar{multiple-value-call-form}$ $\Coloneq$ (multiple-value-call $\metavar{operator-form}$ $\metavar{operand-form}$*)
$\metavar{multiple-value-apply-form}$ $\Coloneq$ (multiple-value-apply $\metavar{operator-form}$ $\metavar{operand-form}$*)
$\metavar{macro-call}$ $\Coloneq$ ($\metavar{macro-operator}$ $\metavar{macro-operand}$*)
$\metavar{macro-operator}$ $\Coloneq$ $\variable$
$\metavar{macro-operand}$ $\Coloneq$ $\object$
$\metavar{plain-function-call}$ $\Coloneq$ ($\metavar{operator-form}$ $\metavar{operand-form}$*)
$\metavar{operator-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{operand-form}$ $\Coloneq$ $\metavar{form}$
$\metavar{self-evaluating-object}$ $\Coloneq$ $\void$ | $\boolean$ | $\number$ | $\character$ | $\string$ | $\keyword$ | $\vector$ | $\primitivefunction$ | $\closure$

The names of the nonterminal symbols are the names that will be used throughout this document to name the forms and their components.

The following production rules introduce additional terminology:

$\metavar{special-operator}$ $\Coloneq$ quote | progn | if | _for-each | _vlambda | _mlambda | _flambda | _dlambda | vref | fref | dref | vset! | fset! | dset! | block | return-from | catch | throw | _handler-bind | unwind-protect | apply | multiple-value-call | multiple-value-apply
$\metavar{call}$ $\Coloneq$ $\metavar{macro-call}$ | $\metavar{function-call}$
$\metavar{function-call}$ $\Coloneq$ $\metavar{plain-function-call}$ | $\metavar{apply-form}$ | $\metavar{multiple-value-call-form}$ | $\metavar{multiple-value-apply-form}$

The parameters of a parameter list fall into two categories: the required parameters, of which there can be any number, and the rest parameters, of which there can be zero or one. Here are the required and rest parameters for the different forms of parameter lists:

Parameter listRequired parametersRest parameters
$\var$none$\var$
($\var_1\ldots\var_{n\ge0}$)$\var_1,\ldots,\var_n$none
($\var_1\ldots\var_{n\ge1}$ . $\var_{n+1}$)$\var_1,\ldots,\var_n$$\var_{n+1}$

The variables quasiquote, unquote, and unquote-splicing are not special operators. The variable quasiquote is the name of a global macro and the variables unquote and unquote-splicing are variables having special meanings in the context of a call to the global macro quasiquote.

A form consisting of a variable $\variable$ is treated as an abbreviation. If it appears in operator position, then it is treated as an abbreviation for the special form (fref $\variable$). Otherwise, it is treated as an abbreviation for the special form (vref $\variable$).

According to the template language, some objects can simultaneously be a special form, a macro call, and a plain function call. Additional rules are needed to disambiguate the situation.

The following rules used by the form analyzer are not expressed by the template language:

The direct subforms of a form are the direct components of the form that are identified as forms by the form's production rule. Note that the body of a lambda abstraction is not considered to be a direct subform of the lambda abstraction as the evaluation of a lambda abstraction does not entail the evaluation of its body. The subforms of a form are the direct subforms of the form, the direct subforms of the direct subforms of the form, …

A form is said to be in tail position with respect to a lambda abstraction other than a _dlambda form if and only if one of the following conditions is satisfied:

Documentation Generator

In this section, the character ⇰ marks the places where line breaks have been added to wrap long lines.

Let us consider the following documented EVLambda source file:

<chapter>
<title>Recursive Functions</title>
<p>...para...</p>
<p>...para...</p>
<section>
<title>Factorial Function</title>
<p>...para...</p>
<p>...para...</p>
(fdef fact (n)
<p>...block...</p>
<p>...block...</p>
(if (= n 0)
1 <comment>...eol...</comment>
(* n (fact (- n 1))))) <comment>...eoll...</comment>

(test 1 (fact 0))
(test 120 (fact 5))
(test 3628800 (fact 10))
</section>
<section>
<title>Fibonacci Sequence</title>
<p>...para...</p>
<p>...para...</p>
(fdef fib (n)
<p>...block...</p>
<p>...block...</p>
(if (= n 0)
0 <comment>...eol...</comment>
(if (= n 1)
1 <comment>...eol...</comment>
(+ (fib (- n 1)) (fib (- n 2)))))) <comment>...eoll...</comment>

(test 0 (fib 0))
(test 5 (fib 5))
(test 55 (fib 10))
</section>
</chapter>

The first step of the documentation generation process converts the documented EVLambda source file into the following XML document:

<chapter>
<title>Recursive Functions</title>
<p>...para...</p>
<p>...para...</p>
<section>
<title>Factorial Function</title>
<p>...para...</p>
<p>...para...</p>
<toplevelcode><blockcode>(fdef fact (n)⇰
</blockcode><indentation style="margin-left: 2ch;"><blockcomment>
<p>...block...</p>
<p>...block...</p></blockcomment></indentation><blockcode>
(if (= n 0)
1 <comment>...eol...</comment>
(* n (fact (- n 1))))) ⇰
<comment>...eoll...</comment></blockcode></toplevelcode>

<toplevelcode><blockcode>(test 1 (fact 0))
(test 120 (fact 5))
(test 3628800 (fact 10))</blockcode></toplevelcode>
</section>
<section>
<title>Fibonacci Sequence</title>
<p>...para...</p>
<p>...para...</p>
<toplevelcode><blockcode>(fdef fib (n)⇰
</blockcode><indentation style="margin-left: 2ch;"><blockcomment>
<p>...block...</p>
<p>...block...</p></blockcomment></indentation><blockcode>
(if (= n 0)
0 <comment>...eol...</comment>
(if (= n 1)
1 <comment>...eol...</comment>
(+ (fib (- n 1)) (fib (- n 2)))))) ⇰
<comment>...eoll...</comment></blockcode></toplevelcode>

<toplevelcode><blockcode>(test 0 (fib 0))
(test 5 (fib 5))
(test 55 (fib 10))</blockcode></toplevelcode>
</section>
</chapter>

Here are a few remarks about the XML document:

The second step of the documentation generation process converts the XML document into the following HTML document:

<html>
<head>
</head>
<body>
<h1>Recursive Functions</h1>
<p>...para...</p>
<p>...para...</p>
<h2>Factorial Function</h2>
<p>...para...</p>
<p>...para...</p>
<pre class="blockcode">(fdef fact (n)</pre>
<div class="indentation" style="margin-left: 2ch;">
<div class="blockcomment">
<p>...block...</p>
<p>...block...</p>
</div>
</div>
<pre class="blockcode">
(if (= n 0)
1 <span class="eolcomment">...eol...</span>
(* n (fact (- n 1))))) ⇰
<span class="eolcomment">...eoll...</span></pre>
<pre class="blockcode">(test 1 (fact 0))
(test 120 (fact 5))
(test 3628800 (fact 10))</pre>
<h2>Fibonacci Sequence</h2>
<p>...para...</p>
<p>...para...</p>
<pre class="blockcode">(fdef fib (n)</pre>
<div class="indentation" style="margin-left: 2ch;">
<div class="blockcomment">
<p>...block...</p>
<p>...block...</p>
</div>
</div>
<pre class="blockcode">
(if (= n 0)
0 <span class="eolcomment">...eol...</span>
(if (= n 1)
1 <span class="eolcomment">...eol...</span>
(+ (fib (- n 1)) (fib (- n 2)))))) ⇰
<span class="eolcomment">...eoll...</span></pre>
<pre class="blockcode">(test 0 (fib 0))
(test 5 (fib 5))
(test 55 (fib 10))</pre>
</body>
</html>

Semantics

Primitive Data Types and Primitive Functions

This section inventories all the primitive data types and all the primitive functions.

Primitive Data Types

Here is a tree-view representation of the hierarchy of primitive data types:

object
|-void
|-boolean
|-number
|-character
|-string
|-symbol
| |-keyword
| |-variable
|-list
| |-empty-list
| |-cons
|-vector
|-function
| |-primitive-function
| |-closure

Primitive Data Type object and Related Primitive Functions

(object? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type object (which is always the case) and #f otherwise.
(eq? $\object_1$ $\object_2$) ⇒ $\boolean$
The function returns #t if and only if the two objects are one and the same. In other words, the function returns #t if and only if the two objects have the same address in the heap.
(eql? $\object_1$ $\object_2$) ⇒ $\boolean$
If both objects are of type number, then the function returns #t if and only if the two objects represent the same mathematical number. Otherwise, if both objects are of type character, then the function returns #t if and only if the two objects represent the same UTF-$16$ code unit. Otherwise, if both objects are of type string, then the function returns #t if and only if the two objects represent the same indexed sequence of UTF-$16$ code units. Otherwise, the function returns #t if and only if the two objects are eq?.

Primitive Data Type void and Related Primitive Functions

(void? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type void and #f otherwise.

Primitive Data Type boolean and Related Primitive Functions

(boolean? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type boolean and #f otherwise.

Primitive Data Type number and Related Primitive Functions

Objects of type number represent mathematical numbers using the floating-point format IEEE 754 binary 64. Some (but not all) of the integers that can be represented exactly by an object of type number are the integers between $-2^{53}=−9,007,199,254,740,992$ and $2^{53}=9,007,199,254,740,992$ (bounds included).

(number? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type number and #f otherwise.
(_+ $\number_1$ $\number_2$) ⇒ $\number$
The function returns the sum $\number_1+\number_2$.
(_- $\number_1$ $\number_2$) ⇒ $\number$
The function returns the difference $\number_1-\number_2$.
(_* $\number_1$ $\number_2$) ⇒ $\number$
The function returns the product $\number_1\times\number_2$.
(_/ $\number_1$ $\number_2$) ⇒ $\number$
The function returns the quotient $\number_1\div\number_2$.
(% $\number_1$ $\number_2$) ⇒ $\number$
The function returns the remainder of the division of $\number_1$ by $\number_2$ when the quotient is forced to be an integer.
(= $\number_1$ $\number_2$) ⇒ $\boolean$
The function returns #t if $\number_1$ and $\number_2$ are numerically equal and #f otherwise.
(/= $\number_1$ $\number_2$) ⇒ $\boolean$
The function returns #t if $\number_1$ and $\number_2$ are numerically different and #f otherwise.
(< $\number_1$ $\number_2$) ⇒ $\boolean$
The function returns #t if $\number_1$ is numerically less than $\number_2$ and #f otherwise.
(<= $\number_1$ $\number_2$) ⇒ $\boolean$
The function returns #t if $\number_1$ is numerically less than or equal to $\number_2$ and #f otherwise.
(> $\number_1$ $\number_2$) ⇒ $\boolean$
The function returns #t if $\number_1$ is numerically greater than $\number_2$ and #f otherwise.
(>= $\number_1$ $\number_2$) ⇒ $\boolean$
The function returns #t if $\number_1$ is numerically greater than or equal to $\number_2$ and #f otherwise.

The functions _+, _-, _*, and _/ have an underscore at the beginning of their names to distinguish them from the similarly named nonprimitive functions +, -, *, and /, which all accept a variable number of arguments.

Primitive Data Type character and Related Primitive Functions

Contrary to what was said in the user manual, an object of type character represents a UTF-$16$ code unit (instead of a Unicode character).

(character? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type character and #f otherwise.

Primitive Data Type string and Related Primitive Functions

Contrary to what was said in the user manual, an object of type string represents an indexed sequence of UTF-$16$ code units (instead of an indexed sequence of Unicode characters).

(string? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type string and #f otherwise.

Primitive Data Type symbol and Related Primitive Functions

(symbol? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type symbol and #f otherwise.

Primitive Data Type keyword and Related Primitive Functions

(keyword? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type keyword and #f otherwise.
(make-keyword? $\string$) ⇒ $\keyword$
The function returns a new uninterned keyword whose name is $\string$.

Primitive Data Type variable and Related Primitive Functions

(variable? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type variable and #f otherwise.
(make-variable $\string$) ⇒ $\variable$
The function returns a new uninterned variable whose name is $\string$.
(variable-value $\variable$) ⇒ $\object$
If there exists a binding for $\variable$ in the value namespace of the global environment, then the function returns the value of that binding. Otherwise, the function returns #v.
(variable-set-value! $\variable$ $\object$) ⇒ $\object$
If there exists a binding for $\variable$ in the value namespace of the global environment, then the value of that binding is replaced by $\object$ and the functions returns $\object$. Otherwise, a new binding between $\variable$ and $\object$ is added to the value namespace of the global environment and the function returns $\object$.
(variable-value-bound? $\variable$) ⇒ $\boolean$
If there exists a binding for $\variable$ in the value namespace of the global environment, then the function returns #t. Otherwise, the function returns #f.
(variable-unbind-value! $\variable$)#v
If there exists a binding for $\variable$ in the value namespace of the global environment, then that binding is deleted and the function returns #v. Otherwise, the function simply returns #v.
(variable-function $\variable$) ⇒ $\object$
If there exists a binding for $\variable$ in the function namespace of the global environment, then the function returns the value of that binding. Otherwise, the function returns #v.
(variable-set-function! $\variable$ $\object$) ⇒ $\object$
If there exists a binding for $\variable$ in the function namespace of the global environment, then the value of that binding is replaced by $\object$ and the function returns $\object$. Otherwise, a new binding between $\variable$ and $\object$ is added to the function namespace of the global environment and the function returns $\object$.
(variable-function-bound? $\variable$) ⇒ $\boolean$
If there exists a binding for $\variable$ in the function namespace of the global environment, then the function returns #t. Otherwise, the function returns #f.
(variable-unbind-function! $\variable$)#v
If there exists a binding for $\variable$ in the function namespace of the global environment, then that binding is deleted and the function returns #v. Otherwise, the function simply returns #v.

A property list is an association between keys (usually of type keyword) and values (of any type). Each variable has an associated property list. The keys must be of type keyword and the values are accessed through the following primitive functions:

(variable-plist-ref $\variable$ $\keyword$) ⇒ $\object$
If there exists an association between $\keyword$ and a value, then the function returns that value. Otherwise, the function returns #v.
(variable-plist-set! $\variable$ $\keyword$ $\object$) ⇒ $\object$
If there exists an association between $\keyword$ and a value, then that value by replaced by $\object$ and the function returns $\object$. Otherwise, an association between $\keyword$ and $\object$ is created and the function returns $\object$.
(variable-plist-bound? $\variable$ $\keyword$) ⇒ $\boolean$
If there exists an association between $\keyword$ and a value, then the function returns #t. Otherwise, the function returns #f.
(variable-plist-unbind! $\variable$ $\keyword$)#v
If there exists an association between $\keyword$ and a value, then that association is deleted and the function returns #v. Otherwise, the function simply returns #v.

Primitive Data Type list and Related Primitive Functions

(list? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type list and #f otherwise.
(_make-list $\number$) ⇒ $\list$
If $\number$ is not a nonnegative integer, then the function completes abruptly for a reason of type error. Otherwise, the function returns a new list of length $\number$ whose elements are all #v. The function exists mainly for testing purposes.

Primitive Data Type empty-list and Related Primitive Functions

(empty-list? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type empty-list and #f otherwise.

Primitive Data Type cons and Related Primitive Functions

(cons? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type cons and #f otherwise.
(cons $\object_1$ $\object_2$) ⇒ $\cons$
The function returns a new cons whose first element is $\object_1$ and whose second element is $\object_2$.
(car $\cons$) ⇒ $\object$
The function returns the first element of $\cons$.
(set-car! $\cons$ $\object$) ⇒ $\object$
The function replaces the first element of $\cons$ by $\object$ and returns $\object$.
(cdr $\cons$) ⇒ $\object$
The function returns the second element of $\cons$
(set-cdr! $\cons$ $\object$) ⇒ $\object$
The function replaces the second element of $\cons$ by $\object$ and returns $\object$.

Primitive Data Type vector and Related Primitive Functions

A vector is an association between indexes (nonnegative integers between zero and the length of the vector minus one) and values of arbitrary types. Not all indexes need to have an associated value. Vectors with missing values have no readable representations. In printable representations, indexes with no associated value appear to be associated with the value #v.

(vector? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type vector and #f otherwise.
(make-vector $\number$ $\object$) ⇒ $\vector$
If $\number$ is not a nonnegative integer, then the function completes abruptly for a reason of type error. Otherwise, the function returns a new vector of length $\number$. The argument $\object$ is optional. If $\object$ is not provided, then the indexes are all with no associated value. If $\object$ is provided, then the indexes are all associated with the value $\object$.
(vector-length $\vector$) ⇒ $\number$
The function returns the length of $\vector$.
(vector-ref $\vector$ $\number$) ⇒ $\object$
If $\number$ is not a nonnegative integer between zero and the length of $\vector$ minus one, then the function completes abruptly for a reason of type error. Otherwise, if there exists an association between $\number$ and a value, then the function returns that value. Otherwise, the function returns #v.
(vector-set! $\vector$ $\number$ $\object$) ⇒ $\object$
If $\number$ is not a nonnegative integer between zero and the length of $\vector$ minus one, then the function completes abruptly for a reason of type error. Otherwise, if there exists an association between $\number$ and a value, then that value is replaced by $\object$ and the function returns $\object$. Otherwise, an association between $\number$ and $\object$ is created and the function returns $\object$.
(vector-bound? $\vector$ $\number$) ⇒ $\boolean$
If $\number$ is not a nonnegative integer between zero and the length of $\vector$ minus one, then the function completes abruptly for a reason of type error. Otherwise, if there exists an association between $\number$ and a value, then the function returns #t. Otherwise, the function returns #f.
(vector-unbind! $\vector$ $\number$)#v
If $\number$ is not a nonnegative integer between zero and the length of $\vector$ minus one, then the function completes abruptly for a reason of type error. Otherwise, if there exists an association between $\number$ and a value, then that association is deleted and the function returns #v. Otherwise, the function simply returns #v.

Primitive Data Type function and Related Primitive Functions

(function? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type function and #f otherwise.

Primitive Data Type primitive-function and Related Primitive Functions

(primitive-function? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type primitive-function and #f otherwise.

Primitive Data Type closure and Related Primitive Functions

(closure? $\object$) ⇒ $\boolean$
The function returns #t if $\object$ is of type closure and #f otherwise.

Miscellaneous Primitive Functions

(values $\object_1\ldots\object_n$) ⇒ $\object_1,\ldots,\object_n$
The function converts its arguments into values: when invoked on the arguments $\object_1,\ldots,\object_n$, the function returns the values $\object_1,\ldots,\object_n$.
(error $\string$) ⇒ completes abruptly for a reason of type error
The invocation of the function completes abruptly for a reason of type error carrying the category "Error" and the description $\string$.
(now) ⇒ $\number$
The function returns the number of milliseconds elapsed since 1970-01-01 00:00:00.000 UTC.

Forms

This section supplements and amends the evaluation rules stated in the user manual.

Special Form _for-each

The special form _for-each is evaluated as follows:

(_for-each $\metavar{function-form}$ $\metavar{list-form}$)
The function form is evaluated. Let $\mlvar{function}$ be the primary value of the function form. If $\mlvar{function}$ is not a function, then the evaluation of the _for-each form completes abruptly for a reason of type error. Otherwise, the list form is evaluated. Let $\mlvar{list}$ be the primary value of the list form. If $\mlvar{list}$ is not a proper list, then the evaluation of the _for-each form completes abruptly for a reason of type error. Otherwise, the function $\mlvar{function}$ is invoked in sequence on each element of the list $\mlvar{list}$, from the first element to the last element. If any invocation completes abruptly for any reason or does not complete, then the following invocations do not happen and the evaluation of the _for-each form also completes abruptly for the same reason or does not complete either. Otherwise, the _for-each form evaluates to #v.

Advanced Control Structures

The two pairs of special forms block/return-from and catch/throw use two additional namespaces: the block namespace, which is only found in lexical environments, and the exit-point namespace, which is only found in dynamic environments.

Special Forms block/return-from

The special forms block and return-from are evaluated as follows:

(block $\metavar{block-name}$ $\metavar{serial-form}$*)
Let $\mlvar{exit-tag}$ be a new uninterned variable. The serial forms are evaluated in sequence from left to right with respect to (1) the environment extending the current lexical environment to bind, in the block namespace, the variable $\metavar{block-name}$ to $\mlvar{exit-tag}$ and (2) the environment extending the current dynamic environment to bind, in the exit-point namespace, the variable $\mlvar{exit-tag}$ to #v (the value is unimportant). If the evaluation of any serial form completes abruptly for any reason, then the following serial forms are not evaluated and the evaluation of the block form proceeds as follows:
Let $\mlvar{reason}$ be the reason for the abrupt completion of the serial form. If $\mlvar{reason}$ is of type nonlocal-exit and carries an exit tag eq? to $\mlvar{exit-tag}$, then the evaluation of the block form completes normally and produces the values carried by $\mlvar{reason}$. Otherwise, the evaluation of the block form completes abruptly for the reason $\mlvar{reason}$.
Otherwise, the evaluations of the serial forms all complete normally and the evaluation of the block form completes normally and produces the values of the last serial form or #v if there are no serial forms.
(return-from $\metavar{block-name}$ $\metavar{values-form}$)
If there exists no binding for the variable $\metavar{block-name}$ in the block namespace of the current lexical environment, then the evaluation of the return-from form completes abruptly for a reason of type error. Otherwise, let $\mlvar{exit-tag}$ be the value of the binding for the variable $\metavar{block-name}$ in the block namespace of the current lexical environment. If there exists no binding for the variable $\mlvar{exit-tag}$ in the exit-point namespace of the current dynamic environment, then the evaluation of the return-from form completes abruptly for a reason of type error. Otherwise, the values form is evaluated. If the evaluation of the values form completes abruptly for any reason, then the evaluation of the return-from form completes abruptly for the same reason. Otherwise, the evaluation of the return-from form completes abruptly for a reason of type nonlocal-exit carrying $\mlvar{exit-tag}$ and the values of the values form.
Special Forms catch/throw

The special forms catch and throw are evaluated as follows:

(catch $\metavar{exit-tag-form}$ $\metavar{serial-form}$*)
The exit-tag form is evaluated. If the evaluation of the exit-tag form completes abruptly for any reason, then the evaluation of the catch form completes abruptly for the same reason. Otherwise, let $\mlvar{exit-tag}$ be the primary value of the exit-tag form. If $\mlvar{exit-tag}$ is not a variable, then the evaluation of the catch form completes abruptly for a reason of type error. Otherwise, the serial forms are evaluated in sequence from left to right with respect to (1) the current lexical environment and (2) the environment extending the current dynamic environment to bind, in the exit-point namespace, the variable $\mlvar{exit-tag}$ to #v (the value is unimportant). If the evaluation of any serial form completes abruptly for any reason, then the following serial forms are not evaluated and the evaluation of the catch form proceeds as follows:
Let $\mlvar{reason}$ be the reason for the abrupt completion of the serial form. If $\mlvar{reason}$ is of type nonlocal-exit and carries an exit tag eq? to $\mlvar{exit-tag}$, then the evaluation of the catch form completes normally and produces the values carried by $\mlvar{reason}$. Otherwise, the evaluation of the catch form completes abruptly for the reason $\mlvar{reason}$.
Otherwise, the evaluations of the serial forms all complete normally and the evaluation of the catch form completes normally and produces the values of the last serial form or #v if there are no serial forms.
(throw $\metavar{exit-tag-form}$ $\metavar{values-form}$)
The exit-tag form is evaluated. If the evaluation of the exit-tag form completes abruptly for any reason, then the evaluation of the throw form completes abruptly for the same reason. Otherwise, let $\mlvar{exit-tag}$ be the primary value of the exit-tag form. If $\mlvar{exit-tag}$ is not a variable, then the evaluation of the throw form completes abruptly for a reason of type error. Otherwise, if there exists no binding for the variable $\mlvar{exit-tag}$ in the exit-point namespace of the current dynamic environment, then the evaluation of the throw form completes abruptly for a reason of type error. Otherwise, the values form is evaluated. If the evaluation of the values form completes abruptly for any reason, then the evaluation of the throw form completes abruptly for the same reason. Otherwise, the evaluation of the throw form completes abruptly for a reason of type nonlocal-exit carrying $\mlvar{exit-tag}$ and the values of the values form.
Special Form _handler-bind

The special form _handler-bind is evaluated as follows:

(_handler-bind $\metavar{handler-form}$ $\metavar{serial-form}$*)
The handler form is evaluated. If the evaluation of the handler form completes abruptly for any reason, then the evaluation of the _handler-bind form completes abruptly for the same reason. Otherwise, let $\mlvar{handler}$ be the primary value of the handler form. If $\mlvar{handler}$ is not a function, then the evaluation of the _handler-bind form completes abruptly for a reason of type error. Otherwise, the serial forms are evaluated in sequence from left to right. If the evaluation of any serial form completes abruptly for any reason, then the following serial forms are not evaluated and the evaluation of the _handler-bind form proceeds as follows:
Let $\mlvar{reason}$ be the reason for the abrupt completion of the serial form. If $\mlvar{reason}$ is of type nonlocal-exit, then the evaluation of the _handler-bind form completes abruptly for the reason $\mlvar{reason}$. Otherwise, $\mlvar{reason}$ is necessarily of type error and $\mlvar{handler}$ is invoked on the category and description carried by $\mlvar{reason}$. If the invocation completes abruptly for any reason, then the evaluation of the _handler-bind form also completes abruptly for the same reason. Otherwise, if the invocation does not complete, then the evaluation of the _handler-bind form does not complete either. Otherwise, the evaluation of the _handler-bind form completes abruptly for the reason $\mlvar{reason}$.
Otherwise, the evaluations of the serial forms all complete normally and the evaluation of the _handler-bind form completes normally and produces the values of the last serial form or #v if there are no serial forms.
Special Form unwind-protect

The special form unwind-protect is evaluated as follows:

(unwind-protect $\metavar{protected-form}$ $\metavar{cleanup-form}$*)
The protected form is evaluated. If the evaluation of the protected form completes abruptly for any reason, then the evaluation of the unwind-protect form proceeds as follows:
Let $\mlvar{reason}$ be the reason for the abrupt completion of the protected form. The cleanup forms are evaluated in sequence from left to right. If the evaluation of any cleanup form completes abruptly for any reason, then the following cleanup forms are not evaluated and the evaluation of the unwind-protect form completes abruptly for the same reason. Otherwise, the evaluations of the cleanup forms all complete normally and the evaluation of the unwind-protect form completes abruptly for the reason $\mlvar{reason}$.
Otherwise, the evaluation of the protected form completes normally and the evaluation of the unwind-protect form proceeds as follows:
The cleanup forms are evaluated in sequence from left to right. If the evaluation of any cleanup form completes abruptly for any reason, then the following cleanup forms are not evaluated and the evaluation of the unwind-protect form completes abruptly for the same reason. Otherwise, the evaluations of the cleanup forms all complete normally and the evaluation of the unwind-protect form completes normally and produces the values of the protected form.

Function Calls

A spreadable sequence of objects is a nonempty sequence of objects such that the last element of the sequence is a proper list of objects. Let $\mlvar{seq}=[\obj_1,\ldots,\obj_n,\code{(}\obj'_1\ldots\obj'_m\code{)}]$, where $n$ and $m$ are nonnegative integers, be a spreadable sequence of objects. We will denote by $\spread(\mlvar{seq})$ the sequence of objects $[\obj_1,\ldots,\obj_n,\obj'_1,\ldots,\obj'_m]$.

The function calls are evaluated as follows (the differences in behavior between the different types of function calls are highlighted with a gray background):

($\metavar{operator-form}$ $\metavar{operand-forms}$)
The operator form is evaluated. Let $\mlvar{operator}$ be the primary value of the operator form. If $\mlvar{operator}$ is not a function, then the evaluation of the plain function call completes abruptly for a reason of type error. Otherwise, the operand forms are evaluated in sequence from left to right, the primary values of the operand forms are collected into a sequence $\mlvar{seq}$, and $\mlvar{operator}$ is invoked on $\mlvar{seq}$. If the invocation completes abruptly for any reason, then the evaluation of the plain function call also completes abruptly for the same reason. Otherwise, if the invocation does not complete, then the evaluation of the plain function call does not complete either. Otherwise, the plain function call evaluates to the values of the invocation. (The behavior described here is identical to the behavior described in the user manual.)
(apply $\metavar{operator-form}$ $\metavar{operand-forms}$)
The operator form is evaluated. Let $\mlvar{operator}$ be the primary value of the operator form. If $\mlvar{operator}$ is not a function, then the evaluation of the apply form completes abruptly for a reason of type error. Otherwise, the operand forms are evaluated in sequence from left to right, the primary values of the operand forms are collected into a sequence $\mlvar{seq}$, and $\mlvar{operator}$ is invoked on $\spread(\mlvar{seq})$. (The evaluation of the apply form completes abruptly for a reason of type error if $\mlvar{seq}$ is not a spreadable sequence of objects.) If the invocation completes abruptly for any reason, then the evaluation of the apply form also completes abruptly for the same reason. Otherwise, if the invocation does not complete, then the evaluation of the apply form does not complete either. Otherwise, the apply form evaluates to the values of the invocation.
(multiple-value-call $\metavar{operator-form}$ $\metavar{operand-forms}$)
The operator form is evaluated. Let $\mlvar{operator}$ be the primary value of the operator form. If $\mlvar{operator}$ is not a function, then the evaluation of the multiple-value-call form completes abruptly for a reason of type error. Otherwise, the operand forms are evaluated in sequence from left to right, all the values of the operand forms are collected into a sequence $\mlvar{seq}$, and $\mlvar{operator}$ is invoked on the sequence $\mlvar{seq}$. If the invocation completes abruptly for any reason, then the evaluation of the multiple-value-call form also completes abruptly for the same reason. Otherwise, if the invocation does not complete, then the evaluation of the multiple-value-call form does not complete either. Otherwise, the multiple-value-call form evaluates to the values of the invocation.
(multiple-value-apply $\metavar{operator-form}$ $\metavar{operand-forms}$)
The operator form is evaluated. Let $\mlvar{operator}$ be the primary value of the operator form. If $\mlvar{operator}$ is not a function, then the evaluation of the multiple-value-apply form completes abruptly for a reason of type error. Otherwise, the operand forms are evaluated in sequence from left to right, all the values of the operand forms are collected into a sequence $\mlvar{seq}$, and $\mlvar{operator}$ is invoked on $\spread(\mlvar{seq})$. (The evaluation of the multiple-value-apply form completes abruptly for a reason of type error if $\mlvar{seq}$ is not a spreadable sequence of objects.) If the invocation completes abruptly for any reason, then the evaluation of the multiple-value-apply form also completes abruptly for the same reason. Otherwise, if the invocation does not complete, then the evaluation of the multiple-value-apply form does not complete either. Otherwise, the multiple-value-apply form evaluates to the values of the invocation.

A primitive function is invoked as described in the user manual. A closure is invoked as described in the user manual except for the way the parameters are paired with the arguments in order to extend the value namespace of the lexical environment captured by the closure (when the corresponding lambda abstraction is a _vlambda form or an _mlambda form), the function namespace of the lexical environment captured by the closure (when the corresponding lambda abstraction is an _flambda form), or the value namespace of the current dynamic environment (when the corresponding lambda abstraction is a _dlambda form). Let $var_1,\ldots,\var_n$ be the required parameters and $\arg_1,\ldots,\arg_m$ be the arguments. The way the parameters are paired with the arguments depends on the absence or presence of a rest parameter:

Case 1, there is no rest parameter:
If $n\ne m$, then the invocation completes abruptly for a reason of type error. Otherwise, the appropriate namespace of the appropriate environment is extended to bind $\var_i$ to $\arg_i$ for all $i$ from $1$ to $n$. (This is the behavior described in the user manual.)
Case 2, there is a rest parameter $\var_{n+1}$:
If $m\lt n$, then the invocation completes abruptly for a reason of type error. Otherwise, the appropriate namespace of the appropriate environment is extended to bind $\var_i$ to $\arg_i$ for all $i$ from $1$ to $n$ and $\var_{n+1}$ to a proper list whose elements are $\arg_{n+1},\ldots,arg_{m}$. The conses used to build the proper list are not necessarily new conses. When the function call is an apply form or a multiple-value-apply form, the proper list and the last element of the spreadable sequence of objects can share conses.

Here are some examples, where the bindings are assumed to belong to the value namespace:

Parameter listArgumentsBindings
(a b)$[\code{1},\code{2},\code{3}]$N/A (error: too many arguments)
(a b c)$[\code{1},\code{2},\code{3}]$$[\vbinding{a}{1},\vbinding{b}{2},\vbinding{c}{3}]$
(a b c d)$[\code{1},\code{2},\code{3}]$N/A (error: too few arguments)
a$[\code{1},\code{2},\code{3}]$$[\vbinding{a}{(1 2 3)}]$
(a . b)$[\code{1},\code{2},\code{3}]$$[\vbinding{a}{1},\vbinding{b}{(2 3)}]$
(a b . c)$[\code{1},\code{2},\code{3}]$$[\vbinding{a}{1},\vbinding{b}{2},\vbinding{c}{(3)}]$
(a b c . d)$[\code{1},\code{2},\code{3}]$$[\vbinding{a}{1},\vbinding{b}{2},\vbinding{c}{3},\vbinding{d}{()}]$
(a b c d . e)$[\code{1},\code{2},\code{3}]$N/A (error: too few arguments)

Here is one way to reproduce the preceding examples using plain function calls and _vlambda forms:

> ((_vlambda (a b) (list a b)) 1 2 3)
EvaluatorError: too-many-arguments: Too many arguments.

> ((_vlambda (a b c) (list a b c)) 1 2 3)
(1 2 3)

> ((_vlambda (a b c d) (list a b c d)) 1 2 3)
EvaluatorError: too-few-arguments: Too few arguments.

> ((_vlambda a (list a)) 1 2 3)
((1 2 3))

> ((_vlambda (a . b) (list a b)) 1 2 3)
(1 (2 3))

> ((_vlambda (a b . c) (list a b c)) 1 2 3)
(1 2 (3))

> ((_vlambda (a b c . d) (list a b c d)) 1 2 3)
(1 2 3 ())

> ((_vlambda (a b c d . e) (list a b c d e)) 1 2 3)
EvaluatorError: too-few-arguments: Too few arguments.

Evaluation Rules in Continuation-Passing Style

Elementary continuations:

Auxiliary functions:

To evaluate (quote $\mlvar{literal}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Invoke $k$ on $\mlvar{literal}$.
To evaluate (progn $\mlvar{serial-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Invoke the auxiliary function $\evalserialforms$ on $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the auxiliary function $\evalserialforms$ on $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and $k$, do the following:
If $\mlvar{serial-forms}$ is empty, then invoke $k$ on #v. Otherwise, invoke the auxiliary function $\evalserialformforms$ on $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the auxiliary function $\evalserialformforms$ on $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and $k$, do the following:
If $\mlvar{serial-forms}$ contains exactly one element, then evaluate the single element of $\mlvar{serial-forms}$ with respect to $\lexenv$, $\dynenv$, and $k$. Otherwise, evaluate the first element of $\mlvar{serial-forms}$ with respect to $\lexenv$, $\dynenv$, and a $\serialform$ continuation capturing $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\serialform(\mlvar{serial-forms},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, invoke the auxiliary function $\evalserialformforms$ on $\mlvar{serial-forms}$ minus its first element, $\lexenv$, $\dynenv$, and $k$.
To evaluate (if $\mlvar{test-form}$ $\mlvar{then-form}$ $\mlvar{else-form}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{test-form}$ with respect to $\lexenv$, $\dynenv$, and an $\iftestform$ continuation capturing $\mlvar{then-form}$, $\mlvar{else-form}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\iftestform(\mlvar{then-form},\mlvar{else-form},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{test}$ be the primary value of $\outcome$. If $\mlvar{test}$ is not a boolean, then invoke $k$ on an abrupt completion reason of type error. If $\mlvar{test}$ is the boolean #t, then evaluate $\mlvar{then-form}$ with respect to $\lexenv$, $\dynenv$, and $k$. If $\mlvar{test}$ is the boolean #f, then evaluate $\mlvar{else-form}$ with respect to $\lexenv$, $\dynenv$, and $k$.
To evaluate (_for-each $\mlvar{function-form}$ $\mlvar{list-form}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{function-form}$ with respect to $\lexenv$, $\dynenv$, and a $\foreachfunctionform$ continuation capturing $\mlvar{list-form}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\foreachfunctionform(\mlvar{list-form},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{function}$ be the primary value of $\outcome$. If $\mlvar{function}$ is not a function, then invoke $k$ on an abrupt completion reason of type error. Otherwise, evaluate $\mlvar{list-form}$ with respect to $\lexenv$, $\dynenv$, and a $\foreachlistform$ continuation capturing $\mlvar{function}$, $\dynenv$, and $k$.
To invoke the continuation $\foreachlistform(\mlvar{function},\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{list}$ be the primary value of $\outcome$. If $\mlvar{list}$ is not a proper list, then invoke $k$ on an abrupt completion reason of type error. Otherwise, invoke the auxiliary function $\foreach$ on $\mlvar{function}$, $\mlvar{list}$, $\dynenv$, and $k$.
To invoke the auxiliary function $\foreach$ on $\mlvar{function}$, $\mlvar{list}$, $\dynenv$, and $k$, do the following:
If $\mlvar{list}$ is empty, then invoke $k$ on #v. Otherwise, invoke the auxiliary function $\invoke$ on $\mlvar{function}$, the car of $\mlvar{list}$, $\dynenv$, and a $\foreachinvocation$ continuation capturing $\mlvar{function}$, $\mlvar{list}$, $\dynenv$, and $k$.
To invoke the continuation $\foreachinvocation(\mlvar{function},\mlvar{list},\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, invoke the auxiliary function $\foreach$ on $\mlvar{function}$, the cdr of $\mlvar{list}$, $\dynenv$, and $k$.
To evaluate (_vlambda $\mlvar{parameter-list}$ $\mlvar{body}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (_mlambda $\mlvar{parameter-list}$ $\mlvar{body}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (_flambda $\mlvar{parameter-list}$ $\mlvar{body}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (_dlambda $\mlvar{parameter-list}$ $\mlvar{body}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Invoke $k$ on a closure recording the lambda abstraction and $\lexenv$.
To evaluate (vref $\mlvar{variable}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (fref $\mlvar{variable}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (dref $\mlvar{variable}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
If there exists a binding for $\mlvar{variable}$, then invoke $k$ on the value of that binding. Otherwise, invoke $k$ on an abrupt completion reason of type error.
To evaluate (vset! $\mlvar{variable}$ $\mlvar{value-form}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (fset! $\mlvar{variable}$ $\mlvar{value-form}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (dset! $\mlvar{variable}$ $\mlvar{value-form}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{value-form}$ with respect to $\lexenv$, $\dynenv$, and a $\setvalueform$ continuation capturing $\mlvar{variable}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\setvalueform(\mlvar{variable},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{value}$ be the primary value of $\outcome$. If there exists a binding for $\mlvar{variable}$, then replace the value of that binding by $\mlvar{value}$ and invoke $k$ on $\mlvar{value}$. Otherwise, create a new binding between $\mlvar{variable}$ and $\mlvar{value}$ and invoke $k$ on $\mlvar{value}$.
To evaluate (block $\mlvar{block-name}$ $\mlvar{serial-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Let $\mlvar{exit-tag}$ be a new uninterned variable. Invoke the auxiliary function $\evalserialforms$ on $\mlvar{serial-forms}$, the environment extending $\lexenv$ to bind, in the block namespace, the variable $\mlvar{block-name}$ to $\mlvar{exit-tag}$, the environment extending $\dynenv$ to bind, in the exit-point namespace, the variable $\mlvar{exit-tag}$ to #v, and a $\blockserialforms$ continuation capturing $\mlvar{exit-tag}$ and $k$.
To invoke the continuation $\blockserialforms(\mlvar{exit-tag},k)$ on $\outcome$, do the following:
If $result$ is an abrupt completion reason of type nonlocal-exit carrying an exit tag eq? to $\mlvar{exit-tag}$, then invoke $k$ on the values carried by $\outcome$. Otherwise, invoke $k$ on $\outcome$.
To evaluate (return-from $\mlvar{block-name}$ $\mlvar{values-form}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
If there exists no binding for the variable $\mlvar{block-name}$ in the block namespace of $\lexenv$, then invoke $k$ on an abrupt completion reason of type error. Otherwise, let $\mlvar{exit-tag}$ be the value of the binding for the variable $\mlvar{block-name}$ in the block namespace of $\lexenv$. If there exists no binding for the variable $\mlvar{exit-tag}$ in the exit-point namespace of $\dynenv$, then invoke $k$ on an abrupt completion reason of type error. Otherwise, evaluate $\mlvar{values-form}$ with respect to $\lexenv$, $\dynenv$, and a $\returnfromvaluesform$ continuation capturing $\mlvar{exit-tag}$ and $k$.
To invoke the continuation $\returnfromvaluesform(\mlvar{exit-tag},k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, invoke $k$ on an abrupt completion reason of type nonlocal-exit carrying $\mlvar{exit-tag}$ and $\outcome$.
To evaluate (catch $\mlvar{exit-tag-form}$ $\mlvar{serial-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{exit-tag-form}$ with respect to $\lexenv$, $\dynenv$, and a $\catchexittagform$ continuation capturing $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\catchexittagform(\mlvar{serial-forms},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{exit-tag}$ be the primary value of $\outcome$. If $\mlvar{exit-tag}$ is not a variable, then invoke $k$ on an abrupt completion reason of type error. Otherwise, invoke the auxiliary function $\evalserialforms$ on $\mlvar{serial-forms}$, $\lexenv$, the environment extending $\dynenv$ to bind, in the exit-point namespace, the variable $\mlvar{exit-tag}$ to #v, and a $\catchserialforms$ continuation capturing $\mlvar{exit-tag}$ and $k$.
To invoke the continuation $\catchserialforms(\mlvar{exit-tag},k)$ on $\outcome$, do the following:
If $result$ is an abrupt completion reason of type nonlocal-exit carrying an exit tag eq? to $\mlvar{exit-tag}$, then invoke $k$ on the values carried by $\outcome$. Otherwise, invoke $k$ on $\outcome$.
To evaluate (throw $\mlvar{exit-tag-form}$ $\mlvar{values-form}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{exit-tag-form}$ with respect to $\lexenv$, $\dynenv$, and a $\throwexittagform$ continuation capturing $\mlvar{values-form}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\throwexittagform(\mlvar{values-form},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ $\outcome$. Otherwise, let $\mlvar{exit-tag}$ be the primary value of $\outcome$. If $\mlvar{exit-tag}$ is not a variable, then invoke $k$ on an abrupt completion reason of type error. Otherwise, if there exists no binding for the variable $\mlvar{exit-tag}$ in the exit-point namespace of $\dynenv$, then invoke $k$ on an abrupt completion reason of type error. Otherwise, evaluate $\mlvar{values-form}$ with respect to $\lexenv$, $\dynenv$, and a $\throwvaluesform$ continuation capturing $\mlvar{exit-tag}$ and $k$.
To invoke the continuation $\throwvaluesform(\mlvar{exit-tag},k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, invoke $k$ on an abrupt completion reason of type nonlocal-exit carrying $\mlvar{exit-tag}$ and $\outcome$.
To evaluate (_handler-bind $\mlvar{handler-form}$ $\mlvar{serial-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{handler-form}$ with respect to $\lexenv$, $\dynenv$, and a $\handlerbindhandlerform$ continuation capturing $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\handlerbindhandlerform(\mlvar{serial-forms},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{handler}$ be the primary value of $\outcome$. If $\mlvar{handler}$ is not a function, then invoke $k$ on an abrupt completion reason of type error. Otherwise, invoke the auxiliary function $\evalserialforms$ on $\mlvar{serial-forms}$, $\lexenv$, $\dynenv$, and a $\handlerbindserialforms$ continuation capturing $\mlvar{handler}$, $\dynenv$, and $k$.
To invoke the continuation $\handlerbindserialforms(\mlvar{handler},\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason of type error, then invoke the auxiliary function $\invoke$ on $\mlvar{handler}$, the category and description carried by $\outcome$, $\dynenv$, and a $\handlerbindinvocation$ continuation capturing $\mlvar{outcome}$ and $k$. Otherwise, invoke $k$ on $\outcome$.
To invoke the continuation $\handlerbindinvocation(\mlvar{serial-forms-outcome},k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\mlvar{outcome}$. Otherwise, invoke $k$ on $\mlvar{serial-forms-outcome}$.
To evaluate (unwind-protect $\mlvar{protected-form}$ $\mlvar{cleanup-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{protected-form}$ with respect to $\lexenv$, $\dynenv$, and an $\unwindprotectprotectedform$ continuation capturing $\mlvar{cleanup-forms}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\unwindprotectprotectedform(\mlvar{cleanup-forms},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
Invoke the auxiliary function $\evalserialforms$ on $\mlvar{cleanup-forms}$, $\lexenv$, $\dynenv$, and an $\unwindprotectcleanupforms$ continuation capturing $\outcome$ and $k$.
To invoke the continuation $\unwindprotectcleanupforms(\mlvar{protected-form-outcome},k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, invoke $k$ on $\mlvar{protected-form-outcome}$.
To evaluate ($\mlvar{operator-form}$ $\mlvar{operand-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (apply $\mlvar{operator-form}$ $\mlvar{operand-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (multiple-value-call $\mlvar{operator-form}$ $\mlvar{operand-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
To evaluate (multiple-value-apply $\mlvar{operator-form}$ $\mlvar{operand-forms}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Evaluate $\mlvar{operator-form}$ with respect to $\lexenv$, $\dynenv$, and a $\functioncalloperatorform$ continuation capturing $\mlvar{operand-forms}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\functioncalloperatorform(\mlvar{operand-forms},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{function}$ be the primary value of $\outcome$. If $\mlvar{function}$ is not a function, then invoke $k$ on an abrupt completion reason of type error. Otherwise, invoke the auxiliary function $\evaloperandforms$ on $\mlvar{function}$, $\mlvar{operand-forms}$, $[]$, $\lexenv$, $\dynenv$, and $k$.
To invoke the auxiliary function $\evaloperandforms$ on $\mlvar{function}$, $\mlvar{operand-forms}$, $\mlvar{arguments}$, $\lexenv$, $\dynenv$, and $k$, do the following:
If $\mlvar{operand-forms}$ is empty, then invoke the auxiliary function $\invoke$ on $\mlvar{function}$, $\mlvar{arguments}$, $\dynenv$, and $k$. Otherwise, evaluate the first element of $\mlvar{operand-forms}$ with respect to $\lexenv$, $\dynenv$, and a $\functioncalloperandform$ continuation capturing $\mlvar{function}$, $\mlvar{operand-forms}$, $\mlvar{arguments}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\functioncalloperandform(\mlvar{function},\mlvar{operand-forms},\mlvar{arguments},\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, let $\mlvar{augmented-arguments}$ be the result of appending the primary value of $\outcome$ or all the values of $\outcome$ to $\mlvar{arguments}$. Invoke the auxiliary function $\evaloperandforms$ on $\mlvar{function}$, $\mlvar{operand-forms}$ minus its first element, $\mlvar{augmented-arguments}$, $\lexenv$, $\dynenv$, and $k$.
To invoke the auxiliary function $\invoke$ on $\mlvar{function}$, $\mlvar{arguments}$, $\dynenv$, and $k$, do the following:
If $\mlvar{function}$ is a primitive function, then invoke $k$ on the outcome of the invocation of the JavaScript function implementing $\mlvar{function}$ on $\mlvar{arguments}$. If $\mlvar{function}$ is a closure, then invoke the auxiliary function $\evalserialforms$ on the body of the lambda abstraction recorded by the closure, the lexical environment recorded by the closure or an extension thereof, $\dynenv$ or an extension thereof, and $k$.
To evaluate ($\mlvar{macro-operator}$ $\mlvar{macro-operands}$) with respect to $\lexenv$, $\dynenv$, and $k$, do the following:
Let $\mlvar{macro}$ be the macro named by $\mlvar{macro-operator}$. Invoke the auxiliary function $\invoke$ on $\mlvar{macro}$, $\mlvar{macro-operands}$, $\dynenv$, and a $\macro$ continuation capturing $\lexenv$, $\dynenv$, and $k$.
To invoke the continuation $\macro(\lexenv,\dynenv,k)$ on $\outcome$, do the following:
If $\outcome$ is an abrupt completion reason, then invoke $k$ on $\outcome$. Otherwise, evaluate the primary value of $\outcome$ with respect to $\lexenv$, $\dynenv$, and $k$.