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

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

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

Design Concepts in Programming Languages

Lab 6: P.S. it s a stack Due 11:59 pm Monday, Mar 31, 2008

Context-Free Grammar. Concepts Introduced in Chapter 2. Parse Trees. Example Grammar and Derivation

Metaprogramming in SML: PostFix and S-expressions

CS Introduction to Data Structures How to Parse Arithmetic Expressions

Operational Semantics

A Simple Syntax-Directed Translator

Problem Set 5 Due:??

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

Metaprogramming in SML: PostFix and S-expressions

Assoc. Prof. Dr. Marenglen Biba. (C) 2010 Pearson Education, Inc. All rights reserved.

15-122: Principles of Imperative Computation, Fall 2015

Shell programming. Introduction to Operating Systems

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

The PCAT Programming Language Reference Manual

Virtual Machine Tutorial

SOURCE LANGUAGE DESCRIPTION

Full file at

STACKS. A stack is defined in terms of its behavior. The common operations associated with a stack are as follows:

12/22/11. Java How to Program, 9/e. Help you get started with Eclipse and NetBeans integrated development environments.

19 Much that I bound, I could not free; Much that I freed returned to me. Lee Wilson Dodd

Pace University. Fundamental Concepts of CS121 1

Typescript on LLVM Language Reference Manual

Programming for Engineers Iteration

UNIT 3

Special Section: Building Your Own Compiler

flex is not a bad tool to use for doing modest text transformations and for programs that collect statistics on input.

Lecture 4: Stack Applications CS2504/CS4092 Algorithms and Linear Data Structures. Parentheses and Mathematical Expressions

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

Postscript Control Flow

ECE220: Computer Systems and Programming Spring 2018 Honors Section due: Saturday 14 April at 11:59:59 p.m. Code Generation for an LC-3 Compiler

Learning Language. Reference Manual. George Liao (gkl2104) Joseanibal Colon Ramos (jc2373) Stephen Robinson (sar2120) Huabiao Xu(hx2104)

CIS 194: Homework 3. Due Wednesday, February 11, Interpreters. Meet SImPL

1 Lexical Considerations

In this chapter you ll learn:

HAWK Language Reference Manual

Postfix Notation is a notation in which the operator follows its operands in the expression (e.g ).

COMP-421 Compiler Design. Presented by Dr Ioanna Dionysiou

211: Computer Architecture Summer 2016

Operators. Java operators are classified into three categories:

Programming Languages Third Edition. Chapter 9 Control I Expressions and Statements

Homework 3 COSE212, Fall 2018

Stack Applications. Lecture 27 Sections Robb T. Koether. Hampden-Sydney College. Wed, Mar 29, 2017

CSCI 3155: Lab Assignment 2

Language Reference Manual simplicity

Intermediate Representations

In Fig. 3.5 and Fig. 3.7, we include some completely blank lines in the pseudocode for readability. programs into their various phases.

Chapter 2, Part III Arithmetic Operators and Decision Making

Design Concepts in Programming Languages Scheme Supplement

CSci 450, Org. of Programming Languages. Chapter 12 Expression Language Compilation

Data Structures and Algorithms

IPCoreL. Phillip Duane Douglas, Jr. 11/3/2010

C Language Part 1 Digital Computer Concept and Practice Copyright 2012 by Jaejin Lee

Operators and Expressions

3.7 Denotational Semantics

Advanced Algorithms and Computational Models (module A)

A Small Interpreted Language

GAWK Language Reference Manual

Semantic analysis and intermediate representations. Which methods / formalisms are used in the various phases during the analysis?

SECOND PUBLIC EXAMINATION. Compilers

COMPILERS BASIC COMPILER FUNCTIONS

GBIL: Generic Binary Instrumentation Language. Language Reference Manual. By: Andrew Calvano. COMS W4115 Fall 2015 CVN

CS 4240: Compilers and Interpreters Project Phase 1: Scanner and Parser Due Date: October 4 th 2015 (11:59 pm) (via T-square)

CHAD Language Reference Manual

COMP1730/COMP6730 Programming for Scientists. Data: Values, types and expressions.

TED Language Reference Manual

Computer Architecture and System Software Lecture 07: Assembly Language Programming

Template Language and Syntax Reference

VENTURE. Section 1. Lexical Elements. 1.1 Identifiers. 1.2 Keywords. 1.3 Literals

CS 360 Programming Languages Interpreters

