CSc 520 Principles of Programming Languages

Similar documents
A Brief Introduction to Scheme (II)

Project 2: Scheme Interpreter

An Explicit-Continuation Metacircular Evaluator

Functional Programming. Pure Functional Programming

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

CSc 520. Principles of Programming Languages 7: Scheme List Processing

Turtles All The Way Down

CSc 520 Principles of Programming Languages. Examining Lists. Constructing Lists... 7: Scheme List Processing

Discussion 12 The MCE (solutions)

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

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

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

CS61A Midterm 2 Review (v1.1)

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

Building a system for symbolic differentiation

Documentation for LISP in BASIC

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

6.034 Artificial Intelligence February 9, 2007 Recitation # 1. (b) Draw the tree structure corresponding to the following list.

LECTURE 16. Functional Programming

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

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

Functional Languages. Hwansoo Han

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

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

Programming Languages

Introduction to Scheme

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

ALISP interpreter in Awk

Building a system for symbolic differentiation

regsim.scm ~/umb/cs450/ch5.base/ 1 11/11/13

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

6.001: Structure and Interpretation of Computer Programs

CSc 520 Principles of Programming Languages

Scheme Quick Reference

Vectors in Scheme. Data Structures in Scheme

Scheme: Strings Scheme: I/O

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

Functional Programming. Pure Functional Languages

CS 360 Programming Languages Interpreters

Functional Programming. Big Picture. Design of Programming Languages

Principles of Programming Languages Topic: Functional Programming Professor L. Thorne McCarty Spring 2003

Functional Programming

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

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

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

This exam is worth 70 points, or about 23% of your total course grade. The exam contains 15 questions.

CS 314 Principles of Programming Languages

Intro. Scheme Basics. scm> 5 5. scm>

COP4020 Programming Assignment 1 - Spring 2011

Essentials of Programming Languages Language

Essentials of Programming Languages Language

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

How to Design Programs Languages

Scheme Quick Reference

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

SCHEME AND CALCULATOR 5b

An Introduction to Scheme

(scheme-1) has lambda but NOT define

Functional Programming. Pure Functional Languages

Normal Order (Lazy) Evaluation SICP. Applicative Order vs. Normal (Lazy) Order. Applicative vs. Normal? How can we implement lazy evaluation?

FP Foundations, Scheme

Notes on Higher Order Programming in Scheme. by Alexander Stepanov

CS 275 Name Final Exam Solutions December 16, 2016

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

CS 61A Interpreters, Tail Calls, Macros, Streams, Iterators. Spring 2019 Guerrilla Section 5: April 20, Interpreters.

SOFTWARE ARCHITECTURE 6. LISP

4/19/2018. Chapter 11 :: Functional Languages

Principles of Programming Languages

Organization of Programming Languages CS3200/5200N. Lecture 11

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

From Syntactic Sugar to the Syntactic Meth Lab:

Symbolic Programming. Dr. Zoran Duric () Symbolic Programming 1/ 89 August 28, / 89

Lecture Notes on Lisp A Brief Introduction

Data abstraction, revisited

INTRODUCTION TO SCHEME

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

CS 314 Principles of Programming Languages. Lecture 16

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

Simplifying Logical Formulas

Sample Final Exam Questions

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

6.945 Adventures in Advanced Symbolic Programming

Evaluating Scheme Expressions

CSC 533: Programming Languages. Spring 2015

CS 480. Lisp J. Kosecka George Mason University. Lisp Slides

Procedural abstraction SICP Data abstractions. The universe of procedures forsqrt. Procedural abstraction example: sqrt

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

Functional Programming - 2. Higher Order Functions

CS61A Summer 2010 George Wang, Jonathan Kotker, Seshadri Mahalingam, Eric Tzeng, Steven Tang

TAIL RECURSION, SCOPE, AND PROJECT 4 11

Important Example: Gene Sequence Matching. Corrigiendum. Central Dogma of Modern Biology. Genetics. How Nucleotides code for Amino Acids

Lexical vs. Dynamic Scope

University of Massachusetts Lowell

Lisp Basic Example Test Questions

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

1.3. Conditional expressions To express case distinctions like

4.2 Variations on a Scheme -- Lazy Evaluation

Fifth Generation CS 4100 LISP. What do we need? Example LISP Program 11/13/13. Chapter 9: List Processing: LISP. Central Idea: Function Application

Comp 311: Sample Midterm Examination

CS 314 Principles of Programming Languages

Transcription:

