HW 4: Pic2PS, Part 1

Overview

The pic language is a domain-specific language (DSL) for drawing pictures. In this assignment, you will implement a compiler/translator that turns a useful subset of the pic language into PostScript. In particular, you will:

  1. Write helper functions that generate PostScript code (e.g., to draw a box).

  2. Use the helper functions to implement an evaluator for pic. The evaluator takes as input a pic AST and generates as output the corresponding PostScript code.

Specifications

There are two specifications that come with this assignment: one for pic and one for PostScript. Your compiler must correctly translate the pic semantics to PostScript, so it is important that you read and understand these parts, and keep them beside you for reference as your implement pic2ps.

We recommend you skim through them now, then read them in more detail before and as your work on the assignment.

Materials

Use the assignment workflow and the link provided on Piazza to get access to this week’s files.

Style, Elegance, and Errors (10%)

Your code should be reasonably well-commented in order to help the graders understand your code. Ten percent of your grade will be based on clarity (e.g., well-documented with comments, good variable names, and generally easy it to understand how your code works) and elegance (e.g., factoring out common code rather than duplicating sections of code).

As always, to get credit, your final submission may not have syntax or type errors. Because you’re coding to a specification, submitted functions must have the exact names and types given in the assignment (though you are encouraged to define other helper functions, as needed).

Your task: Write useful comments and use good names for variables and functions, as you write your code. To make your code elegant, you may need a few iterations of writing—it’s often difficult to write elegant code on the first try. Instead, focus on writing correct, readable code. Then, focus on making it elegant (perhaps by enlisting help from a grutor or professor).

Part 1: A PostScript Library (28%)

The PostScript module defined in the file PostScript.hs is supposed to contain helper functions that generate PostScript code for most of the shapes needed for pic.

For example, the function

  circleCode :: XYPos -> Scalar -> [PostScriptLine]

is supposed to generate PostScript code (i.e., a list of strings, where each string is a line of PostScript code) that draws a circle.

Your task: Implement the undefined functions in PostScript.hs.

Comments / Suggestions

Understand before you code. Be sure you feel relatively good about PostScript programs, especially the stack-based model and how to draw shapes. Also, read over the given code, especially in PostScript.hs, to understand what’s already been implemented, to see what is required of you, and to start getting some ideas for your implementation.

Implementation techniques. For debugging purposes, it can be handy to have your code add comments to the generated PostScript output itself, but you are not required to do so.

Testing. Because there are many ways to generate PostScript for a given picture, we can’t auto-test the string outputs of your functions. You can manually test your functions by loading PostScript.hs into ghci, then using emitCode with the name of an output PostScript file and whatever lines of PostScript you want to check. For example:

    emitCode "testtext.ps" (textCode (3,4) ["Strings centered", "at (3,4)"])
    emitCode "testbox.ps" (boxCode (5,5) 2 2)

You can then look at your output file (e.g., testtext.ps) with gv on knuth. On a Mac, you should run pstopdf or ps2pdf on your PostScript file to get a PDF file, and then open the PDF file with Preview.

Part 2: A Pic-to-PostScript evaluator (62%)

This assignment comes with a number of other files, most of which implement a parser that translates pic concrete syntax into abstract syntax. The file PicAST.hs defines the abstract syntax, as Haskell data types.

The main code for drawing pictures is in PicEvaluator.hs. In this file, the core of evaluation happens in the function

    doElem :: Element -> State -> ([PostScriptLine], State)

Given pic’s current state (current page position and current direction) and a pic element, the doElem function yields lines of PostScript code for that command, along with the new page position and the new current direction. Unfortunately, this function is unfinished, and there are a number of very handy helper functions that are not being used (yet).

Your task: Complete the pic evaluator, by finishing doElem.

Comments / Suggestions

Understand before you code. Be sure you feel relatively good about pic programs, especially the semantics.

Do some planning before you start writing your code. At a minimum, you should decide how you’ll break this problem down into helper functions (and possibly how those functions will be broken down in turn). You may also want to see what helper functions already exist (I’m looking at you, PicEvaluation.hs and Coords.hs!). Don’t overlook the provided comments.

Use good programming practices. Be sure to comment your code well. You might need to read / modify this translator in a later assignment; and, besides, it makes it easier for the course staff to help you with your code.

Using your evaluator. Once doElem is complete, you can use the predefined function run to create a PostScript output file from a pic input file. Specifically, load pic2ps.hs in ghci and type run "test1.pic". The run function reads the input file test1.pic, runs it through the lexer, the parser, and your translator, and puts the PostScript output into the file test1.ps.

Testing. Because you are producing images and because there are many ways to generate PostScript for a given pic AST, we can’t directly test the code generated by the evaluator. However, we can test that the evaluator implements pic’s semantics for direction and position. We’ve provided a few tests that do so, which you can run with the command:

  ghc test/StateSpec.hs -e "StateSpec.main"

We recommend that you also check your generated PostScript files against the output of the “official” pic implementation, using the groff procedure from Lab. The picture may appear on a different part of the page, but the shapes and sizes should match.

Where to go from here

Check out the paper on “Little Languages” by Jon Bentley! It uses the pic language as an example.