IT 374 C# and Applications/ IT695 C# Data Structures

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

Assignment 5. Introduction

Lecture 8: Simple Calculator Application

UNIT-II. Part-2: CENTRAL PROCESSING UNIT

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

Scheme: Data. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, April 3, Glenn G.

Chapter 1 Summary. Chapter 2 Summary. end of a string, in which case the string can span multiple lines.

Syntax and Grammars 1 / 21

Full file at C How to Program, 6/e Multiple Choice Test Bank

Introduction to lambda calculus Part 3

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

CS 115 Lecture 4. More Python; testing software. Neil Moore

Functional Programming. Pure Functional Programming

Control Structures. CIS 118 Intro to LINUX

9/10/10. Arithmetic Operators. Today. Assigning floats to ints. Arithmetic Operators & Expressions. What do you think is the output?

The SPL Programming Language Reference Manual

DaMPL. Language Reference Manual. Henrique Grando

Chapter 4: Control Structures I (Selection) Objectives. Objectives (cont d.) Control Structures. Control Structures (cont d.

Administration CS 412/413. Why build a compiler? Compilers. Architectural independence. Source-to-source translator

Programming Languages Third Edition

An Explicit Continuation Evaluator for Scheme

Principles of Programming Languages

Syntax Errors; Static Semantics

Static Semantics. Lecture 15. (Notes by P. N. Hilfinger and R. Bodik) 2/29/08 Prof. Hilfinger, CS164 Lecture 15 1

Stating the obvious, people and computers do not speak the same language.

CSc 372. Comparative Programming Languages. 4 : Haskell Basics. Department of Computer Science University of Arizona

Transcription:

CS5 Programming Languages Handout # 9 Prof. Lyn Turbak March, 00 Wellesley College Postfix: A Simple Stack Language Several exercises and examples in this course will involve the Postfix mini-language. Postfix is a simple stack-based language inspired by the PostScript graphics language, the Forth programming language, Hewlett Packard calculators, and stack-based byte code interpreters. Here we give a brief introduction to Postfix. Syntax. Commands The basic syntactic unit of a Postfix program is the command. Commands have the following form: Any integer numeral. E.g.,, 0, -. Any string literal (possibly containing the usual escape characters). E.g., "CS0", "Golf? No sir -- prefer prison flog!", "You say \"Goodbye\"\n\tand I say \"Hello\"." One of the following special command tokens: add, div, eq,, ge, get, gt, le, lt,, ne, pop, pri, prs, put, rem, sel,, and. An utable sequence a single command represented as a parenthesized sequence of commands separated by whitespace. Since utable sequences contain other commands (including other utable sequences), they can be arbitrarily nested. An utable sequence counts as a single command despite its hierarchical structure.. Programs A Postfix program is a parenthesized sequence consisting of () the token postfix followed by () an integer indicating the number of program parameters followed by () any number of Postfix commands. For example, here are some sample Postfix programs: (postfix 0 get ) (postfix add div) (postfix 4 4 get 5 get 4 get add add) (postfix (( get ) ( ) ) ) (postfix ( get 0 eq ("\n" prs) ("\n n=" prs get pri "; ans=" prs get pri get get put get ) sel ) get )

. Abstract vs. Concrete Syntax The abstract syntax of Postfix programs and commands is captured in the following Ocaml data type definitions: type pgm = (* PostFix programs *) Pgm of int * com list and com = (* PostFix commands *) Int of int (* push integer numeral *) Str of string (* push string literal *) Seq of com list (* utable sequence *) Pop (* pop top value from stack *) Swap (* top two values of stack *) Sel (* choose one of two values from stack *) Get (* push value at given stack index *) Put (* store top of stack at given stack index *) Prs (* print string *) Pri (* print integer *) Exec (* ute sequence at top of stack *) Add Sub Mul Div Rem (* arithmetic ops *) LT LE EQ NE GE GT (* relational ops *) For example, the concrete program (postfix (( get ) ( ) ) ) would be expressed as the following abstract syntax tree: Pgm(, [Seq[Seq[Int ; Get; Swap; Exec]; Seq[Int ; Mul; Swap; Exec]; Swap]; Seq[Int 5; Sub]; Swap; Exec; Exec]) The concrete syntax of Postfix programs and commands has been designed so that they can be easily parsed and unparsed via s-expressions. Converting between the concrete and abstract syntax of Postfix is left as an exercise. Semantics The meaning of a Postfix program is determined by uting its command sequence in left to right order. Each command manipulates an implicit stack of values that initially contains the integer arguments of the program (where the first argument is at the top of the stack and the last argument is at the bottom). A value on the stack is either () an integer () a string or () an utable sequence. The result of a program is the integer value at the top of the stack after its command sequence has been completely uted. A program signals an error (designated error) if () the final stack is empty, () the value at the top of the final stack is not an integer, or () an inappropriate stack of values is encountered when one of its commands is uted. The behavior of Postfix commands is summarized in Fig.. Each command is specified in terms of how it manipulates the implicit stack. The step-by-step ution of a Postfix program can be understood in terms of the operation of an abstract machine, where the state of the abstract machine is characterized by two components: () a sequence of commands to be uted and () a stack of values that initially

An integer numeral n : Push n onto the stack. A string literal s : Push s onto the stack. : Call the top stack value v and the next-to-top stack value v. Pop these two values off the stack and push the result of v v onto the stack. If there are fewer than two values on the stack or the top two values aren t both numerals, signal an error. The other binary arithmetic operators add (addition), (tiplication), div (integer division a ) and rem (remainder of integer division) behave similarly. Both div and rem signal an error if v is zero. lt : Call the top stack value v and the next-to-top stack value v. Pop these two values off the stack. If v < v, then push a (a true value) on the stack, otherwise push a 0 (false). The other binary comparison operators le (less than or equals), eq (equals), ne (not equals), gt (greater than), and ge (greater than or equals) behave similarly. If there are fewer than two values on the stack or the top two values aren t both numerals, signal an error. pop : Pop the top element off the stack and discard it. Signal an error if the stack is empty. : Swap the top two elements of the stack. Signal an error if the stack has fewer than two values. sel : Call the top three stack values (from top down) v, v, and v. Pop these three values off the stack. If v is the numeral 0, push v onto the stack; if v is a non-zero numeral, push v onto the stack. Signal an error if the stack does not contain three values, or if v is not a numeral. get : Call the top stack value v index and the remaining stack values (from top down) v, v,..., v n. Pop v index off the stack. If v index is a numeral i such that i n, push v i onto the stack. Signal an error if the stack does not contain at least one value, if v index is not a numeral, or if i is not in the range [, n]. put : Call the top stack value v index, the next-to-top stack value v val, the remaining stack values (from top down) v, v,..., v n. Pop v index and v val off the stack. If v index is a numeral i such that i n, replace the slot holding v i on the stack by v val. Signal an error if the stack does not contain at least two values, if v index is not a numeral, or if i is not in the range [, n]. prs : Call the top stack value v s. Pop v s off the stack. If v s is the string s, display s in the terminal window. Signal an error if the stack does not contain at least one value or if v s is not a string. pri : Call the top stack value v i. Pop v i off the stack. If v i is the numeral i, display i in the terminal window. Signal an error if the stack does not contain at least one value or if v i is not a numeral. (C... C n ) : Push the utable sequence (C... C n ) as a single value onto the stack. Executable sequences are used in conjunction with. : Pop the utable sequence from the top of the stack, and prepend its component commands onto the sequence of currently uting commands. Signal an error if the stack is empty or the top stack value isn t an utable sequence. a The integer division of n and d returns the integer quotient q such that n = qd + r, where r (the remainder) is such that 0 r < d if n 0 and d < r 0 if n < 0. Figure : Semantics of Postfix commands. contains the arguments to the program (top down from first to last). On each ution step, the first command in the command sequence component is removed from the command sequence and uted; the result is an updated command sequence and stack. Like any iteration (remember CS and CS0?), this iterative ution process can be presented as a table in which each row contains the state variables of the iteration (in this case, the state of the abstract machine = commands and stack) and the rules of the iteration (in this case, the ution rules) are used to determine the next row of the table from the previous row. We shall call such a table the trace of an ution. For example, consider a Postfix program that takes three arguments (call them a, b, and c)

and calculates a b c: (postfix ) Note how s are used to reorder arguments on the stack. Here is a trace of this program run on the argument list [;4;5] : Commands Stack 4 5 5 5 5 0 0 - Often we do not care about the step-by-step details of a Postfix program ution, but only the final result. We use the notation P args v to mean that uting the Postfix program P on the arguments args returns the value v. The notation P args error means that uting the Postfix program P on the arguments signals an error. Errors are caused by inappropriate stack values or an insufficient number of stack values. In practice, it is desirable for an implementation to indicate the type of error. We will use comments (delimited by squiggly braces) to explain errors and other situations. To illustrate the meanings of various commands, we show the results of some simple program utions. For example, numerals are pushed onto the stack, while pop and are the usual stack operations: (postfix 0 ) [] {Only top stack value returned.} (postfix 0 pop) [] {pop throws top value away.} (postfix 0 pop) [] (postfix 0 ) [] error {Not enough values to.} (postfix 0 pop pop) [] error {Empty stack on second pop.} (postfix 0 pop) [] error {Final stack is empty.} Program arguments are pushed onto the stack (from last to first) before the ution of the program commands. 4

(postfix ) [,4] {Initial stack has on top with 4 below.} (postfix ) [,4] 4 (postfix pop ) [,4,5] 5 It is an error if the actual number of arguments does not match the number of parameters specified in the program. (postfix ) [] error {Wrong number of arguments.} (postfix pop) [4,5] error {Wrong number of arguments.} Program arguments must be integers they cannot be strings or utable sequences. Numerical operations are expressed in postfix notation, in which each operator comes after the commands that compute its operands. add,,, div, and rem are binary integer operators, while lt, le, eq, ne, ge, and gt are binary integer predicates returning either (true) or 0 (false). (postfix 4 ) [] - (postfix 4 add 5 6 div) [] 4 (postfix 5 add div) [,6,5,4,] -0 (postfix 4000 pop add) [00,0,] 400 (postfix add div) [,] 5 {An averaging program.} (postfix 0 div) [] 5 (postfix 0 rem) [] (postfix 0 4 lt) [] (postfix 0 4 gt) [] 0 (postfix 0 4 lt 0 add) [] (postfix 4 add) [] error {Not enough numbers to add.} (postfix 4 div) [4;5] error {Divide by 0.} In all the examples seen so far, each stack value is used at most once. Sometimes it is necessary to use a value two or more times. The get command is used in these situations; it puts at the top of the stack a copy of a stack value at a specified index. The index is -based, from the top of the stack down, not counting the index value itself. It is an error to use an index that is out of bounds. Note that the index of a given value increases every time a new value is pushed on the stack. In addition to copying a value so that it can be used more than once, get is also helpful for accessing values that are not near the top of the stack. get is a generalized version of a common operation in stack languages, often called dup, that duplicates the top element on the stack. 5

(postfix get) [5;6] 5 (postfix get) [5;6] 6 (postfix get) [5;6] error {Too large an index} (postfix 0 get) [5;6] error {Too small an index} (postfix get ) [5] 5 {A squaring program} (postfix 4 {Given args a, b, c, x, calculates ax + bx + c.} 4 get {get x} 5 get {get x again, at new index} {push x on stack} get {tiply x by a} 5 get {get x again, at newest index} 4 get {get b at new index} {calculate bx} add {add ax and bx} 4 get {get c} add {ax + bx + c is now at top of stack} ) [;4;5;0] 45 Whereas get copies a value from a specified index on the stack, the put command stores a new value into a specified index on the stack. It can be used to model the mutable variables and data of other languages in Postfix. (postfix {Given args a, b and c, calculate ac - b} get {Push c} {Replace c and a by ac on top of stack} put {Replace c by ac on bottom of stack} {Calculate ac - b} ) [;;4] 5 Executable sequences are compound commands like ( ) that are pushed onto the stack as a single value. They can be uted later by the command. Executable sequences act like routines in other languages. Execution of an utable sequence is similar to a routine call, except that transmission of arguments and results is accomplished via the stack. (postfix ( ) ) [] 4 (postfix 0 (0 ) ) [] - {( ) is a doubling routine.} (postfix 0 ( ) (0 ) ) [] - (postfix 0 ( )) [] error {Final top of stack is not an integer.} (postfix 0 ( ) gt) [] error {Executable sequence where number expected.} (postfix 0 ) [] error {Number where utable sequence expected.} (postfix (( get ) ( ) ) ) [] 9 {Given n, calculates n-5} The last example illustrates that evaluations involving utable sequences can be rather contorted. Fig. shows a trace for this example. Convince yourself that for an argument n, the program in the last example calculates n 5 (though not in a straightforward way!). The sel command selects between two values. It can be used in conjunction with to conditionally ute one of two utable sequences. (postfix sel) [] (postfix sel) [0] (postfix sel) [] {Any non-zero integer counts as true } (postfix 0 ( ) 4 sel) [] error {Test not a number.} (postfix 4 lt (add) () sel ) [;4;5;6] 0 (postfix 4 lt (add) () sel ) [4;;5;6] 6

Commands (( get ) ( ) ) ( get ) ( ) ( ) get get Stack 5 5 4 9 (( get ) ( ) ) (( get ) ( ) ) (( get ) ( ) ) ( get ) ( ) ( get ) ( get ) ( ) ( ) ( ) ( ) ( ) 4 4 4 Figure : Step-by-step ution of a contorted example.

Postfix s combination of, sel, and get/put is very powerful, since it permits the expression of arbitrary iterations and recursions. For example, here is an iterative factorial program written in Postfix: (postfix ({factorial loop code} get 0 eq {is n = 0?} () {if yes, we re done; ans is on top of stack} ( get {if no, update state vars: ans n*ans} get put {and n n-} get ) {then ute loop again} sel ) { n with factorial loop code} {push initial answer = } get {ute loop} ) To see how this works, consider the following ution trace for calculating the factorial of. To simplify the trace, many steps have been omitted, and the utable sequence annotated {factorial loop code} has been abbreviated as FactIter. A key invariant maintained during the loop is that the bottom three stack values are, from top to bottom, () the current answer (i.e., the running product of numbers n processed so far); () the current value of n; and () the utable sequence FactIter. Commands Stack FactIter get get FactIter get FactIter get FactIter get FactIter FactIter FactIter get 0 eq () ( get get put get ) sel ) FactIter get 0 eq () ( get get put get ) sel ) FactIter get 0 eq () ( get get put get ) sel ) 6 FactIter get 0 eq () ( get get put get ) sel ) 6 0 FactIter 6 0 FactIter It is even possible to calculate factorial recursively in Postfix, as is demonstrated by the following program: (postfix ({factorial recursion code} get 0 eq {is n = 0?} (pop pop ) {if yes, return } ( get {push n-} get get {call fact recursively} pop {delete fact code} {tiply on way out} ) sel ) get {call fact initially} ) To see how it works, consider an ution trace on the argument (Fig. ). We use the name to abbreviate the utable sequence annotated {factorial recursion code}, and we omit many intermediate steps. On the way into the recursion, each integer from the initial argument value n down to 0 is pushed onto the stack along with a copy of the sequence. Additionally, 8

the pending code pop is added to the command sequence. This pending code, which tiplies the numbers on the stack, is performed on the way out of the recursion. It turns out that Postfix is as powerful as any programming language can be. It is Turing complete, which means that it can express any computable function. Any Turing complete language is not only powerful, but also dangerous, in the sense that it is possible to write infinite loops that never return. Here is a simple infinite loop program: (postfix 0 ( get ) get ) [] {Never returns from infinite loop!} To see why this is a infinite loop, consider its ution trace: Commands Stack ( get ) get get ( get ) get ( get ) ( get ) ( get ) get ( get ) Hey! We ve been here before, and will be here again infinitely many times! The only commands we haven t seen in action yet are those involving strings. These aren t strictly necessary, but are nice to have for debugging purposes. For example: (postfix "\nadding " prs {Display Adding after a newline} get pri {Display st arg} " and " prs {Display and } get pri {Display nd arg} "\n" prs {Display newline} add {Return sum of args} ) [;] 0 {Returns 0, after displaying Adding and on the console} As a more compelling example of using strings in a program, consider annotating the iterative factorial program with code that prints the values of n and ans at the beginning of each iteration of the loop: (postfix ( get 0 eq ("\n" prs) ("\n n=" prs get pri "; ans=" prs get pri get get put get ) sel ) get ) For example, running the above program on 5 returns 0 after displaying the following text in the console window: n=5; ans= n=4; ans=5 n=; ans=0 n=; ans=60 n=; ans=0 9

Commands Stack get get get get 0 eq (pop pop ) ( get get get pop ) sel get get get pop get 0 eq (pop pop ) ( get get get pop ) sel pop get 0 eq (pop pop ) ( get get get pop ) sel pop pop get 0 eq (pop pop ) ( get get get pop ) sel pop pop pop pop pop pop pop pop pop pop pop pop pop 0 0 pop pop 6 Figure : Trace of the recursive factorial program on the input. 0