~<#63607#>This subsection provides first glimpse at how to implement a Scheme interpreter. Section~#secinterpreter2#17707> refines this material.<#63607#>
DrScheme is itself a program, consisting of several parts. One function
checks whether the definitions and expressions we wrote down are
grammatical Scheme expressions. Another one evaluates Scheme
expressions. With what we have learned in this section, we can now develop
simple versions of these functions.
Our first task is to agree on a data representation for Scheme programs. In
other words, we must figure out how to represent a Scheme expression as a
piece of Scheme data. This sounds unusual, but it is not difficult. Suppose
we just want to represent numbers, variables, additions, and
multiplications for a start. Clearly, numbers can stand for numbers and
symbols for variables. Additions and multiplications, however, call for a
class of compound data because they consist of an operator and two
subexpressions.
A straightforward way to represent additions and multiplications is to use
two structures: one for additions and another one for multiplications.
Here are the structure definitions:
<#17712#>(define-struct<#17712#> <#17713#>add<#17713#> <#17714#>(left<#17714#> <#17715#>right))<#17715#>
<#17716#>(define-struct<#17716#> <#17717#>mul<#17717#> <#17718#>(left<#17718#> <#17719#>right))<#17719#>
Each structure has two components. One represents the left expression and
the other one the right expression of the operation.
rawhtml26
Let's look at some examples:
These examples cover all cases: numbers, variables, simple
expressions, and nested expressions.
<#17725#>Exercise 14.4.1<#17725#>
Provide a data definition for the representation of Scheme
expressions. Then translate the following expressions into representations:
- <#63608#><#17728#>(+<#17728#>\ <#17729#>10<#17729#>\ <#17730#>-10)<#17730#><#63608#>
- <#63609#><#17731#>(+<#17731#>\ <#17732#>(*<#17732#>\ <#17733#>20<#17733#>\ <#17734#>3)<#17734#>\ <#17735#>33)<#17735#><#63609#>
- <#63610#><#17736#>(*<#17736#>\ <#17737#>3.14<#17737#>\ <#17738#>(*<#17738#>\ <#17739#>r<#17739#>\ <#17740#>r))<#17740#><#63610#>
- <#63611#><#17741#>(+<#17741#>\ <#17742#>(*<#17742#>\ <#17743#>9/5<#17743#>\ <#17744#>c)<#17744#>\ <#17745#>32)<#17745#><#63611#>
- <#63612#><#17746#>(+<#17746#>\ <#17747#>(*<#17747#>\ <#17748#>3.14<#17748#>\ <#17749#>(*<#17749#>\ <#17750#>o<#17750#>\ <#17751#>o))<#17751#>\ <#17752#>(*<#17752#>\ <#17753#>3.14<#17753#>\ <#17754#>(*<#17754#>\ <#17755#>i<#17755#>\ <#17756#>i)))<#17756#><#63612#>~~~ Solution<#63613#><#63613#>
A Scheme evaluator is a function that consumes a representation of a Scheme
expression and produces its value. For example, the expression <#63614#><#17763#>3<#17763#><#63614#>
has the value <#63615#><#17764#>3<#17764#><#63615#>, <#63616#><#17765#>(+<#17765#>\ <#17766#>3<#17766#>\ <#17767#>5)<#17767#><#63616#> has the value <#63617#><#17768#>8<#17768#><#63617#>,
<#63618#><#17769#>(+<#17769#>\ <#17770#>(*<#17770#>\ <#17771#>3<#17771#>\ <#17772#>3)<#17772#>\ <#17773#>(*<#17773#>\ <#17774#>4<#17774#>\ <#17775#>4))<#17775#><#63618#> has the value <#63619#><#17776#>25<#17776#><#63619#>, <#17777#>etc<#17777#>. Since
we are ignoring definitions for now, an expression that contains a
variable, for example, <#63620#><#17778#>(+<#17778#>\ <#17779#>3<#17779#>\ <#17780#>x)<#17780#><#63620#>, does not have a value; after all,
we do not know what the variable stands for. In other words, our Scheme
evaluator should only be applied to representations of expressions that do
not contain variables. We say such expressions are <#17781#>numeric<#17781#>.
<#17782#>Exercise 14.4.2<#17782#>
Provide a data definition for numeric expressions. Develop the function
<#63621#><#17784#>numeric?<#17784#><#63621#>, which consumes (the representation of) a Scheme
expression and determines whether it is numeric.~ Solution<#63622#><#63622#>
<#17790#>Exercise 14.4.3<#17790#>
Develop the function <#63623#><#17792#>evaluate<#17792#><#63623#>. The function consumes (the
representation of) a Scheme expression. If the expression is numeric (see
exercise~#exschemenumeric#17793>), it produces the number that DrScheme
would produce for the actual Scheme expression. Otherwise, it returns
<#63624#><#17794#>false<#17794#><#63624#>.~ Solution<#63625#><#63625#>
When people evaluate expressions with variables, they first replace the
variables with values. Also, when people evaluate an application <#63626#><#17800#>(f<#17800#><#17801#> <#17801#><#17802#>a)<#17802#><#63626#> they replace <#63627#><#17803#>f<#17803#><#63627#>'s parameter with <#63628#><#17804#>a<#17804#><#63628#> in <#63629#><#17805#>f<#17805#><#63629#>'s
body. The following exercise concerns the substitution of variables with
values.
<#17806#>Exercise 14.4.4<#17806#>
Develop the function <#63630#><#17808#>subst<#17808#><#63630#>. The function consumes (the
representation of) a variable (<#63631#><#17809#>V<#17809#><#63631#>), a number (<#63632#><#17810#>N<#17810#><#63632#>), and
(the representation of) a Scheme expression. It produces a structurally
equivalent expression in which all occurrences of <#63633#><#17811#>V<#17811#><#63633#> are
substituted by <#63634#><#17812#>N<#17812#><#63634#>.~ Solution<#63635#><#63635#>