diff --git a/src/haz3lweb/exercises/examples/Tu_ComposingArithmetic.ml b/src/haz3lweb/exercises/examples/Tu_ComposingArithmetic_and_Scope.ml similarity index 57% rename from src/haz3lweb/exercises/examples/Tu_ComposingArithmetic.ml rename to src/haz3lweb/exercises/examples/Tu_ComposingArithmetic_and_Scope.ml index 8cb8b4f67f..44a59ef817 100644 --- a/src/haz3lweb/exercises/examples/Tu_ComposingArithmetic.ml +++ b/src/haz3lweb/exercises/examples/Tu_ComposingArithmetic_and_Scope.ml @@ -44,3 +44,43 @@ let exercise : Tutorial.spec = hints = []; }; } + +let scope_exercise : Tutorial.spec = + { + title = "Scope"; + module_name = "Tu_Scope"; + prompt = + "The scope of a variable is the expression(s) of the program where it is \ + available for use. For let expressions, the sub-expression that follows \ + the `in` keyword has the variable bound by the let expression in scope. \ + Hazel's expression decorations show you where the scope of the variable \ + will end."; + wrapper = true; + version = 1; + your_impl = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hidden_tests = + { + tests = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hints = []; + }; + } diff --git a/src/haz3lweb/exercises/examples/Tu_ComputingEquationally.ml b/src/haz3lweb/exercises/examples/Tu_ComputingEquationally_Shadow.ml similarity index 50% rename from src/haz3lweb/exercises/examples/Tu_ComputingEquationally.ml rename to src/haz3lweb/exercises/examples/Tu_ComputingEquationally_Shadow.ml index df532525f0..308eba1a9f 100644 --- a/src/haz3lweb/exercises/examples/Tu_ComputingEquationally.ml +++ b/src/haz3lweb/exercises/examples/Tu_ComputingEquationally_Shadow.ml @@ -42,3 +42,45 @@ let exercise : Tutorial.spec = hints = []; }; } + +let shadow_exercise : Tutorial.spec = + { + title = "Shadowing"; + module_name = "Tu_Shadowing"; + prompt = + "Once a variable is defined, it cannot be changed. There is no \ + assignment operator in languages based on pure mathematical \ + expressions, where variables are given meaning by substitution, like \ + Hazel. However, it is possible to define a `new variable` that shares \ + the name of a previously bound variable. However, this makes it \ + impossible to refer to the previous binding within the scope of the new \ + binding; we say that variable has been `shadowed`."; + wrapper = true; + version = 1; + your_impl = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hidden_tests = + { + tests = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hints = []; + }; + } diff --git a/src/haz3lweb/exercises/examples/Tu_More.ml b/src/haz3lweb/exercises/examples/Tu_More.ml new file mode 100644 index 0000000000..b79f0a99d1 --- /dev/null +++ b/src/haz3lweb/exercises/examples/Tu_More.ml @@ -0,0 +1,133 @@ +open Haz3lcore + +let bools_ex : Tutorial.spec = + { + title = "Booleans and Types"; + module_name = "Tu_Booleans_and_Types"; + prompt = + "So far, we have only seen expressions that evaluate to integers. \ + However, Hazel supports many other types of values, like booleans. \ + There are two boolean values, `true` and `false` Hazel's type system \ + ensures that expressions are used in ways that make sense. Each \ + expression has a type, which predicts the type of its value. The \ + expressions in the previous slides all had type `Int`, which is the \ + type of integers, whereas the boolean values have type `Bool`. You can \ + see the type of the expression your cursor is on in the cursor \ + inspector at the bottom of the screen. The symbol `:` is pronounced \ + \"has type\". Boolean values can be constructed by using comparison \ + operators like `<`, `==`, and `>` on integers. For example, `2 < 3` \ + evaluates to `true`. Booleans can also be combined using logical and \ + (conjunction), `&&`, and logical or (disjunction), `||`."; + wrapper = true; + version = 1; + your_impl = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hidden_tests = + { + tests = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hints = []; + }; + } + +let cond_ex : Tutorial.spec = + { + title = "Conditional Expressions"; + module_name = "Tu_Conditional_Expressions"; + prompt = + "Given a boolean expression, we can use it to choose between two \ + expressions using a `conditional expression`. For example, `if 2 < 3 \ + then 4 * 4 else 5 * 5` evaluates to `4`."; + wrapper = true; + version = 1; + your_impl = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hidden_tests = + { + tests = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hints = []; + }; + } + +let func_ex : Tutorial.spec = + { + title = "Functions"; + module_name = "Tu_Functions"; + prompt = + "Functions are expressions that take other expressions as inputs and \ + produce other expressions as outputs. For example, `fun x -> x + 1` is \ + a function that takes an integer expression as input and produces an \ + integer expression as output. Functions in Hazel do not themselves have \ + names. Instead, you can use a let expression to name a function.\n\ + \ \n\ + \ You apply a function to an argument expression by using \ + parentheses in the usual way. For example, `let f = fun x -> x + 1 in \ + f(2)` evaluates to `3` . Go through this example in the stepper to see \ + how substitution of the function for the variable standing for the \ + function works."; + wrapper = true; + version = 1; + your_impl = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hidden_tests = + { + tests = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hints = []; + }; + } diff --git a/src/haz3lweb/exercises/examples/Tu_Variables.ml b/src/haz3lweb/exercises/examples/Tu_Variables_and_Compositionality.ml similarity index 58% rename from src/haz3lweb/exercises/examples/Tu_Variables.ml rename to src/haz3lweb/exercises/examples/Tu_Variables_and_Compositionality.ml index 76513ae19a..3d2ffad896 100644 --- a/src/haz3lweb/exercises/examples/Tu_Variables.ml +++ b/src/haz3lweb/exercises/examples/Tu_Variables_and_Compositionality.ml @@ -44,3 +44,41 @@ let exercise : Tutorial.spec = hints = []; }; } + +let comp_exercise : Tutorial.spec = + { + title = "Compositionality"; + module_name = "Tu_Compositionality"; + prompt = + "Let expressions are expressions, just like arithmetic expressions. As \ + we discussed earlier, expressions are constructed compositionally, so \ + we can even make a let expression an operand of an arithmetic operator."; + wrapper = true; + version = 1; + your_impl = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hidden_tests = + { + tests = + { + selection = { focus = Left; content = []; mode = Normal }; + backpack = []; + relatives = + { + siblings = ([ Grout { id = Id.mk (); shape = Convex } ], []); + ancestors = []; + }; + caret = Outer; + }; + hints = []; + }; + } diff --git a/src/haz3lweb/exercises/settings/TutorialSettings_base.re b/src/haz3lweb/exercises/settings/TutorialSettings_base.re index a91a47bf5c..484f47a674 100644 --- a/src/haz3lweb/exercises/settings/TutorialSettings_base.re +++ b/src/haz3lweb/exercises/settings/TutorialSettings_base.re @@ -2,7 +2,12 @@ let filename = "haz3l-demo"; let log_key = filename; let exercises: list(Tutorial.spec) = [ Tu_ExpressiveProgramming.exercise, - Tu_ComposingArithmetic.exercise, - Tu_ComputingEquationally.exercise, - Tu_Variables.exercise, + Tu_ComposingArithmetic_and_Scope.exercise, + Tu_ComputingEquationally_Shadow.exercise, + Tu_Variables_and_Compositionality.exercise, + Tu_Variables_and_Compositionality.comp_exercise, + Tu_ComposingArithmetic_and_Scope.scope_exercise, + Tu_ComputingEquationally_Shadow.shadow_exercise, + Tu_More.bools_ex, + Tu_More.func_ex, ];