CSc 520 Principles of Programming Languages 9: Scheme Metacircular Interpretation Christian Collberg collberg@cs.arizona.edu Department of Computer Science University of Arizona Copyright c 2005 Christian Collberg [1]

Introduction In this lecture I m going to show how you can define Scheme by writing a metacircular interpreter for the language, i.e. an interpreter for Scheme written in Scheme. Before we can do that, we first need to learn a few more this about the language [2]

Let Expressions A let-expression binds names to values: (let ((name 1 value 1 ) (name 2 value 2 )...) expression) The first argument to let is a list of (name value) pairs. The second argument is the expression to evaluate. > (let ((a 3) (b 4) (square (lambda (x)(* x x))) (plus +)) (sqrt (plus (square a) (square b)))) 5.0 [3]

Let Expressions... Let-expressions can be nested: > (let ((x 5) (c 4)) (let ((v (* 4 x)) (t (* 2 c))) (+ v t))) 28 [4]

Imperative Features Scheme is an impure functional language. I.e., Scheme has imperative features. I.e., in Scheme it is possible to program with side-effects. (set! var value) Change the value of var to value. (set-car! var value) Change the car-field of the cons-cell var to value. (set-cdr! var value) Change the cdr-field of the cons-cell var to value. [5]

Imperative Features... Example: > (let ((x 2) (l (a b))) (set! x 3) (set-car! l (c d)) (set-cdr! l (e)) (display x) (newline) (display l) (newline)) 3 ((c d) e) [6]

Dotted Pairs S-expressions are constructed using dotted pairs. It is implemented as a struct (called a cons-cell) consisting of two fields (the size of a machine word) called car and cdr. We can manipulate these fields directly: > (1. 2) (1. 2) > (cons "stacy s" "mom") ("stacy s". "mom") > (1. (2. 3)) (1 2. 3) > (cons 1 2) (1. 2) [7]

Dotted Pairs... When the second part of a dottend pair (the cdr-field) is a list, and the innermost cdr-field is the empty list, we get a normal Scheme list: > (1. ()) (1) > (1. (2. ())) (1 2) > (1. (2 3)) (1 2 3) [8]

Dotted Pairs... We can use set-car! and set-cdr! to manipulate the fields of a cons-cell directly: > (define x (1. 2)) > (set-car! x a) > x (a. 2) > (set-cdr! x (2 3)) > x (a 2 3) [9]

Dotted Pairs... (cons A B) can be thought of as first creating a cons-cell on the heap (using malloc, for example), and then setting the car and cdr fields to A and B, respectively: > (define x (cons 0 0)) > x (0. 0) > (set-car! x 1) > (set-cdr! x ()) > x (1) [10]

Loops Scheme s for-loop do takes these arguments: 1. A list of triples (var init update) which declares a variable var, with an initial value init, and which gets updated using the expression update, on each iteration; 2. A pair (termination_cond return_value) which gives the termination condition and return value of the loop; and 3. a loop body: (do ((var1 init1 update1) (var12 init2 update2) ) (termination cond return value) loop body ) [11]

Loops... Sum the numbers 1 to 4, printing out intermediate results: > (do ((i 1 (+ i 1)) (sum 0 (+ sum i))) ((= i 5) sum) (display sum) (newline) ) 0 1 3 6 10 [12]

Association Lists Association lists are simply lists of key-value pairs that can be searched sequentially: > (assoc bob ((bob 22) (joe 32) (bob 3))) (bob 22) The list is searchedy the list from beginning to end, returning the first pair with a matching key: (assoc key alist) Search for key; compare using equal?. (assq key alist) Search for key; compare using eq?. (assv key alist) Search for key; compare using eqv?. [13]

Association Lists... > (define e ((a 1) (b 2) (c 3))) > (assq a e) (a 1) > (assq b e) (b 2) > (assq d e) #f > (assq (list a) (((a)) ((b)) ((c)))) #f > (assoc (list a) (((a)) ((b)) ((c)))) ((a)) > (assv 5 ((2 3) (5 7) (11 13))) (5 7) [14]

Association Lists... We can actually have more than one value: > (assoc bob ((bob 5 male) (jane 32 female))) (bob 5 male) [15]

Apply Apply returns the result of applying its first argument to its second argument. > (apply + (6 7)) 13 > (apply max (2 5 1 7)) 7 [16]

Eval (eval arg) evaluates its argument. > (eval (+ 4 5)) 9 > (eval (cons a (b c))) (a b c) [17]

