211 lines
8.8 KiB
Racket
211 lines
8.8 KiB
Racket
#reader(lib "docreader.ss" "scribble")
|
|
@require["mz.ss"]
|
|
|
|
@title[#:tag "mz:syntax"]{Core Syntactic Forms}
|
|
|
|
A syntactic form is described by a BNF-like notation that describes a
|
|
combination of (syntax-wrapped) pairs, symbols, and other data (not a
|
|
sequence of characters):
|
|
|
|
@itemize{
|
|
|
|
@item{@scheme[...] indicates zero or more
|
|
repetitions of the preceding datum.}
|
|
|
|
@item{@scheme[...+] indicates one or
|
|
more repetitions of the preceding datum.}
|
|
|
|
@item{@scheme[?] means zero instances or one instance
|
|
of the preceding datum.}
|
|
|
|
@item{Italic sequences of characters play the role of non-terminals. In
|
|
particular:
|
|
|
|
@itemize{
|
|
|
|
@item{A sequence that ends in @scheme[_id] refers to a
|
|
syntax-wrapped symbol.}
|
|
|
|
@item{A sequence that ends in @scheme[_keyword] refers to a
|
|
syntax-wrapped keyword.}
|
|
|
|
@item{A sequence that end with @scheme[_expr] refers to a sub-form
|
|
that is expanded as an expression.}
|
|
}}
|
|
}
|
|
|
|
@;------------------------------------------------------------------------
|
|
@section{Variable Reference}
|
|
|
|
@defform/none[id]{
|
|
|
|
A reference to a module-level or local binding, when @scheme[id] is
|
|
not bound as a transformer (see @secref["mz:expansion"]). At run-time,
|
|
the reference evaluates to the value in the location associated with
|
|
the binding.
|
|
|
|
When the expander encounters an @scheme[id] that is not bound by a
|
|
module or local binding, it converts the expression to @scheme[(#%top
|
|
. id)].}
|
|
|
|
@defform[(#%top . id)]{
|
|
|
|
A reference to a top-level definition that could bind @scheme[id],
|
|
even if @scheme[id] has a local binding in its context. Such
|
|
references are disallowed anywhere within a @scheme[module] form.}
|
|
|
|
@;------------------------------------------------------------------------
|
|
@section{Procedure Application}
|
|
|
|
@defform/none[(proc-expr arg ...)]{
|
|
|
|
A procedure application, normally, when @scheme[proc-expr] is not an
|
|
identifier that has a transformer binding (see
|
|
@secref["mz:expansion"]).
|
|
|
|
More precisely, the expander converts this form to @scheme[(#,
|
|
@schemeidfont{#%app} proc-expr arg ...)] using the lexical
|
|
context for @schemeidfont{#%app} that is associated with the original
|
|
form (i.e., the pair that combines @scheme[proc-expr] and its
|
|
arguments). Typically, the lexical context of the pair indicates the
|
|
procedure-application @scheme[#%app] that is described next.}
|
|
|
|
@defform[(#%app proc-expr arg ...)]{
|
|
|
|
A procedure application. Each @scheme[arg] is one of the following:
|
|
|
|
@specsubform[arg-expr]{The resulting value is a non-keyword
|
|
argument.}
|
|
|
|
@specsubform[(code:line keyword arg-expr)]{The resulting value is a
|
|
keyword argument using @scheme[keyword]. Each
|
|
@scheme[keyword] in the application must be distinct.}
|
|
|
|
The @scheme[proc-expr] and @scheme[_arg-expr]s are evaluated in order,
|
|
left to right. If the result of @scheme[proc-expr] is a procedure that
|
|
accepts as many arguments as non-@scheme[_keyword]
|
|
@scheme[_arg-expr]s, if it accepts arguments for all of the
|
|
e@scheme[_keyword]s in the application, and if all required
|
|
keyword-based arguments are represented among the @scheme[_keyword]s
|
|
in the application, then the procedure is called with the values of
|
|
the @scheme[arg-expr]s. Otherwise, the @exnraise[exn:fail:contract].
|
|
|
|
The continuation of the procedure call is the same as the continuation
|
|
of the application expression, so the result(s) of the application
|
|
expression is(are) the result(s) of the procedure.
|
|
|
|
The relative order of @scheme[_keyword]-based arguments matters only
|
|
for the order of @scheme[_arg-expr] evaluations; the arguments are
|
|
regonized by the applied procedure based on the @scheme[_keyword], and
|
|
not their positions. The other @scheme[_arg-expr] values, in contrast,
|
|
are recognized by the applied procedure according to their order in
|
|
the application form.}
|
|
|
|
|
|
@;------------------------------------------------------------------------
|
|
@section{Procedure Expression: @scheme[lambda] and @scheme[case-lambda]}
|
|
|
|
@defform[(lambda formals* body-expr ...+)]{
|
|
|
|
An expression that procedures a procedure. The @scheme[formals*]
|
|
determines the number of arguments that the procedure accepts. It is
|
|
either a simple @scheme[_formals], or one of the extended forms.
|
|
|
|
A simple @scheme[_formals] has one of the following three forms:
|
|
|
|
@specsubform[(id ... )]{ The procedure accepts as many non-keyword
|
|
argument values as the number of @scheme[id]s. Each @scheme[id]
|
|
is associated with an argument value by position.}
|
|
|
|
@specsubform[(id ...+ . rest-id)]{ The procedure accepts any number of
|
|
non-keyword arguments greater or equal to the number of
|
|
@scheme[id]s. When the procedure is applied, the @scheme[id]s
|
|
are associated with argument values by position, and all
|
|
leftover arguments are placed into a list that is associated to
|
|
@scheme[rest-id].}
|
|
|
|
@specsubform[rest-id]{ The procedure accepts any number of non-keyword
|
|
arguments. All arguments are placed into a list that is
|
|
associated with @scheme[rest-id].}
|
|
|
|
In addition to the form of a @scheme[_formals], a @scheme[formals*]
|
|
can be a sequence of @scheme[_formal*]s optionally ending with a
|
|
@scheme[rest-id]:
|
|
|
|
@specsubform[(formal* ...)]{ Each @scheme[formal*] has the following
|
|
four forms:
|
|
|
|
@specsubform[id]{Adds one to both the minimum and maximum
|
|
number of non-keyword arguments accepted by the procedure. The
|
|
@scheme[id] is associated with an actual argument by
|
|
position.}
|
|
|
|
@specsubform[[id default-expr]]{Adds one to the maximum number
|
|
of non-keyword arguments accepted by the procedure. The
|
|
@scheme[id] is associated with an actual argument by position,
|
|
and if no such argument is provided, the @scheme[default-expr]
|
|
is evaluated to produce a value associated with @scheme[id].
|
|
No @scheme[formal*] with a @scheme[default-expr] can appear
|
|
before an @scheme[id] without a @scheme[default-expr] and
|
|
without a @scheme[keyword].}
|
|
|
|
@specsubform[(code:line keyword id)]{The procedure requires a
|
|
keyword-based argument using @scheme[keyword]. The @scheme[id]
|
|
is associated with a keyword-based actual argument using
|
|
@scheme[keyword].}
|
|
|
|
@specsubform[(code:line keyword [id default-expr])]{The
|
|
procedure accepts a keyword-based using @scheme[keyword]. The
|
|
@scheme[id] is associated with a keyword-based actual argument
|
|
using @scheme[keyword], if supplied in an application;
|
|
otherwise, the @scheme[default-expr] is evaluated to obtain a
|
|
value to associate with @scheme[id].}
|
|
|
|
The position of a @scheme[_keyword] @scheme[formal*] in
|
|
@scheme[formals*] does not matter, but each specified
|
|
@scheme[_keyword] must be distinct.}
|
|
|
|
@specsubform[(formal* ...+ . rest-id)]{ Like the previous case, but
|
|
the procedure accepts any number of non-keyword arguments
|
|
beyond its minimum number of arguments. When more arguments are
|
|
provided than non-@scheme[_keyword] arguments among the @scheme[formal*]s,
|
|
the extra arguments are placed into a list that is associated to
|
|
@scheme[rest-id].}
|
|
|
|
The @scheme[formals*] identifiers are bound in the
|
|
@scheme[body-expr]s. When the procedure is applied, a new location is
|
|
created for each identifier, and the location is filled with the
|
|
associated argument value.
|
|
|
|
If any identifier appears in @scheme[body-expr]s that is not one of
|
|
the identifiers in @scheme[formals*], then it refers to the same
|
|
location that it would if it appears in place of the @scheme[lambda]
|
|
expression. (In other words, variable reference is lexically scoped.)
|
|
|
|
When multiple identifiers appear in a @scheme[formals*], they must be
|
|
distinct according to @scheme[bound-identifier=?].
|
|
|
|
If the procedure procedure by @scheme[lambda] is applied to fewer or
|
|
more arguments than it accepts, the @exnraise[exn:fail:contract]. If
|
|
@scheme[formals*] includes @scheme[keyword]s and an application
|
|
includes too few arguments before the keyword section, the same
|
|
keyword in multiple odd positions of the keyword section, or a keyword
|
|
that is not among the @scheme[formals*] @scheme[keyword]s in an odd
|
|
position of the keyword section, then the
|
|
@exnraise[exn:fail:contract].}
|
|
|
|
@defform[(case-lambda [formals body-expr ...+] ...)]{
|
|
|
|
An expression that procedure. Each @scheme[[forms body-expr ...+]]
|
|
clause is analogous to a single @scheme[lambda] procedure; applying
|
|
the @scheme[case-lambda]-generated procedure is the same as applying a
|
|
procedure that corresponds to one of the clauses---the first procedure
|
|
that accepts the given number of arguments. If no corresponding
|
|
procedure accepts the given number of arguments, the
|
|
@exnraise[exn:fail:contract].
|
|
|
|
Note that a @scheme[case-lambda] clause supports only
|
|
@scheme[formals], not the more general @scheme[_formals*] of
|
|
@scheme[lambda]. That is, @scheme[case-lambda] does not directly
|
|
support keyword and optional arguments for an inidvidual clause.}
|