Comp 311: Sample Midterm Examination

Similar documents
Functional Programming. Pure Functional Programming

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

CSE 413 Midterm, May 6, 2011 Sample Solution Page 1 of 8

Computer Science 21b (Spring Term, 2015) Structure and Interpretation of Computer Programs. Lexical addressing

Below are example solutions for each of the questions. These are not the only possible answers, but they are the most common ones.

6.037 Lecture 4. Interpretation. What is an interpreter? Why do we need an interpreter? Stages of an interpreter. Role of each part of the interpreter

Comp 411 Principles of Programming Languages Lecture 7 Meta-interpreters. Corky Cartwright January 26, 2018

CS 314 Principles of Programming Languages. Lecture 16

Fall Semester, The Metacircular Evaluator. Today we shift perspective from that of a user of computer langugaes to that of a designer of

Principles of Programming Languages

CSE341 Autumn 2017, Final Examination December 12, 2017

User-defined Functions. Conditional Expressions in Scheme

Lecture 09: Data Abstraction ++ Parsing is the process of translating a sequence of characters (a string) into an abstract syntax tree.

CS 314 Principles of Programming Languages

Discussion 12 The MCE (solutions)

CSE341: Programming Languages Lecture 17 Implementing Languages Including Closures. Dan Grossman Autumn 2018

CSE341, Spring 2013, Final Examination June 13, 2013

Why do we need an interpreter? SICP Interpretation part 1. Role of each part of the interpreter. 1. Arithmetic calculator.

;;; Determines if e is a primitive by looking it up in the primitive environment. ;;; Define indentation and output routines for the output for

Documentation for LISP in BASIC

Project 2: Scheme Interpreter

CS 415 Midterm Exam Spring SOLUTION

CSE 341, Spring 2011, Final Examination 9 June Please do not turn the page until everyone is ready.

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

C311 Lab #3 Representation Independence: Representation Independent Interpreters

CSSE 304 Assignment #13 (interpreter milestone #1) Updated for Fall, 2018

Announcements. The current topic: Scheme. Review: BST functions. Review: Representing trees in Scheme. Reminder: Lab 2 is due on Monday at 10:30 am.

11/6/17. Functional programming. FP Foundations, Scheme (2) LISP Data Types. LISP Data Types. LISP Data Types. Scheme. LISP: John McCarthy 1958 MIT

COP4020 Programming Assignment 1 - Spring 2011

CSE341 Spring 2017, Final Examination June 8, 2017

1 Lexical Considerations

