MASSACHVSETTS INSTITVTE OF TECHNOLOGY Department of Electrical Engineering and Computer Science 6.945 Spring 2009 Problem Set 4 Issued: Wed. 25 Feb. 2009 Due: Wed. 4 Mar. 2009 Reading: SICP, From Chapter 4: section 4.1.7--4.2 (from PS03) section 4.3; (pp. 412--437) Code: utils.scm, ghelper.scm, syntax.scm, rtdata.scm, load-analyze.scm, analyze.scm, repl.scm load-amb.scm, analyze-amb.scm repl-amb.scm multiple-dwelling.scm Heavy Evaluator Hacking In this problem set we build interpreters in a different direction. We start with the essential EVAL/APPLY interpreter, written as an analyzer of the syntax into a compiler of compositions of execution procedures -- a small combinator language. We will warm up by making modifications to this evaluator. Next, we will change the evaluator to include AMB expressions. To add AMB, the execution procedures will all have a different shape: in addition to the environment, each will take two "continuation procedures" SUCCEED and FAIL. In general, when a computation comes up with a value it will invoke SUCCEED with the proposed value and a complaint department which, if invoked, will try to produce an alternate value. If a computation cannot come up with a value, it will invoke the complaint department passed to it in the FAIL continuation. An important lesson to be learned here is how to use continuation procedures to partially escape the expression structure of the language. By construction, a functional expression has a unique value. However, in the AMB system an expression may be ambiguous as to its value... Think about how we arrange that to make sense! --------------------------------------------------------------------- Separating Syntactic Analysis from Execution (Compiling to Combinators) It is important to read SICP section 4.1.7 carefully here. When you load "load-analyze.scm" you will get an evaluator similar to the one described in this section. ------------- Problem 4.1: Warmup It is often valuable to have procedures that can take an indefinite number of arguments. The addition and multiplication procedures in Scheme are examples of such procedures. Traditionally, a user may specify such a procedure in a definition by making the bound-variable specification of a lambda expression a symbol rather than a list of formal parameters. That symbol is expected to be bound to the list of arguments supplied. For example, to make a procedure that takes several arguments and returns a list of the squares of the arguments supplied, one may write: (lambda x (map square x)) or (define (ss . x) (map square x)) and then (ss 1 2 3 4) ==> (1 4 9 16) Modify the analyzing interpreter to allow this construction. Hint: you do not need to change the code involving DEFINE or LAMBDA in syntax.scm! This is entirely a change in analyze.scm Demonstrate that your modification allows this kind of procedure, and that it does not cause other troubles. ------------- ------------- Problem 4.2: Infix notation Many people like infix notation for small arithmetic expressions. It is not hard to write a special form, (INFIX ), that takes a character string, parses it as an infix expression with the usual precedence rules, and reduces it to Lisp. Note that to do this you really don't have to delve into the combinator target mechanism of the evaluator, since this can be accomplished as a "macro" in the same way that COND and LET are implemented (see syntax.scm). So, for example, we should be able to write the program: (define (quadratic a b c) (let ((discriminant (infix "b**2-4*a*c"))) (infix "(-b+sqrt(discriminant))/(2*a)"))) Hint: Do not try to parse numbers! That is hard -- let Scheme do it for you: use string->number (see MIT Scheme documentation). Just pass the substring that specifies the number to string->number to get the numerical value. Write the INFIX special form, install it in the evaluator, and demonstrate that it works. Please! Unless you have lots of time to burn, do not write a complete infix parser for some entire language, like Python (easy) or Java (hard)! We just want parsing of simple arithmetic expressions. ------------- --------------------------------------------------------------------- AMB and Nondeterministic Programming Now comes the real fun part of this problem set! Please read section 4.3 of SICP carefully before starting this part. This interpreter requires a change in the interface structure of the combinators that code compiles into, so it is quite different. Of course, our system differs from the one in SICP in that it is implemented with generic extension capability. The loader for the interpreter extended for AMB is "load-analyze.scm". ------------- Problem 4.3: Warmup: Programming with AMB Run the multiple-dwelling program (to get a feeling for how to use the system). Do exercises 4.38, 4.39, and 4.40 (p. 419) from SICP. Note: we supply the multiple-dwelling.scm program so you need not type it in. ------------- ------------- Problem 4.4: Modify the AMB interpreter to record and report the number of alternatives examined in exploring a search space. What is this number for the simple multiple-dwelling program? For your best improvement of it from your work in exercise 4.40, above. -------------