IPython magic for ParselTongue

## Project description

This python module adds ipython magic for the ParselTongue language that is part of the online programming languages class run at Brown.

You can install this module using pip as follows pip install pslmagic

## Notes for Windows Users

If you intend to use this module on Windows, you will need the do the following

1. install and have bash on your PATH. An acceptable version of bash is included in the Git for Windows installer, make sure to select Use Git and optional Unix tools for the Windows Command Prompt

2. Use relative addresses when registering the executable and specifying the test file base (see below).

## Using pslmagic

The first step when using pslmagic is to start the ipython notebook, preferably from the command line in the test folder.

ipython notebook

Start a new notebook and run the following command to load palmagic

%reload_ext pslmagic
WARNING:Please register the address of the ParselTongue executable            using %psl_exe <address>

### Register the ParselTongue interpreter(s)

You need to download the parseltongue interpreter from the Brown CS1730 page

Then, call the psl_exe to register the address for the execuable (Use a relative address for Windows)

%psl_exe /Users/tiverson/Desktop/osx-dist/bin/assignment1-osx

### Line magic to evaluate short commands

You can evaluate a single line of ParselTongue using the psl magic. A single % indicates line magic

%psl +(40, 2)
42

### Errors are thrown as python exceptions

%psl 5;7
  File "<string>", line unknown
SyntaxError: Encountered error while parsing, near: "" [line=#f, column=#f, position=#f]

### Use cell magic to evaluate longer programs

You can type a whole cell of ParselTongue using the %%psl cell magic. The double % are used to indicate cell magic, and the remainder of the current cell will be considered ParselTongue.

%%psl
# deffun defines a recursive function
deffun fib(n)
# operators like + and == are prefix
if <(n, 1) then 0 else
if ==(n, 1) then 1 else
+(fib(-(n, 1)), fib(-(n, 2)))
# The in ends the function body in a deffun, which can be followed by
# another deffun, a defvar, or a braced expression
in
# defvar creates a new variable with an initial value, bound inside the
# body of the defvar
defvar x = 0 in {
# For loops have an initialization, a test, an update, and a body
for(x = 0; <(x,10); x++) {
# print takes any value and displays it
print(fib(x));
print(" ");
};
# The result of the program is the value of the last expression
# evaluated.  It is printed, so we avoid printing it by terminating the
# program with a ""
"";
}
0 1 1 2 3 5 8 13 21 34

### Create tests for the test suite

You can create a test for your test suite using the %%psl_create_test magic. The first argument (on the %%psl_create_test line) is the base file name. Three files will be created

1. base.psl - contains the code in the cell

2. base.psl.expected - creates the output when running the code vs. the correct interpreter.

3. base.psl.error - contains any errors generated when running vs. the correct interpreter

%%psl_create_test test_case
# deffun defines a recursive function
deffun fib(n)
# operators like + and == are prefix
if <(n, 1) then 0 else
if ==(n, 1) then 1 else
+(fib(-(n, 1)), fib(-(n, 2)))
# The in ends the function body in a deffun, which can be followed by
# another deffun, a defvar, or a braced expression
in
# defvar creates a new variable with an initial value, bound inside the
# body of the defvar
defvar x = 0 in {
# For loops have an initialization, a test, an update, and a body
for(x = 0; <(x,10); x++) {
# print takes any value and displays it
print(fib(x));
print(" ");
};
# The result of the program is the value of the last expression
# evaluated.  It is printed, so we avoid printing it by terminating the
# program with a ""
"";
}

To inspect the resulting files, run the following commands

%%bash
echo "*******PSL FILE*******"
less test_case.psl
echo "*******EXPECTED RESULTS FILE*******"
less test_case.psl.expected
echo "*******ERROR FILE*******"
less test_case.psl.error
*****PSL FILE*****
# deffun defines a recursive function
deffun fib(n)
# operators like + and == are prefix
if <(n, 1) then 0 else
if ==(n, 1) then 1 else
+(fib(-(n, 1)), fib(-(n, 2)))
# The in ends the function body in a deffun, which can be followed by
# another deffun, a defvar, or a braced expression
in
# defvar creates a new variable with an initial value, bound inside the
# body of the defvar
defvar x = 0 in {
# For loops have an initialization, a test, an update, and a body
for(x = 0; <(x,10); x++) {
# print takes any value and displays it
print(fib(x));
print(" ");
};
# The result of the program is the value of the last expression
# evaluated.  It is printed, so we avoid printing it by terminating the
# program with a ""
"";
}*******EXPECTED RESULTS FILE*******
0 1 1 2 3 5 8 13 21 34
*****ERROR FILE*****

### Run the test suite versus the 25 incorrect interpreters

You can run your test suite versus the 25 incorrect interpreters using the %psl_run_tests magic. The first argument is the address of the execuable (again using relative addresses on Windows)

%psl_run_tests /Users/tiverson/Desktop/sample-test-suite/
bindings1:
bindings2:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

bindings3:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl
/Users/tiverson/Desktop/sample-test-suite/functions/func5.psl

bindings4:
functions1:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/functions/func5.psl

functions2:
functions3:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

if-then-else1:
if-then-else2:
if-then-else3:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/if1.psl
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

loops1:
loops2:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

loops3:
loops4:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

loops5:
objects1:
objects2:
objects3:
objects4:
operators1:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

operators2:
operators2:
operators3:
sequence1:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

sequence2:
Differences in:
/Users/tiverson/Desktop/sample-test-suite/test_case.psl

You found bugs in 10/25 interpreters.

## Run versus a single interpreter with psl_run_single

You can use the line magic psl_run_single to run a test suite against just one interpreter. The two arguments for this magic are the interpreter name (see psl_run_tests output) and the directory

%psl_run_single <interp-name> <director>
%psl_run_single if-then-else3 /Users/tiverson/Desktop/sample-test-suite/
if-then-else3:
2 tests succeeded.
2 tests failed.
== Output of failed tests ==
=====================================================
=   Results for /Users/tiverson/Desktop/sample-test-suite/if1.psl   =
=====================================================
=== Expected stdout ===
passed
passed
passed
passed

=== Actual stdout ===
failed
passed
failed
failed

=== Expected stderr ===

=== Actual stderr ===

=====================================================
=   Results for /Users/tiverson/Desktop/sample-test-suite/test_case.psl   =
=====================================================
=== Expected stdout ===
0 1 1 2 3 5 8 13 21 34

=== Actual stdout ===

=== Expected stderr ===

=== Actual stderr ===

You found bugs in 1/1 interpreters.

## Project details

Uploaded source