Milestone 2

Assigned: 10/2
Due: Wednesday 10/24 by 11:59 pm Monday 10/29 by 11:59 pm

Updates

Introduction

In this milestone you will extend PlotScript with some additional features and add support for the graphics primitives Point, Line, and Text. You will also prototype the interface to the graphical notebook application using Qt.

You should complete milestone 0 and 1 before attempting this one.

Background Information

Task 1: Adding a literal string type

We will need the ability to give our plots titles, label axes, etc. For this we need a simple string type. Our strings will always be constant string literals denoted by surrounding " (decimal ASCII character 34) and can include any printable character (including spaces) other than ". Extend the interpreter code to support such strings as the type String which are entered directly with quotes. Strings are printed as expressions, including the surrounding quotes to distinguish them from symbols. For now, we are not defining any procedures that operate on strings, but they should be able to be used within PlotScript; i.e. symbols can be defined as strings and lists can hold strings, strings can be used as procedure arguments, etc. Some examples:

plotscript> ("foo")
("foo")
plotscript> ("a string with spaces")
("a string with spaces")
plotscript> (define x ("foo"))
("foo")
plotscript> (x)
("foo")
plotscript> (define mylist (list "eggs" "bread" "milk" "bacon"))
(("eggs") ("bread") ("milk") ("bacon"))
plotscript> (first mylist)
("eggs")

Note: Implementing the String type will require modifications to the Token and Parse modules, in addition to the classes you have modified in earlier milestones.

Task 2: Adding property lists

Now that we have added several features to plotscript, it has become quite useful as a scripting language. The last major piece we will need is a way to tag certain expression with properties. While these might have many uses, we will apply them in the next task to implement geometric primitives within PlotScript itself.

In the C++ code, add the ability to store a property list, consisting of unordered key-value pairs (entries in the property list), associated with the head of an expression. The key must be an expression of PlotScript type String. The value can be any Expression. Properties get copied and assigned with the expression, but do not affect comparisons.

Add two built-in procedures, set-property and get-property, to set and retrieve a property.

Note: In the starter code, Expressions of type None where printed as () but now that we have empty lists, this needs to be adjusted. You should modify the way these expressions are printed to match the example above, that is print NONE for PlotScript Expressions of type None.

Task 3: Implementing graphic primitives

We will need some simple graphical primitives to build our plots from. These should be implemented in plotscript itself as defined lambda expressions, using the previously developed features, and saved as a plain-text file in the source code repository (give it the extension .pls). These pre-defined lambda functions should be parsed and evaluated by plotscript before interpreting any user code (from a file the -e flag, or the REPL). If there is a parsing or semantic error in the start-up script, it should be reported as an warning by the REPL prior to printing results or prompt.

Points: A Point graphic consists of a PlotScript List of two numbers representing a point in a two-dimensional plane, where the first number is the horizontal coordinate and the second number is the vertical coordinate. The list is tagged with the property "object-name" with a value of "point".

Point graphics have the properties:

The following user-defined procedure should be developed in Plotscript and placed in the start-up file.

Line: A Line graphic consists of a PlotScript List with two Point entries indicating the start and end-points of the line respectively.

Lines graphics have the properties:

The following user-defined procedure should be developed in Plotscript and placed in the start-up file.

Text: A Text graphic consists simply of a PlotScript String.

Text graphics have the properties:

The following user-defined procedure should be developed in Plotscript and placed in the start-up file.

Note that there is no precondition checking or error checking within the PlotScript procedures.


Our code will need to locate the start-up script file at run-time. To do this add a text file named startup_config.hpp.in to the source code repository with the following contents

#ifndef STARTUP_CONFIG_HPP
#define STARTUP_CONFIG_HPP

#include <string>

const std::string STARTUP_FILE = "@STARTUP_FILE@";

#endif

We need to configure cmake to use this file to create a header startup_config.hpp in the build directory with the @STARTUP_FILE@ string above replaced by the actual location of the startup file in the source code repository. To do this add the following to the CMakeLists.txt file (replace startup.pls with whatever you named your file)

set(STARTUP_FILE ${CMAKE_SOURCE_DIR}/startup.pls)
configure_file(${CMAKE_SOURCE_DIR}/startup_config.hpp.in ${CMAKE_BINARY_DIR}/startup_config.hpp)
include_directories(${CMAKE_BINARY_DIR})

Now when you run configure using cmake it will write the startup_config.hpp into the build directory, which we can then include and use to locate the file.

Task 4: Starting the notebook implementation

Important Note: In order for testing and grading to work properly the type and object names specified below must be adhered to.

The initial notebook interface consists of two widgets, of type InputWidget and OutputWidget, arranged vertically within a main widget NotebookApp. The NotebookApp widget should be used in the notebook.cpp file to instantiate and show the NotebookApp widget, and enter the Qt event loop only (no other work should be done). The NotebookApp module filename should be notebook_app.hpp/.cpp.

InputWidget must derive from QPlainTextEdit (using dynamic polymorphism) and have a Qt object name of "input". The InputWidget module filename should be input_widget.hpp/.cpp. The widget should allow the user to type in PlotScript code within the widget. If the user enters Shift-Enter (hold a shift key down while pressing the return/enter key) the current text is evaluated as a plotscript expression. The result, one of a parsing error, an expression, or an exception, is displayed by the OutputWidget.

OutputWidget must internally use QGraphicsView, QGraphicsScene, and related types using composition, and have a Qt object name of "output". The OnputWidget module filename should be output_widget.hpp/.cpp. The widget should display the output from the previous expression evaluation using the following formatting rules.

Formatting Rules:

The display is cleared before displaying the next results. For this milestone we will use the default QGraphicsView coordinate system. Below is a video demonstrating the expected behavior. Note the widgets on your host may appear slightly different. You can pause the video to see study specific input/output behavior. Note the example with the user-defined procedure looks strange, but that is the expected behavior for this milestone.

Task 5: Functional tests for NotebookApp

You should write functional tests for your NotebookApp widget within the provided notebook_test.cpp file. These should locate the widgets defined above (see lecture 14) and used them to inject user input and verify the proper response. There is no explicit coverage requirement for these tests, however you should have tests that demonstrate the all the expected behaviors defined above.

Submission

To submit your milestone:

  1. Tag the git commit that you wish to be considered for grading as "milestone2".

    git tag milestone2
  2. Push this change to GitHub

    git push origin milestone2

If you need to tag a different version of your code simply create and push a new tag appending a monotonically increasing number to milestone0 using '-', e.g. milestone2-2, milestone2-3, etc.

Be sure you have committed all the changes you intend to. You should re-clone your repository into a separate directory and double check it is what you intend to submit. Failure to complete these steps by the due date will result in a failed submission.

Grading

There are 6 course percentage points allocated to this milestone. You will receive a detailed feedback report on your submission via Canvas within two weeks of the due date.

Code compiles in the reference environment 0.5 points
Correctness Tests 4 points
Testing 0.5 points
Code Quality 0.5 point
Good Development Practices 0.5 point

Grading Notes: