This lab is designed to transition our interpreter to a more powerful image processing engine by binding in new data types, high performance primitives, and automatic parallelization of interpretation.
This lab builds on the previous interpreters. In addition, to support the image processing primitives and text rendering primitives, you will need to install the
Images packages into Julia. This is done using the Julia package management system:
Note: Julia uses Git as the foundation of their package management system. This can create problems if your system can't access Git using a
protocol – this is manifest by Julia hanging when trying to install packages. To alleviate this, please check out the following links:
When I installed my Julia packages, it took a long time, but it worked. Be patient. :)
For this lab, you will expand the interpreter that we have already built in three ways: with new data types, new high performance primitives, and automatic parallelization.
The primary deliverable for this lab is a new Julia module. Your module should export
analyze functions, and three return types,
Your module should be able to do everything that the three previous interpreters could do. You are welcome to examine the code we developed in class. The
CI6.jl module is available on LearningSuite, under “Content → Julia → High Performance Primitives”.
Please name your module
For this lab, you will implement several new features:
Each is discussed in more detail in the following sections.
The grammar for our new language is the following:
<OWL> ::= number | (+ <OWL> <OWL> <OWL>*) # all owls could be a MatrixVal or a NumVal | (- <OWL> <OWL>) | (* <OWL> <OWL>) | (/ <OWL> <OWL>) | (mod <OWL> <OWL>) | (- <OWL>) | (collatz <OWL>) # Only a NumVal version required for collatz | id | (if0 <OWL> <OWL> <OWL>) | (with ( (id <OWL>)* ) <OWL>) | (lambda (id*) <OWL>) | (and <OWL> <OWL> <OWL>*) | (<OWL> <OWL>*) # # new primitives here # | (simple_load <string>) | (simple_save <OWL> <string>) # this owl should evaluate to a MatrixVal | (render_text <string> <OWL> <OWL>) # these owls should evaluate to NumVals | (emboss <OWL>) # this owl should evaluate to a MatrixVal | (drop_shadow <OWL>) # this owl should evaluate to a MatrixVal | (inner_shadow <OWL>) # this owl should evaluate to a MatrixVal | (min <OWL> <OWL>) # boths owls could be a MatrixVal or a NumVal | (max <OWL> <OWL>)
The new productions in our language map directly to the primitive functions of the same name. For each, you will need to do the following:
We've been through this process several times in class, so we won't belabor it here.
You must also ensure that the
/ operators work any combination of
MatrixVal. I showed you my solution to this problem in class, but the reference code does not contain that, because your implementation (using
BinOp) is likely quite different.
A few notes:
min,max,+,-,/,*functions all must work with any combination of
.*operation (element-wise matrix multiply) instead of
The new primitives create new opportunities for error handling. You should bullet-proof them!
In particular, you should carefully check the number and type of all subexpressions and strings. For example, operations such as
max should operate on
MatrixVal objects, but should throw an error if handed something like a
We discussed several opportunities for parallelization in class. You must use the proper combination of
fetch to parallelize as many of the
calc functions as possible by spawning for each sub-call to
calc. You do not need to parallelize the analyze functions.
Once all is said and done, the following program:
(with ((base_img (render_text "Hello" 25 100)) (swirl (simple_load "/Users/wingated/Desktop/swirl_256.png"))) (with ((ds (drop_shadow base_img))) (with ((tmp4 (+ (* (+ (min ds base_img) (- 1 base_img)) base_img) (* (- 1 base_img) swirl) ))) (with ((tmp5 (- 1 (emboss tmp4))) (base_img2 (render_text "world!" 5 200))) (with ((is (inner_shadow base_img2))) (with ((tmp6 (max base_img2 (* (- 1 base_img2) is) ))) (with ( (output (min tmp5 tmp6 )) ) (simple_save output "output.png") ) ) ) ) ) ) )
should generate the image shown below, using the
swirl_256.png image shown at the right: