This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
cs330_f2016:labw [2018/02/01 21:11] morse |
cs330_f2016:labw [2021/06/30 23:42] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | **This is a draft version of the assignment and may change until the due date of the preceding assignment. | ||
- | ** | ||
- | |||
====Objective:==== | ====Objective:==== | ||
Line 9: | Line 6: | ||
====Pre-requisite:==== | ====Pre-requisite:==== | ||
- | For this lab, you should have Julia 0.6+ installed, the same as for the rudimentary interpreter. You will need both the Lexer and Error modules. | + | For this lab, you should have Julia 1.0 installed, the same as for the rudimentary interpreter. You will need both the Lexer and Error modules. |
---- | ---- | ||
Line 85: | Line 82: | ||
(lambda x (+ x 1)) | (lambda x (+ x 1)) | ||
or | or | ||
- | (with x 5 (+ x 1)) | + | (with (x 5) (+ x 1)) |
</code> | </code> | ||
Line 115: | Line 112: | ||
**Remember to throw errors, not simply print error messages.** | **Remember to throw errors, not simply print error messages.** | ||
- | Your parser and interpreter must detect errors and explicitly signal them by calling throw(LispError(Reason). We will consider an error raised internally by julia to be a bug in your code. | + | Your parser and interpreter must detect errors and explicitly signal them by calling throw(LispError(Reason). **We will consider an error raised internally by julia to be a bug in your code.**. Think how you'd feel as a programmer if an error in your source code caused your compiler to crash instead of telling you what was wrong. |
To include LispError put "using Error" after the module declaration of you code. Error is a module containing LispError. | To include LispError put "using Error" after the module declaration of you code. Error is a module containing LispError. | ||
- | |||
- | For example, Julia signals a “divide by zero” error if you attempt to evaluate (/ 1 0). Since we use Julia's division function to implement division in OWL, you may be tempted to leave it to Julia to signal division by zero errors for you. However, you must signal the error yourself by explicitly testing for division by zero before calling Julia's division procedure. | ||
---- | ---- | ||
Line 134: | Line 129: | ||
abstract type AE end | abstract type AE end | ||
- | type NumNode <: AE | + | struct NumNode <: AE |
n::Real | n::Real | ||
end | end | ||
- | type BinopNode <: AE | + | struct BinopNode <: AE |
op::Function | op::Function | ||
lhs::AE | lhs::AE | ||
Line 144: | Line 139: | ||
end | end | ||
- | type If0Node <: AE | + | struct If0Node <: AE |
condition::AE | condition::AE | ||
zero_branch::AE | zero_branch::AE | ||
Line 150: | Line 145: | ||
end | end | ||
- | type WithNode <: AE | + | struct WithNode <: AE |
- | name::Symbol | + | sym::Symbol |
binding_expr::AE | binding_expr::AE | ||
body::AE | body::AE | ||
end | end | ||
- | type IdNode <: AE | + | struct VarRefNode <: AE |
- | name::Symbol | + | sym::Symbol |
end | end | ||
- | type FunDefNode <: AE | + | struct FunDefNode <: AE |
- | formal_parameter::Symbol | + | formal::Symbol |
- | fun_body::AE | + | fun_body::AE |
end | end | ||
- | type FunAppNode <: AE | + | struct FunAppNode <: AE |
- | fun_expr::AE | + | fun_expr::AE |
- | arg_expr::AE | + | arg_expr::AE |
end | end | ||
- | |||
- | # Rejigger our type hierarchy to better support return values | ||
- | |||
- | # Define both abstract types before we use them | ||
abstract type RetVal end | abstract type RetVal end | ||
Line 178: | Line 169: | ||
abstract type Environment end | abstract type Environment end | ||
- | type NumVal <: RetVal | + | struct NumVal <: RetVal |
n::Real | n::Real | ||
end | end | ||
- | type ClosureVal <: RetVal | + | struct ClosureVal <: RetVal |
- | param::Symbol | + | formal::Symbol |
- | body::OWL | + | body::AE |
- | env::Environment # this is the environment at definition time! | + | env::Environment |
end | end | ||
- | # Definitions for our environment data structures | + | struct EmptyEnv <: Environment |
- | + | ||
- | type mtEnv <: Environment | + | |
end | end | ||
- | type CEnvironment <: Environment | + | struct ExtendedEnv <: Environment |
- | name::Symbol | + | sym::Symbol |
- | value::RetVal | + | val::RetVal |
parent::Environment | parent::Environment | ||
end | end | ||
Line 210: | Line 199: | ||
<code Julia> | <code Julia> | ||
- | function parse(expr::Array{Symbol or Real}) | + | function parse(expr::Any) |
- | function calc(ast::OWL) | + | function calc(ast::AE) |
</code> | </code> | ||
Line 218: | Line 207: | ||
**Conditionals:** | **Conditionals:** | ||
- | The semantics of (if0 test then else) is: if the test evaluates to zero, then the entire expression evaluates to the result of then, otherwise, it evaluates to else. Evaluation should signal an error for non-numeric test values. | + | The semantics of (if0 test then else) is as follows: if the test evaluates to zero, then the entire expression evaluates to the result of then expression, otherwise, it evaluates to the result of the else expression. Evaluation should signal an error for non-numeric test values. |
**Multi-argument fun** | **Multi-argument fun** |