Eval... eval and quote are each other s inverses: > (eval (+ 4 5)) (+ 4 5) > (eval (eval (+ 4 5))) 9 > (eval (eval (eval (+ 4 5)))) 9 [18]

Programs as Data Scheme is homoiconic, self-representing, i.e. programs and data are both represented the same (as S-expressions). This allows us to write programs that generate programs - useful in AI, for example. > (define x car) > (define y (a b c)) > (define p (list x y)) > p (car (a b c)) > (eval p) a [19]

Evaluation Order So far, we have said that to evaluate an expression (op arg1 arg2 arg3) we first evaluate the arguments, then apply the operator op to the resulting values. This is known as applicative-order evaluation. Example: (define (double x) (* x x)) > (double (* 3 4)) (double 12) (+ 12 12) 24 [20]

Evaluation Order... This is not the only possible order of evaluation In normal-order evaluation parameters to a function are always passed unevaluated. This sometimes leads to extra work: (define (double x) (* x x)) > (double (* 3 4)) (+ (* 3 4) (* 3 4))) (+ 12 (* 3 4)) (+ 12 12) 24 [21]

Evaluation Order... Applicative-order can sometimes also lead to more work than normal-order: (define (switch x a b c) (cond ((< x 0) a) ((= x 0) b) ((> x 0) c))) > (switch -1 (+ 1 2) (+ 2 3) (+ 3 4)) Here, applicative-order evaluates all the arguments, although only one value will ever be needed. [22]

Evaluation Order... Ordinary Scheme functions (such as +, car, etc) use applicative-order evaluation. Some special forms (cond, if, etc) must use normal order since they need to consume their arguments unevaluated: > (if #t (display 5) (display 6)) 5 > (cond (#f (display 5)) (#f (display 6)) (#t (display 7))) 7 [23]

A Metacircular Interpreter One way to define the semantics of a language (the effects that programs written in the language will have), is to write a metacircular interpreter. I.e, we define the language by writing an interpreter for it, in the language itself. A metacircular interpreter for Scheme consists of two mutually recursive functions, meval and mapply: (define (meval Expr) ) (define (mapply Op Args) ) [24]

A Metacircular Interpreter... We want to be able to call our interpreter like this: > (meval (+ 1 2)) 3 > (meval (+ 1 (* 3 4))) 13 > (meval (quote (2 3))) (2 3) > (meval (car (quote (1 2)))) 1 [25]

A Metacircular Interpreter... > (meval (cdr (quote (1 2)))) (2) > (meval (cons (quote 5) (quote (1 2)))) (5 1 2) > (meval (null? (quote (1 2)))) #f > (meval (null? (quote ()))) #t > (meval (if (eq? 1 1) 5 6)) 5 [26]

A Metacircular Interpreter... meval handles primitive special forms (lambda, if, const, define, quote, etc), itself. Note that, for these forms, we must use normal-order evaluation. For other expressions, meval evaluates all arguments and calls mapply to perform the required operation: [27]

A Metacircular Interpreter... (define (meval Expr) (cond [(null? Expr) ()] [(number? Expr) Expr] [(eq? (car Expr) if) (mevalif (cadr Expr) (caddr Expr) (cadddr Expr))] [(eq? (car Expr) quote) (cadr Expr)] [else (mapply (car Expr) (mevallist (cdr Expr)))] ) ) [28]

A Metacircular Interpreter... mapply checks if the operation is one of the builtin primitive ones, and if so performs the required operation: (define (mapply Op Args) (case Op [(car) (caar Args)] [(cdr) (cdar Args)] [(cons) (cons (car Args) (cadr Args))] [(eq?) (eq? (car Args) (cadr Args))] [(null?) (null? (car Args))] [(+) (+ (car Args) (cadr Args))] [(*) (* (car Args) (cadr Args))] ) ) [29]

A Metacircular Interpreter... Some auxiliary functions: (define (mevalif b t e) (if (meval b) (meval t) (meval e)) ) (define (mevallist List) (cond [(null? List) ()] [else (cons (meval (car List)) (mevallist (cdr List)))] ) ) [30]

A Metacircular Interpreter... Note that this little interpreter lacks many of Scheme s functions. We don t have symbols, lambda, define. We can t define or invoke user-defined functions. There are no way to define or lookup variables, local or global. To do that, meval and mapply pass around environments (association lists) of variable/value pairs. [31]

Readings and References Read Scott, pp. 592 606, 609-610 [32]