PostFix. PostFix command semanccs (except exec) PostFix Syntax. A PostFix Interpreter in Racket. CS251 Programming Languages Spring 2018, Lyn Turbak

Similar documents
PostFix. PostFix command semanccs (except exec) PostFix Syntax. A PostFix Interpreter in Racket. CS251 Programming Languages Fall 2017, Lyn Turbak

CS251 Programming Languages Spring 2016, Lyn Turbak Department of Computer Science Wellesley College

Metaprogramming in SML: PostFix and S-expressions

Metaprogramming in SML: PostFix and S-expressions

CS251 Programming Languages Handout # 29 Prof. Lyn Turbak March 7, 2007 Wellesley College

Interpre'ng and Compiling Intex

Interpre'ng and Compiling Intex

Interpre'ng and Compiling Intex SOLUTIONS

Valex: Mul*ple Value Types, Condi*onals, Dynamic Type Checking and Desugaring SOLUTIONS

Design Concepts in Programming Languages Scheme Supplement

Valex: Mul*ple Value Types, Condi*onals, Dynamic Type Checking and Desugaring

A brief tour of history

CS301 Compiler Design and Implementation Handout # 18 Prof. Lyn Turbak February 19, 2003 Wellesley College

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

Hofl, a Higher-order Functional Language. 1 An Overview of Hofl. 2 Abstractions and Function Applications

Racket Values. cons Glues Two Values into a Pair. The Pros of cons: Programming with Pairs and Lists. Box-and-pointer diagrams for cons trees

Scheme Quick Reference

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

Racket Values. cons Glues Two Values into a Pair. The Pros of cons: Pairs and Lists in Racket. Box-and-pointer diagrams for cons trees

Overview. Factorial Revisited. Iteration via Tail Recursion in Racket. An itera*ve approach to factorial. What is itera*on?

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

Overview. Iteration via Tail Recursion in Racket SOLUTIONS. Factorial Revisited. An itera*ve approach to factorial

Overview. Iteration via Tail Recursion in Racket. Factorial Revisited. An itera*ve approach to factorial. What is itera*on?

Finish Lec12 TREES, PART 2. Announcements. JavaHyperText topics. Trees, re-implemented. Iterate through data structure 3/7/19

Vectors in Scheme. Data Structures in Scheme

6.821 Programming Languages Handout Fall MASSACHVSETTS INSTITVTE OF TECHNOLOGY Department of Electrical Engineering and Compvter Science

Scheme Quick Reference

User-defined Functions. Conditional Expressions in Scheme

Denotational Semantics

Scheme as implemented by Racket

Recursive List Func.ons in Racket

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

LISP: LISt Processing

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

Design Concepts in Programming Languages

Functions & First Class Function Values

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

Wellesley College CS251 Programming Languages Spring, 2000 FINAL EXAM REVIEW PROBLEM SOLUTIONS

Introduction to Scheme

CSC 533: Programming Languages. Spring 2015

Shell programming. Introduction to Operating Systems

Operational Semantics

Functional Programming. Pure Functional Languages

CS 314 Principles of Programming Languages. Lecture 16

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

Functional Programming. Pure Functional Programming

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

Programming Languages: Application and Interpretation

Introduction to Functional Programming in Racket. CS 550 Programming Languages Jeremy Johnson

Hofl: First-class Functions and Scoping

Functional Programming - 2. Higher Order Functions

Module 8: Local and functional abstraction

Bindex: Naming, Free Variables, and Environments SOLUTIONS

FOFL and FOBS: First-Order Functions

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

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

(Func&onal (Programming (in (Scheme)))) Jianguo Lu

Control Structures. CIS 118 Intro to LINUX

CSE 341 Section Handout #6 Cheat Sheet

Programming Languages: Application and Interpretation

Structure and Interpretation of Computer Programs

An Explicit-Continuation Metacircular Evaluator

Valex: Primitive Operators and Desugaring

How to Design Programs

Homework 3 COSE212, Fall 2018

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?

Problem Set 5 Due:??

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

Documentation for LISP in BASIC

CSE 341 Section 7. Eric Mullen Spring Adapted from slides by Nicholas Shahan, Dan Grossman, and Tam Dang

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

Organization of Programming Languages CS3200/5200N. Lecture 11

Essentials of Programming Languages Language

Essentials of Programming Languages Language

Structure and Interpretation of Computer Programs

