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

Similar documents
6.001, Spring Semester, 1998, Final Exam Solutions Your Name: 2 Part c: The procedure eval-until: (define (eval-until exp env) (let ((return (eval-seq

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

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

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

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

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

CS450 - Structure of Higher Level Languages

Functional Programming. Pure Functional Programming

Building a system for symbolic differentiation

Building a system for symbolic differentiation

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

Discussion 12 The MCE (solutions)

Code example: sfact SICP Explicit-control evaluator. Example register machine: instructions. Goal: a tail-recursive evaluator.

An Explicit-Continuation Metacircular Evaluator

cs61amt2_4 CS 61A Midterm #2 ver March 2, 1998 Exam version: A Your name login: cs61a- Discussion section number TA's name

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

CS61A Midterm 2 Review (v1.1)

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

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

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

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

Using Symbols in Expressions (1) evaluate sub-expressions... Number. ( ) machine code to add

CS 61A Midterm #2 ver March 2, 1998 Exam version: A. Your name. login: cs61a- Discussion section number. TA's name

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

Vectors in Scheme. Data Structures in Scheme

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

Project 2: Scheme Interpreter

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

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

Register Machines. Connecting evaluators to low level machine code

CSc 520 Principles of Programming Languages

CS 61A, Fall, 2002, Midterm #2, L. Rowe. 1. (10 points, 1 point each part) Consider the following five box-and-arrow diagrams.

CS 360 Programming Languages Day 14 Closure Idioms

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

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream?

Simplifying Logical Formulas

6.001, Spring Semester, 1998, Final Exam Your Name: 2 Question 1 (12 points): Each of the parts below should be treated as independent. For each part,

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

bindings (review) Topic 18 Environment Model of Evaluation bindings (review) frames (review) frames (review) frames (review) x: 10 y: #f x: 10

CS 314 Principles of Programming Languages

An Introduction to Scheme

Fall Semester, Lecture Notes { November 12, Variations on a Scheme Nondeterministic evaluation

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

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

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

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream? 2. How does memoization work?

Lexical vs. Dynamic Scope

An Explicit Continuation Evaluator for Scheme

SCHEME 10 COMPUTER SCIENCE 61A. July 26, Warm Up: Conditional Expressions. 1. What does Scheme print? scm> (if (or #t (/ 1 0)) 1 (/ 1 0))

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


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

University of Massachusetts Lowell

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

A Brief Introduction to Scheme (II)

4.2 Variations on a Scheme -- Lazy Evaluation

Documentation for LISP in BASIC

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

CS 314 Principles of Programming Languages. Lecture 16

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

Administrivia. Simple data types

Introduction to Scheme

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

6.945 Adventures in Advanced Symbolic Programming

Data abstraction, revisited

Principles of Programming Languages Topic: Scope and Memory Professor Louis Steinberg Fall 2004

Turtles All The Way Down

6.037 Lecture 7B. Scheme Variants Normal Order Lazy Evaluation Streams

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

CS61A Notes Disc 11: Streams Streaming Along

MORE SCHEME. 1 What Would Scheme Print? COMPUTER SCIENCE MENTORS 61A. October 30 to November 3, Solution: Solutions begin on the following page.

LECTURE 16. Functional Programming

(scheme-1) has lambda but NOT define

ALISP interpreter in Awk

YOUR NAME PLEASE: *** SOLUTIONS ***

Sample Final Exam Questions

CS450: Structure of Higher Level Languages Spring 2018 Assignment 7 Due: Wednesday, April 18, 2018

6.001: Structure and Interpretation of Computer Programs

Scheme Quick Reference

Implementing Coroutines with call/cc. Producer/Consumer using Coroutines

MASSACHVSETTS INSTITVTE OF TECHNOLOGY Department of Electrical Engineering and Computer Science. Issued: Wed. 26 April 2017 Due: Wed.

CS 211. Project 5 Infix Expression Evaluation

Scheme Quick Reference

User-defined Functions. Conditional Expressions in Scheme

Streams and Evalutation Strategies

6.001 Recitation 23: Register Machines and Stack Frames

More Scheme CS 331. Quiz. 4. What is the length of the list (()()()())? Which element does (car (cdr (x y z))) extract from the list?

CS3: Introduction to Symbolic Programming. Lecture 14: Lists.

Racket: Modules, Contracts, Languages

6.001, Fall Semester, 1998 Lecture Notes, October 27 { Object Oriented Programming 2 An environment diagram illustrating +define foo +cons 1 2,, +set-

Programming Languages. Thunks, Laziness, Streams, Memoization. Adapted from Dan Grossman s PL class, U. of Washington

Interpreters and Tail Calls Fall 2017 Discussion 8: November 1, 2017 Solutions. 1 Calculator. calc> (+ 2 2) 4

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

Functional Programming - 2. Higher Order Functions

CS 275 Name Final Exam Solutions December 16, 2016

Overview. CS301 Session 3. Problem set 1. Thinking recursively

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

What is tail position?

CS 61A Discussion 8: Scheme. March 23, 2017

From Syntactic Sugar to the Syntactic Meth Lab:

Transcription:

1 File: regsim.scm Register machine simulator from section 5.2 of STRUCTURE AND INTERPRETATION OF COMPUTER PROGRAMS This file can be loaded into Scheme as a whole. Then you can define and simulate machines as shown in section 5.2 **NB** there are two versions of make stack below. Choose the monitored or unmonitored one by reordering them to put the one you want last, or by commenting one of them out. Also, comment in/out the print stack statistics op in make new machine. To find this stack code below, look for comments with ** Commented and reformatted by C. Offner (Spring/2002 Fall/2003) Changed "primitive" to "machine primitive" to avoid confusion with Scheme primitives. (This term is used only in the comments.) The machine primitives are those operators that are used in (op...) expressions or (perform...) instructions. Changed lookup prim to lookup machine primitive, and changed make primitive exp to make elementary exp, for the same reason. The register machine make machine is what the user invokes to create a new machine. It takes three arguments: register names: a list of register names that are needed by the instructions in the machine. ops: a list of the machine s "machine primitive" operations, and how to perform them. controller text: the actual sequence of instructions of the machine. The machine starts execution with the first instruction. make machine performs three actions: 1. It calls make new machine (defined below) to construct the skeleton of the machine. 2. It adds the registers specified (in register names) to the machine. 3. It adds to the machine primitive operators specified (in ops) to the machine. 4. Finally, it calls assemble (defined below) to assemble each instruction (in controller text) so that it can actually be executed. It then adds these assembled instructions to the machine. (define (make machine register names ops controller text) (let ((machine (make new machine))) (for each (lambda (register name) ((machine allocate register) register name)) register names) ((machine install operations) ops) ((machine install instruction sequence) (assemble controller text machine)) machine))

2 Making and accessing registers (define (make register) (let ((contents *unassigned*)) (cond ((eq? message get) contents) ((eq? message set) (lambda (value) (set! contents value))) (else (error "Unknown request REGISTER " message)))) dispatch)) (define (get contents register) (register get)) (define (set contents! register value) ((register set) value)) Creating a stack ;;**original (unmonitored) version from section 5.2.1 (define (make stack) (let ((s ())) (define (push x) (set! s (cons x s))) (define (pop) (if (null? s) (error "Empty stack POP") (let ((top (car s))) (set! s (cdr s)) top))) (define (initialize) (set! s ()) done) (cond ((eq? message push) push) ((eq? message pop) (pop)) ((eq? message initialize) (initialize)) (else (error "Unknown request STACK " message)))) dispatch)) ;;**monitored version from section 5.2.4 (define (make stack) (let ((s ()) (number pushes 0) (max depth 0) (current depth 0)) (define (push x) (set! s (cons x s)) (set! number pushes (+ 1 number pushes)) (set! current depth (+ 1 current depth)) (set! max depth (max current depth max depth))) (define (pop) (if (null? s) (error "Empty stack POP") (let ((top (car s))) (set! s (cdr s)) (set! current depth ( current depth 1)) top))) (define (initialize) (set! s ()) (set! number pushes 0) (set! max depth 0) (set! current depth 0) done) (define (print statistics) (newline) (display (list total pushes = number pushes maximum depth = max depth)) (newline)) (cond ((eq? message push) push) ((eq? message pop) (pop)) ((eq? message initialize) (initialize)) ((eq? message print statistics) (print statistics)) (else (error "Unknown request STACK " message)))) dispatch)) (define (pop stack) (stack pop)) (define (push stack value) ((stack push) value))

3 Making the skeleton of a machine make new machine makes a basic machine with an empty instruction sequence and only two registers: pc: the "program counter" flag: the "condition code", set by each test instruction and used immediately afterwards by a branch instruction. There are initially two machine primitive operations: initialize stack: This makes sure the stack is empty and resets the statistics gathering counters. print statistics: This is used for reporting purposes. It prints the total number of stack pushes that were performed and the maximum stack depth that was reached since the last call to initialize stack. (define (make new machine) (let ((pc (make register)) (flag (make register)) (stack (make stack)) (the instruction sequence ())) (let ((the ops (list (list initialize stack (stack initialize))) ;;**next for monitored stack (as in section 5.2.4) ;; comment out if not wanted (list print stack statistics (stack print statistics))))) (register table (list (list pc pc) (list flag flag)))) (define (allocate register name) (if (assoc name register table) (error "Multiply defined register: " name) (set! register table (cons (list name (make register)) register table))) register allocated) (define (lookup register name) (let ((val (assoc name register table))) (if val (cadr val) (error "Unknown register: " name)))) (define (execute) (let ((insts (get contents pc))) (if (null? insts) done (begin ((instruction execution proc (car insts))) (execute))))) (cond ((eq? message start) (set contents! pc the instruction sequence) (execute)) ((eq? message install instruction sequence) (lambda (seq) (set! the instruction sequence seq))) ((eq? message allocate register) allocate register) ((eq? message get register) lookup register) ((eq? message install operations) (lambda (ops) (set! the ops (append the ops ops)))) ((eq? message stack) stack) ((eq? message operations) the ops) (else (error "Unknown request MACHINE " message)))) dispatch))) Access functions for the machine: (define (start machine) (machine start)) (define (get register contents machine register name) (get contents (get register machine register name))) (define (set register contents! machine register name value) (set contents! (get register machine register name) value) done) (define (get register machine reg name) ((machine get register) reg name))

4 The assembler assemble first calls extract labels. This creates two lists: 1. a list of labels. Each label is paired with the instruction it refers to. 2. a list of instruction. The labels have been removed from this list. Each instruction is paired (initially) with the empty list. Then update insts! is called to replace the empty list paired with each instruction with the actual code to be generated to implement that instruction. These routines are written in continuation passing style. So instead of something like this: (define (assemble...) (update insts! (extract labels...)...)) update insts! becomes the kernel of the continuation of extract labels. (define (assemble controller text machine) (extract labels controller text (lambda (insts labels) (update insts! insts labels machine) insts))) (define (extract labels text receive) (if (null? text) (receive () ()) ;; This is where everything really happens, at the end. (extract labels (cdr text) (lambda (insts labels) ;; This is where labels and insts are (let ((next inst (car text))) ;; accumulated (as on a stack): (if (symbol? next inst) (receive insts ;; either like this (cons (make label entry next inst ;; (it s a label) insts) labels)) (receive (cons (make instruction next inst) ;; or like this insts) ;; (it s an inst) labels))))))) (define (update insts! insts labels machine) (let ((pc (get register machine pc)) (flag (get register machine flag)) (stack (machine stack)) (ops (machine operations))) (for each (lambda (inst) (set instruction execution proc! inst (make execution procedure ;; Generate the machine code. (instruction text inst) labels machine pc flag stack ops))) insts))) instruction text and whose second element is initially empty. The second element will later be filled in by update insts! using set instruction execution proc! (define (make instruction text) (cons text ())) (define (instruction text inst) (car inst)) (define (instruction execution proc inst) (cdr inst)) (define (set instruction execution proc! inst proc) (set cdr! inst proc)) make label entry creates a pair whose first element is the label and whose second element is the "rest of the instruction sequence". Thus, branching to that label amounts to resuming execution at the second element of the pair. (One could think of the second element of the pair as the address in instruction memory referred to by the label.) (define (make label entry label name insts) (cons label name insts)) (define (lookup label labels label name) (let ((val (assoc label name labels))) (if val (cdr val) (error "Undefined label ASSEMBLE " label name)))) Generation of machine instructions make execution procedure dispatches on the type of instruction to the specific machine code generation routines. Each such routine returns a lambda expression which when executed, performs the action specified by the instruction being assembled. (define (make execution procedure inst labels machine pc flag stack ops) (cond ((eq? (car inst) assign) (make assign inst machine labels ops pc)) ((eq? (car inst) test) (make test inst machine labels ops flag pc)) ((eq? (car inst) branch) (make branch inst machine labels flag pc)) ((eq? (car inst) goto) (make goto inst machine labels pc)) ((eq? (car inst) save) (make save inst machine stack pc)) ((eq? (car inst) restore) (make restore inst machine stack pc)) ((eq? (car inst) perform) (make perform inst machine labels ops pc)) (else (error "Unknown instruction type ASSEMBLE " inst)))) make instruction creates a pair whose first element is the

5 (define (make assign inst machine labels operations pc) (let ((target (get register machine (assign reg name inst))) (value exp (assign value exp inst))) (let ((value proc (if (operation exp? value exp) (make operation exp value exp machine labels operations) (make elementary exp (car value exp) machine labels)))) ; execution procedure for assign (set contents! target (value proc)) (advance pc pc))))) (define (assign reg name assign instruction) (cadr assign instruction)) (define (assign value exp assign instruction) (cddr assign instruction)) (define (advance pc pc) (set contents! pc (cdr (get contents pc)))) (define (make test inst machine labels operations flag pc) (let ((condition (test condition inst))) (if (operation exp? condition) (let ((condition proc (make operation exp condition machine labels operations))) (set contents! flag (condition proc)) (advance pc pc))) (error "Bad TEST instruction ASSEMBLE " inst)))) (define (test condition test instruction) (cdr test instruction)) (define (make branch inst machine labels flag pc) (let ((dest (branch dest inst))) (if (label exp? dest) (let ((insts (lookup label labels (label exp label dest)))) (if (get contents flag) (set contents! pc insts) (advance pc pc)))) (error "Bad BRANCH instruction ASSEMBLE " inst)))) (define (branch dest branch instruction) (cadr branch instruction)) (define (make goto inst machine labels pc) (let ((dest (goto dest inst))) (cond ((label exp? dest) (let ((insts (lookup label labels (label exp label dest)))) (set contents! pc insts)))) ((register exp? dest) (let ((reg (get register machine (register exp reg dest)))) (set contents! pc (get contents reg))))) (else (error "Bad GOTO instruction ASSEMBLE " inst))))) (define (goto dest goto instruction) (cadr goto instruction)) (define (make save inst machine stack pc) (let ((reg (get register machine (stack inst reg name inst)))) (push stack (get contents reg)) (advance pc pc)))) (define (make restore inst machine stack pc) (let ((reg (get register machine (stack inst reg name inst)))) (set contents! reg (pop stack)) (advance pc pc)))) (define (stack inst reg name stack instruction) (cadr stack instruction)) (define (make perform inst machine labels operations pc) (let ((action (perform action inst))) (if (operation exp? action) (let ((action proc (make operation exp action machine labels operations))) (action proc) (advance pc pc))) (error "Bad PERFORM instruction ASSEMBLE " inst)))) (define (perform action inst) (cdr inst)) (define (make elementary exp exp machine labels) (cond ((constant exp? exp) (let ((c (constant exp value exp))) c))) ((label exp? exp) (let ((insts (lookup label labels (label exp label exp)))) insts))) ((register exp? exp) (let ((r (get register machine (register exp reg exp)))) (get contents r)))) (else (error "Unknown expression type ASSEMBLE " exp)))) (define (register exp? exp) (tagged list? exp reg)) (define (register exp reg exp) (cadr exp)) (define (constant exp? exp) (tagged list? exp const)) (define (constant exp value exp) (cadr exp)) (define (label exp? exp) (tagged list? exp label))

6 (define (label exp label exp) (cadr exp)) (define (make operation exp exp machine labels operations) (let ((op (lookup machine primitive (operation exp op exp) operations)) (aprocs (map (lambda (e) (make elementary exp e machine labels)) (operation exp operands exp)))) (apply op (map (lambda (p) (p)) aprocs))))) ;; from 4.1 (define (tagged list? exp tag) (if (pair? exp) (eq? (car exp) tag) #f)) (REGISTER SIMULATOR LOADED) (define (operation exp? exp) (and (pair? exp) (tagged list? (car exp) op))) (define (operation exp op operation exp) (cadr (car operation exp))) (define (operation exp operands operation exp) (cdr operation exp)) (define (lookup machine primitive symbol operations) (let ((val (assoc symbol operations))) (if val (cadr val) (error "Unknown operation ASSEMBLE " symbol))))