Midterm 2 Solutions Many acceptable answers; one was the following: (defparameter g1

LECTURE 16. Functional Programming

Name EID. (calc (parse '{+ {with {x {+ 5 5}} {with {y {- x 3}} {+ y y} } } z } ) )

FP Foundations, Scheme

Principles of Programming Languages 2017W, Functional Programming

Building up a language SICP Variations on a Scheme. Meval. The Core Evaluator. Eval. Apply. 2. syntax procedures. 1.

CS61A Midterm 2 Review (v1.1)

Syntactic Sugar: Using the Metacircular Evaluator to Implement the Language You Want

CS61A Discussion Notes: Week 11: The Metacircular Evaluator By Greg Krimer, with slight modifications by Phoebus Chen (using notes from Todd Segal)

1.3. Conditional expressions To express case distinctions like

Lexical Considerations

Mid-Term 2 Grades

MIDTERM EXAMINATION - CS130 - Spring 2005

Lecture 12: Conditional Expressions and Local Binding

Procedures. EOPL3: Section 3.3 PROC and App B: SLLGEN

Streams, Delayed Evaluation and a Normal Order Interpreter. CS 550 Programming Languages Jeremy Johnson

CMSC 330: Organization of Programming Languages

Parsing Scheme (+ (* 2 3) 1) * 1

Turtles All The Way Down

Functional Programming. Big Picture. Design of Programming Languages

CS 342 Lecture 7 Syntax Abstraction By: Hridesh Rajan

Programming Languages

CS 275 Name Final Exam Solutions December 16, 2016

CSE341 Spring 2016, Final Examination June 6, 2016

CPSC 311, 2010W1 Midterm Exam #2

CSE341 Spring 2017, Final Examination June 8, 2017

CONCEPTS OF PROGRAMMING LANGUAGES Solutions for Mid-Term Examination

COP4020 Spring 2011 Midterm Exam

Functional abstraction. What is abstraction? Eating apples. Readings: HtDP, sections Language level: Intermediate Student With Lambda

Functional abstraction

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

From Syntactic Sugar to the Syntactic Meth Lab:

CS 342 Lecture 8 Data Abstraction By: Hridesh Rajan

Deferred operations. Continuations Structure and Interpretation of Computer Programs. Tail recursion in action.

CSE413 Midterm. Question Max Points Total 100

Principles of Programming Languages

Lecture 3: Expressions

CS 314 Principles of Programming Languages

UMBC CMSC 331 Final Exam

Write a procedure powerset which takes as its only argument a set S and returns the powerset of S.

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

An Explicit-Continuation Metacircular Evaluator

TAIL RECURSION, SCOPE, AND PROJECT 4 11

Lexical Considerations

Organization of Programming Languages CS3200/5200N. Lecture 11

A Brief Introduction to Scheme (II)

Lexical vs. Dynamic Scope

Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7

1. For every evaluation of a variable var, the variable is bound.

Functional Programming. Pure Functional Languages

Lecture 16: Object Programming Languages

CS 314 Principles of Programming Languages

Functional Programming

An Introduction to Scheme

A LISP Interpreter in ML

Functional Programming. Pure Functional Languages

Functions and Recursion. Dr. Philip Cannata 1

CSc 520 Principles of Programming Languages

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

Introduction to Scheme

Building a system for symbolic differentiation

CS 360 Programming Languages Interpreters

CS 415 Midterm Exam Fall 2003

G Programming Languages - Fall 2012

First-class continuations. call/cc, stack-passing CEK machines

Sample Final Exam Questions

;; definition of function, fun, that adds 7 to the input (define fun (lambda (x) (+ x 7)))

Typical workflow. CSE341: Programming Languages. Lecture 17 Implementing Languages Including Closures. Reality more complicated

Transcription:

Comp 311: Sample Midterm Examination October 29, 2007 Name: Id #: Instructions 1. The examination is closed book. If you forget the name for a Scheme operation, make up a name for it and write a brief explanation in the margin. 2. Fill in the information above and the pledge below. 3. There are 6 problems on the exam, totaling 100 points on the exam. 4. You have three hours to complete the exam. Pledge: 1

Problem 1. (10 points) Al Gaulle, a programmer for Kludge, Inc., is designing a simple extension language for a business software package. He is proposing the grammar for imperative Jam (Project 4) except for the following revision to the syntax for if-expressions: <if-exp> ::= if <exp> then <exp> else <exp> if <exp> then <exp> Do you see any problems with this specification (besides the questionable use of Jam as the foundation for his language), particularly his revision to Jam syntax? State your criticism precisely. His extension is a flawed design because the syntax is ambiguous. There are two distinct parse trees for the following expression: if flag1 then if flag2 then foo() else bar() The else clause can be associated with either of the two if expressions. or if flag1 then (if flag2 then foo() else bar()) if flag1 then (if flag2 then foo()) else bar() 2

Problem 2. (10 points) Al Gaulle is responsible for maintaining a Scheme program written by another programmer. In the middle of the program, Al notices the application ((lambda (f) (lambda (x) (map f x))) (lambda (z) (+ x z))) Al decides to optimize the program by reducing the application (using substitution) to (lambda (x) (map (lambda (z) (+ x z)) x) Did he optimize the program correctly? Why or why not? No. He did not optimize the program correctly. The reduction step ((lambda (f) (lambda (x) (map f x))) (lambda (z) (+ x z))) => (lambda (x) (map (lambda (z) (+ x z)) x) is incorrect because the free occurrence of x in (lambda (z) (+ x z))) is captured by the binding occurrence of x when is substitued for f in the body (lambda (x) (map f x))) To reduce the program fragment correctly, Al must rename x (to say l in (lambda (x) (map f x))) before performing the substitution yielding (lambda (l) (map (lambda (z) (+ x z)) l) 3

Problem 3. (20 points) Recall that Scheme let construct (which is not recursive) expands into lambda expressions as follows: abbreviates (let [(x1 E1) (x2 E2)... (xn En)] E)} ((lambda (x1 x2... xn) E) E1 E2... En) Similarly, the let* construct expands into let expressions as follows: abbreviates (let* [(x1 E1) (x2 E2)... (xn En)] E) (let [(x1 E1)] (let [(x2 E2)]... (let [(xn En)] E)...)) The other binding form in the Scheme let family is letrec; it has the same scoping rules as the Jam recursive let. For each of the two expressions on the next page, circle each binding occurrence of a variable and draw arrows from each bound occurrence back to the corresponding binding occurence. For example, given the expression (lambda (x) (+ x 1)) the correct answer is: (lambda (x) (+ x 1)) 4

1. (let* [(fib (lambda (n) (letrec [(fibhelp (lambda (m fn-1 fn-2) (let [(fn (+ fn-1 fn-2))] (if (zero? m) fn (fibhelp (sub1 m) fn fn-1)))))] (if (< n 2) 1 (fibhelp (sub1 n) 1 1))))) (fib100 (fib 100))] (* fib100 fib100)) 2. (let* [(pair (lambda (x y) (let [(x x) (y y)] (lambda (msg) (cond [(eq? msg first) x] [(eq? msg second) y] [else (error pair "illegal method name ~a" msg)]))))) (pair (pair 1 2))] (pair first)) 5

Problem 4. (20 points) The following Eval function interprets a subset of Jam with call-by-value semantics; it is a pruned version of the solution to Assignment 2. For the sake of pedagogic simplicity, functions have been restricted to a single argument, some Jam constructs and primitives have been eliminated, and almost all error checking has been removed. Modify Eval (which appears on the next page) to support a recursive let construct that binds only one identifier let fact := map n to...; in fact(100) The abstract syntax for the construct is (define-struct let-exp (id rhs body)) where id is the new identifier, rhs is an expression specifying what id is bound to, and body is the expression to be evaluated in the extended environment. A space gap has been left in the body of Eval so that you can easily insert your modification. (define-struct num-exp (arg)) (define-struct id-exp (arg)) (define-struct biop-exp (rator rand1 rand2)) (define-struct map-exp (var body)) (define-struct app-exp (rator rand)) (define-struct binding (var val)) (define-struct closure (parm body env)) ; unary functions only ; unary functions only ; unary functions only 6

(define-struct let-exp (id rhs body)) (define Eval (lambda (exp env) (cond ; bool, prim, unop, and if eliminated for pedagogic simplicity [(num-exp? exp) (num-exp-arg exp)] [(id-exp? exp) (binding-val (id-lookup (id-exp-arg exp) env))] [(biop-exp? exp) (local [(define rator (biop-exp-rator exp)) (define rand1 (Eval (biop-exp-rand1 exp) env)) (define rand2 (Eval (biop-exp-rand2 exp) env))] (cond [(eq? rator +) (+ rand1 rand2)] [(eq? rator -) (- rand1 rand2)] [else (error Eval "unrecognized binary operator ~a" rator)]))] [(map-exp? exp) (make-closure (map-exp-var exp) (map-exp-body exp) env)] [(app-exp? exp) (Apply (Eval (app-exp-rator exp) env) (Eval (app-exp-rand exp) env))] [(let-exp? exp) (local [(define var (let-exp-id exp)) (define rhs (let-exp-rhs exp)) (define body (let-exp-body exp)) (define let-env (cons (make-binding var (void)) env))] (begin (set-binding-val! let-env (Eval rhs let-env)) (Eval body new-env)))] [else (error Eval "illegal expression: ~a" exp)]))) (define extend (lambda (env var val) (cons (make-binding var val) env))) (define id-lookup ; returns binding pair not binding-val (lambda (id env) (cond [(eq? id (binding-var (car env))) (car env)] [else (id-lookup id (cdr env))]))) (define Apply (lambda (head arg-val) ; head must be a closure (local 7

[(define parm (closure-parm head)) (define body (closure-body head)) (define env (closure-env head))] (Eval body (extend env parm arg-val))))) The additional code required to support recursive let is enclosed above between pairs of horizontal lines. 8

Problem 5. (20 points) Let Jam have the semantics specified in assignment 3, i.e., map parameters are passed by name and let is recursive. Assume that Jam supports the primitive cons? as the recognizer for non-empty lists. Consider the Jam expression: let and := map x,y to if x then y else false; or := map x,y to if x then true else y; member := map x,l to and(cons?(l), or(x = first(l), member(x, cdr(l)))); in member(1, cons(1, null)) (i) Using explicit substitution, show the major steps in the evaluation of this expression. Please use abbreviations to shorten your trace. 9

(ii) Assume that Jam passes parameters by value rather than by name. Show the major steps in the evaluation of the preceding expression. Please use abbreviations to shorten your trace. 10

Problem 6. (20 points) Al Gaulle has designed the ultimate Algol dialect supporting passing parameters by value, by name, by reference, by result, and by value-result. For value-result parameter passing, assume that the argument evaluated once on entry to the procedure and that the resulting location is used on exit. Consider the following Algol-like program (written in Java-like notation): int i,j,a[5]; // a is an 5 element array with indices 0-4 void swap(int x, int y) { int temp = x; x = y; y = temp; } for (j = 0; j < 5; j++) a[j] := j; i := 1; swap(i,a[i+1]); write(i,a[2]); What numbers does the program print if both parameters in swap are passed by: 1. value? Just prior to the swap statement, a = {0,1,2,3,4} and i = 1. The call on swap has no effect on the actual parameters since they are passed by value. Hence, the program outputs: 1 2 2. reference? Just prior to the swap statement, a = {0,1,2,3,4} and i = 1. The call on swap swaps the contents of i and a[2], yielding a = {0,1,1,3,4} and i = 2. Hence, the program outputs: 2 1 3. name? Just prior to the swap statement, a = {0,1,2,3,4} and i = 1. Let us trace the call on swap in detail. Within the body of swap, x is 11

synonymous with the variable i; y is synonymous with the variable a[i+1]. temp is set to the contents of x (i) which is 1. x (i) is set to the contents of y (a[2]) which is 2. y (a[3] since i is now 2) is set to temp which is 1. On exit from swap, a = {0,1,2,1,4} and i = 2. Hence, the program outputs: 2 2 4. value-result? Just prior to swap statement, a = {0,1,2,3,4} and i = 1. After entering swap, x is bound to 1 and y is bound 2 just as in call-by-value. The left-hand value associated with x is the cell i and the left-hand value associated with y is the cell a[2]. Just before exiting swap, the values of x and y have been swapped: x = 2 and y = 1. Call-by-result stores 2 in i and 1 in a[2]. Hence, the program outputs: 2 1 Algol evaluates procedure arguments in left-to-right order. You can get partial credit if you show your hand evaluation of the code. Some answers may be indeterminate. Addendum Some additional potential topics for questions include: the basic properties of static and dynamic chains; simple questions the semantics of dynamic dispatch; questions about static distance coordinates (extra credit) questions about domain theory (continuity, monotonicity, etc.) 12