Box-and-arrow Diagrams

First-Class Synchronization Barriers. Franklyn Turbak Wellesley College

Fall 2017 December 4, Scheme. Instructions

Bindex: Naming, Free Variables, and Environments

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

CSc 520 Principles of Programming Languages

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

Chapter 15. Functional Programming Languages

FP Foundations, Scheme

Functional Programming. Pure Functional Languages

Notes on Higher Order Programming in Scheme. by Alexander Stepanov

CS 314 Principles of Programming Languages

Project 3 Due October 21, 2015, 11:59:59pm

Languages and Compiler Design II IR Code Generation I

An Explicit Continuation Evaluator for Scheme

Structure and Interpretation of Computer Programs

CPS 506 Comparative Programming Languages. Programming Language Paradigm

Case Study: Undefined Variables

Introduction to Functional Programming

Duplication and Partial Evaluation For a Better Understanding of Reflective Languages

Racket: Macros. Advanced Functional Programming. Jean-Noël Monette. November 2013

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

Functional Programming and Haskell

Symbolic Reasoning. Dr. Neil T. Dantam. Spring CSCI-561, Colorado School of Mines. Dantam (Mines CSCI-561) Symbolic Reasoning Spring / 86

Transcription:

PostFix A PostFix Interpreter in Racket CS251 Programming Languages Spring 2018, Lyn Turbak Department of Computer Science Wellesley College PostFix is a stack-based mini-language that will be our first foray into the study of metalanguages = programs that manipulate programs. It s not a real language, but a toy mini-language used for studying programming language semanccs and implementacon. It is inspired by real stack-based languages like PostScript, Forth, and HP calculators. For the syntax and semanccs of PostFix, see these notes: hgp://cs.wellesley.edu/~cs251/notes/dcpl-introduccon.pdf Here s an example PostFix program (postfix 2 2 nget 0 gt (sub) (swap 1 nget mul add) sel exec) 2 number of expected arguments PostFix Syntax commands (postfix 2 2 nget 0 gt (sub) (swap 1 nget mul add) sel exec) executable sequence command executable sequence command A PostFix command C is one of: An integer One of pop, swap, nget, sel, exec, add, mul, sub, div, rem, ; arithops lt, eq, gt ; relops An executable sequence of the form (C1 Cn) 3 PostFix command semanccs (except exec) Stack Before Command Stack After ( ) integer N (N ) (v1 ) pop ( ) (v1 v2 ) swap (v2 v1 ) (v1 v2 ) sub (other arithops similar) (v1 v2 ) lt (other relops similar) (N )where N is v2 v1 (N )where N is 1 if v2 < v1 and N is 0 otherwise (i v1 vk) nget (vi v1 vk) if 1 i k and vi is an integer (velse vthen vtest ) sel (vthen ) if vtest 0 (velse ) if vtest = 0 4

PostFix command semanccs: exec Stack Before Commands Before Commands After ((C1 Cn) rest-of-stack) (exec rest-of-cmds) (C1 Cn rest-of-cmds) Your turn: PostFix program example Consider this posmix program: '(postfix 2 2 nget 0 gt (sub) (swap 1 nget mul add) sel exec) What is the result of running it on these arguments? '(3 5) '(3-5) 5 6 PostFix Syntax AbstracCons in Racket TesCng membership with memq/member (define (postfix-program? sexp) (and (list? sexp) (>= (length sexp) 2) (eq? (first sexp) 'postfix) (integer? (second sexp)) (postfix-command-sequence? (rest (rest sexp))))) > (member 'c '(a b c d e)) '(c d e) ; returns sublist beginning with found item > (member 'x '(a b c d e)) #f ; returns #f if item not found (define (postfix-command-sequence? sexp) (and (list? sexp) (forall? postfix-command? sexp))) (define (postfix-command? sexp) (or (integer? sexp) (memq sexp '(pop swap nget sel exec add mul sub div rem ; arithops lt eq gt)) ; relops (postfix-command-sequence? sexp))) (define (postfix-numargs pgm) (second pgm)) (define (postfix-commands pgm) (rest (rest pgm))) 7 > (define L '(a b)) > (memq L (list '(c d) L '(e f))) '((a b) (e f)) > (memq L (list '(c d) '(a b) '(e f))) #f ; not found because new list '(a b) not eq? to L ;; member is to memq what equal? is to eq? > (member L (list '(c d) '(a b) '(e f))) '((a b) (e f)) 8

MulCple versions of the PostFix interpreter postfix-config-tail-starter.rkt We will study three different approaches to implemencng a PostFix interpreter. 1. postfix-config-tail: uses tail recursion to perform iteracve execucon of PostFix state configuracons = duples (2-element list) of commands and stack. 2. postfix-config-iterate: uses tail recursion to perform iteracve execucon of PostFix state configuracons. 3. postfix-transform: uses foldl on command sequence to transform inical stack to final stack. Treats exec as a stack transformer. There are two flavors of each of these three interpreters: o simple: limited error handling, straighmorward arithops/relops, no tracing ;; Run the given PostFix program on argument values, ;; which form the initial stack (postfix-exec-config-tail (postfix-commands pgm) args)) ;; Use tail recursion to loop over a configuration state consisting ;; of (1) list of commands and (2) list of stack values (define (postfix-exec-config-tail cmds stk) (cond ((null? cmds) 'flesh-this-out) ; Return top of stack at end ((eq? (first cmds) 'exec) 'flesh-this-out) (else (postfix-exec-config-tail (rest cmds) (postfix-exec-command (first cmds) stk))))) o Fancy: appropriate handling of all error cases; the ability to trace step-by-step execucon; ;; Execute a non-exec command on a stack to yield a new stack. ;; So each command can be viewed as a "stack transformer" ) a general, extensible way to handle arithops and relops 9 10 postfix-exec-command Skeleton postfix-exec-config-tail Fleshed Out ;; Initially simplify things by ignoring errors (cond ((integer? cmd) 'flesh-this-out) ((eq? cmd 'pop) 'flesh-this-out) ((eq? cmd 'swap) 'flesh-this-out) ((eq? cmd 'sub) 'flesh-this-out) ; other arithops similar ((eq? cmd 'lt) 'flesh-this-out) ; other relops similar ((eq? cmd 'sel) 'flesh-this-out) ((postfix-command-sequence? cmd) 'flesh-this-out) (else (error "unrecognized command" cmd)))) ;; Use tail recursion to loop over a configuration state consisting ;; of (1) list of commands and (2) list of stack values (define (postfix-exec-config-tail cmds stk) (cond ((null? cmds) (first stk)) ; Return top of stack at end ((eq? (first cmds) 'exec) (postfix-exec-config-tail (append (first stk) (rest cmds)) (rest stk))) (else (postfix-exec-config-tail (rest cmds) (postfix-exec-command (first cmds) stk))))) 11 12

postfix-exec-command Fleshed Out Side Effects and Sequencing: printf and begin ;; Initially simplify things by ignoring errors (cond ((integer? cmd) (cons cmd stk)) ((eq? cmd 'pop) (rest stk)) ((eq? cmd 'swap) (cons (second stk) (cons (first stk) (rest (rest stk))))) ((eq? cmd 'sub) (cons (- (second stk) (first stk)) (rest (rest stk)))) ; other arithops similar ((eq? cmd 'lt) (cons (if (< (second stk) (first stk)) 1 0) (rest (rest stk)))) ; other relops similar ((eq? cmd 'nget) (cons (list-ref stk (first stk)) (rest stk))) ((eq? cmd 'sel) (cons (if (= (third stk) 0) (first stk) (second stk)) (rest (rest (rest stk))))) ((postfix-command-sequence? cmd) (cons cmd stk)) (else (error "unrecognized command" cmd)))) > (begin (printf "~a + ~a is ~a\n" 1 2 (+ 1 2)) (printf "~a * ~a is ~a\n" 3 4 (* 3 4))) 1 + 2 is 3 3 * 4 is 12 (define (print-and-return val) (begin (printf "~a\n" val) val)) > (* (print-and-return 3) (print-and-return (+ (print-and-return 4) (print-and-return 5)))) 3 ; printed 4 ; printed 5 ; printed 9 ; printed 27 ; returned 13 14 begin is just syntaccc sugar! postfix-exec-config-tail with tracing (begin e) desugars to e (begin e1 e2 ) desugars to (let ((id1 e1)) ; id1 is fresh (begin e2 )) ;; Set this to #t to turn on printing of intermediate stacks; ;; #f to turn it off (define display-steps? #t) (define (postfix-exec-config-tail cmds stk) (begin (if display-steps? ; Only print intermediate stack ;if display-steps? is #t (printf "Commands: ~a\n Stack: ~a\n" cmds stk) 'do-nothing) (cond ))) 15 16

postfix-run ;; Run a postfix program on initial stack from args ;; Simplify things by not checking for errors. (let ((final-stk (postfix-exec-commands (postfix-commands pgm) args))) (first final-stk))) > (postfix-run '(postfix 2 7 4 pop swap sub) '(5 8)) after executing 7, stack is (7 5 8) after executing 4, stack is (4 7 5 8) after executing pop, stack is (7 5 8) after executing swap, stack is (5 7 8) after executing sub, stack is (2 8) 2 17 postfix-run with errors ;; Run a postfix program on initial stack from args ;; This version checks for errors (cond ((not (postfix-program? pgm)) (error "Invalid PostFix program" pgm)) ((not (postfix-arguments? args)) (error "Invalid PostFix arguments" pgm)) ((not (= (postfix-numargs pgm) (length args))) (error "expected number of arguments does not match actual number of arguments" (list (postfix-numargs pgm) (length args)))) (else (let ((final-stack (postfix-exec-commands (postfix-commands pgm) args))) (cond ((null? final-stack) (error "Stack empty at end of program")) ((not (integer? (first final-stack))) (error "Top of final stack not an integer")) (else (first final-stack))))))) 18 postfix-exec-command with errors (cond ((integer? cmd) (cons cmd stk)) ((eq? cmd 'pop) (if (< (length stk) 1) (error "postfix pop requires stack with at least one value" (list cmd stk)) (rest stk))) ((eq? cmd 'swap) (if (< (length stk) 2) (error "postfix swap requires stack with at least two values" (list cmd stk)) (cons (second stk) (cons (first stk) (rest (rest stk)))))) ((postfix-arithop? cmd) (cond ((< (stack-size stk) 2) (error "postfix arithop requires two arguments" (list cmd stk))) ((or (not (integer? (first stk))) (not (integer? (second stk)))) (error "postfix arithop requires two integers" (list cmd stk))) (else (cons ((postfix-arithop->racket-binop cmd) (second stk) (first stk)) (rest (rest stk))))) ;; Other cases omitted (else (error "Unknown PostFix command" cmd)))) BeGer handling of arithops (relops similar) (cond ((postfix-arithop? cmd) (cons ((postfix-arithop->racket-binop cmd) (second stk) (first stk)) (rest (rest stk)))) )) (define postfix-arithops (list (list 'add +) (list 'mul *) (list 'sub -) (list 'div quotient) (list 'rem remainder))) (define (postfix-arithop? cmd) (assoc cmd postfix-arithops)) (define (postfix-arithop->racket-binop arithop) (second (assoc postfix-arithops))) 19 20

postfix-config-iterate-simple.rkt (postfix-exec-config-iterate (postfix-commands pgm) args)) (define (postfix-exec-config-iterate cmds stk) (iterate-apply postfix-exec-config-one-step (λ (cmds stk) (null? cmds)) (λ (cmds stk) (first stk)) (list cmds stk))) (define (postfix-exec-config-one-step cmds stk) (if (eq? (first cmds) 'exec) (list (append (first stk) (rest cmds)) (rest stk)))) (list (rest cmds) (postfix-exec-command (first cmds) stk))))) postfix-transform-simple.rkt (let {[final-stk (postfix-exec-commands (postfix-commands pgm) args)]} (first final-stk))) ;; Execute command list on initial stack ;; and return final stack (define (postfix-exec-commands cmds init-stk) (foldl postfix-exec-command init-stk cmds)) (cond ((eq? cmd 'exec) (postfix-exec-commands (first stk) (rest stk))) (else (error "unrecognized command" cmd)))) 21 > (postfix-exec-commands '(pop swap sub) '(4 7 5 8)) '(2 8) 22 postfix-exec-commands with tracing ;; Execute command list on initial stack ;; and return final stack ;; Print each command and stack resulting from executing it (define (postfix-exec-commands cmds init-stk) (foldl (λ (cmd stk) (let ((new-stk (postfix-exec-command cmd stk))) (begin (printf "after executing ~a, stack is ~a\n" cmd new-stk) new-stk))) init-stk cmds)) > (postfix-exec-commands '(pop swap sub) '(4 7 5 8)) after executing pop, stack is (7 5 8) after executing swap, stack is (5 7 8) after executing sub, stack is (2 8) '(2 8) 23