From 04cc5d578821fe44ae527dc216564c448b3ccbbe Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 9 Jul 2023 21:54:32 +0800 Subject: [PATCH 001/141] Add some function from injection paper. --- src/haz3lcore/dynamics/Incon.re | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/haz3lcore/dynamics/Incon.re diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re new file mode 100644 index 0000000000..a5d4b8ded2 --- /dev/null +++ b/src/haz3lcore/dynamics/Incon.re @@ -0,0 +1,39 @@ +let rec matches = (e: DHExp.t, p: DHPat.t): bool => + switch (e, p) { + | (_, Var(_)) => true + | (_, Wild) => true + | (BoolLit(x), BoolLit(y)) => x == y + | (IntLit(x), IntLit(y)) => x == y + | (FloatLit(x), FloatLit(y)) => x == y + | (StringLit(x), StringLit(y)) => x == y + | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) + // I don't know how to extend the algorithm for projection into that of list or tuples. + | (_, _) => false + }; + +let rec is_val = (e: DHExp.t): bool => + switch (e) { + | BoolLit(_) + | IntLit(_) + | StringLit(_) + | Fun(_, _, _, _) + | ListLit(_, _, _, _, []) + | Tuple([]) => true + | ListLit(_, _, _, _, inner) + | Tuple(inner) => + List.fold_left((last_val, e) => last_val && is_val(e), true, inner) + | BinBoolOp(_, e1, e2) + | BinIntOp(_, e1, e2) + | BinFloatOp(_, e1, e2) + | BinStringOp(_, e1, e2) => is_val(e1) ? is_val(e2) : false + | Inj(_, _, e) => is_val(e) + | _ => false + }; + +let rec is_indet = (e: DHExp.t): bool => + switch (e) { + | EmptyHole(_, _) => true + | NonEmptyHole(_, _, _, e) => is_final(e) + | _ => false + } +and is_final = (e: DHExp.t): bool => is_val(e) && is_indet(e); From 1d1b27aec03e9eaa8541d5662c945740ddd44a35 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 16 Jul 2023 11:59:57 +0800 Subject: [PATCH 002/141] Finished implementing algorithms from P8. --- src/haz3lcore/dynamics/Incon.re | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index a5d4b8ded2..2d403e1174 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -7,10 +7,35 @@ let rec matches = (e: DHExp.t, p: DHPat.t): bool => | (FloatLit(x), FloatLit(y)) => x == y | (StringLit(x), StringLit(y)) => x == y | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) - // I don't know how to extend the algorithm for projection into that of list or tuples. + // I don't know if my algorithm is correct or not. + | (ListLit(_, _, _, _, []), ListLit(_, [])) + | (Tuple([]), Tuple([])) => true + | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) + | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => + matches(hd1, hd2) && matches(Tuple(tl1), Tuple(tl2)) | (_, _) => false }; +let rec does_not_match = (e: DHExp.t, p: DHPat.t): bool => + switch (e, p) { + | (BoolLit(x), BoolLit(y)) => x != y + | (IntLit(x), IntLit(y)) => x != y + | (FloatLit(x), FloatLit(y)) => x != y + | (StringLit(x), StringLit(y)) => x != y + | (ListLit(_, _, _, _, []), ListLit(_, [])) + | (Tuple([]), Tuple([])) => false + | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) + | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => + does_not_match(hd1, hd2) || does_not_match(Tuple(tl1), Tuple(tl2)) + | (Inj(_, side1, x), Inj(side2, y)) => + side1 != side2 || does_not_match(x, y) + | (_, _) => false + }; + +// It is difficult to write indet_match, so I used the theorem to simplify it. Probably it will execute slower. +let indet_match = (e: DHExp.t, p: DHPat.t): bool => + !(matches(e, p) || does_not_match(e, p)); + let rec is_val = (e: DHExp.t): bool => switch (e) { | BoolLit(_) From 092775aba727e12caa8326532a6b1530f8027d58 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Fri, 21 Jul 2023 18:10:34 +0800 Subject: [PATCH 003/141] Translating part of old Constraint.re into this version. --- src/haz3lcore/dynamics/Constraint.re | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/haz3lcore/dynamics/Constraint.re diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re new file mode 100644 index 0000000000..c94c805f29 --- /dev/null +++ b/src/haz3lcore/dynamics/Constraint.re @@ -0,0 +1,41 @@ +open Sexplib.Std; + +[@deriving sexp] +type t = + | Truth + | Falsity + | Hole + | Int(int) + | NotInt(int) + | Float(float) + | NotFloat(float) + | String(string) + | NotString(string) + | And(t, t) + | Or(t, t) + | InjL(t) + | InjR(t) + | List(list(t)); + +// How to replace this function? +let rec constrains = (c: t, ty: HTyp.t): bool => + switch (c, ty) { + // switch (c, HTyp.head_normalize(InitialContext.ctx, ty)) { + | (Truth, _) + | (Falsity, _) + | (Hole, _) => true + | (Int(_) | NotInt(_), Int) => true + | (Int(_) | NotInt(_), _) => false + | (Float(_) | NotFloat(_), Float) => true + | (Float(_) | NotFloat(_), _) => false + | (String(_) | NotString(_), String) => true + | (String(_) | NotString(_), _) => false + | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) + | (Or(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) + | (InjL(c1), Sum(ty1, _)) => constrains(c1, ty1) + | (InjL(_), _) => false + | (InjR(c2), Sum(_, ty2)) => constrains(c2, ty2) + | (InjR(_), _) => false + | (List(c), ty) => + List.fold_left((last, x) => last && constrains(x, ty), true, c) + }; From d714115d4acdb00c7071dc151cb1dfc0221e8537 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Tue, 1 Aug 2023 21:16:36 +0800 Subject: [PATCH 004/141] Rebase the project on `adt_defs_after` instead of `dev`. --- src/haz3lcore/Measured.re | 14 +- src/haz3lcore/dynamics/Builtins.re | 129 +- src/haz3lcore/dynamics/Builtins.rei | 11 + src/haz3lcore/dynamics/DH.re | 26 +- src/haz3lcore/dynamics/DHPat.re | 8 +- .../dynamics/{elaborator.re => Elaborator.re} | 304 +- src/haz3lcore/dynamics/Evaluator.re | 297 +- src/haz3lcore/dynamics/EvaluatorPost.re | 25 +- src/haz3lcore/dynamics/HTyp.re | 190 - src/haz3lcore/dynamics/HTyp.rei | 39 - .../dynamics/InvalidOperationError.re | 4 + .../dynamics/InvalidOperationError.rei | 2 + src/haz3lcore/dynamics/ListErrStatus.re | 6 - src/haz3lcore/dynamics/Substitution.re | 9 +- src/haz3lcore/lang/Form.re | 46 +- src/haz3lcore/lang/Sort.re | 14 +- src/haz3lcore/statics/BuiltinADTs.re | 97 - src/haz3lcore/statics/CoCtx.re | 61 + src/haz3lcore/statics/Constructor.re | 6 + src/haz3lcore/statics/ConstructorMap.re | 101 + src/haz3lcore/statics/Ctx.re | 109 +- src/haz3lcore/statics/Info.re | 480 ++ src/haz3lcore/statics/Kind.re | 4 +- src/haz3lcore/statics/MakeTerm.re | 168 +- src/haz3lcore/statics/Mode.re | 126 + src/haz3lcore/statics/Self.re | 90 + src/haz3lcore/statics/Statics.re | 927 +-- src/haz3lcore/statics/Term.re | 292 +- src/haz3lcore/statics/TermBase.re | 156 +- src/haz3lcore/statics/Typ.re | 247 +- src/haz3lcore/statics/TypBase.re | 606 ++ src/haz3lcore/statics/TypVar.re | 6 + src/haz3lcore/{dynamics => statics}/Var.re | 0 src/haz3lcore/tiles/Id.re | 67 + src/haz3lcore/tiles/Segment.re | 21 + src/haz3lcore/tiles/Skel.re | 7 +- src/haz3lcore/zipper/Editor.re | 4 +- src/haz3lcore/zipper/EditorUtil.re | 5 +- src/haz3lcore/zipper/action/Perform.re | 5 +- .../{SchoolExercise.re => Exercise.re} | 21 +- src/haz3lschool/GradePrelude.re | 4 +- src/haz3lschool/Gradescope.re | 10 +- src/haz3lschool/Grading.re | 4 +- src/haz3lweb/DebugAction.re | 8 +- src/haz3lweb/Editors.re | 115 +- .../{SchoolExercise.re => Exercise.re} | 2 +- src/haz3lweb/ExerciseSettings.re | 2 + ...tings_base.re => ExerciseSettings_base.re} | 2 +- src/haz3lweb/ExerciseSettings_instructor.re | 2 + src/haz3lweb/ExerciseSettings_student.re | 2 + src/haz3lweb/Export.re | 35 +- src/haz3lweb/Grading.re | 2 +- src/haz3lweb/Init.ml | 7336 +++++++++++++++++ src/haz3lweb/Keyboard.re | 28 +- src/haz3lweb/LangDocMessages.re | 257 +- src/haz3lweb/LanguageRefSlide.ml | 1069 --- src/haz3lweb/Log.re | 10 +- src/haz3lweb/Main.re | 4 +- src/haz3lweb/Model.re | 59 +- src/haz3lweb/ModelSettings.re | 33 +- src/haz3lweb/PersistentData.re | 14 + src/haz3lweb/School.re | 11 - src/haz3lweb/SchoolSettings.re | 2 - src/haz3lweb/SchoolSettings_instructor.re | 2 - src/haz3lweb/SchoolSettings_student.re | 2 - src/haz3lweb/ScratchSlidesInit.re | 25 - src/haz3lweb/{LocalStorage.re => Store.re} | 140 +- src/haz3lweb/Update.re | 367 +- src/haz3lweb/UpdateAction.re | 10 +- src/haz3lweb/exercises/BlankTemplate.ml | 2 +- src/haz3lweb/exercises/Ex_OddlyRecursive.ml | 2 +- .../exercises/Ex_RecursiveFibonacci.ml | 2 +- src/haz3lweb/view/BackpackView.re | 2 +- src/haz3lweb/view/Cell.re | 4 +- src/haz3lweb/view/CtxInspector.re | 102 +- src/haz3lweb/view/CursorInspector.re | 451 +- src/haz3lweb/view/DebugMode.re | 2 +- src/haz3lweb/view/Deco.re | 4 +- src/haz3lweb/view/EditorModeView.re | 83 + .../view/{SchoolMode.re => ExerciseMode.re} | 73 +- src/haz3lweb/view/Icons.re | 16 + src/haz3lweb/view/Kind.re | 16 +- src/haz3lweb/view/LangDoc.re | 147 +- src/haz3lweb/view/Page.re | 337 +- src/haz3lweb/view/ScratchMode.re | 50 +- src/haz3lweb/view/Type.re | 44 +- src/haz3lweb/view/dec/PieceDec.re | 22 +- src/haz3lweb/view/dhcode/DHCode.re | 36 +- src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 25 +- src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re | 12 +- src/haz3lweb/view/dhcode/layout/DHDoc_Util.re | 114 + .../view/dhcode/layout/DHDoc_common.re | 37 +- .../view/dhcode/layout/DHDoc_common.rei | 7 +- src/haz3lweb/view/dhcode/layout/HTypDoc.re | 36 +- src/haz3lweb/www/index.html | 12 +- src/haz3lweb/www/style.css | 936 ++- src/util/ListUtil.re | 6 + 97 files changed, 12360 insertions(+), 4507 deletions(-) rename src/haz3lcore/dynamics/{elaborator.re => Elaborator.re} (57%) delete mode 100644 src/haz3lcore/dynamics/HTyp.re delete mode 100644 src/haz3lcore/dynamics/HTyp.rei delete mode 100644 src/haz3lcore/dynamics/ListErrStatus.re delete mode 100644 src/haz3lcore/statics/BuiltinADTs.re create mode 100644 src/haz3lcore/statics/CoCtx.re create mode 100644 src/haz3lcore/statics/Constructor.re create mode 100644 src/haz3lcore/statics/ConstructorMap.re create mode 100644 src/haz3lcore/statics/Info.re create mode 100644 src/haz3lcore/statics/Mode.re create mode 100644 src/haz3lcore/statics/Self.re create mode 100644 src/haz3lcore/statics/TypBase.re create mode 100644 src/haz3lcore/statics/TypVar.re rename src/haz3lcore/{dynamics => statics}/Var.re (100%) rename src/haz3lschool/{SchoolExercise.re => Exercise.re} (98%) rename src/haz3lweb/{SchoolExercise.re => Exercise.re} (80%) create mode 100644 src/haz3lweb/ExerciseSettings.re rename src/haz3lweb/{SchoolSettings_base.re => ExerciseSettings_base.re} (72%) create mode 100644 src/haz3lweb/ExerciseSettings_instructor.re create mode 100644 src/haz3lweb/ExerciseSettings_student.re create mode 100644 src/haz3lweb/Init.ml delete mode 100644 src/haz3lweb/LanguageRefSlide.ml create mode 100644 src/haz3lweb/PersistentData.re delete mode 100644 src/haz3lweb/School.re delete mode 100644 src/haz3lweb/SchoolSettings.re delete mode 100644 src/haz3lweb/SchoolSettings_instructor.re delete mode 100644 src/haz3lweb/SchoolSettings_student.re delete mode 100644 src/haz3lweb/ScratchSlidesInit.re rename src/haz3lweb/{LocalStorage.re => Store.re} (65%) create mode 100644 src/haz3lweb/view/EditorModeView.re rename src/haz3lweb/view/{SchoolMode.re => ExerciseMode.re} (88%) create mode 100644 src/haz3lweb/view/dhcode/layout/DHDoc_Util.re diff --git a/src/haz3lcore/Measured.re b/src/haz3lcore/Measured.re index 77f7697401..68ac8a8ace 100644 --- a/src/haz3lcore/Measured.re +++ b/src/haz3lcore/Measured.re @@ -183,8 +183,8 @@ let find_g = (g: Grout.t, map): measurement => Id.Map.find(g.id, map.grout); // returns the measurement spanning the whole tile let find_t = (t: Tile.t, map): measurement => { let shards = Id.Map.find(t.id, map.tiles); - let first = List.assoc(Tile.l_shard(t), shards); - let last = List.assoc(Tile.r_shard(t), shards); + let first = ListUtil.assoc_err(Tile.l_shard(t), shards, "find_t"); + let last = ListUtil.assoc_err(Tile.r_shard(t), shards, "find_t"); {origin: first.origin, last: last.last}; }; // let find_a = ({shards: (l, r), _} as a: Ancestor.t, map) => @@ -206,8 +206,14 @@ let find_by_id = (id: Id.t, map: t): option(measurement) => { | None => switch (Id.Map.find_opt(id, map.tiles)) { | Some(shards) => - let first = List.assoc(List.hd(shards) |> fst, shards); - let last = List.assoc(ListUtil.last(shards) |> fst, shards); + let first = + ListUtil.assoc_err(List.hd(shards) |> fst, shards, "find_by_id"); + let last = + ListUtil.assoc_err( + ListUtil.last(shards) |> fst, + shards, + "find_by_id", + ); Some({origin: first.origin, last: last.last}); | None => Printf.printf("Measured.WARNING: id %d not found", id); diff --git a/src/haz3lcore/dynamics/Builtins.re b/src/haz3lcore/dynamics/Builtins.re index 5ee5f48796..3a8ed5ee85 100644 --- a/src/haz3lcore/dynamics/Builtins.re +++ b/src/haz3lcore/dynamics/Builtins.re @@ -34,6 +34,57 @@ module Pervasives = { open EvaluatorMonad; open EvaluatorResult; + /* is_finite implementation. */ + let is_finite = (name, r1) => + switch (r1) { + | BoxedValue(FloatLit(f)) => + let b = Float.is_finite(f); + BoxedValue(BoolLit(b)) |> return; + | BoxedValue(d1) => + raise(EvaluatorError.Exception(InvalidBoxedFloatLit(d1))) + | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return + }; + + /* is_infinite implementation. */ + let is_infinite = (name, r1) => + switch (r1) { + | BoxedValue(FloatLit(f)) => + let b = Float.is_infinite(f); + BoxedValue(BoolLit(b)) |> return; + | BoxedValue(d1) => + raise(EvaluatorError.Exception(InvalidBoxedFloatLit(d1))) + | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return + }; + + /* is_NaN implementation. */ + let is_nan = (name, r1) => + switch (r1) { + | BoxedValue(FloatLit(f)) => + let b = Float.is_nan(f); + BoxedValue(BoolLit(b)) |> return; + | BoxedValue(d1) => + raise(EvaluatorError.Exception(InvalidBoxedFloatLit(d1))) + | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return + }; + + /* int_of_string implementation. */ + let int_of_string = (name, r1) => + switch (r1) { + | BoxedValue(StringLit(f) as d1) => + let i = int_of_string_opt(f); + switch (i) { + | Some(x) => BoxedValue(IntLit(x)) |> return + | None => + Indet( + InvalidOperation(ApBuiltin(name, [d1]), InvalidIntOfString), + ) + |> return + }; + | BoxedValue(d1) => + raise(EvaluatorError.Exception(InvalidBoxedStringLit(d1))) + | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return + }; + /* int_of_float implementation. */ let int_of_float = (name, r1) => switch (r1) { @@ -41,7 +92,7 @@ module Pervasives = { let i = int_of_float(f); BoxedValue(IntLit(i)) |> return; | BoxedValue(d1) => - raise(EvaluatorError.Exception(InvalidBoxedIntLit(d1))) + raise(EvaluatorError.Exception(InvalidBoxedFloatLit(d1))) | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return }; @@ -52,7 +103,47 @@ module Pervasives = { let f = float_of_int(i); BoxedValue(FloatLit(f)) |> return; | BoxedValue(d1) => - raise(EvaluatorError.Exception(InvalidBoxedFloatLit(d1))) + raise(EvaluatorError.Exception(InvalidBoxedIntLit(d1))) + | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return + }; + + /* float_of_string implementation. */ + let float_of_string = (name, r1) => + switch (r1) { + | BoxedValue(StringLit(s) as d1) => + let f = float_of_string_opt(s); + switch (f) { + | Some(x) => BoxedValue(FloatLit(x)) |> return + | None => + Indet( + InvalidOperation(ApBuiltin(name, [d1]), InvalidFloatOfString), + ) + |> return + }; + | BoxedValue(d1) => + raise(EvaluatorError.Exception(InvalidBoxedStringLit(d1))) + | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return + }; + + /* string_of_int implementation. */ + let string_of_int = (name, r1) => + switch (r1) { + | BoxedValue(IntLit(i)) => + let s = string_of_int(i); + BoxedValue(StringLit(s)) |> return; + | BoxedValue(d1) => + raise(EvaluatorError.Exception(InvalidBoxedIntLit(d1))) + | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return + }; + + /* string_of_float implementation. */ + let string_of_float = (name, r1) => + switch (r1) { + | BoxedValue(FloatLit(f)) => + let s = string_of_float(f); + BoxedValue(StringLit(s)) |> return; + | BoxedValue(d1) => + raise(EvaluatorError.Exception(InvalidBoxedIntLit(d1))) | Indet(d1) => Indet(ApBuiltin(name, [d1])) |> return }; @@ -73,20 +164,54 @@ module Pervasives = { /* PI implementation. */ let pi = DHExp.FloatLit(Float.pi); + + /* Infinity-float implementation. */ + let infinity = DHExp.FloatLit(Float.infinity); + let neg_infinity = DHExp.FloatLit(Float.neg_infinity); + + /* NaN float implementation. */ + let nan = DHExp.FloatLit(Float.nan); }; let pi = name => Builtin.mk_zero(name, Float, Impls.pi); + let infinity = name => Builtin.mk_zero(name, Float, Impls.infinity); + let neg_infinity = name => Builtin.mk_zero(name, Float, Impls.neg_infinity); + let nan = name => Builtin.mk_zero(name, Float, Impls.nan); + let is_finite = name => + Builtin.mk_one(name, Arrow(Float, Bool), Impls.is_finite); + let is_infinite = name => + Builtin.mk_one(name, Arrow(Float, Bool), Impls.is_infinite); + let is_nan = name => + Builtin.mk_one(name, Arrow(Float, Bool), Impls.is_nan); let int_of_float = name => Builtin.mk_one(name, Arrow(Float, Int), Impls.int_of_float); + let int_of_string = name => + Builtin.mk_one(name, Arrow(String, Int), Impls.int_of_string); let float_of_int = name => Builtin.mk_one(name, Arrow(Int, Float), Impls.float_of_int); + let float_of_string = name => + Builtin.mk_one(name, Arrow(String, Float), Impls.float_of_string); + let string_of_float = name => + Builtin.mk_one(name, Arrow(Float, String), Impls.string_of_float); + let string_of_int = name => + Builtin.mk_one(name, Arrow(Int, String), Impls.string_of_int); let modulo = name => Builtin.mk_one(name, Arrow(Prod([Int, Int]), Int), Impls.int_mod); let builtins = VarMap.empty |> using("pi", pi) + |> using("infinity", infinity) + |> using("neg_infinity", neg_infinity) + |> using("nan", nan) + |> using("is_finite", is_finite) + |> using("is_infinite", is_infinite) + |> using("is_nan", is_nan) |> using("int_of_float", int_of_float) + |> using("int_of_string", int_of_string) |> using("float_of_int", float_of_int) + |> using("float_of_string", float_of_string) + |> using("string_of_int", string_of_int) + |> using("string_of_float", string_of_float) |> using("mod", modulo); }; diff --git a/src/haz3lcore/dynamics/Builtins.rei b/src/haz3lcore/dynamics/Builtins.rei index 51c66c08e5..ecedb94373 100644 --- a/src/haz3lcore/dynamics/Builtins.rei +++ b/src/haz3lcore/dynamics/Builtins.rei @@ -25,9 +25,20 @@ let using: (Var.t, Var.t => Builtin.t, t) => t; */ module Pervasives: { let pi: Var.t => Builtin.t; + let infinity: Var.t => Builtin.t; + let neg_infinity: Var.t => Builtin.t; + let nan: Var.t => Builtin.t; + + let is_finite: Var.t => Builtin.t; + let is_infinite: Var.t => Builtin.t; + let is_nan: Var.t => Builtin.t; let int_of_float: Var.t => Builtin.t; + let int_of_string: Var.t => Builtin.t; let float_of_int: Var.t => Builtin.t; + let float_of_string: Var.t => Builtin.t; + let string_of_int: Var.t => Builtin.t; + let string_of_float: Var.t => Builtin.t; let modulo: Var.t => Builtin.t; let builtins: t; diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index ec00933ed3..883ebe051f 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -69,12 +69,11 @@ module rec DHExp: { | BinIntOp(BinIntOp.t, t, t) | BinFloatOp(BinFloatOp.t, t, t) | BinStringOp(BinStringOp.t, t, t) - | ListLit(MetaVar.t, MetaVarInst.t, ListErrStatus.t, Typ.t, list(t)) + | ListLit(MetaVar.t, MetaVarInst.t, Typ.t, list(t)) | Cons(t, t) | Tuple(list(t)) | Prj(t, int) - | Inj(Typ.t, InjSide.t, t) - | Tag(string) + | Constructor(string) | ConsistentCase(case) | Cast(t, Typ.t, Typ.t) | FailedCast(t, Typ.t, Typ.t) @@ -166,12 +165,11 @@ module rec DHExp: { | BinIntOp(BinIntOp.t, t, t) | BinFloatOp(BinFloatOp.t, t, t) | BinStringOp(BinStringOp.t, t, t) - | ListLit(MetaVar.t, MetaVarInst.t, ListErrStatus.t, Typ.t, list(t)) + | ListLit(MetaVar.t, MetaVarInst.t, Typ.t, list(t)) | Cons(t, t) | Tuple(list(t)) | Prj(t, int) - | Inj(Typ.t, InjSide.t, t) - | Tag(string) + | Constructor(string) | ConsistentCase(case) | Cast(t, Typ.t, Typ.t) | FailedCast(t, Typ.t, Typ.t) @@ -209,8 +207,7 @@ module rec DHExp: { | Cons(_, _) => "Cons" | Tuple(_) => "Tuple" | Prj(_) => "Prj" - | Inj(_, _, _) => "Inj" - | Tag(_) => "Tag" + | Constructor(_) => "Constructor" | ConsistentCase(_) => "ConsistentCase" | InconsistentBranches(_, _, _) => "InconsistentBranches" | Cast(_, _, _) => "Cast" @@ -239,12 +236,10 @@ module rec DHExp: { | Closure(ei, d) => Closure(ei, strip_casts(d)) | Cast(d, _, _) => strip_casts(d) | FailedCast(d, _, _) => strip_casts(d) - | Inj(ty, side, d) => Inj(ty, side, strip_casts(d)) | Tuple(ds) => Tuple(ds |> List.map(strip_casts)) | Prj(d, n) => Prj(strip_casts(d), n) | Cons(d1, d2) => Cons(strip_casts(d1), strip_casts(d2)) - | ListLit(a, b, c, d, ds) => - ListLit(a, b, c, d, List.map(strip_casts, ds)) + | ListLit(a, b, c, ds) => ListLit(a, b, c, List.map(strip_casts, ds)) | NonEmptyHole(err, u, i, d) => NonEmptyHole(err, u, i, strip_casts(d)) | Sequence(a, b) => Sequence(strip_casts(a), strip_casts(b)) | Let(dp, b, c) => Let(dp, strip_casts(b), strip_casts(c)) @@ -277,7 +272,7 @@ module rec DHExp: { | IntLit(_) as d | FloatLit(_) as d | StringLit(_) as d - | Tag(_) as d + | Constructor(_) as d | InvalidOperation(_) as d => d and strip_casts_rule = (Rule(a, d)) => Rule(a, strip_casts(d)); @@ -290,7 +285,7 @@ module rec DHExp: { | (BoolLit(_), _) | (IntLit(_), _) | (FloatLit(_), _) - | (Tag(_), _) => d1 == d2 + | (Constructor(_), _) => d1 == d2 | (StringLit(s1), StringLit(s2)) => String.equal(s1, s2) | (StringLit(_), _) => false @@ -312,7 +307,7 @@ module rec DHExp: { | (Prj(d1, n), Prj(d2, m)) => n == m && fast_equal(d1, d2) | (ApBuiltin(f1, args1), ApBuiltin(f2, args2)) => f1 == f2 && List.for_all2(fast_equal, args1, args2) - | (ListLit(_, _, _, _, ds1), ListLit(_, _, _, _, ds2)) => + | (ListLit(_, _, _, ds1), ListLit(_, _, _, ds2)) => List.for_all2(fast_equal, ds1, ds2) | (BinBoolOp(op1, d11, d21), BinBoolOp(op2, d12, d22)) => op1 == op2 && fast_equal(d11, d12) && fast_equal(d21, d22) @@ -322,8 +317,6 @@ module rec DHExp: { op1 == op2 && fast_equal(d11, d12) && fast_equal(d21, d22) | (BinStringOp(op1, d11, d21), BinStringOp(op2, d12, d22)) => op1 == op2 && fast_equal(d11, d12) && fast_equal(d21, d22) - | (Inj(ty1, side1, d1), Inj(ty2, side2, d2)) => - ty1 == ty2 && side1 == side2 && fast_equal(d1, d2) | (Cast(d1, ty11, ty21), Cast(d2, ty12, ty22)) | (FailedCast(d1, ty11, ty21), FailedCast(d2, ty12, ty22)) => fast_equal(d1, d2) && ty11 == ty12 && ty21 == ty22 @@ -347,7 +340,6 @@ module rec DHExp: { | (BinIntOp(_), _) | (BinFloatOp(_), _) | (BinStringOp(_), _) - | (Inj(_), _) | (Cast(_), _) | (FailedCast(_), _) | (InvalidOperation(_), _) diff --git a/src/haz3lcore/dynamics/DHPat.re b/src/haz3lcore/dynamics/DHPat.re index b2654aee0c..0cac9b9814 100644 --- a/src/haz3lcore/dynamics/DHPat.re +++ b/src/haz3lcore/dynamics/DHPat.re @@ -7,16 +7,16 @@ type t = | Wild | ExpandingKeyword(MetaVar.t, MetaVarInst.t, ExpandingKeyword.t) | InvalidText(MetaVar.t, MetaVarInst.t, string) + | BadConstructor(MetaVar.t, MetaVarInst.t, string) | Var(Var.t) | IntLit(int) | FloatLit(float) | BoolLit(bool) | StringLit(string) - | Inj(InjSide.t, t) | ListLit(Typ.t, list(t)) | Cons(t, t) | Tuple(list(t)) - | Tag(string) + | Constructor(string) | Ap(t, t); let mk_tuple: list(t) => t = @@ -34,14 +34,14 @@ let rec binds_var = (x: Var.t, dp: t): bool => | NonEmptyHole(_, _, _, _) | Wild | InvalidText(_) + | BadConstructor(_) | IntLit(_) | FloatLit(_) | BoolLit(_) | StringLit(_) - | Tag(_) + | Constructor(_) | ExpandingKeyword(_, _, _) => false | Var(y) => Var.eq(x, y) - | Inj(_, dp1) => binds_var(x, dp1) | Tuple(dps) => dps |> List.exists(binds_var(x)) | Cons(dp1, dp2) => binds_var(x, dp1) || binds_var(x, dp2) | ListLit(_, d_list) => diff --git a/src/haz3lcore/dynamics/elaborator.re b/src/haz3lcore/dynamics/Elaborator.re similarity index 57% rename from src/haz3lcore/dynamics/elaborator.re rename to src/haz3lcore/dynamics/Elaborator.re index c4027cfc8d..fc3cb3e772 100644 --- a/src/haz3lcore/dynamics/elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -43,7 +43,7 @@ let bool_op_of: Term.UExp.op_bin_bool => DHExp.BinBoolOp.t = | And => And | Or => Or; -let exp_binop_of: Term.UExp.op_bin => (HTyp.t, (_, _) => DHExp.t) = +let exp_binop_of: Term.UExp.op_bin => (Typ.t, (_, _) => DHExp.t) = fun | Int(op) => (Int, ((e1, e2) => BinIntOp(int_op_of(op), e1, e2))) | Float(op) => (Float, ((e1, e2) => BinFloatOp(float_op_of(op), e1, e2))) @@ -53,116 +53,124 @@ let exp_binop_of: Term.UExp.op_bin => (HTyp.t, (_, _) => DHExp.t) = ((e1, e2) => BinStringOp(string_op_of(op), e1, e2)), ); -/* Wrap: Handles cast insertion and non-empty-hole wrapping +let fixed_exp_typ = (m: Statics.Map.t, e: Term.UExp.t): option(Typ.t) => + switch (Id.Map.find_opt(Term.UExp.rep_id(e), m)) { + | Some(InfoExp({ty, _})) => Some(ty) + | _ => None + }; + +let fixed_pat_typ = (m: Statics.Map.t, p: Term.UPat.t): option(Typ.t) => + switch (Id.Map.find_opt(Term.UPat.rep_id(p), m)) { + | Some(InfoPat({ty, _})) => Some(ty) + | _ => None + }; + +let cast = (ctx: Ctx.t, mode: Mode.t, self_ty: Typ.t, d: DHExp.t) => + switch (mode) { + | Syn => d + | SynFun => + switch (self_ty) { + | Unknown(prov) => + DHExp.cast(d, Unknown(prov), Arrow(Unknown(prov), Unknown(prov))) + | Arrow(_) => d + | _ => failwith("Elaborator.wrap: SynFun non-arrow-type") + } + | Ana(ana_ty) => + let ana_ty = Typ.normalize(ctx, ana_ty); + /* Forms with special ana rules get cast from their appropriate Matched types */ + switch (d) { + | ListLit(_) + | Cons(_) => + switch (ana_ty) { + | Unknown(prov) => DHExp.cast(d, List(Unknown(prov)), Unknown(prov)) + | _ => d + } + | Fun(_) => + switch (ana_ty) { + //| Unknown(prov) => + // DHExp.cast(d, Arrow(Unknown(prov), Unknown(prov)), Unknown(prov)) + | ana_ty => + /* See regression tests in Examples/Dynamics */ + let (_, ana_out) = Typ.matched_arrow(ana_ty); + let (self_in, _) = Typ.matched_arrow(self_ty); + DHExp.cast(d, Arrow(self_in, ana_out), ana_ty); + } + | Tuple(ds) => + switch (ana_ty) { + | Unknown(prov) => + let us = List.init(List.length(ds), _ => Typ.Unknown(prov)); + DHExp.cast(d, Prod(us), Unknown(prov)); + | _ => d + } + | Ap(Constructor(_), _) + | Constructor(_) => + switch (ana_ty, self_ty) { + | (Unknown(prov), Rec(_, Sum(_))) + | (Unknown(prov), Sum(_)) => DHExp.cast(d, self_ty, Unknown(prov)) + | _ => d + } + /* Forms with special ana rules but no particular typing requirements */ + | ConsistentCase(_) + | InconsistentBranches(_) + | Sequence(_) + | Let(_) + | FixF(_) => d + /* Hole-like forms: Don't cast */ + | InvalidText(_) + | FreeVar(_) + | ExpandingKeyword(_) + | EmptyHole(_) + | NonEmptyHole(_) => d + /* DHExp-specific forms: Don't cast */ + | Cast(_) + | Closure(_) + | FailedCast(_) + | InvalidOperation(_) => d + /* Normal cases: wrap */ + | BoundVar(_) + | Ap(_) + | ApBuiltin(_) + | Prj(_) + | BoolLit(_) + | IntLit(_) + | FloatLit(_) + | StringLit(_) + | BinBoolOp(_) + | BinIntOp(_) + | BinFloatOp(_) + | BinStringOp(_) + | TestLit(_) => DHExp.cast(d, self_ty, ana_ty) + }; + }; + +/* Handles cast insertion and non-empty-hole wrapping for elaborated expressions */ -let wrap = (u, mode, self, d: DHExp.t): option(DHExp.t) => - switch (Statics.error_status(mode, self)) { +let wrap = (ctx: Ctx.t, u: Id.t, mode: Mode.t, self, d: DHExp.t): DHExp.t => + switch (Info.status_exp(ctx, mode, self)) { | NotInHole(_) => - switch (mode) { - | Syn => Some(d) - | SynFun => - /* Things in function position get cast to the matched arrow type */ - let ty_self = Typ.t_of_self(self); - switch (ty_self) { - | Unknown(prov) => - Some(DHExp.cast(d, ty_self, Arrow(Unknown(prov), Unknown(prov)))) - | Arrow(_) => Some(d) - | _ => failwith("Elaborator.wrap: SynFun non-arrow-type") + let self_ty = + switch (Self.typ_of_exp(ctx, self)) { + | Some(self_ty) => Typ.normalize(ctx, self_ty) + | None => Unknown(Internal) }; - | Ana(ana_ty) => - /* Forms with special ana rules get cast from their appropriate Matched types */ - switch (d) { - | ListLit(_) - | Cons(_) => - switch (ana_ty) { - | Unknown(prov) => - Some(DHExp.cast(d, List(Unknown(prov)), ana_ty)) - | _ => Some(d) - } - | Fun(_) => - switch (ana_ty) { - | Unknown(prov) => - Some(DHExp.cast(d, Arrow(Unknown(prov), Unknown(prov)), ana_ty)) - | _ => Some(d) - } - | Tuple(ds) => - switch (ana_ty) { - | Unknown(prov) => - let us = List.init(List.length(ds), _ => Typ.Unknown(prov)); - Some(DHExp.cast(d, Prod(us), ana_ty)); - | _ => Some(d) - } - | Inj(_) => - switch (ana_ty) { - | Unknown(prov) => - Some(DHExp.cast(d, Sum(Unknown(prov), Unknown(prov)), ana_ty)) - | _ => Some(d) - } - /* Forms with special ana rules but no particular typing requirements */ - | ConsistentCase(_) - | InconsistentBranches(_) - | Sequence(_) - | Let(_) - | FixF(_) => Some(d) - /* Hole-like forms: Don't cast */ - | InvalidText(_) - | FreeVar(_) - | ExpandingKeyword(_) - | EmptyHole(_) - | NonEmptyHole(_) => Some(d) - /* DHExp-specific forms: Don't cast */ - | Cast(_) - | Closure(_) - | FailedCast(_) - | InvalidOperation(_) => Some(d) - /* Normal cases: wrap */ - | BoundVar(_) - | Ap(_) - | ApBuiltin(_) - | Prj(_) - | Tag(_) - | BoolLit(_) - | IntLit(_) - | FloatLit(_) - | StringLit(_) - | BinBoolOp(_) - | BinIntOp(_) - | BinFloatOp(_) - | BinStringOp(_) - | TestLit(_) => Some(DHExp.cast(d, Typ.t_of_self(self), ana_ty)) - } - } - | InHole(_) => Some(NonEmptyHole(TypeInconsistent, u, 0, d)) + cast(ctx, mode, self_ty, d); + | InHole(_) => NonEmptyHole(TypeInconsistent, u, 0, d) }; -let rec dhexp_of_uexp = (m: Statics.map, uexp: Term.UExp.t): option(DHExp.t) => { - /* NOTE: Left out delta for now */ +let rec dhexp_of_uexp = + (m: Statics.Map.t, uexp: Term.UExp.t): option(DHExp.t) => { switch (Id.Map.find_opt(Term.UExp.rep_id(uexp), m)) { - | Some(InfoExp({mode, self, _})) => - let err_status = Statics.error_status(mode, self); + | Some(InfoExp({mode, self, ctx, _})) => + let err_status = Info.status_exp(ctx, mode, self); let id = Term.UExp.rep_id(uexp); /* NOTE: using term uids for hole ids */ - let* d: DHExp.t = + let+ d: DHExp.t = switch (uexp.term) { - | Invalid(_) /* NOTE: treating invalid as a hole for now */ + | Invalid(t) => Some(DHExp.InvalidText(id, 0, t)) | EmptyHole => Some(DHExp.EmptyHole(id, 0)) | MultiHole(_tms) => /* TODO: add a dhexp case and eval logic for multiholes. Make sure new dhexp form is properly considered Indet to avoid casting issues. */ - /*let+ ds = - tms - |> List.map( - fun - | Term.Exp(e) => dhexp_of_uexp(m, e) - | tm => Some(EmptyHole(Term.rep_id(tm), 0)), - ) - |> OptUtil.sequence; - switch (ds) { - | [] => DHExp.EmptyHole(id, 0) - | [hd, ...tl] => - // TODO: placeholder logic: sequence - tl |> List.fold_left((acc, d) => DHExp.Sequence(d, acc), hd) - };*/ Some(EmptyHole(id, 0)) | Triv => Some(Tuple([])) | Bool(b) => Some(BoolLit(b)) @@ -170,27 +178,18 @@ let rec dhexp_of_uexp = (m: Statics.map, uexp: Term.UExp.t): option(DHExp.t) => | Float(n) => Some(FloatLit(n)) | String(s) => Some(StringLit(s)) | ListLit(es) => - let+ ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; - let ty = Statics.exp_typ(m, uexp) |> Typ.matched_list; - //TODO: why is there an err status on below? - DHExp.ListLit(id, 0, StandardErrStatus(NotInHole), ty, ds); + let* ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; + let+ ty = fixed_exp_typ(m, uexp); + let ty = Typ.matched_list(ty); + DHExp.ListLit(id, 0, ty, ds); | Fun(p, body) => let* dp = dhpat_of_upat(m, p); - let+ d1 = dhexp_of_uexp(m, body); - DHExp.Fun(dp, Statics.pat_typ(m, p), d1, None); + let* d1 = dhexp_of_uexp(m, body); + let+ ty = fixed_pat_typ(m, p); + DHExp.Fun(dp, ty, d1, None); | Tuple(es) => - let+ ds = - List.fold_right( - (e, ds_opt) => { - let* ds = ds_opt; - let+ d = dhexp_of_uexp(m, e); - [d, ...ds]; - }, - es, - Some([]), - ); + let+ ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; DHExp.Tuple(ds); - | Tag(name) => Some(Tag(name)) | Cons(e1, e2) => let* dc1 = dhexp_of_uexp(m, e1); let+ dc2 = dhexp_of_uexp(m, e2); @@ -213,9 +212,15 @@ let rec dhexp_of_uexp = (m: Statics.map, uexp: Term.UExp.t): option(DHExp.t) => DHExp.Ap(TestLit(id), dtest); | Var(name) => switch (err_status) { - | InHole(Free(Variable)) => Some(FreeVar(id, 0, name)) + | InHole(FreeVariable(_)) => Some(FreeVar(id, 0, name)) | _ => Some(BoundVar(name)) } + | Constructor(name) => + switch (err_status) { + | InHole(Common(NoType(FreeConstructor(_)))) => + Some(FreeVar(id, 0, name)) + | _ => Some(Constructor(name)) + } | Let(p, def, body) => let add_name: (option(string), DHExp.t) => DHExp.t = ( name => @@ -225,15 +230,15 @@ let rec dhexp_of_uexp = (m: Statics.map, uexp: Term.UExp.t): option(DHExp.t) => ); let* dp = dhpat_of_upat(m, p); let* ddef = dhexp_of_uexp(m, def); - let+ dbody = dhexp_of_uexp(m, body); - let ty = Statics.pat_self_typ(m, p); + let* dbody = dhexp_of_uexp(m, body); + let+ ty_body = fixed_exp_typ(m, body); switch (Term.UPat.get_recursive_bindings(p)) { | None => /* not recursive */ DHExp.Let(dp, add_name(Term.UPat.get_var(p), ddef), dbody) | Some([f]) => /* simple recursion */ - Let(dp, FixF(f, ty, add_name(Some(f), ddef)), dbody) + Let(dp, FixF(f, ty_body, add_name(Some(f), ddef)), dbody) | Some(fs) => /* mutual recursion */ let ddef = @@ -255,7 +260,7 @@ let rec dhexp_of_uexp = (m: Statics.map, uexp: Term.UExp.t): option(DHExp.t) => }, (0, ddef), ); - Let(dp, FixF(self_id, ty, substituted_def), dbody); + Let(dp, FixF(self_id, ty_body, substituted_def), dbody); }; | Ap(fn, arg) => let* c_fn = dhexp_of_uexp(m, fn); @@ -269,7 +274,7 @@ let rec dhexp_of_uexp = (m: Statics.map, uexp: Term.UExp.t): option(DHExp.t) => DHExp.[Rule(BoolLit(true), d1), Rule(BoolLit(false), d2)]; let d = DHExp.Case(d_scrut, d_rules, 0); switch (err_status) { - | InHole(SynInconsistentBranches(_)) => + | InHole(Common(Inconsistent(Internal(_)))) => DHExp.InconsistentBranches(id, 0, d) | _ => ConsistentCase(d) }; @@ -287,20 +292,21 @@ let rec dhexp_of_uexp = (m: Statics.map, uexp: Term.UExp.t): option(DHExp.t) => |> OptUtil.sequence; let d = DHExp.Case(d_scrut, d_rules, 0); switch (err_status) { - | InHole(SynInconsistentBranches(_)) => + | InHole(Common(Inconsistent(Internal(_)))) => DHExp.InconsistentBranches(id, 0, d) | _ => ConsistentCase(d) }; + | TyAlias(_, _, e) => dhexp_of_uexp(m, e) }; - wrap(id, mode, self, d); - | Some(InfoPat(_) | InfoTyp(_) | InfoRul(_) | Invalid(_)) + wrap(ctx, id, mode, self, d); + | Some(InfoPat(_) | InfoTyp(_) | InfoTPat(_)) | None => None }; } -and dhpat_of_upat = (m: Statics.map, upat: Term.UPat.t): option(DHPat.t) => { +and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.t) => { switch (Id.Map.find_opt(Term.UPat.rep_id(upat), m)) { - | Some(InfoPat({mode, self, _})) => - let err_status = Statics.error_status(mode, self); + | Some(InfoPat({mode, self, ctx, _})) => + let err_status = Info.status_pat(ctx, mode, self); let maybe_reason: option(ErrStatus.HoleReason.t) = switch (err_status) { | NotInHole(_) => None @@ -313,7 +319,7 @@ and dhpat_of_upat = (m: Statics.map, upat: Term.UPat.t): option(DHPat.t) => { | Some(reason) => Some(NonEmptyHole(reason, u, 0, d)) }; switch (upat.term) { - | Invalid(_) /* NOTE: treating invalid as a hole for now */ + | Invalid(t) => Some(DHPat.InvalidText(u, 0, t)) | EmptyHole => Some(EmptyHole(u, 0)) | MultiHole(_) => // TODO: dhexp, eval for multiholes @@ -326,30 +332,21 @@ and dhpat_of_upat = (m: Statics.map, upat: Term.UPat.t): option(DHPat.t) => { | Triv => wrap(Tuple([])) | ListLit(ps) => let* ds = ps |> List.map(dhpat_of_upat(m)) |> OptUtil.sequence; - let ty = Statics.pat_typ(m, upat) |> Typ.matched_list; - wrap(ListLit(ty, ds)); - | Tag(name) => wrap(Tag(name)) + let* ty = fixed_pat_typ(m, upat); + wrap(ListLit(Typ.matched_list(ty), ds)); + | Constructor(name) => + switch (err_status) { + | InHole(Common(NoType(FreeConstructor(_)))) => + Some(BadConstructor(u, 0, name)) + | _ => wrap(Constructor(name)) + } | Cons(hd, tl) => let* d_hd = dhpat_of_upat(m, hd); let* d_tl = dhpat_of_upat(m, tl); wrap(Cons(d_hd, d_tl)); | Tuple(ps) => - let dps = - List.fold_right( - (p, dps_opt) => { - switch (dps_opt) { - | None => None - | Some(dps) => - switch (dhpat_of_upat(m, p)) { - | None => None - | Some(dp) => Some([dp, ...dps]) - } - } - }, - ps, - Some([]), - ); - dps |> Option.map(ds => DHPat.Tuple(ds)); + let* ds = ps |> List.map(dhpat_of_upat(m)) |> OptUtil.sequence; + wrap(DHPat.Tuple(ds)); | Var(name) => Some(Var(name)) | Parens(p) => dhpat_of_upat(m, p) | Ap(p1, p2) => @@ -360,7 +357,7 @@ and dhpat_of_upat = (m: Statics.map, upat: Term.UPat.t): option(DHPat.t) => { let* dp = dhpat_of_upat(m, p); wrap(dp); }; - | Some(InfoExp(_) | InfoTyp(_) | InfoRul(_) | Invalid(_)) + | Some(InfoExp(_) | InfoTyp(_) | InfoTPat(_)) | None => None }; }; @@ -372,10 +369,17 @@ let uexp_elab_wrap_builtins = (d: DHExp.t): DHExp.t => Builtins.forms(Builtins.Pervasives.builtins), ); -let uexp_elab = (m: Statics.map, uexp: Term.UExp.t): ElaborationResult.t => +//let dhexp_of_uexp = Core.Memo.general(~cache_size_bound=1000, dhexp_of_uexp); + +let uexp_elab = (m: Statics.Map.t, uexp: Term.UExp.t): ElaborationResult.t => switch (dhexp_of_uexp(m, uexp)) { | None => DoesNotElaborate | Some(d) => let d = uexp_elab_wrap_builtins(d); - Elaborates(d, Typ.Unknown(Internal), Delta.empty); //TODO: get type from ci + let ty = + switch (fixed_exp_typ(m, uexp)) { + | Some(ty) => ty + | None => Typ.Unknown(Internal) + }; + Elaborates(d, ty, Delta.empty); }; diff --git a/src/haz3lcore/dynamics/Evaluator.re b/src/haz3lcore/dynamics/Evaluator.re index 58d567e942..647740eeb3 100644 --- a/src/haz3lcore/dynamics/Evaluator.re +++ b/src/haz3lcore/dynamics/Evaluator.re @@ -19,15 +19,24 @@ type match_result = | DoesNotMatch | IndetMatch; +let const_unknown: 'a => Typ.t = _ => Unknown(Internal); + let grounded_Arrow = NotGroundOrHole(Arrow(Unknown(Internal), Unknown(Internal))); -let grounded_Sum = - NotGroundOrHole(Sum(Unknown(Internal), Unknown(Internal))); let grounded_Prod = length => NotGroundOrHole(Prod(ListUtil.replicate(length, Typ.Unknown(Internal)))); +let grounded_Sum = (sm: Typ.sum_map): ground_cases => { + let sm' = sm |> ConstructorMap.map(Option.map(const_unknown)); + NotGroundOrHole(Sum(sm')); +}; let grounded_List = NotGroundOrHole(List(Unknown(Internal))); -let ground_cases_of = (ty: Typ.t): ground_cases => +let rec ground_cases_of = (ty: Typ.t): ground_cases => { + let is_ground_arg: option(Typ.t) => bool = + fun + | None + | Some(Typ.Unknown(_)) => true + | Some(ty) => ground_cases_of(ty) == Ground; switch (ty) { | Unknown(_) => Hole | Bool @@ -35,8 +44,8 @@ let ground_cases_of = (ty: Typ.t): ground_cases => | Float | String | Var(_) + | Rec(_) | Arrow(Unknown(_), Unknown(_)) - | Sum(Unknown(_), Unknown(_)) | List(Unknown(_)) => Ground | Prod(tys) => if (List.for_all( @@ -49,10 +58,33 @@ let ground_cases_of = (ty: Typ.t): ground_cases => } else { tys |> List.length |> grounded_Prod; } + | Sum(sm) => + sm |> ConstructorMap.is_ground(is_ground_arg) ? Ground : grounded_Sum(sm) | Arrow(_, _) => grounded_Arrow - | Sum(_, _) => grounded_Sum | List(_) => grounded_List }; +}; + +let cast_sum_maps = + (sm1: Typ.sum_map, sm2: Typ.sum_map) + : option(ConstructorMap.t((Typ.t, Typ.t))) => { + let (ctrs1, tys1) = sm1 |> ConstructorMap.bindings |> List.split; + let (ctrs2, tys2) = sm2 |> ConstructorMap.bindings |> List.split; + if (ctrs1 == ctrs2) { + let tys1 = tys1 |> List.filter(Option.is_some) |> List.map(Option.get); + let tys2 = tys2 |> List.filter(Option.is_some) |> List.map(Option.get); + if (List.length(tys1) == List.length(tys2)) { + Some( + List.(combine(tys1, tys2) |> combine(ctrs1)) + |> ConstructorMap.of_list, + ); + } else { + None; + }; + } else { + None; + }; +}; let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => switch (dp, d) { @@ -62,6 +94,7 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => | (Wild, _) => Matches(Environment.empty) | (ExpandingKeyword(_), _) => DoesNotMatch | (InvalidText(_), _) => IndetMatch + | (BadConstructor(_), _) => IndetMatch | (Var(x), _) => let env = Environment.extend(Environment.empty, (x, d)); Matches(env); @@ -118,23 +151,53 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => | (StringLit(_), Cast(d, String, Unknown(_))) => matches(dp, d) | (StringLit(_), Cast(d, Unknown(_), String)) => matches(dp, d) | (StringLit(_), _) => DoesNotMatch - | (Tag(n1), Tag(n2)) => - if (n1 == n2) { - Matches(Environment.empty); - } else { - DoesNotMatch; + + | (Ap(dp1, dp2), Ap(d1, d2)) => + switch (matches(dp1, d1)) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => + switch (matches(dp2, d2)) { + | DoesNotMatch => DoesNotMatch + | IndetMatch + | Matches(_) => IndetMatch + } + | Matches(env1) => + switch (matches(dp2, d2)) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env2) => Matches(Environment.union(env1, env2)) + } } - | (Tag(_), Cast(d, _, Unknown(_))) => matches(dp, d) - | (Tag(_), Cast(d, Unknown(_), _)) => matches(dp, d) - | (Tag(_), _) => DoesNotMatch - | (Inj(side1, dp), Inj(_, side2, d)) => - switch (side1, side2) { - | (L, L) - | (R, R) => matches(dp, d) - | _ => DoesNotMatch + | ( + Ap(Constructor(ctr), dp_opt), + Cast(d, Sum(sm1) | Rec(_, Sum(sm1)), Sum(sm2) | Rec(_, Sum(sm2))), + ) => + switch (cast_sum_maps(sm1, sm2)) { + | Some(castmap) => matches_cast_Sum(ctr, Some(dp_opt), d, [castmap]) + | None => DoesNotMatch } - | (Inj(side, dp), Cast(_)) => matches_cast_Inj(side, dp, d, []) - | (Inj(_, _), _) => DoesNotMatch + + | (Ap(_, _), Cast(d, Sum(_) | Rec(_, Sum(_)), Unknown(_))) + | (Ap(_, _), Cast(d, Unknown(_), Sum(_) | Rec(_, Sum(_)))) => + matches(dp, d) + | (Ap(_, _), _) => DoesNotMatch + + | (Constructor(ctr), Constructor(ctr')) => + ctr == ctr' ? Matches(Environment.empty) : DoesNotMatch + | ( + Constructor(ctr), + Cast(d, Sum(sm1) | Rec(_, Sum(sm1)), Sum(sm2) | Rec(_, Sum(sm2))), + ) => + switch (cast_sum_maps(sm1, sm2)) { + | Some(castmap) => matches_cast_Sum(ctr, None, d, [castmap]) + | None => DoesNotMatch + } + | (Constructor(_), Cast(d, Sum(_) | Rec(_, Sum(_)), Unknown(_))) => + matches(dp, d) + | (Constructor(_), Cast(d, Unknown(_), Sum(_) | Rec(_, Sum(_)))) => + matches(dp, d) + | (Constructor(_), _) => DoesNotMatch + | (Tuple(dps), Tuple(ds)) => if (List.length(dps) != List.length(ds)) { DoesNotMatch; @@ -156,22 +219,6 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => ds, ); } - | (Ap(dp1, dp2), Ap(d1, d2)) => - switch (matches(dp1, d1)) { - | DoesNotMatch => DoesNotMatch - | IndetMatch => - switch (matches(dp2, d2)) { - | DoesNotMatch => DoesNotMatch - | IndetMatch - | Matches(_) => IndetMatch - } - | Matches(env1) => - switch (matches(dp2, d2)) { - | DoesNotMatch => DoesNotMatch - | IndetMatch => IndetMatch - | Matches(env2) => Matches(Environment.union(env1, env2)) - } - } | (Tuple(dps), Cast(d, Prod(tys), Prod(tys'))) => assert(List.length(tys) == List.length(tys')); matches_cast_Tuple( @@ -185,10 +232,7 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => d, List.map( p => [p], - List.combine( - tys, - List.init(List.length(tys), _ => Typ.Unknown(Internal)), - ), + List.combine(tys, List.init(List.length(tys), const_unknown)), ), ) | (Tuple(dps), Cast(d, Unknown(_), Prod(tys'))) => @@ -197,10 +241,7 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => d, List.map( p => [p], - List.combine( - List.init(List.length(tys'), _ => Typ.Unknown(Internal)), - tys', - ), + List.combine(List.init(List.length(tys'), const_unknown), tys'), ), ) | (Tuple(_), Cast(_)) => DoesNotMatch @@ -216,84 +257,73 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => | (Cons(_, _), ListLit(_)) | (ListLit(_), ListLit(_)) => matches_cast_Cons(dp, d, []) | (Cons(_) | ListLit(_), _) => DoesNotMatch - | (Ap(_, _), _) => DoesNotMatch } -and matches_cast_Inj = +and matches_cast_Sum = ( - side: InjSide.t, - dp: DHPat.t, + ctr: string, + dp: option(DHPat.t), d: DHExp.t, - casts: list((Typ.t, Typ.t, Typ.t, Typ.t)), + castmaps: list(ConstructorMap.t((Typ.t, Typ.t))), ) : match_result => switch (d) { - | Inj(_, side', d') => - switch (side, side') { - | (L, L) - | (R, R) => - let side_casts = - List.map( - (c: (Typ.t, Typ.t, Typ.t, Typ.t)) => { - let (tyL1, tyR1, tyL2, tyR2) = c; - switch (side) { - | L => (tyL1, tyL2) - | R => (tyR1, tyR2) - }; - }, - casts, - ); - matches(dp, DHExp.apply_casts(d', side_casts)); + | Constructor(ctr') => + switch ( + dp, + castmaps |> List.map(ConstructorMap.find_opt(ctr')) |> OptUtil.sequence, + ) { + | (None, Some(_)) => + ctr == ctr' ? Matches(Environment.empty) : DoesNotMatch | _ => DoesNotMatch } - | Cast(d', Sum(tyL1, tyR1), Sum(tyL2, tyR2)) => - matches_cast_Inj(side, dp, d', [(tyL1, tyR1, tyL2, tyR2), ...casts]) - | Cast(d', Sum(tyL1, tyR1), Unknown(_)) => - matches_cast_Inj( - side, - dp, - d', - [(tyL1, tyR1, Unknown(Internal), Unknown(Internal))], - ) - | Cast(d', Unknown(_), Sum(tyL2, tyR2)) => - matches_cast_Inj( - side, + | Ap(Constructor(ctr'), d') => + switch ( dp, - d', - [(Unknown(Internal), Unknown(Internal), tyL2, tyR2)], - ) - | Cast(_, _, _) => DoesNotMatch - | BoundVar(_) => DoesNotMatch - | FreeVar(_) => IndetMatch - | InvalidText(_) => IndetMatch - | ExpandingKeyword(_) => IndetMatch - | Let(_, _, _) => IndetMatch - | FixF(_, _, _) => DoesNotMatch - | Fun(_, _, _, _) => DoesNotMatch - | Closure(_, Fun(_)) => DoesNotMatch - | Closure(_, _) => IndetMatch - | Ap(_, _) => IndetMatch - | ApBuiltin(_, _) => IndetMatch - | BinBoolOp(_, _, _) - | BinIntOp(_, _, _) - | BinFloatOp(_, _, _) - | BinStringOp(_, _, _) - | BoolLit(_) => DoesNotMatch - | IntLit(_) => DoesNotMatch - | Sequence(_) - | TestLit(_) => DoesNotMatch - | FloatLit(_) => DoesNotMatch - | StringLit(_) => DoesNotMatch - | ListLit(_, _, _, _, _) => DoesNotMatch - | Cons(_, _) => DoesNotMatch - | Tuple(_) => DoesNotMatch - | Prj(_) => DoesNotMatch - | Tag(_) => DoesNotMatch - | ConsistentCase(_) - | InconsistentBranches(_) => IndetMatch - | EmptyHole(_) => IndetMatch - | NonEmptyHole(_) => IndetMatch - | FailedCast(_, _, _) => IndetMatch + castmaps |> List.map(ConstructorMap.find_opt(ctr')) |> OptUtil.sequence, + ) { + | (Some(dp), Some(side_casts)) => + matches(dp, DHExp.apply_casts(d', side_casts)) + | _ => DoesNotMatch + } + | Cast(d', Sum(sm1) | Rec(_, Sum(sm1)), Sum(sm2) | Rec(_, Sum(sm2))) => + switch (cast_sum_maps(sm1, sm2)) { + | Some(castmap) => matches_cast_Sum(ctr, dp, d', [castmap, ...castmaps]) + | None => DoesNotMatch + } + | Cast(d', Sum(_) | Rec(_, Sum(_)), Unknown(_)) + | Cast(d', Unknown(_), Sum(_) | Rec(_, Sum(_))) => + matches_cast_Sum(ctr, dp, d', castmaps) + | FreeVar(_) + | ExpandingKeyword(_) + | InvalidText(_) + | Let(_) + | Ap(_) + | ApBuiltin(_) + | BinBoolOp(_) + | BinIntOp(_) + | BinFloatOp(_) + | BinStringOp(_) + | InconsistentBranches(_) + | EmptyHole(_) + | NonEmptyHole(_) + | FailedCast(_, _, _) | InvalidOperation(_) => IndetMatch + | Cast(_) + | BoundVar(_) + | FixF(_) + | Fun(_) + | BoolLit(_) + | IntLit(_) + | FloatLit(_) + | StringLit(_) + | ListLit(_) + | Tuple(_) + | Prj(_) + | ConsistentCase(_) + | Sequence(_, _) + | Closure(_) + | TestLit(_) + | Cons(_) => DoesNotMatch } and matches_cast_Tuple = ( @@ -337,14 +367,14 @@ and matches_cast_Tuple = ); } | Cast(d', Prod(tys), Unknown(_)) => - let tys' = List.init(List.length(tys), _ => Typ.Unknown(Internal)); + let tys' = List.init(List.length(tys), const_unknown); matches_cast_Tuple( dps, d', List.map2(List.cons, List.combine(tys, tys'), elt_casts), ); | Cast(d', Unknown(_), Prod(tys')) => - let tys = List.init(List.length(tys'), _ => Typ.Unknown(Internal)); + let tys = List.init(List.length(tys'), const_unknown); matches_cast_Tuple( dps, d', @@ -372,11 +402,10 @@ and matches_cast_Tuple = | TestLit(_) => DoesNotMatch | FloatLit(_) => DoesNotMatch | StringLit(_) => DoesNotMatch - | Inj(_, _, _) => DoesNotMatch | ListLit(_) => DoesNotMatch | Cons(_, _) => DoesNotMatch | Prj(_) => DoesNotMatch - | Tag(_) => DoesNotMatch + | Constructor(_) => DoesNotMatch | ConsistentCase(_) | InconsistentBranches(_) => IndetMatch | EmptyHole(_) => IndetMatch @@ -387,12 +416,12 @@ and matches_cast_Tuple = and matches_cast_Cons = (dp: DHPat.t, d: DHExp.t, elt_casts: list((Typ.t, Typ.t))): match_result => switch (d) { - | ListLit(_, _, _, _, []) => + | ListLit(_, _, _, []) => switch (dp) { | ListLit(_, []) => Matches(Environment.empty) | _ => DoesNotMatch } - | ListLit(u, i, err, ty, [dhd, ...dtl] as ds) => + | ListLit(u, i, ty, [dhd, ...dtl] as ds) => switch (dp) { | Cons(dp1, dp2) => switch (matches(dp1, DHExp.apply_casts(dhd, elt_casts))) { @@ -407,7 +436,7 @@ and matches_cast_Cons = }, elt_casts, ); - let d2 = DHExp.ListLit(u, i, err, ty, dtl); + let d2 = DHExp.ListLit(u, i, ty, dtl); switch (matches(dp2, DHExp.apply_casts(d2, list_casts))) { | DoesNotMatch => DoesNotMatch | IndetMatch => IndetMatch @@ -508,10 +537,9 @@ and matches_cast_Cons = | TestLit(_) => DoesNotMatch | FloatLit(_) => DoesNotMatch | StringLit(_) => DoesNotMatch - | Inj(_, _, _) => DoesNotMatch | Tuple(_) => DoesNotMatch | Prj(_) => DoesNotMatch - | Tag(_) => DoesNotMatch + | Constructor(_) => DoesNotMatch | ConsistentCase(_) | InconsistentBranches(_) => IndetMatch | EmptyHole(_) => IndetMatch @@ -641,7 +669,7 @@ let rec evaluate: (ClosureEnvironment.t, DHExp.t) => m(EvaluatorResult.t) = let* r1 = evaluate(env, d1); switch (r1) { | BoxedValue(TestLit(id)) => evaluate_test(env, id, d2) - | BoxedValue(Tag(_)) => + | BoxedValue(Constructor(_)) => let* r2 = evaluate(env, d2); switch (r2) { | BoxedValue(d2) => BoxedValue(Ap(d1, d2)) |> return @@ -689,7 +717,7 @@ let rec evaluate: (ClosureEnvironment.t, DHExp.t) => m(EvaluatorResult.t) = | IntLit(_) | FloatLit(_) | StringLit(_) - | Tag(_) => BoxedValue(d) |> return + | Constructor(_) => BoxedValue(d) |> return | BinBoolOp(op, d1, d2) => let* r1 = evaluate(env, d1); @@ -809,13 +837,6 @@ let rec evaluate: (ClosureEnvironment.t, DHExp.t) => m(EvaluatorResult.t) = }; }; - | Inj(ty, side, d1) => - let* r1 = evaluate(env, d1); - switch (r1) { - | BoxedValue(d1') => BoxedValue(Inj(ty, side, d1')) |> return - | Indet(d1') => Indet(Inj(ty, side, d1')) |> return - }; - | Tuple(ds) => let+ lst = ds |> List.map(evaluate(env)) |> sequence; let (ds', indet) = @@ -892,8 +913,8 @@ let rec evaluate: (ClosureEnvironment.t, DHExp.t) => m(EvaluatorResult.t) = | (BoxedValue(d1), Indet(d2)) => Indet(Cons(d1, d2)) |> return | (BoxedValue(d1), BoxedValue(d2)) => switch (d2) { - | ListLit(u, i, err, ty, ds) => - BoxedValue(ListLit(u, i, err, ty, [d1, ...ds])) |> return + | ListLit(u, i, ty, ds) => + BoxedValue(ListLit(u, i, ty, [d1, ...ds])) |> return | Cons(_) | Cast(_, List(_), List(_)) => BoxedValue(Cons(d1, d2)) |> return | _ => @@ -902,7 +923,7 @@ let rec evaluate: (ClosureEnvironment.t, DHExp.t) => m(EvaluatorResult.t) = } }; - | ListLit(u, i, err, ty, lst) => + | ListLit(u, i, ty, lst) => let+ lst = lst |> List.map(evaluate(env)) |> sequence; let (lst, indet) = List.fold_right( @@ -914,7 +935,7 @@ let rec evaluate: (ClosureEnvironment.t, DHExp.t) => m(EvaluatorResult.t) = lst, ([], false), ); - let d = DHExp.ListLit(u, i, err, ty, lst); + let d = DHExp.ListLit(u, i, ty, lst); if (indet) { Indet(d); } else { @@ -1160,6 +1181,14 @@ and evaluate_test = let mk_op = (arg_d1, arg_d2) => DHExp.BinFloatOp(op, arg_d1, arg_d2); evaluate_test_eq(env, mk_op, arg_d1, arg_d2); + | Ap(fn, Tuple(args)) => + let* args_d: list(EvaluatorResult.t) = + args |> List.map(evaluate(env)) |> sequence; + let arg_show = + DHExp.Ap(fn, Tuple(List.map(EvaluatorResult.unbox, args_d))); + let* arg_result = evaluate(env, arg_show); + (arg_show, arg_result) |> return; + | Ap(Ap(arg_d1, arg_d2), arg_d3) => let* arg_d1 = evaluate(env, arg_d1); let* arg_d2 = evaluate(env, arg_d2); diff --git a/src/haz3lcore/dynamics/EvaluatorPost.re b/src/haz3lcore/dynamics/EvaluatorPost.re index ef37e2a44a..03dd0d2a71 100644 --- a/src/haz3lcore/dynamics/EvaluatorPost.re +++ b/src/haz3lcore/dynamics/EvaluatorPost.re @@ -58,7 +58,7 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => | IntLit(_) | FloatLit(_) | StringLit(_) - | Tag(_) => d |> return + | Constructor(_) => d |> return | Sequence(d1, d2) => let* d1' = pp_eval(d1); @@ -99,7 +99,7 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => let* d2' = pp_eval(d2); Cons(d1', d2') |> return; - | ListLit(a, b, c, d, ds) => + | ListLit(a, b, c, ds) => let+ ds = ds |> List.fold_left( @@ -110,11 +110,7 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => }, return([]), ); - ListLit(a, b, c, d, ds); - - | Inj(ty, side, d') => - let* d'' = pp_eval(d'); - Inj(ty, side, d'') |> return; + ListLit(a, b, c, ds); | Tuple(ds) => let+ ds = @@ -271,7 +267,7 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => | IntLit(_) | FloatLit(_) | StringLit(_) - | Tag(_) => d |> return + | Constructor(_) => d |> return | Sequence(d1, d2) => let* d1' = pp_uneval(env, d1); @@ -324,7 +320,7 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => let* d2' = pp_uneval(env, d2); Cons(d1', d2') |> return; - | ListLit(a, b, c, d, ds) => + | ListLit(a, b, c, ds) => let+ ds = ds |> List.fold_left( @@ -335,11 +331,7 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => }, return([]), ); - ListLit(a, b, c, d, ds); - - | Inj(ty, side, d') => - let* d'' = pp_uneval(env, d'); - Inj(ty, side, d'') |> return; + ListLit(a, b, c, ds); | Tuple(ds) => let+ ds = @@ -438,7 +430,7 @@ let rec track_children_of_hole = (hii: HoleInstanceInfo.t, parent: HoleInstanceParents.t_, d: DHExp.t) : HoleInstanceInfo.t => switch (d) { - | Tag(_) + | Constructor(_) | TestLit(_) | BoolLit(_) | IntLit(_) @@ -447,7 +439,6 @@ let rec track_children_of_hole = | BoundVar(_) => hii | FixF(_, _, d) | Fun(_, _, d, _) - | Inj(_, _, d) | Prj(d, _) | Cast(d, _, _) | FailedCast(d, _, _) @@ -463,7 +454,7 @@ let rec track_children_of_hole = let hii = track_children_of_hole(hii, parent, d1); track_children_of_hole(hii, parent, d2); - | ListLit(_, _, _, _, ds) => + | ListLit(_, _, _, ds) => List.fold_right( (d, hii) => track_children_of_hole(hii, parent, d), ds, diff --git a/src/haz3lcore/dynamics/HTyp.re b/src/haz3lcore/dynamics/HTyp.re deleted file mode 100644 index 435400a9bc..0000000000 --- a/src/haz3lcore/dynamics/HTyp.re +++ /dev/null @@ -1,190 +0,0 @@ -open Sexplib.Std; -open Util; - -/* types with holes */ -[@deriving (show({with_path: false}), sexp, yojson)] -type t = - | Hole - | Int - | Float - | Bool - | String - | Arrow(t, t) - | Sum(t, t) - | Prod(list(t)) - | List(t); - -[@deriving sexp] -type join = - | GLB - | LUB; - -let precedence_Prod = 1; -let precedence_Arrow = 2; -let precedence_Sum = 3; -let precedence_const = 4; -let precedence = (ty: t): int => - switch (ty) { - | Int - | Float - | String - | Bool - | Hole - | Prod([]) - | List(_) => precedence_const - | Prod(_) => precedence_Prod - | Sum(_, _) => precedence_Sum - | Arrow(_, _) => precedence_Arrow - }; - -/* equality - At the moment, this coincides with default equality, - but this will change when polymorphic types are implemented */ -let eq = (==); - -/* type consistency */ -let rec consistent = (x, y) => - switch (x, y) { - | (Hole, _) - | (_, Hole) => true - | (Int, Int) => true - | (Int, _) => false - | (Float, Float) => true - | (Float, _) => false - | (Bool, Bool) => true - | (Bool, _) => false - | (String, String) => true - | (String, _) => false - | (Arrow(ty1, ty2), Arrow(ty1', ty2')) - | (Sum(ty1, ty2), Sum(ty1', ty2')) => - consistent(ty1, ty1') && consistent(ty2, ty2') - | (Arrow(_, _), _) => false - | (Sum(_, _), _) => false - | (Prod(tys1), Prod(tys2)) => - ListUtil.for_all2_opt(consistent, tys1, tys2) - |> Option.value(~default=false) - | (Prod(_), _) => false - | (List(ty), List(ty')) => consistent(ty, ty') - | (List(_), _) => false - }; - -let inconsistent = (ty1, ty2) => !consistent(ty1, ty2); - -let rec consistent_all = (types: list(t)): bool => - switch (types) { - | [] => true - | [hd, ...tl] => - if (List.exists(inconsistent(hd), tl)) { - false; - } else { - consistent_all(tl); - } - }; - -/* matched arrow types */ -let matched_arrow = - fun - | Hole => Some((Hole, Hole)) - | Arrow(ty1, ty2) => Some((ty1, ty2)) - | _ => None; - -let get_prod_elements: t => list(t) = - fun - | Prod(tys) => tys - | _ as ty => [ty]; - -let get_prod_arity = ty => ty |> get_prod_elements |> List.length; - -/* matched sum types */ -let matched_sum = - fun - | Hole => Some((Hole, Hole)) - | Sum(tyL, tyR) => Some((tyL, tyR)) - | _ => None; - -/* matched list types */ -let matched_list = - fun - | Hole => Some(Hole) - | List(ty) => Some(ty) - | _ => None; - -/* complete (i.e. does not have any holes) */ -let rec complete = - fun - | Hole => false - | Int => true - | Float => true - | Bool => true - | String => true - | Arrow(ty1, ty2) - | Sum(ty1, ty2) => complete(ty1) && complete(ty2) - | Prod(tys) => tys |> List.for_all(complete) - | List(ty) => complete(ty); - -let rec join = (j, ty1, ty2) => - switch (ty1, ty2) { - | (_, Hole) => - switch (j) { - | GLB => Some(Hole) - | LUB => Some(ty1) - } - | (Hole, _) => - switch (j) { - | GLB => Some(Hole) - | LUB => Some(ty2) - } - | (Int, Int) => Some(ty1) - | (Int, _) => None - | (Float, Float) => Some(ty1) - | (Float, _) => None - | (Bool, Bool) => Some(ty1) - | (Bool, _) => None - | (String, String) => Some(ty1) - | (String, _) => None - | (Arrow(ty1, ty2), Arrow(ty1', ty2')) => - switch (join(j, ty1, ty1'), join(j, ty2, ty2')) { - | (Some(ty1), Some(ty2)) => Some(Arrow(ty1, ty2)) - | _ => None - } - | (Arrow(_), _) => None - | (Sum(ty1, ty2), Sum(ty1', ty2')) => - switch (join(j, ty1, ty1'), join(j, ty2, ty2')) { - | (Some(ty1), Some(ty2)) => Some(Sum(ty1, ty2)) - | _ => None - } - | (Sum(_), _) => None - | (Prod(tys1), Prod(tys2)) => - ListUtil.map2_opt(join(j), tys1, tys2) - |> Option.map(OptUtil.sequence) - |> Option.join - |> Option.map(joined_types => Prod(joined_types)) - | (Prod(_), _) => None - | (List(ty), List(ty')) => - switch (join(j, ty, ty')) { - | Some(ty) => Some(List(ty)) - | None => None - } - | (List(_), _) => None - }; - -let join_all = (j: join, types: list(t)): option(t) => { - switch (types) { - | [] => None - | [hd] => Some(hd) - | [hd, ...tl] => - if (!consistent_all(types)) { - None; - } else { - List.fold_left( - (common_opt, ty) => - switch (common_opt) { - | None => None - | Some(common_ty) => join(j, common_ty, ty) - }, - Some(hd), - tl, - ); - } - }; -}; diff --git a/src/haz3lcore/dynamics/HTyp.rei b/src/haz3lcore/dynamics/HTyp.rei deleted file mode 100644 index 069d5f843a..0000000000 --- a/src/haz3lcore/dynamics/HTyp.rei +++ /dev/null @@ -1,39 +0,0 @@ -/* types with holes */ -[@deriving (show({with_path: false}), sexp, yojson)] -type t = - | Hole - | Int - | Float - | Bool - | String - | Arrow(t, t) - | Sum(t, t) - | Prod(list(t)) - | List(t); - -type join = - | GLB - | LUB; - -let precedence_Prod: int; -let precedence_Arrow: int; -let precedence_Sum: int; -let precedence: t => int; - -/* type equality */ -let eq: (t, t) => bool; - -/* type consistency */ -let consistent: (t, t) => bool; - -let get_prod_elements: t => list(t); -let get_prod_arity: t => int; - -let matched_arrow: t => option((t, t)); -let matched_sum: t => option((t, t)); -let matched_list: t => option(t); - -let complete: t => bool; - -let join: (join, t, t) => option(t); -let join_all: (join, list(t)) => option(t); diff --git a/src/haz3lcore/dynamics/InvalidOperationError.re b/src/haz3lcore/dynamics/InvalidOperationError.re index 3d8a037c05..e4287b56e6 100644 --- a/src/haz3lcore/dynamics/InvalidOperationError.re +++ b/src/haz3lcore/dynamics/InvalidOperationError.re @@ -3,6 +3,8 @@ type t = | DivideByZero | NegativeExponent | OutOfFuel + | InvalidIntOfString + | InvalidFloatOfString | InvalidProjection; let err_msg = (err: t): string => @@ -10,5 +12,7 @@ let err_msg = (err: t): string => | DivideByZero => "Error: Divide by Zero" | NegativeExponent => "Error: Negative Exponent in Integer Exponentiation (Consider using **.)" | OutOfFuel => "Error: Out of Fuel" + | InvalidIntOfString => "Error: Invalid String to Int Conversion" + | InvalidFloatOfString => "Error: Invalid String to Float Conversion" | InvalidProjection => "Error: Invalid Projection" }; diff --git a/src/haz3lcore/dynamics/InvalidOperationError.rei b/src/haz3lcore/dynamics/InvalidOperationError.rei index b7338619be..b255c1f95d 100644 --- a/src/haz3lcore/dynamics/InvalidOperationError.rei +++ b/src/haz3lcore/dynamics/InvalidOperationError.rei @@ -3,6 +3,8 @@ type t = | DivideByZero | NegativeExponent | OutOfFuel + | InvalidIntOfString + | InvalidFloatOfString | InvalidProjection; let err_msg: t => string; diff --git a/src/haz3lcore/dynamics/ListErrStatus.re b/src/haz3lcore/dynamics/ListErrStatus.re deleted file mode 100644 index 6a6dba95fc..0000000000 --- a/src/haz3lcore/dynamics/ListErrStatus.re +++ /dev/null @@ -1,6 +0,0 @@ -open Sexplib.Std; - -[@deriving (show({with_path: false}), sexp, yojson)] -type t = - | StandardErrStatus(ErrStatus.t) - | InconsistentBranches(list(Typ.t), MetaVar.t); diff --git a/src/haz3lcore/dynamics/Substitution.re b/src/haz3lcore/dynamics/Substitution.re index d392c14cdc..70120469a2 100644 --- a/src/haz3lcore/dynamics/Substitution.re +++ b/src/haz3lcore/dynamics/Substitution.re @@ -56,9 +56,9 @@ let rec subst_var = (d1: DHExp.t, x: Var.t, d2: DHExp.t): DHExp.t => | IntLit(_) | FloatLit(_) | StringLit(_) - | Tag(_) => d2 - | ListLit(a, b, c, d, ds) => - ListLit(a, b, c, d, List.map(subst_var(d1, x), ds)) + | Constructor(_) => d2 + | ListLit(a, b, c, ds) => + ListLit(a, b, c, List.map(subst_var(d1, x), ds)) | Cons(d3, d4) => let d3 = subst_var(d1, x, d3); let d4 = subst_var(d1, x, d4); @@ -81,9 +81,6 @@ let rec subst_var = (d1: DHExp.t, x: Var.t, d2: DHExp.t): DHExp.t => let d3 = subst_var(d1, x, d3); let d4 = subst_var(d1, x, d4); BinStringOp(op, d3, d4); - | Inj(ty, side, d3) => - let d3 = subst_var(d1, x, d3); - Inj(ty, side, d3); | ConsistentCase(Case(d3, rules, n)) => let d3 = subst_var(d1, x, d3); let rules = subst_var_rules(d1, x, rules); diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index 9cd2566613..dd5050e632 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -45,6 +45,11 @@ type t = { mold: Mold.t, }; +[@deriving (show({with_path: false}), sexp, yojson)] +type bad_token_cls = + | Other + | BadInt; + let mk = (expansion, label, mold) => {label, mold, expansion}; /* Abbreviations for expansion behaviors */ @@ -62,8 +67,9 @@ let mk_nul_infix = (t: Token.t, prec) => mk(ss, [t], mk_bin(~l=Any, ~r=Any, prec, Any, [])); /* Token Recognition Predicates */ -let is_arbitary_int = regexp("^[0-9_]*$"); -let is_arbitary_float = x => x != "." && regexp("^[0-9]*\\.[0-9]*$", x); +let is_arbitary_int = regexp("^-?\\d+[0-9_]*$"); +let is_arbitary_float = x => + x != "." && regexp("^-?[0-9]*\\.?[0-9]*((e|E)-?[0-9]*)?$", x); let is_int = str => is_arbitary_int(str) && int_of_string_opt(str) != None; /* NOTE: The is_arbitary_int check is necessary to prevent minuses from being parsed as part of the int token. */ @@ -83,18 +89,16 @@ let is_bool = str => str == "true" || str == "false"; let is_reserved = str => is_bool(str); let is_var = str => !is_reserved(str) && regexp("^[a-z][A-Za-z0-9_]*$", str); let is_capitalized_name = regexp("^[A-Z][A-Za-z0-9_]*$"); -let is_tag = is_capitalized_name; -let is_concrete_typ = str => - str == "String" || str == "Int" || str == "Float" || str == "Bool"; -let is_typ_var = t => is_capitalized_name(t) && !is_concrete_typ(t); -let is_partial_concrete_typ = x => - !is_concrete_typ(x) && is_capitalized_name(x); +let is_ctr = is_capitalized_name; +let is_base_typ = regexp("^(String|Int|Float|Bool)$"); +let is_typ_var = is_capitalized_name; +let is_partial_base_typ = x => !is_base_typ(x) && is_capitalized_name(x); let is_wild = regexp("^_$"); /* The below case represents tokens which we want the user to be able to type in, but which have no reasonable semantic interpretation */ let is_bad_lit = str => - is_bad_int(str) || is_bad_float(str) || is_partial_concrete_typ(str); + is_bad_int(str) || is_bad_float(str) || is_partial_base_typ(str); /* is_string: last clause is a somewhat hacky way of making sure there are at most two quotes, in order to prevent merges */ @@ -141,7 +145,7 @@ let duomerges = (lbl: Label.t): option(Label.t) => exceptions when used elsewhere, as no molds will be found. Such exceptions are currently caught. This should be replaced by a more disciplined approach to invalid text.*/ -let is_whitelisted_char = regexp("[!@]"); +let is_whitelisted_char = regexp("[!@\\{\\}]"); /* A. Secondary Notation (Comments, Whitespace, etc.) */ let space = " "; @@ -155,6 +159,13 @@ let is_comment_delim = t => t == "#"; let is_secondary = t => List.mem(t, [space, linebreak]) || regexp(comment_regexp, t); +let bad_token_cls: string => bad_token_cls = + t => + switch () { + | _ when is_bad_int(t) => BadInt + | _ => Other + }; + /* B. Operands: Order in this list determines relative remolding priority for forms with overlapping regexps */ @@ -162,8 +173,9 @@ let atomic_forms: list((string, (string => bool, list(Mold.t)))) = [ ("bad_lit", (is_bad_lit, [mk_op(Any, [])])), ("var", (is_var, [mk_op(Exp, []), mk_op(Pat, [])])), ("ty_var", (is_typ_var, [mk_op(Typ, [])])), - ("ctr", (is_tag, [mk_op(Exp, []), mk_op(Pat, [])])), - ("type", (is_concrete_typ, [mk_op(Typ, [])])), + ("ty_var_p", (is_typ_var, [mk_op(TPat, [])])), + ("ctr", (is_ctr, [mk_op(Exp, []), mk_op(Pat, [])])), + ("type", (is_base_typ, [mk_op(Typ, [])])), ("empty_list", (is_empty_list, [mk_op(Exp, []), mk_op(Pat, [])])), ( "empty_tuple", @@ -181,6 +193,8 @@ let atomic_forms: list((string, (string => bool, list(Mold.t)))) = [ priority for forms which share the same labels */ let forms: list((string, t)) = [ + ("typ_plus", mk_infix("+", Typ, P.or_)), + ("typ_sum_single", mk(ss, ["+"], mk_pre(P.or_, Typ, []))), ("cell-join", mk_infix(";", Exp, 10)), ("plus", mk_infix("+", Exp, P.plus)), ("minus", mk_infix("-", Exp, P.plus)), @@ -226,7 +240,12 @@ let forms: list((string, t)) = [ ("if_", mk(ds, ["if", "then", "else"], mk_pre(P.if_, Exp, [Exp, Exp]))), ("ap_exp", mk(ii, ["(", ")"], mk_post(P.ap, Exp, [Exp]))), ("ap_pat", mk(ii, ["(", ")"], mk_post(P.ap, Pat, [Pat]))), + ("ap_typ", mk(ii, ["(", ")"], mk_post(P.ap, Typ, [Typ]))), ("let_", mk(ds, ["let", "=", "in"], mk_pre(P.let_, Exp, [Pat, Exp]))), + ( + "type_alias", + mk(ds, ["type", "=", "in"], mk_pre(P.let_, Exp, [TPat, Typ])), + ), ("typeann", mk(ss, [":"], mk_bin'(P.ann, Pat, Pat, [], Typ))), ("case", mk(ds, ["case", "end"], mk_op(Exp, [Rul]))), ( @@ -260,7 +279,8 @@ let forms: list((string, t)) = [ //("block", mk(ii, ["{", "}"], mk_op(Exp, [Exp]))), ]; -let get: String.t => t = name => List.assoc(name, forms); +let get: String.t => t = + name => Util.ListUtil.assoc_err(name, forms, "Forms.get"); let delims: list(Token.t) = forms diff --git a/src/haz3lcore/lang/Sort.re b/src/haz3lcore/lang/Sort.re index 3ba8c327b2..2b66c3282b 100644 --- a/src/haz3lcore/lang/Sort.re +++ b/src/haz3lcore/lang/Sort.re @@ -4,12 +4,13 @@ type t = | Nul | Pat | Typ + | TPat | Rul | Exp; let root = Exp; -let all = [Any, Nul, Pat, Typ, Rul, Exp]; +let all = [Any, Nul, Pat, Typ, Rul, Exp, TPat]; let consistent = (s, s') => switch (s, s') { @@ -25,6 +26,17 @@ let to_string = | Any => "Any" | Nul => "Nul" | Pat => "Pat" + | TPat => "TPat" | Typ => "Typ" | Rul => "Rul" | Exp => "Exp"; + +let to_string_verbose = + fun + | Any => "any" + | Nul => "null" + | Pat => "pattern" + | TPat => "type pattern" + | Typ => "type" + | Rul => "rule" + | Exp => "expression"; diff --git a/src/haz3lcore/statics/BuiltinADTs.re b/src/haz3lcore/statics/BuiltinADTs.re deleted file mode 100644 index f8ed37f489..0000000000 --- a/src/haz3lcore/statics/BuiltinADTs.re +++ /dev/null @@ -1,97 +0,0 @@ -open Sexplib.Std; - -[@deriving (show({with_path: false}), sexp, yojson)] -type tag = { - name: string, - arg: option(Typ.t), -}; - -[@deriving (show({with_path: false}), sexp, yojson)] -type adt = (string, list(tag)); - -let alftyp = Typ.Var("ALFTyp"); -let alfexpr = Typ.Var("ALFExpr"); -let option_alftyp = Typ.Var("Option_ALFTyp"); - -let adts: list(adt) = [ - ( - "Color", - [ - {name: "Red", arg: None}, - {name: "Green", arg: None}, - {name: "Blue", arg: None}, - ], - ), - ( - "Option_ALFTyp", - [{name: "None", arg: None}, {name: "Some", arg: Some(alftyp)}], - ), - ( - "ALFTyp", - { - [ - {name: "Num", arg: None}, - {name: "Bool", arg: None}, - {name: "Arrow", arg: Some(Prod([alftyp, alftyp]))}, - {name: "Prod", arg: Some(Prod([alftyp, alftyp]))}, - ]; - }, - ), - ( - "ALFExpr", - { - [ - {name: "NumLit", arg: Some(Int)}, - {name: "Plus", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "Times", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "Minus", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "Eq", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "Lt", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "Gt", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "Neg", arg: Some(alfexpr)}, - {name: "BoolLit", arg: Some(Bool)}, - {name: "If", arg: Some(Prod([alfexpr, alfexpr, alfexpr]))}, - {name: "Var", arg: Some(String)}, - {name: "Let", arg: Some(Prod([String, alfexpr, alfexpr]))}, - {name: "Fun", arg: Some(Prod([String, alftyp, alfexpr]))}, - {name: "Ap", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "Pair", arg: Some(Prod([alfexpr, alfexpr]))}, - {name: "PrjL", arg: Some(alfexpr)}, - {name: "PrjR", arg: Some(alfexpr)}, - { - name: "LetPair", - arg: Some(Prod([String, String, alfexpr, alfexpr])), - }, - ]; - }, - ), -]; - -let is_typ_var = name => List.assoc_opt(name, adts); - -let tags: list((string, Typ.t)) = - List.map( - ((name, tags)) => { - List.map( - adt => - ( - adt.name, - switch (adt.arg) { - | None => Typ.Var(name) - | Some(typ) => Arrow(typ, Var(name)) - }, - ), - tags, - ) - }, - adts, - ) - |> List.flatten; - -let get_tag_typ = (tag_name: string): option(Typ.t) => - List.assoc_opt(tag_name, tags); - -// Check type names are unique -assert(Util.ListUtil.are_duplicates(List.map(fst, adts))); -// Check tag names are unique -assert(Util.ListUtil.are_duplicates(List.map(fst, tags))); diff --git a/src/haz3lcore/statics/CoCtx.re b/src/haz3lcore/statics/CoCtx.re new file mode 100644 index 0000000000..7cbcc51b97 --- /dev/null +++ b/src/haz3lcore/statics/CoCtx.re @@ -0,0 +1,61 @@ +open Sexplib.Std; + +/* Co-contexts: + + A typing co-context (dual to a typing context), is a map between + variable names and a list of that variable's uses within some scope. + For each use, we retain the unique id and expected type of the use site. + The co-ctx, along with the ctx, can be used to determine free and unused variables. + + The following definitions are useful: + + 1. A locally free variable (in an expression) is one + that occurs in the co_ctx of that expression. + 2. A global free variable (in the program) is one that + occurs in the co_ctx but not the ctx of some expression + 3. A locally unused variable (in an expression) is one that + occurs in the ctx but not the co-ctx of that expression + 4. A global unused variable (in the program) is one that + occurs in the ctx but not the co_ctx of some expression + + The following theorems should hold: + + A. To determine if a variable is globally free, it suffices to consider + expressions which are variable references (locus of ctx lookups) + B. To determine if a variable is globally unused, it suffices to consider + expressions which are the bodies of binding forms (locus of ctx extensions) + + */ + +[@deriving (show({with_path: false}), sexp, yojson)] +type entry = { + id: Id.t, + expected_ty: Typ.t, +}; + +/* Each co-context entry is a list of the uses of a variable + within some scope, including their type demands */ +[@deriving (show({with_path: false}), sexp, yojson)] +type t = VarMap.t_(list(entry)); + +let empty: t = VarMap.empty; + +let mk = (ctx_before: Ctx.t, ctx_after, co_ctx: t): t => { + let added_bindings = Ctx.added_bindings(ctx_after, ctx_before); + VarMap.filter( + ((name, _)) => + switch (Ctx.lookup_var(added_bindings, name)) { + | None => true + | Some(_) => false + }, + co_ctx, + ); +}; + +/* Note: this currently shadows in the case of duplicates */ +let union: list(t) => t = + List.fold_left((co_ctx1, co_ctx2) => co_ctx1 @ co_ctx2, []); + +let singleton = (name, id, expected_ty): t => [ + (name, [{id, expected_ty}]), +]; diff --git a/src/haz3lcore/statics/Constructor.re b/src/haz3lcore/statics/Constructor.re new file mode 100644 index 0000000000..6515fd2f97 --- /dev/null +++ b/src/haz3lcore/statics/Constructor.re @@ -0,0 +1,6 @@ +open Sexplib.Std; + +[@deriving (show({with_path: false}), sexp, yojson)] +type t = string; + +let equal = String.equal; diff --git a/src/haz3lcore/statics/ConstructorMap.re b/src/haz3lcore/statics/ConstructorMap.re new file mode 100644 index 0000000000..c9ff0667dc --- /dev/null +++ b/src/haz3lcore/statics/ConstructorMap.re @@ -0,0 +1,101 @@ +open Util.OptUtil.Syntax; +open Sexplib.Std; + +[@deriving (show({with_path: false}), sexp, yojson)] +type binding('a) = (Constructor.t, 'a); + +[@deriving (show({with_path: false}), sexp, yojson)] +type t('a) = list(binding('a)); + +let compare = compare; + +let empty: t('a) = []; + +let is_empty: t('a) => bool = + fun + | [] => true + | _ => false; + +let rec add = (ctr: Constructor.t, value: 'a, map: t('a)): t('a) => + switch (map) { + | [] => [(ctr, value)] + | [(ctr', value') as head, ...tail] => + if (Constructor.equal(ctr, ctr')) { + if (value === value') { + map; + } else { + [(ctr, value), ...tail]; + }; + } else { + [head, ...add(ctr, value, tail)]; + } + }; + +let singleton = (ctr: Constructor.t, value: 'a): t('a) => [(ctr, value)]; + +let compare_bindings = + ((ctr1, _): binding('a), (ctr2, _): binding('a)): int => + compare(ctr1, ctr2); + +/* compares ctrs only */ +let equal = (val_equal: ('a, 'a) => bool, map1: t('a), map2: t('a)): bool => { + let equal_bindings = + ( + val_equal: ('a, 'a) => bool, + (ctr1, val1): binding('a), + (ctr2, val2): binding('a), + ) + : bool => + Constructor.equal(ctr1, ctr2) && val_equal(val1, val2); + map1 === map2 + || { + let map1 = List.fast_sort(compare_bindings, map1); + let map2 = List.fast_sort(compare_bindings, map2); + List.equal(equal_bindings(val_equal), map1, map2); + }; +}; + +let cardinal: t('a) => int = List.length; + +let ctrs_of = (m: list((Constructor.t, 'a))): list(Constructor.t) => + List.map(fst, m); + +let same_constructors_same_order = (map1: t('a), map2: t('a)): bool => + cardinal(map1) === cardinal(map2) + && List.for_all2(Constructor.equal, ctrs_of(map1), ctrs_of(map2)); + +let ctrs_equal = (map1: t('a), map2: t('a)): bool => { + let ctrs1 = ctrs_of(map1); + let ctrs2 = ctrs_of(map2); + ctrs1 === ctrs2 + || List.fast_sort(compare, ctrs1) == List.fast_sort(compare, ctrs2); +}; + +let for_all: (binding('a) => bool, t('a)) => bool = List.for_all; + +let bindings: t('a) => list(binding('a)) = x => x; + +let find_opt = (ctr: Constructor.t, map: t('a)): option('a) => { + let+ binding = List.find_opt(((k, _)) => Constructor.equal(ctr, k), map); + snd(binding); +}; + +let map = (f: 'a => 'b, m: t('a)): t('b) => { + let (ctrs, vals) = List.split(m); + let vals = List.map(f, vals); + List.combine(ctrs, vals); +}; + +/* sorts on ctrs only */ +let sort = (map: t('a)): t('a) => { + List.fast_sort(compare_bindings, map); +}; + +let of_list: list(binding('a)) => t('a) = x => x; + +let rec is_ground = (is_ground_value: 'a => bool, map: t('a)): bool => + switch (map) { + | [] => true + | [(_, head), ...tail] => + is_ground_value(head) && tail |> is_ground(is_ground_value) + }; diff --git a/src/haz3lcore/statics/Ctx.re b/src/haz3lcore/statics/Ctx.re index 2fd801e3bc..1b1ccffd2c 100644 --- a/src/haz3lcore/statics/Ctx.re +++ b/src/haz3lcore/statics/Ctx.re @@ -1,108 +1 @@ -open Sexplib.Std; - -[@deriving (show({with_path: false}), sexp, yojson)] -type var_entry = { - name: Token.t, - id: Id.t, - typ: Typ.t, -}; - -[@deriving (show({with_path: false}), sexp, yojson)] -type entry = - | VarEntry(var_entry) - | TVarEntry({ - name: Token.t, - id: Id.t, - kind: Kind.t, - }); - -let get_id = (entry: entry) => - switch (entry) { - | VarEntry({id, _}) => id - | TVarEntry({id, _}) => id - }; - -[@deriving (show({with_path: false}), sexp, yojson)] -type t = list(entry); - -[@deriving (show({with_path: false}), sexp, yojson)] -type co_item = { - id: Id.t, - mode: Typ.mode, -}; - -[@deriving (show({with_path: false}), sexp, yojson)] -type co_entry = list(co_item); - -[@deriving (show({with_path: false}), sexp, yojson)] -type co = VarMap.t_(co_entry); - -let empty = VarMap.empty; - -let extend = (entry: entry, ctx: t) => [entry, ...ctx]; - -let lookup_var = (ctx: t, name: string): option(var_entry) => - List.find_map( - entry => - switch (entry) { - | VarEntry(var) => - if (var.name == name) { - Some(var); - } else { - None; - } - | TVarEntry(_) => None - }, - ctx, - ); - -let subtract_typ = (ctx: t, free: co): co => - VarMap.filter( - ((k, _)) => - switch (lookup_var(ctx, k)) { - | None => true - | Some(_) => false - }, - free, - ); - -let subtract_prefix = (ctx: t, prefix_ctx: t): option(t) => { - // NOTE: does not check that the prefix is an actual prefix - let prefix_length = List.length(prefix_ctx); - let ctx_length = List.length(ctx); - if (prefix_length > ctx_length) { - None; - } else { - Some( - List.rev( - Util.ListUtil.sublist((prefix_length, ctx_length), List.rev(ctx)), - ), - ); - }; -}; - -//TODO(andrew): is this correct in the case of duplicates? -let union: list(co) => co = - List.fold_left((free1, free2) => free1 @ free2, []); - -module VarSet = Set.Make(Token); - -// Note: filter out duplicates when rendering -let filter_duplicates = (ctx: t): t => - ctx - |> List.fold_left( - ((ctx, term_set, typ_set), entry) => { - switch (entry) { - | VarEntry({name, _}) => - VarSet.mem(name, term_set) - ? (ctx, term_set, typ_set) - : ([entry, ...ctx], VarSet.add(name, term_set), typ_set) - | TVarEntry({name, _}) => - VarSet.mem(name, term_set) - ? (ctx, term_set, typ_set) - : ([entry, ...ctx], term_set, VarSet.add(name, typ_set)) - } - }, - ([], VarSet.empty, VarSet.empty), - ) - |> (((ctx, _, _)) => List.rev(ctx)); +include TypBase.Ctx; diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re new file mode 100644 index 0000000000..c7c5985c0a --- /dev/null +++ b/src/haz3lcore/statics/Info.re @@ -0,0 +1,480 @@ +open Sexplib.Std; +open Util; +open OptUtil.Syntax; +open Term; + +/* INFO.re + + This module defines the cursor INFO data structure, which is used + to represent the static information associated with a term in the + AST. This includes the term itself, and information related to + typing and syntax, included erroneous states. + + Each term is assigned a STATUS, which is directly used to determine + the message displayed to the user in CursorInspector.re. Each sort + has its own status datatype, which is divided into OK states (not + in error holes) and ERROR states (in error holes). + + Regardless of errors, every expression & pattern term is ultimately + assigned a FIXED TYPE, which is the type of the term after hole + fixing; that is, all otherwise ill-typed terms are considered to + be 'wrapped in non-empty holes', i.e. assigned an Unknown type. + + Fixed types are determined by reconcilling two sources of type + information: the SELF (Self.re), representing the type information + derivable from a term in isolation, and the MODE (Mode.re), + representing the expected type information imposed by the surrounding + syntactic context. A successful reconcilliation results in an OK + status; otherwise, an ERROR status, but in both cases, a fixed type + is determined. + + */ + +/* The ids of a term's ancestors in the AST */ +[@deriving (show({with_path: false}), sexp, yojson)] +type ancestors = list(Id.t); + +[@deriving (show({with_path: false}), sexp, yojson)] +type error_inconsistent = + /* Self type (syn) inconsistent with expected type (ana) */ + | Expectation({ + ana: Typ.t, + syn: Typ.t, + }) + /* Inconsistent match or listlit */ + | Internal(list(Typ.t)) + /* Bad function position */ + | WithArrow(Typ.t); + +[@deriving (show({with_path: false}), sexp, yojson)] +type error_no_type = + /* Invalid expression token, treated as hole */ + | BadToken(Token.t) + /* Sum constructor neiter bound nor in ana type */ + | FreeConstructor(Constructor.t); + +/* Errors which can apply to either expression or patterns */ +[@deriving (show({with_path: false}), sexp, yojson)] +type error_common = + /* No type can be assigned */ + | NoType(error_no_type) + /* Assigned type inconsistent with expectation */ + | Inconsistent(error_inconsistent); + +[@deriving (show({with_path: false}), sexp, yojson)] +type error_exp = + | FreeVariable(Var.t) /* Unbound variable (not in typing context) */ + | Common(error_common); + +[@deriving (show({with_path: false}), sexp, yojson)] +type error_pat = + | ExpectedConstructor /* Only construtors can be applied */ + | Common(error_common); + +[@deriving (show({with_path: false}), sexp, yojson)] +type ok_ana = + /* The expected (ana) type and the self (syn) type are + consistent, as witnessed by their joint type (join) */ + | Consistent({ + ana: Typ.t, + syn: Typ.t, + join: Typ.t, + }) + /* A match expression or list literal which, in synthetic position, + would be marked as internally inconsistent, but is considered + fine as the expected type provides a consistent lower bound + (often Unknown) for the types of the branches/elements */ + | InternallyInconsistent({ + ana: Typ.t, + nojoin: list(Typ.t), + }); + +[@deriving (show({with_path: false}), sexp, yojson)] +type ok_common = + | Syn(Typ.t) + | Ana(ok_ana); + +[@deriving (show({with_path: false}), sexp, yojson)] +type ok_exp = ok_common; + +[@deriving (show({with_path: false}), sexp, yojson)] +type ok_pat = ok_common; + +[@deriving (show({with_path: false}), sexp, yojson)] +type status_common = + | InHole(error_common) + | NotInHole(ok_common); + +[@deriving (show({with_path: false}), sexp, yojson)] +type status_exp = + | InHole(error_exp) + | NotInHole(ok_exp); + +[@deriving (show({with_path: false}), sexp, yojson)] +type status_pat = + | InHole(error_pat) + | NotInHole(ok_pat); + +[@deriving (show({with_path: false}), sexp, yojson)] +type status_variant = + | Unique + | Duplicate; + +/* Expectation imposed on a type by the parent form. + TODO: This is fundamentally syntactic and should + eventually be reimplemeted via a seperate sort */ +[@deriving (show({with_path: false}), sexp, yojson)] +type typ_expects = + | TypeExpected + | ConstructorExpected(status_variant, Typ.t) + | VariantExpected(status_variant, Typ.t); + +/* Type term errors + TODO: The three additional errors statuses + are fundamentally syntactic and should when + possible be reimplemeted via a seperate sort */ +[@deriving (show({with_path: false}), sexp, yojson)] +type error_typ = + | BadToken(Token.t) /* Invalid token, treated as type hole */ + | FreeTypeVariable(TypVar.t) /* Free type variable */ + | DuplicateConstructor(Constructor.t) /* Duplicate ctr in same sum */ + | WantTypeFoundAp + | WantConstructorFoundType(Typ.t) + | WantConstructorFoundAp; + +/* Type ok statuses for cursor inspector */ +[@deriving (show({with_path: false}), sexp, yojson)] +type ok_typ = + | Variant(Constructor.t, Typ.t) + | VariantIncomplete(Typ.t) + | TypeAlias(TypVar.t, Typ.t) + | Type(Typ.t); + +[@deriving (show({with_path: false}), sexp, yojson)] +type status_typ = + | InHole(error_typ) + | NotInHole(ok_typ); + +[@deriving (show({with_path: false}), sexp, yojson)] +type type_var_err = + | Other + | NotCapitalized; + +/* Type pattern term errors */ +[@deriving (show({with_path: false}), sexp, yojson)] +type error_tpat = + | ShadowsType(TypVar.t) + | NotAVar(type_var_err); + +/* Type pattern ok statuses for cursor inspector */ +[@deriving (show({with_path: false}), sexp, yojson)] +type ok_tpat = + | Empty + | Var(TypVar.t); + +[@deriving (show({with_path: false}), sexp, yojson)] +type status_tpat = + | NotInHole(ok_tpat) + | InHole(error_tpat); + +[@deriving (show({with_path: false}), sexp, yojson)] +type exp = { + term: UExp.t, /* The term under consideration */ + ancestors, /* Ascending list of containing term ids */ + ctx: Ctx.t, /* Typing context for the term */ + mode: Mode.t, /* Parental type expectations; see Mode.re */ + self: Self.exp, /* Expectation-independent type info; see Self.re */ + co_ctx: CoCtx.t, /* Locally unbound variables; see CoCtx.re */ + cls: Term.Cls.t, /* derived */ + status: status_exp, /* derived: cursor inspector display */ + ty: Typ.t /* derived: type after hole fixing */ +}; + +[@deriving (show({with_path: false}), sexp, yojson)] +type pat = { + term: UPat.t, + ancestors, + ctx: Ctx.t, + mode: Mode.t, + self: Self.pat, + cls: Term.Cls.t, /* derived */ + status: status_pat, /* derived: cursor inspector display */ + ty: Typ.t /* derived: type after hole fixing */ +}; + +[@deriving (show({with_path: false}), sexp, yojson)] +type typ = { + term: UTyp.t, + ancestors, + ctx: Ctx.t, + expects: typ_expects, + cls: Term.Cls.t, /* derived */ + status: status_typ, /* derived: cursor inspector display */ + ty: Typ.t /* derived: represented type */ +}; + +[@deriving (show({with_path: false}), sexp, yojson)] +type tpat = { + term: UTPat.t, + ancestors, + ctx: Ctx.t, + cls: Term.Cls.t, /* derived */ + status: status_tpat /* derived : cursor inspector display */ +}; + +/* The static information collated for each term */ +[@deriving (show({with_path: false}), sexp, yojson)] +type t = + | InfoExp(exp) + | InfoPat(pat) + | InfoTyp(typ) + | InfoTPat(tpat); + +let sort_of: t => Sort.t = + fun + | InfoExp(_) => Exp + | InfoPat(_) => Pat + | InfoTyp(_) => Typ + | InfoTPat(_) => TPat; + +let cls_of: t => Cls.t = + fun + | InfoExp({cls, _}) + | InfoPat({cls, _}) + | InfoTyp({cls, _}) + | InfoTPat({cls, _}) => cls; + +let ctx_of: t => Ctx.t = + fun + | InfoExp({ctx, _}) + | InfoPat({ctx, _}) + | InfoTyp({ctx, _}) + | InfoTPat({ctx, _}) => ctx; + +let exp_co_ctx: exp => CoCtx.t = ({co_ctx, _}) => co_ctx; +let exp_ty: exp => Typ.t = ({ty, _}) => ty; +let pat_ctx: pat => Ctx.t = ({ctx, _}) => ctx; +let pat_ty: pat => Typ.t = ({ty, _}) => ty; + +let rec status_common = + (ctx: Ctx.t, mode: Mode.t, self: Self.t): status_common => + switch (self, mode) { + | (Just(syn), Syn) => NotInHole(Syn(syn)) + | (Just(syn), Ana(ana)) => + switch (Typ.join_fix(ctx, ana, syn)) { + | None => InHole(Inconsistent(Expectation({syn, ana}))) + | Some(join) => NotInHole(Ana(Consistent({ana, syn, join}))) + } + | (Just(syn), SynFun) => + switch ( + Typ.join_fix(ctx, Arrow(Unknown(Internal), Unknown(Internal)), syn) + ) { + | None => InHole(Inconsistent(WithArrow(syn))) + | Some(_) => NotInHole(Syn(syn)) + } + | (IsConstructor({name, syn_ty}), _) => + /* If a ctr is being analyzed against (an arrow type returning) + a sum type having that ctr as a variant, its self type is + considered to be determined by the sum type; otherwise, + check the context for the ctr's type */ + switch (Mode.ctr_ana_typ(ctx, mode, name), syn_ty) { + | (Some(ana_ty), _) => status_common(ctx, mode, Just(ana_ty)) + | (_, Some(syn_ty)) => status_common(ctx, mode, Just(syn_ty)) + | _ => InHole(NoType(FreeConstructor(name))) + } + | (BadToken(name), _) => InHole(NoType(BadToken(name))) + | (IsMulti, _) => NotInHole(Syn(Unknown(Internal))) + | (NoJoin(tys), Ana(ana)) => + NotInHole( + Ana(InternallyInconsistent({ana, nojoin: Typ.of_source(tys)})), + ) + | (NoJoin(tys), Syn | SynFun) => + InHole(Inconsistent(Internal(Typ.of_source(tys)))) + }; + +let status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => + switch (mode, self) { + | (Syn | Ana(_), Common(self_pat)) + | (SynFun, Common(IsConstructor(_) as self_pat)) => + /* Little bit of a hack. Anything other than a bound ctr will, in + function position, have SynFun mode (see Typ.ap_mode). Since we + are prohibiting non-ctrs in ctr applications in patterns for now, + we catch them here, diverting to an ExpectedConstructor error. But we + avoid capturing the second case above, as these will ultimately + get a (more precise) unbound ctr via status_common */ + switch (status_common(ctx, mode, self_pat)) { + | NotInHole(ok_exp) => NotInHole(ok_exp) + | InHole(err_pat) => InHole(Common(err_pat)) + } + | (SynFun, _) => InHole(ExpectedConstructor) + }; + +/* Determines whether an expression or pattern is in an error hole, + depending on the mode, which represents the expectations of the + surrounding syntactic context, and the self which represents the + makeup of the expression / pattern itself. */ +let status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => + switch (self, mode) { + | (Free(name), _) => InHole(FreeVariable(name)) + | (Common(self_pat), _) => + switch (status_common(ctx, mode, self_pat)) { + | NotInHole(ok_exp) => NotInHole(ok_exp) + | InHole(err_pat) => InHole(Common(err_pat)) + } + }; + +/* This logic determines whether a type should be put + in a hole or not. It's mostly syntactic, determining + the proper placement of sum type variants and ctrs; + this should be reimplemented in the future as a + separate sort. It also determines semantic properties + such as whether or not a type variable reference is + free, and whether a ctr name is a dupe. */ +let status_typ = + (ctx: Ctx.t, expects: typ_expects, term: TermBase.UTyp.t, ty: Typ.t) + : status_typ => + switch (term.term) { + | Invalid(token) => InHole(BadToken(token)) + | EmptyHole => NotInHole(Type(ty)) + | Var(name) + | Constructor(name) => + switch (expects) { + | VariantExpected(Unique, sum_ty) + | ConstructorExpected(Unique, sum_ty) => + NotInHole(Variant(name, sum_ty)) + | VariantExpected(Duplicate, _) + | ConstructorExpected(Duplicate, _) => + InHole(DuplicateConstructor(name)) + | TypeExpected => + switch (Ctx.is_alias(ctx, name)) { + | false => InHole(FreeTypeVariable(name)) + | true => NotInHole(TypeAlias(name, Typ.weak_head_normalize(ctx, ty))) + } + } + | Ap(t1, t2) => + switch (expects) { + | VariantExpected(status_variant, ty_variant) => + let ty_in = UTyp.to_typ(ctx, t2); + switch (status_variant, t1.term) { + | (Unique, Var(name) | Constructor(name)) => + NotInHole(Variant(name, Arrow(ty_in, ty_variant))) + | _ => NotInHole(VariantIncomplete(Arrow(ty_in, ty_variant))) + }; + | ConstructorExpected(_) => InHole(WantConstructorFoundAp) + | TypeExpected => InHole(WantTypeFoundAp) + } + | _ => + switch (expects) { + | TypeExpected => NotInHole(Type(ty)) + | ConstructorExpected(_) + | VariantExpected(_) => InHole(WantConstructorFoundType(ty)) + } + }; + +let status_tpat = (ctx: Ctx.t, utpat: UTPat.t): status_tpat => + switch (utpat.term) { + | EmptyHole => NotInHole(Empty) + | Var(name) + when Form.is_base_typ(name) || Ctx.lookup_alias(ctx, name) != None => + InHole(ShadowsType(name)) + | Var(name) => NotInHole(Var(name)) + | Invalid(_) => InHole(NotAVar(NotCapitalized)) + | MultiHole(_) => InHole(NotAVar(Other)) + }; + +/* Determines whether any term is in an error hole. */ +let is_error = (ci: t): bool => { + switch (ci) { + | InfoExp({mode, self, ctx, _}) => + switch (status_exp(ctx, mode, self)) { + | InHole(_) => true + | NotInHole(_) => false + } + | InfoPat({mode, self, ctx, _}) => + switch (status_pat(ctx, mode, self)) { + | InHole(_) => true + | NotInHole(_) => false + } + | InfoTyp({expects, ctx, term, ty, _}) => + switch (status_typ(ctx, expects, term, ty)) { + | InHole(_) => true + | NotInHole(_) => false + } + | InfoTPat({term, ctx, _}) => + switch (status_tpat(ctx, term)) { + | InHole(_) => true + | NotInHole(_) => false + } + }; +}; + +/* Determined the type of an expression or pattern 'after hole fixing'; + that is, all ill-typed terms are considered to be 'wrapped in + non-empty holes', i.e. assigned Unknown type. */ +let fixed_typ_ok: ok_pat => Typ.t = + fun + | Syn(syn) => syn + | Ana(Consistent({join, _})) => join + | Ana(InternallyInconsistent({ana, _})) => ana; + +let fixed_typ_pat = (ctx, mode: Mode.t, self: Self.pat): Typ.t => + switch (status_pat(ctx, mode, self)) { + | InHole(_) => Unknown(Internal) + | NotInHole(ok) => fixed_typ_ok(ok) + }; + +let fixed_typ_exp = (ctx, mode: Mode.t, self: Self.exp): Typ.t => + switch (status_exp(ctx, mode, self)) { + | InHole(_) => Unknown(Internal) + | NotInHole(ok) => fixed_typ_ok(ok) + }; + +/* Add derivable attributes for expression terms */ +let derived_exp = + (~uexp: UExp.t, ~ctx, ~mode, ~ancestors, ~self, ~co_ctx): exp => { + let cls = Cls.Exp(UExp.cls_of_term(uexp.term)); + let status = status_exp(ctx, mode, self); + let ty = fixed_typ_exp(ctx, mode, self); + {cls, self, ty, mode, status, ctx, co_ctx, ancestors, term: uexp}; +}; + +/* Add derivable attributes for pattern terms */ +let derived_pat = (~upat: UPat.t, ~ctx, ~mode, ~ancestors, ~self): pat => { + let cls = Cls.Pat(UPat.cls_of_term(upat.term)); + let status = status_pat(ctx, mode, self); + let ty = fixed_typ_pat(ctx, mode, self); + {cls, self, mode, ty, status, ctx, ancestors, term: upat}; +}; + +/* Add derivable attributes for types */ +let derived_typ = (~utyp: UTyp.t, ~ctx, ~ancestors, ~expects): typ => { + let cls: Cls.t = + /* Hack to improve CI display */ + switch (expects, UTyp.cls_of_term(utyp.term)) { + | (VariantExpected(_), Var) => Cls.Typ(Constructor) + | (_, cls) => Cls.Typ(cls) + }; + let ty = UTyp.to_typ(ctx, utyp); + let status = status_typ(ctx, expects, utyp, ty); + {cls, ctx, ancestors, status, expects, ty, term: utyp}; +}; + +/* Add derivable attributes for type patterns */ +let derived_tpat = (~utpat: UTPat.t, ~ctx, ~ancestors): tpat => { + let cls = Cls.TPat(UTPat.cls_of_term(utpat.term)); + let status = status_tpat(ctx, utpat); + {cls, ancestors, status, ctx, term: utpat}; +}; + +/* If the info represents some kind of name binding which + exists in the context, return the id where the binding occurs */ +let get_binding_site = (info: t): option(Id.t) => { + switch (info) { + | InfoExp({term: {term: Var(name) | Constructor(name), _}, ctx, _}) + | InfoPat({term: {term: Constructor(name), _}, ctx, _}) + | InfoTyp({term: {term: Var(name), _}, ctx, _}) => + let+ entry = Ctx.lookup(ctx, name); + Ctx.get_id(entry); + | _ => None + }; +}; diff --git a/src/haz3lcore/statics/Kind.re b/src/haz3lcore/statics/Kind.re index 85cfe1651d..8db5638e94 100644 --- a/src/haz3lcore/statics/Kind.re +++ b/src/haz3lcore/statics/Kind.re @@ -1,3 +1 @@ -[@deriving (show({with_path: false}), sexp, yojson)] -type t = - | Type; +include TypBase.Kind; diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index 42fe033450..531b538498 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -73,43 +73,20 @@ let _complete_root = } | root => root; -let is_tuple_exp = ((commas, kids): tiles): option(list(UExp.t)) => - if (commas |> List.map(snd) |> List.for_all((==)(([","], [])))) { - kids - |> List.map( - fun - | Exp(e) => Some(e) - | _ => None, - ) - |> OptUtil.sequence; - } else { - None; - }; -let is_tuple_pat = ((commas, kids): tiles): option(list(UPat.t)) => - if (commas |> List.map(snd) |> List.for_all((==)(([","], [])))) { - kids - |> List.map( - fun - | Pat(p) => Some(p) - | _ => None, - ) - |> OptUtil.sequence; - } else { - None; - }; -let is_tuple_typ = ((commas, kids): tiles): option(list(UTyp.t)) => - if (commas |> List.map(snd) |> List.for_all((==)(([","], [])))) { - kids - |> List.map( - fun - | Typ(ty) => Some(ty) - | _ => None, - ) - |> OptUtil.sequence; +let is_nary = + (is_sort: any => option('sort), delim: Token.t, (delims, kids): tiles) + : option(list('sort)) => + if (delims |> List.map(snd) |> List.for_all((==)(([delim], [])))) { + kids |> List.map(is_sort) |> OptUtil.sequence; } else { None; }; +let is_tuple_exp = is_nary(TermBase.Any.is_exp, ","); +let is_tuple_pat = is_nary(TermBase.Any.is_pat, ","); +let is_tuple_typ = is_nary(TermBase.Any.is_typ, ","); +let is_typ_bsum = is_nary(TermBase.Any.is_typ, "+"); + let is_grout = tiles => Aba.get_as(tiles) |> List.map(snd) |> List.for_all((==)(([" "], []))); @@ -134,12 +111,6 @@ let is_rules = ((ts, kids): tiles): option(Aba.t(UPat.t, UExp.t)) => { Aba.mk(ps, clauses); }; -// let have_sort = (tms: list(any)) => -// tms -// |> List.map( - -// ) - let ids_of_tiles = (tiles: tiles) => List.map(fst, Aba.get_as(tiles)); let ids = fun @@ -175,9 +146,17 @@ let return_dark_hole = (~ids=[], s) => { hole; }; +let parse_sum_term: UTyp.t => UTyp.variant = + fun + | {term: Var(ctr), ids} => Variant(ctr, ids, None) + | {term: Ap({term: Var(ctr), ids: ids_ctr}, u), ids: ids_ap} => + Variant(ctr, ids_ctr @ ids_ap, Some(u)) + | t => BadEntry(t); + let rec go_s = (s: Sort.t, skel: Skel.t, seg: Segment.t): any => switch (s) { | Pat => Pat(pat(unsorted(skel, seg))) + | TPat => TPat(tpat(unsorted(skel, seg))) | Typ => Typ(typ(unsorted(skel, seg))) | Exp => Exp(exp(unsorted(skel, seg))) | Rul => Rul(rul(unsorted(skel, seg))) @@ -207,7 +186,6 @@ and exp = unsorted => { } and exp_term: unsorted => (UExp.term, list(Id.t)) = { let ret = (tm: UExp.term) => (tm, []); - let _unrecog = UExp.Invalid(UnrecognizedTerm); let hole = unsorted => Term.UExp.hole(kids_of_unsorted(unsorted)); fun | Op(tiles) as tm => @@ -219,10 +197,13 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { | ([t], []) when Form.is_empty_list(t) => ret(ListLit([])) | ([t], []) when Form.is_bool(t) => ret(Bool(bool_of_string(t))) | ([t], []) when Form.is_int(t) => ret(Int(int_of_string(t))) - | ([t], []) when Form.is_string(t) => ret(String(t)) + | ([t], []) when Form.is_string(t) => + let s = Re.Str.string_after(t, 1); + let s = Re.Str.string_before(s, String.length(s) - 1); + ret(String(s)); | ([t], []) when Form.is_float(t) => ret(Float(float_of_string(t))) | ([t], []) when Form.is_var(t) => ret(Var(t)) - | ([t], []) when Form.is_tag(t) => ret(Tag(t)) + | ([t], []) when Form.is_ctr(t) => ret(Constructor(t)) | (["(", ")"], [Exp(body)]) => ret(Parens(body)) | (["[", "]"], [Exp(body)]) => switch (body) { @@ -234,6 +215,7 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { Match(scrut, rules), ids, ) + | ([t], []) when t != " " => ret(Invalid(t)) | _ => ret(hole(tm)) } | _ => ret(hole(tm)) @@ -246,6 +228,8 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { | (["-"], []) => UnOp(Int(Minus), r) | (["fun", "->"], [Pat(pat)]) => Fun(pat, r) | (["let", "=", "in"], [Pat(pat), Exp(def)]) => Let(pat, def, r) + | (["type", "=", "in"], [TPat(tpat), Typ(def)]) => + TyAlias(tpat, def, r) | (["if", "then", "else"], [Exp(cond), Exp(conseq)]) => If(cond, conseq, r) | _ => hole(tm) @@ -313,7 +297,6 @@ and pat = unsorted => { } and pat_term: unsorted => (UPat.term, list(Id.t)) = { let ret = (term: UPat.term) => (term, []); - let _unrecog = UPat.Invalid(UnrecognizedTerm); let hole = unsorted => Term.UPat.hole(kids_of_unsorted(unsorted)); fun | Op(tiles) as tm => @@ -326,10 +309,14 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { | ([t], []) when Form.is_bool(t) => Bool(bool_of_string(t)) | ([t], []) when Form.is_float(t) => Float(float_of_string(t)) | ([t], []) when Form.is_int(t) => Int(int_of_string(t)) - | ([t], []) when Form.is_string(t) => String(t) + | ([t], []) when Form.is_string(t) => + let s = Re.Str.string_after(t, 1); + let s = Re.Str.string_before(s, String.length(s) - 1); + String(s); | ([t], []) when Form.is_var(t) => Var(t) | ([t], []) when Form.is_wild(t) => Wild - | ([t], []) when Form.is_tag(t) => Tag(t) + | ([t], []) when Form.is_ctr(t) => Constructor(t) + | ([t], []) when t != " " => Invalid(t) | (["(", ")"], [Pat(body)]) => Parens(body) | (["[", "]"], [Pat(body)]) => switch (body) { @@ -369,43 +356,90 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { } | tm => ret(hole(tm)); } - and typ = unsorted => { - let term = typ_term(unsorted); - let ids = ids(unsorted); + let (term, inner_ids) = typ_term(unsorted); + let ids = ids(unsorted) @ inner_ids; return(ty => Typ(ty), ids, {ids, term}); } -and typ_term: unsorted => UTyp.term = { - let _unrecog = UTyp.Invalid(UnrecognizedTerm); +and typ_term: unsorted => (UTyp.term, list(Id.t)) = { + let ret = (term: UTyp.term) => (term, []); let hole = unsorted => Term.UTyp.hole(kids_of_unsorted(unsorted)); fun | Op(tiles) as tm => switch (tiles) { | ([(_id, tile)], []) => - switch (tile) { - | ([t], []) when Form.is_empty_tuple(t) => Tuple([]) - | (["Bool"], []) => Bool - | (["Int"], []) => Int - | (["Float"], []) => Float - | (["String"], []) => String - | ([t], []) when Form.is_typ_var(t) => Var(t) - | (["(", ")"], [Typ(body)]) => Parens(body) - | (["[", "]"], [Typ(body)]) => List(body) - | _ => hole(tm) - } - | _ => hole(tm) + ret( + switch (tile) { + | ([t], []) when Form.is_empty_tuple(t) => Tuple([]) + | (["Bool"], []) => Bool + | (["Int"], []) => Int + | (["Float"], []) => Float + | (["String"], []) => String + | ([t], []) when Form.is_typ_var(t) => Var(t) + | (["(", ")"], [Typ(body)]) => Parens(body) + | (["[", "]"], [Typ(body)]) => List(body) + | ([t], []) when t != " " => Invalid(t) + | _ => hole(tm) + }, + ) + | _ => ret(hole(tm)) + } + | Post(Typ(t), tiles) as tm => + switch (tiles) { + | ([(_, (["(", ")"], [Typ(typ)]))], []) => ret(Ap(t, typ)) + | _ => ret(hole(tm)) + } + | Pre(tiles, Typ({term: Sum(t0), ids})) as tm => + /* Case for leading prefix + preceeding a sum */ + switch (tiles) { + | ([(_, (["+"], []))], []) => (Sum(t0), ids) + | _ => ret(hole(tm)) + } + | Pre(tiles, Typ(t)) as tm => + switch (tiles) { + | ([(_, (["+"], []))], []) => ret(Sum([parse_sum_term(t)])) + | _ => ret(hole(tm)) + } + | Bin(Typ(t1), tiles, Typ(t2)) as tm when is_typ_bsum(tiles) != None => + switch (is_typ_bsum(tiles)) { + | Some(between_kids) => + ret(Sum(List.map(parse_sum_term, [t1] @ between_kids @ [t2]))) + | None => ret(hole(tm)) } - | (Pre(_) | Post(_)) as tm => hole(tm) | Bin(Typ(l), tiles, Typ(r)) as tm => switch (is_tuple_typ(tiles)) { - | Some(between_kids) => Tuple([l] @ between_kids @ [r]) + | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) | None => switch (tiles) { - | ([(_id, (["->"], []))], []) => Arrow(l, r) - | _ => hole(tm) + | ([(_id, (["->"], []))], []) => ret(Arrow(l, r)) + | _ => ret(hole(tm)) } } - | tm => hole(tm); + | tm => ret(hole(tm)); +} +and tpat = unsorted => { + let term = tpat_term(unsorted); + let ids = ids(unsorted); + return(ty => TPat(ty), ids, {ids, term}); +} +and tpat_term: unsorted => UTPat.term = { + let ret = (term: UTPat.term) => term; + let hole = unsorted => Term.UTPat.hole(kids_of_unsorted(unsorted)); + fun + | Op(tiles) as tm => + switch (tiles) { + | ([(_id, tile)], []) => + ret( + switch (tile) { + | ([t], []) when Form.is_typ_var(t) => Var(t) + | ([t], []) when t != " " => Invalid(t) + | _ => hole(tm) + }, + ) + | _ => ret(hole(tm)) + } + | (Pre(_) | Post(_)) as tm => ret(hole(tm)) + | tm => ret(hole(tm)); } // and rul = unsorted => { diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re new file mode 100644 index 0000000000..cb3a7ab8c9 --- /dev/null +++ b/src/haz3lcore/statics/Mode.re @@ -0,0 +1,126 @@ +open Util; +open OptUtil.Syntax; + +/* MODE.re + + This module defines the (analytic) type expectation imposed by a term's + syntactic context, in particular its immediate parent. The most common + cases are either Syn (no type expectation), or Ana (some type expectation). + + A term's MODE is used in combination with that term's SELF (Self.re) by + to determine that term's STATUS (Info.re), which dictates whether or not + it is placed in a hole, and hence its FIXED TYPE (Info.re). + + (It is conjectured [citation needed] that the Syn mode is functionally + indistinguishable from Ana(Unknown(SynSwitch)), and that this type is + thus vestigial.) + + */ + +[@deriving (show({with_path: false}), sexp, yojson)] +type t = + | SynFun /* Used only in function position of applications */ + | Syn + | Ana(Typ.t); + +let ana: Typ.t => t = ty => Ana(ty); + +/* The expected type imposed by a mode */ +let ty_of: t => Typ.t = + fun + | Ana(ty) => ty + | Syn => Unknown(SynSwitch) + | SynFun => Arrow(Unknown(SynSwitch), Unknown(SynSwitch)); + +let of_arrow = (ctx: Ctx.t, mode: t): (t, t) => + switch (mode) { + | Syn + | SynFun => (Syn, Syn) + | Ana(ty) => + ty + |> Typ.weak_head_normalize(ctx) + |> Typ.matched_arrow + |> TupleUtil.map2(ana) + }; + +let of_prod = (ctx: Ctx.t, mode: t, length): list(t) => + switch (mode) { + | Syn + | SynFun => List.init(length, _ => Syn) + | Ana(ty) => + ty + |> Typ.weak_head_normalize(ctx) + |> Typ.matched_prod(length) + |> List.map(ana) + }; + +let matched_list_normalize = (ctx: Ctx.t, ty: Typ.t): Typ.t => + ty |> Typ.weak_head_normalize(ctx) |> Typ.matched_list; + +let of_cons_hd = (ctx: Ctx.t, mode: t): t => + switch (mode) { + | Syn + | SynFun => Syn + | Ana(ty) => Ana(matched_list_normalize(ctx, ty)) + }; + +let of_cons_tl = (ctx: Ctx.t, mode: t, hd_ty: Typ.t): t => + switch (mode) { + | Syn + | SynFun => Ana(List(hd_ty)) + | Ana(ty) => Ana(List(matched_list_normalize(ctx, ty))) + }; + +let of_list = (ctx: Ctx.t, mode: t): t => + switch (mode) { + | Syn + | SynFun => Syn + | Ana(ty) => Ana(matched_list_normalize(ctx, ty)) + }; + +let of_list_lit = (ctx: Ctx.t, length, mode: t): list(t) => + List.init(length, _ => of_list(ctx, mode)); + +let ctr_ana_typ = (ctx: Ctx.t, mode: t, ctr: Constructor.t): option(Typ.t) => { + /* If a ctr is being analyzed against (an arrow type returning) + a sum type having that ctr as a variant, we consider the + ctr's type to be determined by the sum type */ + switch (mode) { + | Ana(Arrow(_, ty_ana)) + | Ana(ty_ana) => + let* ctrs = Typ.get_sum_constructors(ctx, ty_ana); + let+ (_, ty_entry) = Typ.sum_entry(ctr, ctrs); + switch (ty_entry) { + | None => ty_ana + | Some(ty_in) => Arrow(ty_in, ty_ana) + }; + | _ => None + }; +}; + +let of_ctr_in_ap = (ctx: Ctx.t, mode: t, ctr: Constructor.t): option(t) => + switch (ctr_ana_typ(ctx, mode, ctr)) { + | Some(Arrow(_) as ty_ana) => Some(Ana(ty_ana)) + | Some(ty_ana) => + /* Consider for example "let _ : +Yo = Yo("lol") in..." + Here, the 'Yo' constructor should be in a hole, as it + is nullary but used as unary; we reflect this by analyzing + against an arrow type. Since we can't guess at what the + parameter type might have be, we use Unknown. */ + Some(Ana(Arrow(Unknown(Internal), ty_ana))) + | None => None + }; + +let of_ap = (ctx, mode, ctr: option(Constructor.t)): t => + /* If a ctr application is being analyzed against a sum type for + which that ctr is a variant, then we consider the ctr to be in + analytic mode against an arrow returning that sum type; otherwise + we use the typical mode for function applications */ + switch (ctr) { + | Some(name) => + switch (of_ctr_in_ap(ctx, mode, name)) { + | Some(mode) => mode + | _ => SynFun + } + | None => SynFun + }; diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re new file mode 100644 index 0000000000..611c4b1455 --- /dev/null +++ b/src/haz3lcore/statics/Self.re @@ -0,0 +1,90 @@ +open Sexplib.Std; + +/* SELF.re + + This module defines the SELF data structure, which represents + the synthetic type information derivable from a term independent + of the type expectation (i.e. MODE) of its syntactic context. This + synethetic information is not entirely independent, in that it still + uses the typing context passed down from the syntactic context. + + A term which from which a type can be derived in isolation, that is, + that has a valid synthetic typing judgement, will generally have a SELF + of Just(some_type). (The one current exception are the constructors of labelled + sum types, which are handled specially as their synthetic type + may be 'overwritten' by the analytic expectation) + + The other cases all represent states for which no single type can be + derived, such as syntactic errors, or branching constructs which may + have inconsistent types. + + */ + +[@deriving (show({with_path: false}), sexp, yojson)] +type t = + | Just(Typ.t) /* Just a regular type */ + | NoJoin(list(Typ.source)) /* Inconsistent types for e.g match, listlits */ + | BadToken(Token.t) /* Invalid expression token, treated as hole */ + | IsMulti /* Multihole, treated as hole */ + | IsConstructor({ + name: Constructor.t, + syn_ty: option(Typ.t), + }); /* Constructors have special ana logic */ + +/* Expressions can also be free variables */ +[@deriving (show({with_path: false}), sexp, yojson)] +type exp = + | Free(Var.t) + | Common(t); + +[@deriving (show({with_path: false}), sexp, yojson)] +type pat = + | Common(t); + +/* What the type would be if the position had been + synthetic, so no hole fixing. Returns none if + there's no applicable synthetic rule. */ +let typ_of: (Ctx.t, t) => option(Typ.t) = + _ctx => + fun + | Just(typ) => Some(typ) + | IsConstructor({syn_ty, _}) => syn_ty + | BadToken(_) + | IsMulti + | NoJoin(_) => None; + +let typ_of_exp: (Ctx.t, exp) => option(Typ.t) = + ctx => + fun + | Free(_) => None + | Common(self) => typ_of(ctx, self); + +/* The self of a var depends on the ctx; if the + lookup fails, it is a free variable */ +let of_exp_var = (ctx: Ctx.t, name: Var.t): exp => + switch (Ctx.lookup_var(ctx, name)) { + | None => Free(name) + | Some(var) => Common(Just(var.typ)) + }; + +/* The self of a ctr depends on the ctx, but a + lookup failure doesn't necessarily means its + free; it may be given a type analytically */ +let of_ctr = (ctx: Ctx.t, name: Constructor.t): t => + IsConstructor({ + name, + syn_ty: + switch (Ctx.lookup_ctr(ctx, name)) { + | None => None + | Some({typ, _}) => Some(typ) + }, + }); + +/* The self assigned to things like cases and list literals + which can have internal type inconsistencies. */ +let join = + (wrap: Typ.t => Typ.t, tys: list(Typ.t), ids: list(Id.t), ctx: Ctx.t): t => + switch (Typ.join_all(ctx, tys)) { + | None => NoJoin(List.map2((id, ty) => Typ.{id, ty}, ids, tys)) + | Some(ty) => Just(wrap(ty)) + }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 6814b19550..11705afad4 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -1,325 +1,155 @@ -open Sexplib.Std; -open Util; +open Term; -/* STATICS +/* STATICS.re - This module determines the statics semantics of the language. - It takes a term and returns a map which associates the unique - ids of each term to an 'info' data structure which reflects that - term's statics. The statics collected depend on the term's sort, - but every term has a syntactic class (The cls types from Term), - except Invalid terms which Term could not parse. + This module determines the statics semantics of a program. + It makes use of the following modules: - The map generated by this module is intended to be generated once - from a given term and then reused anywhere there is logic which - depends on static information. - */ + INFO.re: Defines the Info.t type which is used to represent the + static STATUS of a term. This STATUS can be either OK or ERROR, + and is determined by reconcilling two sources of typing information, + the MODE and the SELF. -/* Expressions are assigned a mode (reflecting the static expectations - if any of their syntactic parent), a self (reflecting what their - statics would be in isolation), a context (variables in scope), and - free (variables occuring free in the expression. */ -[@deriving (show({with_path: false}), sexp, yojson)] -type info_exp = { - cls: Term.UExp.cls, - term: Term.UExp.t, - mode: Typ.mode, - self: Typ.self, - ctx: Ctx.t, - free: Ctx.co, - // TODO: add derived attributes like error_status and typ_after_fix? -}; - -/* Patterns are assigned a mode (reflecting the static expectations - if any of their syntactic parent) and a self (reflecting what their - statics would be in isolation), a context (variables in scope) */ -[@deriving (show({with_path: false}), sexp, yojson)] -type info_pat = { - cls: Term.UPat.cls, - term: Term.UPat.t, - mode: Typ.mode, - self: Typ.self, - ctx: Ctx.t // TODO: detect in-pattern shadowing -}; - -/* (Syntactic) Types are assigned their corresponding semantic type. */ -[@deriving (show({with_path: false}), sexp, yojson)] -type info_typ = { - cls: Term.UTyp.cls, - term: Term.UTyp.t, - self: Typ.self, -}; - -[@deriving (show({with_path: false}), sexp, yojson)] -type info_rul = { - cls: Term.URul.cls, - term: Term.UExp.t, -}; - -/* The Info aka Cursorinfo assigned to each subterm. */ -[@deriving (show({with_path: false}), sexp, yojson)] -type t = - | Invalid(TermBase.parse_flag) - | InfoExp(info_exp) - | InfoPat(info_pat) - | InfoTyp(info_typ) - | InfoRul(info_rul); - -/* The InfoMap collating all info for a composite term */ -type map = Id.Map.t(t); + MODE.re: Defines the Mode.t type which is used to represent the + typing expectations imposed by a term's ancestors. -let terms = (map: map): Id.Map.t(Term.any) => - map - |> Id.Map.filter_map(_ => - fun - | Invalid(_) => None - | InfoExp({term, _}) => Some(Term.Exp(term)) - | InfoPat({term, _}) => Some(Term.Pat(term)) - | InfoTyp({term, _}) => Some(Term.Typ(term)) - | InfoRul({term, _}) => Some(Term.Exp(term)) - ); + SELF.re: Define the Self.t type which is used to represent the + type information derivable from the term itself. -/* Static error classes */ -[@deriving (show({with_path: false}), sexp, yojson)] -type error = - | Free(Typ.free_errors) - | Multi - | NoFun(Typ.t) - | SynInconsistentBranches(list(Typ.t)) - | TypeInconsistent(Typ.t, Typ.t); + The point of STATICS.re itself is to derive a map between each + term's unique id and that term's static INFO. The below functions + are intended mostly as infrastructure: The point is to define a + traversal through the syntax tree which, for each term, passes + down the MODE, passes up the SELF, calculates the INFO, and adds + it to the map. -/* Statics non-error classes */ -[@deriving (show({with_path: false}), sexp, yojson)] -type happy = - | SynConsistent(Typ.t) - | AnaConsistent(Typ.t, Typ.t, Typ.t) //ana, syn, join - | AnaInternalInconsistent(Typ.t, list(Typ.t)) // ana, branches - | AnaExternalInconsistent(Typ.t, Typ.t); // ana, syn + The architectural intention here is that most type-manipulation + logic is defined in INFO, MODE, and SELF, and the STATICS module + itself is dedicated to the piping necessary to (A) introduce and + (B) propagate the necessary information through the syntax tree. -/* The error status which 'wraps' each term. */ -[@deriving (show({with_path: false}), sexp, yojson)] -type error_status = - | InHole(error) - | NotInHole(happy); + */ -/* Determines whether an expression or pattern is in an error hole, - depending on the mode, which represents the expectations of the - surrounding syntactic context, and the self which represents the - makeup of the expression / pattern itself. */ -let error_status = (mode: Typ.mode, self: Typ.self): error_status => - switch (mode, self) { - | (SynFun, Just(ty)) => - switch (Typ.join(Arrow(Unknown(Internal), Unknown(Internal)), ty)) { - | None => InHole(NoFun(ty)) - | Some(_) => NotInHole(SynConsistent(ty)) - } - | (SynFun, Joined(_wrap, tys_syn)) => - let tys_syn = Typ.source_tys(tys_syn); - switch (Typ.join_all(tys_syn)) { - | None => InHole(SynInconsistentBranches(tys_syn)) - | Some(ty_joined) => - switch ( - Typ.join(Arrow(Unknown(Internal), Unknown(Internal)), ty_joined) - ) { - | None => InHole(NoFun(ty_joined)) - | Some(_) => NotInHole(SynConsistent(ty_joined)) - } - }; - | (Syn | SynFun | Ana(_), Free(free_error)) => InHole(Free(free_error)) - | (Syn | SynFun | Ana(_), Multi) => - NotInHole(SynConsistent(Unknown(Internal))) - | (Syn, Just(ty)) => NotInHole(SynConsistent(ty)) - | (Syn, Joined(wrap, tys_syn)) => - let tys_syn = Typ.source_tys(tys_syn); - switch (Typ.join_all(tys_syn)) { - | None => InHole(SynInconsistentBranches(tys_syn)) - | Some(ty_joined) => NotInHole(SynConsistent(wrap(ty_joined))) - }; - | (Ana(ty_ana), Just(ty_syn)) => - switch (Typ.join(ty_ana, ty_syn)) { - | None => InHole(TypeInconsistent(ty_syn, ty_ana)) - | Some(ty_join) => NotInHole(AnaConsistent(ty_ana, ty_syn, ty_join)) - } - | (Ana(ty_ana), Joined(wrap, tys_syn)) => - // TODO: review logic of these cases - switch (Typ.join_all(Typ.source_tys(tys_syn))) { - | Some(ty_syn) => - let ty_syn = wrap(ty_syn); - switch (Typ.join(ty_syn, ty_ana)) { - | None => NotInHole(AnaExternalInconsistent(ty_ana, ty_syn)) - | Some(ty_join) => NotInHole(AnaConsistent(ty_syn, ty_ana, ty_join)) - }; - | None => - NotInHole(AnaInternalInconsistent(ty_ana, Typ.source_tys(tys_syn))) - } - }; +module Info = Info; -/* Determines whether any term is in an error hole. Currently types cannot - be in error, and Invalids (things to which Term was unable to assign a - parse) are always in error. The error status of expressions and patterns - are determined by error_status above. */ -let is_error = (ci: t): bool => { - switch (ci) { - | Invalid(Secondary) => false - | Invalid(_) => true - | InfoExp({mode, self, _}) - | InfoPat({mode, self, _}) => - switch (error_status(mode, self)) { - | InHole(_) => true - | NotInHole(_) => false - } - | InfoTyp({self, _}) => - switch (self) { - | Free(TypeVariable) => true - | _ => false - } - | InfoRul(_) => false //TODO - }; +module Map = { + [@deriving (show({with_path: false}), sexp, yojson)] + type t = Id.Map.t(Info.t); }; -/* Determined the type of an expression or pattern 'after hole wrapping'; - that is, all ill-typed terms are considered to be 'wrapped in - non-empty holes', i.e. assigned Unknown type. */ -let typ_after_fix = (mode: Typ.mode, self: Typ.self): Typ.t => - switch (error_status(mode, self)) { - | InHole(_) => Unknown(Internal) - | NotInHole(SynConsistent(t)) => t - | NotInHole(AnaConsistent(_, _, ty_join)) => ty_join - | NotInHole(AnaExternalInconsistent(ty_ana, _)) => ty_ana - | NotInHole(AnaInternalInconsistent(ty_ana, _)) => ty_ana - }; - -/* The type of an expression after hole wrapping */ -let exp_typ = (m: map, e: Term.UExp.t): Typ.t => - switch (Id.Map.find_opt(Term.UExp.rep_id(e), m)) { - | Some(InfoExp({mode, self, _})) => typ_after_fix(mode, self) - | Some(InfoPat(_) | InfoTyp(_) | InfoRul(_) | Invalid(_)) - | None => failwith(__LOC__ ++ ": XXX") - }; - -let exp_self_typ_id = (m: map, id): Typ.t => - switch (Id.Map.find_opt(id, m)) { - | Some(InfoExp({self, _})) => Typ.t_of_self(self) - | Some(InfoPat(_) | InfoTyp(_) | InfoRul(_) | Invalid(_)) - | None => failwith(__LOC__ ++ ": XXX") - }; - -let exp_self_typ = (m: map, e: Term.UExp.t): Typ.t => - exp_self_typ_id(m, Term.UExp.rep_id(e)); - -let exp_mode_id = (m: map, id): Typ.mode => - switch (Id.Map.find_opt(id, m)) { - | Some(InfoExp({mode, _})) => mode - | Some(InfoPat(_) | InfoTyp(_) | InfoRul(_) | Invalid(_)) - | None => failwith(__LOC__ ++ ": XXX") - }; - -let exp_mode = (m: map, e: Term.UExp.t): Typ.mode => - exp_mode_id(m, Term.UExp.rep_id(e)); - -/* The type of a pattern after hole wrapping */ -let pat_typ = (m: map, p: Term.UPat.t): Typ.t => - switch (Id.Map.find_opt(Term.UPat.rep_id(p), m)) { - | Some(InfoPat({mode, self, _})) => typ_after_fix(mode, self) - | Some(InfoExp(_) | InfoTyp(_) | InfoRul(_) | Invalid(_)) - | None => failwith(__LOC__ ++ ": XXX") - }; -let pat_self_typ = (m: map, p: Term.UPat.t): Typ.t => - switch (Id.Map.find_opt(Term.UPat.rep_id(p), m)) { - | Some(InfoPat({self, _})) => Typ.t_of_self(self) - | Some(InfoExp(_) | InfoTyp(_) | InfoRul(_) | Invalid(_)) - | None => failwith(__LOC__ ++ ": XXX") - }; - -let union_m = +let map_m = (f, xs, m: Map.t) => List.fold_left( - (m1, m2) => Id.Map.union((_, _, b) => Some(b), m1, m2), - Id.Map.empty, + ((xs, m), x) => f(x, m) |> (((x, m)) => (xs @ [x], m)), + ([], m), + xs, ); -let add_info = (ids, info: 'a, m: Ptmap.t('a)) => - ids - |> List.map(id => Id.Map.singleton(id, info)) - |> List.fold_left(Id.Map.disj_union, m); +let add_info = (ids: list(Id.t), info: Info.t, m: Map.t): Map.t => + ids |> List.fold_left((m, id) => Id.Map.add(id, info, m), m); let extend_let_def_ctx = - (ctx: Ctx.t, pat: Term.UPat.t, pat_ctx: Ctx.t, def: Term.UExp.t) => - if (Term.UPat.is_tuple_of_arrows(pat) - && Term.UExp.is_tuple_of_functions(def)) { - VarMap.concat(ctx, pat_ctx); + (ctx: Ctx.t, pat: UPat.t, pat_ctx: Ctx.t, def: UExp.t): Ctx.t => + if (UPat.is_tuple_of_arrows(pat) && UExp.is_tuple_of_functions(def)) { + pat_ctx; } else { ctx; }; -let typ_exp_binop_bin_int: Term.UExp.op_bin_int => Typ.t = +let typ_exp_binop_bin_int: UExp.op_bin_int => Typ.t = fun | (Plus | Minus | Times | Power | Divide) as _op => Int | (LessThan | GreaterThan | LessThanOrEqual | GreaterThanOrEqual | Equals) as _op => Bool; -let typ_exp_binop_bin_float: Term.UExp.op_bin_float => Typ.t = +let typ_exp_binop_bin_float: UExp.op_bin_float => Typ.t = fun | (Plus | Minus | Times | Power | Divide) as _op => Float | (LessThan | GreaterThan | LessThanOrEqual | GreaterThanOrEqual | Equals) as _op => Bool; -let typ_exp_binop_bin_string: Term.UExp.op_bin_string => Typ.t = +let typ_exp_binop_bin_string: UExp.op_bin_string => Typ.t = fun | Equals as _op => Bool; -let typ_exp_binop: Term.UExp.op_bin => (Typ.t, Typ.t, Typ.t) = +let typ_exp_binop: UExp.op_bin => (Typ.t, Typ.t, Typ.t) = fun | Bool(And | Or) => (Bool, Bool, Bool) | Int(op) => (Int, Int, typ_exp_binop_bin_int(op)) | Float(op) => (Float, Float, typ_exp_binop_bin_float(op)) | String(op) => (String, String, typ_exp_binop_bin_string(op)); -let typ_exp_unop: Term.UExp.op_un => (Typ.t, Typ.t) = +let typ_exp_unop: UExp.op_un => (Typ.t, Typ.t) = fun | Int(Minus) => (Int, Int); -let rec any_to_info_map = (~ctx: Ctx.t, any: Term.any): (Ctx.co, map) => +let rec any_to_info_map = + (~ctx: Ctx.t, ~ancestors, any: any, m: Map.t): (CoCtx.t, Map.t) => switch (any) { | Exp(e) => - let (_, co, map) = uexp_to_info_map(~ctx, e); - (co, map); + let (Info.{co_ctx, _}, m) = uexp_to_info_map(~ctx, ~ancestors, e, m); + (co_ctx, m); | Pat(p) => - let (_, _, map) = upat_to_info_map(~is_synswitch=false, ~ctx, p); - (VarMap.empty, map); - | Typ(ty) => - let (_, map) = utyp_to_info_map(ty); - (VarMap.empty, map); - // TODO(d) consider Rul case + let m = + upat_to_info_map(~is_synswitch=false, ~ancestors, ~ctx, p, m) |> snd; + (VarMap.empty, m); + | TPat(tp) => ( + VarMap.empty, + utpat_to_info_map(~ctx, ~ancestors, tp, m) |> snd, + ) + | Typ(ty) => ( + VarMap.empty, + utyp_to_info_map(~ctx, ~ancestors, ty, m) |> snd, + ) | Rul(_) | Nul () - | Any () => (VarMap.empty, Id.Map.empty) + | Any () => (VarMap.empty, m) } +and multi = (~ctx, ~ancestors, m, tms) => + List.fold_left( + ((co_ctxs, m), any) => { + let (co_ctx, m) = any_to_info_map(~ctx, ~ancestors, any, m); + (co_ctxs @ [co_ctx], m); + }, + ([], m), + tms, + ) and uexp_to_info_map = - (~ctx: Ctx.t, ~mode=Typ.Syn, {ids, term} as uexp: Term.UExp.t) - : (Typ.t, Ctx.co, map) => { + ( + ~ctx: Ctx.t, + ~mode=Mode.Syn, + ~ancestors, + {ids, term} as uexp: UExp.t, + m: Map.t, + ) + : (Info.exp, Map.t) => { /* Maybe switch mode to syn */ let mode = switch (mode) { - | Ana(Unknown(SynSwitch)) => Typ.Syn + | Ana(Unknown(SynSwitch)) => Mode.Syn | _ => mode }; - let cls = Term.UExp.cls_of_term(term); - let go = uexp_to_info_map(~ctx); - let add = (~self, ~free, m) => ( - typ_after_fix(mode, self), - free, - add_info(ids, InfoExp({cls, self, mode, ctx, free, term: uexp}), m), - ); - let atomic = self => add(~self, ~free=[], Id.Map.empty); + let add' = (~self, ~co_ctx, m) => { + let info = + Info.derived_exp(~uexp, ~ctx, ~mode, ~ancestors, ~self, ~co_ctx); + (info, add_info(ids, InfoExp(info), m)); + }; + let add = (~self, ~co_ctx, m) => add'(~self=Common(self), ~co_ctx, m); + let ancestors = [UExp.rep_id(uexp)] @ ancestors; + let go' = uexp_to_info_map(~ancestors); + let go = go'(~ctx); + let map_m_go = m => + List.fold_left2( + ((es, m), mode, e) => + go(~mode, e, m) |> (((e, m)) => (es @ [e], m)), + ([], m), + ); + let go_pat = upat_to_info_map(~ctx, ~ancestors); + let atomic = self => add(~self, ~co_ctx=CoCtx.empty, m); switch (term) { - | Invalid(msg) => ( - Unknown(Internal), - [], - add_info(ids, Invalid(msg), Id.Map.empty), - ) | MultiHole(tms) => - let (free, maps) = tms |> List.map(any_to_info_map(~ctx)) |> List.split; - add(~self=Multi, ~free=Ctx.union(free), union_m(maps)); + let (co_ctxs, m) = multi(~ctx, ~ancestors, m, tms); + add(~self=IsMulti, ~co_ctx=CoCtx.union(co_ctxs), m); + | Invalid(token) => atomic(BadToken(token)) | EmptyHole => atomic(Just(Unknown(Internal))) | Triv => atomic(Just(Prod([]))) | Bool(_) => atomic(Just(Bool)) @@ -328,192 +158,198 @@ and uexp_to_info_map = | String(_) => atomic(Just(String)) | ListLit([]) => atomic(Just(List(Unknown(Internal)))) | ListLit(es) => - let modes = List.init(List.length(es), _ => Typ.matched_list_mode(mode)); - let e_ids = List.map(Term.UExp.rep_id, es); - let infos = List.map2((e, mode) => go(~mode, e), es, modes); - let tys = List.map(((ty, _, _)) => ty, infos); - let self: Typ.self = - switch (Typ.join_all(tys)) { - | None => - Joined( - ty => List(ty), - List.map2((id, ty) => Typ.{id, ty}, e_ids, tys), - ) - | Some(ty) => Just(List(ty)) - }; - let free = Ctx.union(List.map(((_, f, _)) => f, infos)); - let m = union_m(List.map(((_, _, m)) => m, infos)); - add(~self, ~free, m); - | Cons(e1, e2) => - let mode_e = Typ.matched_list_mode(mode); - let (ty1, free1, m1) = go(~mode=mode_e, e1); - let (_, free2, m2) = go(~mode=Ana(List(ty1)), e2); + let ids = List.map(UExp.rep_id, es); + let modes = Mode.of_list_lit(ctx, List.length(es), mode); + let (es, m) = map_m_go(m, modes, es); + let tys = List.map(Info.exp_ty, es); + add( + ~self=Self.join(ty => List(ty), tys, ids, ctx), + ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es)), + m, + ); + | Cons(hd, tl) => + let (hd, m) = go(~mode=Mode.of_cons_hd(ctx, mode), hd, m); + let (tl, m) = go(~mode=Mode.of_cons_tl(ctx, mode, hd.ty), tl, m); add( - ~self=Just(List(ty1)), - ~free=Ctx.union([free1, free2]), - union_m([m1, m2]), + ~self=Just(List(hd.ty)), + ~co_ctx=CoCtx.union([hd.co_ctx, tl.co_ctx]), + m, ); | Var(name) => - switch (Ctx.lookup_var(ctx, name)) { - | None => atomic(Free(Variable)) - | Some(var) => - add( - ~self=Just(var.typ), - ~free=[(name, [{id: Term.UExp.rep_id(uexp), mode}])], - Id.Map.empty, - ) - } + add'( + ~self=Self.of_exp_var(ctx, name), + ~co_ctx=CoCtx.singleton(name, UExp.rep_id(uexp), Mode.ty_of(mode)), + m, + ) | Parens(e) => - let (ty, free, m) = go(~mode, e); - add(~self=Just(ty), ~free, m); + let (e, m) = go(~mode, e, m); + add(~self=Just(e.ty), ~co_ctx=e.co_ctx, m); | UnOp(op, e) => let (ty_in, ty_out) = typ_exp_unop(op); - let (_, free, m) = go(~mode=Ana(ty_in), e); - add(~self=Just(ty_out), ~free, m); + let (e, m) = go(~mode=Ana(ty_in), e, m); + add(~self=Just(ty_out), ~co_ctx=e.co_ctx, m); | BinOp(op, e1, e2) => let (ty1, ty2, ty_out) = typ_exp_binop(op); - let (_, free1, m1) = go(~mode=Ana(ty1), e1); - let (_, free2, m2) = go(~mode=Ana(ty2), e2); - add( - ~self=Just(ty_out), - ~free=Ctx.union([free1, free2]), - union_m([m1, m2]), - ); + let (e1, m) = go(~mode=Ana(ty1), e1, m); + let (e2, m) = go(~mode=Ana(ty2), e2, m); + add(~self=Just(ty_out), ~co_ctx=CoCtx.union([e1.co_ctx, e2.co_ctx]), m); | Tuple(es) => - let modes = Typ.matched_prod_mode(mode, List.length(es)); - let infos = List.map2((e, mode) => go(~mode, e), es, modes); - let free = Ctx.union(List.map(((_, f, _)) => f, infos)); - let self = Typ.Just(Prod(List.map(((ty, _, _)) => ty, infos))); - let m = union_m(List.map(((_, _, m)) => m, infos)); - add(~self, ~free, m); - | Tag(name) => - switch (BuiltinADTs.get_tag_typ(name)) { - | None => atomic(Free(Tag)) - | Some(typ) => atomic(Just(typ)) - } - | Test(test) => - let (_, free_test, m1) = go(~mode=Ana(Bool), test); - add(~self=Just(Prod([])), ~free=free_test, m1); - | If(cond, e1, e2) => - let (_, free_e0, m1) = go(~mode=Ana(Bool), cond); - let (ty_e1, free_e1, m2) = go(~mode, e1); - let (ty_e2, free_e2, m3) = go(~mode, e2); + let modes = Mode.of_prod(ctx, mode, List.length(es)); + let (es, m) = map_m_go(m, modes, es); add( - ~self= - Joined( - Fun.id, - [ - {id: Term.UExp.rep_id(e1), ty: ty_e1}, - {id: Term.UExp.rep_id(e2), ty: ty_e2}, - ], - ), - ~free=Ctx.union([free_e0, free_e1, free_e2]), - union_m([m1, m2, m3]), + ~self=Just(Prod(List.map(Info.exp_ty, es))), + ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es)), + m, ); + | Test(e) => + let (e, m) = go(~mode=Ana(Bool), e, m); + add(~self=Just(Prod([])), ~co_ctx=e.co_ctx, m); | Seq(e1, e2) => - let (_, free1, m1) = go(~mode=Syn, e1); - let (ty2, free2, m2) = go(~mode, e2); - add( - ~self=Just(ty2), - ~free=Ctx.union([free1, free2]), - union_m([m1, m2]), - ); + let (e1, m) = go(~mode=Syn, e1, m); + let (e2, m) = go(~mode, e2, m); + add(~self=Just(e2.ty), ~co_ctx=CoCtx.union([e1.co_ctx, e2.co_ctx]), m); + | Constructor(ctr) => atomic(Self.of_ctr(ctx, ctr)) | Ap(fn, arg) => - /* Function position mode Ana(Hole->Hole) instead of Syn */ - let (ty_fn, free_fn, m_fn) = - uexp_to_info_map(~ctx, ~mode=Typ.ap_mode, fn); - let (ty_in, ty_out) = Typ.matched_arrow(ty_fn); - let (_, free_arg, m_arg) = - uexp_to_info_map(~ctx, ~mode=Ana(ty_in), arg); + let fn_mode = Mode.of_ap(ctx, mode, UExp.ctr_name(fn)); + let (fn, m) = go(~mode=fn_mode, fn, m); + let (ty_in, ty_out) = Typ.matched_arrow(fn.ty); + let (arg, m) = go(~mode=Ana(ty_in), arg, m); add( ~self=Just(ty_out), - ~free=Ctx.union([free_fn, free_arg]), - union_m([m_fn, m_arg]), + ~co_ctx=CoCtx.union([fn.co_ctx, arg.co_ctx]), + m, ); - | Fun(pat, body) => - let (mode_pat, mode_body) = Typ.matched_arrow_mode(mode); - let (ty_pat, ctx_pat, m_pat) = - upat_to_info_map(~is_synswitch=false, ~mode=mode_pat, pat); - let ctx_body = VarMap.concat(ctx, ctx_pat); - let (ty_body, free_body, m_body) = - uexp_to_info_map(~ctx=ctx_body, ~mode=mode_body, body); + | Fun(p, e) => + let (mode_pat, mode_body) = Mode.of_arrow(ctx, mode); + let (p, m) = go_pat(~is_synswitch=false, ~mode=mode_pat, p, m); + let (e, m) = go'(~ctx=p.ctx, ~mode=mode_body, e, m); add( - ~self=Just(Arrow(ty_pat, ty_body)), - ~free=Ctx.subtract_typ(ctx_pat, free_body), - union_m([m_pat, m_body]), + ~self=Just(Arrow(p.ty, e.ty)), + ~co_ctx=CoCtx.mk(ctx, p.ctx, e.co_ctx), + m, ); - | Let(pat, def, body) => - let (ty_pat, ctx_pat, _m_pat) = - upat_to_info_map(~is_synswitch=true, ~mode=Syn, pat); - let def_ctx = extend_let_def_ctx(ctx, pat, ctx_pat, def); - let (ty_def, free_def, m_def) = - uexp_to_info_map(~ctx=def_ctx, ~mode=Ana(ty_pat), def); + | Let(p, def, body) => + let (p_syn, _) = go_pat(~is_synswitch=true, ~mode=Syn, p, m); + let def_ctx = extend_let_def_ctx(ctx, p, p_syn.ctx, def); + let (def, m) = go'(~ctx=def_ctx, ~mode=Ana(p_syn.ty), def, m); /* Analyze pattern to incorporate def type into ctx */ - let (_, ctx_pat_ana, m_pat) = - upat_to_info_map(~is_synswitch=false, ~mode=Ana(ty_def), pat); - let ctx_body = VarMap.concat(ctx, ctx_pat_ana); - let (ty_body, free_body, m_body) = - uexp_to_info_map(~ctx=ctx_body, ~mode, body); + let (p_ana, m) = go_pat(~is_synswitch=false, ~mode=Ana(def.ty), p, m); + let (body, m) = go'(~ctx=p_ana.ctx, ~mode, body, m); + add( + ~self=Just(body.ty), + ~co_ctx= + CoCtx.union([def.co_ctx, CoCtx.mk(ctx, p_ana.ctx, body.co_ctx)]), + m, + ); + | If(e0, e1, e2) => + let branch_ids = List.map(UExp.rep_id, [e1, e2]); + let (cond, m) = go(~mode=Ana(Bool), e0, m); + let (cons, m) = go(~mode, e1, m); + let (alt, m) = go(~mode, e2, m); add( - ~self=Just(ty_body), - ~free=Ctx.union([free_def, Ctx.subtract_typ(ctx_pat_ana, free_body)]), - union_m([m_pat, m_def, m_body]), + ~self=Self.join(Fun.id, [cons.ty, alt.ty], branch_ids, ctx), + ~co_ctx=CoCtx.union([cond.co_ctx, cons.co_ctx, alt.co_ctx]), + m, ); | Match(scrut, rules) => - let (ty_scrut, free_scrut, m_scrut) = go(~mode=Syn, scrut); - let (pats, branches) = List.split(rules); - let pat_infos = - List.map( - upat_to_info_map(~is_synswitch=false, ~mode=Typ.Ana(ty_scrut)), - pats, - ); - let branch_infos = - List.map2( - (branch, (_, ctx_pat, _)) => - uexp_to_info_map(~ctx=VarMap.concat(ctx, ctx_pat), ~mode, branch), - branches, - pat_infos, - ); - let branch_sources = - List.map2( - (e: Term.UExp.t, (ty, _, _)) => Typ.{id: Term.UExp.rep_id(e), ty}, - branches, - branch_infos, + let (scrut, m) = go(~mode=Syn, scrut, m); + let (ps, es) = List.split(rules); + let branch_ids = List.map(UExp.rep_id, es); + let (ps, m) = + map_m(go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty)), ps, m); + let p_ctxs = List.map(Info.pat_ctx, ps); + let (es, m) = + List.fold_left2( + ((es, m), e, ctx) => + go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), + ([], m), + es, + p_ctxs, ); - let pat_ms = List.map(((_, _, m)) => m, pat_infos); - let branch_ms = List.map(((_, _, m)) => m, branch_infos); - let branch_frees = List.map(((_, free, _)) => free, branch_infos); - let self = Typ.Joined(Fun.id, branch_sources); - let free = Ctx.union([free_scrut] @ branch_frees); - add(~self, ~free, union_m([m_scrut] @ pat_ms @ branch_ms)); + let e_tys = List.map(Info.exp_ty, es); + let e_co_ctxs = + List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); + add( + ~self=Self.join(Fun.id, e_tys, branch_ids, ctx), + ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), + m, + ); + | TyAlias(typat, utyp, body) => + let m = utpat_to_info_map(~ctx, ~ancestors, typat, m) |> snd; + switch (typat.term) { + | Var(name) when !Ctx.shadows_typ(ctx, name) => + /* Currently we disallow all type shadowing */ + /* NOTE(andrew): Currently, UTyp.to_typ returns Unknown(TypeHole) + for any type variable reference not in its ctx. So any free variables + in the definition won't be noticed. But we need to check for free + variables to decide whether to make a recursive type or not. So we + tentatively add an abtract type to the ctx, representing the + speculative rec parameter. */ + let (ty_def, ctx_def, ctx_body) = { + let ty_pre = UTyp.to_typ(Ctx.extend_dummy_tvar(ctx, name), utyp); + switch (utyp.term) { + | Sum(_) when List.mem(name, Typ.free_vars(ty_pre)) => + let ty_rec = Typ.Rec("α", Typ.subst(Var("α"), name, ty_pre)); + let ctx_def = + Ctx.extend_alias(ctx, name, UTPat.rep_id(typat), ty_rec); + (ty_rec, ctx_def, ctx_def); + | _ => + let ty = UTyp.to_typ(ctx, utyp); + (ty, ctx, Ctx.extend_alias(ctx, name, UTPat.rep_id(typat), ty)); + }; + }; + let ctx_body = + switch (Typ.get_sum_constructors(ctx, ty_def)) { + | Some(sm) => Ctx.add_ctrs(ctx_body, name, UTyp.rep_id(utyp), sm) + | None => ctx_body + }; + let (Info.{co_ctx, ty: ty_body, _}, m) = + go'(~ctx=ctx_body, ~mode, body, m); + /* Make sure types don't escape their scope */ + let ty_escape = Typ.subst(ty_def, name, ty_body); + let m = utyp_to_info_map(~ctx=ctx_def, ~ancestors, utyp, m) |> snd; + add(~self=Just(ty_escape), ~co_ctx, m); + | Var(_) + | Invalid(_) + | EmptyHole + | MultiHole(_) => + let (Info.{co_ctx, ty: ty_body, _}, m) = go'(~ctx, ~mode, body, m); + let m = utyp_to_info_map(~ctx, ~ancestors, utyp, m) |> snd; + add(~self=Just(ty_body), ~co_ctx, m); + }; }; } and upat_to_info_map = ( ~is_synswitch, - ~ctx=Ctx.empty, - ~mode: Typ.mode=Typ.Syn, - {ids, term} as upat: Term.UPat.t, + ~ctx, + ~ancestors: Info.ancestors, + ~mode: Mode.t=Mode.Syn, + {ids, term} as upat: UPat.t, + m: Map.t, ) - : (Typ.t, Ctx.t, map) => { - let upat_to_info_map = upat_to_info_map(~is_synswitch); + : (Info.pat, Map.t) => { + let add = (~self, ~ctx, m) => { + let info = + Info.derived_pat(~upat, ~ctx, ~mode, ~ancestors, ~self=Common(self)); + (info, add_info(ids, InfoPat(info), m)); + }; + let atomic = self => add(~self, ~ctx, m); + let ancestors = [UPat.rep_id(upat)] @ ancestors; + let go = upat_to_info_map(~is_synswitch, ~ancestors); let unknown = Typ.Unknown(is_synswitch ? SynSwitch : Internal); - let cls = Term.UPat.cls_of_term(term); - let add = (~self, ~ctx, m) => ( - typ_after_fix(mode, self), - ctx, - add_info(ids, InfoPat({cls, self, mode, ctx, term: upat}), m), - ); - let atomic = self => add(~self, ~ctx, Id.Map.empty); + let ctx_fold = (ctx: Ctx.t, m) => + List.fold_left2( + ((ctx, tys, m), e, mode) => + go(~ctx, ~mode, e, m) + |> (((info, m)) => (info.ctx, tys @ [info.ty], m)), + (ctx, [], m), + ); switch (term) { - | Invalid(msg) => ( - Unknown(Internal), - ctx, - add_info(ids, Invalid(msg), Id.Map.empty), - ) | MultiHole(tms) => - let (_, maps) = tms |> List.map(any_to_info_map(~ctx)) |> List.split; - add(~self=Multi, ~ctx, union_m(maps)); + let (_, m) = multi(~ctx, ~ancestors, m, tms); + add(~self=IsMulti, ~ctx, m); + | Invalid(token) => atomic(BadToken(token)) | EmptyHole => atomic(Just(unknown)) | Int(_) => atomic(Just(Int)) | Float(_) => atomic(Just(Float)) @@ -522,141 +358,160 @@ and upat_to_info_map = | String(_) => atomic(Just(String)) | ListLit([]) => atomic(Just(List(Unknown(Internal)))) | ListLit(ps) => - let modes = List.init(List.length(ps), _ => Typ.matched_list_mode(mode)); - let p_ids = List.map(Term.UPat.rep_id, ps); - let (ctx, infos) = - List.fold_left2( - ((ctx, infos), e, mode) => { - let (_, ctx, _) as info = upat_to_info_map(~ctx, ~mode, e); - (ctx, infos @ [info]); - }, - (ctx, []), - ps, - modes, - ); - let tys = List.map(((ty, _, _)) => ty, infos); - let self: Typ.self = - switch (Typ.join_all(tys)) { - | None => - Joined( - ty => List(ty), - List.map2((id, ty) => Typ.{id, ty}, p_ids, tys), - ) - | Some(ty) => Just(List(ty)) - }; - let info: t = InfoPat({cls, self, mode, ctx, term: upat}); - let m = union_m(List.map(((_, _, m)) => m, infos)); - /* Add an entry for the id of each comma tile */ - let m = List.fold_left((m, id) => Id.Map.add(id, info, m), m, ids); - (typ_after_fix(mode, self), ctx, m); + let modes = Mode.of_list_lit(ctx, List.length(ps), mode); + let (ctx, tys, m) = ctx_fold(ctx, m, ps, modes); + add( + ~self=Self.join(ty => List(ty), tys, List.map(UPat.rep_id, ps), ctx), + ~ctx, + m, + ); | Cons(hd, tl) => - let mode_e = Typ.matched_list_mode(mode); - let (ty1, ctx, m_hd) = upat_to_info_map(~ctx, ~mode=mode_e, hd); - let (_, ctx, m_tl) = upat_to_info_map(~ctx, ~mode=Ana(List(ty1)), tl); - add(~self=Just(List(ty1)), ~ctx, union_m([m_hd, m_tl])); - | Tag(name) => - switch (BuiltinADTs.get_tag_typ(name)) { - | None => atomic(Free(Tag)) - | Some(typ) => atomic(Just(typ)) - } + let (hd, m) = go(~ctx, ~mode=Mode.of_cons_hd(ctx, mode), hd, m); + let (tl, m) = + go(~ctx=hd.ctx, ~mode=Mode.of_cons_tl(ctx, mode, hd.ty), tl, m); + add(~self=Just(List(hd.ty)), ~ctx=tl.ctx, m); | Wild => atomic(Just(unknown)) | Var(name) => - let typ = typ_after_fix(mode, Just(Unknown(Internal))); - let entry = Ctx.VarEntry({name, id: Term.UPat.rep_id(upat), typ}); - add(~self=Just(unknown), ~ctx=Ctx.extend(entry, ctx), Id.Map.empty); + /* NOTE: The self type assigned to pattern variables (Unknown) + may be SynSwitch, but SynSwitch is never added to the context; + Unknown(Internal) is used in this case */ + let ctx_typ = + Info.fixed_typ_pat(ctx, mode, Common(Just(Unknown(Internal)))); + let entry = Ctx.VarEntry({name, id: UPat.rep_id(upat), typ: ctx_typ}); + add(~self=Just(unknown), ~ctx=Ctx.extend(ctx, entry), m); | Tuple(ps) => - let modes = Typ.matched_prod_mode(mode, List.length(ps)); - let (ctx, infos) = - List.fold_left2( - ((ctx, infos), e, mode) => { - let (_, ctx, _) as info = upat_to_info_map(~mode, ~ctx, e); - (ctx, infos @ [info]); - }, - (ctx, []), - ps, - modes, - ); - let self = Typ.Just(Prod(List.map(((ty, _, _)) => ty, infos))); - let m = union_m(List.map(((_, _, m)) => m, infos)); - add(~self, ~ctx, m); + let modes = Mode.of_prod(ctx, mode, List.length(ps)); + let (ctx, tys, m) = ctx_fold(ctx, m, ps, modes); + add(~self=Just(Prod(tys)), ~ctx, m); | Parens(p) => - let (ty, ctx, m) = upat_to_info_map(~ctx, ~mode, p); - add(~self=Just(ty), ~ctx, m); + let (p, m) = go(~ctx, ~mode, p, m); + add(~self=Just(p.ty), ~ctx=p.ctx, m); + | Constructor(ctr) => atomic(Self.of_ctr(ctx, ctr)) | Ap(fn, arg) => - /* Contructor application */ - /* Function position mode Ana(Hole->Hole) instead of Syn */ - let (ty_fn, ctx, m_fn) = upat_to_info_map(~ctx, ~mode=Typ.ap_mode, fn); - let (ty_in, ty_out) = Typ.matched_arrow(ty_fn); - let (_, ctx, m_arg) = upat_to_info_map(~ctx, ~mode=Ana(ty_in), arg); - add(~self=Just(ty_out), ~ctx, union_m([m_fn, m_arg])); - | TypeAnn(p, ty) => - let (ty_ann, m_typ) = utyp_to_info_map(ty); - let (_ty, ctx, m) = upat_to_info_map(~ctx, ~mode=Ana(ty_ann), p); - add(~self=Just(ty_ann), ~ctx, union_m([m, m_typ])); + let fn_mode = Mode.of_ap(ctx, mode, UPat.ctr_name(fn)); + let (fn, m) = go(~ctx, ~mode=fn_mode, fn, m); + let (ty_in, ty_out) = Typ.matched_arrow(fn.ty); + let (arg, m) = go(~ctx, ~mode=Ana(ty_in), arg, m); + add(~self=Just(ty_out), ~ctx=arg.ctx, m); + | TypeAnn(p, ann) => + let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); + let (p, m) = go(~ctx, ~mode=Ana(ann.ty), p, m); + add(~self=Just(ann.ty), ~ctx=p.ctx, m); }; } -and utyp_to_info_map = ({ids, term} as utyp: Term.UTyp.t): (Typ.t, map) => { - let cls = Term.UTyp.cls_of_term(term); - let ty = Term.utyp_to_ty(utyp); - let add = self => add_info(ids, InfoTyp({cls, self, term: utyp})); - let just = m => (ty, add(Just(ty), m)); - switch (term) { - | Invalid(msg) => ( - Unknown(Internal), - add_info(ids, Invalid(msg), Id.Map.empty), +and utyp_to_info_map = + ( + ~ctx, + ~expects=Info.TypeExpected, + ~ancestors, + {ids, term} as utyp: UTyp.t, + m: Map.t, ) + : (Info.typ, Map.t) => { + let add = m => { + let info = Info.derived_typ(~utyp, ~ctx, ~ancestors, ~expects); + (info, add_info(ids, InfoTyp(info), m)); + }; + let ancestors = [UTyp.rep_id(utyp)] @ ancestors; + let go' = utyp_to_info_map(~ctx, ~ancestors); + let go = go'(~expects=TypeExpected); + //TODO(andrew): make this return free, replacing Typ.free_vars + switch (term) { + | MultiHole(tms) => + let (_, m) = multi(~ctx, ~ancestors, m, tms); + add(m); + | Invalid(_) | EmptyHole | Int | Float | Bool - | String => just(Id.Map.empty) + | String => add(m) + | Var(_) + | Constructor(_) => + /* Names are resolved in Info.status_typ */ + add(m) | List(t) - | Parens(t) => - let (_, m) = utyp_to_info_map(t); - just(m); + | Parens(t) => add(go(t, m) |> snd) | Arrow(t1, t2) => - let (_, m_t1) = utyp_to_info_map(t1); - let (_, m_t2) = utyp_to_info_map(t2); - just(union_m([m_t1, m_t2])); + let m = go(t1, m) |> snd; + let m = go(t2, m) |> snd; + add(m); | Tuple(ts) => - let m = ts |> List.map(utyp_to_info_map) |> List.map(snd) |> union_m; - just(m); - | Var(name) => - switch (BuiltinADTs.is_typ_var(name)) { - | None => (Unknown(Internal), add(Free(TypeVariable), Id.Map.empty)) - | Some(_) => (Var(name), add(Just(Var(name)), Id.Map.empty)) - } + let m = map_m(go, ts, m) |> snd; + add(m); + | Ap(t1, t2) => + let ty_in = UTyp.to_typ(ctx, t2); + let t1_mode: Info.typ_expects = + switch (expects) { + | VariantExpected(m, sum_ty) => + ConstructorExpected(m, Arrow(ty_in, sum_ty)) + | _ => ConstructorExpected(Unique, Arrow(ty_in, Unknown(Internal))) + }; + let m = go'(~expects=t1_mode, t1, m) |> snd; + let m = go'(~expects=TypeExpected, t2, m) |> snd; + add(m); + | Sum(variants) => + let ty_sum = UTyp.to_typ(ctx, utyp); + let (m, _) = + List.fold_left( + variant_to_info_map(~ctx, ~ancestors, ~ty_sum), + (m, []), + variants, + ); + add(m); + }; +} +and utpat_to_info_map = + (~ctx, ~ancestors, {ids, term} as utpat: UTPat.t, m: Map.t) + : (Info.tpat, Map.t) => { + let add = m => { + let info = Info.derived_tpat(~utpat, ~ctx, ~ancestors); + (info, add_info(ids, InfoTPat(info), m)); + }; + let ancestors = [UTPat.rep_id(utpat)] @ ancestors; + switch (term) { | MultiHole(tms) => - // TODO thread ctx through to multihole terms once ctx is available - let (_, maps) = - tms |> List.map(any_to_info_map(~ctx=Ctx.empty)) |> List.split; - just(union_m(maps)); + let (_, m) = multi(~ctx, ~ancestors, m, tms); + add(m); + | Invalid(_) + | EmptyHole + | Var(_) => add(m) + }; +} +and variant_to_info_map = + (~ctx, ~ancestors, ~ty_sum, (m, ctrs), uty: UTyp.variant) => { + let go = expects => utyp_to_info_map(~ctx, ~ancestors, ~expects); + switch (uty) { + | BadEntry(uty) => + let m = go(VariantExpected(Unique, ty_sum), uty, m) |> snd; + (m, ctrs); + | Variant(ctr, ids, param) => + let m = + go( + ConstructorExpected( + List.mem(ctr, ctrs) ? Duplicate : Unique, + ty_sum, + ), + {term: Constructor(ctr), ids}, + m, + ) + |> snd; + let m = + switch (param) { + | Some(param_ty) => go(TypeExpected, param_ty, m) |> snd + | None => m + }; + (m, [ctr, ...ctrs]); }; }; let mk_map = - Core.Memo.general( - ~cache_size_bound=1000, - e => { - let (_, _, map) = - uexp_to_info_map(~ctx=Builtins.ctx(Builtins.Pervasives.builtins), e); - map; - }, - ); - -let get_binding_site = (id: Id.t, statics_map: map): option(Id.t) => { - open OptUtil.Syntax; - let* opt = Id.Map.find_opt(id, statics_map); - let* info_exp = - switch (opt) { - | InfoExp(info_exp) => Some(info_exp) - | _ => None - }; - - let+ entry = - switch (info_exp.term.term) { - | TermBase.UExp.Var(name) => Ctx.lookup_var(info_exp.ctx, name) - | _ => None - }; - entry.id; -}; + Core.Memo.general(~cache_size_bound=1000, e => { + uexp_to_info_map( + ~ctx=Builtins.ctx(Builtins.Pervasives.builtins), + ~ancestors=[], + e, + Id.Map.empty, + ) + |> snd + }); diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index 81297af417..377650975e 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -19,7 +19,6 @@ include TermBase.Any; type any = t; - module UTyp = { [@deriving (show({with_path: false}), sexp, yojson)] type cls = @@ -32,9 +31,12 @@ module UTyp = { | String | Arrow | Tuple + | Sum | List | Var - | Parens; + | Constructor + | Parens + | Ap; include TermBase.UTyp; @@ -61,23 +63,29 @@ module UTyp = { | List(_) => List | Arrow(_) => Arrow | Var(_) => Var + | Constructor(_) => Constructor | Tuple(_) => Tuple - | Parens(_) => Parens; + | Parens(_) => Parens + | Ap(_) => Ap + | Sum(_) => Sum; let show_cls: cls => string = fun - | Invalid => "Invalid Type" - | EmptyHole => "Empty Type Hole" - | MultiHole => "Multi Type Hole" + | Invalid => "Invalid type" + | MultiHole => "Broken type" + | EmptyHole => "Empty type hole" | Int | Float | String - | Bool => "Base Type" - | Var => "Type Variable" - | List => "List Type" - | Arrow => "Function Type" - | Tuple => "Product Type" - | Parens => "Parenthesized Type Term"; + | Bool => "Base type" + | Var => "Type variable" + | Constructor => "Sum constructor" + | List => "List type" + | Arrow => "Function type" + | Tuple => "Product type" + | Sum => "Sum type" + | Parens => "Parenthesized type" + | Ap => "Constructor application"; let rec is_arrow = (typ: t) => { switch (typ.term) { @@ -92,9 +100,89 @@ module UTyp = { | String | List(_) | Tuple(_) - | Var(_) => false + | Var(_) + | Constructor(_) + | Ap(_) + | Sum(_) => false }; }; + + /* Converts a syntactic type into a semantic type */ + let rec to_typ: (Ctx.t, t) => Typ.t = + (ctx, utyp) => + switch (utyp.term) { + | Invalid(_) + | MultiHole(_) => Unknown(Internal) + | EmptyHole => Unknown(TypeHole) + | Bool => Bool + | Int => Int + | Float => Float + | String => String + | Var(name) => + switch (Ctx.lookup_tvar(ctx, name)) { + | Some(_) => Var(name) + | None => Unknown(Free(name)) + } + | Arrow(u1, u2) => Arrow(to_typ(ctx, u1), to_typ(ctx, u2)) + | Tuple(us) => Prod(List.map(to_typ(ctx), us)) + | Sum(uts) => Sum(to_ctr_map(ctx, uts)) + | List(u) => List(to_typ(ctx, u)) + | Parens(u) => to_typ(ctx, u) + /* The below cases should occur only inside sums */ + | Constructor(_) + | Ap(_) => Unknown(Internal) + } + and to_variant: + (Ctx.t, variant) => option(ConstructorMap.binding(option(Typ.t))) = + ctx => + fun + | Variant(ctr, _, u) => Some((ctr, Option.map(to_typ(ctx), u))) + | BadEntry(_) => None + and to_ctr_map = (ctx: Ctx.t, uts: list(variant)): Typ.sum_map => { + List.fold_left( + (acc, ut) => + List.find_opt(((ctr, _)) => ctr == fst(ut), acc) == None + ? acc @ [ut] : acc, + [], + List.filter_map(to_variant(ctx), uts), + ); + }; +}; + +module UTPat = { + [@deriving (show({with_path: false}), sexp, yojson)] + type cls = + | Invalid + | EmptyHole + | MultiHole + | Var; + + include TermBase.UTPat; + + let rep_id = ({ids, _}) => { + assert(ids != []); + List.hd(ids); + }; + + let hole = (tms: list(any)) => + switch (tms) { + | [] => EmptyHole + | [_, ..._] => MultiHole(tms) + }; + + let cls_of_term: term => cls = + fun + | Invalid(_) => Invalid + | EmptyHole => EmptyHole + | MultiHole(_) => MultiHole + | Var(_) => Var; + + let show_cls: cls => string = + fun + | Invalid => "Invalid type alias" + | MultiHole => "Broken type alias" + | EmptyHole => "Empty type alias hole" + | Var => "Type alias"; }; module UPat = { @@ -110,7 +198,7 @@ module UPat = { | String | Triv | ListLit - | Tag + | Constructor | Cons | Var | Tuple @@ -143,7 +231,7 @@ module UPat = { | String(_) => String | Triv => Triv | ListLit(_) => ListLit - | Tag(_) => Tag + | Constructor(_) => Constructor | Cons(_) => Cons | Var(_) => Var | Tuple(_) => Tuple @@ -153,23 +241,23 @@ module UPat = { let show_cls: cls => string = fun - | Invalid => "Invalid Pattern" - | EmptyHole => "Empty Pattern Hole" - | MultiHole => "Multi Pattern Hole" - | Wild => "Wildcard Pattern" - | Int => "Integer Literal" - | Float => "Float Literal" - | Bool => "Boolean Literal" - | String => "String Literal" - | Triv => "Trivial Literal. Pathetic, really." - | ListLit => "List Literal Pattern" - | Tag => "Constructor Pattern" - | Cons => "List Cons" - | Var => "Pattern Variable" - | Tuple => "Tuple Pattern" - | Parens => "Parenthesized Pattern" - | Ap => "Constructor Application" - | TypeAnn => "Type Annotation"; + | Invalid => "Invalid pattern" + | MultiHole => "Broken pattern" + | EmptyHole => "Empty pattern hole" + | Wild => "Wildcard" + | Int => "Integer literal" + | Float => "Float literal" + | Bool => "Boolean literal" + | String => "String literal" + | Triv => "Trivial literal" + | ListLit => "List literal" + | Constructor => "Constructor" + | Cons => "Cons" + | Var => "New variable" + | Tuple => "Tuple" + | Parens => "Parenthesized pattern" + | Ap => "Constructor application" + | TypeAnn => "Annotation"; let rec is_var = (pat: t) => { switch (pat.term) { @@ -188,7 +276,7 @@ module UPat = { | ListLit(_) | Cons(_, _) | Tuple(_) - | Tag(_) + | Constructor(_) | Ap(_) => false }; }; @@ -210,7 +298,7 @@ module UPat = { | Cons(_, _) | Var(_) | Tuple(_) - | Tag(_) + | Constructor(_) | Ap(_) => false }; }; @@ -234,7 +322,7 @@ module UPat = { | Cons(_, _) | Var(_) | TypeAnn(_) - | Tag(_) + | Constructor(_) | Ap(_) => false } ); @@ -256,7 +344,7 @@ module UPat = { | ListLit(_) | Cons(_, _) | Tuple(_) - | Tag(_) + | Constructor(_) | Ap(_) => None }; }; @@ -283,7 +371,7 @@ module UPat = { | Cons(_, _) | Var(_) | Tuple(_) - | Tag(_) + | Constructor(_) | Ap(_) => None }; }; @@ -314,17 +402,50 @@ module UPat = { | Cons(_, _) | Var(_) | TypeAnn(_) - | Tag(_) + | Constructor(_) | Ap(_) => None } }; }; + + let ctr_name = (p: t): option(Constructor.t) => + switch (p.term) { + | Constructor(name) => Some(name) + | _ => None + }; }; module UExp = { include TermBase.UExp; - let hole = (tms: list(any)) => + [@deriving (show({with_path: false}), sexp, yojson)] + type cls = + | Invalid + | EmptyHole + | MultiHole + | Triv + | Bool + | Int + | Float + | String + | ListLit + | Constructor + | Fun + | Tuple + | Var + | Let + | TyAlias + | Ap + | If + | Seq + | Test + | Parens + | Cons + | UnOp(op_un) + | BinOp(op_bin) + | Match; + + let hole = (tms: list(any)): term => switch (tms) { | [] => EmptyHole | [_, ..._] => MultiHole(tms) @@ -346,11 +467,12 @@ module UExp = { | Float(_) => Float | String(_) => String | ListLit(_) => ListLit - | Tag(_) => Tag + | Constructor(_) => Constructor | Fun(_) => Fun | Tuple(_) => Tuple | Var(_) => Var | Let(_) => Let + | TyAlias(_) => TyAlias | Ap(_) => Ap | If(_) => If | Seq(_) => Seq @@ -413,29 +535,30 @@ module UExp = { let show_cls: cls => string = fun - | Invalid => "Invalid Expression" - | EmptyHole => "Empty Expression Hole" - | MultiHole => "Multi Expression Hole" - | Triv => "Trivial Literal. Pathetic, really." - | Bool => "Boolean Literal" - | Int => "Integer Literal" - | Float => "Float Literal" - | String => "String Literal" - | ListLit => "List Literal" - | Tag => "Constructor" - | Fun => "Function Literal" - | Tuple => "Tuple Literal" - | Var => "Variable Reference" - | Let => "Let Expression" - | Ap => "Function/Contructor Application" - | If => "If Expression" - | Seq => "Sequence Expression" - | Test => "Test (Effectful)" - | Parens => "Parenthesized Expression" + | Invalid => "Invalid expression" + | MultiHole => "Broken expression" + | EmptyHole => "Empty expression hole" + | Triv => "Trivial litera" + | Bool => "Boolean literal" + | Int => "Integer literal" + | Float => "Float literal" + | String => "String literal" + | ListLit => "List literal" + | Constructor => "Constructor" + | Fun => "Function literal" + | Tuple => "Tuple literal" + | Var => "Variable reference" + | Let => "Let expression" + | TyAlias => "Type Alias definition" + | Ap => "Application" + | If => "If expression" + | Seq => "Sequence expression" + | Test => "Test" + | Parens => "Parenthesized expression" | Cons => "Cons" | BinOp(op) => show_binop(op) | UnOp(op) => show_unop(op) - | Match => "Match Expression"; + | Match => "Case expression"; let rec is_fun = (e: t) => { switch (e.term) { @@ -453,6 +576,7 @@ module UExp = { | Tuple(_) | Var(_) | Let(_) + | TyAlias(_) | Ap(_) | If(_) | Seq(_) @@ -461,7 +585,7 @@ module UExp = { | UnOp(_) | BinOp(_) | Match(_) - | Tag(_) => false + | Constructor(_) => false }; }; @@ -483,6 +607,7 @@ module UExp = { | Fun(_) | Var(_) | Let(_) + | TyAlias(_) | Ap(_) | If(_) | Seq(_) @@ -491,28 +616,16 @@ module UExp = { | UnOp(_) | BinOp(_) | Match(_) - | Tag(_) => false + | Constructor(_) => false } ); -}; -/* Converts a syntactic type into a semantic type */ -let rec utyp_to_ty: UTyp.t => Typ.t = - utyp => - switch (utyp.term) { - | Invalid(_) - | MultiHole(_) => Unknown(Internal) - | EmptyHole => Unknown(TypeHole) - | Bool => Bool - | Int => Int - | Float => Float - | String => String - | Var(name) => Var(name) - | Arrow(u1, u2) => Arrow(utyp_to_ty(u1), utyp_to_ty(u2)) - | Tuple(us) => Prod(List.map(utyp_to_ty, us)) - | List(u) => List(utyp_to_ty(u)) - | Parens(u) => utyp_to_ty(u) + let ctr_name = (e: t): option(Constructor.t) => + switch (e.term) { + | Constructor(name) => Some(name) + | _ => None }; +}; // TODO(d): consider just folding this into UExp module URul = { @@ -543,11 +656,31 @@ module URul = { }; }; +module Cls = { + [@deriving (show({with_path: false}), sexp, yojson)] + type t = + | Exp(UExp.cls) + | Pat(UPat.cls) + | Typ(UTyp.cls) + | TPat(UTPat.cls) + | Rul(URul.cls); + + let show = (cls: t) => + switch (cls) { + | Exp(cls) => UExp.show_cls(cls) + | Pat(cls) => UPat.show_cls(cls) + | Typ(cls) => UTyp.show_cls(cls) + | TPat(cls) => UTPat.show_cls(cls) + | Rul(cls) => URul.show_cls(cls) + }; +}; + let rec ids = fun | Exp(tm) => tm.ids | Pat(tm) => tm.ids | Typ(tm) => tm.ids + | TPat(tm) => tm.ids | Rul(tm) => URul.ids(~any_ids=ids, tm) | Nul () | Any () => []; @@ -568,6 +701,7 @@ let rep_id = | Exp(tm) => UExp.rep_id(tm) | Pat(tm) => UPat.rep_id(tm) | Typ(tm) => UTyp.rep_id(tm) + | TPat(tm) => UTPat.rep_id(tm) | Rul(tm) => URul.rep_id(~any_ids=ids, tm) | Nul () | Any () => raise(Invalid_argument("Term.rep_id")); diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index b1e269a7dd..04d583e00d 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -1,37 +1,42 @@ open Sexplib.Std; -[@deriving (show({with_path: false}), sexp, yojson)] -type parse_flag = - | Secondary // Not really an error - | MalformedGrout // Should never happen - | UnrecognizedTerm // Reminder to add term to MakeTerm - | IncompleteTile; // Remove in future - -let show_parse_flag: parse_flag => string = - fun - | Secondary => "Secondary" - | MalformedGrout => "Malformed Grout" - | UnrecognizedTerm => "Unrecognized Term" - | IncompleteTile => "Incomplete Tile"; - module rec Any: { [@deriving (show({with_path: false}), sexp, yojson)] type t = | Exp(UExp.t) | Pat(UPat.t) | Typ(UTyp.t) + | TPat(UTPat.t) | Rul(URul.t) | Nul(unit) | Any(unit); + + let is_exp: t => option(UExp.t); + let is_pat: t => option(UPat.t); + let is_typ: t => option(UTyp.t); } = { [@deriving (show({with_path: false}), sexp, yojson)] type t = | Exp(UExp.t) | Pat(UPat.t) | Typ(UTyp.t) + | TPat(UTPat.t) | Rul(URul.t) | Nul(unit) | Any(unit); + + let is_exp: t => option(UExp.t) = + fun + | Exp(e) => Some(e) + | _ => None; + let is_pat: t => option(UPat.t) = + fun + | Pat(p) => Some(p) + | _ => None; + let is_typ: t => option(UTyp.t) = + fun + | Typ(t) => Some(t) + | _ => None; } and UExp: { [@deriving (show({with_path: false}), sexp, yojson)] @@ -84,35 +89,9 @@ and UExp: { | Bool(op_bin_bool) | String(op_bin_string); - [@deriving (show({with_path: false}), sexp, yojson)] - type cls = - | Invalid - | EmptyHole - | MultiHole - | Triv - | Bool - | Int - | Float - | String - | ListLit - | Tag - | Fun - | Tuple - | Var - | Let - | Ap - | If - | Seq - | Test - | Parens - | Cons - | UnOp(op_un) - | BinOp(op_bin) - | Match; - [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | EmptyHole | MultiHole(list(Any.t)) | Triv @@ -121,12 +100,12 @@ and UExp: { | Float(float) | String(string) | ListLit(list(t)) - | Tag(string) + | Constructor(string) | Fun(UPat.t, t) | Tuple(list(t)) - | Var(Token.t) + | Var(Var.t) | Let(UPat.t, t, t) - // Let_pat(UPat.t, t) + | TyAlias(UTPat.t, UTyp.t, t) | Ap(t, t) | If(t, t, t) | Seq(t, t) @@ -192,35 +171,9 @@ and UExp: { | Bool(op_bin_bool) | String(op_bin_string); - [@deriving (show({with_path: false}), sexp, yojson)] - type cls = - | Invalid - | EmptyHole - | MultiHole - | Triv - | Bool - | Int - | Float - | String - | ListLit - | Tag - | Fun - | Tuple - | Var - | Let - | Ap - | If - | Seq - | Test - | Parens - | Cons - | UnOp(op_un) - | BinOp(op_bin) - | Match; - [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | EmptyHole | MultiHole(list(Any.t)) | Triv @@ -229,12 +182,12 @@ and UExp: { | Float(float) | String(string) | ListLit(list(t)) - | Tag(string) + | Constructor(string) | Fun(UPat.t, t) | Tuple(list(t)) - | Var(Token.t) + | Var(Var.t) | Let(UPat.t, t, t) - // Let_pat(UPat.t, t) + | TyAlias(UTPat.t, UTyp.t, t) | Ap(t, t) | If(t, t, t) | Seq(t, t) @@ -253,7 +206,7 @@ and UExp: { and UPat: { [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | EmptyHole | MultiHole(list(Any.t)) | Wild @@ -263,9 +216,9 @@ and UPat: { | String(string) | Triv | ListLit(list(t)) - | Tag(string) + | Constructor(string) | Cons(t, t) - | Var(Token.t) + | Var(Var.t) | Tuple(list(t)) | Parens(t) | Ap(t, t) @@ -277,7 +230,7 @@ and UPat: { } = { [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | EmptyHole | MultiHole(list(Any.t)) | Wild @@ -287,9 +240,9 @@ and UPat: { | String(string) | Triv | ListLit(list(t)) - | Tag(string) + | Constructor(string) | Cons(t, t) - | Var(Token.t) + | Var(Var.t) | Tuple(list(t)) | Parens(t) | Ap(t, t) @@ -302,7 +255,7 @@ and UPat: { and UTyp: { [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | EmptyHole | MultiHole(list(Any.t)) | Int @@ -311,9 +264,15 @@ and UTyp: { | String | List(t) | Var(string) + | Constructor(string) | Arrow(t, t) | Tuple(list(t)) | Parens(t) + | Ap(t, t) + | Sum(list(variant)) + and variant = + | Variant(Constructor.t, list(Id.t), option(t)) + | BadEntry(t) and t = { ids: list(Id.t), term, @@ -321,7 +280,7 @@ and UTyp: { } = { [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | EmptyHole | MultiHole(list(Any.t)) | Int @@ -330,9 +289,38 @@ and UTyp: { | String | List(t) | Var(string) + | Constructor(string) | Arrow(t, t) | Tuple(list(t)) | Parens(t) + | Ap(t, t) + | Sum(list(variant)) + and variant = + | Variant(Constructor.t, list(Id.t), option(t)) + | BadEntry(t) + and t = { + ids: list(Id.t), + term, + }; +} +and UTPat: { + [@deriving (show({with_path: false}), sexp, yojson)] + type term = + | Invalid(string) + | EmptyHole + | MultiHole(list(Any.t)) + | Var(TypVar.t) + and t = { + ids: list(Id.t), + term, + }; +} = { + [@deriving (show({with_path: false}), sexp, yojson)] + type term = + | Invalid(string) + | EmptyHole + | MultiHole(list(Any.t)) + | Var(TypVar.t) and t = { ids: list(Id.t), term, @@ -341,7 +329,7 @@ and UTyp: { and URul: { [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | Hole(list(Any.t)) | Rules(UExp.t, list((UPat.t, UExp.t))) and t = { @@ -351,7 +339,7 @@ and URul: { } = { [@deriving (show({with_path: false}), sexp, yojson)] type term = - | Invalid(parse_flag) + | Invalid(string) | Hole(list(Any.t)) | Rules(UExp.t, list((UPat.t, UExp.t))) and t = { diff --git a/src/haz3lcore/statics/Typ.re b/src/haz3lcore/statics/Typ.re index e3a139aa13..3c34e25a60 100644 --- a/src/haz3lcore/statics/Typ.re +++ b/src/haz3lcore/statics/Typ.re @@ -1,246 +1 @@ -open Sexplib.Std; - -/* TYPE_PROVENANCE: From whence does an unknown type originate? - Is it generated from an unannotated pattern variable (SynSwitch), - a pattern variable annotated with a type hole (TypeHole), or - generated by an internal judgement (Internal)? */ -[@deriving (show({with_path: false}), sexp, yojson)] -type type_provenance = - | SynSwitch - | TypeHole - | Internal; - -/* TYP.T: Hazel types */ -[@deriving (show({with_path: false}), sexp, yojson)] -type t = - | Unknown(type_provenance) - | Int - | Float - | Bool - | String - | Var(string) - | List(t) - | Arrow(t, t) - | Sum(t, t) // unused - | Prod(list(t)); - -/* SOURCE: Hazel type annotated with a relevant source location. - Currently used to track match branches for inconsistent - branches errors, but could perhaps be used more broadly - for type debugging UI. */ -[@deriving (show({with_path: false}), sexp, yojson)] -type source = { - id: int, - ty: t, -}; - -[@deriving (show({with_path: false}), sexp, yojson)] -type free_errors = - | Variable - | Tag - | TypeVariable; - -/* SELF: The (synthetic) type information derivable from a term - in isolation, using the typing context but not the syntactic - context. This can either be Free (no type, in the case of - unbound/undefined names), Joined (a list of types, possibly - inconsistent, generated by branching forms like ifs, - matches, and list literals), or Just a regular type. */ -[@deriving (show({with_path: false}), sexp, yojson)] -type self = - | Just(t) - // TODO: make it so that joined applies only to inconsistent types; rename NoJoin - | Joined(t => t, list(source)) - | Multi - | Free(free_errors); - -/* MODE: The (analytic) type information derived from a term's - syntactic context. This can either Syn (no type expectation), - or Ana (a type expectation). It is conjectured [citation needed] - that the Syn mode is functionally indistinguishable from - Ana(Unknown(SynSwitch)), and that this type is thus vestigial. */ -[@deriving (show({with_path: false}), sexp, yojson)] -type mode = - | SynFun - | Syn - | Ana(t); - -/* Strip location information from a list of sources */ -let source_tys = List.map((source: source) => source.ty); - -/* How type provenance information should be collated when - joining unknown types. This probably requires more thought, - but right now TypeHole strictly predominates over Internal - which strictly predominates over SynSwitch. */ -let join_type_provenance = - (p1: type_provenance, p2: type_provenance): type_provenance => - switch (p1, p2) { - | (TypeHole, TypeHole | Internal | SynSwitch) - | (Internal | SynSwitch, TypeHole) => TypeHole - | (Internal, Internal | SynSwitch) - | (SynSwitch, Internal) => Internal - | (SynSwitch, SynSwitch) => SynSwitch - }; - -/* Lattice join on types. This is a LUB join in the hazel2 - sense in that any type dominates Unknown */ -let rec join = (ty1: t, ty2: t): option(t) => - switch (ty1, ty2) { - | (Unknown(p1), Unknown(p2)) => - Some(Unknown(join_type_provenance(p1, p2))) - | (Unknown(_), ty) - | (ty, Unknown(_)) => Some(ty) - | (Int, Int) => Some(Int) - | (Int, _) => None - | (Float, Float) => Some(Float) - | (Float, _) => None - | (Bool, Bool) => Some(Bool) - | (Bool, _) => None - | (String, String) => Some(String) - | (String, _) => None - | (Arrow(ty1_1, ty1_2), Arrow(ty2_1, ty2_2)) => - switch (join(ty1_1, ty2_1), join(ty1_2, ty2_2)) { - | (Some(ty1), Some(ty2)) => Some(Arrow(ty1, ty2)) - | _ => None - } - | (Arrow(_), _) => None - | (Prod(tys1), Prod(tys2)) => - if (List.length(tys1) != List.length(tys2)) { - None; - } else { - switch (List.map2(join, tys1, tys2) |> Util.OptUtil.sequence) { - | None => None - | Some(tys) => Some(Prod(tys)) - }; - } - | (Prod(_), _) => None - | (Sum(ty1_1, ty1_2), Sum(ty2_1, ty2_2)) => - switch (join(ty1_1, ty2_1), join(ty1_2, ty2_2)) { - | (Some(ty1), Some(ty2)) => Some(Sum(ty1, ty2)) - | _ => None - } - | (Sum(_), _) => None - | (List(ty_1), List(ty_2)) => - switch (join(ty_1, ty_2)) { - | Some(ty) => Some(List(ty)) - | None => None - } - | (List(_), _) => None - | (Var(n1), Var(n2)) when n1 == n2 => Some(ty1) - | (Var(_), _) => None - }; - -let join_all: list(t) => option(t) = - List.fold_left( - (acc, ty) => Util.OptUtil.and_then(join(ty), acc), - Some(Unknown(Internal)), - ); - -let join_or_fst = (ty: t, ty': t): t => - switch (join(ty, ty')) { - | None => ty - | Some(ty) => ty - }; - -let t_of_self = - fun - | Just(t) => t - | Joined(wrap, ss) => - switch (ss |> List.map(s => s.ty) |> join_all) { - | None => Unknown(Internal) - | Some(t) => wrap(t) - } - | Multi - | Free(_) => Unknown(Internal); - -/* MATCHED JUDGEMENTS: Note that matched judgements work - a bit different than hazel2 here since hole fixing is - implicit. Somebody should check that what I'm doing - here actually makes sense -Andrew */ - -let matched_arrow: t => (t, t) = - fun - | Arrow(ty_in, ty_out) => (ty_in, ty_out) - | Unknown(prov) => (Unknown(prov), Unknown(prov)) - | _ => (Unknown(Internal), Unknown(Internal)); - -let matched_arrow_mode: mode => (mode, mode) = - fun - | SynFun - | Syn => (Syn, Syn) - | Ana(ty) => { - let (ty_in, ty_out) = matched_arrow(ty); - (Ana(ty_in), Ana(ty_out)); - }; - -let matched_prod_mode = (mode: mode, length): list(mode) => - switch (mode) { - | Ana(Prod(ana_tys)) when List.length(ana_tys) == length => - List.map(ty => Ana(ty), ana_tys) - | Ana(Unknown(prod)) => List.init(length, _ => Ana(Unknown(prod))) - | _ => List.init(length, _ => Syn) - }; - -let matched_list: t => t = - fun - | List(ty) => ty - | Unknown(prov) => Unknown(prov) - | _ => Unknown(Internal); - -let matched_list_mode: mode => mode = - fun - | SynFun - | Syn => Syn - | Ana(ty) => Ana(matched_list(ty)); - -let ap_mode: mode = SynFun; - -/* Legacy code from HTyp */ - -let precedence_Prod = 1; -let precedence_Arrow = 2; -let precedence_Sum = 3; -let precedence_const = 4; -let precedence = (ty: t): int => - switch (ty) { - | Int - | Float - | Bool - | String - | Unknown(_) - | Var(_) - | Prod([]) - | List(_) => precedence_const - | Prod(_) => precedence_Prod - | Sum(_, _) => precedence_Sum - | Arrow(_, _) => precedence_Arrow - }; - -/* equality - At the moment, this coincides with default equality, - but this will change when polymorphic types are implemented */ -let rec eq = (t1, t2) => - switch (t1, t2) { - | (Int, Int) => true - | (Int, _) => false - | (Float, Float) => true - | (Float, _) => false - | (Bool, Bool) => true - | (Bool, _) => false - | (String, String) => true - | (String, _) => false - | (Unknown(_), Unknown(_)) => true - | (Unknown(_), _) => false - | (Arrow(t1_1, t1_2), Arrow(t2_1, t2_2)) => - eq(t1_1, t2_1) && eq(t1_2, t2_2) - | (Arrow(_), _) => false - | (Prod(tys1), Prod(tys2)) => - List.length(tys1) == List.length(tys2) && List.for_all2(eq, tys1, tys2) - | (Prod(_), _) => false - | (Sum(t1_1, t1_2), Sum(t2_1, t2_2)) => eq(t1_1, t2_1) && eq(t1_2, t2_2) - | (Sum(_), _) => false - | (List(t1), List(t2)) => eq(t1, t2) - | (List(_), _) => false - | (Var(n1), Var(n2)) => n1 == n2 - | (Var(_), _) => false - }; +include TypBase.Typ; diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re new file mode 100644 index 0000000000..775d177801 --- /dev/null +++ b/src/haz3lcore/statics/TypBase.re @@ -0,0 +1,606 @@ +open Sexplib.Std; +open Util; +open OptUtil.Syntax; + +module rec Typ: { + /* TYPE_PROVENANCE: From whence does an unknown type originate? + Is it generated from an unannotated pattern variable (SynSwitch), + a pattern variable annotated with a type hole (TypeHole), or + generated by an internal judgement (Internal)? */ + [@deriving (show({with_path: false}), sexp, yojson)] + type type_provenance = + | SynSwitch + | TypeHole + | Free(TypVar.t) + | Internal; + + /* TYP.T: Hazel types */ + [@deriving (show({with_path: false}), sexp, yojson)] + type t = + | Unknown(type_provenance) + | Int + | Float + | Bool + | String + | Var(TypVar.t) + | List(t) + | Arrow(t, t) + | Sum(sum_map) + | Prod(list(t)) + | Rec(TypVar.t, t) + and sum_map = ConstructorMap.t(option(t)); + + [@deriving (show({with_path: false}), sexp, yojson)] + type sum_entry = ConstructorMap.binding(option(t)); + + /* Hazel type annotated with a relevant source location. + Currently used to track match branches for inconsistent + branches errors, but could perhaps be used more broadly + for type debugging UI. */ + [@deriving (show({with_path: false}), sexp, yojson)] + type source = { + id: int, + ty: t, + }; + + let of_source: list(source) => list(t); + let join_type_provenance: + (type_provenance, type_provenance) => type_provenance; + let matched_arrow: t => (t, t); + let matched_prod: (int, t) => list(t); + let matched_cons: t => (t, t); + let matched_list: t => t; + let precedence_Prod: int; + let precedence_Arrow: int; + let precedence_Sum: int; + let precedence_const: int; + let precedence: t => int; + let subst: (t, TypVar.t, t) => t; + let unroll: t => t; + let eq: (t, t) => bool; + let free_vars: (~bound: list(Var.t)=?, t) => list(Var.t); + let join: (~resolve: bool=?, ~fix: bool, Ctx.t, t, t) => option(t); + let join_fix: (~resolve: bool=?, Ctx.t, t, t) => option(t); + let join_all: (Ctx.t, list(t)) => option(t); + let weak_head_normalize: (Ctx.t, t) => t; + let normalize: (Ctx.t, t) => t; + let sum_entry: (Constructor.t, sum_map) => option(sum_entry); + let get_sum_constructors: (Ctx.t, t) => option(sum_map); +} = { + [@deriving (show({with_path: false}), sexp, yojson)] + type type_provenance = + | SynSwitch + | TypeHole + | Free(TypVar.t) + | Internal; + + /* TYP.T: Hazel types */ + [@deriving (show({with_path: false}), sexp, yojson)] + type t = + | Unknown(type_provenance) + | Int + | Float + | Bool + | String + | Var(TypVar.t) + | List(t) + | Arrow(t, t) + | Sum(sum_map) + | Prod(list(t)) + | Rec(TypVar.t, t) + and sum_map = ConstructorMap.t(option(t)); + + [@deriving (show({with_path: false}), sexp, yojson)] + type sum_entry = ConstructorMap.binding(option(t)); + + [@deriving (show({with_path: false}), sexp, yojson)] + type source = { + id: int, + ty: t, + }; + + /* Strip location information from a list of sources */ + let of_source = List.map((source: source) => source.ty); + + /* How type provenance information should be collated when + joining unknown types. This probably requires more thought, + but right now TypeHole strictly predominates over Internal + which strictly predominates over SynSwitch. */ + let join_type_provenance = + (p1: type_provenance, p2: type_provenance): type_provenance => + switch (p1, p2) { + | (Free(tv1), Free(tv2)) when TypVar.eq(tv1, tv2) => Free(tv1) + | (Internal | Free(_), _) + | (_, Internal | Free(_)) => Internal + | (TypeHole, TypeHole | SynSwitch) + | (SynSwitch, TypeHole) => TypeHole + | (SynSwitch, SynSwitch) => SynSwitch + }; + + let matched_arrow: t => (t, t) = + fun + | Arrow(ty_in, ty_out) => (ty_in, ty_out) + | Unknown(SynSwitch) => (Unknown(SynSwitch), Unknown(SynSwitch)) + | _ => (Unknown(Internal), Unknown(Internal)); + + let matched_prod: (int, t) => list(t) = + length => + fun + | Prod(tys) when List.length(tys) == length => tys + | Unknown(SynSwitch) => List.init(length, _ => Unknown(SynSwitch)) + | _ => List.init(length, _ => Unknown(Internal)); + + let matched_cons: t => (t, t) = + fun + | List(ty) => (ty, List(ty)) + | Unknown(SynSwitch) => (Unknown(SynSwitch), List(Unknown(SynSwitch))) + | _ => (Unknown(Internal), List(Unknown(SynSwitch))); + + let matched_list: t => t = + fun + | List(ty) => ty + | Unknown(SynSwitch) => Unknown(SynSwitch) + | _ => Unknown(Internal); + + let precedence_Prod = 1; + let precedence_Arrow = 2; + let precedence_Sum = 3; + let precedence_const = 4; + let precedence = (ty: t): int => + switch (ty) { + | Int + | Float + | Bool + | String + | Unknown(_) + | Var(_) + | Rec(_) + | Sum(_) + | List(_) => precedence_const + | Prod(_) => precedence_Prod + | Arrow(_, _) => precedence_Arrow + }; + + let rec subst = (s: t, x: TypVar.t, ty: t) => { + switch (ty) { + | Int => Int + | Float => Float + | Bool => Bool + | String => String + | Unknown(prov) => Unknown(prov) + | Arrow(ty1, ty2) => Arrow(subst(s, x, ty1), subst(s, x, ty2)) + | Prod(tys) => Prod(List.map(subst(s, x), tys)) + | Sum(sm) => Sum(ConstructorMap.map(Option.map(subst(s, x)), sm)) + | Rec(y, ty) when TypVar.eq(x, y) => Rec(y, ty) + | Rec(y, ty) => Rec(y, subst(s, x, ty)) + | List(ty) => List(subst(s, x, ty)) + | Var(y) => TypVar.eq(x, y) ? s : Var(y) + }; + }; + + let unroll = (ty: t): t => + switch (ty) { + | Rec(x, ty_body) => subst(ty, x, ty_body) + | _ => ty + }; + + /* Type Equality: At the moment, this coincides with alpha equivalence, + but this will change when polymorphic types are implemented */ + let rec eq = (t1: t, t2: t): bool => { + switch (t1, t2) { + | (Rec(x1, t1), Rec(x2, t2)) => eq(t1, subst(Var(x1), x2, t2)) + | (Rec(_), _) => false + | (Int, Int) => true + | (Int, _) => false + | (Float, Float) => true + | (Float, _) => false + | (Bool, Bool) => true + | (Bool, _) => false + | (String, String) => true + | (String, _) => false + | (Unknown(_), Unknown(_)) => true + | (Unknown(_), _) => false + | (Arrow(t1, t2), Arrow(t1', t2')) => eq(t1, t1') && eq(t2, t2') + | (Arrow(_), _) => false + | (Prod(tys1), Prod(tys2)) => List.equal(eq, tys1, tys2) + | (Prod(_), _) => false + | (List(t1), List(t2)) => eq(t1, t2) + | (List(_), _) => false + | (Sum(sm1), Sum(sm2)) => + ConstructorMap.equal(Option.equal(eq), sm1, sm2) + | (Sum(_), _) => false + | (Var(n1), Var(n2)) => n1 == n2 + | (Var(_), _) => false + }; + }; + + let rec free_vars = (~bound=[], ty: t): list(Var.t) => + switch (ty) { + | Unknown(_) + | Int + | Float + | Bool + | String => [] + | Var(v) => List.mem(v, bound) ? [] : [v] + | List(ty) => free_vars(~bound, ty) + | Arrow(t1, t2) => free_vars(~bound, t1) @ free_vars(~bound, t2) + | Sum(sm) => + ListUtil.flat_map( + fun + | None => [] + | Some(typ) => free_vars(~bound, typ), + List.map(snd, sm), + ) + | Prod(tys) => ListUtil.flat_map(free_vars(~bound), tys) + | Rec(x, ty) => free_vars(~bound=[x, ...bound], ty) + }; + + /* Lattice join on types. This is a LUB join in the hazel2 + sense in that any type dominates Unknown. The optional + resolve parameter specifies whether, in the case of a type + variable and a succesful join, to return the resolved join type, + or to return the (first) type variable for readability */ + let rec join = + (~resolve=false, ~fix, ctx: Ctx.t, ty1: t, ty2: t): option(t) => { + let join' = join(~resolve, ~fix, ctx); + switch (ty1, ty2) { + | (_, Unknown(TypeHole | Free(_)) as ty) when fix => + /* NOTE(andrew): This is load bearing + for ensuring that function literals get appropriate + casts. Examples/Dynamics has regression tests */ + Some(ty) + | (Unknown(p1), Unknown(p2)) => + Some(Unknown(join_type_provenance(p1, p2))) + | (Unknown(_), ty) + | (ty, Unknown(_)) => Some(ty) + | (Var(n1), Var(n2)) => + if (n1 == n2) { + Some(Var(n1)); + } else { + let* ty1 = Ctx.lookup_alias(ctx, n1); + let* ty2 = Ctx.lookup_alias(ctx, n2); + let+ ty_join = join'(ty1, ty2); + !resolve && eq(ty1, ty_join) ? Var(n1) : ty_join; + } + | (Var(name), ty) + | (ty, Var(name)) => + let* ty_name = Ctx.lookup_alias(ctx, name); + let+ ty_join = join'(ty_name, ty); + !resolve && eq(ty_name, ty_join) ? Var(name) : ty_join; + /* Note: Ordering of Unknown, Var, and Rec above is load-bearing! */ + | (Rec(x1, ty1), Rec(x2, ty2)) => + /* TODO: + This code isn't fully correct, as we may be doing + substitution on open terms; if x1 occurs in ty2, + we should be substituting x1 for a fresh variable + in ty2. This is annoying, and should be obviated + by the forthcoming debruijn index implementation + */ + let ctx = Ctx.extend_dummy_tvar(ctx, x1); + let+ ty_body = + join(~resolve, ~fix, ctx, ty1, subst(Var(x1), x2, ty2)); + Rec(x1, ty_body); + | (Rec(_), _) => None + | (Int, Int) => Some(Int) + | (Int, _) => None + | (Float, Float) => Some(Float) + | (Float, _) => None + | (Bool, Bool) => Some(Bool) + | (Bool, _) => None + | (String, String) => Some(String) + | (String, _) => None + | (Arrow(ty1, ty2), Arrow(ty1', ty2')) => + let* ty1 = join'(ty1, ty1'); + let+ ty2 = join'(ty2, ty2'); + Arrow(ty1, ty2); + | (Arrow(_), _) => None + | (Prod(tys1), Prod(tys2)) => + let* tys = ListUtil.map2_opt(join', tys1, tys2); + let+ tys = OptUtil.sequence(tys); + Prod(tys); + | (Prod(_), _) => None + | (Sum(sm1), Sum(sm2)) => + let (sorted1, sorted2) = + /* If same order, retain order for UI */ + ConstructorMap.same_constructors_same_order(sm1, sm2) + ? (sm1, sm2) + : (ConstructorMap.sort(sm1), ConstructorMap.sort(sm2)); + let* ty = + ListUtil.map2_opt( + join_sum_entries(~resolve, ~fix, ctx), + sorted1, + sorted2, + ); + let+ ty = OptUtil.sequence(ty); + Sum(ty); + | (Sum(_), _) => None + | (List(ty1), List(ty2)) => + let+ ty = join'(ty1, ty2); + List(ty); + | (List(_), _) => None + }; + } + and join_sum_entries = + ( + ~resolve, + ~fix, + ctx: Ctx.t, + (ctr1, ty1): sum_entry, + (ctr2, ty2): sum_entry, + ) + : option(sum_entry) => + switch (ty1, ty2) { + | (None, None) when ctr1 == ctr2 => Some((ctr1, None)) + | (Some(ty1), Some(ty2)) when ctr1 == ctr2 => + let+ ty_join = join(~resolve, ~fix, ctx, ty1, ty2); + (ctr1, Some(ty_join)); + | _ => None + }; + + let join_fix = join(~fix=true); + + let join_all = (ctx: Ctx.t, ts: list(t)): option(t) => + List.fold_left( + (acc, ty) => OptUtil.and_then(join(~fix=false, ctx, ty), acc), + Some(Unknown(Internal)), + ts, + ); + + let rec weak_head_normalize = (ctx: Ctx.t, ty: t): t => + switch (ty) { + | Var(x) => + switch (Ctx.lookup_alias(ctx, x)) { + | Some(ty) => weak_head_normalize(ctx, ty) + | None => ty + } + | _ => ty + }; + + let rec normalize = (ctx: Ctx.t, ty: t): t => { + switch (ty) { + | Var(x) => + switch (Ctx.lookup_alias(ctx, x)) { + | Some(ty) => normalize(ctx, ty) + | None => ty + } + | Unknown(_) + | Int + | Float + | Bool + | String => ty + | List(t) => List(normalize(ctx, t)) + | Arrow(t1, t2) => Arrow(normalize(ctx, t1), normalize(ctx, t2)) + | Prod(ts) => Prod(List.map(normalize(ctx), ts)) + | Sum(ts) => Sum(ConstructorMap.map(Option.map(normalize(ctx)), ts)) + | Rec(name, ty) => + /* NOTE: Dummy tvar added has fake id but shouldn't matter + as in current implementation Recs do not occur in the + surface syntax, so we won't try to jump to them. */ + Rec(name, normalize(Ctx.extend_dummy_tvar(ctx, name), ty)) + }; + }; + + let sum_entry = (ctr: Constructor.t, ctrs: sum_map): option(sum_entry) => + List.find_map( + fun + | (t, typ) when Constructor.equal(t, ctr) => Some((t, typ)) + | _ => None, + ctrs, + ); + + let get_sum_constructors = (ctx: Ctx.t, ty: t): option(sum_map) => { + let ty = weak_head_normalize(ctx, ty); + switch (ty) { + | Sum(sm) => Some(sm) + | Rec(_) => + /* Note: We must unroll here to get right ctr types; + otherwise the rec parameter will leak */ + switch (unroll(ty)) { + | Sum(sm) => Some(sm) + | _ => None + } + | _ => None + }; + }; +} +and Ctx: { + [@deriving (show({with_path: false}), sexp, yojson)] + type var_entry = { + name: Var.t, + id: Id.t, + typ: Typ.t, + }; + + [@deriving (show({with_path: false}), sexp, yojson)] + type tvar_entry = { + name: TypVar.t, + id: Id.t, + kind: Kind.t, + }; + + [@deriving (show({with_path: false}), sexp, yojson)] + type entry = + | VarEntry(var_entry) + | ConstructorEntry(var_entry) + | TVarEntry(tvar_entry); + + [@deriving (show({with_path: false}), sexp, yojson)] + type t = list(entry); + + let extend: (t, entry) => t; + let extend_tvar: (t, tvar_entry) => t; + let extend_alias: (t, TypVar.t, Id.t, Typ.t) => t; + let extend_dummy_tvar: (t, TypVar.t) => t; + let lookup: (t, Var.t) => option(entry); + let lookup_tvar: (t, TypVar.t) => option(tvar_entry); + let lookup_alias: (t, TypVar.t) => option(Typ.t); + let get_id: entry => int; + let lookup_var: (t, string) => option(var_entry); + let lookup_ctr: (t, string) => option(var_entry); + let is_alias: (t, TypVar.t) => bool; + let add_ctrs: (t, TypVar.t, Id.t, Typ.sum_map) => t; + let subtract_prefix: (t, t) => option(t); + let added_bindings: (t, t) => t; + let filter_duplicates: t => t; + let shadows_typ: (t, TypVar.t) => bool; +} = { + [@deriving (show({with_path: false}), sexp, yojson)] + type var_entry = { + name: Var.t, + id: Id.t, + typ: Typ.t, + }; + + [@deriving (show({with_path: false}), sexp, yojson)] + type tvar_entry = { + name: TypVar.t, + id: Id.t, + kind: Kind.t, + }; + + [@deriving (show({with_path: false}), sexp, yojson)] + type entry = + | VarEntry(var_entry) + | ConstructorEntry(var_entry) + | TVarEntry(tvar_entry); + + [@deriving (show({with_path: false}), sexp, yojson)] + type t = list(entry); + + let extend = (ctx, entry) => List.cons(entry, ctx); + + let lookup = (ctx: t, name) => + List.find_map( + fun + | VarEntry(v) when v.name == name => Some(VarEntry(v)) + | ConstructorEntry(v) when v.name == name => Some(ConstructorEntry(v)) + | TVarEntry(v) when v.name == name => Some(TVarEntry(v)) + | _ => None, + ctx, + ); + + let extend_tvar = (ctx: t, tvar_entry: tvar_entry): t => + extend(ctx, TVarEntry(tvar_entry)); + + let extend_alias = (ctx: t, name: TypVar.t, id: Id.t, ty: Typ.t): t => + extend_tvar(ctx, {name, id, kind: Singleton(ty)}); + + let extend_dummy_tvar = (ctx: t, name: TypVar.t) => + extend_tvar(ctx, {kind: Abstract, name, id: Id.invalid}); + + let lookup_tvar = (ctx: t, name: TypVar.t): option(tvar_entry) => + List.find_map( + fun + | TVarEntry(v) when v.name == name => Some(v) + | _ => None, + ctx, + ); + + let lookup_alias = (ctx: t, t: TypVar.t): option(Typ.t) => + switch (lookup_tvar(ctx, t)) { + | Some({kind: Singleton(ty), _}) => Some(ty) + | Some({kind: Abstract, _}) + | _ => None + }; + + let get_id: entry => int = + fun + | VarEntry({id, _}) + | ConstructorEntry({id, _}) + | TVarEntry({id, _}) => id; + + let lookup_var = (ctx: t, name: string): option(var_entry) => + switch (lookup(ctx, name)) { + | Some(VarEntry(v)) => Some(v) + | _ => None + }; + + let lookup_ctr = (ctx: t, name: string): option(var_entry) => + switch (lookup(ctx, name)) { + | Some(ConstructorEntry(t)) => Some(t) + | _ => None + }; + + let is_alias = (ctx: t, name: TypVar.t): bool => + switch (lookup_alias(ctx, name)) { + | Some(_) => true + | None => false + }; + + let add_ctrs = (ctx: t, name: TypVar.t, id: Id.t, ctrs: Typ.sum_map): t => + List.map( + ((ctr, typ)) => + ConstructorEntry({ + name: ctr, + id, + typ: + switch (typ) { + | None => Var(name) + | Some(typ) => Arrow(typ, Var(name)) + }, + }), + ctrs, + ) + @ ctx; + + let subtract_prefix = (ctx: t, prefix_ctx: t): option(t) => { + // NOTE: does not check that the prefix is an actual prefix + let prefix_length = List.length(prefix_ctx); + let ctx_length = List.length(ctx); + if (prefix_length > ctx_length) { + None; + } else { + Some( + List.rev( + ListUtil.sublist((prefix_length, ctx_length), List.rev(ctx)), + ), + ); + }; + }; + + let added_bindings = (ctx_after: t, ctx_before: t): t => { + /* Precondition: new_ctx is old_ctx plus some new bindings */ + let new_count = List.length(ctx_after) - List.length(ctx_before); + switch (ListUtil.split_n_opt(new_count, ctx_after)) { + | Some((ctx, _)) => ctx + | _ => [] + }; + }; + + module VarSet = Set.Make(Var); + + // Note: filter out duplicates when rendering + let filter_duplicates = (ctx: t): t => + ctx + |> List.fold_left( + ((ctx, term_set, typ_set), entry) => { + switch (entry) { + | VarEntry({name, _}) + | ConstructorEntry({name, _}) => + VarSet.mem(name, term_set) + ? (ctx, term_set, typ_set) + : ([entry, ...ctx], VarSet.add(name, term_set), typ_set) + | TVarEntry({name, _}) => + VarSet.mem(name, typ_set) + ? (ctx, term_set, typ_set) + : ([entry, ...ctx], term_set, VarSet.add(name, typ_set)) + } + }, + ([], VarSet.empty, VarSet.empty), + ) + |> (((ctx, _, _)) => List.rev(ctx)); + + let shadows_typ = (ctx: t, name: TypVar.t): bool => + Form.is_base_typ(name) || lookup_alias(ctx, name) != None; +} +and Kind: { + [@deriving (show({with_path: false}), sexp, yojson)] + type t = + | Singleton(Typ.t) + | Abstract; +} = { + [@deriving (show({with_path: false}), sexp, yojson)] + type t = + | Singleton(Typ.t) + | Abstract; +}; diff --git a/src/haz3lcore/statics/TypVar.re b/src/haz3lcore/statics/TypVar.re new file mode 100644 index 0000000000..7b4f4d4ef2 --- /dev/null +++ b/src/haz3lcore/statics/TypVar.re @@ -0,0 +1,6 @@ +open Sexplib.Std; + +[@deriving (show({with_path: false}), sexp, yojson)] +type t = string; + +let eq = String.equal; diff --git a/src/haz3lcore/dynamics/Var.re b/src/haz3lcore/statics/Var.re similarity index 100% rename from src/haz3lcore/dynamics/Var.re rename to src/haz3lcore/statics/Var.re diff --git a/src/haz3lcore/tiles/Id.re b/src/haz3lcore/tiles/Id.re index ca1ec111e4..8b578284ea 100644 --- a/src/haz3lcore/tiles/Id.re +++ b/src/haz3lcore/tiles/Id.re @@ -1,5 +1,72 @@ open Sexplib.Std; +/* ID FAQ + + WHAT ARE IDS USED FOR? + + Unique ids are assigned to tiles (and hence, indirectly, to terms) + at the time of creation of surface syntax. Ids are used as keys in + various maps (mostly notably the Measured map, which tracks screen + coordinates for the view, and the Info map which collects static + data such as type information). + + BUT WHY IS THERE A _LIST_ OF IDS? + + Technically, each tile has a list of ids, to support n-ary forms like + tuples; there are rep_id functions in Term to canonically extract + single representative ids from this list where appropriate. + + HOW ARE NEW IDS CREATED? + + In the parts of the implementation which manipulate Zippers, fresh id + creation is done by threading an IdGen parameter through all of the + (functions which call) functions where new tiles can be created. This + generally follows the state monad pattern. When a fresh Id is required, + the current value of the IdGen is used, and the IdGen is incremented + and must then be returned to the caller. + + The threading of IdGen through essentially all syntax modification + functions presents a significant complication for the action code, + and may eventually be replaced it with a mutable ref. + + WHERE DOES IDGEN LIVE? + + The initial IdGen passed to zipper functions is generally packaged + along with a zipper through the Zipper.state type. Although in + principle the initial IdGen could be set by traversing the zipper + and finding the largest Id, to avoid this traversal we track the + IdGen along with the zipper state. Each editor mode is responsible + for this tracking. Ultimately, each zipper action which can result in + new Ids being created must be sandwiched by calls to + Editors.get_editor_and_id and Editors.put_editor_and_id, to ensure that + IdGen state is tracked between actions and properly serialized to + local storage. + + HOW DO I GENERATE FRESH IDS FOR MY USE CASE? + + Currently there is no easy way to generate fresh IDs in places one + might concievably want them after Term creation, for example in the + elaborator or evaluator. Doing so is a significant change with + indirect implications for architrcture and performance; ask Andrew + about your use case before attempting this. For some uses, a dummy id + may be sufficient; this should be documented and use Id.invalid or + another similar label rather than magic literals. If you do need to + generated genuinely fresh IDs, then you'll need (A) a strategy + to route an IdGen to/from your use site to the aformentioned + Editors functions, and a traversal/mutation strategy within your + context of use. + + IDS IN DYNAMICS: + + Currently, DHExps (as produced by the elaborator and produced/consumed + by the evaluator) do not in general persist ids; the exceptions are + things like holes and tests which have additional metadata which is + accumulated duting evaluation. There are many use cases for tracking + ids more generally during evaluation, but doing so in a principled + way is a large-scale change with architectural implications. + + */ + [@deriving (show({with_path: false}), sexp, yojson)] type t = int; let compare = Int.compare; diff --git a/src/haz3lcore/tiles/Segment.re b/src/haz3lcore/tiles/Segment.re index 2d487f3fb9..9f107989cc 100644 --- a/src/haz3lcore/tiles/Segment.re +++ b/src/haz3lcore/tiles/Segment.re @@ -121,6 +121,7 @@ let rec remold = (~shape=Nib.Shape.concave(), seg: t, s: Sort.t) => | Pat => remold_pat(shape, seg) | Exp => remold_exp(shape, seg) | Rul => remold_rul(shape, seg) + | TPat => remold_tpat(shape, seg) | _ => failwith("remold unexpected") } and remold_tile = (s: Sort.t, shape, t: Tile.t): option(Tile.t) => { @@ -251,6 +252,26 @@ and remold_pat = (shape, seg: t): t => } } } +and remold_tpat = (shape, seg: t): t => + switch (seg) { + | [] => [] + | [hd, ...tl] => + switch (hd) { + | Secondary(_) + | Grout(_) => [hd, ...remold_tpat(shape, tl)] + | Tile(t) => + switch (remold_tile(TPat, shape, t)) { + | None => [Tile(t), ...remold_tpat(snd(Tile.shapes(t)), tl)] + | Some(t) => + switch (Tile.nibs(t)) { + | (_, {shape, sort: Typ}) => + let (remolded, shape, rest) = remold_typ_uni(shape, tl); + [Piece.Tile(t), ...remolded] @ remold_tpat(shape, rest); + | _ => [Tile(t), ...remold_tpat(snd(Tile.shapes(t)), tl)] + } + } + } + } and remold_exp_uni = (shape, seg: t): (t, Nib.Shape.t, t) => switch (seg) { | [] => ([], shape, []) diff --git a/src/haz3lcore/tiles/Skel.re b/src/haz3lcore/tiles/Skel.re index 0fd2a4e6f5..8d11c40961 100644 --- a/src/haz3lcore/tiles/Skel.re +++ b/src/haz3lcore/tiles/Skel.re @@ -88,6 +88,7 @@ let rel = (p1: Piece.t, p2: Piece.t): option(rel) => lbl1(case) && lbl2(rule), lbl1(rule) && lbl2(rule), lbl1(comma) && lbl2(comma) && t1.mold == t2.mold, + lbl1(["+"]) && lbl2(["+"]) && t1.mold == t2.mold, ] |> List.fold_left((||), false); if (eq) { @@ -170,7 +171,11 @@ module Stacks = { | (_, Some((l, r))) => let is = List.map(fst, chain); let split_kids = n => - ListUtil.split_n(n, stacks.output) |> PairUtil.map_fst(List.rev); + try(ListUtil.split_n(n, stacks.output) |> PairUtil.map_fst(List.rev)) { + | _ => + print_endline(show(stacks)); + failwith("Skel.push_output: split_kids: index out of bounds"); + }; let output = switch (l, r) { | (Convex, Convex) => diff --git a/src/haz3lcore/zipper/Editor.re b/src/haz3lcore/zipper/Editor.re index 70d7f76542..6ac16b3cda 100644 --- a/src/haz3lcore/zipper/Editor.re +++ b/src/haz3lcore/zipper/Editor.re @@ -156,7 +156,7 @@ let can_redo = ed => Option.is_some(redo(ed)); let set_read_only = (ed, read_only) => {...ed, read_only}; -let trailing_hole_ctx = (ed: t, info_map: Statics.map) => { +let trailing_hole_ctx = (ed: t, info_map: Statics.Map.t) => { let segment = Zipper.unselect_and_zip(ed.state.zipper); let convex_grout = Segment.convex_grout(segment); // print_endline(String.concat("; ", List.map(Grout.show, convex_grout))); @@ -167,7 +167,7 @@ let trailing_hole_ctx = (ed: t, info_map: Statics.map) => { let id = grout.id; let info = Id.Map.find_opt(id, info_map); switch (info) { - | Some(InfoExp(info_exp)) => Some(info_exp.ctx) + | Some(info) => Some(Info.ctx_of(info)) | _ => None }; }; diff --git a/src/haz3lcore/zipper/EditorUtil.re b/src/haz3lcore/zipper/EditorUtil.re index 02e0652d70..c504144bcd 100644 --- a/src/haz3lcore/zipper/EditorUtil.re +++ b/src/haz3lcore/zipper/EditorUtil.re @@ -64,7 +64,7 @@ let rec append_exp = (id, e1: TermBase.UExp.t, e2: TermBase.UExp.t) => { | Float(_) | String(_) | ListLit(_) - | Tag(_) + | Constructor(_) | Fun(_) | Tuple(_) | Var(_) @@ -88,6 +88,9 @@ let rec append_exp = (id, e1: TermBase.UExp.t, e2: TermBase.UExp.t) => { | Let(p, edef, ebody) => let (id, ebody') = append_exp(id, ebody, e2); (id, TermBase.UExp.{ids: e1.ids, term: Let(p, edef, ebody')}); + | TyAlias(tp, tdef, ebody) => + let (id, ebody') = append_exp(id, ebody, e2); + (id, TermBase.UExp.{ids: e1.ids, term: TyAlias(tp, tdef, ebody')}); }; }; diff --git a/src/haz3lcore/zipper/action/Perform.re b/src/haz3lcore/zipper/action/Perform.re index fc2fec547b..7165081045 100644 --- a/src/haz3lcore/zipper/action/Perform.re +++ b/src/haz3lcore/zipper/action/Perform.re @@ -50,8 +50,9 @@ let go_z = ( switch (jump_target) { | BindingSiteOfIndicatedVar => - let* binding_id = - Option.bind(idx, Statics.get_binding_site(_, statics)); + let* idx = idx; + let* ci = Id.Map.find_opt(idx, statics); + let* binding_id = Info.get_binding_site(ci); Move.jump_to_id(z, binding_id); | TileId(id) => Move.jump_to_id(z, id) } diff --git a/src/haz3lschool/SchoolExercise.re b/src/haz3lschool/Exercise.re similarity index 98% rename from src/haz3lschool/SchoolExercise.re rename to src/haz3lschool/Exercise.re index 8b74b3dc51..057a2c171f 100644 --- a/src/haz3lschool/SchoolExercise.re +++ b/src/haz3lschool/Exercise.re @@ -8,8 +8,7 @@ module type ExerciseEnv = { }; let output_header_grading = _module_name => - "module SchoolExercise = GradePrelude.SchoolExercise\n" - ++ "let prompt = ()\n"; + "module Exercise = GradePrelude.Exercise\n" ++ "let prompt = ()\n"; module F = (ExerciseEnv: ExerciseEnv) => { [@deriving (show({with_path: false}), sexp, yojson)] @@ -572,7 +571,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { module StaticsItem = { type t = { term: TermBase.UExp.t, - info_map: Statics.map, + info_map: Statics.Map.t, }; }; @@ -725,7 +724,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { module DynamicsItem = { type t = { term: TermBase.UExp.t, - info_map: Statics.map, + info_map: Statics.Map.t, simple_result: ModelResult.simple, }; }; @@ -857,7 +856,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { "let prompt = " ++ module_name ++ "_prompt.prompt\n" - ++ "let exercise: SchoolExercise.spec = "; + ++ "let exercise: Exercise.spec = "; let record = show_p(editor_pp, eds); let data = prefix ++ record ++ "\n"; data; @@ -874,7 +873,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { "let prompt = " ++ module_name ++ "_prompt.prompt\n" - ++ "let exercise: SchoolExercise.spec = SchoolExercise.transition("; + ++ "let exercise: Exercise.spec = Exercise.transition("; let record = show_p(transitionary_editor_pp, eds); let data = prefix ++ record ++ ")\n"; data; @@ -882,7 +881,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { let export_grading_module = (module_name, {eds, _}: state) => { let header = output_header_grading(module_name); - let prefix = "let exercise: SchoolExercise.spec = "; + let prefix = "let exercise: Exercise.spec = "; let record = show_p(editor_pp, eds); let data = header ++ prefix ++ record ++ "\n"; data; @@ -935,10 +934,10 @@ module F = (ExerciseEnv: ExerciseEnv) => { }; }; - // From LocalStorage + // From Store [@deriving (show({with_path: false}), sexp, yojson)] - type school_export = { + type exercise_export = { cur_exercise: key, exercise_data: list((key, persistent_state)), }; @@ -956,7 +955,7 @@ module F = (ExerciseEnv: ExerciseEnv) => { |> unpersist_state(~spec, ~instructor_mode); }; - let deserialize_school_export = data => { - data |> Sexplib.Sexp.of_string |> school_export_of_sexp; + let deserialize_exercise_export = data => { + data |> Sexplib.Sexp.of_string |> exercise_export_of_sexp; }; }; diff --git a/src/haz3lschool/GradePrelude.re b/src/haz3lschool/GradePrelude.re index 4a84398706..a45b34fa15 100644 --- a/src/haz3lschool/GradePrelude.re +++ b/src/haz3lschool/GradePrelude.re @@ -1,9 +1,9 @@ module ExerciseEnv = { type node = unit; let default = (); - let output_header = SchoolExercise.output_header_grading; + let output_header = Exercise.output_header_grading; }; -module SchoolExercise = SchoolExercise.F(ExerciseEnv); +module Exercise = Exercise.F(ExerciseEnv); module Grading = Grading.F(ExerciseEnv); diff --git a/src/haz3lschool/Gradescope.re b/src/haz3lschool/Gradescope.re index 1c43ef3288..3c4e2d3314 100644 --- a/src/haz3lschool/Gradescope.re +++ b/src/haz3lschool/Gradescope.re @@ -4,7 +4,7 @@ open Haz3lschool; open Core; open Specs; -open GradePrelude.SchoolExercise; +open GradePrelude.Exercise; open GradePrelude.Grading; [@deriving (sexp, yojson)] @@ -44,15 +44,15 @@ type section = { type chapter = list(section); module Main = { - let name_to_school_export = path => { + let name_to_exercise_export = path => { let yj = Yojson.Safe.from_file(path); switch (yj) { | `Assoc(l) => let sch = List.Assoc.find_exn(~equal=String.(==), l, "school"); switch (sch) { | `String(sch) => - let school_export = sch |> deserialize_school_export; - school_export; + let exercise_export = sch |> deserialize_exercise_export; + exercise_export; | _ => failwith("School is not a string") }; | _ => failwith("Json without school key") @@ -98,7 +98,7 @@ module Main = { }; let run = () => { let hw_path = Sys.get_argv()[1]; - let hw = name_to_school_export(hw_path); + let hw = name_to_exercise_export(hw_path); let export_chapter = hw.exercise_data |> List.map(~f=(((name, _) as key, persistent_state)) => { diff --git a/src/haz3lschool/Grading.re b/src/haz3lschool/Grading.re index 948afd49b2..d20a490610 100644 --- a/src/haz3lschool/Grading.re +++ b/src/haz3lschool/Grading.re @@ -1,8 +1,8 @@ open Haz3lcore; open Sexplib.Std; -module F = (ExerciseEnv: SchoolExercise.ExerciseEnv) => { - open SchoolExercise.F(ExerciseEnv); +module F = (ExerciseEnv: Exercise.ExerciseEnv) => { + open Exercise.F(ExerciseEnv); [@deriving (show({with_path: false}), sexp, yojson)] type percentage = float; diff --git a/src/haz3lweb/DebugAction.re b/src/haz3lweb/DebugAction.re index 6258163f5c..f25af2897c 100644 --- a/src/haz3lweb/DebugAction.re +++ b/src/haz3lweb/DebugAction.re @@ -1,13 +1,13 @@ [@deriving (show({with_path: false}), sexp, yojson)] type t = | TurnOffDynamics - | ClearLocalStorage; + | ClearStore; let perform = action => { switch (action) { | TurnOffDynamics => - let settings = LocalStorage.Settings.load(); - LocalStorage.Settings.save({...settings, dynamics: false}); - | ClearLocalStorage => JsUtil.clear_localstore() + let settings = Store.Settings.load(); + Store.Settings.save({...settings, dynamics: false}); + | ClearStore => JsUtil.clear_localstore() }; }; diff --git a/src/haz3lweb/Editors.re b/src/haz3lweb/Editors.re index eafd68a308..85a700ed86 100644 --- a/src/haz3lweb/Editors.re +++ b/src/haz3lweb/Editors.re @@ -2,29 +2,20 @@ open Sexplib.Std; open Haz3lcore; [@deriving (show({with_path: false}), sexp, yojson)] -type t = - | DebugLoad - | Scratch(int, list(ScratchSlide.state)) - | School(int, list(SchoolExercise.spec), SchoolExercise.state); +type scratch = (int, list(ScratchSlide.state)); [@deriving (show({with_path: false}), sexp, yojson)] -type scratch = (int, list(ScratchSlide.state)); +type examples = (string, list((string, ScratchSlide.state))); [@deriving (show({with_path: false}), sexp, yojson)] -type school = (int, list(SchoolExercise.spec), SchoolExercise.state); +type exercises = (int, list(Exercise.spec), Exercise.state); [@deriving (show({with_path: false}), sexp, yojson)] -type mode = +type t = | DebugLoad - | Scratch - | School; - -let rotate_mode = (editors: t) => - switch (editors) { - | DebugLoad => DebugLoad - | Scratch(_) => School - | School(_) => Scratch - }; + | Scratch(int, list(ScratchSlide.state)) + | Examples(string, list((string, ScratchSlide.state))) + | Exercise(int, list(Exercise.spec), Exercise.state); let get_editor_and_id = (editors: t): (Id.t, Editor.t) => switch (editors) { @@ -35,9 +26,15 @@ let get_editor_and_id = (editors: t): (Id.t, Editor.t) => let id = ScratchSlide.id_of_state(slide); let ed = ScratchSlide.editor_of_state(slide); (id, ed); - | School(_, _, exercise) => - let id = SchoolExercise.id_of_state(exercise); - let ed = SchoolExercise.editor_of_state(exercise); + | Examples(name, slides) => + assert(List.mem_assoc(name, slides)); + let slide = List.assoc(name, slides); + let id = ScratchSlide.id_of_state(slide); + let ed = ScratchSlide.editor_of_state(slide); + (id, ed); + | Exercise(_, _, exercise) => + let id = Exercise.id_of_state(exercise); + let ed = Exercise.editor_of_state(exercise); (id, ed); }; @@ -57,8 +54,17 @@ let put_editor_and_id = (id: Id.t, ed: Editor.t, eds: t): t => slides, ), ); - | School(n, specs, exercise) => - School(n, specs, SchoolExercise.put_editor_and_id(exercise, id, ed)) + | Examples(name, slides) => + assert(List.mem_assoc(name, slides)); + let slide = List.assoc(name, slides); + Examples( + name, + slides + |> List.remove_assoc(name) + |> List.cons((name, ScratchSlide.put_editor_and_id(slide, id, ed))), + ); + | Exercise(n, specs, exercise) => + Exercise(n, specs, Exercise.put_editor_and_id(exercise, id, ed)) }; let get_zipper = (editors: t): Zipper.t => get_editor(editors).state.zipper; @@ -69,32 +75,73 @@ let get_spliced_elabs = (editors: t): list((ModelResults.key, DHExp.t)) => { | Scratch(n, slides) => let slide = List.nth(slides, n); ScratchSlide.spliced_elabs(slide); - | School(_, _, exercise) => SchoolExercise.spliced_elabs(exercise) + | Examples(name, slides) => + let slide = List.assoc(name, slides); + ScratchSlide.spliced_elabs(slide); + | Exercise(_, _, exercise) => Exercise.spliced_elabs(exercise) }; }; let set_instructor_mode = (editors: t, instructor_mode: bool): t => switch (editors) { | DebugLoad => failwith("no editors in debug load mode") - | Scratch(_) => editors - | School(n, specs, exercise) => - School( + | Scratch(_) + | Examples(_) => editors + | Exercise(n, specs, exercise) => + Exercise( n, specs, - SchoolExercise.set_instructor_mode(exercise, instructor_mode), + Exercise.set_instructor_mode(exercise, instructor_mode), ) }; -let num_slides = (editors: t): int => +let reset_nth_slide = (n, slides) => { + let data = List.nth(Init.startup.scratch |> snd, n); + let init_nth = ScratchSlide.unpersist(data); + Util.ListUtil.put_nth(n, init_nth, slides); +}; + +let reset_named_slide = (name, slides) => { + let data = List.assoc(name, Init.startup.examples |> snd); + let init_name = ScratchSlide.unpersist(data); + slides |> List.remove_assoc(name) |> List.cons((name, init_name)); +}; + +let reset_current = (editors: t, ~instructor_mode: bool): t => switch (editors) { - | DebugLoad => 0 - | Scratch(_, slides) => List.length(slides) - | School(_, specs, _) => List.length(specs) + | DebugLoad => failwith("impossible") + | Scratch(n, slides) => Scratch(n, reset_nth_slide(n, slides)) + | Examples(name, slides) => + Examples(name, reset_named_slide(name, slides)) + | Exercise(n, specs, _) => + Exercise( + n, + specs, + List.nth(specs, n) |> Exercise.state_of_spec(~instructor_mode), + ) + }; + +let import_current = (editors: t, data: option(string)): t => + switch (editors) { + | DebugLoad + | Examples(_) + | Exercise(_) => failwith("impossible") + | Scratch(idx, slides) => + switch (data) { + | None => editors + | Some(data) => + let state = ScratchSlide.import(data); + let slides = Util.ListUtil.put_nth(idx, state, slides); + Scratch(idx, slides); + } }; -let cur_slide = (editors: t): int => +let switch_example_slide = (editors: t, name: string): option(t) => switch (editors) { - | DebugLoad => 0 - | Scratch(n, _) - | School(n, _, _) => n + | DebugLoad + | Scratch(_) + | Exercise(_) => None + | Examples(cur, slides) when !List.mem_assoc(name, slides) || cur == name => + None + | Examples(_, slides) => Some(Examples(name, slides)) }; diff --git a/src/haz3lweb/SchoolExercise.re b/src/haz3lweb/Exercise.re similarity index 80% rename from src/haz3lweb/SchoolExercise.re rename to src/haz3lweb/Exercise.re index c209dff2f2..ec187c90db 100644 --- a/src/haz3lweb/SchoolExercise.re +++ b/src/haz3lweb/Exercise.re @@ -7,4 +7,4 @@ module ExerciseEnv = { "let prompt = " ++ module_name ++ "_prompt.prompt\n"; }; -include Haz3lschool.SchoolExercise.F(ExerciseEnv); +include Haz3lschool.Exercise.F(ExerciseEnv); diff --git a/src/haz3lweb/ExerciseSettings.re b/src/haz3lweb/ExerciseSettings.re new file mode 100644 index 0000000000..09f0735d77 --- /dev/null +++ b/src/haz3lweb/ExerciseSettings.re @@ -0,0 +1,2 @@ +include ExerciseSettings_base; +let show_instructor = true; diff --git a/src/haz3lweb/SchoolSettings_base.re b/src/haz3lweb/ExerciseSettings_base.re similarity index 72% rename from src/haz3lweb/SchoolSettings_base.re rename to src/haz3lweb/ExerciseSettings_base.re index b39716cfe5..c97171c755 100644 --- a/src/haz3lweb/SchoolSettings_base.re +++ b/src/haz3lweb/ExerciseSettings_base.re @@ -1,6 +1,6 @@ let filename = "haz3l-demo"; let log_key = filename; -let exercises: list(SchoolExercise.spec) = [ +let exercises: list(Exercise.spec) = [ Ex_OddlyRecursive.exercise, Ex_RecursiveFibonacci.exercise, ]; diff --git a/src/haz3lweb/ExerciseSettings_instructor.re b/src/haz3lweb/ExerciseSettings_instructor.re new file mode 100644 index 0000000000..09f0735d77 --- /dev/null +++ b/src/haz3lweb/ExerciseSettings_instructor.re @@ -0,0 +1,2 @@ +include ExerciseSettings_base; +let show_instructor = true; diff --git a/src/haz3lweb/ExerciseSettings_student.re b/src/haz3lweb/ExerciseSettings_student.re new file mode 100644 index 0000000000..e18079d14c --- /dev/null +++ b/src/haz3lweb/ExerciseSettings_student.re @@ -0,0 +1,2 @@ +include ExerciseSettings_base; +let show_instructor = false; diff --git a/src/haz3lweb/Export.re b/src/haz3lweb/Export.re index 19a4fda72c..ab734aaccf 100644 --- a/src/haz3lweb/Export.re +++ b/src/haz3lweb/Export.re @@ -5,7 +5,8 @@ type all = { settings: string, langDocMessages: string, scratch: string, - school: string, + exercise: string, + examples: string, log: string, }; @@ -14,23 +15,28 @@ type all = { type all_f22 = { settings: string, scratch: string, - school: string, + exercise: string, log: string, }; let mk_all = (~instructor_mode) => { print_endline("Mk all"); - let settings = LocalStorage.Settings.export(); + let settings = Store.Settings.export(); print_endline("Settings OK"); - let langDocMessages = LocalStorage.LangDocMessages.export(); + let langDocMessages = Store.LangDocMessages.export(); print_endline("LangDocMessages OK"); - let scratch = LocalStorage.Scratch.export(); + let scratch = Store.Scratch.export(); print_endline("Scratch OK"); - let specs = School.exercises; - let school = LocalStorage.School.export(~specs, ~instructor_mode); - print_endline("School OK"); + let examples = Store.Examples.export(); + print_endline("Examples OK"); + let exercise = + Store.Exercise.export( + ~specs=ExerciseSettings.exercises, + ~instructor_mode, + ); + print_endline("Exercise OK"); let log = Log.export(); - {settings, langDocMessages, scratch, school, log}; + {settings, langDocMessages, scratch, examples, exercise, log}; }; let export_all = (~instructor_mode) => { @@ -45,15 +51,16 @@ let import_all = (data, ~specs) => { { settings: all_f22.settings, scratch: all_f22.scratch, - school: all_f22.school, + examples: "", + exercise: all_f22.exercise, log: all_f22.log, langDocMessages: "", }; }; - let settings = LocalStorage.Settings.import(all.settings); - LocalStorage.LangDocMessages.import(all.langDocMessages); + let settings = Store.Settings.import(all.settings); + Store.LangDocMessages.import(all.langDocMessages); let instructor_mode = settings.instructor_mode; - LocalStorage.Scratch.import(all.scratch); - LocalStorage.School.import(all.school, ~specs, ~instructor_mode); + Store.Scratch.import(all.scratch); + Store.Exercise.import(all.exercise, ~specs, ~instructor_mode); Log.import(all.log); }; diff --git a/src/haz3lweb/Grading.re b/src/haz3lweb/Grading.re index b3474eb18c..6b3c5568d8 100644 --- a/src/haz3lweb/Grading.re +++ b/src/haz3lweb/Grading.re @@ -1,7 +1,7 @@ open Virtual_dom.Vdom; open Node; -include Haz3lschool.Grading.F(SchoolExercise.ExerciseEnv); +include Haz3lschool.Grading.F(Exercise.ExerciseEnv); let score_view = ((earned: points, max: points)) => { div( diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml new file mode 100644 index 0000000000..fb818acba9 --- /dev/null +++ b/src/haz3lweb/Init.ml @@ -0,0 +1,7336 @@ +let startup : PersistentData.t = + { + settings = + { + captions = true; + secondary_icons = false; + statics = true; + dynamics = true; + async_evaluation = false; + context_inspector = false; + instructor_mode = true; + benchmark = false; + mode = Examples; + }; + scratch = + ( 0, + [ + ( 1416, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(()((Grout((id \ + 1415)(shape Convex))))))(ancestors())))(caret Outer))"; + backup_text = " "; + } ); + ( 281, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Tile((id \ + 236)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 239)(shape \ + Concave)))(Tile((id 244)(label(Option))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 245)(content(Whitespace\" \"))))(Tile((id \ + 246)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 248)(content(Whitespace\" \"))))(Tile((id \ + 252)(label(None))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 253)(content(Whitespace\" \"))))(Tile((id \ + 254)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 256)(content(Whitespace\" \"))))(Tile((id \ + 260)(label(Some))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 261)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 265)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Grout((id 268)(shape \ + Concave)))(Tile((id 269)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 270)(content(Whitespace\" \"))))(Secondary((id \ + 271)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 274)(shape Concave)))(Tile((id 277)(label(Some))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 278)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 280)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))))))))()))(ancestors())))(caret \ + Outer))"; + backup_text = "type Option = None + Some(Int) in \n Some(3)"; + } ); + ( 18901, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Secondary((id \ + 16278)(content(Comment\"#Non-recursive sum/alias \ + tests#\"))))(Secondary((id \ + 16279)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16335)(content(Comment\"#all lines with trailing err comment \ + should have 1 error#\"))))(Secondary((id \ + 16336)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16370)(content(Comment\"#no other lines should have \ + errors#\"))))(Secondary((id \ + 16371)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16372)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16400)(content(Comment\"#type definitions: no \ + errors#\"))))(Secondary((id \ + 16401)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 16405)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16406)(content(Whitespace\" \"))))(Secondary((id \ + 16407)(content(Whitespace\" \"))))(Secondary((id \ + 16408)(content(Whitespace\" \"))))(Secondary((id \ + 16409)(content(Whitespace\" \"))))(Tile((id \ + 16410)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16412)(content(Whitespace\" \"))))(Secondary((id \ + 16413)(content(Whitespace\" \"))))(Secondary((id \ + 16414)(content(Whitespace\" \"))))(Secondary((id \ + 16415)(content(Whitespace\" \"))))(Tile((id \ + 16417)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16418)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16421)(shape Concave)))(Tile((id \ + 16424)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16427)(shape \ + Concave)))(Tile((id 16436)(label(SingleNull))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16437)(content(Whitespace\" \"))))(Tile((id \ + 16438)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16440)(content(Whitespace\" \"))))(Secondary((id \ + 16441)(content(Whitespace\" \"))))(Grout((id 16443)(shape \ + Convex)))(Tile((id 16442)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16446)(label(One))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16449)(shape \ + Concave)))(Tile((id 16450)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16451)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16454)(shape Concave)))(Tile((id \ + 16457)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16460)(shape \ + Concave)))(Tile((id 16465)(label(Single))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16466)(content(Whitespace\" \"))))(Tile((id \ + 16467)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16469)(content(Whitespace\" \"))))(Secondary((id \ + 16470)(content(Whitespace\" \"))))(Grout((id 16472)(shape \ + Convex)))(Tile((id 16471)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16473)(label(F))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16474)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 16478)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Grout((id \ + 16481)(shape Concave)))(Tile((id 16482)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16483)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16486)(shape Concave)))(Tile((id \ + 16489)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16492)(shape \ + Concave)))(Tile((id 16498)(label(GoodSum))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16499)(content(Whitespace\" \"))))(Tile((id \ + 16500)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16502)(content(Whitespace\" \"))))(Tile((id \ + 16503)(label(A))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16504)(content(Whitespace\" \"))))(Tile((id \ + 16505)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16507)(content(Whitespace\" \"))))(Tile((id \ + 16508)(label(B))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16509)(content(Whitespace\" \"))))(Tile((id \ + 16510)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16512)(content(Whitespace\" \"))))(Tile((id \ + 16513)(label(C))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16514)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 16518)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Grout((id \ + 16521)(shape Concave)))(Tile((id 16522)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16523)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16526)(shape Concave)))(Tile((id \ + 16529)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16532)(shape \ + Concave)))(Tile((id 16538)(label(Partial))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16539)(content(Whitespace\" \"))))(Tile((id \ + 16540)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16542)(content(Whitespace\" \"))))(Tile((id \ + 16544)(label(Ok))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16545)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Grout((id \ + 16550)(shape Convex)))(Secondary((id \ + 16547)(content(Whitespace\" \"))))(Secondary((id \ + 16548)(content(Whitespace\" \"))))(Secondary((id \ + 16549)(content(Whitespace\" \")))))))))(Secondary((id \ + 16551)(content(Whitespace\" \"))))(Tile((id \ + 16552)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16554)(content(Whitespace\" \"))))(Secondary((id \ + 16555)(content(Whitespace\" \"))))(Secondary((id \ + 16556)(content(Whitespace\" \"))))(Secondary((id \ + 16557)(content(Whitespace\" \"))))(Tile((id \ + 16559)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16560)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16563)(shape Concave)))(Tile((id \ + 16566)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16569)(shape \ + Concave)))(Tile((id 16579)(label(DoubleAlias))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16580)(content(Whitespace\" \"))))(Tile((id \ + 16581)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16583)(content(Whitespace\" \"))))(Tile((id \ + 16590)(label(GoodSum))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16593)(shape \ + Concave)))(Tile((id 16594)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16595)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16598)(shape Concave)))(Tile((id \ + 16601)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16604)(shape \ + Concave)))(Tile((id 16618)(label(VerticalLeading))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16619)(content(Whitespace\" \"))))(Tile((id \ + 16620)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16622)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16623)(content(Whitespace\" \"))))(Grout((id 16625)(shape \ + Convex)))(Tile((id 16624)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16626)(content(Whitespace\" \"))))(Tile((id \ + 16627)(label(A))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16628)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 16629)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16631)(content(Whitespace\" \"))))(Tile((id \ + 16632)(label(B))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16633)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 16641)(label(GoodSum))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 16642)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 16643)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16645)(content(Whitespace\" \"))))(Tile((id \ + 16646)(label(C))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16647)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 16652)(label(Bool))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16655)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 16659)(label(Bool))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 16660)(content(Whitespace\" \"))))(Secondary((id \ + 16661)(content(Whitespace\" \"))))(Secondary((id \ + 16662)(content(Whitespace\" \"))))(Secondary((id \ + 16663)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16665)(shape Concave)))(Tile((id 16666)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16667)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16668)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16709)(content(Comment\"#incorrect or incomplete type \ + definitions#\"))))(Secondary((id \ + 16710)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16713)(shape Concave)))(Tile((id \ + 16716)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16719)(shape \ + Concave)))(Tile((id 16729)(label(badTypeName))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16730)(content(Whitespace\" \"))))(Tile((id \ + 16731)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16733)(content(Whitespace\" \"))))(Secondary((id \ + 16734)(content(Whitespace\" \"))))(Secondary((id \ + 16735)(content(Whitespace\" \"))))(Secondary((id \ + 16736)(content(Whitespace\" \"))))(Tile((id \ + 16738)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16739)(content(Whitespace\" \"))))(Secondary((id \ + 16762)(content(Comment\"#err: invalid type \ + name#\"))))(Secondary((id \ + 16763)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16766)(shape Concave)))(Tile((id \ + 16769)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16770)(content(Whitespace\" \"))))(Tile((id \ + 16771)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Secondary((id \ + 16773)(content(Whitespace\" \"))))(Secondary((id \ + 16774)(content(Whitespace\" \"))))(Secondary((id \ + 16775)(content(Whitespace\" \"))))(Grout((id 16777)(shape \ + Convex)))(Tile((id 16776)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 14))(sort \ + Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16782)(shape \ + Convex)))(Secondary((id 16778)(content(Whitespace\" \ + \"))))(Secondary((id 16779)(content(Whitespace\" \ + \"))))(Secondary((id 16780)(content(Whitespace\" \ + \"))))(Secondary((id 16781)(content(Whitespace\" \ + \")))))))))(Secondary((id 16783)(content(Whitespace\" \ + \"))))(Tile((id 16784)(label(=))(mold((out \ + Any)(in_())(nibs(((shape(Concave 8))(sort \ + Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16786)(content(Whitespace\" \"))))(Secondary((id \ + 16787)(content(Whitespace\" \"))))(Secondary((id \ + 16788)(content(Whitespace\" \"))))(Secondary((id \ + 16789)(content(Whitespace\" \"))))(Tile((id \ + 16791)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16792)(content(Whitespace\" \"))))(Secondary((id \ + 16815)(content(Comment\"#err: invalid type \ + name#\"))))(Secondary((id \ + 16816)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16819)(shape Concave)))(Tile((id \ + 16822)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16823)(content(Whitespace\" \"))))(Secondary((id \ + 16824)(content(Whitespace\" \"))))(Secondary((id \ + 16825)(content(Whitespace\" \"))))(Secondary((id \ + 16826)(content(Whitespace\" \"))))(Tile((id \ + 16827)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16829)(content(Whitespace\" \"))))(Tile((id \ + 16841)(label(badTypeToken))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Grout((id \ + 16844)(shape Concave)))(Tile((id 16845)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16846)(content(Whitespace\" \"))))(Secondary((id \ + 16870)(content(Comment\"#err: invalid type \ + token#\"))))(Secondary((id \ + 16871)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16874)(shape Concave)))(Tile((id \ + 16877)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16880)(shape \ + Concave)))(Tile((id 16886)(label(NotASum))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16887)(content(Whitespace\" \"))))(Tile((id \ + 16888)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16890)(content(Whitespace\" \"))))(Tile((id \ + 16898)(label(NotInSum))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 16899)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 16904)(label(Bool))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Grout((id \ + 16907)(shape Concave)))(Tile((id 16908)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16909)(content(Whitespace\" \"))))(Secondary((id \ + 16930)(content(Comment\"#err: cons not in \ + sum#\"))))(Secondary((id \ + 16931)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16934)(shape Concave)))(Tile((id \ + 16937)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16940)(shape \ + Concave)))(Tile((id 16943)(label(Bool))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16944)(content(Whitespace\" \"))))(Tile((id \ + 16945)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16947)(content(Whitespace\" \"))))(Secondary((id \ + 16948)(content(Whitespace\" \"))))(Secondary((id \ + 16949)(content(Whitespace\" \"))))(Secondary((id \ + 16950)(content(Whitespace\" \"))))(Secondary((id \ + 16951)(content(Whitespace\" \"))))(Tile((id \ + 16953)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16954)(content(Whitespace\" \"))))(Secondary((id \ + 16977)(content(Comment\"#err: shadows base \ + type#\"))))(Secondary((id \ + 16978)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 16981)(shape Concave)))(Tile((id \ + 16984)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 16987)(shape \ + Concave)))(Tile((id 16991)(label(Dupes))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 16992)(content(Whitespace\" \"))))(Tile((id \ + 16993)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 16995)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16996)(content(Whitespace\" \"))))(Grout((id 16998)(shape \ + Convex)))(Tile((id 16997)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 16999)(content(Whitespace\" \"))))(Tile((id \ + 17002)(label(Guy))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17003)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17008)(label(Bool))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17009)(content(Whitespace\" \"))))(Secondary((id \ + 17016)(content(Comment\"#no err#\"))))(Secondary((id \ + 17017)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17018)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17020)(content(Whitespace\" \"))))(Tile((id \ + 17023)(label(Guy))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17024)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17028)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17029)(content(Whitespace\" \"))))(Secondary((id \ + 17047)(content(Comment\"#err: already \ + used#\"))))(Secondary((id \ + 17048)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17049)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17051)(content(Whitespace\" \"))))(Tile((id \ + 17054)(label(Guy))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17057)(shape \ + Concave)))(Tile((id 17058)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17059)(content(Whitespace\" \"))))(Secondary((id \ + 17077)(content(Comment\"#err: already \ + used#\"))))(Secondary((id \ + 17078)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 17081)(shape Concave)))(Tile((id \ + 17084)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17087)(shape \ + Concave)))(Tile((id 17093)(label(BadCons))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17094)(content(Whitespace\" \"))))(Tile((id \ + 17095)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 17097)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17098)(content(Whitespace\" \"))))(Grout((id 17100)(shape \ + Convex)))(Tile((id 17099)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17101)(content(Whitespace\" \"))))(Tile((id \ + 17103)(label(Um))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17104)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17112)(label(Unbound))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17113)(content(Whitespace\" \"))))(Secondary((id \ + 17135)(content(Comment\"#err: unbound type \ + var#\"))))(Secondary((id \ + 17136)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17137)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17139)(content(Whitespace\" \"))))(Secondary((id \ + 17140)(content(Whitespace\" \"))))(Tile((id \ + 17147)(label(invalid))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17148)(content(Whitespace\" \"))))(Secondary((id \ + 17161)(content(Comment\"#err: invalid#\"))))(Secondary((id \ + 17162)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17163)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17165)(content(Whitespace\" \"))))(Tile((id \ + 17169)(label(Bool))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17170)(content(Whitespace\" \"))))(Secondary((id \ + 17200)(content(Comment\"#err: expected cons found \ + type#\"))))(Secondary((id \ + 17201)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17202)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17204)(content(Whitespace\" \"))))(Tile((id \ + 17207)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17208)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17212)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17213)(content(Whitespace\" \"))))(Secondary((id \ + 17243)(content(Comment\"#err: expected cons found \ + type#\"))))(Secondary((id \ + 17244)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17245)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17247)(content(Whitespace\" \"))))(Tile((id \ + 17248)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Grout((id \ + 17252)(shape Convex)))(Secondary((id \ + 17249)(content(Whitespace\" \"))))(Secondary((id \ + 17250)(content(Whitespace\" \"))))(Secondary((id \ + 17251)(content(Whitespace\" \")))))))))(Tile((id \ + 17253)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17257)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17258)(content(Whitespace\" \"))))(Secondary((id \ + 17288)(content(Comment\"#err: expected cons found \ + type#\"))))(Secondary((id \ + 17289)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17290)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17292)(content(Whitespace\" \"))))(Tile((id \ + 17293)(label(A))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17294)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17299)(label(Bool))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 17300)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17304)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Grout((id \ + 17307)(shape Concave)))(Tile((id 17308)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17309)(content(Whitespace\" \"))))(Secondary((id \ + 17338)(content(Comment\"#err: expected cons found \ + app#\"))))(Secondary((id \ + 17339)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17340)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17379)(content(Comment\"#nested sum defs dont add tags to \ + scope#\"))))(Secondary((id \ + 17380)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 17383)(shape Concave)))(Tile((id \ + 17386)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17389)(shape \ + Concave)))(Tile((id 17399)(label(NestedAlias))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17400)(content(Whitespace\" \"))))(Tile((id \ + 17401)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 17403)(content(Whitespace\" \"))))(Tile((id \ + 17404)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17407)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17408)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17410)(content(Whitespace\" \"))))(Tile((id \ + 17419)(label(Anonymous))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17420)(content(Whitespace\" \"))))(Tile((id \ + 17421)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17423)(content(Whitespace\" \"))))(Tile((id \ + 17426)(label(Sum))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Grout((id \ + 17429)(shape Concave)))(Tile((id 17430)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17431)(content(Whitespace\" \"))))(Secondary((id \ + 17432)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 17435)(shape Concave)))(Tile((id 17438)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id 17439)(content(Whitespace\" \ + \"))))(Tile((id 17441)(label(x))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 17442)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 17454)(label(NestedAlias))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17455)(content(Whitespace\" \")))))((Secondary((id \ + 17457)(content(Whitespace\" \"))))(Tile((id \ + 17458)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17459)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17460)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17462)(content(Whitespace\" \"))))(Tile((id \ + 17465)(label(Sum))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17468)(content(Whitespace\" \")))))))))(Secondary((id \ + 17470)(content(Whitespace\" \"))))(Secondary((id \ + 17487)(content(Comment\"#err: not \ + defined#\"))))(Secondary((id \ + 17488)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17489)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17532)(content(Comment\"#unbound tyvars treated as \ + unknown-typehole#\"))))(Secondary((id \ + 17533)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17537)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 17538)(content(Whitespace\" \"))))(Tile((id \ + 17540)(label(a))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 17541)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 17545)(label(Bad))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17546)(content(Whitespace\" \")))))((Secondary((id \ + 17548)(content(Whitespace\" \"))))(Tile((id \ + 17549)(label(0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17552)(content(Whitespace\" \")))))))))(Secondary((id \ + 17554)(content(Whitespace\" \"))))(Tile((id \ + 17555)(label(a))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17556)(content(Whitespace\" \"))))(Tile((id \ + 17559)(label(==))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17560)(content(Whitespace\" \"))))(Tile((id \ + 17561)(label(0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17562)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17564)(content(Whitespace\" \"))))(Secondary((id \ + 17579)(content(Comment\"#err: not bound#\"))))(Secondary((id \ + 17580)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17581)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17613)(content(Comment\"#non-sum-types cant be \ + recursive#\"))))(Secondary((id \ + 17614)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17618)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17621)(shape \ + Concave)))(Tile((id 17623)(label(Lol))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17624)(content(Whitespace\" \"))))(Tile((id \ + 17625)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 17627)(content(Whitespace\" \"))))(Tile((id \ + 17630)(label(Lol))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17633)(shape \ + Concave)))(Tile((id 17634)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17635)(content(Whitespace\" \"))))(Secondary((id \ + 17650)(content(Comment\"#err: not bound#\"))))(Secondary((id \ + 17651)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17652)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17682)(content(Comment\"#no errors: analytic \ + shadowing#\"))))(Secondary((id \ + 17683)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 17686)(shape Concave)))(Tile((id \ + 17689)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17692)(shape \ + Concave)))(Tile((id 17696)(label(Tork1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17697)(content(Whitespace\" \"))))(Tile((id \ + 17698)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 17700)(content(Whitespace\" \"))))(Secondary((id \ + 17701)(content(Whitespace\" \"))))(Grout((id 17703)(shape \ + Convex)))(Tile((id 17702)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17707)(label(Blob))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17710)(shape \ + Concave)))(Tile((id 17711)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17712)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 17715)(shape Concave)))(Tile((id \ + 17718)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17721)(shape \ + Concave)))(Tile((id 17725)(label(Tork2))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17726)(content(Whitespace\" \"))))(Tile((id \ + 17727)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 17729)(content(Whitespace\" \"))))(Secondary((id \ + 17730)(content(Whitespace\" \"))))(Grout((id 17732)(shape \ + Convex)))(Tile((id 17731)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17736)(label(Blob))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17739)(shape \ + Concave)))(Tile((id 17740)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17741)(content(Whitespace\" \"))))(Secondary((id \ + 17742)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 17745)(shape Concave)))(Tile((id 17748)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id 17749)(content(Whitespace\" \ + \"))))(Tile((id 17751)(label(x))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 17752)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 17758)(label(Tork1))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17759)(content(Whitespace\" \")))))((Secondary((id \ + 17761)(content(Whitespace\" \"))))(Tile((id \ + 17765)(label(Blob))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17768)(content(Whitespace\" \")))))))))(Secondary((id \ + 17770)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17771)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 17788)(content(Comment\"#exp tests: \ + happy#\"))))(Secondary((id \ + 17789)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17793)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 17796)(shape \ + Concave)))(Tile((id 17801)(label(YoDawg))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17802)(content(Whitespace\" \"))))(Tile((id \ + 17803)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 17805)(content(Whitespace\" \"))))(Secondary((id \ + 17806)(content(Whitespace\" \"))))(Tile((id \ + 17808)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17809)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17813)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17814)(content(Whitespace\" \"))))(Tile((id \ + 17815)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17817)(content(Whitespace\" \"))))(Tile((id \ + 17819)(label(Bo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17820)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17824)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 17825)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17827)(content(Whitespace\" \"))))(Tile((id \ + 17831)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17832)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17837)(label(Bool))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Grout((id \ + 17840)(shape Concave)))(Tile((id 17841)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 17842)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 17845)(shape Concave)))(Tile((id 17848)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id 17849)(content(Whitespace\" \ + \"))))(Tile((id 17851)(label(_))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 17852)(content(Whitespace\" \")))))((Secondary((id \ + 17854)(content(Whitespace\" \"))))(Tile((id \ + 17856)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17857)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17859)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17862)(content(Whitespace\" \")))))))))(Secondary((id \ + 17864)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17868)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 17869)(content(Whitespace\" \"))))(Tile((id \ + 17871)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 17872)(content(Whitespace\" \"))))(Tile((id \ + 17873)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17875)(content(Whitespace\" \"))))(Tile((id \ + 17881)(label(YoDawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17882)(content(Whitespace\" \")))))((Secondary((id \ + 17884)(content(Whitespace\" \"))))(Tile((id \ + 17886)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17887)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17889)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17892)(content(Whitespace\" \")))))))))(Secondary((id \ + 17894)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17898)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 17899)(content(Whitespace\" \"))))(Tile((id \ + 17901)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 17902)(content(Whitespace\" \"))))(Tile((id \ + 17903)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17905)(content(Whitespace\" \"))))(Secondary((id \ + 17906)(content(Whitespace\" \"))))(Grout((id 17908)(shape \ + Convex)))(Tile((id 17907)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17910)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 17911)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 17916)(label(Bool))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 17917)(content(Whitespace\" \")))))((Secondary((id \ + 17919)(content(Whitespace\" \"))))(Tile((id \ + 17921)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17922)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17927)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17930)(content(Whitespace\" \")))))))))(Secondary((id \ + 17932)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17936)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 17937)(content(Whitespace\" \"))))(Tile((id \ + 17939)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 17940)(content(Whitespace\" \"))))(Tile((id \ + 17941)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17943)(content(Whitespace\" \"))))(Tile((id \ + 17944)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 17946)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17947)(content(Whitespace\" \"))))(Tile((id \ + 17948)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 17950)(content(Whitespace\" \"))))(Tile((id \ + 17954)(label(Dawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 17955)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17957)(content(Whitespace\" \"))))(Tile((id \ + 17960)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 17961)(content(Whitespace\" \")))))((Secondary((id \ + 17963)(content(Whitespace\" \"))))(Tile((id \ + 17964)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 17968)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17969)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 17971)(label(5))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 17974)(content(Whitespace\" \")))))))))(Secondary((id \ + 17976)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 17980)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 17981)(content(Whitespace\" \"))))(Tile((id \ + 17983)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 17984)(content(Whitespace\" \"))))(Tile((id \ + 17985)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17987)(content(Whitespace\" \"))))(Tile((id \ + 17998)(label(DoubleAlias))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 17999)(content(Whitespace\" \")))))((Secondary((id \ + 18001)(content(Whitespace\" \"))))(Tile((id \ + 18002)(label(C))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18003)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18005)(label(4))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18008)(content(Whitespace\" \")))))))))(Secondary((id \ + 18010)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 18011)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 18029)(content(Comment\"#exp tests: \ + errors#\"))))(Secondary((id \ + 18030)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18034)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18035)(content(Whitespace\" \"))))(Tile((id \ + 18037)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18038)(content(Whitespace\" \")))))((Secondary((id \ + 18040)(content(Whitespace\" \"))))(Tile((id \ + 18041)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18042)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18044)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18047)(content(Whitespace\" \")))))))))(Secondary((id \ + 18049)(content(Whitespace\" \"))))(Secondary((id \ + 18072)(content(Comment\"#err: incons with \ + arrow#\"))))(Secondary((id \ + 18073)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18077)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18078)(content(Whitespace\" \"))))(Tile((id \ + 18080)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18081)(content(Whitespace\" \")))))((Secondary((id \ + 18083)(content(Whitespace\" \"))))(Tile((id \ + 18092)(label(Undefined))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18093)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18095)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18098)(content(Whitespace\" \")))))))))(Secondary((id \ + 18100)(content(Whitespace\" \"))))(Secondary((id \ + 18120)(content(Comment\"#err: cons \ + undefined#\"))))(Secondary((id \ + 18121)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18125)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18126)(content(Whitespace\" \"))))(Tile((id \ + 18128)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18129)(content(Whitespace\" \")))))((Secondary((id \ + 18131)(content(Whitespace\" \"))))(Tile((id \ + 18132)(label(B))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18133)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18138)(label(\"\\\"lol\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18141)(content(Whitespace\" \")))))))))(Secondary((id \ + 18143)(content(Whitespace\" \"))))(Secondary((id \ + 18160)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18161)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18165)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18166)(content(Whitespace\" \"))))(Tile((id \ + 18168)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18169)(content(Whitespace\" \"))))(Tile((id \ + 18170)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18172)(content(Whitespace\" \"))))(Secondary((id \ + 18173)(content(Whitespace\" \"))))(Grout((id 18175)(shape \ + Convex)))(Tile((id 18174)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18177)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18178)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18183)(label(Bool))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 18184)(content(Whitespace\" \")))))((Secondary((id \ + 18186)(content(Whitespace\" \"))))(Tile((id \ + 18188)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 18191)(content(Whitespace\" \")))))))))(Secondary((id \ + 18193)(content(Whitespace\" \"))))(Secondary((id \ + 18210)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18211)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18215)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18216)(content(Whitespace\" \"))))(Tile((id \ + 18218)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18219)(content(Whitespace\" \"))))(Tile((id \ + 18220)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18222)(content(Whitespace\" \"))))(Secondary((id \ + 18223)(content(Whitespace\" \"))))(Grout((id 18225)(shape \ + Convex)))(Tile((id 18224)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18227)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18228)(content(Whitespace\" \")))))((Secondary((id \ + 18230)(content(Whitespace\" \"))))(Tile((id \ + 18232)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18233)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18238)(label(\"\\\"lol\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18241)(content(Whitespace\" \")))))))))(Secondary((id \ + 18243)(content(Whitespace\" \"))))(Secondary((id \ + 18260)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18261)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18265)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18266)(content(Whitespace\" \"))))(Tile((id \ + 18268)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18269)(content(Whitespace\" \"))))(Tile((id \ + 18270)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18272)(content(Whitespace\" \"))))(Secondary((id \ + 18273)(content(Whitespace\" \"))))(Grout((id 18275)(shape \ + Convex)))(Tile((id 18274)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18278)(label(One))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18279)(content(Whitespace\" \")))))((Secondary((id \ + 18281)(content(Whitespace\" \"))))(Tile((id \ + 18283)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18284)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18286)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18289)(content(Whitespace\" \")))))))))(Secondary((id \ + 18291)(content(Whitespace\" \"))))(Secondary((id \ + 18308)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18309)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 18310)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 18361)(content(Comment\"#pat tests: happy (but refutable \ + patterns so weird)#\"))))(Secondary((id \ + 18362)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18366)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18367)(content(Whitespace\" \"))))(Tile((id \ + 18370)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18371)(content(Whitespace\" \")))))((Secondary((id \ + 18373)(content(Whitespace\" \"))))(Tile((id \ + 18375)(label(Bo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 18378)(content(Whitespace\" \")))))))))(Secondary((id \ + 18380)(content(Whitespace\" \"))))(Secondary((id \ + 18401)(content(Comment\"#kind of a weird \ + edge#\"))))(Secondary((id \ + 18402)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18406)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18407)(content(Whitespace\" \"))))(Tile((id \ + 18410)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18411)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18413)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 18414)(content(Whitespace\" \")))))((Secondary((id \ + 18416)(content(Whitespace\" \"))))(Tile((id \ + 18420)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18421)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18426)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18429)(content(Whitespace\" \")))))))))(Secondary((id \ + 18431)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18435)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18436)(content(Whitespace\" \"))))(Tile((id \ + 18439)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18440)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18442)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 18443)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18445)(content(Whitespace\" \"))))(Tile((id \ + 18451)(label(YoDawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18452)(content(Whitespace\" \")))))((Secondary((id \ + 18454)(content(Whitespace\" \"))))(Tile((id \ + 18456)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18457)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18459)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18462)(content(Whitespace\" \")))))))))(Secondary((id \ + 18464)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18468)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18469)(content(Whitespace\" \"))))(Tile((id \ + 18472)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18473)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18475)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 18476)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18478)(content(Whitespace\" \"))))(Secondary((id \ + 18479)(content(Whitespace\" \"))))(Grout((id 18481)(shape \ + Convex)))(Tile((id 18480)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18483)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18484)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18488)(label(Int))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 18489)(content(Whitespace\" \")))))((Secondary((id \ + 18491)(content(Whitespace\" \"))))(Tile((id \ + 18493)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18494)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18496)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18499)(content(Whitespace\" \")))))))))(Secondary((id \ + 18501)(content(Whitespace\" \"))))(Secondary((id \ + 18502)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18506)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18507)(content(Whitespace\" \"))))(Tile((id \ + 18510)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18511)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18513)(content(Whitespace\" \"))))(Secondary((id \ + 18514)(content(Whitespace\" \"))))(Grout((id 18516)(shape \ + Convex)))(Tile((id 18515)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18518)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18519)(content(Whitespace\" \")))))((Secondary((id \ + 18521)(content(Whitespace\" \"))))(Tile((id \ + 18523)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 18526)(content(Whitespace\" \")))))))))(Secondary((id \ + 18528)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 18529)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 18547)(content(Comment\"#pat tests: \ + errors#\"))))(Secondary((id \ + 18548)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18552)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18553)(content(Whitespace\" \"))))(Tile((id \ + 18555)(label(2))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18556)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18558)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 18559)(content(Whitespace\" \")))))((Secondary((id \ + 18561)(content(Whitespace\" \"))))(Tile((id \ + 18562)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 18565)(content(Whitespace\" \")))))))))(Secondary((id \ + 18567)(content(Whitespace\" \"))))(Secondary((id \ + 18590)(content(Comment\"#err: incons with \ + arrow#\"))))(Secondary((id \ + 18591)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18595)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18596)(content(Whitespace\" \"))))(Tile((id \ + 18607)(label(NotDefined))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18608)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18610)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 18611)(content(Whitespace\" \")))))((Secondary((id \ + 18613)(content(Whitespace\" \"))))(Tile((id \ + 18614)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 18617)(content(Whitespace\" \")))))))))(Secondary((id \ + 18619)(content(Whitespace\" \"))))(Secondary((id \ + 18639)(content(Comment\"#err: cons \ + undefined#\"))))(Secondary((id \ + 18640)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18644)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18645)(content(Whitespace\" \"))))(Tile((id \ + 18648)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18649)(content(Whitespace\" \")))))((Secondary((id \ + 18651)(content(Whitespace\" \"))))(Tile((id \ + 18655)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 18658)(content(Whitespace\" \")))))))))(Secondary((id \ + 18660)(content(Whitespace\" \"))))(Secondary((id \ + 18677)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18678)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18682)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18683)(content(Whitespace\" \"))))(Tile((id \ + 18686)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18687)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18692)(label(true))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 18693)(content(Whitespace\" \")))))((Secondary((id \ + 18695)(content(Whitespace\" \"))))(Tile((id \ + 18699)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18700)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18705)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18708)(content(Whitespace\" \")))))))))(Secondary((id \ + 18710)(content(Whitespace\" \"))))(Secondary((id \ + 18727)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18728)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18732)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18733)(content(Whitespace\" \"))))(Tile((id \ + 18736)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18737)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18739)(content(Whitespace\" \"))))(Tile((id \ + 18745)(label(YoDawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18746)(content(Whitespace\" \")))))((Secondary((id \ + 18748)(content(Whitespace\" \"))))(Tile((id \ + 18750)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18751)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18753)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18756)(content(Whitespace\" \")))))))))(Secondary((id \ + 18758)(content(Whitespace\" \"))))(Secondary((id \ + 18775)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18776)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18780)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18781)(content(Whitespace\" \"))))(Tile((id \ + 18784)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18785)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18787)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 18788)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18790)(content(Whitespace\" \"))))(Secondary((id \ + 18791)(content(Whitespace\" \"))))(Grout((id 18793)(shape \ + Convex)))(Tile((id 18792)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18795)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 18796)(content(Whitespace\" \")))))((Secondary((id \ + 18798)(content(Whitespace\" \"))))(Tile((id \ + 18800)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 18803)(content(Whitespace\" \")))))))))(Secondary((id \ + 18805)(content(Whitespace\" \"))))(Secondary((id \ + 18822)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18823)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18827)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 18828)(content(Whitespace\" \"))))(Tile((id \ + 18831)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18832)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18834)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 18835)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 18837)(content(Whitespace\" \"))))(Secondary((id \ + 18838)(content(Whitespace\" \"))))(Grout((id 18840)(shape \ + Convex)))(Tile((id 18839)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18842)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 18843)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 18848)(label(Bool))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 18849)(content(Whitespace\" \")))))((Secondary((id \ + 18851)(content(Whitespace\" \"))))(Tile((id \ + 18853)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 18854)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 18859)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 18862)(content(Whitespace\" \")))))))))(Secondary((id \ + 18864)(content(Whitespace\" \"))))(Secondary((id \ + 18881)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 18882)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 18899)(label(\"\\\"Thats all, folks\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 18900)(content(Whitespace\"\\226\\143\\142\")))))()))(ancestors())))(caret \ + Outer))"; + backup_text = + "#Non-recursive sum/alias tests#\n\ + #all lines with trailing err comment should have 1 error#\n\ + #no other lines should have errors#\n\n\ + #type definitions: no errors#\n\ + type = in\n\ + \ type SingleNull = +One in\n\ + \ type Single = +F(Int) in\n\ + \ type GoodSum = A + B + C(Int) in\n\ + \ type Partial = Ok( ) + in\n\ + \ type DoubleAlias = GoodSum in\n\ + \ type VerticalLeading =\n\ + \ + A\n\ + + B(GoodSum)\n\ + + C(Bool->Bool) \n\ + \ in\n\n\ + #incorrect or incomplete type definitions#\n\ + \ type badTypeName = in #err: invalid type name#\n\ + \ type ( , ) = in #err: invalid type name#\n\ + \ type = badTypeToken in #err: invalid type token#\n\ + \ type NotASum = NotInSum(Bool) in #err: cons not in sum#\n\ + \ type Bool = in #err: shadows base type#\n\ + \ type Dupes =\n\ + \ + Guy(Bool) #no err#\n\ + + Guy(Int) #err: already used#\n\ + + Guy in #err: already used#\n\ + \ type BadCons =\n\ + \ + Um(Unbound) #err: unbound type var#\n\ + + invalid #err: invalid#\n\ + + Bool #err: expected cons found type#\n\ + + Int(Int) #err: expected cons found type#\n\ + + ( )(Int) #err: expected cons found type#\n\ + + A(Bool)(Int) in #err: expected cons found app#\n\n\ + #nested sum defs dont add tags to scope#\n\ + \ type NestedAlias = (Int, Anonymous + Sum) in \n\ + \ let x:NestedAlias = (1, Sum) in #err: not defined#\n\n\ + #unbound tyvars treated as unknown-typehole#\n\ + let a:Bad = 0 in a == 0; #err: not bound#\n\n\ + #non-sum-types cant be recursive#\n\ + type Lol = Lol in #err: not bound#\n\n\ + #no errors: analytic shadowing#\n\ + \ type Tork1 = +Blob in\n\ + \ type Tork2 = +Blob in \n\ + \ let x:Tork1 = Blob in\n\n\ + #exp tests: happy#\n\ + type YoDawg = Yo(Int) + Bo(Int)+ Dawg(Bool) in\n\ + \ let _ = Yo(1) in\n\ + let _ : YoDawg = Yo(2) in\n\ + let _ : +Yo(Bool) = Yo(true) in\n\ + let _ : (Yo + Dawg, Int) = (Dawg,5) in\n\ + let _ : DoubleAlias = C(4) in\n\n\ + #exp tests: errors#\n\ + let _ = 2(1) in #err: incons with arrow#\n\ + let _ = Undefined(1) in #err: cons undefined#\n\ + let _ = B(\"lol\") in #err: type incons#\n\ + let _ : +Yo(Bool) = Yo in #err: type incons#\n\ + let _ : +Yo = Yo(\"lol\") in #err: type incons#\n\ + let _ : +One = Yo(1) in #err: type incons#\n\n\ + #pat tests: happy (but refutable patterns so weird)#\n\ + let Yo = Bo in #kind of a weird edge#\n\ + let Yo(1) = Dawg(true) in\n\ + let Yo(1): YoDawg = Yo(1) in\n\ + let Yo(1): +Yo(Int) = Yo(1) in \n\ + let Yo: +Yo = Yo in\n\n\ + #pat tests: errors#\n\ + let 2(1) = 3 in #err: incons with arrow#\n\ + let NotDefined(1) = 3 in #err: cons undefined#\n\ + let Yo = Dawg in #err: type incons#\n\ + let Yo(true) = Dawg(true) in #err: type incons#\n\ + let Yo: YoDawg = Yo(1) in #err: type incons#\n\ + let Yo(1): +Yo = Yo in #err: type incons#\n\ + let Yo(1): +Yo(Bool) = Yo(true) in #err: type incons#\n\ + \"Thats all, folks\"\n"; + } ); + ( 552, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Tile((id \ + 521)(label(step))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 522)(content(Whitespace\" \"))))(Secondary((id \ + 523)(content(Whitespace\" \"))))(Secondary((id \ + 524)(content(Whitespace\" \"))))(Tile((id \ + 525)(label(*))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 527)(content(Whitespace\" \"))))(Secondary((id \ + 528)(content(Whitespace\" \"))))(Secondary((id \ + 529)(content(Whitespace\" \"))))(Tile((id \ + 531)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 532)(content(Whitespace\" \"))))(Secondary((id \ + 533)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 536)(shape Concave)))(Tile((id 535)(label(2))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 537)(content(Whitespace\" \"))))(Tile((id \ + 538)(label(*))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 540)(content(Whitespace\" \"))))(Tile((id \ + 541)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 542)(content(Whitespace\" \"))))(Tile((id \ + 543)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 545)(content(Whitespace\" \"))))(Tile((id \ + 546)(label(4))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 547)(content(Whitespace\" \"))))(Tile((id \ + 548)(label(*))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 550)(content(Whitespace\" \"))))(Tile((id \ + 551)(label(5))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))()))(ancestors())))(caret \ + Outer))"; + backup_text = "step * in \n 2 * 3 + 4 * 5"; + } ); + ( 810, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Tile((id \ + 682)(label(type))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Grout((id 685)(shape \ + Concave)))(Tile((id 688)(label(Test))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 689)(content(Whitespace\" \"))))(Tile((id \ + 690)(label(=))(mold((out Any)(in_())(nibs(((shape(Concave \ + 8))(sort Any))((shape(Concave 8))(sort \ + Any))))))(shards(0))(children())))(Secondary((id \ + 692)(content(Whitespace\" \"))))(Secondary((id \ + 693)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 695)(shape Convex)))(Tile((id 694)(label(+))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 5))(sort \ + Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 696)(content(Whitespace\" \"))))(Tile((id \ + 697)(label(A))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 698)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 702)(label(Int))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 703)(content(Whitespace\" \"))))(Secondary((id \ + 704)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 705)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 707)(content(Whitespace\" \"))))(Tile((id \ + 708)(label(B))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 709)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 710)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 712)(content(Whitespace\" \"))))(Tile((id \ + 713)(label(C))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 714)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 720)(label(Float))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 721)(content(Whitespace\" \"))))(Secondary((id \ + 722)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 724)(shape Concave)))(Tile((id 725)(label(in))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 726)(content(Whitespace\" \"))))(Secondary((id \ + 727)(content(Whitespace\"\\226\\143\\142\"))))(Grout((id \ + 729)(shape Concave)))(Tile((id 732)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id 733)(content(Whitespace\" \ + \"))))(Tile((id 735)(label(x))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 736)(content(Whitespace\" \"))))(Tile((id \ + 737)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 739)(content(Whitespace\" \"))))(Tile((id \ + 743)(label(Test))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 744)(content(Whitespace\" \")))))((Secondary((id \ + 746)(content(Whitespace\" \"))))(Tile((id \ + 747)(label(C))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 748)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 752)(label(7.7))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 755)(content(Whitespace\" \")))))))))(Secondary((id \ + 757)(content(Whitespace\" \"))))(Secondary((id \ + 758)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 763)(label(case end))(mold((out Exp)(in_(Rul))(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 764)(content(Whitespace\" \ + \"))))(Tile((id 766)(label(x))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 767)(content(Whitespace\" \"))))(Secondary((id \ + 768)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 769)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 771)(content(Whitespace\" \ + \"))))(Tile((id 772)(label(A))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 773)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 775)(label(n))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 776)(content(Whitespace\" \")))))))))(Secondary((id \ + 779)(content(Whitespace\" \"))))(Tile((id \ + 780)(label(n))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 781)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 782)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 784)(content(Whitespace\" \ + \"))))(Tile((id 785)(label(B))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 786)(content(Whitespace\" \")))))))))(Secondary((id \ + 789)(content(Whitespace\" \"))))(Tile((id \ + 790)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 791)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 792)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 794)(content(Whitespace\" \ + \"))))(Tile((id 795)(label(C))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 796)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 798)(label(n))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 799)(content(Whitespace\" \")))))))))(Secondary((id \ + 802)(content(Whitespace\" \"))))(Tile((id \ + 803)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 807)(content(Whitespace\" \"))))(Secondary((id \ + 804)(content(Whitespace\" \"))))(Secondary((id \ + 805)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 809)(content(Whitespace\" \")))))()))(ancestors())))(caret \ + Outer))"; + backup_text = + "type Test = \n\ + \ + A(Int) \n\ + + B\n\ + + C(Float) \n\ + \ in \n\ + \ let x : Test = C(7.7) in \n\ + case x \n\ + | A(n) => n\n\ + | B => 2\n\ + | C(n) => 3 \n\ + end "; + } ); + ( 4, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Secondary((id \ + 2)(content(Whitespace\" \"))))(Secondary((id \ + 3)(content(Whitespace\" \")))))((Grout((id 0)(shape \ + Convex))))))(ancestors())))(caret Outer))"; + backup_text = " "; + } ); + ( 4, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Secondary((id \ + 2)(content(Whitespace\" \"))))(Secondary((id \ + 3)(content(Whitespace\" \")))))((Grout((id 0)(shape \ + Convex))))))(ancestors())))(caret Outer))"; + backup_text = " "; + } ); + ( 4, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Secondary((id \ + 2)(content(Whitespace\" \"))))(Secondary((id \ + 3)(content(Whitespace\" \")))))((Grout((id 0)(shape \ + Convex))))))(ancestors())))(caret Outer))"; + backup_text = " "; + } ); + ] ); + examples = + ( "Introduction", + [ + ( "Introduction", + ( 16872, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Secondary((id \ + 14750)(content(Comment\"# Welcome to Hazel! \ + #\"))))(Secondary((id \ + 15734)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 15735)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16048)(content(Comment\"# To get started, type 2 * 3 + 4 \ + into the hole below, #\"))))(Secondary((id \ + 15875)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16071)(content(Comment\"# stopping between each character \ + to observe how holes #\"))))(Secondary((id \ + 15941)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16868)(content(Comment\"# appear at each step to ensure \ + that every editor state #\"))))(Secondary((id \ + 16170)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16187)(content(Comment\"# is meaningful. \ + #\"))))(Secondary((id \ + 15830)(content(Whitespace\"\\226\\143\\142\")))))((Grout((id \ + 16871)(shape Convex)))(Secondary((id \ + 16009)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16010)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16295)(content(Comment\"# Once you are finished, navigate \ + the menu in the top bar #\"))))(Secondary((id \ + 16296)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16369)(content(Comment\"# to see other examples, enter \ + Scratch mode to play with #\"))))(Secondary((id \ + 16370)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16427)(content(Comment\"# Hazel, or enter Exercises mode to \ + do some introductory #\"))))(Secondary((id \ + 16428)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16650)(content(Comment\"# exercises. Hazel is a \ + work-in-progress research project, #\"))))(Secondary((id \ + 16569)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16793)(content(Comment\"# so there is not much public \ + educational material yet. #\"))))(Secondary((id \ + 16669)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16805)(content(Comment\"# Check out the research papers at \ + hazel.org for more on #\"))))(Secondary((id \ + 16745)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 16766)(content(Comment\"# how Hazel works. \ + #\")))))))(ancestors())))(caret Outer))"; + backup_text = + "# Welcome to Hazel! #\n\n\ + # To get started, type 2 * 3 + 4 into the hole below, #\n\ + # stopping between each character to observe how holes #\n\ + # appear at each step to ensure that every editor state #\n\ + # is meaningful. #\n\ + \ \n\n\ + # Once you are finished, navigate the menu in the top bar #\n\ + # to see other examples, enter Scratch mode to play with #\n\ + # Hazel, or enter Exercises mode to do some introductory #\n\ + # exercises. Hazel is a work-in-progress research project, #\n\ + # so there is not much public educational material yet. #\n\ + # Check out the research papers at hazel.org for more on #\n\ + # how Hazel works. #"; + } ) ); + ( "Basic Reference", + ( 13633, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(((Secondary((id \ + 1674)(content(Whitespace\" \"))))(Tile((id \ + 1685)(label(float_lits))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1686)(content(Whitespace\" \")))))((Tile((id \ + 1687)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1689)(content(Whitespace\" \"))))(Tile((id \ + 1694)(label(Float))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1695)(content(Whitespace\" \")))))))(ancestors((((id \ + 1673)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards((0)(1 \ + 2)))(children(()(((Secondary((id 1698)(content(Whitespace\" \ + \"))))(Tile((id 1701)(label(1.5))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1704)(content(Whitespace\" \")))))))))(((Secondary((id \ + 2915)(content(Comment\"# Hazel Language Quick Reference \ + #\"))))(Secondary((id \ + 3020)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3021)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3150)(content(Comment\"# Empty holes stand for missing \ + expressions, patterns, or types #\"))))(Secondary((id \ + 3030)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3035)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3036)(content(Whitespace\" \"))))(Tile((id \ + 3047)(label(empty_hole))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 3048)(content(Whitespace\" \")))))((Secondary((id \ + 3052)(content(Whitespace\" \"))))(Grout((id 3051)(shape \ + Convex)))(Secondary((id 3050)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 3151)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3152)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2840)(content(Comment\"# Integers #\"))))(Secondary((id \ + 2829)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1498)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1499)(content(Whitespace\" \"))))(Tile((id \ + 1508)(label(int_lits))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1509)(content(Whitespace\" \"))))(Tile((id \ + 1510)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1512)(content(Whitespace\" \"))))(Tile((id \ + 1515)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1516)(content(Whitespace\" \")))))((Secondary((id \ + 1519)(content(Whitespace\" \"))))(Tile((id \ + 1520)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1523)(content(Whitespace\" \")))))))))(Secondary((id \ + 1525)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1530)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1531)(content(Whitespace\" \"))))(Tile((id \ + 1540)(label(negation))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1541)(content(Whitespace\" \")))))((Secondary((id \ + 1544)(content(Whitespace\" \"))))(Tile((id \ + 1545)(label(-))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 2))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1546)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1549)(content(Whitespace\" \")))))))))(Secondary((id \ + 1551)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1556)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1557)(content(Whitespace\" \"))))(Tile((id \ + 1568)(label(arithmetic))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1569)(content(Whitespace\" \")))))((Secondary((id \ + 1572)(content(Whitespace\" \"))))(Tile((id \ + 1573)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1574)(label(*))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1576)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1577)(content(Whitespace\" \"))))(Tile((id \ + 1578)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1580)(content(Whitespace\" \"))))(Tile((id \ + 1581)(label(8))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1582)(label(/))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1584)(label(4))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1587)(content(Whitespace\" \")))))))))(Secondary((id \ + 1589)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1594)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1595)(content(Whitespace\" \"))))(Tile((id \ + 1610)(label(int_comparison))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1611)(content(Whitespace\" \")))))((Secondary((id \ + 1614)(content(Whitespace\" \"))))(Tile((id \ + 1615)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1617)(label(10))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1618)(content(Whitespace\" \"))))(Tile((id \ + 1621)(label(==))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1622)(content(Whitespace\" \"))))(Tile((id \ + 1624)(label(10))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1625)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1627)(content(Whitespace\" \"))))(Tile((id \ + 1628)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1629)(content(Whitespace\" \"))))(Tile((id \ + 1630)(label(<))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1632)(content(Whitespace\" \"))))(Tile((id \ + 1633)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1634)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1636)(content(Whitespace\" \"))))(Tile((id \ + 1637)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1638)(content(Whitespace\" \"))))(Tile((id \ + 1641)(label(<=))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1642)(content(Whitespace\" \"))))(Tile((id \ + 1643)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1644)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1646)(content(Whitespace\" \"))))(Tile((id \ + 1647)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1648)(content(Whitespace\" \"))))(Tile((id \ + 1649)(label(>))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1651)(content(Whitespace\" \"))))(Tile((id \ + 1652)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1653)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1655)(content(Whitespace\" \"))))(Tile((id \ + 1656)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1657)(content(Whitespace\" \"))))(Tile((id \ + 1660)(label(>=))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1661)(content(Whitespace\" \"))))(Tile((id \ + 1662)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1665)(content(Whitespace\" \")))))))))(Secondary((id \ + 3353)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2841)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2866)(content(Comment\"# Floating Point Numbers \ + #\"))))(Secondary((id \ + 1669)(content(Whitespace\"\\226\\143\\142\")))))((Secondary((id \ + 1706)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1711)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1712)(content(Whitespace\" \"))))(Tile((id \ + 1724)(label(float_artih))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1725)(content(Whitespace\" \")))))((Secondary((id \ + 1728)(content(Whitespace\" \"))))(Tile((id \ + 1730)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1731)(content(Whitespace\" \"))))(Tile((id \ + 1734)(label(*.))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1735)(content(Whitespace\" \"))))(Tile((id \ + 1737)(label(2.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1738)(content(Whitespace\" \"))))(Tile((id \ + 1741)(label(+.))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1742)(content(Whitespace\" \"))))(Tile((id \ + 1744)(label(8.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1745)(content(Whitespace\" \"))))(Tile((id \ + 1748)(label(/.))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1749)(content(Whitespace\" \"))))(Tile((id \ + 1751)(label(4.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1754)(content(Whitespace\" \")))))))))(Secondary((id \ + 1756)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1761)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1762)(content(Whitespace\" \"))))(Tile((id \ + 1779)(label(float_comparison))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1780)(content(Whitespace\" \")))))((Secondary((id \ + 1783)(content(Whitespace\" \"))))(Tile((id \ + 1784)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1787)(label(10.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1788)(content(Whitespace\" \"))))(Tile((id \ + 1792)(label(==.))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1793)(content(Whitespace\" \"))))(Tile((id \ + 1796)(label(10.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1797)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1799)(content(Whitespace\" \"))))(Tile((id \ + 1801)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1802)(content(Whitespace\" \"))))(Tile((id \ + 1805)(label(<.))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1806)(content(Whitespace\" \"))))(Tile((id \ + 1808)(label(2.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1809)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1811)(content(Whitespace\" \"))))(Tile((id \ + 1813)(label(2.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1814)(content(Whitespace\" \"))))(Tile((id \ + 1818)(label(<=.))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1819)(content(Whitespace\" \"))))(Tile((id \ + 1821)(label(3.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1822)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1824)(content(Whitespace\" \"))))(Tile((id \ + 1826)(label(3.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1827)(content(Whitespace\" \"))))(Tile((id \ + 1830)(label(>.))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1831)(content(Whitespace\" \"))))(Tile((id \ + 1833)(label(2.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1834)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1836)(content(Whitespace\" \"))))(Tile((id \ + 1838)(label(2.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1839)(content(Whitespace\" \"))))(Tile((id \ + 1843)(label(>=.))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1844)(content(Whitespace\" \"))))(Tile((id \ + 13632)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1849)(content(Whitespace\" \")))))))))(Secondary((id \ + 1851)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2867)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2878)(content(Comment\"# Booleans #\"))))(Secondary((id \ + 1853)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1857)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1858)(content(Whitespace\" \"))))(Tile((id \ + 1867)(label(booleans))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1868)(content(Whitespace\" \"))))(Tile((id \ + 1869)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1871)(content(Whitespace\" \"))))(Tile((id \ + 1872)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 1876)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 1877)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1879)(content(Whitespace\" \"))))(Tile((id \ + 1883)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 1884)(content(Whitespace\" \")))))((Secondary((id \ + 1887)(content(Whitespace\" \"))))(Tile((id \ + 1888)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1892)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1893)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1895)(content(Whitespace\" \"))))(Tile((id \ + 1900)(label(false))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1903)(content(Whitespace\" \")))))))))(Secondary((id \ + 1905)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1910)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1911)(content(Whitespace\" \"))))(Tile((id \ + 1924)(label(conditionals))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1925)(content(Whitespace\" \")))))((Secondary((id \ + 1928)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1932)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1933)(content(Whitespace\" \"))))(Tile((id \ + 1935)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 1936)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1937)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1939)(content(Whitespace\" \"))))(Tile((id \ + 1940)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 1941)(content(Whitespace\" \")))))((Secondary((id \ + 1944)(content(Whitespace\" \"))))(Tile((id \ + 1945)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1946)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1947)(content(Whitespace\" \"))))(Tile((id \ + 1948)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1950)(content(Whitespace\" \"))))(Tile((id \ + 1951)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1952)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1954)(content(Whitespace\" \"))))(Tile((id \ + 1955)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1956)(content(Whitespace\" \"))))(Tile((id \ + 1957)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1959)(content(Whitespace\" \"))))(Tile((id \ + 1960)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1963)(content(Whitespace\" \")))))))))(Secondary((id \ + 1965)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1969)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1970)(content(Whitespace\" \"))))(Tile((id \ + 1972)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1973)(content(Whitespace\" \"))))(Tile((id \ + 1974)(label(>))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1976)(content(Whitespace\" \"))))(Tile((id \ + 1977)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1980)(content(Whitespace\" \")))))((Secondary((id \ + 1984)(content(Whitespace\" \"))))(Tile((id \ + 1986)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1991)(content(Whitespace\" \"))))(Secondary((id \ + 1987)(content(Whitespace\" \"))))(Secondary((id \ + 1988)(content(Whitespace\" \"))))(Secondary((id \ + 1989)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 1995)(content(Whitespace\" \"))))(Tile((id \ + 1997)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2002)(content(Whitespace\" \"))))(Secondary((id \ + 1998)(content(Whitespace\" \"))))(Secondary((id \ + 1999)(content(Whitespace\" \"))))(Secondary((id \ + 2000)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2004)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2916)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2925)(content(Comment\"# Tuples #\"))))(Secondary((id \ + 2006)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2010)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2011)(content(Whitespace\" \"))))(Tile((id \ + 2018)(label(tuples))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2019)(content(Whitespace\" \"))))(Tile((id \ + 2020)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2022)(content(Whitespace\" \"))))(Tile((id \ + 2023)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 2026)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2027)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2029)(content(Whitespace\" \"))))(Tile((id \ + 2033)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2034)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2036)(content(Whitespace\" \"))))(Tile((id \ + 2037)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 2041)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2042)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2044)(content(Whitespace\" \"))))(Tile((id \ + 2047)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))))))))))))(Secondary((id \ + 2048)(content(Whitespace\" \")))))((Secondary((id \ + 2051)(content(Whitespace\" \"))))(Tile((id \ + 2052)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2053)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2054)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2056)(content(Whitespace\" \"))))(Tile((id \ + 2060)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2061)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2063)(content(Whitespace\" \"))))(Tile((id \ + 2064)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2069)(label(false))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2070)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2072)(content(Whitespace\" \"))))(Tile((id \ + 2073)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))))))))))))(Secondary((id \ + 2076)(content(Whitespace\" \")))))))))(Secondary((id \ + 2078)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2083)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2084)(content(Whitespace\" \"))))(Tile((id \ + 2086)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 2087)(label(a))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2088)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2090)(content(Whitespace\" \"))))(Tile((id \ + 2091)(label(b))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2092)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2094)(content(Whitespace\" \"))))(Tile((id \ + 2095)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 2096)(label(c))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2097)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2099)(content(Whitespace\" \"))))(Tile((id \ + 2100)(label(d))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))))))))))))(Secondary((id \ + 2101)(content(Whitespace\" \")))))((Secondary((id \ + 2104)(content(Whitespace\" \"))))(Tile((id \ + 2110)(label(tuples))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2113)(content(Whitespace\" \")))))))))(Secondary((id \ + 2115)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2926)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2938)(content(Comment\"# Functions #\"))))(Secondary((id \ + 2117)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2121)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2122)(content(Whitespace\" \"))))(Tile((id \ + 2124)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2125)(content(Whitespace\" \"))))(Tile((id \ + 2126)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2128)(content(Whitespace\" \"))))(Tile((id \ + 2129)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 2132)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2133)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2135)(content(Whitespace\" \"))))(Tile((id \ + 2138)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2139)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2141)(content(Whitespace\" \"))))(Tile((id \ + 2144)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2145)(content(Whitespace\" \"))))(Tile((id \ + 2148)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2149)(content(Whitespace\" \"))))(Tile((id \ + 2152)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2153)(content(Whitespace\" \")))))((Secondary((id \ + 2156)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2160)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 2161)(content(Whitespace\" \"))))(Tile((id \ + 2163)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 2164)(label(m))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2165)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2167)(content(Whitespace\" \"))))(Tile((id \ + 2168)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2169)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2171)(content(Whitespace\" \"))))(Tile((id \ + 2172)(label(b))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 2173)(content(Whitespace\" \")))))))))(Secondary((id \ + 2177)(content(Whitespace\" \"))))(Tile((id \ + 2178)(label(m))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2179)(content(Whitespace\" \"))))(Tile((id \ + 2180)(label(*))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 4))(sort Exp))((shape(Concave 4))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2182)(content(Whitespace\" \"))))(Tile((id \ + 2183)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2184)(content(Whitespace\" \"))))(Tile((id \ + 2185)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2187)(content(Whitespace\" \"))))(Tile((id \ + 2188)(label(b))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2193)(content(Whitespace\" \"))))(Secondary((id \ + 2189)(content(Whitespace\" \"))))(Secondary((id \ + 2190)(content(Whitespace\" \"))))(Secondary((id \ + 2191)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2195)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2939)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2998)(content(Comment\"# Recursive Functions (arrow type \ + annotation required) #\"))))(Secondary((id \ + 2197)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2201)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2202)(content(Whitespace\" \"))))(Tile((id \ + 2221)(label(double_recursively))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2222)(content(Whitespace\" \"))))(Tile((id \ + 2223)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2225)(content(Whitespace\" \"))))(Tile((id \ + 2228)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2229)(content(Whitespace\" \"))))(Tile((id \ + 2232)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2233)(content(Whitespace\" \"))))(Tile((id \ + 2236)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2237)(content(Whitespace\" \")))))((Secondary((id \ + 2240)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2244)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 2245)(content(Whitespace\" \"))))(Tile((id \ + 2247)(label(n))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2248)(content(Whitespace\" \")))))))))(Secondary((id \ + 2252)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2255)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2256)(content(Whitespace\" \"))))(Tile((id \ + 2258)(label(n))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2259)(content(Whitespace\" \"))))(Tile((id \ + 2262)(label(==))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2263)(content(Whitespace\" \"))))(Tile((id \ + 2264)(label(0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2267)(content(Whitespace\" \")))))((Secondary((id \ + 2271)(content(Whitespace\" \"))))(Tile((id \ + 2273)(label(0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2278)(content(Whitespace\" \"))))(Secondary((id \ + 2274)(content(Whitespace\" \"))))(Secondary((id \ + 2275)(content(Whitespace\" \"))))(Secondary((id \ + 2276)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2282)(content(Whitespace\" \"))))(Tile((id \ + 2301)(label(double_recursively))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 2302)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2304)(label(n))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2305)(content(Whitespace\" \"))))(Tile((id \ + 2306)(label(-))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2308)(content(Whitespace\" \"))))(Tile((id \ + 2309)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 2310)(content(Whitespace\" \"))))(Tile((id \ + 2311)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2313)(content(Whitespace\" \"))))(Tile((id \ + 2314)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2319)(content(Whitespace\" \"))))(Secondary((id \ + 2315)(content(Whitespace\" \"))))(Secondary((id \ + 2316)(content(Whitespace\" \"))))(Secondary((id \ + 2317)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2321)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2999)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3007)(content(Comment\"# Lists #\"))))(Secondary((id \ + 2323)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2327)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2328)(content(Whitespace\" \"))))(Tile((id \ + 2339)(label(empty_list))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2340)(content(Whitespace\" \"))))(Tile((id \ + 2341)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2343)(content(Whitespace\" \"))))(Tile((id 2344)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 2347)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2348)(content(Whitespace\" \")))))((Secondary((id \ + 2351)(content(Whitespace\" \"))))(Tile((id \ + 2354)(label([]))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2357)(content(Whitespace\" \")))))))))(Secondary((id \ + 2359)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2364)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2365)(content(Whitespace\" \"))))(Tile((id \ + 2380)(label(non_empty_list))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2381)(content(Whitespace\" \"))))(Tile((id \ + 2382)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2384)(content(Whitespace\" \"))))(Tile((id 2385)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 2388)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2389)(content(Whitespace\" \")))))((Secondary((id \ + 2392)(content(Whitespace\" \"))))(Tile((id \ + 2393)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2396)(label(::))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 6))(sort Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2397)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2400)(label(::))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 6))(sort Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2401)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2404)(label(::))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 6))(sort Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2407)(label([]))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2410)(content(Whitespace\" \")))))))))(Secondary((id \ + 2412)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2417)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2418)(content(Whitespace\" \"))))(Tile((id \ + 2432)(label(list_literals))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2433)(content(Whitespace\" \"))))(Tile((id \ + 2434)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2436)(content(Whitespace\" \"))))(Tile((id 2437)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 2440)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2441)(content(Whitespace\" \")))))((Secondary((id \ + 2444)(content(Whitespace\" \"))))(Tile((id 2445)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 2446)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 2447)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2449)(content(Whitespace\" \"))))(Tile((id \ + 2450)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2451)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2453)(content(Whitespace\" \"))))(Tile((id \ + 2454)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 2457)(content(Whitespace\" \")))))))))(Secondary((id \ + 2459)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2464)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2465)(content(Whitespace\" \"))))(Tile((id \ + 2472)(label(length))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2473)(content(Whitespace\" \"))))(Tile((id \ + 2474)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2476)(content(Whitespace\" \"))))(Tile((id 2477)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 2480)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2481)(content(Whitespace\" \"))))(Tile((id \ + 2484)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2485)(content(Whitespace\" \"))))(Tile((id \ + 2488)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2489)(content(Whitespace\" \")))))((Secondary((id \ + 2492)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2496)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 2497)(content(Whitespace\" \"))))(Tile((id \ + 2500)(label(xs))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2501)(content(Whitespace\" \")))))))))(Secondary((id \ + 2505)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2510)(label(case end))(mold((out \ + Exp)(in_(Rul))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2511)(content(Whitespace\" \ + \"))))(Tile((id 2514)(label(xs))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2515)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2516)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2518)(content(Whitespace\" \ + \"))))(Tile((id 2521)(label([]))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2522)(content(Whitespace\" \")))))))))(Secondary((id \ + 2525)(content(Whitespace\" \"))))(Tile((id \ + 2526)(label(0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2527)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2528)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2530)(content(Whitespace\" \ + \"))))(Tile((id 2532)(label(hd))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 2535)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 6))(sort Pat))((shape(Concave 6))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2537)(label(tl))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2538)(content(Whitespace\" \")))))))))(Secondary((id \ + 2541)(content(Whitespace\" \"))))(Tile((id \ + 2542)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2543)(content(Whitespace\" \"))))(Tile((id \ + 2544)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2546)(content(Whitespace\" \"))))(Tile((id \ + 2552)(label(length))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2553)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2556)(label(tl))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 2561)(content(Whitespace\" \"))))(Secondary((id \ + 2557)(content(Whitespace\" \"))))(Secondary((id \ + 2558)(content(Whitespace\" \"))))(Secondary((id \ + 2559)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2568)(content(Whitespace\" \"))))(Secondary((id \ + 2564)(content(Whitespace\" \"))))(Secondary((id \ + 2565)(content(Whitespace\" \"))))(Secondary((id \ + 2566)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2570)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2575)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2576)(content(Whitespace\" \"))))(Tile((id \ + 2602)(label(has_at_least_two_elements))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2603)(content(Whitespace\" \"))))(Tile((id \ + 2604)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2606)(content(Whitespace\" \"))))(Tile((id 2607)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 2610)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2611)(content(Whitespace\" \"))))(Tile((id \ + 2614)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2615)(content(Whitespace\" \"))))(Tile((id \ + 2619)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2620)(content(Whitespace\" \")))))((Secondary((id \ + 2623)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2627)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 2628)(content(Whitespace\" \"))))(Tile((id \ + 2631)(label(xs))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2632)(content(Whitespace\" \")))))))))(Secondary((id \ + 2636)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2641)(label(case end))(mold((out \ + Exp)(in_(Rul))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2642)(content(Whitespace\" \ + \"))))(Tile((id 2645)(label(xs))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2646)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2647)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2649)(content(Whitespace\" \ + \"))))(Tile((id 2652)(label([]))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2653)(content(Whitespace\" \")))))))))(Secondary((id \ + 2656)(content(Whitespace\" \"))))(Tile((id \ + 2661)(label(false))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2662)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2663)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2665)(content(Whitespace\" \ + \"))))(Tile((id 2667)(label(hd))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 2670)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 6))(sort Pat))((shape(Concave 6))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2673)(label([]))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2674)(content(Whitespace\" \")))))))))(Secondary((id \ + 2677)(content(Whitespace\" \"))))(Tile((id \ + 2682)(label(false))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2683)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2684)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2686)(content(Whitespace\" \ + \"))))(Tile((id 2687)(label(a))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 2690)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 6))(sort Pat))((shape(Concave 6))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2691)(label(b))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2694)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 6))(sort Pat))((shape(Concave 6))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2697)(label([]))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2698)(content(Whitespace\" \")))))))))(Secondary((id \ + 2701)(content(Whitespace\" \"))))(Tile((id \ + 2705)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2710)(content(Whitespace\" \"))))(Secondary((id \ + 2706)(content(Whitespace\" \"))))(Secondary((id \ + 2707)(content(Whitespace\" \"))))(Secondary((id \ + 2708)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2717)(content(Whitespace\" \"))))(Secondary((id \ + 2713)(content(Whitespace\" \"))))(Secondary((id \ + 2714)(content(Whitespace\" \"))))(Secondary((id \ + 2715)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2719)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3008)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3018)(content(Comment\"# Strings #\"))))(Secondary((id \ + 2722)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2726)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2727)(content(Whitespace\" \"))))(Tile((id \ + 2739)(label(string_lits))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2740)(content(Whitespace\" \")))))((Secondary((id \ + 2743)(content(Whitespace\" \"))))(Tile((id \ + 2757)(label(\"\\\"Hello, world!\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2760)(content(Whitespace\" \")))))))))(Secondary((id \ + 2762)(content(Whitespace\" \"))))(Secondary((id \ + 2764)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2768)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2769)(content(Whitespace\" \"))))(Tile((id \ + 2785)(label(string_equality))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2786)(content(Whitespace\" \")))))((Secondary((id \ + 2789)(content(Whitespace\" \"))))(Tile((id \ + 2800)(label(string_lits))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2801)(content(Whitespace\" \"))))(Tile((id \ + 2805)(label($==))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2806)(content(Whitespace\" \"))))(Tile((id \ + 2820)(label(\"\\\"Hello, world!\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2823)(content(Whitespace\" \")))))))))(Secondary((id \ + 2825)(content(Whitespace\" \"))))(Secondary((id \ + 3019)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3409)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3466)(content(Comment\"# Non-empty holes are the red dotted \ + boxes around errors #\"))))(Secondary((id \ + 3467)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3519)(content(Comment\"# (you can still run programs with \ + non-empty holes) #\"))))(Secondary((id \ + 3520)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3524)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3525)(content(Whitespace\" \"))))(Tile((id \ + 3540)(label(non_empty_hole))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 3541)(content(Whitespace\" \"))))(Tile((id \ + 3542)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3544)(content(Whitespace\" \"))))(Tile((id \ + 3547)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3548)(content(Whitespace\" \")))))((Secondary((id \ + 3551)(content(Whitespace\" \"))))(Tile((id \ + 3555)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 3558)(content(Whitespace\" \")))))))))(Secondary((id \ + 3560)(content(Whitespace\" \"))))(Secondary((id \ + 3562)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3563)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3564)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 3565)(content(Whitespace\" \"))))(Tile((id \ + 3566)(label(+))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 5))(sort Exp))((shape(Concave 5))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 3568)(content(Whitespace\" \"))))(Tile((id \ + 3569)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2827)(content(Whitespace\"\\226\\143\\142\")))))))))))(caret \ + Outer))"; + backup_text = + "# Hazel Language Quick Reference #\n\n\ + # Empty holes stand for missing expressions, patterns, or \ + types #\n\ + let empty_hole = in\n\n\ + # Integers #\n\ + let int_lits : Int = 1 in\n\ + let negation = -1 in\n\ + let arithmetic = 1*2 + 8/4 in\n\ + let int_comparison = (10 == 10, 1 < 2, 2 <= 3, 3 > 2, 2 >= \ + 1) in\n\n\ + # Floating Point Numbers #\n\ + let float_lits : Float = 1.5 in\n\ + let float_artih = 1. *. 2. +. 8. /. 4. in\n\ + let float_comparison = (10. ==. 10., 1. <. 2., 2. <=. 3., \ + 3. >. 2., 2. >=. 1.) in\n\n\ + # Booleans #\n\ + let booleans : (Bool, Bool) = (true, false) in\n\ + let conditionals =\n\ + let (x, y) = (2 + 2, 3 + 3) in\n\ + if y > x then 1 \n\ + else 2 \n\ + in\n\n\ + # Tuples #\n\ + let tuples : (Int, Bool, (Bool, Int)) = (1, true, (false, \ + 3)) in\n\ + let (a, b, (c, d)) = tuples in\n\n\ + # Functions #\n\ + let y : (Int, Int, Int) -> Int =\n\ + fun (m, x, b) -> m * x + b \n\ + in\n\n\ + # Recursive Functions (arrow type annotation required) #\n\ + let double_recursively : Int -> Int =\n\ + fun n ->\n\ + if n == 0 then 0 \n\ + else double_recursively(n - 1) + 2 \n\ + in\n\n\ + # Lists #\n\ + let empty_list : [Int] = [] in\n\ + let non_empty_list : [Int] = 1::2::3::[] in\n\ + let list_literals : [Int] = [1, 2, 3] in\n\ + let length : [Int] -> Int =\n\ + fun xs ->\n\ + case xs\n\ + | [] => 0\n\ + | hd::tl => 1 + length(tl) \n\ + end \n\ + in\n\ + let has_at_least_two_elements : [Int] -> Bool =\n\ + fun xs ->\n\ + case xs\n\ + | [] => false\n\ + | hd::[] => false\n\ + | a::b::[] => true \n\ + end \n\ + in\n\n\ + # Strings #\n\ + let string_lits = \"Hello, world!\" in \n\ + let string_equality = string_lits $== \"Hello, world!\" in \n\n\ + # Non-empty holes are the red dotted boxes around errors #\n\ + # (you can still run programs with non-empty holes) #\n\ + let non_empty_hole : Int = true in \n\n\ + 2 + 2\n"; + } ) ); + ( "Types & errors", + ( 25454, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(()((Secondary((id \ + 23732)(content(Comment\"#Types and type error \ + examples#\"))))(Secondary((id \ + 23733)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 23734)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 23738)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25393)(content(Whitespace\" \"))))(Tile((id \ + 25396)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 23739)(content(Whitespace\" \")))))((Secondary((id \ + 23744)(content(Whitespace\" \"))))(Tile((id \ + 23751)(label(unbound))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23754)(content(Whitespace\" \")))))))))(Secondary((id \ + 23756)(content(Whitespace\" \"))))(Secondary((id \ + 23760)(content(Comment #err#))))(Secondary((id \ + 23761)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 23765)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 23766)(content(Whitespace\" \"))))(Tile((id \ + 23776)(label(Undefined))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 23777)(content(Whitespace\" \")))))((Secondary((id \ + 23779)(content(Whitespace\" \"))))(Tile((id \ + 23788)(label(Undefined))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23791)(content(Whitespace\" \")))))))))(Secondary((id \ + 23793)(content(Whitespace\" \"))))(Secondary((id \ + 23801)(content(Comment\"# 2x err#\"))))(Secondary((id \ + 23802)(content(Whitespace\" \"))))(Secondary((id \ + 23803)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 23807)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 23808)(content(Whitespace\" \"))))(Tile((id \ + 23813)(label(true))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 23814)(content(Whitespace\" \")))))((Secondary((id \ + 23816)(content(Whitespace\" \"))))(Tile((id \ + 23817)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23820)(content(Whitespace\" \")))))))))(Secondary((id \ + 23822)(content(Whitespace\" \"))))(Secondary((id \ + 23826)(content(Comment #err#))))(Secondary((id \ + 23827)(content(Whitespace\" \"))))(Secondary((id \ + 23828)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 23829)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 23833)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25453)(content(Whitespace\" \"))))(Grout((id 23838)(shape \ + Convex)))(Secondary((id 23834)(content(Whitespace\" \ + \")))))((Secondary((id 23839)(content(Whitespace\" \ + \"))))(Tile((id 23842)(label(if then else))(mold((out \ + Exp)(in_(Exp Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 12))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id 23843)(content(Whitespace\" \ + \"))))(Tile((id 23848)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23851)(content(Whitespace\" \")))))((Secondary((id \ + 23855)(content(Whitespace\" \"))))(Tile((id \ + 23856)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23859)(content(Whitespace\" \")))))))))(Secondary((id \ + 23863)(content(Whitespace\" \"))))(Tile((id \ + 23865)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23868)(content(Whitespace\" \")))))))))(Secondary((id \ + 23870)(content(Whitespace\" \"))))(Secondary((id \ + 23874)(content(Comment #err#))))(Secondary((id \ + 23875)(content(Whitespace\" \"))))(Secondary((id \ + 23876)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 23880)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 23881)(content(Whitespace\" \"))))(Tile((id \ + 23883)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 23884)(content(Whitespace\" \")))))((Secondary((id \ + 23886)(content(Whitespace\" \"))))(Tile((id 23889)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 23890)(content(Whitespace\" \"))))(Tile((id \ + 23895)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23898)(content(Whitespace\" \")))))((Secondary((id \ + 23902)(content(Whitespace\" \"))))(Tile((id \ + 23903)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23906)(content(Whitespace\" \")))))))))(Secondary((id \ + 23910)(content(Whitespace\" \"))))(Tile((id \ + 23912)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23915)(content(Whitespace\" \")))))))))(Secondary((id \ + 23917)(content(Whitespace\" \"))))(Secondary((id \ + 23921)(content(Comment #err#))))(Secondary((id \ + 23922)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 23926)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 23927)(content(Whitespace\" \"))))(Tile((id \ + 23929)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 23930)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25452)(content(Whitespace\" \"))))(Grout((id 23935)(shape \ + Convex)))(Secondary((id 23932)(content(Whitespace\" \ + \")))))((Secondary((id 23936)(content(Whitespace\" \ + \"))))(Tile((id 23939)(label(if then else))(mold((out \ + Exp)(in_(Exp Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 12))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id 23940)(content(Whitespace\" \ + \"))))(Tile((id 23945)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23948)(content(Whitespace\" \")))))((Secondary((id \ + 23952)(content(Whitespace\" \"))))(Tile((id \ + 23953)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23956)(content(Whitespace\" \")))))))))(Secondary((id \ + 23960)(content(Whitespace\" \"))))(Tile((id \ + 23962)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23965)(content(Whitespace\" \")))))))))(Secondary((id \ + 23967)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 23971)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 23972)(content(Whitespace\" \"))))(Tile((id \ + 23974)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 23975)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 23977)(content(Whitespace\" \"))))(Tile((id \ + 23980)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 23981)(content(Whitespace\" \")))))((Secondary((id \ + 23983)(content(Whitespace\" \"))))(Tile((id 23986)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 23987)(content(Whitespace\" \"))))(Tile((id \ + 23992)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23995)(content(Whitespace\" \")))))((Secondary((id \ + 23999)(content(Whitespace\" \"))))(Tile((id \ + 24000)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24003)(content(Whitespace\" \")))))))))(Secondary((id \ + 24007)(content(Whitespace\" \"))))(Tile((id \ + 24009)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24012)(content(Whitespace\" \")))))))))(Secondary((id \ + 24014)(content(Whitespace\" \"))))(Secondary((id \ + 24018)(content(Comment #err#))))(Secondary((id \ + 24019)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24023)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24024)(content(Whitespace\" \"))))(Tile((id \ + 24026)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24027)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24029)(content(Whitespace\" \"))))(Tile((id \ + 24033)(label(Fake))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24034)(content(Whitespace\" \")))))((Secondary((id \ + 24036)(content(Whitespace\" \"))))(Tile((id 24039)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24040)(content(Whitespace\" \"))))(Tile((id \ + 24045)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24048)(content(Whitespace\" \")))))((Secondary((id \ + 24052)(content(Whitespace\" \"))))(Tile((id \ + 24053)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24056)(content(Whitespace\" \")))))))))(Secondary((id \ + 24060)(content(Whitespace\" \"))))(Tile((id \ + 24064)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24067)(content(Whitespace\" \")))))))))(Secondary((id \ + 24069)(content(Whitespace\" \"))))(Secondary((id \ + 24073)(content(Comment #err#))))(Secondary((id \ + 24074)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24078)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24079)(content(Whitespace\" \"))))(Tile((id \ + 24081)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24082)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24084)(content(Whitespace\" \"))))(Tile((id \ + 24085)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24086)(content(Whitespace\" \")))))((Secondary((id \ + 24088)(content(Whitespace\" \"))))(Tile((id 24091)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24092)(content(Whitespace\" \"))))(Tile((id \ + 24097)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24100)(content(Whitespace\" \")))))((Secondary((id \ + 24104)(content(Whitespace\" \"))))(Tile((id \ + 24105)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24108)(content(Whitespace\" \")))))))))(Secondary((id \ + 24112)(content(Whitespace\" \"))))(Tile((id \ + 24114)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24117)(content(Whitespace\" \")))))))))(Secondary((id \ + 24119)(content(Whitespace\" \"))))(Secondary((id \ + 24126)(content(Comment\"#2x err#\"))))(Secondary((id \ + 24127)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24131)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24132)(content(Whitespace\" \"))))(Tile((id \ + 24134)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24135)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24137)(content(Whitespace\" \"))))(Tile((id \ + 24138)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24139)(content(Whitespace\" \")))))((Secondary((id \ + 24141)(content(Whitespace\" \"))))(Tile((id \ + 24142)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24145)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24146)(content(Whitespace\" \"))))(Tile((id \ + 24151)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24154)(content(Whitespace\" \")))))((Secondary((id \ + 24158)(content(Whitespace\" \"))))(Tile((id \ + 24159)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24162)(content(Whitespace\" \")))))))))(Secondary((id \ + 24166)(content(Whitespace\" \"))))(Tile((id \ + 24168)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24169)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Grout((id 24175)(shape \ + Convex)))(Secondary((id 24171)(content(Whitespace\" \ + \"))))(Secondary((id 24172)(content(Whitespace\" \ + \"))))(Secondary((id 24173)(content(Whitespace\" \ + \")))))))))(Secondary((id 24177)(content(Whitespace\" \ + \"))))(Secondary((id 24181)(content(Comment \ + #err#))))(Secondary((id \ + 24182)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24186)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24187)(content(Whitespace\" \"))))(Tile((id \ + 24189)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24190)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24192)(content(Whitespace\" \"))))(Grout((id 24194)(shape \ + Convex)))(Tile((id 24193)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 14))(sort \ + Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24195)(content(Whitespace\" \"))))(Tile((id \ + 24196)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24197)(content(Whitespace\" \")))))((Secondary((id \ + 24199)(content(Whitespace\" \"))))(Tile((id \ + 24200)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24203)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24204)(content(Whitespace\" \"))))(Tile((id \ + 24209)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24212)(content(Whitespace\" \")))))((Secondary((id \ + 24216)(content(Whitespace\" \"))))(Tile((id \ + 24217)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24220)(content(Whitespace\" \")))))))))(Secondary((id \ + 24224)(content(Whitespace\" \"))))(Tile((id \ + 24226)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24227)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Grout((id 24233)(shape \ + Convex)))(Secondary((id 24229)(content(Whitespace\" \ + \"))))(Secondary((id 24230)(content(Whitespace\" \ + \"))))(Secondary((id 24231)(content(Whitespace\" \ + \")))))))))(Secondary((id 24235)(content(Whitespace\" \ + \"))))(Secondary((id \ + 24236)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24240)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24241)(content(Whitespace\" \"))))(Tile((id 24243)(label([ \ + ]))(mold((out Pat)(in_(Pat))(nibs(((shape Convex)(sort \ + Pat))((shape Convex)(sort Pat))))))(shards(0 \ + 1))(children(((Tile((id 24244)(label(_))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 24245)(content(Whitespace\" \")))))((Secondary((id \ + 24247)(content(Whitespace\" \"))))(Tile((id 24248)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 24249)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24252)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24253)(content(Whitespace\" \"))))(Tile((id \ + 24258)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24261)(content(Whitespace\" \")))))((Secondary((id \ + 24265)(content(Whitespace\" \"))))(Tile((id \ + 24266)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24269)(content(Whitespace\" \")))))))))(Secondary((id \ + 24273)(content(Whitespace\" \"))))(Tile((id \ + 24275)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))))))))))))(Secondary((id \ + 24278)(content(Whitespace\" \")))))))))(Secondary((id \ + 24280)(content(Whitespace\" \"))))(Secondary((id \ + 24281)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24285)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24286)(content(Whitespace\" \"))))(Tile((id 24288)(label([ \ + ]))(mold((out Pat)(in_(Pat))(nibs(((shape Convex)(sort \ + Pat))((shape Convex)(sort Pat))))))(shards(0 \ + 1))(children(((Tile((id 24289)(label(_))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 24290)(content(Whitespace\" \")))))((Secondary((id \ + 24292)(content(Whitespace\" \"))))(Tile((id \ + 24293)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24296)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24297)(content(Whitespace\" \"))))(Tile((id \ + 24302)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24305)(content(Whitespace\" \")))))((Secondary((id \ + 24309)(content(Whitespace\" \"))))(Tile((id \ + 24310)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24313)(content(Whitespace\" \")))))))))(Secondary((id \ + 24317)(content(Whitespace\" \"))))(Tile((id \ + 24319)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 24322)(content(Whitespace\" \")))))))))(Secondary((id \ + 24324)(content(Whitespace\" \"))))(Secondary((id \ + 24331)(content(Comment\"#2x err#\"))))(Secondary((id \ + 24332)(content(Whitespace\" \"))))(Secondary((id \ + 24333)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 24334)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25411)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Grout((id \ + 25413)(shape Convex)))(Secondary((id \ + 25412)(content(Whitespace\" \")))))))))(Tile((id \ + 24338)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24342)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24343)(content(Whitespace\" \"))))(Tile((id \ + 24348)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24351)(content(Whitespace\" \")))))((Secondary((id \ + 24355)(content(Whitespace\" \"))))(Tile((id \ + 24356)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24359)(content(Whitespace\" \")))))))))(Secondary((id \ + 24363)(content(Whitespace\" \"))))(Tile((id \ + 24365)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24366)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24368)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24369)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 24370)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24374)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24375)(content(Whitespace\" \"))))(Tile((id \ + 24380)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24383)(content(Whitespace\" \")))))((Secondary((id \ + 24387)(content(Whitespace\" \"))))(Tile((id \ + 24388)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24391)(content(Whitespace\" \")))))))))(Secondary((id \ + 24395)(content(Whitespace\" \"))))(Tile((id \ + 24397)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24398)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24400)(content(Whitespace\" \"))))(Secondary((id \ + 24404)(content(Comment #err#))))(Secondary((id \ + 24405)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24406)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24407)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24408)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24412)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24413)(content(Whitespace\" \"))))(Tile((id \ + 24418)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24421)(content(Whitespace\" \")))))((Secondary((id \ + 24425)(content(Whitespace\" \"))))(Tile((id \ + 24426)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24429)(content(Whitespace\" \")))))))))(Secondary((id \ + 24433)(content(Whitespace\" \"))))(Tile((id \ + 24435)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24436)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24438)(content(Whitespace\" \"))))(Secondary((id \ + 24442)(content(Comment #err#))))(Secondary((id \ + 24443)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24444)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24448)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 25439)(content(Whitespace\" \"))))(Grout((id 25440)(shape \ + Convex)))(Secondary((id 25441)(content(Whitespace\" \ + \")))))))))(Secondary((id 25442)(content(Whitespace\" \ + \"))))(Grout((id 24457)(shape Convex))))))))(Tile((id \ + 24458)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24462)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24463)(content(Whitespace\" \"))))(Tile((id \ + 24468)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24471)(content(Whitespace\" \")))))((Secondary((id \ + 24475)(content(Whitespace\" \"))))(Tile((id \ + 24476)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24479)(content(Whitespace\" \")))))))))(Secondary((id \ + 24483)(content(Whitespace\" \"))))(Tile((id \ + 24485)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24486)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24488)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24489)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24493)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 24494)(content(Whitespace\" \"))))(Tile((id \ + 24496)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24497)(content(Whitespace\" \")))))))))(Secondary((id \ + 25443)(content(Whitespace\" \"))))(Grout((id 24502)(shape \ + Convex))))))))(Tile((id 24503)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24507)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24508)(content(Whitespace\" \"))))(Tile((id \ + 24513)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24516)(content(Whitespace\" \")))))((Secondary((id \ + 24520)(content(Whitespace\" \"))))(Tile((id \ + 24521)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24524)(content(Whitespace\" \")))))))))(Secondary((id \ + 24528)(content(Whitespace\" \"))))(Tile((id \ + 24530)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24531)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24533)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24534)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24538)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 24539)(content(Whitespace\" \"))))(Tile((id \ + 24541)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24542)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25444)(content(Whitespace\" \"))))(Grout((id 24548)(shape \ + Convex)))(Secondary((id 24544)(content(Whitespace\" \ + \")))))))))(Secondary((id 25445)(content(Whitespace\" \ + \"))))(Grout((id 24551)(shape Convex))))))))(Tile((id \ + 24552)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24556)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24557)(content(Whitespace\" \"))))(Tile((id \ + 24562)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24565)(content(Whitespace\" \")))))((Secondary((id \ + 24569)(content(Whitespace\" \"))))(Tile((id \ + 24570)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24573)(content(Whitespace\" \")))))))))(Secondary((id \ + 24577)(content(Whitespace\" \"))))(Tile((id \ + 24579)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24580)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24582)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24583)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24587)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 24588)(content(Whitespace\" \"))))(Tile((id \ + 24590)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24591)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24593)(content(Whitespace\" \"))))(Tile((id \ + 24596)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24597)(content(Whitespace\" \")))))))))(Secondary((id \ + 25446)(content(Whitespace\" \"))))(Grout((id 24602)(shape \ + Convex))))))))(Tile((id 24603)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24607)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24608)(content(Whitespace\" \"))))(Tile((id \ + 24613)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24616)(content(Whitespace\" \")))))((Secondary((id \ + 24620)(content(Whitespace\" \"))))(Tile((id \ + 24621)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24624)(content(Whitespace\" \")))))))))(Secondary((id \ + 24628)(content(Whitespace\" \"))))(Tile((id \ + 24630)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 24631)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24633)(content(Whitespace\" \"))))(Secondary((id \ + 24637)(content(Comment #err#))))(Secondary((id \ + 24638)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 24639)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24643)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24644)(content(Whitespace\" \"))))(Tile((id \ + 24646)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24647)(content(Whitespace\" \")))))((Secondary((id \ + 24649)(content(Whitespace\" \"))))(Tile((id \ + 24653)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 24654)(content(Whitespace\" \"))))(Tile((id \ + 24656)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24657)(content(Whitespace\" \")))))))))(Secondary((id \ + 24660)(content(Whitespace\" \"))))(Tile((id 24663)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24664)(content(Whitespace\" \"))))(Tile((id \ + 24669)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24672)(content(Whitespace\" \")))))((Secondary((id \ + 24676)(content(Whitespace\" \"))))(Tile((id \ + 24677)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24680)(content(Whitespace\" \")))))))))(Secondary((id \ + 24684)(content(Whitespace\" \"))))(Tile((id \ + 24686)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24689)(content(Whitespace\" \")))))))))(Secondary((id \ + 24691)(content(Whitespace\" \"))))(Secondary((id \ + 24695)(content(Comment #err#))))(Secondary((id \ + 24696)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24700)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24701)(content(Whitespace\" \"))))(Tile((id \ + 24703)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24704)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25417)(content(Whitespace\" \"))))(Grout((id 24709)(shape \ + Convex)))(Secondary((id 24706)(content(Whitespace\" \ + \")))))((Secondary((id 24710)(content(Whitespace\" \ + \"))))(Tile((id 24714)(label(fun ->))(mold((out \ + Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 24715)(content(Whitespace\" \ + \"))))(Tile((id 24717)(label(x))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24718)(content(Whitespace\" \")))))))))(Secondary((id \ + 24721)(content(Whitespace\" \"))))(Tile((id 24724)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24725)(content(Whitespace\" \"))))(Tile((id \ + 24730)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24733)(content(Whitespace\" \")))))((Secondary((id \ + 24737)(content(Whitespace\" \"))))(Tile((id \ + 24738)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24741)(content(Whitespace\" \")))))))))(Secondary((id \ + 24745)(content(Whitespace\" \"))))(Tile((id \ + 24747)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24750)(content(Whitespace\" \")))))))))(Secondary((id \ + 24752)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24756)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24757)(content(Whitespace\" \"))))(Tile((id \ + 24759)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24760)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25416)(content(Whitespace\" \"))))(Grout((id 25415)(shape \ + Convex)))(Secondary((id 25419)(content(Whitespace\" \ + \"))))(Tile((id 24766)(label(->))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 6))(sort \ + Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25418)(content(Whitespace\" \"))))(Grout((id 24771)(shape \ + Convex)))(Secondary((id 24768)(content(Whitespace\" \ + \")))))((Secondary((id 24772)(content(Whitespace\" \ + \"))))(Tile((id 24776)(label(fun ->))(mold((out \ + Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 24777)(content(Whitespace\" \ + \"))))(Tile((id 24779)(label(x))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24780)(content(Whitespace\" \")))))))))(Secondary((id \ + 24783)(content(Whitespace\" \"))))(Tile((id 24786)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24787)(content(Whitespace\" \"))))(Tile((id \ + 24792)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24795)(content(Whitespace\" \")))))((Secondary((id \ + 24799)(content(Whitespace\" \"))))(Tile((id \ + 24800)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24803)(content(Whitespace\" \")))))))))(Secondary((id \ + 24807)(content(Whitespace\" \"))))(Tile((id \ + 24809)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24812)(content(Whitespace\" \")))))))))(Secondary((id \ + 24814)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24818)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24819)(content(Whitespace\" \"))))(Tile((id \ + 24821)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24822)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24824)(content(Whitespace\" \"))))(Grout((id 24829)(shape \ + Convex)))(Secondary((id 25420)(content(Whitespace\" \ + \"))))(Tile((id 24828)(label(->))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 6))(sort \ + Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24830)(content(Whitespace\" \"))))(Tile((id \ + 24833)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24834)(content(Whitespace\" \")))))((Secondary((id \ + 24836)(content(Whitespace\" \"))))(Tile((id \ + 24840)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 13))(sort \ + Exp))))))(shards(0 1))(children(((Secondary((id \ + 24841)(content(Whitespace\" \"))))(Tile((id \ + 24843)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24844)(content(Whitespace\" \")))))))))(Secondary((id \ + 24847)(content(Whitespace\" \"))))(Tile((id 24850)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24851)(content(Whitespace\" \"))))(Tile((id \ + 24856)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24859)(content(Whitespace\" \")))))((Secondary((id \ + 24863)(content(Whitespace\" \"))))(Tile((id \ + 24864)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24867)(content(Whitespace\" \")))))))))(Secondary((id \ + 24871)(content(Whitespace\" \"))))(Tile((id \ + 24873)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24876)(content(Whitespace\" \")))))))))(Secondary((id \ + 24878)(content(Whitespace\" \"))))(Secondary((id \ + 24882)(content(Comment #err#))))(Secondary((id \ + 24883)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24887)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24888)(content(Whitespace\" \"))))(Tile((id \ + 24890)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 24891)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24893)(content(Whitespace\" \"))))(Grout((id 24898)(shape \ + Convex)))(Secondary((id 25421)(content(Whitespace\" \ + \"))))(Tile((id 24897)(label(->))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 6))(sort \ + Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 24899)(content(Whitespace\" \"))))(Tile((id 25423)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Grout((id 25431)(shape \ + Convex))))))))(Secondary((id 24903)(content(Whitespace\" \ + \")))))((Secondary((id 24905)(content(Whitespace\" \ + \"))))(Tile((id 24909)(label(fun ->))(mold((out \ + Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 24910)(content(Whitespace\" \ + \"))))(Tile((id 24912)(label(x))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 24913)(content(Whitespace\" \")))))))))(Secondary((id \ + 24916)(content(Whitespace\" \"))))(Tile((id 24919)(label(if \ + then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ + Convex)(sort Exp))((shape(Concave 12))(sort \ + Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24920)(content(Whitespace\" \"))))(Tile((id \ + 24925)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24928)(content(Whitespace\" \")))))((Secondary((id \ + 24932)(content(Whitespace\" \"))))(Tile((id \ + 24933)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24936)(content(Whitespace\" \")))))))))(Secondary((id \ + 24940)(content(Whitespace\" \"))))(Tile((id \ + 24942)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24945)(content(Whitespace\" \")))))))))(Secondary((id \ + 24947)(content(Whitespace\" \"))))(Secondary((id \ + 24954)(content(Comment\"#2x err#\"))))(Secondary((id \ + 24955)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 24956)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25448)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Grout((id \ + 25449)(shape Convex))))))))(Tile((id \ + 24962)(label(::))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 6))(sort \ + Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id 24963)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 24964)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 24967)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 24968)(content(Whitespace\" \"))))(Tile((id \ + 24973)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24976)(content(Whitespace\" \")))))((Secondary((id \ + 24980)(content(Whitespace\" \"))))(Tile((id \ + 24981)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24984)(content(Whitespace\" \")))))))))(Secondary((id \ + 24988)(content(Whitespace\" \"))))(Tile((id \ + 24990)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))))))))))))(Tile((id \ + 24991)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 24993)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 24994)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 24997)(label(::))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 6))(sort \ + Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id 24998)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 24999)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 25002)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25003)(content(Whitespace\" \"))))(Tile((id \ + 25008)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25011)(content(Whitespace\" \")))))((Secondary((id \ + 25015)(content(Whitespace\" \"))))(Tile((id \ + 25016)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25019)(content(Whitespace\" \")))))))))(Secondary((id \ + 25023)(content(Whitespace\" \"))))(Tile((id \ + 25025)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))))))))))))(Tile((id \ + 25026)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25028)(content(Whitespace\" \"))))(Secondary((id \ + 25032)(content(Comment #err#))))(Secondary((id \ + 25033)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25034)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 25035)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25036)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25451)(content(Whitespace\" \"))))(Tile((id \ + 25038)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 25041)(label(::))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 6))(sort \ + Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id 25042)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 25043)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 25046)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25047)(content(Whitespace\" \"))))(Tile((id \ + 25052)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25055)(content(Whitespace\" \")))))((Secondary((id \ + 25059)(content(Whitespace\" \"))))(Tile((id \ + 25060)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25063)(content(Whitespace\" \")))))))))(Secondary((id \ + 25067)(content(Whitespace\" \"))))(Tile((id \ + 25069)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))))))))))))(Tile((id \ + 25070)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25072)(content(Whitespace\" \"))))(Secondary((id \ + 25079)(content(Comment\"#2x err#\"))))(Secondary((id \ + 25080)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 25081)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25085)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Grout((id \ + 25090)(shape Convex)))(Secondary((id \ + 25086)(content(Whitespace\" \"))))(Secondary((id \ + 25088)(content(Whitespace\" \"))))(Secondary((id \ + 25089)(content(Whitespace\" \")))))((Secondary((id \ + 25091)(content(Whitespace\" \"))))(Tile((id 25092)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 25093)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 25094)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25096)(content(Whitespace\" \"))))(Tile((id \ + 25098)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25099)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25101)(content(Whitespace\" \"))))(Tile((id \ + 25105)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25108)(content(Whitespace\" \")))))))))(Secondary((id \ + 25110)(content(Whitespace\" \"))))(Secondary((id \ + 25128)(content(Comment\"#err: \ + inconsistent#\"))))(Secondary((id \ + 25129)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25133)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25134)(content(Whitespace\" \"))))(Tile((id \ + 25136)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 25137)(content(Whitespace\" \")))))((Secondary((id \ + 25139)(content(Whitespace\" \"))))(Tile((id 25140)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 25141)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 25142)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25144)(content(Whitespace\" \"))))(Tile((id \ + 25146)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25147)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25149)(content(Whitespace\" \"))))(Tile((id \ + 25153)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25156)(content(Whitespace\" \")))))))))(Secondary((id \ + 25158)(content(Whitespace\" \"))))(Secondary((id \ + 25176)(content(Comment\"#err: \ + inconsistent#\"))))(Secondary((id \ + 25177)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25181)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25182)(content(Whitespace\" \"))))(Tile((id \ + 25184)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 25185)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25433)(content(Whitespace\" \"))))(Grout((id 25189)(shape \ + Convex)))(Secondary((id 25187)(content(Whitespace\" \ + \"))))(Secondary((id 25188)(content(Whitespace\" \ + \")))))((Secondary((id 25190)(content(Whitespace\" \ + \"))))(Tile((id 25191)(label([ ]))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 25192)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25193)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25195)(content(Whitespace\" \"))))(Tile((id \ + 25197)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25198)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25200)(content(Whitespace\" \"))))(Tile((id \ + 25204)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25207)(content(Whitespace\" \")))))))))(Secondary((id \ + 25209)(content(Whitespace\" \"))))(Secondary((id \ + 25210)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25214)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25215)(content(Whitespace\" \"))))(Tile((id \ + 25217)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 25218)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25434)(content(Whitespace\" \"))))(Tile((id 25437)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Grout((id 25436)(shape \ + Convex))))))))(Secondary((id 25223)(content(Whitespace\" \ + \")))))((Secondary((id 25225)(content(Whitespace\" \ + \"))))(Tile((id 25226)(label([ ]))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 25227)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25228)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25230)(content(Whitespace\" \"))))(Tile((id \ + 25232)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25233)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25235)(content(Whitespace\" \"))))(Tile((id \ + 25239)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25242)(content(Whitespace\" \")))))))))(Secondary((id \ + 25244)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25248)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25249)(content(Whitespace\" \"))))(Tile((id \ + 25251)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 25252)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25435)(content(Whitespace\" \"))))(Tile((id 25254)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 25257)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 25258)(content(Whitespace\" \")))))((Secondary((id \ + 25260)(content(Whitespace\" \"))))(Tile((id 25261)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 25262)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 25263)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25265)(content(Whitespace\" \"))))(Tile((id \ + 25267)(label(1.))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25268)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 25270)(content(Whitespace\" \"))))(Tile((id \ + 25274)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25277)(content(Whitespace\" \")))))))))(Secondary((id \ + 25279)(content(Whitespace\" \"))))(Secondary((id \ + 25286)(content(Comment\"#2x err#\"))))(Secondary((id \ + 25287)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 25288)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25292)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25293)(content(Whitespace\" \"))))(Tile((id \ + 25295)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 25296)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25298)(content(Whitespace\" \"))))(Tile((id 25299)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 25302)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 25303)(content(Whitespace\" \")))))((Secondary((id \ + 25305)(content(Whitespace\" \"))))(Tile((id \ + 25306)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25309)(label(::))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 6))(sort \ + Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id 25310)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 25311)(label(2))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25314)(content(Whitespace\" \")))))))))(Secondary((id \ + 25316)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25320)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25321)(content(Whitespace\" \"))))(Tile((id \ + 25323)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 25324)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25326)(content(Whitespace\" \"))))(Tile((id 25327)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 25330)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 25331)(content(Whitespace\" \")))))((Secondary((id \ + 25333)(content(Whitespace\" \"))))(Tile((id \ + 25336)(label(1.0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25339)(label(::))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 6))(sort \ + Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id 25340)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 25341)(label(2))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25344)(content(Whitespace\" \")))))))))(Secondary((id \ + 25346)(content(Whitespace\" \"))))(Secondary((id \ + 25350)(content(Comment #err#))))(Secondary((id \ + 25351)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25355)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 25356)(content(Whitespace\" \"))))(Tile((id \ + 25358)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 25359)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 25361)(content(Whitespace\" \"))))(Tile((id 25362)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 25365)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 25366)(content(Whitespace\" \")))))((Secondary((id \ + 25368)(content(Whitespace\" \"))))(Tile((id \ + 25369)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 25372)(label(::))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 6))(sort \ + Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Tile((id 25373)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 25376)(label(2.0))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 25379)(content(Whitespace\" \")))))))))(Secondary((id \ + 25381)(content(Whitespace\" \"))))(Secondary((id \ + 25385)(content(Comment #err#))))(Secondary((id \ + 25386)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 25390)(label(\"\\\"BYE\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))(ancestors())))(caret \ + Outer))"; + backup_text = + "#Types and type error examples#\n\n\ + let _ = unbound in #err#\n\ + let Undefined = Undefined in # 2x err# \n\ + let true = 2 in #err# \n\n\ + let = if true then 1 else 1. in #err# \n\ + let _ = if true then 1 else 1. in #err#\n\ + let _: = if true then 1 else 1. in\n\ + let _: Int = if true then 1 else 1. in #err#\n\ + let _: Fake = if true then 1 else true in #err#\n\ + let _, _ = if true then 1 else 1. in #2x err#\n\ + let _, _ = (if true then 1 else 1.), in #err#\n\ + let _: , _ = (if true then 1 else 1.), in \n\ + let [_] = [(if true then 1 else 1.)] in \n\ + let [_] = (if true then 1 else 1.) in #2x err# \n\n\ + ( )(if true then 1 else 1.);\n\ + 1(if true then 1 else 1.); #err#\n\ + (1)(if true then 1 else 1.); #err#\n\ + (fun -> )(if true then 1 else 1.);\n\ + (fun _ -> )(if true then 1 else 1.);\n\ + (fun _: -> )(if true then 1 else 1.);\n\ + (fun _: Int -> )(if true then 1 else 1.); #err#\n\n\ + let _ = fun x -> if true then 1 else 1. in #err#\n\ + let _: = fun x -> if true then 1 else 1. in\n\ + let _: -> = fun x -> if true then 1 else 1. in\n\ + let _: -> Int = fun x -> if true then 1 else 1. in #err#\n\ + let _: -> [ ] = fun x -> if true then 1 else 1. in #2x \ + err#\n\n\ + ( )::[(if true then 1 else 1.)];\n\ + 1::[(if true then 1 else 1.)]; #err#\n\ + (1, 1)::[(if true then 1 else 1.)]; #2x err#\n\n\ + let = [1, 1., true] in #err: inconsistent#\n\ + let _ = [1, 1., true] in #err: inconsistent#\n\ + let _: = [1, 1., true] in \n\ + let _: [ ] = [1, 1., true] in\n\ + let _: [Int] = [1, 1., true] in #2x err#\n\n\ + let _: [Int] = 1::[2] in\n\ + let _: [Int] = 1.0::[2] in #err#\n\ + let _: [Int] = 1::[2.0] in #err#\n\ + \"BYE\""; + } ) ); + ( "ADT Statics", + ( 29384, + { + zipper = + "((selection((focus \ + Left)(content())))(backpack())(relatives((siblings(()((Secondary((id \ + 8111)(content(Comment\"#Non-recursive sum/alias \ + tests#\"))))(Secondary((id \ + 8112)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 8174)(content(Comment\"#all lines with trailing err comment \ + should have 1 error#\"))))(Secondary((id \ + 8175)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 8209)(content(Comment\"#no other lines should have \ + errors#\"))))(Secondary((id \ + 6602)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 6603)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 6930)(content(Comment\"#type definitions: no \ + errors#\"))))(Secondary((id \ + 3939)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2974)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2975)(content(Whitespace\" \"))))(Grout((id 2979)(shape \ + Convex)))(Secondary((id 3016)(content(Whitespace\" \ + \")))))((Secondary((id 2980)(content(Whitespace\" \ + \"))))(Grout((id 8391)(shape Convex)))(Secondary((id \ + 2987)(content(Whitespace\" \")))))))))(Secondary((id \ + 3017)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3023)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3024)(content(Whitespace\" \"))))(Tile((id \ + 3054)(label(SingleNull))(mold((out \ + TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ + Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 3039)(content(Whitespace\" \")))))((Secondary((id \ + 3041)(content(Whitespace\" \"))))(Tile((id \ + 3042)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 3048)(label(One))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3049)(content(Whitespace\" \")))))))))(Secondary((id \ + 2861)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2867)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2868)(content(Whitespace\" \"))))(Tile((id \ + 3059)(label(Single))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 2871)(content(Whitespace\" \")))))((Secondary((id \ + 2873)(content(Whitespace\" \"))))(Tile((id \ + 2874)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2876)(label(F))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2878)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 2942)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2883)(content(Whitespace\" \")))))))))(Secondary((id \ + 2885)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2046)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2047)(content(Whitespace\" \"))))(Tile((id \ + 3185)(label(GoodSum))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 2050)(content(Whitespace\" \")))))((Secondary((id \ + 2052)(content(Whitespace\" \"))))(Tile((id \ + 2065)(label(A))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2080)(content(Whitespace\" \"))))(Tile((id \ + 2068)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2069)(content(Whitespace\" \"))))(Tile((id \ + 2070)(label(B))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2072)(content(Whitespace\" \"))))(Tile((id \ + 2073)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2074)(content(Whitespace\" \"))))(Tile((id \ + 2375)(label(C))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 3186)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3201)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2077)(content(Whitespace\" \")))))))))(Secondary((id \ + 6117)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 6123)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 6124)(content(Whitespace\" \"))))(Tile((id \ + 6132)(label(Partial))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 6133)(content(Whitespace\" \")))))((Secondary((id \ + 6135)(content(Whitespace\" \"))))(Tile((id \ + 6138)(label(Ok))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 6139)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Grout((id \ + 6141)(shape Convex))))))))(Secondary((id \ + 6143)(content(Whitespace\" \"))))(Tile((id \ + 6172)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 6181)(content(Whitespace\" \"))))(Grout((id 6180)(shape \ + Convex)))(Secondary((id 6173)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 3316)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2495)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2496)(content(Whitespace\" \"))))(Tile((id \ + 3477)(label(DoubleAlias))(mold((out \ + TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ + Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 2499)(content(Whitespace\" \")))))((Secondary((id \ + 2501)(content(Whitespace\" \"))))(Tile((id \ + 3460)(label(GoodSum))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2506)(content(Whitespace\" \")))))))))(Secondary((id \ + 1428)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1434)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1435)(content(Whitespace\" \"))))(Tile((id \ + 8239)(label(VerticalLeading))(mold((out \ + TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ + Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 1438)(content(Whitespace\" \")))))((Secondary((id \ + 8305)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 8307)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8308)(content(Whitespace\" \"))))(Tile((id \ + 8306)(label(A))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1446)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1447)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1448)(content(Whitespace\" \"))))(Tile((id \ + 1449)(label(B))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 1451)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3631)(label(GoodSum))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 1456)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1457)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1458)(content(Whitespace\" \"))))(Tile((id \ + 1459)(label(C))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 1461)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 1466)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 1468)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 1473)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 1476)(content(Whitespace\" \"))))(Secondary((id \ + 1474)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 3687)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3951)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 6938)(content(Comment\"#incorrect or incomplete type \ + definitions#\"))))(Secondary((id \ + 3860)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3866)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3867)(content(Whitespace\" \"))))(Tile((id \ + 3879)(label(badTypeName))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 3880)(content(Whitespace\" \")))))((Secondary((id \ + 3882)(content(Whitespace\" \"))))(Grout((id 7903)(shape \ + Convex)))(Secondary((id 3898)(content(Whitespace\" \ + \")))))))))(Secondary((id 6939)(content(Whitespace\" \ + \"))))(Secondary((id 7915)(content(Comment\"#err: invalid \ + type name#\"))))(Secondary((id \ + 3900)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3906)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3907)(content(Whitespace\" \"))))(Tile((id \ + 3908)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Grout((id \ + 3911)(shape Convex)))(Tile((id 3910)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 14))(sort \ + Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 4907)(content(Whitespace\" \"))))(Grout((id 3914)(shape \ + Convex))))))))(Secondary((id 3916)(content(Whitespace\" \ + \")))))((Secondary((id 3918)(content(Whitespace\" \ + \"))))(Grout((id 6260)(shape Convex)))(Secondary((id \ + 3936)(content(Whitespace\" \")))))))))(Secondary((id \ + 6974)(content(Whitespace\" \"))))(Secondary((id \ + 7938)(content(Comment\"#err: invalid type \ + name#\"))))(Secondary((id \ + 7939)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 7945)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 7946)(content(Whitespace\" \"))))(Grout((id 7995)(shape \ + Convex)))(Secondary((id 7959)(content(Whitespace\" \ + \")))))((Secondary((id 7961)(content(Whitespace\" \ + \"))))(Tile((id 7974)(label(badTypeToken))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 7977)(content(Whitespace\" \")))))))))(Secondary((id \ + 7979)(content(Whitespace\" \"))))(Secondary((id \ + 8008)(content(Comment\"#err: invalid type \ + token#\"))))(Secondary((id \ + 6205)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 6211)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 6212)(content(Whitespace\" \"))))(Tile((id \ + 6253)(label(NotASum))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 6221)(content(Whitespace\" \")))))((Secondary((id \ + 6223)(content(Whitespace\" \"))))(Tile((id \ + 6232)(label(NotInSum))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 6233)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 6238)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 6241)(content(Whitespace\" \")))))))))(Secondary((id \ + 6995)(content(Whitespace\" \"))))(Secondary((id \ + 8363)(content(Comment\"#err: cons not in \ + sum#\"))))(Secondary((id \ + 8309)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 8315)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 8316)(content(Whitespace\" \"))))(Tile((id \ + 8371)(label(Bool))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 8321)(content(Whitespace\" \")))))((Secondary((id \ + 8330)(content(Whitespace\" \"))))(Grout((id 8329)(shape \ + Convex)))(Secondary((id 8323)(content(Whitespace\" \ + \"))))(Secondary((id 8324)(content(Whitespace\" \ + \")))))))))(Secondary((id 8328)(content(Whitespace\" \ + \"))))(Secondary((id 8361)(content(Comment\"#err: shadows \ + base type#\"))))(Secondary((id \ + 3688)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3694)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3695)(content(Whitespace\" \"))))(Tile((id \ + 3701)(label(Dupes))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 3702)(content(Whitespace\" \")))))((Secondary((id \ + 8009)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 7772)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8012)(content(Whitespace\" \"))))(Tile((id \ + 3708)(label(Guy))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 3709)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3714)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 8052)(content(Whitespace\" \"))))(Secondary((id \ + 8059)(content(Comment\"#no err#\"))))(Secondary((id \ + 8010)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3723)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3724)(content(Whitespace\" \"))))(Tile((id \ + 3728)(label(Guy))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 3729)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3733)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 8033)(content(Whitespace\" \"))))(Secondary((id \ + 8051)(content(Comment\"#err: already \ + used#\"))))(Secondary((id \ + 8011)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 6271)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 6273)(content(Whitespace\" \"))))(Tile((id \ + 6276)(label(Guy))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 6277)(content(Whitespace\" \")))))))))(Secondary((id \ + 7023)(content(Whitespace\" \"))))(Secondary((id \ + 8032)(content(Comment\"#err: already \ + used#\"))))(Secondary((id \ + 3800)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3807)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3808)(content(Whitespace\" \"))))(Tile((id \ + 3816)(label(BadCons))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 3817)(content(Whitespace\" \")))))((Secondary((id \ + 7701)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 7770)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 7771)(content(Whitespace\" \"))))(Tile((id \ + 7738)(label(Um))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 7739)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 7746)(label(Unbound))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 7747)(content(Whitespace\" \"))))(Secondary((id \ + 7769)(content(Comment\"#err: unbound type \ + var#\"))))(Secondary((id \ + 7524)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 7532)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 7533)(content(Whitespace\" \"))))(Tile((id \ + 7531)(label(invalid))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 7534)(content(Whitespace\" \"))))(Secondary((id \ + 7547)(content(Comment\"#err: invalid#\"))))(Secondary((id \ + 7517)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 7522)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 7523)(content(Whitespace\" \"))))(Tile((id \ + 7521)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 7548)(content(Whitespace\" \"))))(Secondary((id \ + 7578)(content(Comment\"#err: expected cons found \ + type#\"))))(Secondary((id \ + 7498)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 7497)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 7501)(content(Whitespace\" \"))))(Tile((id \ + 3823)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 3824)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3828)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 7602)(content(Whitespace\" \"))))(Secondary((id \ + 7632)(content(Comment\"#err: expected cons found \ + type#\"))))(Secondary((id \ + 7499)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3830)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3831)(content(Whitespace\" \"))))(Tile((id \ + 3832)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Grout((id \ + 3834)(shape Convex))))))))(Tile((id \ + 3836)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3840)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 7633)(content(Whitespace\" \"))))(Secondary((id \ + 7663)(content(Comment\"#err: expected cons found \ + type#\"))))(Secondary((id \ + 7500)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3842)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3843)(content(Whitespace\" \"))))(Tile((id \ + 3844)(label(A))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 3846)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 6020)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Tile((id \ + 3849)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3853)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 3856)(content(Whitespace\" \")))))))))(Secondary((id \ + 3859)(content(Whitespace\" \"))))(Secondary((id \ + 7700)(content(Comment\"#err: expected cons found \ + app#\"))))(Secondary((id \ + 1563)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3564)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 8704)(content(Comment\"#sums in compound aliases dont add \ + ctrs to scope#\"))))(Secondary((id \ + 8930)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 8985)(content(Comment\"#but compound alias types should \ + propagate analytically#\"))))(Secondary((id \ + 3512)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 3518)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 3519)(content(Whitespace\" \"))))(Tile((id \ + 9369)(label(CompoundAlias))(mold((out \ + TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ + Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 3531)(content(Whitespace\" \")))))((Secondary((id \ + 3533)(content(Whitespace\" \"))))(Tile((id \ + 3534)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 3538)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 3539)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3540)(content(Whitespace\" \"))))(Tile((id \ + 3550)(label(Anonymous))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3551)(content(Whitespace\" \"))))(Tile((id \ + 3552)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 3553)(content(Whitespace\" \"))))(Tile((id \ + 3557)(label(Sum))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 3560)(content(Whitespace\" \")))))))))(Secondary((id \ + 3562)(content(Whitespace\" \"))))(Secondary((id \ + 1485)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2243)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2244)(content(Whitespace\" \"))))(Tile((id \ + 9126)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2250)(content(Whitespace\" \")))))((Secondary((id \ + 2262)(content(Whitespace\" \"))))(Tile((id \ + 3503)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 8493)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 3507)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 6011)(content(Whitespace\" \"))))(Tile((id \ + 3511)(label(Sum))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 2252)(content(Whitespace\" \")))))))))(Secondary((id \ + 6892)(content(Whitespace\" \"))))(Secondary((id \ + 7774)(content(Comment\"#err: not \ + defined#\"))))(Secondary((id \ + 8564)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 8569)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 8570)(content(Whitespace\" \"))))(Tile((id \ + 9128)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 8573)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9070)(content(Whitespace\" \"))))(Tile((id \ + 9383)(label(CompoundAlias))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8586)(content(Whitespace\" \")))))((Secondary((id \ + 8587)(content(Whitespace\" \"))))(Tile((id \ + 8588)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 8589)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 8591)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 8592)(content(Whitespace\" \"))))(Tile((id \ + 8596)(label(Sum))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 8599)(content(Whitespace\" \")))))))))(Secondary((id \ + 8987)(content(Whitespace\" \"))))(Secondary((id \ + 8996)(content(Comment\"#no error#\"))))(Secondary((id \ + 8805)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 8811)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 8812)(content(Whitespace\" \"))))(Tile((id \ + 9254)(label(Yorp))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 8818)(content(Whitespace\" \")))))((Secondary((id \ + 8819)(content(Whitespace\" \"))))(Tile((id \ + 8823)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8824)(content(Whitespace\" \"))))(Tile((id \ + 8826)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8827)(content(Whitespace\" \"))))(Tile((id \ + 8836)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 9229)(label(Inside))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8830)(content(Whitespace\" \"))))(Tile((id \ + 8831)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8832)(content(Whitespace\" \"))))(Tile((id \ + 9235)(label(Ouside))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 8835)(content(Whitespace\" \")))))))))(Secondary((id \ + 8837)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 8842)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 8843)(content(Whitespace\" \"))))(Tile((id \ + 9129)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 8847)(content(Whitespace\" \")))))((Secondary((id \ + 8853)(content(Whitespace\" \"))))(Tile((id 8858)(label(fun \ + ->))(mold((out Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 8859)(content(Whitespace\" \ + \"))))(Tile((id 8860)(label(_))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 8882)(content(Whitespace\" \")))))))))(Secondary((id \ + 8884)(content(Whitespace\" \"))))(Tile((id \ + 9241)(label(Inside))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 8889)(content(Whitespace\" \")))))))))(Secondary((id \ + 9032)(content(Whitespace\" \"))))(Secondary((id \ + 9049)(content(Comment\"#err: not \ + defined#\"))))(Secondary((id \ + 8494)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 9001)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 9002)(content(Whitespace\" \"))))(Tile((id \ + 9130)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 9006)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9071)(content(Whitespace\" \"))))(Tile((id \ + 9253)(label(Yorp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9010)(content(Whitespace\" \")))))((Secondary((id \ + 9011)(content(Whitespace\" \"))))(Tile((id 9016)(label(fun \ + ->))(mold((out Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 9017)(content(Whitespace\" \ + \"))))(Tile((id 9018)(label(_))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 9020)(content(Whitespace\" \")))))))))(Secondary((id \ + 9022)(content(Whitespace\" \"))))(Tile((id \ + 9248)(label(Inside))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 9029)(content(Whitespace\" \")))))))))(Secondary((id \ + 9051)(content(Whitespace\" \"))))(Secondary((id \ + 9060)(content(Comment\"#no error#\"))))(Secondary((id \ + 9073)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 9079)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 9080)(content(Whitespace\" \"))))(Tile((id \ + 9094)(label(Gargs))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 9095)(content(Whitespace\" \")))))((Secondary((id \ + 9096)(content(Whitespace\" \"))))(Tile((id 9097)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id 9199)(label(BigGuy))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9102)(content(Whitespace\" \"))))(Tile((id \ + 9103)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9104)(content(Whitespace\" \"))))(Tile((id \ + 9211)(label(Small))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 9111)(content(Whitespace\" \")))))))))(Secondary((id \ + 9072)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 9116)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 9117)(content(Whitespace\" \"))))(Tile((id \ + 9131)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 9123)(content(Whitespace\" \")))))((Secondary((id \ + 9132)(content(Whitespace\" \"))))(Tile((id \ + 9206)(label(BigGuy))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 9137)(content(Whitespace\" \")))))))))(Secondary((id \ + 9178)(content(Whitespace\" \"))))(Secondary((id \ + 9195)(content(Comment\"#err: not \ + defined#\"))))(Secondary((id \ + 9138)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 9143)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 9144)(content(Whitespace\" \"))))(Tile((id \ + 9147)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 9149)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9150)(content(Whitespace\" \"))))(Tile((id \ + 9156)(label(Gargs))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9157)(content(Whitespace\" \")))))((Secondary((id \ + 9158)(content(Whitespace\" \"))))(Tile((id 9159)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 9217)(label(BigGuy))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 9166)(content(Whitespace\" \")))))))))(Secondary((id \ + 9167)(content(Whitespace\" \"))))(Secondary((id \ + 9176)(content(Comment\"#no error#\"))))(Secondary((id \ + 9255)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 9260)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 9261)(content(Whitespace\" \"))))(Tile((id \ + 9262)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 9264)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9265)(content(Whitespace\" \"))))(Tile((id \ + 9275)(label(Gargs))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9271)(content(Whitespace\" \")))))((Secondary((id \ + 9276)(content(Whitespace\" \"))))(Tile((id \ + 9283)(label(BigGuy))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 9284)(content(Whitespace\" \"))))(Tile((id \ + 9286)(label(::))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 6))(sort Exp))((shape(Concave 6))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 9287)(content(Whitespace\" \"))))(Tile((id 9338)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Tile((id 9344)(label(BigGuy))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 9291)(content(Whitespace\" \")))))))))(Secondary((id \ + 9292)(content(Whitespace\" \"))))(Secondary((id \ + 9354)(content(Comment\"#no error#\"))))(Secondary((id \ + 9293)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 4008)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 8078)(content(Comment\"#unbound tyvars treated as \ + unknown-typehole#\"))))(Secondary((id \ + 4053)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4058)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4059)(content(Whitespace\" \"))))(Tile((id \ + 4060)(label(a))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 4062)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 4066)(label(Bad))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 4067)(content(Whitespace\" \")))))((Secondary((id \ + 4069)(content(Whitespace\" \"))))(Tile((id \ + 8085)(label(0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 4075)(content(Whitespace\" \")))))))))(Secondary((id \ + 4077)(content(Whitespace\" \"))))(Tile((id \ + 4078)(label(a))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 8079)(content(Whitespace\" \"))))(Tile((id \ + 8082)(label(==))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 8083)(content(Whitespace\" \"))))(Tile((id \ + 8086)(label(0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4080)(label(\";\"))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 10))(sort \ + Exp))((shape(Concave 10))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 6758)(content(Whitespace\" \"))))(Secondary((id \ + 7776)(content(Comment\"#err: not bound#\"))))(Secondary((id \ + 6021)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 6022)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 8093)(content(Comment\"#non-sum-types cant be \ + recursive#\"))))(Secondary((id \ + 6070)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 6076)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 6077)(content(Whitespace\" \"))))(Tile((id \ + 6081)(label(Lol))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 6082)(content(Whitespace\" \")))))((Secondary((id \ + 6084)(content(Whitespace\" \"))))(Tile((id \ + 6088)(label(Lol))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 6091)(content(Whitespace\" \")))))))))(Secondary((id \ + 6736)(content(Whitespace\" \"))))(Secondary((id \ + 7778)(content(Comment\"#err: not bound#\"))))(Secondary((id \ + 6466)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 6703)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 6805)(content(Comment\"#no errors: analytic \ + shadowing#\"))))(Secondary((id \ + 6806)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 6812)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 6813)(content(Whitespace\" \"))))(Tile((id \ + 6819)(label(Tork1))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 6820)(content(Whitespace\" \")))))((Secondary((id \ + 6822)(content(Whitespace\" \"))))(Tile((id \ + 6823)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 6829)(label(Blob))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 6832)(content(Whitespace\" \")))))))))(Secondary((id \ + 6834)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 6840)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 6841)(content(Whitespace\" \"))))(Tile((id \ + 6847)(label(Tork2))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 6848)(content(Whitespace\" \")))))((Secondary((id \ + 6850)(content(Whitespace\" \"))))(Tile((id \ + 6851)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 6857)(label(Blob))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 6860)(content(Whitespace\" \")))))))))(Secondary((id \ + 6862)(content(Whitespace\" \"))))(Secondary((id \ + 6863)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 6868)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 6869)(content(Whitespace\" \"))))(Tile((id \ + 6870)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 6872)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 6878)(label(Tork1))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 6879)(content(Whitespace\" \")))))((Secondary((id \ + 6881)(content(Whitespace\" \"))))(Tile((id \ + 6886)(label(Blob))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 6889)(content(Whitespace\" \")))))))))(Secondary((id \ + 6467)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 3994)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 5074)(content(Comment\"#exp tests: \ + happy#\"))))(Secondary((id \ + 4344)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4350)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4351)(content(Whitespace\" \"))))(Tile((id \ + 5397)(label(YoDawg))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 4354)(content(Whitespace\" \")))))((Secondary((id \ + 4356)(content(Whitespace\" \"))))(Secondary((id \ + 4357)(content(Whitespace\" \"))))(Tile((id \ + 4952)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 4360)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 4434)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 6501)(content(Whitespace\" \"))))(Tile((id \ + 6507)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8413)(content(Whitespace\" \"))))(Tile((id \ + 6502)(label(Bo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 6503)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 6506)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Tile((id \ + 4367)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 4368)(content(Whitespace\" \"))))(Tile((id \ + 4980)(label(Dawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 4371)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 4438)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 4378)(content(Whitespace\" \")))))))))(Secondary((id \ + 4388)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4393)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4394)(content(Whitespace\" \"))))(Tile((id \ + 4728)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 4397)(content(Whitespace\" \")))))((Secondary((id \ + 4399)(content(Whitespace\" \"))))(Tile((id \ + 4954)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4402)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4403)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4407)(content(Whitespace\" \")))))))))(Secondary((id \ + 4595)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4600)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4601)(content(Whitespace\" \"))))(Tile((id \ + 4730)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5016)(content(Whitespace\" \"))))(Tile((id \ + 4604)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5013)(content(Whitespace\" \"))))(Tile((id \ + 6116)(label(YoDawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 4607)(content(Whitespace\" \")))))((Secondary((id \ + 4609)(content(Whitespace\" \"))))(Tile((id \ + 4956)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4612)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4613)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4617)(content(Whitespace\" \")))))))))(Secondary((id \ + 4619)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4624)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4625)(content(Whitespace\" \"))))(Tile((id \ + 4732)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5017)(content(Whitespace\" \"))))(Tile((id \ + 4628)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5012)(content(Whitespace\" \"))))(Tile((id \ + 4630)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5007)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 4633)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 4638)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 4639)(content(Whitespace\" \")))))((Secondary((id \ + 4641)(content(Whitespace\" \"))))(Tile((id \ + 5009)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4644)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4649)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4652)(content(Whitespace\" \")))))))))(Secondary((id \ + 4656)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4661)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4662)(content(Whitespace\" \"))))(Tile((id \ + 4734)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5018)(content(Whitespace\" \"))))(Tile((id \ + 4665)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5014)(content(Whitespace\" \"))))(Tile((id \ + 4667)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 5005)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5010)(content(Whitespace\" \"))))(Tile((id \ + 4670)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5011)(content(Whitespace\" \"))))(Tile((id \ + 4984)(label(Dawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 4673)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 4674)(content(Whitespace\" \"))))(Tile((id \ + 4678)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 4679)(content(Whitespace\" \")))))((Secondary((id \ + 4681)(content(Whitespace\" \"))))(Tile((id \ + 4682)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4989)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4685)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4686)(label(5))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4690)(content(Whitespace\" \")))))))))(Secondary((id \ + 4692)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4697)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4698)(content(Whitespace\" \"))))(Tile((id \ + 4736)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5019)(content(Whitespace\" \"))))(Tile((id \ + 4701)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5015)(content(Whitespace\" \"))))(Tile((id \ + 4713)(label(DoubleAlias))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 4714)(content(Whitespace\" \")))))((Secondary((id \ + 4716)(content(Whitespace\" \"))))(Tile((id \ + 4717)(label(C))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4719)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4720)(label(4))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4724)(content(Whitespace\" \")))))))))(Secondary((id \ + 4782)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 4474)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 4851)(content(Comment\"#exp tests: \ + errors#\"))))(Secondary((id \ + 4783)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4788)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4789)(content(Whitespace\" \"))))(Tile((id \ + 4837)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 4792)(content(Whitespace\" \")))))((Secondary((id \ + 4794)(content(Whitespace\" \"))))(Tile((id \ + 4795)(label(2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4797)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4798)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4802)(content(Whitespace\" \")))))))))(Secondary((id \ + 7107)(content(Whitespace\" \"))))(Secondary((id \ + 7780)(content(Comment\"#err: incons with \ + arrow#\"))))(Secondary((id \ + 4804)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4809)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4810)(content(Whitespace\" \"))))(Tile((id \ + 4835)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 4813)(content(Whitespace\" \")))))((Secondary((id \ + 4815)(content(Whitespace\" \"))))(Tile((id \ + 4825)(label(Undefined))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4826)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4827)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4831)(content(Whitespace\" \")))))))))(Secondary((id \ + 7135)(content(Whitespace\" \"))))(Secondary((id \ + 7782)(content(Comment\"#err: cons \ + undefined#\"))))(Secondary((id \ + 4737)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4479)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4480)(content(Whitespace\" \"))))(Tile((id \ + 4739)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 4483)(content(Whitespace\" \")))))((Secondary((id \ + 4485)(content(Whitespace\" \"))))(Tile((id \ + 4486)(label(B))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4488)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4493)(label(\"\\\"lol\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 4496)(content(Whitespace\" \")))))))))(Secondary((id \ + 7158)(content(Whitespace\" \"))))(Secondary((id \ + 7794)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 4444)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 4546)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 4547)(content(Whitespace\" \"))))(Tile((id \ + 4741)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5020)(content(Whitespace\" \"))))(Tile((id \ + 4550)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 4551)(content(Whitespace\" \"))))(Tile((id \ + 4552)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5000)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 4555)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 4560)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 4561)(content(Whitespace\" \")))))((Secondary((id \ + 4563)(content(Whitespace\" \"))))(Tile((id \ + 4958)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 4574)(content(Whitespace\" \")))))))))(Secondary((id \ + 7183)(content(Whitespace\" \"))))(Secondary((id \ + 7793)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 4410)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1756)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1757)(content(Whitespace\" \"))))(Tile((id \ + 4743)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5021)(content(Whitespace\" \"))))(Tile((id \ + 1760)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1761)(content(Whitespace\" \"))))(Tile((id \ + 1762)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5003)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1765)(content(Whitespace\" \")))))((Secondary((id \ + 1767)(content(Whitespace\" \"))))(Tile((id \ + 4960)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1770)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4582)(label(\"\\\"lol\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1778)(content(Whitespace\" \")))))))))(Secondary((id \ + 1780)(content(Whitespace\" \"))))(Secondary((id \ + 7792)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 1713)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1718)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1719)(content(Whitespace\" \"))))(Tile((id \ + 4745)(label(_))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5022)(content(Whitespace\" \"))))(Tile((id \ + 1722)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1723)(content(Whitespace\" \"))))(Tile((id \ + 4590)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 4593)(label(One))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1735)(content(Whitespace\" \")))))((Secondary((id \ + 1737)(content(Whitespace\" \"))))(Tile((id \ + 4962)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1740)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 4594)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1748)(content(Whitespace\" \")))))))))(Secondary((id \ + 7220)(content(Whitespace\" \"))))(Secondary((id \ + 7791)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 5051)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 5052)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 7272)(content(Comment\"#pat tests: happy (but refutable \ + patterns so weird)#\"))))(Secondary((id \ + 5239)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5244)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5245)(content(Whitespace\" \"))))(Tile((id \ + 6526)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5249)(content(Whitespace\" \")))))((Secondary((id \ + 5251)(content(Whitespace\" \"))))(Tile((id \ + 6509)(label(Bo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5257)(content(Whitespace\" \")))))))))(Secondary((id \ + 5286)(content(Whitespace\" \"))))(Secondary((id \ + 5307)(content(Comment\"#kind of a weird \ + edge#\"))))(Secondary((id \ + 5075)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5080)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5081)(content(Whitespace\" \"))))(Tile((id \ + 5139)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5140)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5341)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 5084)(content(Whitespace\" \")))))((Secondary((id \ + 5154)(content(Whitespace\" \"))))(Tile((id \ + 5159)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 5149)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5164)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 5086)(content(Whitespace\" \")))))))))(Secondary((id \ + 5428)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5433)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5434)(content(Whitespace\" \"))))(Tile((id \ + 5437)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5438)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5757)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 5441)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5442)(content(Whitespace\" \"))))(Tile((id \ + 5449)(label(YoDawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5450)(content(Whitespace\" \")))))((Secondary((id \ + 5460)(content(Whitespace\" \"))))(Tile((id \ + 5466)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 5467)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5469)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 5452)(content(Whitespace\" \")))))))))(Secondary((id \ + 5708)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5713)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5714)(content(Whitespace\" \"))))(Tile((id \ + 5717)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5718)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5755)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 5721)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5722)(content(Whitespace\" \"))))(Tile((id \ + 5753)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5747)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5748)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 5752)(label(Int))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 5730)(content(Whitespace\" \")))))((Secondary((id \ + 5732)(content(Whitespace\" \"))))(Tile((id \ + 5735)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 5736)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5737)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 5741)(content(Whitespace\" \")))))))))(Secondary((id \ + 5743)(content(Whitespace\" \"))))(Secondary((id \ + 2700)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5092)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5093)(content(Whitespace\" \"))))(Tile((id \ + 5167)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5171)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5180)(content(Whitespace\" \"))))(Tile((id \ + 5173)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5175)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5096)(content(Whitespace\" \")))))((Secondary((id \ + 5177)(content(Whitespace\" \"))))(Tile((id \ + 5179)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5098)(content(Whitespace\" \")))))))))(Secondary((id \ + 5103)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 5120)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 5208)(content(Comment\"#pat tests: \ + errors#\"))))(Secondary((id \ + 5522)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5527)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5528)(content(Whitespace\" \"))))(Tile((id \ + 5590)(label(2))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5555)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5594)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 5540)(content(Whitespace\" \")))))((Secondary((id \ + 5542)(content(Whitespace\" \"))))(Tile((id \ + 5596)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5551)(content(Whitespace\" \")))))))))(Secondary((id \ + 7273)(content(Whitespace\" \"))))(Secondary((id \ + 7801)(content(Comment\"#err: incons with \ + arrow#\"))))(Secondary((id \ + 5559)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5564)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5565)(content(Whitespace\" \"))))(Tile((id \ + 6317)(label(NotDefined))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5568)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5592)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 5571)(content(Whitespace\" \")))))((Secondary((id \ + 5573)(content(Whitespace\" \"))))(Tile((id \ + 5598)(label(3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5578)(content(Whitespace\" \")))))))))(Secondary((id \ + 5580)(content(Whitespace\" \"))))(Secondary((id \ + 7803)(content(Comment\"#err: cons \ + undefined#\"))))(Secondary((id \ + 5209)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5264)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5265)(content(Whitespace\" \"))))(Tile((id \ + 5268)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 5269)(content(Whitespace\" \")))))((Secondary((id \ + 5271)(content(Whitespace\" \"))))(Tile((id \ + 5285)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5277)(content(Whitespace\" \")))))))))(Secondary((id \ + 5279)(content(Whitespace\" \"))))(Secondary((id \ + 7805)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 5329)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5346)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5347)(content(Whitespace\" \"))))(Tile((id \ + 5350)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5351)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5377)(label(true))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 5354)(content(Whitespace\" \")))))((Secondary((id \ + 5356)(content(Whitespace\" \"))))(Tile((id \ + 5361)(label(Dawg))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 5362)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5367)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 5370)(content(Whitespace\" \")))))))))(Secondary((id \ + 7339)(content(Whitespace\" \"))))(Secondary((id \ + 7807)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 5470)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5475)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5476)(content(Whitespace\" \"))))(Tile((id \ + 5479)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5505)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5758)(content(Whitespace\" \"))))(Tile((id \ + 5512)(label(YoDawg))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5486)(content(Whitespace\" \")))))((Secondary((id \ + 5488)(content(Whitespace\" \"))))(Tile((id \ + 5518)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 5519)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5521)(label(1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 5502)(content(Whitespace\" \")))))))))(Secondary((id \ + 7358)(content(Whitespace\" \"))))(Secondary((id \ + 7809)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 5599)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5604)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5605)(content(Whitespace\" \"))))(Tile((id \ + 5608)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5663)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5665)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 5609)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5759)(content(Whitespace\" \"))))(Tile((id \ + 5666)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5669)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5617)(content(Whitespace\" \")))))((Secondary((id \ + 5619)(content(Whitespace\" \"))))(Tile((id \ + 5622)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5628)(content(Whitespace\" \")))))))))(Secondary((id \ + 5630)(content(Whitespace\" \"))))(Secondary((id \ + 7811)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 5631)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 5636)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 5637)(content(Whitespace\" \"))))(Tile((id \ + 5640)(label(Yo))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 5687)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 5703)(label(1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Tile((id \ + 5671)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5760)(content(Whitespace\" \"))))(Tile((id \ + 5673)(label(+))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5675)(label(Yo))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 5676)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 5697)(label(Bool))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 5649)(content(Whitespace\" \")))))((Secondary((id \ + 5651)(content(Whitespace\" \"))))(Tile((id \ + 5654)(label(Yo))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 5655)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5702)(label(true))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 5660)(content(Whitespace\" \")))))))))(Secondary((id \ + 7395)(content(Whitespace\" \"))))(Secondary((id \ + 7813)(content(Comment\"#err: type \ + incons#\"))))(Secondary((id \ + 6564)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 7846)(label(\"\\\"Thats all, folks\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2231)(content(Whitespace\"\\226\\143\\142\")))))))(ancestors())))(caret \ + Outer))"; + backup_text = + "#Non-recursive sum/alias tests#\n\ + #all lines with trailing err comment should have 1 error#\n\ + #no other lines should have errors#\n\n\ + #type definitions: no errors#\n\ + type = in\n\ + type SingleNull = +One in\n\ + type Single = +F(Int) in\n\ + type GoodSum = A + B + C(Int) in\n\ + type Partial = Ok( ) + in\n\ + type DoubleAlias = GoodSum in\n\ + type VerticalLeading =\n\ + + A\n\ + + B(GoodSum)\n\ + + C(Bool->Bool) \n\ + in\n\n\ + #incorrect or incomplete type definitions#\n\ + type badTypeName = in #err: invalid type name#\n\ + type ( , ) = in #err: invalid type name#\n\ + type = badTypeToken in #err: invalid type token#\n\ + type NotASum = NotInSum(Bool) in #err: cons not in sum#\n\ + type Bool = in #err: shadows base type#\n\ + type Dupes =\n\ + + Guy(Bool) #no err#\n\ + + Guy(Int) #err: already used#\n\ + + Guy in #err: already used#\n\ + type BadCons =\n\ + + Um(Unbound) #err: unbound type var#\n\ + + invalid #err: invalid#\n\ + + Bool #err: expected cons found type#\n\ + + Int(Int) #err: expected cons found type#\n\ + + ( )(Int) #err: expected cons found type#\n\ + + A(Bool)(Int) in #err: expected cons found app#\n\n\ + #sums in compound aliases dont add ctrs to scope#\n\ + #but compound alias types should propagate analytically#\n\ + type CompoundAlias = (Int, Anonymous + Sum) in \n\ + let _ = (1, Sum) in #err: not defined#\n\ + let _: CompoundAlias = (1, Sum) in #no error#\n\ + type Yorp = Int -> (Inside + Ouside) in\n\ + let _ = fun _ -> Inside in #err: not defined#\n\ + let _: Yorp = fun _ -> Inside in #no error#\n\ + type Gargs = [BigGuy + Small] in\n\ + let _ = BigGuy in #err: not defined#\n\ + let _: Gargs = [BigGuy] in #no error#\n\ + let _: Gargs = BigGuy :: [BigGuy] in #no error#\n\n\ + #unbound tyvars treated as unknown-typehole#\n\ + let a:Bad = 0 in a == 0; #err: not bound#\n\n\ + #non-sum-types cant be recursive#\n\ + type Lol = Lol in #err: not bound#\n\n\ + #no errors: analytic shadowing#\n\ + type Tork1 = +Blob in\n\ + type Tork2 = +Blob in \n\ + let x:Tork1 = Blob in\n\n\ + #exp tests: happy#\n\ + type YoDawg = Yo(Int) + Bo(Int)+ Dawg(Bool) in\n\ + let _ = Yo(1) in\n\ + let _ : YoDawg = Yo(2) in\n\ + let _ : +Yo(Bool) = Yo(true) in\n\ + let _ : (Yo + Dawg, Int) = (Dawg,5) in\n\ + let _ : DoubleAlias = C(4) in\n\n\ + #exp tests: errors#\n\ + let _ = 2(1) in #err: incons with arrow#\n\ + let _ = Undefined(1) in #err: cons undefined#\n\ + let _ = B(\"lol\") in #err: type incons#\n\ + let _ : +Yo(Bool) = Yo in #err: type incons#\n\ + let _ : +Yo = Yo(\"lol\") in #err: type incons#\n\ + let _ : +One = Yo(1) in #err: type incons#\n\n\ + #pat tests: happy (but refutable patterns so weird)#\n\ + let Yo = Bo in #kind of a weird edge#\n\ + let Yo(1) = Dawg(true) in\n\ + let Yo(1): YoDawg = Yo(1) in\n\ + let Yo(1): +Yo(Int) = Yo(1) in \n\ + let Yo: +Yo = Yo in\n\n\ + #pat tests: errors#\n\ + let 2(1) = 3 in #err: incons with arrow#\n\ + let NotDefined(1) = 3 in #err: cons undefined#\n\ + let Yo = Dawg in #err: type incons#\n\ + let Yo(true) = Dawg(true) in #err: type incons#\n\ + let Yo: YoDawg = Yo(1) in #err: type incons#\n\ + let Yo(1): +Yo = Yo in #err: type incons#\n\ + let Yo(1): +Yo(Bool) = Yo(true) in #err: type incons#\n\ + \"Thats all, folks\"\n"; + } ) ); + ( "ADT Dynamics", + ( 2482, + { + zipper = + "((selection((focus \ + Right)(content())))(backpack())(relatives((siblings(((Secondary((id \ + 2389)(content(Comment\"#recursive sum type dynamics \ + tests#\"))))(Secondary((id \ + 2390)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 2467)(content(Comment\"#all calls should evaluate fully \ + with no exns or cast fails#\"))))(Secondary((id \ + 2352)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 337)(label(type = in))(mold((out Exp)(in_(TPat \ + Typ))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 338)(content(Whitespace\" \"))))(Tile((id \ + 342)(label(Exp))(mold((out TPat)(in_())(nibs(((shape \ + Convex)(sort TPat))((shape Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 343)(content(Whitespace\" \")))))((Secondary((id \ + 2350)(content(Whitespace\" \"))))(Tile((id \ + 352)(label(Var))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 353)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 360)(label(String))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 2351)(content(Whitespace\" \"))))(Tile((id \ + 362)(label(+))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 10))(sort Typ))((shape(Concave 10))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 364)(content(Whitespace\" \"))))(Tile((id \ + 2480)(label(Lam))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 371)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape(Concave 1))(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 378)(label(String))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 379)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 381)(content(Whitespace\" \"))))(Tile((id \ + 384)(label(Exp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 405)(content(Whitespace\" \")))))))))(Secondary((id \ + 2472)(content(Whitespace\"\\226\\143\\142\")))))((Secondary((id \ + 2097)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2102)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2103)(content(Whitespace\" \"))))(Tile((id \ + 2297)(label(s0))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2110)(content(Whitespace\" \"))))(Tile((id \ + 2111)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2112)(content(Whitespace\" \"))))(Tile((id \ + 2113)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Grout((id \ + 2116)(shape Convex)))(Tile((id 2115)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 14))(sort \ + Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2117)(content(Whitespace\" \"))))(Grout((id 2120)(shape \ + Convex)))(Tile((id 2119)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 14))(sort \ + Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2295)(content(Whitespace\" \"))))(Grout((id 2123)(shape \ + Convex))))))))(Secondary((id 2125)(content(Whitespace\" \ + \"))))(Tile((id 2127)(label(->))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 6))(sort \ + Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2128)(content(Whitespace\" \"))))(Grout((id 2294)(shape \ + Convex)))(Secondary((id 2133)(content(Whitespace\" \ + \")))))((Secondary((id 2135)(content(Whitespace\" \ + \"))))(Tile((id 2140)(label(fun ->))(mold((out \ + Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2141)(content(Whitespace\" \ + \"))))(Tile((id 2142)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 2143)(label(e))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2145)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2146)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2148)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2149)(label(v))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 2151)(content(Whitespace\" \")))))))))(Secondary((id \ + 2154)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2160)(label(case end))(mold((out \ + Exp)(in_(Rul))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2161)(content(Whitespace\" \ + \"))))(Tile((id 2162)(label(e))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2164)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2165)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2166)(content(Whitespace\" \ + \"))))(Tile((id 2170)(label(Var))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 2171)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 2172)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 2174)(content(Whitespace\" \")))))))))(Secondary((id \ + 2176)(content(Whitespace\" \"))))(Tile((id \ + 2177)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2181)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2182)(content(Whitespace\" \"))))(Tile((id \ + 2183)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2185)(content(Whitespace\" \"))))(Tile((id \ + 2188)(label($==))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2189)(content(Whitespace\" \"))))(Tile((id \ + 2190)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2194)(content(Whitespace\" \")))))((Secondary((id \ + 2198)(content(Whitespace\" \"))))(Tile((id \ + 2199)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2203)(content(Whitespace\" \")))))))))(Secondary((id \ + 2207)(content(Whitespace\" \"))))(Tile((id \ + 2208)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 2210)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 2211)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 2212)(content(Whitespace\" \ + \"))))(Tile((id 2216)(label(Lam))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 2217)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 2218)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 2220)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 2221)(content(Whitespace\" \"))))(Tile((id \ + 2224)(label(e1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 2225)(content(Whitespace\" \")))))))))(Secondary((id \ + 2227)(content(Whitespace\" \"))))(Tile((id \ + 2228)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2232)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 2233)(content(Whitespace\" \"))))(Tile((id \ + 2234)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2236)(content(Whitespace\" \"))))(Tile((id \ + 2239)(label($==))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2240)(content(Whitespace\" \"))))(Tile((id \ + 2241)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2245)(content(Whitespace\" \")))))((Secondary((id \ + 2249)(content(Whitespace\" \"))))(Tile((id \ + 2250)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2254)(content(Whitespace\" \")))))))))(Secondary((id \ + 2258)(content(Whitespace\" \"))))(Tile((id \ + 2262)(label(Lam))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2263)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2264)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2266)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2267)(content(Whitespace\" \"))))(Tile((id \ + 2299)(label(s0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2274)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2277)(label(e1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2278)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2279)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2281)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2282)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))))))))))))(Secondary((id \ + 2286)(content(Whitespace\" \"))))(Secondary((id \ + 2284)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2291)(content(Whitespace\" \")))))))))(Secondary((id \ + 2293)(content(Whitespace\" \"))))(Secondary((id \ + 1804)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1809)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1810)(content(Whitespace\" \"))))(Tile((id \ + 2301)(label(s1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1817)(content(Whitespace\" \"))))(Tile((id \ + 1818)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1819)(content(Whitespace\" \"))))(Tile((id \ + 1820)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Grout((id \ + 2071)(shape Convex)))(Tile((id 1825)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 14))(sort \ + Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1826)(content(Whitespace\" \"))))(Grout((id 1830)(shape \ + Convex)))(Tile((id 1829)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 14))(sort \ + Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 2072)(content(Whitespace\" \"))))(Grout((id 1833)(shape \ + Convex))))))))(Secondary((id 1835)(content(Whitespace\" \ + \"))))(Tile((id 1837)(label(->))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 6))(sort \ + Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1838)(content(Whitespace\" \"))))(Tile((id \ + 1842)(label(Exp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1843)(content(Whitespace\" \")))))((Secondary((id \ + 1845)(content(Whitespace\" \"))))(Tile((id 1850)(label(fun \ + ->))(mold((out Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1851)(content(Whitespace\" \ + \"))))(Tile((id 1852)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 1853)(label(e))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1855)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1856)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1858)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1859)(label(v))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 1861)(content(Whitespace\" \")))))))))(Secondary((id \ + 1864)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1870)(label(case end))(mold((out \ + Exp)(in_(Rul))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1871)(content(Whitespace\" \ + \"))))(Tile((id 1872)(label(e))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1874)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1875)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1876)(content(Whitespace\" \ + \"))))(Tile((id 1880)(label(Var))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 1881)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 1882)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 1884)(content(Whitespace\" \")))))))))(Secondary((id \ + 1886)(content(Whitespace\" \"))))(Tile((id \ + 1887)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1891)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1892)(content(Whitespace\" \"))))(Tile((id \ + 1893)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1895)(content(Whitespace\" \"))))(Tile((id \ + 1898)(label($==))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1899)(content(Whitespace\" \"))))(Tile((id \ + 1900)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1904)(content(Whitespace\" \")))))((Secondary((id \ + 1908)(content(Whitespace\" \"))))(Tile((id \ + 1909)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1913)(content(Whitespace\" \")))))))))(Secondary((id \ + 1917)(content(Whitespace\" \"))))(Tile((id \ + 1918)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1920)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1921)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1922)(content(Whitespace\" \ + \"))))(Tile((id 2078)(label(Lam))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 1930)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 1931)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1933)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1934)(content(Whitespace\" \"))))(Tile((id \ + 1937)(label(e1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 1938)(content(Whitespace\" \")))))))))(Secondary((id \ + 1940)(content(Whitespace\" \"))))(Tile((id \ + 1941)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1945)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1946)(content(Whitespace\" \"))))(Tile((id \ + 1947)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1949)(content(Whitespace\" \"))))(Tile((id \ + 1952)(label($==))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1953)(content(Whitespace\" \"))))(Tile((id \ + 1954)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1958)(content(Whitespace\" \")))))((Secondary((id \ + 1962)(content(Whitespace\" \"))))(Tile((id \ + 1963)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1967)(content(Whitespace\" \")))))))))(Secondary((id \ + 1971)(content(Whitespace\" \"))))(Tile((id \ + 2075)(label(Lam))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1979)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1980)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1982)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1983)(content(Whitespace\" \"))))(Tile((id \ + 2303)(label(s1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1990)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1993)(label(e1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1994)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1995)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1997)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1998)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))))))))))))(Secondary((id \ + 2000)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 2064)(content(Whitespace\" \")))))))))(Secondary((id \ + 2066)(content(Whitespace\" \"))))(Secondary((id \ + 1540)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1545)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1546)(content(Whitespace\" \"))))(Tile((id \ + 2305)(label(s2))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1553)(content(Whitespace\" \"))))(Tile((id \ + 1554)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1555)(content(Whitespace\" \"))))(Tile((id \ + 1556)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 1560)(label(Exp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 1561)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1562)(content(Whitespace\" \"))))(Grout((id 1565)(shape \ + Convex)))(Tile((id 1564)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 14))(sort \ + Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1566)(content(Whitespace\" \"))))(Grout((id 1803)(shape \ + Convex))))))))(Secondary((id 1571)(content(Whitespace\" \ + \"))))(Tile((id 1573)(label(->))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 6))(sort \ + Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1574)(content(Whitespace\" \"))))(Tile((id \ + 1578)(label(Exp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 1579)(content(Whitespace\" \")))))((Secondary((id \ + 1581)(content(Whitespace\" \"))))(Tile((id 1586)(label(fun \ + ->))(mold((out Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1587)(content(Whitespace\" \ + \"))))(Tile((id 1588)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 1589)(label(e))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1591)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1592)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1594)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1595)(label(v))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 1597)(content(Whitespace\" \")))))))))(Secondary((id \ + 1600)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1606)(label(case end))(mold((out \ + Exp)(in_(Rul))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1607)(content(Whitespace\" \ + \"))))(Tile((id 1608)(label(e))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1610)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1611)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1612)(content(Whitespace\" \ + \"))))(Tile((id 1616)(label(Var))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 1617)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 1618)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 1620)(content(Whitespace\" \")))))))))(Secondary((id \ + 1622)(content(Whitespace\" \"))))(Tile((id \ + 1623)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1627)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1628)(content(Whitespace\" \"))))(Tile((id \ + 1629)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1631)(content(Whitespace\" \"))))(Tile((id \ + 1634)(label($==))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1635)(content(Whitespace\" \"))))(Tile((id \ + 1636)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1640)(content(Whitespace\" \")))))((Secondary((id \ + 1644)(content(Whitespace\" \"))))(Tile((id \ + 1645)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1649)(content(Whitespace\" \")))))))))(Secondary((id \ + 1653)(content(Whitespace\" \"))))(Tile((id \ + 1654)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 1656)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1657)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 1658)(content(Whitespace\" \ + \"))))(Tile((id 2081)(label(Lam))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 1666)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 1667)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 1669)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1670)(content(Whitespace\" \"))))(Tile((id \ + 1673)(label(e1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 1674)(content(Whitespace\" \")))))))))(Secondary((id \ + 1676)(content(Whitespace\" \"))))(Tile((id \ + 1677)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1681)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 1682)(content(Whitespace\" \"))))(Tile((id \ + 1683)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1685)(content(Whitespace\" \"))))(Tile((id \ + 1688)(label($==))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 8))(sort \ + Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1689)(content(Whitespace\" \"))))(Tile((id \ + 1690)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1694)(content(Whitespace\" \")))))((Secondary((id \ + 1698)(content(Whitespace\" \"))))(Tile((id \ + 1699)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1703)(content(Whitespace\" \")))))))))(Secondary((id \ + 1707)(content(Whitespace\" \"))))(Tile((id \ + 2084)(label(Lam))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1715)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1716)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1718)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1719)(content(Whitespace\" \"))))(Tile((id \ + 2307)(label(s2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1726)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1729)(label(e1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1730)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1731)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1733)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1734)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))))))))))))(Secondary((id \ + 2068)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 1800)(content(Whitespace\" \")))))))))(Secondary((id \ + 1802)(content(Whitespace\" \"))))(Secondary((id \ + 410)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 414)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 415)(content(Whitespace\" \"))))(Tile((id \ + 2309)(label(s3))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 422)(content(Whitespace\" \"))))(Tile((id \ + 423)(label(:))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 11))(sort Pat))((shape(Concave 11))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 425)(content(Whitespace\" \"))))(Tile((id \ + 426)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 1209)(label(Exp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 430)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 14))(sort Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 432)(content(Whitespace\" \"))))(Grout((id 1215)(shape \ + Convex)))(Tile((id 434)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 14))(sort \ + Typ))((shape(Concave 14))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 994)(content(Whitespace\" \"))))(Tile((id \ + 1206)(label(Exp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 440)(content(Whitespace\" \"))))(Tile((id \ + 443)(label(->))(mold((out Typ)(in_())(nibs(((shape(Concave \ + 6))(sort Typ))((shape(Concave 6))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 444)(content(Whitespace\" \"))))(Tile((id \ + 1292)(label(Exp))(mold((out Typ)(in_())(nibs(((shape \ + Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 448)(content(Whitespace\" \")))))((Secondary((id \ + 451)(content(Whitespace\" \"))))(Tile((id 455)(label(fun \ + ->))(mold((out Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 456)(content(Whitespace\" \ + \"))))(Tile((id 458)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 459)(label(e))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 460)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 462)(label(x))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 463)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 465)(label(v))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 466)(content(Whitespace\" \")))))))))(Secondary((id \ + 470)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 475)(label(case end))(mold((out Exp)(in_(Rul))(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 476)(content(Whitespace\" \ + \"))))(Tile((id 478)(label(e))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 479)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 480)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 482)(content(Whitespace\" \ + \"))))(Tile((id 485)(label(Var))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 486)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 488)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 489)(content(Whitespace\" \")))))))))(Secondary((id \ + 492)(content(Whitespace\" \"))))(Tile((id \ + 493)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 496)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 497)(content(Whitespace\" \"))))(Tile((id \ + 499)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 500)(content(Whitespace\" \"))))(Tile((id \ + 504)(label($==))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 505)(content(Whitespace\" \"))))(Tile((id \ + 506)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 509)(content(Whitespace\" \")))))((Secondary((id \ + 513)(content(Whitespace\" \"))))(Tile((id \ + 515)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 518)(content(Whitespace\" \")))))))))(Secondary((id \ + 522)(content(Whitespace\" \"))))(Tile((id \ + 1418)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 525)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 526)(label(| =>))(mold((out \ + Rul)(in_(Pat))(nibs(((shape(Concave 19))(sort \ + Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id 528)(content(Whitespace\" \ + \"))))(Tile((id 2087)(label(Lam))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 535)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape(Concave 1))(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 537)(label(y))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 538)(label(,))(mold((out Pat)(in_())(nibs(((shape(Concave \ + 14))(sort Pat))((shape(Concave 14))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 540)(content(Whitespace\" \"))))(Tile((id \ + 542)(label(e1))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 543)(content(Whitespace\" \")))))))))(Secondary((id \ + 546)(content(Whitespace\" \"))))(Tile((id \ + 547)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 550)(label(if then else))(mold((out Exp)(in_(Exp \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 12))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 551)(content(Whitespace\" \"))))(Tile((id \ + 553)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 554)(content(Whitespace\" \"))))(Tile((id \ + 558)(label($==))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 8))(sort Exp))((shape(Concave 8))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 559)(content(Whitespace\" \"))))(Tile((id \ + 560)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 563)(content(Whitespace\" \")))))((Secondary((id \ + 567)(content(Whitespace\" \"))))(Tile((id \ + 569)(label(e))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 572)(content(Whitespace\" \")))))))))(Secondary((id \ + 576)(content(Whitespace\" \"))))(Tile((id \ + 2090)(label(Lam))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 584)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 586)(label(y))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 587)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 589)(content(Whitespace\" \"))))(Tile((id \ + 2311)(label(s3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 595)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 598)(label(e1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 599)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 601)(label(x))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 602)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 604)(label(v))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))))))))))))(Secondary((id \ + 605)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ + 669)(content(Whitespace\" \")))))))))(Secondary((id \ + 1308)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ + 902)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 906)(label(let = in))(mold((out Exp)(in_(Pat \ + Exp))(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0 1 2))(children(((Secondary((id \ + 907)(content(Whitespace\" \"))))(Tile((id \ + 1463)(label(in))(mold((out Pat)(in_())(nibs(((shape \ + Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 914)(content(Whitespace\" \")))))((Secondary((id \ + 917)(content(Whitespace\" \"))))(Tile((id \ + 2478)(label(Lam))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1471)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1474)(label(\"\\\"b\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 1475)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 1477)(content(Whitespace\" \"))))(Tile((id \ + 1480)(label(Var))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1481)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1484)(label(\"\\\"a\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children())))))))))))))(Tile((id \ + 1485)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1488)(label(\"\\\"a\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 1489)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1493)(label(Var))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1494)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1497)(label(\"\\\"x\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 954)(content(Whitespace\" \")))))))))(Secondary((id \ + 956)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ + 1539)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2313)(label(s0))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1535)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1538)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 2348)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2349)(content(Whitespace\" \"))))(Tile((id \ + 2317)(label(s1))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2318)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2321)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 2322)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2339)(content(Whitespace\" \"))))(Tile((id \ + 2325)(label(s2))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2326)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2329)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Tile((id \ + 2330)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave \ + 14))(sort Exp))((shape(Concave 14))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 2340)(content(Whitespace\" \"))))(Tile((id \ + 2333)(label(s3))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2334)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 2337)(label(in))(mold((out Exp)(in_())(nibs(((shape \ + Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))))))))))))(Secondary((id \ + 674)(content(Whitespace\"\\226\\143\\142\")))))))(ancestors())))(caret \ + Outer))"; + backup_text = + "#recursive sum type dynamics tests#\n\ + #all calls should evaluate fully with no exns or cast fails#\n\ + type Exp = Var(String) + Lam(String, Exp) in\n\n\ + let s0 : ( , , ) -> = fun (e,x,v) ->\n\ + case e\n\ + | Var(y) => (if y $== x then v else e)\n\ + | Lam(y, e1) => (if y $== x then e else Lam(y, s0(e1,x,v))) \n\ + end in \n\ + let s1 : ( , , ) -> Exp = fun (e,x,v) ->\n\ + case e\n\ + | Var(y) => (if y $== x then v else e)\n\ + | Lam(y, e1) => (if y $== x then e else Lam(y, s1(e1,x,v)))\n\ + end in \n\ + let s2 : (Exp, , ) -> Exp = fun (e,x,v) ->\n\ + case e\n\ + | Var(y) => (if y $== x then v else e)\n\ + | Lam(y, e1) => (if y $== x then e else Lam(y, s2(e1,x,v)))\n\ + end in \n\ + let s3 : (Exp, , Exp) -> Exp = fun (e,x,v) ->\n\ + case e\n\ + | Var(y) => (if y $== x then v else e)\n\ + | Lam(y, e1) => (if y $== x then e else Lam(y, s3(e1,x,v)))\n\ + end in\n\n\ + let in = Lam(\"b\", Var(\"a\")),\"a\",Var(\"x\") in\n\ + (s0(in), s1(in), s2(in), s3(in))\n"; + } ) ); + ] ); + } diff --git a/src/haz3lweb/Keyboard.re b/src/haz3lweb/Keyboard.re index 7ade716b6d..e5fb8c8e16 100644 --- a/src/haz3lweb/Keyboard.re +++ b/src/haz3lweb/Keyboard.re @@ -36,13 +36,29 @@ let handle_key_event = (k: Key.t, ~model: Model.t): list(Update.t) => { } | {key: D(key), sys: _, shift: Down, meta: Up, ctrl: Up, alt: Up} when is_f_key(key) => + let get_term = z => z |> Zipper.unselect_and_zip |> MakeTerm.go |> fst; switch (key) { - | "F2" => print(Zipper.show(zipper)) + | "F1" => zipper |> Zipper.show |> print + | "F2" => zipper |> Zipper.unselect_and_zip |> Segment.show |> print + | "F3" => zipper |> get_term |> TermBase.UExp.show |> print + | "F4" => zipper |> get_term |> Statics.mk_map |> Statics.Map.show |> print + | "F5" => + let term = zipper |> get_term; + let map = term |> Statics.mk_map; + Interface.get_result(map, term) |> ProgramResult.show |> print; | "F6" => - let (term, _) = MakeTerm.go(Zipper.unselect_and_zip(zipper)); - print(TermBase.UExp.show(term)); + let index = Indicated.index(zipper); + let map = zipper |> get_term |> Statics.mk_map; + switch (index) { + | Some(index) => + switch (Haz3lcore.Id.Map.find_opt(index, map)) { + | Some(ci) => print(Info.show(ci)) + | _ => print("DEBUG: No CI found for index") + } + | _ => print("DEBUG: No indicated index") + }; | _ => [] - } + }; | {key: D(key), sys: _, shift, meta: Up, ctrl: Up, alt: Up} => switch (shift, key) { | (Up, "ArrowLeft") => now(Move(Local(Left(ByChar)))) @@ -100,7 +116,7 @@ let handle_key_event = (k: Key.t, ~model: Model.t): list(Update.t) => { | "p" => now(Pick_up) | "a" => now(Move(Extreme(Up))) @ now(Select(Resize(Extreme(Down)))) | "k" => [ResetCurrentEditor] - | _ when is_digit(key) => [SwitchSlide(int_of_string(key))] + | _ when is_digit(key) => [SwitchScratchSlide(int_of_string(key))] | "ArrowLeft" => now(Move(Extreme(Left(ByToken)))) | "ArrowRight" => now(Move(Extreme(Right(ByToken)))) | "ArrowUp" => now(Move(Extreme(Up))) @@ -114,7 +130,7 @@ let handle_key_event = (k: Key.t, ~model: Model.t): list(Update.t) => { | "p" => now(Pick_up) | "a" => now(Move(Extreme(Up))) @ now(Select(Resize(Extreme(Down)))) | "k" => [ResetCurrentEditor] - | _ when is_digit(key) => [SwitchSlide(int_of_string(key))] + | _ when is_digit(key) => [SwitchScratchSlide(int_of_string(key))] | "ArrowLeft" => now(Move(Local(Left(ByToken)))) | "ArrowRight" => now(Move(Local(Right(ByToken)))) | "Home" => now(Move(Extreme(Up))) diff --git a/src/haz3lweb/LangDocMessages.re b/src/haz3lweb/LangDocMessages.re index da48cbc424..6b97e83872 100644 --- a/src/haz3lweb/LangDocMessages.re +++ b/src/haz3lweb/LangDocMessages.re @@ -48,6 +48,9 @@ let pat = v => Example.mk_monotile(Form.mk(Form.ss, [v], Mold.(mk_op(Pat, [])))); let typ = t => Example.mk_monotile(Form.mk(Form.ss, [t], Mold.(mk_op(Typ, [])))); +let tpat = v => + Example.mk_monotile(Form.mk(Form.ss, [v], Mold.(mk_op(TPat, [])))); +let typ_pat_var = t => Example.mk_monotile(Form.mk_atomic(TPat, t)); let int = n => Example.mk_monotile(Form.mk_atomic(Exp, n)); let bool = b => Example.mk_monotile(Form.mk_atomic(Exp, b)); let mk_parens_exp = Example.mk_tile(Form.get("parens_exp")); @@ -90,6 +93,8 @@ let mk_fun = Example.mk_tile(Form.get("fun_")); let mk_ap_exp = Example.mk_tile(Form.get("ap_exp")); let mk_ap_pat = Example.mk_tile(Form.get("ap_pat")); let mk_let = Example.mk_tile(Form.get("let_")); +let mk_tyalias = Example.mk_tile(Form.get("type_alias")); + let mk_if = Example.mk_tile(Form.get("if_")); let mk_test = Example.mk_tile(Form.get("test")); let mk_case = Example.mk_tile(Form.get("case")); @@ -105,34 +110,47 @@ let mk_example = str => { }; let empty_hole_exp_group = "empty_hole_exp_group"; -let empty_hole_exp: form = { +let empty_hole_tpat_group = "empty_hole_tpat_group"; +let empty_hole_template = (sort, str, id): form => { let explanation = { - message: "Empty hole. This marks an expression that needs to be filled in.", + message: + Printf.sprintf( + "Empty hole. This should be filled with %s to complete the program.", + str, + ), feedback: Unselected, }; { - id: "empty_hole_exp", - syntactic_form: [exp("EmptyHole")], + id, + syntactic_form: [sort("EmptyHole")], expandable_id: None, explanation, examples: [], }; }; +let empty_hole_exp: form = + empty_hole_template(exp, "an expression", "empty_hole_exp"); +let empty_hole_tpat: form = + empty_hole_template(tpat, "a type pattern", "empty_hole_tpat"); let multi_hole_exp_group = "multi_hole_exp_group"; -let multi_hole_exp: form = { +let multi_hole_tpat_group = "multi_hole_tpat_group"; + +let multi_hole_template = (sort, id: string): form => { let explanation = { message: "Not recognized. This is an invalid term.", feedback: Unselected, }; { - id: "multi_hole_exp", - syntactic_form: [exp("INVALID")], + id, + syntactic_form: [sort("INVALID")], expandable_id: None, explanation, examples: [], }; }; +let multi_hole_exp: form = multi_hole_template(exp, "multi_hole_exp"); +let multi_hole_tpat: form = multi_hole_template(tpat, "multi_hole_tpat"); let triv_exp_group = "triv_exp_group"; let triv_exp: form = { @@ -242,7 +260,7 @@ let function_var_group = "function_var_group"; let function_tuple_group = "function_tuple_group"; let function_tuple_2_group = "function_tuple_2_group"; let function_tuple_3_group = "function_tuple_3_group"; -let function_tag_group = "function_tag_group"; +let function_ctr_group = "function_ctr_group"; let function_ap_group = "function_ap_group"; let basic_fun_ex = { sub_id: "basic_fun_ex", @@ -334,8 +352,8 @@ let tuple3_fun_ex = { message: "When given a 3-tuple of booleans, the function evaluates to the logical-and of the three booleans.", feedback: Unselected, }; -let tag_fun_ex = { - sub_id: "tag_fun_ex", +let ctr_fun_ex = { + sub_id: "ctr_fun_ex", term: mk_example("fun None -> 1"), message: "When given a None constructor argument, the function evaluates 1.", feedback: Unselected, @@ -699,20 +717,20 @@ let function_tuple3_exp: form = { }; let _pat = pat("C"); let _exp = exp("e"); -let function_tag_exp_coloring_ids = +let function_ctr_exp_coloring_ids = _pat_body_function_exp_coloring_ids(Piece.id(_pat), Piece.id(_exp)); -let function_tag_exp: form = { +let function_ctr_exp: form = { let explanation = { message: "Function literal. The only value that matches the [*argument pattern*](%i) is the *`%s` constructor*. When applied to an argument which matches the [*argument pattern*](%i), evaluates to the function [*body*](%i).", feedback: Unselected, }; let form = [mk_fun([[space(), _pat, space()]]), space(), _exp]; { - id: "function_tag_exp", + id: "function_ctr_exp", syntactic_form: form, expandable_id: Some(Piece.id(_pat)), explanation, - examples: [tag_fun_ex], + examples: [ctr_fun_ex], }; }; let _pat_con = pat("p_con"); @@ -840,12 +858,15 @@ let var_exp: form = { }; }; -let tag_exp_group = "tag_exp_group"; -let tag_exp: form = { - let explanation = {message: "`%s` constructor.", feedback: Unselected}; +let ctr_exp_group = "ctr_exp_group"; +let ctr_exp: form = { + let explanation = { + message: "`%s` is a constructor for a sum type variant.", + feedback: Unselected, + }; { - id: "tag_exp", - syntactic_form: [exp("C")], + id: "ctr_exp", + syntactic_form: [exp("Constructor")], expandable_id: None, explanation, examples: [], @@ -854,7 +875,9 @@ let tag_exp: form = { let let_base_exp_group = "let_base_exp_group"; let let_empty_hole_exp_group = "let_empty_hole_exp_group"; +let let_empty_hole_tpat_group = "let_empty_hole_tpat_group"; let let_multi_hole_exp_group = "let_multi_hole_exp_group"; +let let_multi_hole_tpat_group = "let_multi_hole_tpat_group"; let let_wild_exp_group = "let_wild_hole_exp_group"; let let_int_exp_group = "let_int_exp_group"; let let_float_exp_group = "let_float_exp_group"; @@ -868,7 +891,7 @@ let let_var_exp_group = "let_var_exp_group"; let let_tuple_base_exp_group = "let_tuple_base_exp_group"; let let_tuple2_exp_group = "let_tuple2_exp_group"; let let_tuple3_exp_group = "let_tuple3_exp_group"; -let let_tag_exp_group = "let_tag_exp_group"; +let let_ctr_exp_group = "let_ctr_exp_group"; let let_ap_exp_group = "let_ap_exp_group"; let let_base_ex = { sub_id: "let_base_ex", @@ -954,8 +977,8 @@ let let_tuple3_ex = { message: "The x is bound to 1, the y is bound to 2, and the z is bound to 3, so the expression evaluates to 1 + 2 + 3, which is 6.", feedback: Unselected, }; -let let_tag_ex = { - sub_id: "let_tag_ex", +let let_ctr_ex = { + sub_id: "let_ctr_ex", term: mk_example("let None = None in \n2"), message: "The None is thrown away, so the expression evaluates to 2.", feedback: Unselected, @@ -1421,13 +1444,13 @@ let let_tuple3_exp: form = { let _pat = pat("C"); let _exp_def = exp("e_def"); let _exp_body = exp("e_body"); -let let_tag_exp_coloring_ids = +let let_ctr_exp_coloring_ids = _pat_def_body_let_exp_coloring_ids( Piece.id(_pat), Piece.id(_exp_def), Piece.id(_exp_body), ); -let let_tag_exp: form = { +let let_ctr_exp: form = { let explanation = { message: "Let expression. The only value for the [*definition*](%i) that matches the [*pattern*](%i) is the *`%s` constructor*. The [*definition*](%i) can't be referenced in the [*body*](%i).", feedback: Unselected, @@ -1438,11 +1461,11 @@ let let_tag_exp: form = { _exp_body, ]; { - id: "let_tag_exp", + id: "let_ctr_exp", syntactic_form: form, expandable_id: Some(Piece.id(_pat)), explanation, - examples: [let_tag_ex], + examples: [let_ctr_ex], }; }; let _pat_con = pat("p_con"); @@ -1477,6 +1500,32 @@ let let_ap_exp: form = { }; }; +let tyalias_exp_group = "tyalias_exp_group"; +let _tpat = tpat("p"); +let _typ_def = typ("ty_def"); +let tyalias_base_exp_coloring_ids = (~tpat_id: Id.t, ~def_id: Id.t) => [ + (Piece.id(_tpat), tpat_id), + (Piece.id(_typ_def), def_id), +]; +let tyalias_base_exp: form = { + let explanation = { + message: "Type alias expression. The [*type*](%i) is bound to the [*type variable*](%i) in the body.", + feedback: Unselected, + }; + let form = [ + mk_tyalias([[space(), _tpat, space()], [space(), _typ_def, space()]]), + linebreak(), + exp("e_body"), + ]; + { + id: "tyalias_base_exp", + syntactic_form: form, + expandable_id: None, + explanation, + examples: [], + }; +}; + let funapp_exp_group = "funapp_exp_group"; let conapp_exp_group = "conapp_exp_group"; let funapp_exp_ex = { @@ -2864,15 +2913,15 @@ let tuple_pat_size3: form = { }; }; -let tag_pat_group = "tag_pat_group"; -let tag_pat: form = { +let ctr_pat_group = "ctr_pat_group"; +let ctr_pat: form = { let explanation = { message: "Constructor pattern. Only expressions that match the *`%s` constructor* match this constructor pattern.", feedback: Unselected, }; { - id: "tag_pat", - syntactic_form: [pat("C")], + id: "ctr_pat", + syntactic_form: [pat("Constructor")], expandable_id: None, explanation, examples: [], @@ -3088,6 +3137,59 @@ let arrow3_typ: form = { }; }; +let labelled_sum_typ_group = "labelled_sum_typ_group"; +let labelled_sum_typ: form = { + let explanation = { + message: "Sum type. Sum types express finite labeled choices. Values of this type consist of one of the specified constructors applied to a parameter of the corresponding parameter type, if specified. Constructor names must be unique within a sum.", + feedback: Unselected, + }; + let divider = Example.mk_monotile(Form.get("typ_plus")); + { + id: "labelled_sum_typ", + syntactic_form: [ + space(), + typ("Cons(ty)"), + space(), + divider, + space(), + typ("..."), + space(), + ], + expandable_id: Some(Piece.id(divider)), + explanation, + examples: [], + }; +}; +let sum_typ_unary_constructor_def_group = "sum_typ_unary_constructor_def_group"; +let sum_typ_unary_constructor_def: form = { + let explanation = { + message: "Parameterized constructor definition. This specifies one possible way of constructing the parent sum type, when applied to a parameter of the specified parameter type.", + feedback: Unselected, + }; + { + id: "sum_typ_unary_constructor_def", + syntactic_form: [typ("Constructor(type)")], + expandable_id: None, + explanation, + examples: [], + }; +}; + +let sum_typ_nullary_constructor_def_group = "sum_typ_nullary_constructor_def_group"; +let sum_typ_nullary_constructor_def: form = { + let explanation = { + message: "Constant constructor definition. This specifies one possible way of constructing the parent sum type. It does not take an argument, so it a constant of that type.", + feedback: Unselected, + }; + { + id: "sum_typ_nullary_constructor_def", + syntactic_form: [typ("Constructor")], + expandable_id: None, + explanation, + examples: [], + }; +}; + let tuple_typ_group = "tuple_typ_group"; let tuple2_typ_group = "tuple2_typ_group"; let tuple3_typ_group = "tuple3_typ_group"; @@ -3160,10 +3262,28 @@ let tuple3_typ: form = { let var_typ_group = "var_typ_group"; let var_typ: form = { - let explanation = {message: "`%s` type.", feedback: Unselected}; + let explanation = { + message: "`%s` is a type variable.", + feedback: Unselected, + }; { id: "var_typ", - syntactic_form: [typ("x")], + syntactic_form: [typ("T")], + expandable_id: None, + explanation, + examples: [], + }; +}; + +let var_typ_pat_group = "var_typ_pat_group"; +let var_typ_pat: form = { + let explanation = { + message: "`%s` binds a type variable.", + feedback: Unselected, + }; + { + id: "var_typ_pat", + syntactic_form: [typ_pat_var("T")], expandable_id: None, explanation, examples: [], @@ -3181,25 +3301,40 @@ type t = { groups: list((string, form_group)), }; +let find = (p: 'a => bool, xs: list('a), err: string): 'a => + switch (List.find_opt(p, xs)) { + | Some(x) => x + | None => failwith(err) + }; + let get_group = (group_id, doc: t) => { - let (_, form_group) = List.find(((id, _)) => id == group_id, doc.groups); + let (_, form_group) = + find( + ((id, _)) => id == group_id, + doc.groups, + "group not found: " ++ group_id, + ); form_group; }; +let get_form = (form_id, docs) => + find(({id, _}) => id == form_id, docs, "form not found: " ++ form_id); + +let get_example = (example_sub_id, examples) => + find( + ({sub_id, _}) => sub_id == example_sub_id, + examples, + "example not found: " ++ example_sub_id, + ); + let get_form_and_options = (group_id, doc: t) => { let form_group = get_group(group_id, doc); let (selected_id, _) = List.nth(form_group.options, form_group.current_selection); - let form = List.find(({id, _}) => id == selected_id, doc.forms); + let form = get_form(selected_id, doc.forms); (form, form_group.options); }; -let get_example = (example_sub_id, examples) => - List.find(({sub_id, _}) => sub_id == example_sub_id, examples); - -let get_form = (form_id, docs) => - List.find(({id, _}) => id == form_id, docs); - let rec update_form = (new_form, docs) => { switch (docs) { | [] => [] @@ -3246,12 +3381,14 @@ let init_options = options => { let init = { show: true, - highlight: true, + highlight: false, specificity_open: false, forms: [ // Expressions empty_hole_exp, + empty_hole_tpat, multi_hole_exp, + multi_hole_tpat, triv_exp, bool_exp, int_exp, @@ -3274,13 +3411,13 @@ let init = { function_tuple_exp, function_tuple2_exp, function_tuple3_exp, - function_tag_exp, + function_ctr_exp, function_ap_exp, tuple_exp, tuple_exp_size2, tuple_exp_size3, var_exp, - tag_exp, + ctr_exp, let_base_exp, let_empty_hole_exp, let_multi_hole_exp, @@ -3297,8 +3434,9 @@ let init = { let_tuple_exp, let_tuple2_exp, let_tuple3_exp, - let_tag_exp, + let_ctr_exp, let_ap_exp, + tyalias_base_exp, funapp_exp, conapp_exp, if_exp, @@ -3348,7 +3486,7 @@ let init = { tuple_pat, tuple_pat_size2, tuple_pat_size3, - tag_pat, + ctr_pat, ap_pat, typann_pat, // Types @@ -3361,15 +3499,21 @@ let init = { list_typ, arrow_typ, arrow3_typ, + labelled_sum_typ, + sum_typ_unary_constructor_def, + sum_typ_nullary_constructor_def, tuple_typ, tuple2_typ, tuple3_typ, var_typ, + var_typ_pat, ], groups: [ // Expressions (empty_hole_exp_group, init_options([(empty_hole_exp.id, [])])), + (empty_hole_tpat_group, init_options([(empty_hole_tpat.id, [])])), (multi_hole_exp_group, init_options([(multi_hole_exp.id, [])])), + (multi_hole_tpat_group, init_options([(multi_hole_tpat.id, [])])), (triv_exp_group, init_options([(triv_exp.id, [])])), (bool_exp_group, init_options([(bool_exp.id, [])])), (int_exp_group, init_options([(int_exp.id, [])])), @@ -3491,10 +3635,10 @@ let init = { ]), ), ( - function_tag_group, + function_ctr_group, init_options([ (function_exp.id, [pat("p")]), - (function_tag_exp.id, [pat("C")]), + (function_ctr_exp.id, [pat("C")]), ]), ), ( @@ -3526,7 +3670,7 @@ let init = { ]), ), (var_exp_group, init_options([(var_exp.id, [])])), - (tag_exp_group, init_options([(tag_exp.id, [])])), + (ctr_exp_group, init_options([(ctr_exp.id, [])])), (let_base_exp_group, init_options([(let_base_exp.id, [])])), ( let_empty_hole_exp_group, @@ -3639,10 +3783,10 @@ let init = { ]), ), ( - let_tag_exp_group, + let_ctr_exp_group, init_options([ (let_base_exp.id, [pat("p")]), - (let_tag_exp.id, [pat("C")]), + (let_ctr_exp.id, [pat("C")]), ]), ), ( @@ -3652,6 +3796,7 @@ let init = { (let_ap_exp.id, [pat("p_con"), mk_ap_pat([[pat("p_arg")]])]), ]), ), + (tyalias_exp_group, init_options([(tyalias_base_exp.id, [])])), (funapp_exp_group, init_options([(funapp_exp.id, [])])), (conapp_exp_group, init_options([(conapp_exp.id, [])])), (if_exp_group, init_options([(if_exp.id, [])])), @@ -3722,7 +3867,7 @@ let init = { ), ]), ), - (tag_pat_group, init_options([(tag_pat.id, [])])), + (ctr_pat_group, init_options([(ctr_pat.id, [])])), (ap_pat_group, init_options([(ap_pat.id, [])])), (typann_pat_group, init_options([(typann_pat.id, [])])), // Types @@ -3741,6 +3886,15 @@ let init = { (arrow3_typ.id, [typ("ty_arg2"), arrow(), typ("ty_out")]), ]), ), + (labelled_sum_typ_group, init_options([(labelled_sum_typ.id, [])])), + ( + sum_typ_unary_constructor_def_group, + init_options([(sum_typ_unary_constructor_def.id, [])]), + ), + ( + sum_typ_nullary_constructor_def_group, + init_options([(sum_typ_nullary_constructor_def.id, [])]), + ), (tuple_typ_group, init_options([(tuple_typ.id, [])])), ( tuple2_typ_group, @@ -3760,6 +3914,7 @@ let init = { ]), ), (var_typ_group, init_options([(var_typ.id, [])])), + (var_typ_pat_group, init_options([(var_typ_pat.id, [])])), ], }; diff --git a/src/haz3lweb/LanguageRefSlide.ml b/src/haz3lweb/LanguageRefSlide.ml deleted file mode 100644 index 827279da11..0000000000 --- a/src/haz3lweb/LanguageRefSlide.ml +++ /dev/null @@ -1,1069 +0,0 @@ -let slide : ScratchSlide.persistent_state = - ( 3588, - { - zipper = - "((selection((focus \ - Left)(content())))(backpack())(relatives((siblings(((Secondary((id \ - 2915)(content(Comment\"# Hazel Language Quick Reference \ - #\")))))((Secondary((id \ - 3020)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3021)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3150)(content(Comment\"# Empty holes stand for missing expressions, \ - patterns, or types #\"))))(Secondary((id \ - 3030)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 3035)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 3036)(content(Whitespace\" \ - \"))))(Tile((id 3047)(label(empty_hole))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 3048)(content(Whitespace\" \")))))((Secondary((id \ - 3052)(content(Whitespace\" \"))))(Grout((id 3051)(shape \ - Convex)))(Secondary((id 3050)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 3151)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3152)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2840)(content(Comment\"# Integers #\"))))(Secondary((id \ - 2829)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1498)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1499)(content(Whitespace\" \ - \"))))(Tile((id 1508)(label(int_lits))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1509)(content(Whitespace\" \"))))(Tile((id 1510)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 1512)(content(Whitespace\" \"))))(Tile((id \ - 1515)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 1516)(content(Whitespace\" \")))))((Secondary((id \ - 1519)(content(Whitespace\" \"))))(Tile((id 1520)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1523)(content(Whitespace\" \")))))))))(Secondary((id \ - 1525)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1530)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1531)(content(Whitespace\" \ - \"))))(Tile((id 1540)(label(negation))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1541)(content(Whitespace\" \")))))((Secondary((id \ - 1544)(content(Whitespace\" \"))))(Tile((id 1545)(label(-))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape(Concave 2))(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1546)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1549)(content(Whitespace\" \")))))))))(Secondary((id \ - 1551)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1556)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1557)(content(Whitespace\" \ - \"))))(Tile((id 1568)(label(arithmetic))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1569)(content(Whitespace\" \")))))((Secondary((id \ - 1572)(content(Whitespace\" \"))))(Tile((id 1573)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1574)(label(*))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 4))(sort Exp))((shape(Concave \ - 4))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 1576)(label(2))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1577)(content(Whitespace\" \"))))(Tile((id 1578)(label(+))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1580)(content(Whitespace\" \"))))(Tile((id 1581)(label(8))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1582)(label(/))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 4))(sort Exp))((shape(Concave \ - 4))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 1584)(label(4))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1587)(content(Whitespace\" \")))))))))(Secondary((id \ - 1589)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1594)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1595)(content(Whitespace\" \ - \"))))(Tile((id 1610)(label(int_comparison))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1611)(content(Whitespace\" \")))))((Secondary((id \ - 1614)(content(Whitespace\" \"))))(Tile((id \ - 1615)(label(\"(\"\")\"))(mold((out Exp)(in_(Exp))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Tile((id 1617)(label(10))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1618)(content(Whitespace\" \"))))(Tile((id 1621)(label(==))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 8))(sort Exp))((shape(Concave \ - 8))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1622)(content(Whitespace\" \"))))(Tile((id 1624)(label(10))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1625)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1627)(content(Whitespace\" \"))))(Tile((id 1628)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1629)(content(Whitespace\" \"))))(Tile((id 1630)(label(<))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1632)(content(Whitespace\" \"))))(Tile((id 1633)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1634)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1636)(content(Whitespace\" \"))))(Tile((id 1637)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1638)(content(Whitespace\" \"))))(Tile((id 1641)(label(<=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 8))(sort Exp))((shape(Concave \ - 8))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1642)(content(Whitespace\" \"))))(Tile((id 1643)(label(3))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1644)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1646)(content(Whitespace\" \"))))(Tile((id 1647)(label(3))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1648)(content(Whitespace\" \"))))(Tile((id 1649)(label(>))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1651)(content(Whitespace\" \"))))(Tile((id 1652)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1653)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1655)(content(Whitespace\" \"))))(Tile((id 1656)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1657)(content(Whitespace\" \"))))(Tile((id 1660)(label(>=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 8))(sort Exp))((shape(Concave \ - 8))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1661)(content(Whitespace\" \"))))(Tile((id 1662)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - 1665)(content(Whitespace\" \")))))))))(Secondary((id \ - 3353)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2841)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2866)(content(Comment\"# Floating Point Numbers #\"))))(Secondary((id \ - 1669)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1673)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1674)(content(Whitespace\" \ - \"))))(Tile((id 1685)(label(float_lits))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1686)(content(Whitespace\" \"))))(Tile((id 1687)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 1689)(content(Whitespace\" \"))))(Tile((id \ - 1694)(label(Float))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 1695)(content(Whitespace\" \")))))((Secondary((id \ - 1698)(content(Whitespace\" \"))))(Tile((id \ - 1701)(label(1.5))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1704)(content(Whitespace\" \")))))))))(Secondary((id \ - 1706)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1711)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1712)(content(Whitespace\" \ - \"))))(Tile((id 1724)(label(float_artih))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1725)(content(Whitespace\" \")))))((Secondary((id \ - 1728)(content(Whitespace\" \"))))(Tile((id 1730)(label(1.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1731)(content(Whitespace\" \"))))(Tile((id 1734)(label(*.))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 4))(sort Exp))((shape(Concave \ - 4))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1735)(content(Whitespace\" \"))))(Tile((id 1737)(label(2.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1738)(content(Whitespace\" \"))))(Tile((id 1741)(label(+.))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1742)(content(Whitespace\" \"))))(Tile((id 1744)(label(8.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1745)(content(Whitespace\" \"))))(Tile((id 1748)(label(/.))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 4))(sort Exp))((shape(Concave \ - 4))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1749)(content(Whitespace\" \"))))(Tile((id 1751)(label(4.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1754)(content(Whitespace\" \")))))))))(Secondary((id \ - 1756)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1761)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1762)(content(Whitespace\" \ - \"))))(Tile((id 1779)(label(float_comparison))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1780)(content(Whitespace\" \")))))((Secondary((id \ - 1783)(content(Whitespace\" \"))))(Tile((id \ - 1784)(label(\"(\"\")\"))(mold((out Exp)(in_(Exp))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Tile((id 1787)(label(10.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1788)(content(Whitespace\" \"))))(Tile((id \ - 1792)(label(==.))(mold((out Exp)(in_())(nibs(((shape(Concave 8))(sort \ - Exp))((shape(Concave 8))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1793)(content(Whitespace\" \"))))(Tile((id \ - 1796)(label(10.))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 1797)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave 14))(sort \ - Exp))((shape(Concave 14))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1799)(content(Whitespace\" \"))))(Tile((id 1801)(label(1.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1802)(content(Whitespace\" \"))))(Tile((id 1805)(label(<.))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1806)(content(Whitespace\" \"))))(Tile((id 1808)(label(2.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1809)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1811)(content(Whitespace\" \"))))(Tile((id 1813)(label(2.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1814)(content(Whitespace\" \"))))(Tile((id \ - 1818)(label(<=.))(mold((out Exp)(in_())(nibs(((shape(Concave 8))(sort \ - Exp))((shape(Concave 8))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1819)(content(Whitespace\" \"))))(Tile((id 1821)(label(3.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1822)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1824)(content(Whitespace\" \"))))(Tile((id 1826)(label(3.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1827)(content(Whitespace\" \"))))(Tile((id 1830)(label(>.))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1831)(content(Whitespace\" \"))))(Tile((id 1833)(label(2.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1834)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1836)(content(Whitespace\" \"))))(Tile((id 1838)(label(2.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1839)(content(Whitespace\" \"))))(Tile((id \ - 1843)(label(>=.))(mold((out Exp)(in_())(nibs(((shape(Concave 8))(sort \ - Exp))((shape(Concave 8))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1844)(content(Whitespace\" \"))))(Tile((id 1846)(label(1.))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - 1849)(content(Whitespace\" \")))))))))(Secondary((id \ - 1851)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2867)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2878)(content(Comment\"# Booleans #\"))))(Secondary((id \ - 1853)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1857)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1858)(content(Whitespace\" \ - \"))))(Tile((id 1867)(label(booleans))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1868)(content(Whitespace\" \"))))(Tile((id 1869)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 1871)(content(Whitespace\" \"))))(Tile((id \ - 1872)(label(\"(\"\")\"))(mold((out Typ)(in_(Typ))(nibs(((shape \ - Convex)(sort Typ))((shape Convex)(sort Typ))))))(shards(0 \ - 1))(children(((Tile((id 1876)(label(Bool))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id 1877)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 14))(sort Typ))((shape(Concave \ - 14))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 1879)(content(Whitespace\" \"))))(Tile((id \ - 1883)(label(Bool))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 1884)(content(Whitespace\" \")))))((Secondary((id \ - 1887)(content(Whitespace\" \"))))(Tile((id \ - 1888)(label(\"(\"\")\"))(mold((out Exp)(in_(Exp))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Tile((id 1892)(label(true))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1893)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1895)(content(Whitespace\" \"))))(Tile((id \ - 1900)(label(false))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - 1903)(content(Whitespace\" \")))))))))(Secondary((id \ - 1905)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1910)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1911)(content(Whitespace\" \ - \"))))(Tile((id 1924)(label(conditionals))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1925)(content(Whitespace\" \")))))((Secondary((id \ - 1928)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1932)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1933)(content(Whitespace\" \ - \"))))(Tile((id 1935)(label(\"(\"\")\"))(mold((out \ - Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0 1))(children(((Tile((id 1936)(label(x))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id 1937)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 14))(sort Pat))((shape(Concave \ - 14))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 1939)(content(Whitespace\" \"))))(Tile((id 1940)(label(y))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children()))))))))(Secondary((id \ - 1941)(content(Whitespace\" \")))))((Secondary((id \ - 1944)(content(Whitespace\" \"))))(Tile((id \ - 1945)(label(\"(\"\")\"))(mold((out Exp)(in_(Exp))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Tile((id 1946)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1947)(content(Whitespace\" \"))))(Tile((id 1948)(label(+))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1950)(content(Whitespace\" \"))))(Tile((id 1951)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 1952)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1954)(content(Whitespace\" \"))))(Tile((id 1955)(label(3))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1956)(content(Whitespace\" \"))))(Tile((id 1957)(label(+))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1959)(content(Whitespace\" \"))))(Tile((id 1960)(label(3))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - 1963)(content(Whitespace\" \")))))))))(Secondary((id \ - 1965)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 1969)(label(if then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 12))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 1970)(content(Whitespace\" \ - \"))))(Tile((id 1972)(label(y))(mold((out Exp)(in_())(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1973)(content(Whitespace\" \"))))(Tile((id 1974)(label(>))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 1976)(content(Whitespace\" \"))))(Tile((id 1977)(label(x))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1980)(content(Whitespace\" \")))))((Secondary((id \ - 1984)(content(Whitespace\" \"))))(Tile((id 1986)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 1991)(content(Whitespace\" \"))))(Secondary((id \ - 1987)(content(Whitespace\" \"))))(Secondary((id \ - 1988)(content(Whitespace\" \"))))(Secondary((id \ - 1989)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 1995)(content(Whitespace\" \"))))(Tile((id 1997)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2002)(content(Whitespace\" \"))))(Secondary((id \ - 1998)(content(Whitespace\" \"))))(Secondary((id \ - 1999)(content(Whitespace\" \"))))(Secondary((id \ - 2000)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2004)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2916)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2925)(content(Comment\"# Tuples #\"))))(Secondary((id \ - 2006)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2010)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2011)(content(Whitespace\" \ - \"))))(Tile((id 2018)(label(tuples))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2019)(content(Whitespace\" \"))))(Tile((id 2020)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2022)(content(Whitespace\" \"))))(Tile((id \ - 2023)(label(\"(\"\")\"))(mold((out Typ)(in_(Typ))(nibs(((shape \ - Convex)(sort Typ))((shape Convex)(sort Typ))))))(shards(0 \ - 1))(children(((Tile((id 2026)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id 2027)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 14))(sort Typ))((shape(Concave \ - 14))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2029)(content(Whitespace\" \"))))(Tile((id \ - 2033)(label(Bool))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 2034)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave 14))(sort \ - Typ))((shape(Concave 14))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 2036)(content(Whitespace\" \"))))(Tile((id \ - 2037)(label(\"(\"\")\"))(mold((out Typ)(in_(Typ))(nibs(((shape \ - Convex)(sort Typ))((shape Convex)(sort Typ))))))(shards(0 \ - 1))(children(((Tile((id 2041)(label(Bool))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id 2042)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 14))(sort Typ))((shape(Concave \ - 14))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2044)(content(Whitespace\" \"))))(Tile((id \ - 2047)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))))))))))))(Secondary((id \ - 2048)(content(Whitespace\" \")))))((Secondary((id \ - 2051)(content(Whitespace\" \"))))(Tile((id \ - 2052)(label(\"(\"\")\"))(mold((out Exp)(in_(Exp))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Tile((id 2053)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 2054)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2056)(content(Whitespace\" \"))))(Tile((id \ - 2060)(label(true))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 2061)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave 14))(sort \ - Exp))((shape(Concave 14))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2063)(content(Whitespace\" \"))))(Tile((id \ - 2064)(label(\"(\"\")\"))(mold((out Exp)(in_(Exp))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Tile((id 2069)(label(false))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 2070)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2072)(content(Whitespace\" \"))))(Tile((id 2073)(label(3))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))))))))))))(Secondary((id \ - 2076)(content(Whitespace\" \")))))))))(Secondary((id \ - 2078)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2083)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2084)(content(Whitespace\" \ - \"))))(Tile((id 2086)(label(\"(\"\")\"))(mold((out \ - Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0 1))(children(((Tile((id 2087)(label(a))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id 2088)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 14))(sort Pat))((shape(Concave \ - 14))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 2090)(content(Whitespace\" \"))))(Tile((id 2091)(label(b))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id 2092)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 14))(sort Pat))((shape(Concave \ - 14))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 2094)(content(Whitespace\" \"))))(Tile((id \ - 2095)(label(\"(\"\")\"))(mold((out Pat)(in_(Pat))(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort Pat))))))(shards(0 \ - 1))(children(((Tile((id 2096)(label(c))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id 2097)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 14))(sort Pat))((shape(Concave \ - 14))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 2099)(content(Whitespace\" \"))))(Tile((id 2100)(label(d))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))))))))))))(Secondary((id \ - 2101)(content(Whitespace\" \")))))((Secondary((id \ - 2104)(content(Whitespace\" \"))))(Tile((id \ - 2110)(label(tuples))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2113)(content(Whitespace\" \")))))))))(Secondary((id \ - 2115)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2926)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2938)(content(Comment\"# Functions #\"))))(Secondary((id \ - 2117)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2121)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2122)(content(Whitespace\" \ - \"))))(Tile((id 2124)(label(y))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2125)(content(Whitespace\" \"))))(Tile((id 2126)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2128)(content(Whitespace\" \"))))(Tile((id \ - 2129)(label(\"(\"\")\"))(mold((out Typ)(in_(Typ))(nibs(((shape \ - Convex)(sort Typ))((shape Convex)(sort Typ))))))(shards(0 \ - 1))(children(((Tile((id 2132)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id 2133)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 14))(sort Typ))((shape(Concave \ - 14))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2135)(content(Whitespace\" \"))))(Tile((id \ - 2138)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 2139)(label(,))(mold((out Typ)(in_())(nibs(((shape(Concave 14))(sort \ - Typ))((shape(Concave 14))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 2141)(content(Whitespace\" \"))))(Tile((id \ - 2144)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 2145)(content(Whitespace\" \"))))(Tile((id 2148)(label(->))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 6))(sort Typ))((shape(Concave \ - 6))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2149)(content(Whitespace\" \"))))(Tile((id \ - 2152)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 2153)(content(Whitespace\" \")))))((Secondary((id \ - 2156)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2160)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2161)(content(Whitespace\" \ - \"))))(Tile((id 2163)(label(\"(\"\")\"))(mold((out \ - Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0 1))(children(((Tile((id 2164)(label(m))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id 2165)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 14))(sort Pat))((shape(Concave \ - 14))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 2167)(content(Whitespace\" \"))))(Tile((id 2168)(label(x))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id 2169)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 14))(sort Pat))((shape(Concave \ - 14))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 2171)(content(Whitespace\" \"))))(Tile((id 2172)(label(b))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children()))))))))(Secondary((id \ - 2173)(content(Whitespace\" \")))))))))(Secondary((id \ - 2177)(content(Whitespace\" \"))))(Tile((id 2178)(label(m))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2179)(content(Whitespace\" \"))))(Tile((id 2180)(label(*))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 4))(sort Exp))((shape(Concave \ - 4))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2182)(content(Whitespace\" \"))))(Tile((id 2183)(label(x))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2184)(content(Whitespace\" \"))))(Tile((id 2185)(label(+))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2187)(content(Whitespace\" \"))))(Tile((id 2188)(label(b))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2193)(content(Whitespace\" \"))))(Secondary((id \ - 2189)(content(Whitespace\" \"))))(Secondary((id \ - 2190)(content(Whitespace\" \"))))(Secondary((id \ - 2191)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2195)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2939)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2998)(content(Comment\"# Recursive Functions (arrow type annotation \ - required) #\"))))(Secondary((id \ - 2197)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2201)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2202)(content(Whitespace\" \ - \"))))(Tile((id 2221)(label(double_recursively))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2222)(content(Whitespace\" \"))))(Tile((id 2223)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2225)(content(Whitespace\" \"))))(Tile((id \ - 2228)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 2229)(content(Whitespace\" \"))))(Tile((id 2232)(label(->))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 6))(sort Typ))((shape(Concave \ - 6))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2233)(content(Whitespace\" \"))))(Tile((id \ - 2236)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 2237)(content(Whitespace\" \")))))((Secondary((id \ - 2240)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2244)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2245)(content(Whitespace\" \ - \"))))(Tile((id 2247)(label(n))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2248)(content(Whitespace\" \")))))))))(Secondary((id \ - 2252)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2255)(label(if then else))(mold((out Exp)(in_(Exp Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 12))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2256)(content(Whitespace\" \ - \"))))(Tile((id 2258)(label(n))(mold((out Exp)(in_())(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2259)(content(Whitespace\" \"))))(Tile((id 2262)(label(==))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 8))(sort Exp))((shape(Concave \ - 8))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2263)(content(Whitespace\" \"))))(Tile((id 2264)(label(0))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2267)(content(Whitespace\" \")))))((Secondary((id \ - 2271)(content(Whitespace\" \"))))(Tile((id 2273)(label(0))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2278)(content(Whitespace\" \"))))(Secondary((id \ - 2274)(content(Whitespace\" \"))))(Secondary((id \ - 2275)(content(Whitespace\" \"))))(Secondary((id \ - 2276)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2282)(content(Whitespace\" \"))))(Tile((id \ - 2301)(label(double_recursively))(mold((out Exp)(in_())(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 2302)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - 2304)(label(n))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2305)(content(Whitespace\" \"))))(Tile((id 2306)(label(-))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2308)(content(Whitespace\" \"))))(Tile((id 2309)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - 2310)(content(Whitespace\" \"))))(Tile((id 2311)(label(+))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2313)(content(Whitespace\" \"))))(Tile((id 2314)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2319)(content(Whitespace\" \"))))(Secondary((id \ - 2315)(content(Whitespace\" \"))))(Secondary((id \ - 2316)(content(Whitespace\" \"))))(Secondary((id \ - 2317)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2321)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 2999)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3007)(content(Comment\"# Lists #\"))))(Secondary((id \ - 2323)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2327)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2328)(content(Whitespace\" \ - \"))))(Tile((id 2339)(label(empty_list))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2340)(content(Whitespace\" \"))))(Tile((id 2341)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2343)(content(Whitespace\" \"))))(Tile((id 2344)(label([ \ - ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 2347)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 2348)(content(Whitespace\" \")))))((Secondary((id \ - 2351)(content(Whitespace\" \"))))(Tile((id 2354)(label([]))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2357)(content(Whitespace\" \")))))))))(Secondary((id \ - 2359)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2364)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2365)(content(Whitespace\" \ - \"))))(Tile((id 2380)(label(non_empty_list))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2381)(content(Whitespace\" \"))))(Tile((id 2382)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2384)(content(Whitespace\" \"))))(Tile((id 2385)(label([ \ - ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 2388)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 2389)(content(Whitespace\" \")))))((Secondary((id \ - 2392)(content(Whitespace\" \"))))(Tile((id 2393)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 2396)(label(::))(mold((out Exp)(in_())(nibs(((shape(Concave 6))(sort \ - Exp))((shape(Concave 6))(sort \ - Exp))))))(shards(0))(children())))(Tile((id 2397)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 2400)(label(::))(mold((out Exp)(in_())(nibs(((shape(Concave 6))(sort \ - Exp))((shape(Concave 6))(sort \ - Exp))))))(shards(0))(children())))(Tile((id 2401)(label(3))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 2404)(label(::))(mold((out Exp)(in_())(nibs(((shape(Concave 6))(sort \ - Exp))((shape(Concave 6))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 2407)(label([]))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2410)(content(Whitespace\" \")))))))))(Secondary((id \ - 2412)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2417)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2418)(content(Whitespace\" \ - \"))))(Tile((id 2432)(label(list_literals))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2433)(content(Whitespace\" \"))))(Tile((id 2434)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2436)(content(Whitespace\" \"))))(Tile((id 2437)(label([ \ - ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 2440)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 2441)(content(Whitespace\" \")))))((Secondary((id \ - 2444)(content(Whitespace\" \"))))(Tile((id 2445)(label([ \ - ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - 2446)(label(1))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 2447)(label(,))(mold((out Exp)(in_())(nibs(((shape(Concave 14))(sort \ - Exp))((shape(Concave 14))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2449)(content(Whitespace\" \"))))(Tile((id 2450)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id 2451)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 14))(sort Exp))((shape(Concave \ - 14))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2453)(content(Whitespace\" \"))))(Tile((id 2454)(label(3))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - 2457)(content(Whitespace\" \")))))))))(Secondary((id \ - 2459)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2464)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2465)(content(Whitespace\" \ - \"))))(Tile((id 2472)(label(length))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2473)(content(Whitespace\" \"))))(Tile((id 2474)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2476)(content(Whitespace\" \"))))(Tile((id 2477)(label([ \ - ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 2480)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 2481)(content(Whitespace\" \"))))(Tile((id 2484)(label(->))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 6))(sort Typ))((shape(Concave \ - 6))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2485)(content(Whitespace\" \"))))(Tile((id \ - 2488)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 2489)(content(Whitespace\" \")))))((Secondary((id \ - 2492)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2496)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2497)(content(Whitespace\" \ - \"))))(Tile((id 2500)(label(xs))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2501)(content(Whitespace\" \")))))))))(Secondary((id \ - 2505)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2510)(label(case end))(mold((out Exp)(in_(Rul))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2511)(content(Whitespace\" \ - \"))))(Tile((id 2514)(label(xs))(mold((out Exp)(in_())(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2515)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2516)(label(| =>))(mold((out Rul)(in_(Pat))(nibs(((shape(Concave \ - 19))(sort Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2518)(content(Whitespace\" \ - \"))))(Tile((id 2521)(label([]))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2522)(content(Whitespace\" \")))))))))(Secondary((id \ - 2525)(content(Whitespace\" \"))))(Tile((id 2526)(label(0))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2527)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2528)(label(| =>))(mold((out Rul)(in_(Pat))(nibs(((shape(Concave \ - 19))(sort Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2530)(content(Whitespace\" \ - \"))))(Tile((id 2532)(label(hd))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 2535)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave 6))(sort \ - Pat))((shape(Concave 6))(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 2537)(label(tl))(mold((out Pat)(in_())(nibs(((shape Convex)(sort \ - Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2538)(content(Whitespace\" \")))))))))(Secondary((id \ - 2541)(content(Whitespace\" \"))))(Tile((id 2542)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2543)(content(Whitespace\" \"))))(Tile((id 2544)(label(+))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 2546)(content(Whitespace\" \"))))(Tile((id \ - 2552)(label(length))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 2553)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape(Concave 1))(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - 2556)(label(tl))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - 2561)(content(Whitespace\" \"))))(Secondary((id \ - 2557)(content(Whitespace\" \"))))(Secondary((id \ - 2558)(content(Whitespace\" \"))))(Secondary((id \ - 2559)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2568)(content(Whitespace\" \"))))(Secondary((id \ - 2564)(content(Whitespace\" \"))))(Secondary((id \ - 2565)(content(Whitespace\" \"))))(Secondary((id \ - 2566)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2570)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2575)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2576)(content(Whitespace\" \ - \"))))(Tile((id 2602)(label(has_at_least_two_elements))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2603)(content(Whitespace\" \"))))(Tile((id 2604)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2606)(content(Whitespace\" \"))))(Tile((id 2607)(label([ \ - ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 2610)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 2611)(content(Whitespace\" \"))))(Tile((id 2614)(label(->))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 6))(sort Typ))((shape(Concave \ - 6))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 2615)(content(Whitespace\" \"))))(Tile((id \ - 2619)(label(Bool))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 2620)(content(Whitespace\" \")))))((Secondary((id \ - 2623)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2627)(label(fun ->))(mold((out Exp)(in_(Pat))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 13))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2628)(content(Whitespace\" \ - \"))))(Tile((id 2631)(label(xs))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2632)(content(Whitespace\" \")))))))))(Secondary((id \ - 2636)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2641)(label(case end))(mold((out Exp)(in_(Rul))(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2642)(content(Whitespace\" \ - \"))))(Tile((id 2645)(label(xs))(mold((out Exp)(in_())(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2646)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2647)(label(| =>))(mold((out Rul)(in_(Pat))(nibs(((shape(Concave \ - 19))(sort Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2649)(content(Whitespace\" \ - \"))))(Tile((id 2652)(label([]))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2653)(content(Whitespace\" \")))))))))(Secondary((id \ - 2656)(content(Whitespace\" \"))))(Tile((id \ - 2661)(label(false))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2662)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2663)(label(| =>))(mold((out Rul)(in_(Pat))(nibs(((shape(Concave \ - 19))(sort Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2665)(content(Whitespace\" \ - \"))))(Tile((id 2667)(label(hd))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 2670)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave 6))(sort \ - Pat))((shape(Concave 6))(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 2673)(label([]))(mold((out Pat)(in_())(nibs(((shape Convex)(sort \ - Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2674)(content(Whitespace\" \")))))))))(Secondary((id \ - 2677)(content(Whitespace\" \"))))(Tile((id \ - 2682)(label(false))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2683)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2684)(label(| =>))(mold((out Rul)(in_(Pat))(nibs(((shape(Concave \ - 19))(sort Exp))((shape(Concave 19))(sort Exp))))))(shards(0 \ - 1))(children(((Secondary((id 2686)(content(Whitespace\" \ - \"))))(Tile((id 2687)(label(a))(mold((out Pat)(in_())(nibs(((shape \ - Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 2690)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave 6))(sort \ - Pat))((shape(Concave 6))(sort \ - Pat))))))(shards(0))(children())))(Tile((id 2691)(label(b))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 2694)(label(::))(mold((out Pat)(in_())(nibs(((shape(Concave 6))(sort \ - Pat))((shape(Concave 6))(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 2697)(label([]))(mold((out Pat)(in_())(nibs(((shape Convex)(sort \ - Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2698)(content(Whitespace\" \")))))))))(Secondary((id \ - 2701)(content(Whitespace\" \"))))(Tile((id \ - 2705)(label(true))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2710)(content(Whitespace\" \"))))(Secondary((id \ - 2706)(content(Whitespace\" \"))))(Secondary((id \ - 2707)(content(Whitespace\" \"))))(Secondary((id \ - 2708)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2717)(content(Whitespace\" \"))))(Secondary((id \ - 2713)(content(Whitespace\" \"))))(Secondary((id \ - 2714)(content(Whitespace\" \"))))(Secondary((id \ - 2715)(content(Whitespace\"\\226\\143\\142\")))))))))(Secondary((id \ - 2719)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3008)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3018)(content(Comment\"# Strings #\"))))(Secondary((id \ - 2722)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2726)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2727)(content(Whitespace\" \ - \"))))(Tile((id 2739)(label(string_lits))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2740)(content(Whitespace\" \")))))((Secondary((id \ - 2743)(content(Whitespace\" \"))))(Tile((id 2757)(label(\"\\\"Hello, \ - world!\\\"\"))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2760)(content(Whitespace\" \")))))))))(Secondary((id \ - 2762)(content(Whitespace\" \"))))(Secondary((id \ - 2764)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 2768)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 2769)(content(Whitespace\" \ - \"))))(Tile((id 2785)(label(string_equality))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 2786)(content(Whitespace\" \")))))((Secondary((id \ - 2789)(content(Whitespace\" \"))))(Tile((id \ - 2800)(label(string_lits))(mold((out Exp)(in_())(nibs(((shape \ - Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2801)(content(Whitespace\" \"))))(Tile((id \ - 2805)(label($==))(mold((out Exp)(in_())(nibs(((shape(Concave 8))(sort \ - Exp))((shape(Concave 8))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2806)(content(Whitespace\" \"))))(Tile((id 2820)(label(\"\\\"Hello, \ - world!\\\"\"))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2823)(content(Whitespace\" \")))))))))(Secondary((id \ - 2825)(content(Whitespace\" \"))))(Secondary((id \ - 3019)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3409)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3466)(content(Comment\"# Non-empty holes are the red dotted boxes \ - around errors #\"))))(Secondary((id \ - 3467)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3519)(content(Comment\"# (you can still run programs with non-empty \ - holes) #\"))))(Secondary((id \ - 3520)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 3524)(label(let = in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape \ - Convex)(sort Exp))((shape(Concave 16))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id 3525)(content(Whitespace\" \ - \"))))(Tile((id 3540)(label(non_empty_hole))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 3541)(content(Whitespace\" \"))))(Tile((id 3542)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 11))(sort Pat))((shape(Concave \ - 11))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 3544)(content(Whitespace\" \"))))(Tile((id \ - 3547)(label(Int))(mold((out Typ)(in_())(nibs(((shape Convex)(sort \ - Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 3548)(content(Whitespace\" \")))))((Secondary((id \ - 3551)(content(Whitespace\" \"))))(Tile((id \ - 3555)(label(true))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 3558)(content(Whitespace\" \")))))))))(Secondary((id \ - 3560)(content(Whitespace\" \"))))(Secondary((id \ - 3562)(content(Whitespace\"\\226\\143\\142\"))))(Secondary((id \ - 3563)(content(Whitespace\"\\226\\143\\142\"))))(Tile((id \ - 3564)(label(2))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 3565)(content(Whitespace\" \"))))(Tile((id 3566)(label(+))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 5))(sort Exp))((shape(Concave \ - 5))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 3568)(content(Whitespace\" \"))))(Tile((id 3569)(label(2))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 2827)(content(Whitespace\"\\226\\143\\142\")))))))(ancestors())))(caret \ - Outer))"; - backup_text = - "# Hazel Language Quick Reference #\n\n\ - # Empty holes stand for missing expressions, patterns, or types #\n\ - let empty_hole = in\n\n\ - # Integers #\n\ - let int_lits : Int = 1 in\n\ - let negation = -1 in\n\ - let arithmetic = 1*2 + 8/4 in\n\ - let int_comparison = (10 == 10, 1 < 2, 2 <= 3, 3 > 2, 2 >= 1) in\n\n\ - # Floating Point Numbers #\n\ - let float_lits : Float = 1.5 in\n\ - let float_artih = 1. *. 2. +. 8. /. 4. in\n\ - let float_comparison = (10. ==. 10., 1. <. 2., 2. <=. 3., 3. >. 2., \ - 2. >=. 1.) in\n\n\ - # Booleans #\n\ - let booleans : (Bool, Bool) = (true, false) in\n\ - let conditionals =\n\ - let (x, y) = (2 + 2, 3 + 3) in\n\ - if y > x then 1 \n\ - else 2 \n\ - in\n\n\ - # Tuples #\n\ - let tuples : (Int, Bool, (Bool, Int)) = (1, true, (false, 3)) in\n\ - let (a, b, (c, d)) = tuples in\n\n\ - # Functions #\n\ - let y : (Int, Int, Int) -> Int =\n\ - fun (m, x, b) -> m * x + b \n\ - in\n\n\ - # Recursive Functions (arrow type annotation required) #\n\ - let double_recursively : Int -> Int =\n\ - fun n ->\n\ - if n == 0 then 0 \n\ - else double_recursively(n - 1) + 2 \n\ - in\n\n\ - # Lists #\n\ - let empty_list : [Int] = [] in\n\ - let non_empty_list : [Int] = 1::2::3::[] in\n\ - let list_literals : [Int] = [1, 2, 3] in\n\ - let length : [Int] -> Int =\n\ - fun xs ->\n\ - case xs\n\ - | [] => 0\n\ - | hd::tl => 1 + length(tl) \n\ - end \n\ - in\n\ - let has_at_least_two_elements : [Int] -> Bool =\n\ - fun xs ->\n\ - case xs\n\ - | [] => false\n\ - | hd::[] => false\n\ - | a::b::[] => true \n\ - end \n\ - in\n\n\ - # Strings #\n\ - let string_lits = \"Hello, world!\" in \n\ - let string_equality = string_lits $== \"Hello, world!\" in \n\n\ - # Non-empty holes are the red dotted boxes around errors #\n\ - # (you can still run programs with non-empty holes) #\n\ - let non_empty_hole : Int = true in \n\n\ - 2 + 2\n"; - } ) diff --git a/src/haz3lweb/Log.re b/src/haz3lweb/Log.re index 1fb6aee273..8663b4dc8f 100644 --- a/src/haz3lweb/Log.re +++ b/src/haz3lweb/Log.re @@ -20,14 +20,16 @@ let is_action_logged: UpdateAction.t => bool = | InitImportAll(_) | InitImportScratchpad(_) | UpdateResult(_) - | DebugAction(_) => false + | DebugAction(_) + | ExportPersistentData => false | ResetCurrentEditor | Set(_) | FinishImportAll(_) | FinishImportScratchpad(_) | ResetSlide - | ToggleMode - | SwitchSlide(_) + | SetMode(_) + | SwitchScratchSlide(_) + | SwitchExampleSlide(_) | SwitchEditor(_) | PerformAction(_) | FailedInput(_) @@ -39,7 +41,7 @@ let is_action_logged: UpdateAction.t => bool = | MoveToNextHole(_) | UpdateLangDocMessages(_) => true; -let storage_key = "LOG_" ++ SchoolSettings.log_key; +let storage_key = "LOG_" ++ ExerciseSettings.log_key; let max_log_string_length = 4_750_000; // based on 5MB limit on localstore in browser module Entry = { diff --git a/src/haz3lweb/Main.re b/src/haz3lweb/Main.re index 6f0106220b..6816daad60 100644 --- a/src/haz3lweb/Main.re +++ b/src/haz3lweb/Main.re @@ -160,9 +160,7 @@ let fragment = let initial_model = { switch (fragment) { | "debug" => Model.debug - | _ => - let model = Update.load_model(Model.blank); - model; + | _ => Model.load(Model.blank) }; }; diff --git a/src/haz3lweb/Model.re b/src/haz3lweb/Model.re index e291cc9b0a..598875313a 100644 --- a/src/haz3lweb/Model.re +++ b/src/haz3lweb/Model.re @@ -21,7 +21,7 @@ let cutoff = (===); let mk = editors => { editors, results: ModelResults.empty, - settings: ModelSettings.init, + settings: Init.startup.settings, // TODO: move below to 'io_state'? font_metrics: FontMetrics.init, logo_font_metrics: FontMetrics.init, @@ -33,3 +33,60 @@ let mk = editors => { let blank = mk(Editors.Scratch(0, [])); let debug = mk(Editors.DebugLoad); + +let load_editors = + (~mode: ModelSettings.mode, ~instructor_mode: bool): Editors.t => + switch (mode) { + | DebugLoad => DebugLoad + | Scratch => + let (idx, slides) = Store.Scratch.load(); + Scratch(idx, slides); + | Examples => + let (name, slides) = Store.Examples.load(); + Examples(name, slides); + | Exercise => + let (n, specs, exercise) = + Store.Exercise.load( + ~specs=ExerciseSettings.exercises, + ~instructor_mode, + ); + Exercise(n, specs, exercise); + }; + +let save_editors = (editors: Editors.t, ~instructor_mode: bool): unit => + switch (editors) { + | DebugLoad => failwith("no editors in debug load mode") + | Scratch(n, slides) => Store.Scratch.save((n, slides)) + | Examples(name, slides) => Store.Examples.save((name, slides)) + | Exercise(n, specs, exercise) => + Store.Exercise.save((n, specs, exercise), ~instructor_mode) + }; + +let load = (init_model: t): t => { + let settings = Store.Settings.load(); + let langDocMessages = Store.LangDocMessages.load(); + let editors = + load_editors( + ~mode=settings.mode, + ~instructor_mode=settings.instructor_mode, + ); + let results = + ModelResults.init( + settings.dynamics ? Editors.get_spliced_elabs(editors) : [], + ); + {...init_model, editors, settings, langDocMessages, results}; +}; + +let save = (model: t) => { + save_editors( + model.editors, + ~instructor_mode=model.settings.instructor_mode, + ); + Store.LangDocMessages.save(model.langDocMessages); + Store.Settings.save(model.settings); +}; + +let save_and_return = (model: t) => { + save(model); + Ok(model); +}; diff --git a/src/haz3lweb/ModelSettings.re b/src/haz3lweb/ModelSettings.re index 0e8841f885..d2ef576db9 100644 --- a/src/haz3lweb/ModelSettings.re +++ b/src/haz3lweb/ModelSettings.re @@ -1,5 +1,20 @@ open Sexplib.Std; +[@deriving (show({with_path: false}), sexp, yojson)] +type mode = + | DebugLoad + | Scratch + | Examples + | Exercise; + +let mode_of_string = (s: string): mode => + switch (s) { + | "Scratch" => Scratch + | "Examples" => Examples + | "Exercise" => Exercise + | _ => failwith("mode_of_string: unknown mode:" ++ s) + }; + [@deriving (show({with_path: false}), sexp, yojson)] type t = { captions: bool, @@ -10,25 +25,11 @@ type t = { context_inspector: bool, instructor_mode: bool, benchmark: bool, - mode: Editors.mode, + mode, }; -let init = { - captions: true, - secondary_icons: false, - statics: true, - dynamics: true, - async_evaluation: false, - context_inspector: false, - instructor_mode: SchoolSettings.show_instructor, - benchmark: false, - mode: Editors.Scratch, -}; - -let init_debug = {...init, mode: Editors.DebugLoad}; - let fix_instructor_mode = settings => - if (settings.instructor_mode && !SchoolSettings.show_instructor) { + if (settings.instructor_mode && !ExerciseSettings.show_instructor) { {...settings, instructor_mode: false}; } else { settings; diff --git a/src/haz3lweb/PersistentData.re b/src/haz3lweb/PersistentData.re new file mode 100644 index 0000000000..87bb55f155 --- /dev/null +++ b/src/haz3lweb/PersistentData.re @@ -0,0 +1,14 @@ +open Sexplib.Std; + +[@deriving (show({with_path: false}), sexp, yojson)] +type scratch = (int, list(ScratchSlide.persistent_state)); + +[@deriving (show({with_path: false}), sexp, yojson)] +type examples = (string, list((string, ScratchSlide.persistent_state))); + +[@deriving (show({with_path: false}), sexp, yojson)] +type t = { + settings: ModelSettings.t, + scratch, + examples, +}; diff --git a/src/haz3lweb/School.re b/src/haz3lweb/School.re deleted file mode 100644 index 30b0fc1b16..0000000000 --- a/src/haz3lweb/School.re +++ /dev/null @@ -1,11 +0,0 @@ -let exercises: list(SchoolExercise.spec) = SchoolSettings.exercises; -assert(List.length(exercises) > 0); - -let init = (~instructor_mode: bool): Editors.school => { - ( - 0, - exercises, - List.nth(exercises, 0) |> SchoolExercise.state_of_spec(~instructor_mode), - ); -}; -//TODO: make sure in the final version hidden editors are NOT PLAINTEXT STRINGS diff --git a/src/haz3lweb/SchoolSettings.re b/src/haz3lweb/SchoolSettings.re deleted file mode 100644 index d669d5887f..0000000000 --- a/src/haz3lweb/SchoolSettings.re +++ /dev/null @@ -1,2 +0,0 @@ -include SchoolSettings_base; -let show_instructor = true; diff --git a/src/haz3lweb/SchoolSettings_instructor.re b/src/haz3lweb/SchoolSettings_instructor.re deleted file mode 100644 index d669d5887f..0000000000 --- a/src/haz3lweb/SchoolSettings_instructor.re +++ /dev/null @@ -1,2 +0,0 @@ -include SchoolSettings_base; -let show_instructor = true; diff --git a/src/haz3lweb/SchoolSettings_student.re b/src/haz3lweb/SchoolSettings_student.re deleted file mode 100644 index f199a8cdc1..0000000000 --- a/src/haz3lweb/SchoolSettings_student.re +++ /dev/null @@ -1,2 +0,0 @@ -include SchoolSettings_base; -let show_instructor = false; diff --git a/src/haz3lweb/ScratchSlidesInit.re b/src/haz3lweb/ScratchSlidesInit.re deleted file mode 100644 index 16bd634cd8..0000000000 --- a/src/haz3lweb/ScratchSlidesInit.re +++ /dev/null @@ -1,25 +0,0 @@ -let slide0: ScratchSlide.persistent_state = LanguageRefSlide.slide; - -let empty: ScratchSlide.persistent_state = ( - 1, - { - zipper: "((selection((focus Left)(content())))(backpack())(relatives((siblings(()((Grout((id 0)(shape Convex))))))(ancestors())))(caret Outer))", - backup_text: "", - }, -); - -let num_empty = 7; - -let init_data = [slide0, ...List.init(num_empty, _ => empty)]; - -assert(List.length(init_data) > 0); - -let init = (): Editors.scratch => ( - 0, - init_data |> List.map(ScratchSlide.unpersist), -); - -let init_nth = n => { - let data = List.nth(init_data, n); - ScratchSlide.unpersist(data); -}; diff --git a/src/haz3lweb/LocalStorage.re b/src/haz3lweb/Store.re similarity index 65% rename from src/haz3lweb/LocalStorage.re rename to src/haz3lweb/Store.re index 549692055f..84913c9b0e 100644 --- a/src/haz3lweb/LocalStorage.re +++ b/src/haz3lweb/Store.re @@ -1,9 +1,11 @@ -open Sexplib.Std; +open Haz3lcore; // Settings serialization module Settings = { let save_settings_key: string = "SETTINGS"; + let default = Init.startup.settings; + let serialize = settings => settings |> ModelSettings.sexp_of_t |> Sexplib.Sexp.to_string; @@ -16,15 +18,15 @@ module Settings = { ) { | _ => print_endline("Could not deserialize settings."); - ModelSettings.init; + default; }; let save = (settings: ModelSettings.t): unit => JsUtil.set_localstore(save_settings_key, serialize(settings)); let init = () => { - JsUtil.set_localstore(save_settings_key, serialize(ModelSettings.init)); - ModelSettings.init; + JsUtil.set_localstore(save_settings_key, serialize(default)); + default; }; let load = (): ModelSettings.t => @@ -94,14 +96,14 @@ module Scratch = { let save_scratch_key: string = "SAVE_SCRATCH"; [@deriving (show({with_path: false}), sexp, yojson)] - type persistent = (int, list(ScratchSlide.persistent_state)); + type persistent = PersistentData.scratch; - let to_persistent = ((idx, slides): Editors.scratch): persistent => ( + let to_persistent = ((idx, slides)): persistent => ( idx, List.map(ScratchSlide.persist, slides), ); - let of_persistent = ((idx, slides): persistent): Editors.scratch => { + let of_persistent = ((idx, slides): persistent) => { (idx, List.map(ScratchSlide.unpersist, slides)); }; @@ -113,12 +115,12 @@ module Scratch = { data |> Sexplib.Sexp.of_string |> persistent_of_sexp |> of_persistent; }; - let save = (scratch: Editors.scratch): unit => { + let save = (scratch): unit => { JsUtil.set_localstore(save_scratch_key, serialize(scratch)); }; let init = () => { - let scratch = ScratchSlidesInit.init(); + let scratch = of_persistent(Init.startup.scratch); save(scratch); scratch; }; @@ -136,8 +138,63 @@ module Scratch = { let import = data => save(deserialize(data)); }; -module School = { - open SchoolExercise; +module Examples = { + let save_examples_key: string = "SAVE_EXAMPLES"; + + [@deriving (show({with_path: false}), sexp, yojson)] + type persistent = PersistentData.examples; + + let persist = ((name, (id, editor: Editor.t))) => { + (name, (id, PersistentZipper.persist(editor.state.zipper))); + }; + + let unpersist = ((name, (id, zipper))) => { + let (id, zipper) = PersistentZipper.unpersist(zipper, id); + (name, (id, Editor.init(zipper, ~read_only=false))); + }; + + let to_persistent = ((string, slides)): persistent => ( + string, + List.map(persist, slides), + ); + + let of_persistent = ((string, slides): persistent) => { + (string, List.map(unpersist, slides)); + }; + + let serialize = examples => { + examples |> to_persistent |> sexp_of_persistent |> Sexplib.Sexp.to_string; + }; + + let deserialize = data => { + data |> Sexplib.Sexp.of_string |> persistent_of_sexp |> of_persistent; + }; + + let save = (examples): unit => { + JsUtil.set_localstore(save_examples_key, serialize(examples)); + }; + + let init = () => { + let examples = of_persistent(Init.startup.examples); + save(examples); + examples; + }; + + let load = () => + switch (JsUtil.get_localstore(save_examples_key)) { + | None => init() + | Some(data) => + try(deserialize(data)) { + | _ => init() + } + }; + + let export = () => serialize(load()); + let import = data => save(deserialize(data)); +}; + +module Exercise = { + open Exercise; let cur_exercise_key = "CUR_EXERCISE"; @@ -158,29 +215,27 @@ module School = { }; let save_exercise = (exercise, ~instructor_mode) => { - let key = SchoolExercise.key_of_state(exercise); + let key = Exercise.key_of_state(exercise); let keystring = keystring_of_key(key); - let value = SchoolExercise.serialize_exercise(exercise, ~instructor_mode); + let value = Exercise.serialize_exercise(exercise, ~instructor_mode); JsUtil.set_localstore(keystring, value); }; let init_exercise = (spec, ~instructor_mode) => { - let key = SchoolExercise.key_of(spec); + let key = Exercise.key_of(spec); let keystring = keystring_of_key(key); - let exercise = SchoolExercise.state_of_spec(spec, ~instructor_mode); + let exercise = Exercise.state_of_spec(spec, ~instructor_mode); save_exercise(exercise, ~instructor_mode); JsUtil.set_localstore(cur_exercise_key, keystring); exercise; }; - let load_exercise = (key, spec, ~instructor_mode): SchoolExercise.state => { + let load_exercise = (key, spec, ~instructor_mode): Exercise.state => { let keystring = keystring_of_key(key); switch (JsUtil.get_localstore(keystring)) { | Some(data) => let exercise = - try( - SchoolExercise.deserialize_exercise(data, ~spec, ~instructor_mode) - ) { + try(Exercise.deserialize_exercise(data, ~spec, ~instructor_mode)) { | _ => init_exercise(spec, ~instructor_mode) }; JsUtil.set_localstore(cur_exercise_key, keystring); @@ -197,16 +252,23 @@ module School = { }; let init = (~instructor_mode) => { - let school = School.init(~instructor_mode); - save(school, ~instructor_mode); - school; + let exercises = { + ( + 0, + ExerciseSettings.exercises, + List.nth(ExerciseSettings.exercises, 0) + |> Exercise.state_of_spec(~instructor_mode), + ); + }; + save(exercises, ~instructor_mode); + exercises; }; - let load = (~specs, ~instructor_mode): Editors.school => { + let load = (~specs, ~instructor_mode) => { switch (JsUtil.get_localstore(cur_exercise_key)) { | Some(keystring) => let key = key_of_keystring(keystring); - switch (SchoolExercise.find_key_opt(key, specs)) { + switch (Exercise.find_key_opt(key, specs)) { | Some((n, spec)) => switch (JsUtil.get_localstore(keystring)) { | Some(data) => @@ -217,23 +279,21 @@ module School = { (n, specs, exercise); | None => // initialize exercise from spec - let exercise = SchoolExercise.state_of_spec(spec, ~instructor_mode); + let exercise = Exercise.state_of_spec(spec, ~instructor_mode); save_exercise(exercise, ~instructor_mode); (n, specs, exercise); } | None => // invalid current exercise key saved, load the first exercise let first_spec = List.nth(specs, 0); - let first_key = SchoolExercise.key_of(first_spec); + let first_key = Exercise.key_of(first_spec); (0, specs, load_exercise(first_key, first_spec, ~instructor_mode)); }; | None => init(~instructor_mode) }; }; - type school_export = SchoolExercise.school_export; - - let prep_school_export = (~specs, ~instructor_mode) => { + let prep_exercise_export = (~specs, ~instructor_mode) => { { cur_exercise: key_of_keystring( @@ -242,37 +302,37 @@ module School = { exercise_data: specs |> List.map(spec => { - let key = SchoolExercise.key_of(spec); + let key = Exercise.key_of(spec); let exercise = load_exercise(key, spec, ~instructor_mode) - |> SchoolExercise.persistent_state_of_state(~instructor_mode); + |> Exercise.persistent_state_of_state(~instructor_mode); (key, exercise); }), }; }; - let serialize_school_export = (~specs, ~instructor_mode) => { - prep_school_export(~specs, ~instructor_mode) - |> sexp_of_school_export + let serialize_exercise_export = (~specs, ~instructor_mode) => { + prep_exercise_export(~specs, ~instructor_mode) + |> sexp_of_exercise_export |> Sexplib.Sexp.to_string; }; let export = (~specs, ~instructor_mode) => { - serialize_school_export(~specs, ~instructor_mode); + serialize_exercise_export(~specs, ~instructor_mode); }; let import = (data, ~specs, ~instructor_mode) => { - let school_export = data |> deserialize_school_export; - save_exercise_key(school_export.cur_exercise); - school_export.exercise_data + let exercise_export = data |> deserialize_exercise_export; + save_exercise_key(exercise_export.cur_exercise); + exercise_export.exercise_data |> List.iter(((key, persistent_state)) => { - let spec = SchoolExercise.find_key_opt(key, specs); + let spec = Exercise.find_key_opt(key, specs); switch (spec) { | None => print_endline("Warning: saved key does not correspond to exercise") | Some((_, spec)) => save_exercise( - SchoolExercise.unpersist_state( + Exercise.unpersist_state( persistent_state, ~spec, ~instructor_mode, diff --git a/src/haz3lweb/Update.re b/src/haz3lweb/Update.re index ce12036075..9dad74a51b 100644 --- a/src/haz3lweb/Update.re +++ b/src/haz3lweb/Update.re @@ -2,127 +2,72 @@ open Haz3lcore; include UpdateAction; // to prevent circularity -let save_editors = (model: Model.t): unit => - switch (model.editors) { - | DebugLoad => failwith("no editors in debug load mode") - | Scratch(n, slides) => LocalStorage.Scratch.save((n, slides)) - | School(n, specs, exercise) => - LocalStorage.School.save( - (n, specs, exercise), - ~instructor_mode=model.settings.instructor_mode, - ) - }; - -let update_settings = (a: settings_action, model: Model.t): Model.t => { - let settings = model.settings; - let model = - switch (a) { - | Statics => - /* NOTE: dynamics depends on statics, so if dynamics is on and - we're turning statics off, turn dynamics off as well */ - { - ...model, - settings: { - ...settings, - statics: !settings.statics, - dynamics: !settings.statics && settings.dynamics, - }, - } - | Dynamics => { - ...model, - settings: { - ...settings, - dynamics: !settings.dynamics, - }, - } - | Benchmark => { - ...model, - settings: { - ...settings, - benchmark: !settings.benchmark, - }, - } - | Captions => { - ...model, - settings: { - ...settings, - captions: !settings.captions, - }, - } - | SecondaryIcons => { - ...model, - settings: { - ...settings, - secondary_icons: !settings.secondary_icons, - }, - } - | ContextInspector => { - ...model, - settings: { - ...settings, - context_inspector: !settings.context_inspector, - }, - } - | InstructorMode => - let new_mode = !settings.instructor_mode; - { - ...model, - editors: Editors.set_instructor_mode(model.editors, new_mode), - settings: { - ...settings, - instructor_mode: !settings.instructor_mode, - }, - }; - | Mode(mode) => { - ...model, - settings: { - ...settings, - mode, - }, - } - }; - LocalStorage.Settings.save(model.settings); - save_editors(model); - model; -}; - -let load_model = (model: Model.t): Model.t => { - let settings = LocalStorage.Settings.load(); - let langDocMessages = LocalStorage.LangDocMessages.load(); - let model = {...model, settings, langDocMessages}; - let model = - switch (model.settings.mode) { - | DebugLoad => model - | Scratch => - let (idx, slides) = LocalStorage.Scratch.load(); - {...model, editors: Scratch(idx, slides)}; - | School => - let instructor_mode = model.settings.instructor_mode; - let specs = School.exercises; - let (n, specs, exercise) = - LocalStorage.School.load(~specs, ~instructor_mode); - {...model, editors: School(n, specs, exercise)}; +let update_settings = + (a: settings_action, {settings, _} as model: Model.t): Model.t => + switch (a) { + | Statics => + /* NOTE: dynamics depends on statics, so if dynamics is on and + we're turning statics off, turn dynamics off as well */ + { + ...model, + settings: { + ...settings, + statics: !settings.statics, + dynamics: !settings.statics && settings.dynamics, + }, + } + | Dynamics => { + ...model, + settings: { + ...settings, + dynamics: !settings.dynamics, + }, + } + | Benchmark => { + ...model, + settings: { + ...settings, + benchmark: !settings.benchmark, + }, + } + | Captions => { + ...model, + settings: { + ...settings, + captions: !settings.captions, + }, + } + | SecondaryIcons => { + ...model, + settings: { + ...settings, + secondary_icons: !settings.secondary_icons, + }, + } + | ContextInspector => { + ...model, + settings: { + ...settings, + context_inspector: !settings.context_inspector, + }, + } + | InstructorMode => + let new_mode = !settings.instructor_mode; + { + ...model, + editors: Editors.set_instructor_mode(model.editors, new_mode), + settings: { + ...settings, + instructor_mode: !settings.instructor_mode, + }, }; - { - ...model, - results: - ModelResults.init( - model.settings.dynamics - ? Editors.get_spliced_elabs(model.editors) : [], - ), - }; -}; - -let load_default_editor = (model: Model.t): Model.t => - switch (model.editors) { - | DebugLoad => model - | Scratch(_) => - let (idx, editors) = LocalStorage.Scratch.init(); - {...model, editors: Scratch(idx, editors)}; - | School(_) => - let instructor_mode = model.settings.instructor_mode; - let (n, specs, exercise) = LocalStorage.School.init(~instructor_mode); - {...model, editors: School(n, specs, exercise)}; + | Mode(mode) => { + ...model, + settings: { + ...settings, + mode, + }, + } }; let reevaluate_post_update = @@ -156,7 +101,8 @@ let reevaluate_post_update = | InitImportScratchpad(_) | FailedInput(_) | UpdateLangDocMessages(_) - | DebugAction(_) => false + | DebugAction(_) + | ExportPersistentData => false // may not be necessary on all of these // TODO review and prune | ResetCurrentEditor @@ -165,8 +111,9 @@ let reevaluate_post_update = | FinishImportScratchpad(_) | ResetSlide | SwitchEditor(_) - | SwitchSlide(_) - | ToggleMode + | SwitchScratchSlide(_) + | SwitchExampleSlide(_) + | SetMode(_) | Cut | Paste(_) | Undo @@ -218,18 +165,70 @@ let perform_action = }; }; +let switch_scratch_slide = + (editors: Editors.t, ~instructor_mode, idx: int): option(Editors.t) => + switch (editors) { + | DebugLoad + | Examples(_) => None + | Scratch(n, _) when n == idx => None + | Scratch(_, slides) when idx >= List.length(slides) => None + | Scratch(_, slides) => Some(Scratch(idx, slides)) + | Exercise(_, specs, _) when idx >= List.length(specs) => None + | Exercise(_, specs, _) => + let spec = List.nth(specs, idx); + let key = Exercise.key_of(spec); + let exercise = Store.Exercise.load_exercise(key, spec, ~instructor_mode); + Some(Exercise(idx, specs, exercise)); + }; + +let switch_exercise_editor = + (editors: Editors.t, ~pos, ~instructor_mode): option(Editors.t) => + switch (editors) { + | DebugLoad + | Examples(_) + | Scratch(_) => None + | Exercise(m, specs, exercise) => + let exercise = Exercise.switch_editor(~pos, instructor_mode, ~exercise); + Store.Exercise.save_exercise(exercise, ~instructor_mode); + Some(Exercise(m, specs, exercise)); + }; + +/* This action saves a file which serializes all current editor + settings, including the states of all Scratch and Example slides. + This saved file can directly replace Haz3lweb/Init.ml, allowing + you to make your current state the default startup state. + + This does NOT save any Exercises mode state or any langdocs + state. The latter is intentional as we don't want to persist + this between users. The former is a TODO, currently difficult + due to the more complex architecture of Exercises. */ +let export_persistent_data = () => { + let data: PersistentData.t = { + examples: Store.Examples.load() |> Store.Examples.to_persistent, + scratch: Store.Scratch.load() |> Store.Scratch.to_persistent, + settings: Store.Settings.load(), + }; + let contents = + "let startup : PersistentData.t = " ++ PersistentData.show(data); + JsUtil.download_string_file( + ~filename="Init.ml", + ~content_type="text/plain", + ~contents, + ); + print_endline("INFO: Persistent data exported to Init.ml"); +}; + let apply = (model: Model.t, update: t, state: State.t, ~schedule_action) : Result.t(Model.t) => { let m: Result.t(Model.t) = switch (update) { - | Set(s_action) => Ok(update_settings(s_action, model)) + | Set(s_action) => + Model.save_and_return(update_settings(s_action, model)) | UpdateDoubleTap(double_tap) => Ok({...model, double_tap}) | Mousedown => Ok({...model, mousedown: true}) | Mouseup => Ok({...model, mousedown: false}) - | Save => - save_editors(model); - Ok(model); + | Save => Model.save_and_return(model) | InitImportAll(file) => JsUtil.read_file(file, data => schedule_action(FinishImportAll(data))); Ok(model); @@ -237,9 +236,8 @@ let apply = switch (data) { | None => Ok(model) | Some(data) => - let specs = School.exercises; - Export.import_all(data, ~specs); - Ok(load_model(model)); + Export.import_all(data, ~specs=ExerciseSettings.exercises); + Ok(Model.load(model)); } | InitImportScratchpad(file) => JsUtil.read_file(file, data => @@ -247,87 +245,37 @@ let apply = ); Ok(model); | FinishImportScratchpad(data) => - switch (model.editors) { - | DebugLoad => failwith("impossible") - | School(_) => failwith("impossible") - | Scratch(idx, slides) => - switch (data) { - | None => Ok(model) - | Some(data) => - let state = ScratchSlide.import(data); - let slides = Util.ListUtil.put_nth(idx, state, slides); - LocalStorage.Scratch.save((idx, slides)); - - Ok({...model, editors: Scratch(idx, slides)}); - } - } - | ResetSlide => - let model = - switch (model.editors) { - | DebugLoad => failwith("impossible") - | Scratch(n, slides) => - let slides = - Util.ListUtil.put_nth(n, ScratchSlidesInit.init_nth(n), slides); - {...model, editors: Scratch(n, slides)}; - | School(n, specs, _) => - let instructor_mode = model.settings.instructor_mode; - { - ...model, - editors: - School( - n, - specs, - List.nth(specs, n) - |> SchoolExercise.state_of_spec(~instructor_mode), - ), - }; - }; - save_editors(model); + let editors = Editors.import_current(model.editors, data); + Model.save_and_return({...model, editors}); + | ExportPersistentData => + export_persistent_data(); Ok(model); - | SwitchSlide(n) => - switch (model.editors) { - | DebugLoad => failwith("impossible") - | Scratch(m, _) when m == n => Error(FailedToSwitch) - | Scratch(_, slides) => - switch (n < List.length(slides)) { - | false => Error(FailedToSwitch) - | true => - LocalStorage.Scratch.save((n, slides)); - Ok({...model, editors: Scratch(n, slides)}); - } - | School(_, specs, _) => - switch (n < List.length(specs)) { - | false => Error(FailedToSwitch) - | true => - let instructor_mode = model.settings.instructor_mode; - let spec = List.nth(specs, n); - let key = SchoolExercise.key_of(spec); - let exercise = - LocalStorage.School.load_exercise(key, spec, ~instructor_mode); - Ok({...model, editors: School(n, specs, exercise)}); - } + | ResetSlide => + let instructor_mode = model.settings.instructor_mode; + let editors = Editors.reset_current(model.editors, ~instructor_mode); + Model.save_and_return({...model, editors}); + | SwitchScratchSlide(n) => + let instructor_mode = model.settings.instructor_mode; + switch (switch_scratch_slide(model.editors, ~instructor_mode, n)) { + | None => Error(FailedToSwitch) + | Some(editors) => Model.save_and_return({...model, editors}) + }; + | SwitchExampleSlide(name) => + switch (Editors.switch_example_slide(model.editors, name)) { + | None => Error(FailedToSwitch) + | Some(editors) => Model.save_and_return({...model, editors}) } | SwitchEditor(pos) => - switch (model.editors) { - | DebugLoad => failwith("impossible") - | Scratch(_) => Error(FailedToSwitch) // one editor per scratch - | School(m, specs, exercise) => - let exercise = - SchoolExercise.switch_editor( - ~pos, - model.settings.instructor_mode, - ~exercise, - ); - LocalStorage.School.save_exercise( - exercise, - ~instructor_mode=model.settings.instructor_mode, - ); - Ok({...model, editors: School(m, specs, exercise)}); - } - | ToggleMode => - let new_mode = Editors.rotate_mode(model.editors); - let model = update_settings(Mode(new_mode), model); - Ok(load_model(model)); + let instructor_mode = model.settings.instructor_mode; + switch (switch_exercise_editor(model.editors, ~pos, ~instructor_mode)) { + | None => Error(FailedToSwitch) + | Some(editors) => Model.save_and_return({...model, editors}) + }; + | SetMode(mode) => + let model = update_settings(Mode(mode), model); + /* NOTE: Need to reload model for editors to load */ + Model.save(model); + Ok(Model.load(model)); | SetShowBackpackTargets(b) => Ok({...model, show_backpack_targets: b}) | SetFontMetrics(font_metrics) => Ok({...model, font_metrics}) | SetLogoFontMetrics(logo_font_metrics) => @@ -406,8 +354,7 @@ let apply = | UpdateLangDocMessages(u) => let langDocMessages = LangDocMessages.set_update(model.langDocMessages, u); - LocalStorage.LangDocMessages.save(langDocMessages); - Ok({...model, langDocMessages}); + Model.save_and_return({...model, langDocMessages}); | UpdateResult(key, res) => /* If error, print a message. */ switch (res) { diff --git a/src/haz3lweb/UpdateAction.re b/src/haz3lweb/UpdateAction.re index 29cc3b33ff..7385833900 100644 --- a/src/haz3lweb/UpdateAction.re +++ b/src/haz3lweb/UpdateAction.re @@ -11,7 +11,7 @@ type settings_action = | Benchmark | ContextInspector | InstructorMode - | Mode(Editors.mode); + | Mode(ModelSettings.mode); [@deriving (show({with_path: false}), sexp, yojson)] type t = @@ -23,11 +23,13 @@ type t = | FinishImportAll(option(string)) | InitImportScratchpad([@opaque] Js_of_ocaml.Js.t(Js_of_ocaml.File.file)) | FinishImportScratchpad(option(string)) + | ExportPersistentData | ResetSlide | Save - | ToggleMode - | SwitchSlide(int) - | SwitchEditor(SchoolExercise.pos) + | SetMode(ModelSettings.mode) + | SwitchScratchSlide(int) + | SwitchExampleSlide(string) + | SwitchEditor(Exercise.pos) | SetFontMetrics(FontMetrics.t) | SetLogoFontMetrics(FontMetrics.t) | PerformAction(Action.t) diff --git a/src/haz3lweb/exercises/BlankTemplate.ml b/src/haz3lweb/exercises/BlankTemplate.ml index 192aeda1de..31bf1fe0b6 100644 --- a/src/haz3lweb/exercises/BlankTemplate.ml +++ b/src/haz3lweb/exercises/BlankTemplate.ml @@ -5,7 +5,7 @@ *) let exercise = - SchoolExercise.blank_spec ~title:"Recursive Fibonacci" + Exercise.blank_spec ~title:"Recursive Fibonacci" ~module_name:"Ex_RecursiveFibonacci" (* make sure your file is named .ml *) ~point_distribution: diff --git a/src/haz3lweb/exercises/Ex_OddlyRecursive.ml b/src/haz3lweb/exercises/Ex_OddlyRecursive.ml index 5441acad00..4d9aec53f7 100644 --- a/src/haz3lweb/exercises/Ex_OddlyRecursive.ml +++ b/src/haz3lweb/exercises/Ex_OddlyRecursive.ml @@ -1,6 +1,6 @@ let prompt = Ex_OddlyRecursive_prompt.prompt -let exercise : SchoolExercise.spec = +let exercise : Exercise.spec = { next_id = 5134; title = "Oddly Recursive"; diff --git a/src/haz3lweb/exercises/Ex_RecursiveFibonacci.ml b/src/haz3lweb/exercises/Ex_RecursiveFibonacci.ml index e1e9afa755..3ef6d6163f 100644 --- a/src/haz3lweb/exercises/Ex_RecursiveFibonacci.ml +++ b/src/haz3lweb/exercises/Ex_RecursiveFibonacci.ml @@ -1,6 +1,6 @@ let prompt = Ex_RecursiveFibonacci_prompt.prompt -let exercise : SchoolExercise.spec = +let exercise : Exercise.spec = { next_id = 813; title = "Recursive Fibonacci"; diff --git a/src/haz3lweb/view/BackpackView.re b/src/haz3lweb/view/BackpackView.re index bf7349e658..b2ced49b00 100644 --- a/src/haz3lweb/view/BackpackView.re +++ b/src/haz3lweb/view/BackpackView.re @@ -13,7 +13,7 @@ let backpack_sel_view = module Text = Code.Text({ let map = Measured.of_segment(content); - let settings = ModelSettings.init; + let settings = Init.startup.settings; }); // TODO(andrew): Maybe use init sort at caret to prime this div( diff --git a/src/haz3lweb/view/Cell.re b/src/haz3lweb/view/Cell.re index 05facc8846..8813021061 100644 --- a/src/haz3lweb/view/Cell.re +++ b/src/haz3lweb/view/Cell.re @@ -274,7 +274,7 @@ let editor_view = ~selected: bool, ~caption: option(Node.t)=?, ~code_id: string, - ~info_map: Statics.map, + ~info_map: Statics.Map.t, ~test_results: option(Interface.test_results), ~footer: option(Node.t), ~color_highlighting: option(ColorSteps.colorMap), @@ -339,7 +339,7 @@ let editor_with_result_view = ~selected: bool, ~caption: option(Node.t)=?, ~code_id: string, - ~info_map: Statics.map, + ~info_map: Statics.Map.t, ~result: ModelResult.simple, editor: Editor.t, ) => { diff --git a/src/haz3lweb/view/CtxInspector.re b/src/haz3lweb/view/CtxInspector.re index 36fa463408..24ee5af2ff 100644 --- a/src/haz3lweb/view/CtxInspector.re +++ b/src/haz3lweb/view/CtxInspector.re @@ -2,66 +2,70 @@ open Virtual_dom.Vdom; open Node; open Util.Web; -let context_entry_view = (~inject, entry: Haz3lcore.Ctx.entry): Node.t => - div( - ~attr= - Attr.many([ - clss(["context-entry"]), - Attr.on_click(_ => - inject( - UpdateAction.PerformAction( - Jump(TileId(Haz3lcore.Ctx.get_id(entry))), - ), - ) - ), - ]), - switch (entry) { - | VarEntry({name, typ, _}) => [text(name), text(":"), Type.view(typ)] - | TVarEntry({name, kind, _}) => [ - text("type "), - text(name), - text("::"), +let jump_to = entry => + UpdateAction.PerformAction(Jump(TileId(Haz3lcore.Ctx.get_id(entry)))); + +let context_entry_view = (~inject, entry: Haz3lcore.Ctx.entry): Node.t => { + let div_name = + div( + ~attr= + Attr.many([ + clss(["name"]), + Attr.on_click(_ => inject(jump_to(entry))), + ]), + ); + switch (entry) { + | VarEntry({name, typ, _}) + | ConstructorEntry({name, typ, _}) => + div_c( + "context-entry", + [ + div_name([text(name)]), + div(~attr=clss(["seperator"]), [text(":")]), + Type.view(typ), + ], + ) + | TVarEntry({name, kind, _}) => + div_c( + "context-entry", + [ + div_name([Type.alias_view(name)]), + div(~attr=clss(["seperator"]), [text("::")]), Kind.view(kind), - ] - }, - ); + ], + ) + }; +}; -let ctxc = "context-entries"; +let div_ctx = div(~attr=clss(["context-entries"])); -let exp_ctx_view = (~inject, ctx: Haz3lcore.Ctx.t): Node.t => { - let ctx = ctx |> Haz3lcore.Ctx.filter_duplicates; - div( - ~attr=clss([ctxc, "exp"]), - List.map(context_entry_view(~inject), List.rev(ctx)), +let ctx_view = (~inject, ctx: Haz3lcore.Ctx.t): Node.t => + div_ctx( + List.map( + context_entry_view(~inject), + ctx |> Haz3lcore.Ctx.filter_duplicates |> List.rev, + ), ); -}; -let pat_ctx_view = (~inject, ctx: Haz3lcore.Ctx.t): Node.t => { - let ctx = ctx |> Haz3lcore.Ctx.filter_duplicates; - div( - ~attr=clss([ctxc, "pat"]), - List.map(context_entry_view(~inject), List.rev(ctx)), - ); -}; - -let ctx_sorts_view = (~inject, ci: Haz3lcore.Statics.t): Node.t => { - switch (ci) { - | Invalid(_) => div(~attr=clss([ctxc, "invalid"]), [text("")]) - | InfoExp({ctx, _}) => exp_ctx_view(~inject, ctx) - | InfoPat({ctx, _}) => pat_ctx_view(~inject, ctx) - | InfoTyp(_) => div(~attr=clss([ctxc, "typ"]), []) - | InfoRul(_) => div(~attr=clss([ctxc, "rul"]), []) - }; -}; +let ctx_sorts_view = (~inject, ci: Haz3lcore.Statics.Info.t) => + Haz3lcore.Info.ctx_of(ci) + |> Haz3lcore.Ctx.filter_duplicates + |> List.rev + |> List.map(context_entry_view(~inject)); let inspector_view = - (~inject, ~settings: ModelSettings.t, _id: int, ci: Haz3lcore.Statics.t) + ( + ~inject, + ~settings: ModelSettings.t, + _id: int, + ci: Haz3lcore.Statics.Info.t, + ) : Node.t => { let clss = clss( ["context-inspector"] @ (settings.context_inspector ? ["visible"] : []), ); - div(~attr=clss, [ctx_sorts_view(~inject, ci)]); + div(~attr=clss, ctx_sorts_view(~inject, ci)); }; let view = @@ -69,7 +73,7 @@ let view = ~inject, ~settings: ModelSettings.t, index': option(int), - info_map: Haz3lcore.Statics.map, + info_map: Haz3lcore.Statics.Map.t, ) => { let (index, ci) = switch (index') { diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index ee67d1f695..2221760aa1 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -2,274 +2,249 @@ open Virtual_dom.Vdom; open Node; open Util.Web; open Util; +open Haz3lcore; -let cls_str = (ci: Haz3lcore.Statics.t): string => - switch (ci) { - | Invalid(msg) => Haz3lcore.TermBase.show_parse_flag(msg) - | InfoExp({cls, _}) => Haz3lcore.Term.UExp.show_cls(cls) - | InfoPat({cls, _}) => Haz3lcore.Term.UPat.show_cls(cls) - | InfoTyp({cls, _}) => Haz3lcore.Term.UTyp.show_cls(cls) - | InfoRul({cls, _}) => Haz3lcore.Term.URul.show_cls(cls) - }; +let errc = "error"; +let okc = "ok"; +let div_err = div(~attr=clss([errc])); +let div_ok = div(~attr=clss([okc])); + +let lang_doc_toggle = (~inject, ~show_lang_doc) => { + let tooltip = "Toggle language documentation"; + let toggle_landocs = _ => + Virtual_dom.Vdom.Effect.Many([ + inject(Update.UpdateLangDocMessages(LangDocMessages.ToggleShow)), + Virtual_dom.Vdom.Effect.Stop_propagation, + ]); + div( + ~attr=clss(["lang-doc-button"]), + [Widgets.toggle(~tooltip, "i", show_lang_doc, toggle_landocs)], + ); +}; + +let cls_view = (ci: Info.t) => + div( + ~attr=clss(["syntax-class"]), + [text(ci |> Info.cls_of |> Term.Cls.show)], + ); -let errorc = "error"; -let happyc = "happy"; -let infoc = "info"; +let term_view = (~inject, ~settings: ModelSettings.t, ~show_lang_doc, id, ci) => { + let sort = ci |> Info.sort_of |> Sort.show; + let context_menu = + div( + ~attr= + Attr.many([ + Attr.on_click(_ => inject(Update.Set(ContextInspector))), + clss(["gamma"] @ (settings.context_inspector ? ["visible"] : [])), + ]), + [text("Γ")], + ); + div( + ~attr= + clss( + ["ci-header", "ci-header-" ++ sort] + @ (Info.is_error(ci) ? [errc] : []), + ), + [ + context_menu, + CtxInspector.inspector_view(~inject, ~settings, id, ci), + div(~attr=clss(["term-tag"]), [text(sort)]), + lang_doc_toggle(~inject, ~show_lang_doc), + cls_view(ci), + ], + ); +}; -let error_view = (err: Haz3lcore.Statics.error) => +let no_type_error = (err: Info.error_no_type) => switch (err) { - | Multi => - div(~attr=clss([errorc, "err-multi"]), [text("⑂ Multi Hole")]) - | Free(Variable) => - div( - ~attr=clss([errorc, "err-free-variable"]), - [text("Variable is not bound")], - ) - | NoFun(typ) => - div( - ~attr=clss([errorc, "err-not-function"]), - [text("Not a function: "), Type.view(typ)], - ) - | Free(TypeVariable) => - div( - ~attr=clss([errorc, "err-free-variable"]), - [text("Type Variable is not bound")], - ) - | Free(Tag) => - div( - ~attr=clss([errorc, "err-free-variable"]), - [text("Constructor is not defined")], - ) - | SynInconsistentBranches(tys) => - div( - ~attr=clss([errorc, "err-inconsistent-branches"]), - [text("Expecting branches to have consistent types but got:")] - @ ListUtil.join(text(","), List.map(Type.view, tys)), - ) - | TypeInconsistent(ty_syn, ty_ana) => - div( - ~attr=clss([errorc, "err-type-inconsistent"]), - [ - text("Expecting"), - Type.view(ty_ana), - text("but found"), - Type.view(ty_syn), - ], - ) + | BadToken(token) => + switch (Form.bad_token_cls(token)) { + | BadInt => "Integer is too large or too small" + | Other => Printf.sprintf("\"%s\" isn't a valid token", token) + } + | FreeConstructor(name) => "'" ++ name ++ "' not found" }; -let happy_view = (suc: Haz3lcore.Statics.happy) => { - switch (suc) { - | SynConsistent(ty_syn) => - div( - ~attr=clss([happyc, "syn-consistent"]), - [text("has type"), Type.view(ty_syn)], - ) - | AnaConsistent(ty_ana, ty_syn, _ty_join) when ty_ana == ty_syn => - div( - ~attr=clss([happyc, "ana-consistent-equal"]), - [text("has expected type"), Type.view(ty_ana)], - ) - | AnaConsistent(ty_ana, ty_syn, _ty_join) => - div( - ~attr=clss([happyc, "ana-consistent"]), - switch (ty_syn) { - // A hack for EECS 490 A1 - | Haz3lcore.Typ.Unknown(_) => [ - text("has expected type"), - Type.view(ty_ana), - ] - | _ => [ - text("has type"), - Type.view(ty_syn), - text("which is consistent with"), - Type.view(ty_ana), - ] - }, - ) - | AnaInternalInconsistent(ty_ana, _) - | AnaExternalInconsistent(ty_ana, _) => - div( - ~attr=clss([happyc, "ana-consistent-external"]), - [ - div( - ~attr=clss(["typ-view", "atom"]), - [text("⇐"), div(~attr=clss(["typ-mod"]), [text("☆")])], - ), - Type.view(ty_ana), - ], - ) - }; -}; +let elements_noun: Term.Cls.t => string = + fun + | Exp(Match | If) => "Branches" + | Exp(ListLit) + | Pat(ListLit) => "Elements" + | _ => failwith("elements_noun: Cls doesn't have elements"); -let status_view = (err: Haz3lcore.Statics.error_status) => { +let common_err_view = (cls: Term.Cls.t, err: Info.error_common) => switch (err) { - | InHole(error) => error_view(error) - | NotInHole(happy) => happy_view(happy) + | NoType(err) => [text(no_type_error(err))] + | Inconsistent(WithArrow(typ)) => [ + Type.view(typ), + text("is inconsistent with arrow type"), + ] + | Inconsistent(Internal(tys)) => [ + text(elements_noun(cls) ++ " have inconsistent types:"), + ...ListUtil.join(text(","), List.map(Type.view, tys)), + ] + | Inconsistent(Expectation({ana, syn})) => [ + text(":"), + Type.view(syn), + text("inconsistent with expected type"), + Type.view(ana), + ] + }; + +let common_ok_view = (cls: Term.Cls.t, ok: Info.ok_pat) => { + switch (ok) { + | Syn(_) when cls == Exp(EmptyHole) => [ + text("Fillable by any expression"), + ] + | Syn(_) when cls == Pat(EmptyHole) => [text("Fillable by any pattern")] + | Ana(Consistent({ana, _})) + when cls == Exp(EmptyHole) || cls == Pat(EmptyHole) => [ + text("Expecting type"), + Type.view(ana), + ] + | Syn(syn) => [text(":"), Type.view(syn)] + | Ana(Consistent({ana, syn, _})) when ana == syn => [ + text(":"), + Type.view(syn), + text("exactly satisfies expected type"), + ] + | Ana(Consistent({ana, syn: Unknown(_) as syn, _})) => [ + text(":"), + Type.view(syn), + text("trivially satisfies expected type"), + Type.view(ana), + ] + | Ana(Consistent({ana: Unknown(_) as ana, syn, _})) => [ + text(":"), + Type.view(syn), + text("satisfies trivial expected type"), + Type.view(ana), + ] + | Ana(Consistent({ana, syn, _})) => [ + text(":"), + Type.view(syn), + text("satisfies expected type"), + Type.view(ana), + ] + | Ana(InternallyInconsistent({ana, nojoin: tys})) => + [ + text(elements_noun(cls) ++ " have inconsistent types:"), + ...ListUtil.join(text(","), List.map(Type.view, tys)), + ] + @ [text("but these satisfy expected type"), Type.view(ana)] }; }; -let term_tag = (~inject, ~show_lang_doc, is_err, sort) => { - let lang_doc = - div( - ~attr=clss(["lang-doc-button"]), - [ - Widgets.toggle( - ~tooltip="Toggle language documentation", "i", show_lang_doc, _ => - Effect.Many([ - inject(Update.UpdateLangDocMessages(LangDocMessages.ToggleShow)), - Effect.Stop_propagation, - ]) - ), - ], - ); +let typ_ok_view = (cls: Term.Cls.t, ok: Info.ok_typ) => + switch (ok) { + | Type(_) when cls == Typ(EmptyHole) => [text("Fillable by any type")] + | Type(ty) => [Type.view(ty)] + | TypeAlias(name, ty_lookup) => [ + Type.view(Var(name)), + text("is a type alias for"), + Type.view(ty_lookup), + ] + | Variant(name, _sum_ty) => [Type.view(Var(name))] + | VariantIncomplete(_sum_ty) => [text("is incomplete")] + }; - div( - ~attr= - Attr.many([ - clss(["term-tag", "term-tag-" ++ sort] @ (is_err ? [errorc] : [])), - ]), - [div(~attr=clss(["gamma"]), [text("Γ")]), text(sort), lang_doc], - ); -}; +let typ_err_view = (ok: Info.error_typ) => + switch (ok) { + | FreeTypeVariable(name) => [Type.view(Var(name)), text("not found")] + | BadToken(token) => [ + text("'" ++ token ++ "' isn't a type or type operator"), + ] + | WantConstructorFoundAp + | WantConstructorFoundType(_) => [text("Expected a constructor")] + | WantTypeFoundAp => [text("Must be part of a sum type")] + | DuplicateConstructor(name) => [ + Type.view(Var(name)), + text("already used in this sum"), + ] + }; -let view_of_info = - (~inject, ~show_lang_doc: bool, ci: Haz3lcore.Statics.t): Node.t => { - let is_err = Haz3lcore.Statics.is_error(ci); - switch (ci) { - | Invalid(msg) => - div( - ~attr=clss([infoc, "unknown"]), - [text("🚫 " ++ Haz3lcore.TermBase.show_parse_flag(msg))], - ) - | InfoExp({mode, self, _}) => - let error_status = Haz3lcore.Statics.error_status(mode, self); - div( - ~attr=clss([infoc, "exp"]), - [ - term_tag(~inject, ~show_lang_doc, is_err, "exp"), - status_view(error_status), - ], - ); - | InfoPat({mode, self, _}) => - let error_status = Haz3lcore.Statics.error_status(mode, self); - div( - ~attr=clss([infoc, "pat"]), - [ - term_tag(~inject, ~show_lang_doc, is_err, "pat"), - status_view(error_status), - ], - ); - | InfoTyp({self: Free(free_error), _}) => - div( - ~attr=clss([infoc, "typ"]), - [ - term_tag(~inject, ~show_lang_doc, is_err, "typ"), - error_view(Free(free_error)), - ], - ) - | InfoTyp({self: Just(ty), _}) => - div( - ~attr=clss([infoc, "typ"]), - [ - term_tag(~inject, ~show_lang_doc, is_err, "typ"), - text("is"), - Type.view(ty), - ], - ) - | InfoTyp({self: _, _}) => - failwith("CursorInspector: Impossible type error") - | InfoRul(_) => - div( - ~attr=clss([infoc, "rul"]), - [term_tag(~inject, ~show_lang_doc, is_err, "rul"), text("Rule")], - ) +let exp_view = (cls: Term.Cls.t, status: Info.status_exp) => + switch (status) { + | InHole(FreeVariable(name)) => + div_err([text("'" ++ name ++ "' not found")]) + | InHole(Common(error)) => div_err(common_err_view(cls, error)) + | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) }; -}; -let cls_view = (ci: Haz3lcore.Statics.t): Node.t => - div(~attr=clss(["syntax-class"]), [text(cls_str(ci))]); +let pat_view = (cls: Term.Cls.t, status: Info.status_pat) => + switch (status) { + | InHole(ExpectedConstructor) => div_err([text("Expected a constructor")]) + | InHole(Common(error)) => div_err(common_err_view(cls, error)) + | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) + }; -let id_view = (id): Node.t => - div(~attr=clss(["id"]), [text(string_of_int(id + 1))]); +let typ_view = (cls: Term.Cls.t, status: Info.status_typ) => + switch (status) { + | NotInHole(ok) => div_ok(typ_ok_view(cls, ok)) + | InHole(err) => div_err(typ_err_view(err)) + }; -let extra_view = (visible: bool, id: int, ci: Haz3lcore.Statics.t): Node.t => - div( - ~attr=Attr.many([clss(["extra"] @ (visible ? ["visible"] : []))]), - [id_view(id), cls_view(ci)], - ); +let tpat_view = (_: Term.Cls.t, status: Info.status_tpat) => + switch (status) { + | NotInHole(Empty) => div_ok([text("Fillable with a new type alias")]) + | NotInHole(Var(name)) => div_ok([Type.alias_view(name)]) + | InHole(NotAVar(NotCapitalized)) => + div_err([text("Must begin with a capital letter")]) + | InHole(NotAVar(_)) => div_err([text("Expected a type alias")]) + | InHole(ShadowsType(name)) when Form.is_base_typ(name) => + div_err([text("Can't shadow base type"), Type.view(Var(name))]) + | InHole(ShadowsType(name)) => + div_err([text("Can't shadow existing alias"), Type.view(Var(name))]) + }; -let toggle_context_and_print_ci = (~inject: Update.t => 'a, ci, _) => { - print_endline(Haz3lcore.Statics.show(ci)); +let view_of_info = + (~inject, ~settings, ~show_lang_doc: bool, id, ci: Statics.Info.t): Node.t => { + let wrapper = status_view => + div( + ~attr=clss(["info"]), + [term_view(~inject, ~settings, ~show_lang_doc, id, ci), status_view], + ); switch (ci) { - | InfoPat({mode, self, _}) - | InfoExp({mode, self, _}) => - Haz3lcore.Statics.error_status(mode, self) - |> Haz3lcore.Statics.show_error_status - |> print_endline - | _ => () + | InfoExp({cls, status, _}) => wrapper(exp_view(cls, status)) + | InfoPat({cls, status, _}) => wrapper(pat_view(cls, status)) + | InfoTyp({cls, status, _}) => wrapper(typ_view(cls, status)) + | InfoTPat({cls, status, _}) => wrapper(tpat_view(cls, status)) }; - inject(Set(ContextInspector)); }; -let inspector_view = - ( - ~inject, - ~settings: ModelSettings.t, - ~show_lang_doc: bool, - id: int, - ci: Haz3lcore.Statics.t, - ) - : Node.t => +let inspector_view = (~inject, ~settings, ~show_lang_doc, id, ci): Node.t => div( - ~attr= - Attr.many([ - clss( - ["cursor-inspector"] - @ [Haz3lcore.Statics.is_error(ci) ? errorc : happyc], - ), - Attr.on_click(toggle_context_and_print_ci(~inject, ci)), - ]), - [ - extra_view(settings.context_inspector, id, ci), - view_of_info(~inject, ~show_lang_doc, ci), - CtxInspector.inspector_view(~inject, ~settings, id, ci), - ], + ~attr=clss(["cursor-inspector"] @ [Info.is_error(ci) ? errc : okc]), + [view_of_info(~inject, ~settings, ~show_lang_doc, id, ci)], ); let view = ( ~inject, - ~settings, + ~settings: ModelSettings.t, ~show_lang_doc: bool, - zipper: Haz3lcore.Zipper.t, - info_map: Haz3lcore.Statics.map, + zipper: Zipper.t, + info_map: Statics.Map.t, ) => { - let backpack = zipper.backpack; - if (List.length(backpack) > 0) { - div([]); - } else { - let index = Haz3lcore.Indicated.index(zipper); - - switch (index) { - | Some(index) => - switch (Haz3lcore.Id.Map.find_opt(index, info_map)) { - | Some(ci) => - inspector_view(~inject, ~settings, ~show_lang_doc, index, ci) - | None => - div( - ~attr=clss(["cursor-inspector"]), - [div(~attr=clss(["icon"]), [Icons.magnify]), text("")], - ) - } - | None => + let bar_view = div(~attr=Attr.id("bottom-bar")); + let err_view = err => + bar_view([ div( - ~attr=clss(["cursor-inspector"]), - [ - div(~attr=clss(["icon"]), [Icons.magnify]), - text("No Indicated Index"), - ], - ) - }; + ~attr=clss(["cursor-inspector", "no-info"]), + [div(~attr=clss(["icon"]), [Icons.magnify]), text(err)], + ), + ]); + switch (zipper.backpack, Indicated.index(zipper)) { + | ([_, ..._], _) => err_view("No information while backpack in use") + | (_, None) => err_view("No cursor in program") + | (_, Some(id)) => + switch (Id.Map.find_opt(id, info_map)) { + | None => err_view("Whitespace or Comment") + | Some(ci) => + bar_view([ + inspector_view(~inject, ~settings, ~show_lang_doc, id, ci), + div(~attr=clss(["id"]), [text(string_of_int(id + 1))]), + ]) + } }; }; diff --git a/src/haz3lweb/view/DebugMode.re b/src/haz3lweb/view/DebugMode.re index f8ed4cf2bc..ee01231c44 100644 --- a/src/haz3lweb/view/DebugMode.re +++ b/src/haz3lweb/view/DebugMode.re @@ -20,7 +20,7 @@ let view = (~inject) => { btn( ~inject, "clear local storage (LOSE ALL DATA!)", - UpdateAction.DebugAction(ClearLocalStorage), + UpdateAction.DebugAction(ClearStore), ), ]) ); diff --git a/src/haz3lweb/view/Deco.re b/src/haz3lweb/view/Deco.re index 5cd7bc9959..6125d4ce7d 100644 --- a/src/haz3lweb/view/Deco.re +++ b/src/haz3lweb/view/Deco.re @@ -10,7 +10,7 @@ module Deco = let show_backpack_targets: bool; let terms: TermMap.t; let term_ranges: TermRanges.t; - let info_map: Statics.map; + let info_map: Statics.Map.t; let tiles: TileMap.t; }, ) => { @@ -277,7 +277,7 @@ module Deco = let is_err = (id: Id.t) => switch (Id.Map.find_opt(id, M.info_map)) { | None => false - | Some(info) => Statics.is_error(info) + | Some(info) => Info.is_error(info) }; let is_rep = (id: Id.t) => switch (Id.Map.find_opt(id, M.terms)) { diff --git a/src/haz3lweb/view/EditorModeView.re b/src/haz3lweb/view/EditorModeView.re new file mode 100644 index 0000000000..3fe4a306f8 --- /dev/null +++ b/src/haz3lweb/view/EditorModeView.re @@ -0,0 +1,83 @@ +open Virtual_dom.Vdom; +open Node; +open Widgets; + +let option_view = (name, n) => + option( + ~attr=n == name ? Attr.create("selected", "selected") : Attr.many([]), + [text(n)], + ); + +let mode_menu = (~inject, ~mode: ModelSettings.mode) => + div( + ~attr=Attr.many([Attr.class_("mode-name"), Attr.title("Toggle Mode")]), + [ + select( + ~attr= + Attr.on_change((_, name) => + inject(Update.SetMode(ModelSettings.mode_of_string(name))) + ), + List.map( + option_view(ModelSettings.show_mode(mode)), + ["Scratch", "Examples", "Exercise"], + ), + ), + ], + ); + +let slide_select = (~inject, ~cur_slide, ~num_slides) => { + let next_ed = (cur_slide + 1) mod num_slides; + let prev_ed = Util.IntUtil.modulo(cur_slide - 1, num_slides); + [ + button(Icons.back, _ => inject(Update.SwitchScratchSlide(prev_ed))), + text(Printf.sprintf("%d / %d", cur_slide + 1, num_slides)), + button(Icons.forward, _ => inject(Update.SwitchScratchSlide(next_ed))), + ]; +}; + +let scratch_view = (~inject, ~cur_slide, ~slides) => + [mode_menu(~inject, ~mode=Scratch)] + @ slide_select(~inject, ~cur_slide, ~num_slides=List.length(slides)); + +let examples_view = (~inject, ~name, ~editors) => [ + mode_menu(~inject, ~mode=Examples), + select( + ~attr= + Attr.on_change((_, name) => inject(Update.SwitchExampleSlide(name))), + List.map(option_view(name), List.map(fst, editors)), + ), +]; + +let instructor_toggle = (~inject, ~instructor_mode) => + ExerciseSettings.show_instructor + ? [ + toggle("🎓", ~tooltip="Toggle Instructor Mode", instructor_mode, _ => + inject(Update.Set(InstructorMode)) + ), + ] + : []; + +let exercises_view = (~inject, ~cur_slide, ~specs, ~instructor_mode) => { + [mode_menu(~inject, ~mode=Exercise)] + @ instructor_toggle(~inject, ~instructor_mode) + @ slide_select(~inject, ~cur_slide, ~num_slides=List.length(specs)); +}; + +let view = + ( + ~inject: Update.t => 'a, + ~editors: Editors.t, + ~settings as {instructor_mode, _}: ModelSettings.t, + ) + : Node.t => { + let contents = + switch (editors) { + | DebugLoad => [] + | Scratch(cur_slide, slides) => + scratch_view(~inject, ~cur_slide, ~slides) + | Examples(name, editors) => examples_view(~inject, ~name, ~editors) + | Exercise(cur_slide, specs, _) => + exercises_view(~cur_slide, ~specs, ~inject, ~instructor_mode) + }; + div(~attr=Attr.id("editor-mode"), contents); +}; diff --git a/src/haz3lweb/view/SchoolMode.re b/src/haz3lweb/view/ExerciseMode.re similarity index 88% rename from src/haz3lweb/view/SchoolMode.re rename to src/haz3lweb/view/ExerciseMode.re index 04b44a9433..5cbeb84542 100644 --- a/src/haz3lweb/view/SchoolMode.re +++ b/src/haz3lweb/view/ExerciseMode.re @@ -3,26 +3,26 @@ open Virtual_dom.Vdom; open Node; type t = { - exercise: SchoolExercise.state, + exercise: Exercise.state, results: option(ModelResults.t), settings: ModelSettings.t, langDocMessages: LangDocMessages.t, - stitched_dynamics: SchoolExercise.stitched(SchoolExercise.DynamicsItem.t), + stitched_dynamics: Exercise.stitched(Exercise.DynamicsItem.t), grading_report: Grading.GradingReport.t, }; let mk = ( - ~exercise: SchoolExercise.state, + ~exercise: Exercise.state, ~results: option(ModelResults.t), ~settings, ~langDocMessages, ) : t => { - let SchoolExercise.{eds, _} = exercise; + let Exercise.{eds, _} = exercise; let stitched_dynamics = Util.TimeUtil.measure_time("stitch_dynamics", true, () => - SchoolExercise.stitch_dynamic(exercise, results) + Exercise.stitch_dynamic(exercise, results) ); let grading_report = Grading.GradingReport.mk(eds, ~stitched_dynamics); @@ -61,8 +61,8 @@ let view = grading_report, langDocMessages, } = self; - let SchoolExercise.{pos, eds} = exercise; - let SchoolExercise.{ + let Exercise.{pos, eds} = exercise; + let Exercise.{ test_validation, user_impl, user_tests, @@ -72,7 +72,7 @@ let view = hidden_tests: _, } = stitched_dynamics; let (focal_zipper, focal_info_map) = - SchoolExercise.focus(exercise, stitched_dynamics); + Exercise.focus(exercise, stitched_dynamics); let color_highlighting: option(ColorSteps.colorMap) = if (langDocMessages.highlight && langDocMessages.show) { @@ -171,7 +171,7 @@ let view = switch (specific_ctx) { | None => Node.div([text("No context available")]) // TODO show exercise configuration error | Some(specific_ctx) => - CtxInspector.exp_ctx_view(~inject, specific_ctx) + CtxInspector.ctx_view(~inject, specific_ctx) }; }; }; @@ -218,8 +218,8 @@ let view = ( i, ( - SchoolExercise.{impl, _}, - SchoolExercise.DynamicsItem.{info_map, simple_result, _}, + Exercise.{impl, _}, + Exercise.DynamicsItem.{info_map, simple_result, _}, ), ) => { InstructorOnly( @@ -326,7 +326,7 @@ let view = ), ); - let ci_view = + let bottom_bar = settings.statics ? [ CursorInspector.view( @@ -338,7 +338,17 @@ let view = ), ] : []; - + let sidebar = + langDocMessages.show && settings.statics + ? LangDoc.view( + ~inject, + ~font_metrics, + ~settings, + ~doc=langDocMessages, + Indicated.index(focal_zipper), + focal_info_map, + ) + : div([]); [ div( ~attr=Attr.id("main"), @@ -362,36 +372,23 @@ let view = hidden_tests_view, impl_grading_view, ], - ) - @ ( - langDocMessages.show && settings.statics - ? [ - LangDoc.view( - ~inject, - ~font_metrics, - ~settings, - ~doc=langDocMessages, - Indicated.index(focal_zipper), - focal_info_map, - ), - ] - : [] - ), + ), ), ], ), - div(~attr=Attr.class_("bottom-bar"), ci_view), - ]; // TODO lang doc visibility tied to ci visibility (is this desired?) + sidebar, + ] + @ bottom_bar; }; let toolbar_buttons = (~inject, editors: Editors.t, ~settings: ModelSettings.t) => { - let (_idx, _specs, exercise): Editors.school = + let (_idx, _specs, exercise): Editors.exercises = switch (editors) { - | School(idx, specs, exercise) => (idx, specs, exercise) + | Exercise(idx, specs, exercise) => (idx, specs, exercise) | _ => assert(false) }; - let SchoolExercise.{pos: _, eds} = exercise; + let Exercise.{pos: _, eds} = exercise; let reset_button = Widgets.button( @@ -420,8 +417,7 @@ let toolbar_buttons = let module_name = eds.module_name; let filename = eds.module_name ++ ".ml"; let content_type = "text/plain"; - let contents = - SchoolExercise.export_module(module_name, exercise); + let contents = Exercise.export_module(module_name, exercise); JsUtil.download_string_file( ~filename, ~content_type, @@ -445,10 +441,7 @@ let toolbar_buttons = let filename = eds.module_name ++ ".ml"; let content_type = "text/plain"; let contents = - SchoolExercise.export_transitionary_module( - module_name, - exercise, - ); + Exercise.export_transitionary_module(module_name, exercise); JsUtil.download_string_file( ~filename, ~content_type, @@ -472,7 +465,7 @@ let toolbar_buttons = let filename = eds.module_name ++ "_grading.ml"; let content_type = "text/plain"; let contents = - SchoolExercise.export_grading_module(module_name, exercise); + Exercise.export_grading_module(module_name, exercise); JsUtil.download_string_file( ~filename, ~content_type, diff --git a/src/haz3lweb/view/Icons.re b/src/haz3lweb/view/Icons.re index 915191db30..543690448f 100644 --- a/src/haz3lweb/view/Icons.re +++ b/src/haz3lweb/view/Icons.re @@ -136,3 +136,19 @@ let magnify = "M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z", ], ); + +let chest = + simple_icon( + ~view="0 0 100 125", + [ + "M56,54v-4c0-1.1,0.9-2,2-2s2,0.9,2,2v4c0,1.1-0.9,2-2,2S56,55.1,56,54z M94,28v12v36c0,3.3-2.7,6-6,6H12c-3.3,0-6-2.7-6-6 V40V28c0-5.5,4.5-10,10-10h68C89.5,18,94,22.5,94,28z M84,22H24c1.3,1.7,2,3.7,2,6v10h64V28C90,24.7,87.3,22,84,22z M10,38h12V28 c0-3.3-2.7-6-6-6s-6,2.7-6,6V38z M12,78h10V42H10v34C10,77.1,10.9,78,12,78z M90,42H26v36h62c1.1,0,2-0.9,2-2V42z", + ], + ); + +let sprout = + simple_icon( + ~view="0 0 100 125", + [ + "M48.8,68.2c-2,0.8-1.6,2.2-2.1,2.5c-0.8,0.3-0.1-1-2.1-1.6c-4.5-1.4-4,4.3-6.5,4.2c-1.7-0.1-1.8-0.6-3.4-0.4 c-1.6,0.3-1.1,2.1-2.9,2.3c-1.1,0.1-0.7,1.2-2.4,1c-1.4-0.2-2,1.6-2.1,2.7c-0.1,0.8-0.3,1.6-1.6,2.3c-1.2,0.7-3.3,0.2-4.4,1.7 c-1.6,2-1.7,5.1-1.7,5.1h60.7c0,0-0.1-2.3-2.6-3.9c-0.7-0.4,0.1-0.4,0.4-2c0.1-0.6,0-1.5-0.7-2.6c-0.9-1.3-2.7-0.9-3.4-0.7 c0.2-0.9,0.2-2-1.2-2.9c-1-0.7-1.3-0.3-1.9-0.4c-0.7-0.1-0.3-0.8-1-1.2c-1.8-1.1-0.5-2.1-3.3-3.2c-1.7-0.7-2-0.6-5.6-0.6 c-1.4,0-1.7-2.3-3.6-1.8c-1.9,0.6-1.1-0.5-2.2-1.6c-0.3-0.3-0.9-0.5-1.5-0.5c-0.1-10.6-0.1-24.5,0.3-27.2c0.6-4.5,5.7-9.8,13.1-10.6 c-7,5.2-10.2,6.7-10.8,9.9c-0.6,3.2,5.1,2.5,9.6,0c4.5-2.5,12.1-14.6,12.4-19c-6.4-1.6-22,4.1-27.1,16.6C49.6,26.6,47.7,12,20.3,12 c-0.1,2.6,0.6,2.9,1.9,6.1c1.3,3.2,9.9,18.1,20.7,17.5c1.6-0.1-0.3-3.8-2.9-6.8c0,0-6.4-5.9-8.3-7.5c6.4,2.5,16.2,9.9,17,15.3 c0.5,3.5,0.4,20.2,0.2,31.7C49,68.2,48.9,68.2,48.8,68.2z", + ], + ); diff --git a/src/haz3lweb/view/Kind.re b/src/haz3lweb/view/Kind.re index 419b507c6f..f84672515c 100644 --- a/src/haz3lweb/view/Kind.re +++ b/src/haz3lweb/view/Kind.re @@ -2,16 +2,8 @@ open Virtual_dom.Vdom; open Node; open Util.Web; -// TODO: (poly) Finish the skeleton -let kind_view = (cls: string, s: string): Node.t => - div(~attr=clss(["kind-view", cls]), [text(s)]); - -// TODO: (poly) Finish the skeleton -let view = (ty: Haz3lcore.Kind.t): Node.t => - switch (ty) { - | Type => - div( - ~attr=clss(["kind-view"]), - [text("S"), kind_view("Singleton", "Singleton")], - ) +let view = (kind: Haz3lcore.Kind.t): Node.t => + switch (kind) { + | Singleton(ty) => div_c("kind-view", [Type.view(ty)]) + | Abstract => div_c("kind-view", [text("Type")]) }; diff --git a/src/haz3lweb/view/LangDoc.re b/src/haz3lweb/view/LangDoc.re index 97c88f8939..5fb3a6bdf0 100644 --- a/src/haz3lweb/view/LangDoc.re +++ b/src/haz3lweb/view/LangDoc.re @@ -250,18 +250,11 @@ let deco = let get_clss = segment => switch (List.nth(segment, 0)) { - | Base.Tile({mold, _}) => - switch (mold.out) { - | Pat => ["term-tag-pat"] - | Exp => ["term-tag-exp"] // TODO the brown on brown isn't the greatest... but okay - | Typ => ["term-tag-typ"] - | Any - | Nul - | Rul => [] - } + | Base.Tile({mold, _}) => [ + "ci-header-" ++ Sort.to_string(mold.out), + ] | _ => [] }; - let specificity_menu = Node.div( ~attr= @@ -493,7 +486,11 @@ type message_mode = | Colorings; let get_doc = - (~docs: LangDocMessages.t, info: option(Statics.t), mode: message_mode) + ( + ~docs: LangDocMessages.t, + info: option(Statics.Info.t), + mode: message_mode, + ) : (list(Node.t), (list(Node.t), ColorSteps.t), list(Node.t)) => { let default = ( [text("No syntactic form available")], @@ -556,38 +553,38 @@ let get_doc = }; }; + let basic_info = group => { + let (doc, options) = LangDocMessages.get_form_and_options(group, docs); + get_message(doc, options, group, doc.explanation.message, []); + }; + switch (info) { | Some(InfoExp({term, _})) => let rec get_message_exp = (term) : (list(Node.t), (list(Node.t), ColorSteps.t), list(Node.t)) => - switch (term) { - | TermBase.UExp.Invalid(_) => default - | EmptyHole => + switch ((term: TermBase.UExp.term)) { + | Invalid(_) => default + | EmptyHole => basic_info(LangDocMessages.empty_hole_exp_group) + | MultiHole(_) => basic_info(LangDocMessages.multi_hole_exp_group) + | TyAlias(ty_pat, ty_def, _body) => let (doc, options) = LangDocMessages.get_form_and_options( - LangDocMessages.empty_hole_exp_group, + LangDocMessages.tyalias_exp_group, docs, ); + let tpat_id = List.nth(ty_pat.ids, 0); + let def_id = List.nth(ty_def.ids, 0); get_message( doc, options, - LangDocMessages.empty_hole_exp_group, - doc.explanation.message, - [], - ); - | MultiHole(_children) => - let (doc, options) = - LangDocMessages.get_form_and_options( - LangDocMessages.multi_hole_exp_group, - docs, - ); - get_message( - doc, - options, - LangDocMessages.multi_hole_exp_group, - doc.explanation.message, - [], + LangDocMessages.tyalias_exp_group, + Printf.sprintf( + Scanf.format_from_string(doc.explanation.message, "%i%i"), + def_id, + tpat_id, + ), + LangDocMessages.tyalias_base_exp_coloring_ids(~tpat_id, ~def_id), ); | Triv => let (doc, options) = @@ -1156,19 +1153,19 @@ let get_doc = } else { basic(doc, LangDocMessages.function_ap_group, options); }; - | Tag(v) => + | Constructor(v) => let (doc, options) = LangDocMessages.get_form_and_options( - LangDocMessages.function_tag_group, + LangDocMessages.function_ctr_group, docs, ); - if (LangDocMessages.function_tag_exp.id == doc.id) { + if (LangDocMessages.function_ctr_exp.id == doc.id) { let pat_id = List.nth(pat.ids, 0); let body_id = List.nth(body.ids, 0); get_message( doc, options, - LangDocMessages.function_tag_group, + LangDocMessages.function_ctr_group, Printf.sprintf( Scanf.format_from_string(doc.explanation.message, "%i%s%i%i"), pat_id, @@ -1176,13 +1173,13 @@ let get_doc = pat_id, body_id, ), - LangDocMessages.function_tag_exp_coloring_ids( + LangDocMessages.function_ctr_exp_coloring_ids( ~pat_id, ~body_id, ), ); } else { - basic(doc, LangDocMessages.function_tag_group, options); + basic(doc, LangDocMessages.function_ctr_group, options); }; | Invalid(_) => default // Shouldn't get hit | Parens(_) => default // Shouldn't get hit? @@ -1817,20 +1814,20 @@ let get_doc = } else { basic(doc, LangDocMessages.let_ap_exp_group, options); }; - | Tag(v) => + | Constructor(v) => let (doc, options) = LangDocMessages.get_form_and_options( - LangDocMessages.let_tag_exp_group, + LangDocMessages.let_ctr_exp_group, docs, ); - if (LangDocMessages.let_tag_exp.id == doc.id) { + if (LangDocMessages.let_ctr_exp.id == doc.id) { let pat_id = List.nth(pat.ids, 0); let def_id = List.nth(def.ids, 0); let body_id = List.nth(body.ids, 0); get_message( doc, options, - LangDocMessages.let_tag_exp_group, + LangDocMessages.let_ctr_exp_group, Printf.sprintf( Scanf.format_from_string( doc.explanation.message, @@ -1842,14 +1839,14 @@ let get_doc = def_id, body_id, ), - LangDocMessages.let_tag_exp_coloring_ids( + LangDocMessages.let_ctr_exp_coloring_ids( ~pat_id, ~def_id, ~body_id, ), ); } else { - basic(doc, LangDocMessages.let_tag_exp_group, options); + basic(doc, LangDocMessages.let_ctr_exp_group, options); }; | Invalid(_) => default // Shouldn't get hit | Parens(_) => default // Shouldn't get hit? @@ -1869,7 +1866,7 @@ let get_doc = ); }; switch (x.term) { - | Tag(v) => + | Constructor(v) => let (doc, options) = LangDocMessages.get_form_and_options( LangDocMessages.conapp_exp_group, @@ -2130,16 +2127,16 @@ let get_doc = ), LangDocMessages.case_exp_coloring_ids(~scrut_id), ); - | Tag(v) => + | Constructor(v) => let (doc, options) = LangDocMessages.get_form_and_options( - LangDocMessages.tag_exp_group, + LangDocMessages.ctr_exp_group, docs, ); get_message( doc, options, - LangDocMessages.tag_exp_group, + LangDocMessages.ctr_exp_group, Printf.sprintf( Scanf.format_from_string(doc.explanation.message, "%s"), v, @@ -2464,16 +2461,16 @@ let get_doc = ), LangDocMessages.ap_pat_coloring_ids(~con_id, ~arg_id), ); - | Tag(con) => + | Constructor(con) => let (doc, options) = LangDocMessages.get_form_and_options( - LangDocMessages.tag_pat_group, + LangDocMessages.ctr_pat_group, docs, ); get_message( doc, options, - LangDocMessages.tag_pat_group, + LangDocMessages.ctr_pat_group, Printf.sprintf( Scanf.format_from_string(doc.explanation.message, "%s"), con, @@ -2504,7 +2501,7 @@ let get_doc = // Shouldn't be hit? default } - | Some(InfoTyp({term, _})) => + | Some(InfoTyp({term, cls, _})) => switch (bypass_parens_typ(term).term) { | EmptyHole => let (doc, options) = @@ -2726,6 +2723,10 @@ let get_doc = ); basic(doc, LangDocMessages.tuple_typ_group, options); }; + | Constructor(_) => + basic_info(LangDocMessages.sum_typ_nullary_constructor_def_group) + | Var(_) when cls == Typ(Constructor) => + basic_info(LangDocMessages.sum_typ_nullary_constructor_def_group) | Var(v) => let (doc, options) = LangDocMessages.get_form_and_options( @@ -2742,12 +2743,34 @@ let get_doc = ), [], ); - | Invalid(_) // Shouldn't be hit + | Sum(_) => basic_info(LangDocMessages.labelled_sum_typ_group) + | Ap(_) => basic_info(LangDocMessages.sum_typ_unary_constructor_def_group) | Parens(_) => default // Shouldn't be hit? + | Invalid(_) => default + } + | Some(InfoTPat(info)) => + switch (info.term.term) { + | Invalid(_) => default + | EmptyHole => basic_info(LangDocMessages.empty_hole_tpat_group) + | MultiHole(_) => basic_info(LangDocMessages.multi_hole_tpat_group) + | Var(v) => + let (doc, options) = + LangDocMessages.get_form_and_options( + LangDocMessages.var_typ_pat_group, + docs, + ); + get_message( + doc, + options, + LangDocMessages.var_typ_pat_group, + Printf.sprintf( + Scanf.format_from_string(doc.explanation.message, "%s"), + v, + ), + [], + ); } - | Some(InfoRul(_)) // Can't have cursor on just a rule atm - | None - | Some(Invalid(_)) => default + | None => default }; }; @@ -2758,8 +2781,8 @@ let section = (~section_clss: string, ~title: string, contents: list(Node.t)) => ); let get_color_map = - (~doc: LangDocMessages.t, index': option(int), info_map: Statics.map) => { - let info: option(Statics.t) = + (~doc: LangDocMessages.t, index': option(int), info_map: Statics.Map.t) => { + let info: option(Statics.Info.t) = switch (index') { | Some(index) => switch (Id.Map.find_opt(index, info_map)) { @@ -2779,9 +2802,9 @@ let view = ~settings: ModelSettings.t, ~doc: LangDocMessages.t, index': option(int), - info_map: Statics.map, + info_map: Statics.Map.t, ) => { - let info: option(Statics.t) = + let info: option(Statics.Info.t) = switch (index') { | Some(index) => switch (Id.Map.find_opt(index, info_map)) { @@ -2793,10 +2816,10 @@ let view = let (syn_form, (explanation, _), example) = get_doc(~docs=doc, info, MessageContent(inject, font_metrics, settings)); div( - ~attr=clss(["lang-doc"]), + ~attr=Attr.id("side-bar"), [ div( - ~attr=clss(["content"]), + ~attr=clss(["lang-doc"]), [ div( ~attr=clss(["top-bar"]), @@ -2820,7 +2843,7 @@ let view = ) ), ]), - [text("X")], + [text("✕")], ), ], ), diff --git a/src/haz3lweb/view/Page.re b/src/haz3lweb/view/Page.re index 0b0813e9dd..a3166c737e 100644 --- a/src/haz3lweb/view/Page.re +++ b/src/haz3lweb/view/Page.re @@ -5,179 +5,119 @@ open Util.Web; open Haz3lcore; open Widgets; -let next_slide = (~inject: Update.t => 'a, cur_slide, num_slides, _) => { - let next_ed = (cur_slide + 1) mod num_slides; - inject(SwitchSlide(next_ed)); -}; - let download_editor_state = (~instructor_mode) => { let data = Export.export_all(~instructor_mode); - JsUtil.download_json(SchoolSettings.filename, data); + JsUtil.download_json(ExerciseSettings.filename, data); }; - -let prev_slide = (~inject: Update.t => 'a, cur_slide, num_slides, _) => { - let prev_ed = Util.IntUtil.modulo(cur_slide - 1, num_slides); - inject(SwitchSlide(prev_ed)); -}; - -let slide_toggle_view = (~inject, ~model: Model.t, ~caption, ~control) => { - let id = Attr.id("editor-mode"); - let tooltip = Attr.title("Toggle Mode"); - let toggle_mode = Attr.on_mousedown(_ => inject(Update.ToggleMode)); - let cur_slide = Editors.cur_slide(model.editors); - let num_slides = Editors.num_slides(model.editors); - let cur_slide_text = Printf.sprintf("%d / %d", cur_slide + 1, num_slides); - div( - ~attr=id, - [ - div(~attr=Attr.many([toggle_mode, tooltip]), [text(caption)]), - button(Icons.back, prev_slide(~inject, cur_slide, num_slides)), - text(cur_slide_text), - button(Icons.forward, next_slide(~inject, cur_slide, num_slides)), - ] - @ Option.to_list(control), - ); +let menu_icon = { + let attr = + Attr.many( + Attr.[ + clss(["menu-icon"]), + href("https://hazel.org"), + title("Hazel"), + create("target", "_blank"), + ], + ); + a(~attr, [Icons.hazelnut]); }; -let editor_mode_toggle_view = (~inject: Update.t => 'a, ~model: Model.t) => { - switch (model.editors) { - | DebugLoad => failwith("impossible") - | Scratch(_) => - slide_toggle_view(~inject, ~model, ~caption="Scratch", ~control=None) - | School(_) => - let control = - if (SchoolSettings.show_instructor) { - Some( - toggle( - "🎓", - ~tooltip="Toggle Instructor Mode", - model.settings.instructor_mode, - _ => - inject(Set(InstructorMode)) - ), - ); - } else { - None; - }; - slide_toggle_view(~inject, ~model, ~caption="Exercises", ~control); - }; -}; +let history_bar = (ed: Editor.t, ~inject: Update.t => 'a) => [ + button_d( + Icons.undo, + inject(Undo), + ~disabled=!Editor.can_undo(ed), + ~tooltip="Undo", + ), + button_d( + Icons.redo, + inject(Redo), + ~disabled=!Editor.can_redo(ed), + ~tooltip="Redo", + ), +]; -let menu_icon = +let nut_menu = + ( + ~inject: Update.t => 'a, + {statics, dynamics, benchmark, instructor_mode, _}: ModelSettings.t, + ) => [ + menu_icon, div( - ~attr=clss(["menu-icon"]), + ~attr=clss(["menu"]), [ - div( - ~attr=clss(["icon", "menu-icon-inner"]), - [ - a( - ~attr= - Attr.many( - Attr.[ - href("https://hazel.org"), - title("Hazel"), - create("target", "_blank"), - ], - ), - [Icons.hazelnut], - ), - ], + toggle("τ", ~tooltip="Toggle Statics", statics, _ => + inject(Set(Statics)) ), - ], - ); + toggle("𝛿", ~tooltip="Toggle Dynamics", dynamics, _ => + inject(Set(Dynamics)) + ), + toggle("b", ~tooltip="Toggle Performance Benchmark", benchmark, _ => + inject(Set(Benchmark)) + ), + button( + Icons.export, + _ => { + download_editor_state(~instructor_mode); + Virtual_dom.Vdom.Effect.Ignore; + }, + ~tooltip="Export Submission", + ), + file_select_button( + "import-submission", + Icons.import, + file => { + switch (file) { + | None => Virtual_dom.Vdom.Effect.Ignore + | Some(file) => inject(InitImportAll(file)) + } + }, + ~tooltip="Import Submission", + ), + button( + Icons.eye, + _ => inject(Set(SecondaryIcons)), + ~tooltip="Toggle Visible Secondary", + ), + link( + Icons.github, + "https://github.com/hazelgrove/hazel", + ~tooltip="Hazel on GitHub", + ), + ] + @ ( + instructor_mode + ? [ + button( + Icons.sprout, + _ => inject(ExportPersistentData), + ~tooltip="Export Persistent Data", + ), + ] + : [] + ), + ), +]; let top_bar_view = ( ~inject: Update.t => 'a, ~toolbar_buttons: list(Node.t), - ~top_right: option(Node.t)=?, - model: Model.t, - ) => { - let ed = Editors.get_editor(model.editors); - let can_undo = Editor.can_undo(ed); - let can_redo = Editor.can_redo(ed); - let top_left_bar = - div( - ~attr=Attr.id("top-left-bar"), - [ - menu_icon, - div( - ~attr=clss(["menu"]), - [ - toggle("τ", ~tooltip="Toggle Statics", model.settings.statics, _ => - inject(Set(Statics)) - ), - toggle( - "𝛿", ~tooltip="Toggle Dynamics", model.settings.dynamics, _ => - inject(Set(Dynamics)) - ), - toggle( - "b", - ~tooltip="Toggle Performance Benchmark", - model.settings.benchmark, - _ => - inject(Set(Benchmark)) - ), - button( - Icons.export, - _ => { - download_editor_state( - ~instructor_mode=model.settings.instructor_mode, - ); - Virtual_dom.Vdom.Effect.Ignore; - }, - ~tooltip="Export Submission", - ), - file_select_button( - "import-submission", - Icons.import, - file => { - switch (file) { - | None => Virtual_dom.Vdom.Effect.Ignore - | Some(file) => inject(InitImportAll(file)) - } - }, - ~tooltip="Import Submission", - ), - button( - Icons.eye, - _ => inject(Set(SecondaryIcons)), - ~tooltip="Toggle Visible Secondary", - ), - link( - Icons.github, - "https://github.com/hazelgrove/hazel", - ~tooltip="Hazel on GitHub", - ), - ], - ), - button_d( - Icons.undo, - inject(Undo), - ~disabled=!can_undo, - ~tooltip="Undo", - ), - button_d( - Icons.redo, - inject(Redo), - ~disabled=!can_redo, - ~tooltip="Redo", - ), - editor_mode_toggle_view(~inject, ~model), - ] - @ toolbar_buttons, - ); - let top_right_bar = - div(~attr=Attr.id("top-right-bar"), Option.to_list(top_right)); + ~model as {editors, settings, _}: Model.t, + ) => div( ~attr=Attr.id("top-bar"), - [div(~attr=Attr.id("top-bar-content"), [top_left_bar, top_right_bar])], + nut_menu(~inject, settings) + @ [div(~attr=Attr.id("title"), [text("hazel")])] + @ [EditorModeView.view(~inject, ~settings, ~editors)] + @ history_bar(Editors.get_editor(editors), ~inject) + @ toolbar_buttons, ); -}; -let main_ui_view = +let exercises_view = ( ~inject, + ~exercise, { editors, font_metrics, @@ -189,70 +129,54 @@ let main_ui_view = _, } as model: Model.t, ) => { - switch (editors) { - | DebugLoad => [DebugMode.view(~inject)] - | Scratch(idx, slides) => - let toolbar_buttons = - ScratchMode.toolbar_buttons(~inject, List.nth(slides, idx)); - let top_bar_view = top_bar_view(~inject, ~toolbar_buttons, model); - let result_key = ScratchSlide.scratch_key; - let editor = Editors.get_editor(editors); - let result = - settings.dynamics - ? ModelResult.get_simple(ModelResults.lookup(results, result_key)) - : None; + let exercise_mode = + ExerciseMode.mk( + ~settings, + ~exercise, + ~results=settings.dynamics ? Some(results) : None, + ~langDocMessages, + ); + let toolbar_buttons = + ExerciseMode.toolbar_buttons(~inject, ~settings, editors) + @ [ + Grading.GradingReport.view_overall_score(exercise_mode.grading_report), + ]; + [top_bar_view(~inject, ~model, ~toolbar_buttons)] + @ ExerciseMode.view( + ~inject, + ~font_metrics, + ~mousedown, + ~show_backpack_targets, + exercise_mode, + ); +}; - [top_bar_view] - @ ScratchMode.view( - ~inject, - ~font_metrics, - ~mousedown, - ~show_backpack_targets, - ~settings, - ~langDocMessages, - ~editor, - ~result, - ); - | School(_, _, exercise) => - let toolbar_buttons = - SchoolMode.toolbar_buttons(~inject, ~settings, editors); - let results = settings.dynamics ? Some(results) : None; - let school_mode = - SchoolMode.mk(~settings, ~exercise, ~results, ~langDocMessages); - let grading_report = school_mode.grading_report; - let overall_score = - Grading.GradingReport.view_overall_score(grading_report); - let top_bar_view = - top_bar_view( - ~inject, - model, - ~toolbar_buttons, - ~top_right=overall_score, - ); +let slide_view = (~inject, ~model, slide_state) => { + let toolbar_buttons = ScratchMode.toolbar_buttons(~inject, slide_state); + [top_bar_view(~inject, ~toolbar_buttons, ~model)] + @ ScratchMode.view(~inject, ~model); +}; - [top_bar_view] - @ SchoolMode.view( - ~inject, - ~font_metrics, - ~mousedown, - ~show_backpack_targets, - school_mode, - ); +let editors_view = (~inject, model: Model.t) => { + switch (model.editors) { + | DebugLoad => [DebugMode.view(~inject)] + | Scratch(slide_idx, slides) => + slide_view(~inject, ~model, List.nth(slides, slide_idx)) + | Examples(name, slides) => + slide_view(~inject, ~model, List.assoc(name, slides)) + | Exercise(_, _, exercise) => exercises_view(~inject, ~exercise, model) }; }; -let page_id = "page"; - let get_selection = (model: Model.t): string => model.editors |> Editors.get_editor |> Printer.to_string_selection; -let view = (~inject, ~handlers, model: Model.t) => { - let main_ui = main_ui_view(~inject, model); +let view = (~inject, ~handlers, model: Model.t) => div( ~attr= Attr.many( Attr.[ - id(page_id), + id("page"), // safety handler in case mousedown overlay doesn't catch it on_mouseup(_ => inject(Update.Mouseup)), on_blur(_ => { @@ -286,6 +210,5 @@ let view = (~inject, ~handlers, model: Model.t) => { DecUtil.filters, JsUtil.clipboard_shim, ] - @ main_ui, + @ editors_view(~inject, model), ); -}; diff --git a/src/haz3lweb/view/ScratchMode.re b/src/haz3lweb/view/ScratchMode.re index b658082e24..b0edee347d 100644 --- a/src/haz3lweb/view/ScratchMode.re +++ b/src/haz3lweb/view/ScratchMode.re @@ -8,19 +8,29 @@ type state = (Id.t, Editor.t); let view = ( ~inject, - ~font_metrics, - ~show_backpack_targets, - ~mousedown, - ~editor: Editor.t, - ~settings: ModelSettings.t, - ~langDocMessages: LangDocMessages.t, - ~result: ModelResult.simple, + ~model as + { + editors, + font_metrics, + show_backpack_targets, + settings, + mousedown, + langDocMessages, + results, + _, + }: Model.t, ) => { + let editor = Editors.get_editor(editors); let zipper = editor.state.zipper; let unselected = Zipper.unselect_and_zip(zipper); let (term, _) = MakeTerm.go(unselected); let info_map = Statics.mk_map(term); - + let result = + settings.dynamics + ? ModelResult.get_simple( + ModelResults.lookup(results, ScratchSlide.scratch_key), + ) + : None; let color_highlighting: option(ColorSteps.colorMap) = if (langDocMessages.highlight && langDocMessages.show) { Some( @@ -50,7 +60,7 @@ let view = ~result, editor, ); - let ci_view = + let bottom_bar = settings.statics ? [ CursorInspector.view( @@ -62,28 +72,26 @@ let view = ), ] : []; - let bottom_bar = div(~attr=Attr.class_("bottom-bar"), ci_view); - let right_panel = + let sidebar = langDocMessages.show && settings.statics - ? [ - LangDoc.view( + ? LangDoc.view( ~inject, ~font_metrics, ~settings, ~doc=langDocMessages, Indicated.index(zipper), info_map, - ), - ] - : []; + ) + : div([]); [ div( ~attr=Attr.id("main"), - [div(~attr=clss(["editor", "single"]), [editor_view] @ right_panel)], + [div(~attr=clss(["editor", "single"]), [editor_view])], ), - bottom_bar, - ]; + sidebar, + ] + @ bottom_bar; }; let download_slide_state = state => { @@ -125,9 +133,9 @@ let toolbar_buttons = (~inject, state: ScratchSlide.state) => { ~tooltip="Import Scratchpad", ); - // for pasting into files like LanguageRefSlide.ml (note .ml extension) + // for pasting into files like SerializedExamples.ml (note .ml extension) let export_init_button = - SchoolSettings.show_instructor + ExerciseSettings.show_instructor ? Some( Widgets.button( Icons.export, diff --git a/src/haz3lweb/view/Type.re b/src/haz3lweb/view/Type.re index dc42c37f76..12678ea17f 100644 --- a/src/haz3lweb/view/Type.re +++ b/src/haz3lweb/view/Type.re @@ -5,13 +5,18 @@ open Util.Web; let ty_view = (cls: string, s: string): Node.t => div(~attr=clss(["typ-view", cls]), [text(s)]); +let alias_view = (s: string): Node.t => + div(~attr=clss(["typ-alias-view"]), [text(s)]); + let prov_view: Haz3lcore.Typ.type_provenance => Node.t = fun | Internal => div([]) + | Free(name) => + div(~attr=clss(["typ-mod", "free-type-var"]), [text(name)]) | TypeHole => div(~attr=clss(["typ-mod", "type-hole"]), [text("𝜏")]) | SynSwitch => div(~attr=clss(["typ-mod", "syn-switch"]), [text("⇒")]); -let rec view = (ty: Haz3lcore.Typ.t): Node.t => +let rec view_ty = (ty: Haz3lcore.Typ.t): Node.t => //TODO: parens on ops when ambiguous switch (ty) { | Unknown(prov) => @@ -24,19 +29,24 @@ let rec view = (ty: Haz3lcore.Typ.t): Node.t => | String => ty_view("String", "String") | Bool => ty_view("Bool", "Bool") | Var(name) => ty_view("Var", name) + | Rec(x, t) => + div( + ~attr=clss(["typ-view", "Rec"]), + [text("Rec " ++ x ++ ". "), view_ty(t)], + ) | List(t) => div( ~attr=clss(["typ-view", "atom", "List"]), - [text("["), view(t), text("]")], + [text("["), view_ty(t), text("]")], ) | Arrow(t1, t2) => div( ~attr=clss(["typ-view", "Arrow"]), - [view(t1), text("->"), view(t2)], + [view_ty(t1), text(" -> "), view_ty(t2)], ) | Prod([]) => div(~attr=clss(["typ-view", "Prod"]), [text("()")]) | Prod([_]) => - div(~attr=clss(["typ-view", "Prod"]), [text("BadProduct")]) + div(~attr=clss(["typ-view", "Prod"]), [text("Singleton Product")]) | Prod([t0, ...ts]) => div( ~attr=clss(["typ-view", "atom", "Prod"]), @@ -44,12 +54,30 @@ let rec view = (ty: Haz3lcore.Typ.t): Node.t => text("("), div( ~attr=clss(["typ-view", "Prod"]), - [view(t0)] - @ (List.map(t => [text(","), view(t)], ts) |> List.flatten), + [view_ty(t0)] + @ (List.map(t => [text(", "), view_ty(t)], ts) |> List.flatten), ), text(")"), ], ) - | Sum(t1, t2) => - div(~attr=clss(["typ-view", "Sum"]), [view(t1), text("+"), view(t2)]) + | Sum(ts) => + div( + ~attr=clss(["typ-view", "Sum"]), + switch (ts) { + | [] => [text("Nullary Sum")] + | [t0] => [text("+")] @ ctr_view(t0) + | [t0, ...ts] => + let ts_views = + List.map(t => [text(" + ")] @ ctr_view(t), ts) |> List.flatten; + ctr_view(t0) @ ts_views; + }, + ) + } +and ctr_view = ((ctr, typ)) => + switch (typ) { + | None => [text(ctr)] + | Some(typ) => [text(ctr ++ "("), view_ty(typ), text(")")] }; + +let view = (ty: Haz3lcore.Typ.t): Node.t => + div_c("typ-wrapper", [view_ty(ty)]); diff --git a/src/haz3lweb/view/dec/PieceDec.re b/src/haz3lweb/view/dec/PieceDec.re index e6a6a74f69..43c90344e7 100644 --- a/src/haz3lweb/view/dec/PieceDec.re +++ b/src/haz3lweb/view/dec/PieceDec.re @@ -141,13 +141,27 @@ let chunky_shard = ) => { let (nib_l, origin) = { let (id, index) = i; - let (_, mold, shards) = List.find(((id', _, _)) => id' == id, tiles); - (fst(Mold.nib_shapes(~index, mold)), List.assoc(index, shards).origin); + let (_, mold, shards) = + switch (List.find_opt(((id', _, _)) => id' == id, tiles)) { + | Some(x) => x + | None => failwith("chunky_shard 1") + }; + ( + fst(Mold.nib_shapes(~index, mold)), + ListUtil.assoc_err(index, shards, "chunky_shard").origin, + ); }; let (nib_r, last) = { let (id, index) = j; - let (_, mold, shards) = List.find(((id', _, _)) => id' == id, tiles); - (snd(Mold.nib_shapes(~index, mold)), List.assoc(index, shards).last); + let (_, mold, shards) = + switch (List.find_opt(((id', _, _)) => id' == id, tiles)) { + | Some(x) => x + | None => failwith("chunky_shard 2") + }; + ( + snd(Mold.nib_shapes(~index, mold)), + ListUtil.assoc_err(index, shards, "chunky_shard").last, + ); }; let indent_col = Measured.Rows.find(origin.row, rows).indent; let max_col = diff --git a/src/haz3lweb/view/dhcode/DHCode.re b/src/haz3lweb/view/dhcode/DHCode.re index ed242dc337..394cff2f51 100644 --- a/src/haz3lweb/view/dhcode/DHCode.re +++ b/src/haz3lweb/view/dhcode/DHCode.re @@ -55,22 +55,28 @@ let view_of_layout = ds, ) | CastDecoration => ([with_cls("CastDecoration", txt)], ds) + | OperationError(InvalidIntOfString) => ( + [with_cls("OperationError", txt)], + ds, + ) + | OperationError(InvalidFloatOfString) => ( + [with_cls("OperationError", txt)], + ds, + ) | OperationError(DivideByZero) => ( - [with_cls("DivideByZero", txt)], + [with_cls("OperationError", txt)], ds, ) | OperationError(NegativeExponent) => ( - [with_cls("NegativeExponent", txt)], + [with_cls("OperationError", txt)], ds, ) | OperationError(OutOfFuel) => ( - //TODO: custom class - [with_cls("DivideByZero", txt)], + [with_cls("OperationError", txt)], ds, ) | OperationError(InvalidProjection) => ( - //TODO: custom class - [with_cls("DivideByZero", txt)], + [with_cls("OperationError", txt)], ds, ) | VarHole(_) => ([with_cls("InVarHole", txt)], ds) @@ -190,21 +196,27 @@ let view_of_layout_tylr = ) | CastDecoration => ([with_cls("CastDecoration", txt)], ds) | OperationError(DivideByZero) => ( - [with_cls("DivideByZero", txt)], + [with_cls("OperationError", txt)], + ds, + ) + | OperationError(InvalidIntOfString) => ( + [with_cls("OperationError", txt)], + ds, + ) + | OperationError(InvalidFloatOfString) => ( + [with_cls("OperationError", txt)], ds, ) | OperationError(NegativeExponent) => ( - [with_cls("NegativeExponent", txt)], + [with_cls("OperationError", txt)], ds, ) | OperationError(OutOfFuel) => ( - //TODO: custom class - [with_cls("DivideByZero", txt)], + [with_cls("OperationError", txt)], ds, ) | OperationError(InvalidProjection) => ( - //TODO: custom class - [with_cls("DivideByZero", txt)], + [with_cls("OperationError", txt)], ds, ) | VarHole(_) => ([with_cls("InVarHole", txt)], ds) diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index b648a0a2ed..ad54cad1a3 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -51,10 +51,9 @@ let rec precedence = (~show_casts: bool, d: DHExp.t) => { | FloatLit(_) | StringLit(_) | ListLit(_) - | Inj(_) | Prj(_) | EmptyHole(_) - | Tag(_) + | Constructor(_) | FailedCast(_) | InvalidOperation(_) | Fun(_) @@ -207,31 +206,23 @@ let rec mk = | InconsistentBranches(u, i, Case(dscrut, drs, _)) => go_case(dscrut, drs) |> annot(DHAnnot.InconsistentBranches((u, i))) | BoundVar(x) => text(x) - | Tag(name) => DHDoc_common.mk_TagLit(name) + | Constructor(name) => DHDoc_common.mk_ConstructorLit(name) | BoolLit(b) => DHDoc_common.mk_BoolLit(b) | IntLit(n) => DHDoc_common.mk_IntLit(n) | FloatLit(f) => DHDoc_common.mk_FloatLit(f) - | StringLit(s) => DHDoc_common.mk_StringLit(s) + | StringLit(s) => DHDoc_common.mk_StringLit("\"" ++ s ++ "\"") | TestLit(_) => Doc.text(ExpandingKeyword.to_string(Test)) | Sequence(d1, d2) => let (doc1, doc2) = (go'(d1), go'(d2)); DHDoc_common.mk_Sequence(mk_cast(doc1), mk_cast(doc2)); - | ListLit(_, _, StandardErrStatus(_), _, d_list) => + | ListLit(_, _, _, d_list) => let ol = d_list |> List.map(go') |> List.map(mk_cast); DHDoc_common.mk_ListLit(ol); - | ListLit(u, i, InconsistentBranches(_, _), _, d_list) => - let ol = d_list |> List.map(go') |> List.map(mk_cast); - DHDoc_common.mk_ListLit(ol) - |> annot(DHAnnot.InconsistentBranches((u, i))); - | Inj(_, inj_side, d) => - let child = (~enforce_inline) => mk_cast(go(~enforce_inline, d)); - DHDoc_common.mk_Inj( - inj_side, - child |> DHDoc_common.pad_child(~enforce_inline), - ); | Ap(d1, d2) => - let (doc1, doc2) = - mk_left_associative_operands(DHDoc_common.precedence_Ap, d1, d2); + let (doc1, doc2) = ( + go'(~parenthesize=precedence(d1) > DHDoc_common.precedence_Ap, d1), + go'(~parenthesize=false, d2), + ); DHDoc_common.mk_Ap(mk_cast(doc1), mk_cast(doc2)); | ApBuiltin(ident, args) => switch (args) { diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re index 832cc58407..c27aa21b07 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re @@ -8,14 +8,14 @@ let precedence = (dp: DHPat.t) => | Wild | ExpandingKeyword(_) | InvalidText(_) + | BadConstructor(_) | Var(_) | IntLit(_) | FloatLit(_) | BoolLit(_) | StringLit(_) - | Inj(_) | ListLit(_) - | Tag(_) => DHDoc_common.precedence_const + | Constructor(_) => DHDoc_common.precedence_const | Tuple(_) => DHDoc_common.precedence_Comma | Cons(_) => DHDoc_common.precedence_Cons | Ap(_) => DHDoc_common.precedence_Ap @@ -40,18 +40,14 @@ let rec mk = | ExpandingKeyword(u, i, k) => DHDoc_common.mk_ExpandingKeyword((u, i), k) | InvalidText(u, i, t) => DHDoc_common.mk_InvalidText(t, (u, i)) + | BadConstructor(u, i, t) => DHDoc_common.mk_InvalidText(t, (u, i)) | Var(x) => Doc.text(x) | Wild => DHDoc_common.Delim.wild - | Tag(name) => DHDoc_common.mk_TagLit(name) + | Constructor(name) => DHDoc_common.mk_ConstructorLit(name) | IntLit(n) => DHDoc_common.mk_IntLit(n) | FloatLit(f) => DHDoc_common.mk_FloatLit(f) | BoolLit(b) => DHDoc_common.mk_BoolLit(b) | StringLit(s) => DHDoc_common.mk_StringLit(s) - | Inj(inj_side, dp) => - DHDoc_common.mk_Inj( - inj_side, - mk(dp) |> DHDoc_common.pad_child(~enforce_inline), - ) | ListLit(_, d_list) => let ol = List.map(mk', d_list); DHDoc_common.mk_ListLit(ol); diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Util.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Util.re new file mode 100644 index 0000000000..1923f9c821 --- /dev/null +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Util.re @@ -0,0 +1,114 @@ +open Util; +open Haz3lcore; + +module Doc = Pretty.Doc; + +[@deriving sexp] +type t = Doc.t(DHAnnot.t); + +type formattable_child = (~enforce_inline: bool) => t; + +let precedence_const = DHDoc_common.precedence_const; +let precedence_Ap = DHDoc_common.precedence_Ap; +let precedence_Times = DHDoc_common.precedence_Times; +let precedence_Divide = DHDoc_common.precedence_Divide; +let precedence_Plus = DHDoc_common.precedence_Plus; +let precedence_Minus = DHDoc_common.precedence_Minus; +let precedence_Cons = DHDoc_common.precedence_Cons; +let precedence_Equals = DHDoc_common.precedence_Equals; +let precedence_LessThan = DHDoc_common.precedence_LessThan; +let precedence_GreaterThan = DHDoc_common.precedence_GreaterThan; +let precedence_And = DHDoc_common.precedence_And; +let precedence_Or = DHDoc_common.precedence_Or; +let precedence_Comma = DHDoc_common.precedence_Comma; +let precedence_max = DHDoc_common.precedence_max; + +let pad_child = + ( + ~inline_padding as (l, r)=(Doc.empty(), Doc.empty()), + ~enforce_inline: bool, + child: formattable_child, + ) + : t => { + let inline_choice = Doc.hcats([l, child(~enforce_inline=true), r]); + let para_choice = + Doc.( + hcats([ + linebreak(), + indent_and_align(child(~enforce_inline=false)), + linebreak(), + ]) + ); + enforce_inline ? inline_choice : Doc.choice(inline_choice, para_choice); +}; + +module Delim = { + let mk = (delim_text: string): t => + Doc.text(delim_text) |> Doc.annot(DHAnnot.Delim); + + let empty_hole = ((u, i): HoleInstance.t): t => { + let lbl = + StringUtil.cat([string_of_int(u + 1), ":", string_of_int(i + 1)]); + Doc.text(lbl) + |> Doc.annot(DHAnnot.HoleLabel) + |> Doc.annot(DHAnnot.Delim); + }; + + let list_nil = mk("[]"); + let triv = mk("()"); + let wild = mk("_"); + + let open_Parenthesized = mk("("); + let close_Parenthesized = mk(")"); + + let sym_Fun = mk("fun"); + let colon_Lam = mk(":"); + let open_Lam = mk(".{"); + let close_Lam = mk("}"); + + let fix_FixF = mk("fix"); + let colon_FixF = mk(":"); + let open_FixF = mk(".{"); + let close_FixF = mk("}"); + let open_Case = mk("case"); + let close_Case = mk("end"); + + let bar_Rule = mk("|"); + let arrow_Rule = mk("=>"); + + let open_Cast = mk("<"); + let arrow_Cast = mk(Unicode.castArrowSym); + let close_Cast = mk(">"); + + let open_FailedCast = open_Cast |> Doc.annot(DHAnnot.FailedCastDelim); + let arrow_FailedCast = + mk(Unicode.castArrowSym) |> Doc.annot(DHAnnot.FailedCastDelim); + let close_FailedCast = close_Cast |> Doc.annot(DHAnnot.FailedCastDelim); +}; + +let mk_EmptyHole = (~selected=false, (u, i)) => + Delim.empty_hole((u, i)) + |> Doc.annot(DHAnnot.EmptyHole(selected, (u, i))); + +let mk_Keyword = (u, i, k) => + Doc.text(ExpandingKeyword.to_string(k)) + |> Doc.annot(DHAnnot.VarHole(ExpandingKeyword(k), (u, i))); + +let mk_IntLit = n => Doc.text(string_of_int(n)); + +let mk_FloatLit = (f: float) => + switch (f < 0., Float.is_infinite(f), Float.is_nan(f)) { + | (false, true, _) => Doc.text("Inf") + /* TODO: NegInf is temporarily introduced until unary minus is introduced to Hazel */ + | (true, true, _) => Doc.text("NegInf") + | (_, _, true) => Doc.text("NaN") + | _ => Doc.text(string_of_float(f)) + }; + +let mk_BoolLit = b => Doc.text(string_of_bool(b)); + +let mk_Cons = (hd, tl) => Doc.(hcats([hd, text("::"), tl])); + +let mk_Pair = (doc1, doc2) => Doc.(hcats([doc1, text(", "), doc2])); + +let mk_Ap = (doc1, doc2) => Doc.hseps([doc1, doc2]); diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re index 03ddd3dfe1..345eccc722 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re @@ -1,5 +1,4 @@ module Doc = Pretty.Doc; -open Util; open Haz3lcore; open DHDoc; @@ -71,10 +70,6 @@ module Delim = { let open_FixF = mk(".{"); let close_FixF = mk("}"); - let open_Inj = (inj_side: InjSide.t) => - mk(StringUtil.cat([InjSide.to_string(inj_side), "("])); - let close_Inj = mk(")"); - let projection_dot = mk("."); let open_Case = mk("case"); @@ -121,32 +116,24 @@ let mk_FloatLit = (f: float) => let mk_BoolLit = b => Doc.text(string_of_bool(b)); -let mk_TagLit = Doc.text; - -let mk_Inj = (inj_side, padded_child) => - Doc.hcats([Delim.open_Inj(inj_side), padded_child, Delim.close_Inj]); +let mk_ConstructorLit = Doc.text; let mk_Cons = (hd, tl) => Doc.(hcats([hd, text("::"), tl])); -let rec mk_comma_seq = (ld, rd, l, ol) => - switch (l) { - | [] => - if (l == ol) { - Doc.(hcats([text(ld), text(rd)])); - } else { - Doc.(hcats([text(rd)])); - } - | [hd, ...tl] => - if (l == ol) { - Doc.(hcats([text(ld), hd, mk_comma_seq(ld, rd, tl, ol)])); - } else { - Doc.(hcats([text(", "), hd, mk_comma_seq(ld, rd, tl, ol)])); - } +let mk_comma_seq = (ld, rd, l) => { + let rec mk_comma_seq_inner = l => { + switch (l) { + | [] => [] + | [hd] => [hd] + | [hd, ...tl] => Doc.([hd, text(", ")] @ mk_comma_seq_inner(tl)) + }; }; + Doc.(hcats([text(ld)] @ mk_comma_seq_inner(l) @ [text(rd)])); +}; -let mk_ListLit = l => mk_comma_seq("[", "]", l, l); +let mk_ListLit = l => mk_comma_seq("[", "]", l); -let mk_Tuple = elts => mk_comma_seq("(", ")", elts, elts); +let mk_Tuple = elts => mk_comma_seq("", "", elts); let mk_Ap = (doc1, doc2) => Doc.(hcats([doc1, text("("), doc2, text(")")])); diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei index 0faefff5d8..0763fdb608 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei @@ -48,9 +48,6 @@ module Delim: { let open_FixF: DHDoc.t; let close_FixF: DHDoc.t; - let open_Inj: InjSide.t => DHDoc.t; - let close_Inj: DHDoc.t; - let open_Case: DHDoc.t; let close_Case: DHDoc.t; @@ -84,12 +81,10 @@ let mk_FloatLit: float => Pretty.Doc.t('a); let mk_BoolLit: bool => Pretty.Doc.t('a); -let mk_TagLit: string => Pretty.Doc.t('a); +let mk_ConstructorLit: string => Pretty.Doc.t('a); let mk_StringLit: string => Pretty.Doc.t('a); -let mk_Inj: (InjSide.t, Pretty.Doc.t(DHAnnot.t)) => Pretty.Doc.t(DHAnnot.t); - let mk_Cons: (Pretty.Doc.t('a), Pretty.Doc.t('a)) => Pretty.Doc.t('a); let mk_ListLit: list(Pretty.Doc.t('a)) => Pretty.Doc.t('a); diff --git a/src/haz3lweb/view/dhcode/layout/HTypDoc.re b/src/haz3lweb/view/dhcode/layout/HTypDoc.re index d2f561afd2..b245fa0167 100644 --- a/src/haz3lweb/view/dhcode/layout/HTypDoc.re +++ b/src/haz3lweb/view/dhcode/layout/HTypDoc.re @@ -105,17 +105,37 @@ let rec mk = (~parenthesize=false, ~enforce_inline: bool, ty: Typ.t): t => { ) |> hcats; (center, true); - | Sum(ty1, ty2) => - let (d1, d2) = - mk_right_associative_operands(Typ.precedence_Sum, ty1, ty2); - ( + | Rec(x, ty) => ( hcats([ - d1, - hcats([choices([linebreak(), space()]), text("| ")]), - d2, + text("Rec " ++ x ++ ".{"), + ( + (~enforce_inline) => + annot(HTypAnnot.Step(0), mk(~enforce_inline, ty)) + ) + |> pad_child(~enforce_inline), + mk_delim("}"), ]), parenthesize, - ); + ) + | Sum(sum_map) => + let center = + List.mapi( + (i, (ctr, ty)) => + switch (ty) { + | None => annot(HTypAnnot.Step(i + 1), text(ctr)) + | Some(ty) => + annot( + HTypAnnot.Step(i + 1), + hcats([text(ctr ++ "("), mk'(ty), text(")")]), + ) + }, + sum_map, + ) + |> ListUtil.join( + hcats([text(" +"), choices([linebreak(), space()])]), + ) + |> hcats; + (center, true); }; let doc = annot(HTypAnnot.Term, doc); parenthesize ? Doc.hcats([mk_delim("("), doc, mk_delim(")")]) : doc; diff --git a/src/haz3lweb/www/index.html b/src/haz3lweb/www/index.html index 831a967f44..cd9cc8aa2a 100644 --- a/src/haz3lweb/www/index.html +++ b/src/haz3lweb/www/index.html @@ -12,13 +12,13 @@ -
-
-
- - +
+
+
+ +
-

loading

+ loading
diff --git a/src/haz3lweb/www/style.css b/src/haz3lweb/www/style.css index a8396d3c60..3c126149e6 100644 --- a/src/haz3lweb/www/style.css +++ b/src/haz3lweb/www/style.css @@ -57,7 +57,6 @@ --top-bar-text: #a79f89; --test-panel-bkg: #f8ebc6; - --delim-color: #586e75; --code-emphasis: #ce9600; --err-color: red; @@ -72,9 +71,24 @@ /* SORT COLORS */ + --nul-text-color: red; + --nul-off-color: var(--nul-text-color); + --nul-delim-color: var(--nul-text-color); + --nul-shadow-color: var(--nul-text-color); + --nul-bg-color: #ffacac; + --nul-bg-off-color: var(--nul-bg-color); + + --any-text-color: var(--nul-text-color); + --any-off-color: var(--nul-off-color); + --any-delim-color: var(--nul-delim-color); + --any-shadow-color: var(--nul-shadow-color); + --any-bg-color: var(--nul-bg-color); + --any-bg-off-color: var(--nul-bg-off-color); + --exp-text-color: var(--light-text-color); - --exp-shadow-color: #c4b599; --exp-off-color: #b1a47f; + --exp-delim-color: var(--light-text-color); + --exp-shadow-color: #c4b599; --exp-bg-color: #ebdfc5; --exp-bg-off-color: #feddb3; @@ -85,28 +99,26 @@ --pat-bg-color: #b2e8ff; --pat-bg-off-color: #d7f3ff; + --tpat-text-color: #16c8dc; + --tpat-off-color: #13d2d2; + --tpat-delim-color: #a2fbf9; + --tpat-shadow-color: var(--pat-off-color); + --tpat-bg-color: #b2fbff; + --tpat-bg-off-color: #d7fff7; + --typ-text-color: #772cff; - /*#24ae62;*/ --typ-off-color: #975dff; - /*#7fc97f;*/ --typ-delim-color: #cfb5ff; - /*#aee5c6;*/ --typ-shadow-color: var(--typ-off-color); --typ-bg-color: #f2ccff; - /*#bdf5c4;*/ --typ-bg-off-color: #f9e8ff; - --rul-text-color: #a6b29a; - /*#24ae62;*/ - --rul-off-color: #bcc29b; - /*#7fc97f;*/ - --rul-bg-color: #e7ead6; - /*#bdf5c4;*/ - --rul-shadow-color: var(--rul-off-color); - --rul-delim-color: #aee5c6; - - --nul-bg-color: #ffacac; - --nul-shadow-color: #690000; + --rul-text-color: var(--exp-text-color); + --rul-off-color: var(--exp-off-color); + --rul-delim-color: #ccc2af; + --rul-shadow-color: var(--exp-shadow-color); + --rul-bg-color: var(--exp-bg-color); + --rul-bg-off-color: var(--exp-bg-off-color); /* END SORT COLORS */ @@ -138,6 +150,7 @@ --caret-position-z: 13; --current-caret-pos-z: 15; --caret-z: 14; + --docs-highlight-z:8; --type-inspector-z: 14; --top-bar-z: 15; @@ -234,18 +247,69 @@ svg { } } -/* PAGE */ +body { + /* Default UI font */ + font-family: 'Helvetica Neue'; +} -#page { +/* LOADING: This shows before the app is loaded */ + +#container { + position: fixed; + top: 0; + left: 0; height: 100vh; width: 100vw; - position: fixed; - top: 0%; - left: 0%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; background-color: var(--light-page-color); color: var(--light-text-color); + font-size: 1.75em; + font-style: italic; +} + +#container .loading { display: flex; flex-direction: column; + align-items: center; +} + +#container .loading .spinner { + display: flex; + align-items: center; + justify-content: center; +} + +#container .loading .spinner .spinner-nut { + position: fixed; + transform: scale(0.25); + filter: invert(); +} + +/* PAGE */ + +#page { + position: fixed; + top: 0; + left: 0; + height: 100vh; + width: 100vw; + display: grid; + grid-template: 2.75em minmax(0, 1fr) 2em / 1fr fit-content(16em); + background-color: var(--light-page-color); + color: var(--light-text-color); +} + +#main { + grid-row: 2; + grid-column: 1 / span 1; + overflow: auto; +} + +select { + cursor: pointer; } #font-specimen { @@ -256,7 +320,6 @@ svg { #font-specimen, .code-container, .DHCode, -.cursor-inspector, .context-entry, .typ-view { line-height: var(--line-height); @@ -266,10 +329,6 @@ svg { font-size: 13pt; } -body { - font-family: 'Helvetica Neue'; -} - #editor-mode, .cell-caption, .cell-prompt, @@ -283,85 +342,76 @@ body { /* TOP BAR */ #top-bar { - box-sizing: border-box; - width: 100%; - min-width: fit-content; - padding: 0.75em; - padding-left: 3.5em; - /* to accommodate Hazel icon */ + grid-row: 1 / span 1; + grid-column: 1 / span 2; + z-index: var(--top-bar-z); display: flex; - background-color: var(--light-page-color); + align-items: center; + gap: 1em; + border-bottom: 0.6px solid #c7b480; } -#top-bar-content { - display: flex; - justify-content: space-between; - width: 100%; - max-width: 68vw; +#top-bar #title { + color: #a69460; } -#top-left-bar { +#top-bar .menu { display: flex; + transform-origin: top; + transform: scaleY(0); + transition: transform 0.07s ease; + position: fixed; + top: 2.75em; + left: 0; + width: 2.75em; + padding-top: 1em; + padding-bottom: 1em; gap: 1em; + flex-direction: column; + justify-content: center; + align-items: center; + background-color: #a69461; } -#top-right-bar { +#top-bar .menu:hover, +#top-bar .menu-icon:hover+.menu { + transform: scaleY(1); display: flex; - justify-content: right; - gap: 1em; + border-radius: 0 0 1.3em 0; } #top-bar .menu-icon { width: 2.75em; height: 2.75em; - position: fixed; - top: 0; - left: 0; display: flex; justify-content: center; align-items: center; background-color: var(--top_bar_icon_fill); cursor: pointer; + color: white; + /*border-radius: 0 0 1.1em 0;*/ + transition: all 0.1s ease-in; } -#top-bar .menu:hover, -#top-bar .menu-icon:hover+.menu { - transform: scaleY(1); - display: flex; +#top-bar .menu-icon:hover { + border-radius: 0; } -#top-bar .menu { - /*display: none;*/ - display: flex; - transform-origin: top; - transform: scaleY(0); - transition: transform 0.07s ease; - position: fixed; - top: 2.75em; - left: 0; - width: 2.75em; - padding-top: 1em; - padding-bottom: 1em; - gap: 1em; - flex-direction: column; - justify-content: center; - align-items: center; - background-color: #a69461; +#top-bar .menu-icon svg { + fill: var(--light-page-color); } -#top-bar .menu-icon:hover .menu-icon-inner { +#top-bar .menu-icon:hover svg, +#top-bar .menu-icon svg:hover { + height: 1.6em; + width: 1.6em; animation: jello 0.6s ease 0s 1 normal forwards; } -#top-bar .icon:hover svg, -.menu-icon:hover .menu-icon-inner svg { +#top-bar .icon:hover svg { transform: scale(130%); } -#top-bar .menu-icon-inner.icon svg { - fill: var(--light-page-color); -} - #top-bar .menu .icon:hover svg { animation: wobble 0.6s ease 0s 1 normal forwards; filter: brightness(1.2); @@ -391,7 +441,6 @@ body { } #top-bar #editor-mode { - font-size: 0.7em; color: #fdf6e3; display: flex; align-items: center; @@ -399,9 +448,9 @@ body { cursor: pointer; user-select: none; background-color: #c7b480; - border-radius: 1em; - padding: 0.2em 0.5em 0.2em 0.5em; + border-radius: 0.4em 1em 1em 0.4em; transition: width 0.1s ease-in; + font-size: 0.7em; } #top-bar #editor-mode .icon { @@ -411,6 +460,10 @@ body { align-items: center; } +#top-bar #editor-mode .icon:hover { + filter: brightness(0.45) sepia(1) hue-rotate(15deg) saturate(50); +} + #top-bar #editor-mode .icon svg { fill: var(--light-page-color); } @@ -419,24 +472,45 @@ body { background-color: #99854a; } +#top-bar #editor-mode .mode-name{ + border-radius: 0.4em 1em 1em 0.4em; + padding: 0 0.5em 0 0.5em; + background-color: #a69460; + border-bottom: 0.7px solid #ebe0c2; + color: #fdf6e3; +} + +#top-bar #editor-mode .mode-name select:hover, +#top-bar #editor-mode select:hover { + color: #fad56f; +} #top-bar #editor-mode .icon svg { - width: 15px; height: 15px; } -#top-bar #editor-mode:hover { - transform: scale(110%); -} - -#editor-mode .toggle-switch.active .toggle-knob { +#top-bar #editor-mode .toggle-switch.active .toggle-knob { filter: grayscale(1) sepia(1); } -#editor-mode .toggle-switch .toggle-knob { +#top-bar #editor-mode .toggle-switch .toggle-knob { filter: grayscale(1) sepia(1) opacity(0.3); } +#top-bar #editor-mode select { + background-color: #0000; + border: none; + color: white; + font-size: 1em; + height: 1.7em; +} + +#top-bar #editor-mode select:focus-visible { + background-color: #0000 !important; + color: #fad56f !important; + outline: none; +} + /* END TOP BAR */ .editor { @@ -456,8 +530,7 @@ body { } .editor.single { - padding-top: 2em; - padding-left: 2em; + padding: 2em 2em 4em 2em; } #mousedown-overlay { @@ -474,14 +547,17 @@ body { position: relative; } +.editor .code-container { + cursor: text; +} + .code { /*white-space: nowrap;*/ } .cell-container { width: fit-content; - min-width: 70vw; - max-width: 70vw; + /*min-width: 24em;*/ } .cell-container .cell-item:first-child { @@ -501,7 +577,6 @@ body { .title-cell .title-text { font-size: 1.5rem; - font-family: "Helvetica Neue", sans-serif; font-weight: bold; color: var(--light-text-color); } @@ -523,8 +598,6 @@ body { border-left: 1px solid var(--top_bar_icon_fill); } -.cell.school {} - .cell.selected { border-left: 1px solid var(--cell-selected-accent); background-color: #fffcf3; @@ -642,58 +715,10 @@ body { vector-effect: non-scaling-stroke; } -.child-line.Exp { - stroke: var(--exp-shadow-color); -} - -.child-line.Pat { - stroke: var(--pat-shadow-color); -} - -.child-line.Typ { - stroke: var(--typ-shadow-color); -} - -.child-line.Rul { - stroke: var(--rul-shadow-color); -} - -/*TODO(andrew): clean up text classes*/ -.code .text-Pat { - color: var(--pat-text-color); -} - -.code .delim.text-Pat { - color: var(--pat-delim-color); - font-weight: bold; -} - -.code .text-Exp { - color: var(--exp-text-color); -} - -.code .text-Typ { - color: var(--typ-text-color); -} - -.code .delim.text-Typ { - color: var(--typ-delim-color); +.code .delim { font-weight: bold; } -.code .text-Rul { - color: var(--rul-text-color); -} - -.code .delim.text-Rul { - color: var(--rul-delim-color); - font-weight: bold; -} - -/* TOKEN COLORS */ - -.code .token.mono {} - .code .token.mono-string-lit { color: var(--string-lit-color); } @@ -703,7 +728,7 @@ body { } .code .token.delim { - color: var(--delim-color); + color: var(--exp-delim-color); font-weight: bold; } @@ -734,205 +759,174 @@ svg.tile-selected { filter: url(#raised-drop-shadow-Nul) !important; } - -.tile-path.Exp { - filter: url(#drop-shadow-Exp); -} - -.tile-path.Exp.indicated { - fill: var(--exp-bg-color); -} - -.tile-path.Exp.indicated-caret { - fill: var(--exp-bg-off-color); -} - -#drop-shadow-Exp .tile-drop-shadow, -#raised-drop-shadow-Exp .tile-drop-shadow { - flood-color: var(--exp-shadow-color); -} - -.tile-path.Pat { - /*stroke: var(--pat-text-color);*/ - filter: url(#drop-shadow-Pat); -} - -.tile-path.Pat.indicated { - fill: var(--pat-bg-off-color); -} - -.tile-path.Pat.indicated-caret { - fill: var(--pat-bg-color); -} - -.tile-path.Pat.raised { - filter: url(#raised-drop-shadow-Pat); -} - -#drop-shadow-Pat .tile-drop-shadow, -#raised-drop-shadow-Pat .tile-drop-shadow { - flood-color: var(--pat-shadow-color); -} - -.tile-path.Typ { - filter: url(#drop-shadow-Typ); -} - -.tile-path.Typ.indicated { - fill: var(--typ-bg-off-color); -} - -.tile-path.Typ.indicated-caret { - fill: var(--typ-bg-color); - /* TODO(andrew) */ -} - -.tile-path.Typ.raised { - filter: url(#raised-drop-shadow-Typ); -} - -#drop-shadow-Typ .tile-drop-shadow, -#raised-drop-shadow-Typ .tile-drop-shadow { - flood-color: var(--typ-shadow-color); -} - -.tile-path.Rul { - filter: url(#drop-shadow-Rul); -} - -.tile-path.Rul.indicated { - fill: var(--rul-bg-color); -} - -.tile-path.Rul.indicated-caret { - fill: var(--rul-bg-color); -} - -.tile-path.Rul.raised { - filter: url(#raised-drop-shadow-Rul); +.caret-position-path { + vector-effect: non-scaling-stroke; + stroke-width: 0.1px; } -#drop-shadow-Rul .tile-drop-shadow, -#raised-drop-shadow-Rul .tile-drop-shadow { - flood-color: var(--rul-shadow-color); +.caret-position-path.outer-cousin { + stroke: var(--bar-color); + fill: var(--bar-color); } -.tile-path.Nul { - filter: url(#drop-shadow-Nul); +@property --color { + syntax: ''; + /* <- defined as type number for the transition to work */ + initial-value: #000000; + inherits: false; } -.tile-path.Nul.indicated { - fill: var(--nul-bg-color); +#caret-bar { + position: absolute; + height: 100%; + top: 0; + left: 0; + width: 2px; + transform: translate(-50%, 0%); + z-index: var(--caret-bar-z); } -.tile-path.Nul.indicated-caret { - fill: var(--nul-bg-color); -} +/* TOKEN COLORS */ -.tile-path.Nul.raised { - filter: url(#raised-drop-shadow-Nul); +.code .text-Nul { color: var(--nul-text-color); } +.code .text-Any { color: var(--any-text-color); } +.code .text-Exp { color: var(--exp-text-color); } +.code .text-Pat { color: var(--pat-text-color); } +.code .text-Typ { color: var(--typ-text-color); } +.code .text-Rul { color: var(--rul-text-color); } +.code .text-TPat { color: var(--tpat-text-color); } + +.code .delim.text-Nul { color: var(--nul-delim-color); } +.code .delim.text-Any { color: var(--any-delim-color); } +.code .delim.text-Exp { color: var(--exp-delim-color); } +.code .delim.text-Pat { color: var(--pat-delim-color); } +.code .delim.text-Typ { color: var(--typ-delim-color); } +.code .delim.text-Rul { color: var(--rul-delim-color); } +.code .delim.text-TPat { color: var(--tpat-delim-color); } + +.tile-path.Nul { filter: url(#drop-shadow-Nul); } +.tile-path.Any { filter: url(#drop-shadow-Any); } +.tile-path.Exp { filter: url(#drop-shadow-Exp); } +.tile-path.Pat { filter: url(#drop-shadow-Pat); } +.tile-path.Typ { filter: url(#drop-shadow-Typ); } +.tile-path.Rul { filter: url(#drop-shadow-Rul); } +.tile-path.TPat { filter: url(#drop-shadow-TPat); } + +.tile-path.Nul.indicated { fill: var(--nul-bg-color); } +.tile-path.Any.indicated { fill: var(--any-bg-color); } +.tile-path.Exp.indicated { fill: var(--exp-bg-color); } +.tile-path.Pat.indicated { fill: var(--pat-bg-off-color); } +.tile-path.Typ.indicated { fill: var(--typ-bg-off-color); } +.tile-path.Rul.indicated { fill: var(--rul-bg-color); } +.tile-path.TPat.indicated { fill: var(--tpat-bg-off-color); } + +.tile-path.Nul.indicated-caret { fill: var(--nul-bg-color); } +.tile-path.Any.indicated-caret { fill: var(--any-bg-color); } +.tile-path.Exp.indicated-caret { fill: var(--exp-bg-off-color); } +.tile-path.Pat.indicated-caret { fill: var(--pat-bg-color); } +.tile-path.Typ.indicated-caret { fill: var(--typ-bg-color); } +.tile-path.Rul.indicated-caret { fill: var(--rul-bg-color); } +.tile-path.TPat.indicated-caret { fill: var(--tpat-bg-color); } + +.tile-path.Nul.raised { filter: url(#raised-drop-shadow-Nul); } +.tile-path.Any.raised { filter: url(#raised-drop-shadow-Any); } +.tile-path.Exp.raised { filter: url(#raised-drop-shadow-Exp); } +.tile-path.Pat.raised { filter: url(#raised-drop-shadow-Pat); } +.tile-path.Typ.raised { filter: url(#raised-drop-shadow-Typ); } +.tile-path.Rul.raised { filter: url(#raised-drop-shadow-Rul); } +.tile-path.TPat.raised { filter: url(#raised-drop-shadow-TPat); } + +.child-line.Nul { stroke: var(--nul-shadow-color); } +.child-line.Any { stroke: var(--any-shadow-color); } +.child-line.Exp { stroke: var(--exp-shadow-color); } +.child-line.Pat { stroke: var(--pat-shadow-color); } +.child-line.Typ { stroke: var(--typ-shadow-color); } +.child-line.Rul { stroke: var(--rul-shadow-color); } +.child-line.TPat { stroke: var(--tpat-shadow-color); } + +#drop-shadow-Nul .tile-drop-shadow { flood-color: var(--nul-shadow-color); } +#drop-shadow-Any .tile-drop-shadow { flood-color: var(--any-shadow-color); } +#drop-shadow-Exp .tile-drop-shadow { flood-color: var(--exp-shadow-color); } +#drop-shadow-Pat .tile-drop-shadow { flood-color: var(--pat-shadow-color); } +#drop-shadow-Typ .tile-drop-shadow { flood-color: var(--typ-shadow-color); } +#drop-shadow-Rul .tile-drop-shadow { flood-color: var(--rul-shadow-color); } +#drop-shadow-TPat .tile-drop-shadow { flood-color: var(--tpat-shadow-color); } + +#raised-drop-shadow-Nul .tile-drop-shadow { flood-color: var(--nul-shadow-color); } +#raised-drop-shadow-Any .tile-drop-shadow { flood-color: var(--any-shadow-color); } +#raised-drop-shadow-Exp .tile-drop-shadow { flood-color: var(--exp-shadow-color); } +#raised-drop-shadow-Pat .tile-drop-shadow { flood-color: var(--pat-shadow-color); } +#raised-drop-shadow-Typ .tile-drop-shadow { flood-color: var(--typ-shadow-color); } +#raised-drop-shadow-Rul .tile-drop-shadow { flood-color: var(--rul-shadow-color); } +#raised-drop-shadow-TPat .tile-drop-shadow { flood-color: var(--tpat-shadow-color); } + +/* OTHER SORT COLORS */ + +.ci-header-Nul { + background-color: var(--nul-bg-color); + color: var(--nul-off-color); +} +.ci-header-Any { + background-color: var(--any-bg-color); + color: var(--any-off-color); +} +.ci-header-Exp { + background-color: var(--exp-bg-color); + color: var(--exp-off-color); } - -#drop-shadow-Nul .tile-drop-shadow, -#raised-drop-shadow-Nul .tile-drop-shadow { - flood-color: var(--nul-shadow-color); +.ci-header-Pat { + background-color: var(--pat-bg-color); + color: var(--pat-off-color); } - -.caret-position-path { - vector-effect: non-scaling-stroke; - stroke-width: 0.1px; +.ci-header-Typ { + background-color: var(--typ-bg-color); + color: var(--typ-off-color); } - -.caret-position-path.outer-cousin { - stroke: var(--bar-color); - fill: var(--bar-color); +.ci-header-Rul { + background-color: var(--rul-bg-color); + color: var(--rul-off-color); } - -.caret-position-path.Exp.sibling { - stroke: var(--exp-text-color); - fill: var(--exp-text-color); +.ci-header-TPat { + background-color: var(--tpat-bg-color); + color: var(--tpat-off-color); } +/* is this used? */ +.caret-position-path.Exp.sibling, .caret-position-path.Exp.inner-cousin { stroke: var(--exp-text-color); fill: var(--exp-text-color); } - .caret-position-path.Pat.sibling, .caret-position-path.Pat.inner-cousin { stroke: var(--pat-text-color); fill: var(--pat-text-color); } +.caret-position-path.Typ.sibling, +.caret-position-path.Typ.inner-cousin { + stroke: var(--typ-text-color); + fill: var(--typ-text-color); +} +/* is this used? */ .caret-position-path.Exp.anchor, .caret-position-path.Exp.current-caret-pos { stroke: var(--exp-shadow-color); fill: var(--exp-shadow-color); } - .caret-position-path.Pat.anchor, .caret-position-path.Pat.current-caret-pos { stroke: var(--pat-text-color); fill: var(--pat-text-color); } - .caret-position-path.Typ.anchor, .caret-position-path.Typ.current-caret-pos { stroke: var(--typ-text-color); fill: var(--typ-text-color); } -@property --color { - syntax: ''; - /* <- defined as type number for the transition to work */ - initial-value: #000000; - inherits: false; -} - -#caret-bar { - position: absolute; - height: 100%; - top: 0; - left: 0; - width: 2px; - transform: translate(-50%, 0%); - z-index: var(--caret-bar-z); -} - -#caret-bar.Exp { - background-color: var(--exp-shadow-color); -} +/* END SORT COLORS */ -#caret-bar.Pat { - background-color: var(--pat-text-color); -} - -.sort-label { - border-radius: 2px; - font-weight: 600; -} - -.sort-label.typ { - background-color: var(--typ-bg-color); -} - -.sort-label.pat { - background-color: var(--pat-bg-color); -} - -.sort-label.exp { - background-color: var(--exp-bg-color); -} - -.sort-label.Exp { - /*color: var(--light-page-color);*/ - color: var(--exp-shadow-color); -} - -.sort-label.Pat { - /*color: var(--light-page-color);*/ - color: var(--pat-text-color); -} .keyboard-arrow { position: relative; @@ -1048,6 +1042,10 @@ svg.tile-selected { .typ-view { color: var(--typ-text-color); display: flex; +} + +.kind-view { + display: flex; gap: 0.5em; } @@ -1057,62 +1055,48 @@ svg.tile-selected { gap: 0em; } +.typ-alias-view { + color: var(--tpat-text-color); + display: flex; +} + .typ-mod { vertical-align: super; font-size: 0.7em; } -.term-tag { +.ci-header { padding: 0em 0.6em 0em 0em; - /*border-radius: 0 0.4em 0.4em 0;*/ border-radius: 0 1.1em 0 0; display: flex; gap: 0.5em; - color: #0006; - font-weight: bolder; - text-transform: uppercase; align-items: center; } -.term-tag.error { +.ci-header.error { background-color: var(--err-color); color: #830000 !important; /* HACK(andrew) */ } -.term-tag-typ { - background-color: var(--typ-bg-color); - color: var(--typ-off-color); -} - -.term-tag-pat { - background-color: var(--pat-bg-color); - color: var(--pat-off-color); -} - -.term-tag-exp { - background-color: var(--exp-bg-color); - color: var(--exp-off-color); -} - -.term-tag-rul { - background-color: var(--rul-bg-color); - color: var(--rul-off-color); +.term-tag { + font-weight: bolder; + text-transform: uppercase; } /* CURSOR INSPECTOR */ .cursor-inspector { - z-index: var(--type-inspector-z); display: flex; + /*z-index: var(--type-inspector-z); gap: 0.5em; color: #8c795b; - /*border-radius: 0.3em;*/ border-radius: 0 1.1em 0 0; padding-right: 0.6em; - /* border-right: 1px solid #daca9f; */ - background-color: #fbecaa; - /*#fefcf3;*/ + align-items: stretch;*/ +} + +.cursor-inspector.no-info { align-items: center; } @@ -1120,131 +1104,180 @@ svg.tile-selected { border-color: var(--err-color); } -.cursor-inspector .extra { - z-index: 30; - position: fixed; - width: max-content; - /* top: 3.5em; */ - left: 1.2em; - bottom: 4.5em; - display: none; - gap: 0.5em; - font-size: 0.5em; -} - -.cursor-inspector:hover .extra, -.cursor-inspector .extra.visible, -.cursor-inspector:hover .context-inspector, +.cursor-inspector .gamma:hover + .context-inspector, .context-inspector.visible { display: flex; } -.cursor-inspector .extra .syntax-class { - color: var(--top_bar_icon_fill); -} - -.cursor-inspector .extra .id { - color: #8f8054; -} - .cursor-inspector .info { display: flex; - align-items: center; + align-items: stretch; gap: 0.5em; color: #8c795b; } -.cursor-inspector .info .happy, +.cursor-inspector .info .ok, .cursor-inspector .info .error { display: flex; + align-items: center; gap: 0.5em; + white-space: nowrap; } -.cursor-inspector .info .error, -.cursor-inspector .info .error .typ-view { +.cursor-inspector .info .error { color: var(--err-color); } /* CONTEXT INSPECTOR */ .context-inspector { - display: none; + /* below triggers chrome jank bug */ + /*scroll-snap-type: y mandatory;*/ + direction: rtl; + position: absolute; z-index: 20; - position: fixed; - left: 0.2em; - bottom: 2.1em; + bottom: 1.9em; min-width: 10em; - max-width: 14em; - max-height: 12em; + max-height: 11.26em; overflow: auto; - padding: 0.2em; - padding-bottom: 1.5em; + display: none; + flex-direction: column; + align-items: flex-end; + padding-left: 0.1em; + padding-right: 0.5em; white-space: nowrap; - border-radius: 0.2em; + border-radius: 0 0.2em 0em 0; color: #586e75; - border-left: 1px solid #daca9f; - border-right: 1px solid #daca9f; + border-top: 1px solid #e6ce8f; + border-right: 1px solid #c7b480; + border-bottom: 1px solid #c7b480; background-color: #f7ebc5; - box-shadow: 0px 3px 0px #77580255; + box-shadow: 0px 20px 20px #77580255; + scrollbar-color: #c7b480 #e4d6a6; + scrollbar-width: thin; +} +@supports (-moz-appearance:none) { + .context-inspector { scroll-snap-type: y mandatory; } +} + +.context-inspector::-webkit-scrollbar { + background-color: #e4d6a6; +} + +::-webkit-scrollbar-thumb { + background-color: #c7b480; + border-radius: 0 0.5em 0.5em 0em; } .context-entry { - cursor: pointer; + box-sizing: border-box; + scroll-snap-align: end; + direction: ltr; display: flex; gap: 0.5em; + max-width: 17em; + -webkit-mask-image: linear-gradient(to right, black 13em, transparent); + border-top: 0.5px solid #0000; + border-bottom: 0.5px solid #e2d4a9; + padding-left: 0.3em; + padding-right: 0.3em; +} + +.context-entry:hover { + max-width: 400em; + -webkit-mask-image: none; + background-image: linear-gradient(0deg, rgb(138 99 32), 1%, #f0e1b2, 10%, #f3e6be); + border-radius: 0.1em 0.6em 0.1em 0.6em; + border-top: 0.5px solid #ffffff; + border-bottom: 0.5px solid rgb(51 36 11); +} + +.context-entry .name{ + cursor: pointer; +} + +.context-entry .name:hover { + filter: brightness(0); +} + +.context-entry .typ-view:hover { + /*filter: brightness(1.25) hue-rotate(10deg);*/ +} + +.context-entry .seperator { + color: #c7b480; } /* END STATICS*/ -.bottom-bar { - z-index: var(--result-z); - /*max-height: 3.2em; - overflow-y: auto;*/ - left: 0; - width: 100%; +#bottom-bar { + grid-row: 3 / span 1; + grid-column: 1 / span 2; display: flex; align-items: center; gap: 1em; - background-color: var(--top_bar_icon_fill); - color: #fdf6e3; justify-content: space-between; + align-items: stretch; + background-color: #fbecaa; + border-top: 0.6px solid #c7b480; } -.bottom-bar .cursor-inspector .gamma { - background-color: #b69f79; - padding: 0.16em; +#bottom-bar .icon { + display: flex; + padding: 0.2em; +} + +#bottom-bar .id { + display: flex; + gap: 1em; + font-size: 0.6em; + align-items: center; + padding-left: 1em; + padding-right: 1em; + white-space: nowrap; + color: #a69461; +} + +#bottom-bar .syntax-class { display: flex; + align-items: center; +} + +#bottom-bar .cursor-inspector .gamma { + cursor: pointer; + display: flex; + align-items: center; + font-family: math; + font-weight: normal; + background-color: #b69f79; border-radius: 0 1.1em 0 0; padding-left: 0.5em; - padding-right: 0.5em; + padding-right: 0.7em; color: var(--light-page-color); + height: 100%; +} + +#bottom-bar .cursor-inspector .gamma:hover, +#bottom-bar .cursor-inspector .gamma.visible { + color: gold; + background-color: #907b5a; + border-radius: 0; +} + +#side-bar { + grid-row: 2 / span 1; + grid-column: 2 / span 1; + border-left: 0.6px solid #c7b480; } .lang-doc { - z-index: 20; - position: fixed; - right: 1em; - /* top: 3.8em; */ - /* bottom: 1.8em; */ - width: 25vw; - height: 100vh; - overflow: auto; padding: 0.2em; - padding-bottom: 1.5em; white-space: nowrap; - color: var(--light-text-color); - background-color: #f7ebc5; - /*#fbebaa;*/ } .comment { color: #a0c1aa; } -/* TODO slightly hacky way to be able to scroll to all content vertically - can't see scrollbars on the bottom even when there though...*/ -.lang-doc .content { - padding-bottom: 8em; -} - /* TODO seems like should be better way to ignore inconsistentcy colorings...*/ .lang-doc .code .text-Pat.mono-inconsistent { color: var(--pat-text-color); @@ -1263,12 +1296,24 @@ svg.tile-selected { } .lang-doc .code .token.delim-inconsistent { - color: var(--delim-color); + color: var(--exp-delim-color); font-weight: bold; } +.lang-doc #examples { + display: flex; + flex-direction: column; + gap: 0.6em; +} + .lang-doc .example { - border-bottom: 1px dotted #a69461; + display: flex; + flex-direction: column; +} + +.lang-doc .example + .example { + border-top: 1px dotted #c7b480; + padding-top: 0.6em; } .lang-doc .example .code-text { @@ -1278,6 +1323,7 @@ svg.tile-selected { .lang-doc .example .ex-result { display: flex; align-items: center; + gap: 0.5em; padding-top: 5px; } @@ -1297,7 +1343,9 @@ svg.tile-selected { transform-origin: top; transform: scaleY(0); transition: transform 0.07s ease; - background-color: var(--top_bar_icon_fill); + background-color: #f1e5bf; + border: 0.7px solid #e1c475; + border-top: none; } .specificity-options-menu .selected { @@ -1316,6 +1364,20 @@ svg.tile-selected { .lang-doc .top-bar .close { cursor: pointer; + font-family: 'Source Code Pro'; + color: var(--top_bar_icon_fill); + width: 1.2em; + height: 1.2em; + border-radius: 2em; + display: flex; + align-items: end; + justify-content: center; +} + +.lang-doc .top-bar .close:hover { + animation: wobble 0.4s ease 0s 1 normal none; + color: var(--light-page-color); + background-color: #c7b480; } .lang-doc .section { @@ -1331,6 +1393,9 @@ svg.tile-selected { .lang-doc .section .section-title { text-transform: uppercase; font-weight: bold; + color: #a69460; + font-size: 0.8em; + padding: 0 0 0.5em 0; } .lang-doc .section .explanation-contents { @@ -1338,27 +1403,27 @@ svg.tile-selected { } .highlight-blue { - background-color: rgb(180, 203, 240); + background-color: rgb(255 0 255 / 20%); } .highlight-code-blue { - fill: rgb(180, 203, 240); + fill: rgb(255 0 255 / 20%); } .highlight-pink { - background-color: rgb(242, 177, 182); + background-color: rgb(0 255 255 / 40%); } .highlight-code-pink { - fill: rgb(242, 177, 182); + fill: rgb(0 255 255 / 40%); } .highlight-teal { - background-color: rgb(127, 243, 245); + background-color: rgb(0 255 0 / 20%); } .highlight-code-teal { - fill: rgb(127, 243, 245); + fill: rgb(0 255 0 / 20%); } .highlight-orange { @@ -1405,10 +1470,9 @@ div.expandable-target { svg.expandable { - fill: rgba(19, 17, 17, 0.067); - stroke-dasharray: 4, 4; - stroke: var(--light-text-color); - stroke-width: 2px; + fill: rgb(199 180 128 / 0%); + stroke-dasharray: 3, 3; + stroke: #a69460; /* mix-blend-mode: color; */ z-index: var(--err-hole-z); } @@ -1474,7 +1538,8 @@ svg.expandable path { .result { min-height: 1.6em; - overflow: hidden; + overflow-y: hidden; + overflow-x: auto; } /* DYNAMICS - DHEXP */ @@ -1524,16 +1589,9 @@ svg.expandable path { display: inline-block; } +.DHCode .OperationError, .DHCode .CastDecoration, -.DHCode .FailedCastDecoration, -.DHCode .DivideByZero { - display: inline-block; - position: relative; - font-size: 75%; - top: -10px; -} - -.DHCode .NegativeExponent { +.DHCode .FailedCastDecoration { display: inline-block; position: relative; font-size: 75%; @@ -1554,23 +1612,6 @@ svg.expandable path { /* DYNAMICS - test panel */ -.school-panel { - color: var(--light-text-color); - min-width: 50vw; - max-width: 70vw; - /*min-width: 15em; - max-height: 100%; - overflow-y: auto; - z-index: var(--test-panel-z); - position: fixed; - right: 0; - top: 0em; - max-width: 21em;*/ - display: flex; - flex-direction: column; - gap: 0.5em; -} - .test-panel { z-index: var(--test-panel-z); display: flex; @@ -1736,16 +1777,25 @@ svg.expandable path { } .test-percent { - font-weight: bold; - font-family: 'Helvetica Neue' + height: 1.7em; + display: flex; + padding: 0 1em 0 1em; + font-size: 0.7em; + border-radius: 1em; + background-color: #c7b480; + align-items: center; + margin-left: auto; + margin-right: 1em; } .test-percent.all-pass { - color: #7cb; + background-color: #66ffcb; + color: #289f87; + animation: jello 1s ease 0s 1 normal none; } .test-percent.some-fail { - color: tan; + color: var(--light-page-color); } .test-bar .segment:first-child { @@ -1854,7 +1904,7 @@ svg.expandable path { /* END TOGGLE */ -/* Exercises */ +/* Exercise */ .exercise-code { white-space: nowrap; font-family: "Source Code Pro", monospace; @@ -1881,7 +1931,3 @@ svg.expandable path { left: -1em; } -#main { - overflow: auto; - flex: 1; -} \ No newline at end of file diff --git a/src/util/ListUtil.re b/src/util/ListUtil.re index 0ef44f38f9..7d15427aa9 100644 --- a/src/util/ListUtil.re +++ b/src/util/ListUtil.re @@ -430,3 +430,9 @@ let init_fold: (int, 'b, (int, 'b) => ('b, 'a)) => ('b, list('a)) = ); (acc, List.rev(rev_xs)); }; + +let assoc_err = (x, xs, err: string) => + switch (List.assoc_opt(x, xs)) { + | None => failwith(err) + | Some(y) => y + }; From 6cb7ca9e2bf962794943010b8600eea49f54c98d Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Mon, 7 Aug 2023 22:23:42 +0800 Subject: [PATCH 005/141] Finished porting `Constraint.re`. --- .github/workflows/deploy_branches.yml | 1 + INSTALL.md | 4 +- INSTRUCTORS.md | 2 +- Makefile | 4 +- README.md | 44 +++++----- src/haz3lcore/dynamics/Constraint.re | 112 ++++++++++++++++++++++++-- 6 files changed, 134 insertions(+), 33 deletions(-) diff --git a/.github/workflows/deploy_branches.yml b/.github/workflows/deploy_branches.yml index 928502a69e..a0046e4761 100644 --- a/.github/workflows/deploy_branches.yml +++ b/.github/workflows/deploy_branches.yml @@ -47,6 +47,7 @@ jobs: git config user.name github-deploy-action git config user.email hazel-deploy@hazel.org git add -A + git pull --no-edit git status git diff-index --quiet HEAD || (git commit -m "github-deploy-action-${BRANCH_NAME}"; git push) working-directory: ./server \ No newline at end of file diff --git a/INSTALL.md b/INSTALL.md index e3a601702c..434ece43e7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -231,12 +231,12 @@ If the build fails, it sometimes helps to do a `make clean`. - `make win-chrome` You can also launch Hazel directly by opening -`_build/default/src/hazelweb/www/index.html` in your browser. The command `make +`_build/default/src/haz3lweb/www/index.html` in your browser. The command `make echo-html` echos that path to the terminal, so that you don't have to remember it. You can also run `make repl` to get a REPL in which you can play with the definitions -in `hazelcore`. The definitions in `hazelweb` cannot be used in the REPL because that +in `haz3lcore`. The definitions in `haz3lweb` cannot be used in the REPL because that package needs a browser environment to run. diff --git a/INSTRUCTORS.md b/INSTRUCTORS.md index 4fbeb16b37..a1ded61b5a 100644 --- a/INSTRUCTORS.md +++ b/INSTRUCTORS.md @@ -2,7 +2,7 @@ 1. Make a copy of src/haz3lweb/exercises/BlankTemplate.ml, filling in the arguments for your exercise. Make sure the module_name argument matches your module name. Use the .ml extension (for technical reasons). -2. Add your exercise to the exercise list in SchoolSettings_base.re. +2. Add your exercise to the exercise list in ExerciseSettings_base.re. 3. Compile and load Hazel, select your exercise, make sure Instructor Mode is on. diff --git a/Makefile b/Makefile index 86394c603e..cc409caf68 100644 --- a/Makefile +++ b/Makefile @@ -10,10 +10,10 @@ change-deps: opam switch export opam.export setup-instructor: - cp src/haz3lweb/SchoolSettings_instructor.re src/haz3lweb/SchoolSettings.re + cp src/haz3lweb/ExerciseSettings_instructor.re src/haz3lweb/ExerciseSettings.re setup-student: - cp src/haz3lweb/SchoolSettings_student.re src/haz3lweb/SchoolSettings.re + cp src/haz3lweb/ExerciseSettings_student.re src/haz3lweb/ExerciseSettings.re dev-helper: dune build @src/fmt --auto-promote src --profile dev diff --git a/README.md b/README.md index df2f396d9a..3057e5f585 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ # Hazel ![Build Status](https://github.com/hazelgrove/hazel/actions/workflows/deploy_branches.yml/badge.svg) -[![Hazel Mascot](src/hazelweb/www/imgs/hazel-logo.png)](https://hazel.org) - Hazel is a live functional-programming environment rooted in the principles of type theory. You can find the relevant papers and more motivation at [the Hazel website](https://hazel.org/). -You can try Hazel online with either the -[trunk](https://hazel.org/build/trunk/index.html) or -[dev](https://hazel.org/build/dev/index.html) version. Note that the trunk -branch is updated infrequently and is currently almost two years behind! +You can try Hazel online: the +[dev](https://hazel.org/build/dev) branch is the main branch at the +moment. Every other branch that has been pushed to GitHub and successfully builds +can also be accessed at: + + `https://hazel.org/build/` @@ -26,13 +26,13 @@ installed, you can build Hazel by running the following commands. - `make dev` To view Hazel, you have to serve it, on localhost for development (you can't -run it from a `file:///` URL due to browser restrictions on web workers.) +run it from a `file:///` URL due to browser restrictions on e.g. web workers.) If you have `python3` on your path, you can use the Python server via `make serve`, then navigate to `http://0.0.0.0:8000/` in your browser. -Otherwise, run `make echo-html-dir` for the directory that needs to be served -using the server of your choice. +Otherwise, run `make echo-html-dir` which will echo the directory that needs +to be served using some other server of your choice. ### Long Version @@ -44,16 +44,20 @@ instructions contained in [INSTALL.md](INSTALL.md). ### From OCaml to ReasonML +Hazel is written in ReasonML, which is a syntactic sugar atop OCaml. This link lets you type OCaml and see what the corresponding ReasonML syntax is: . This is useful if you are trying to figure out the ReasonML syntax for something that you know the OCaml syntax for. +You can also convert between OCaml and ReasonML syntax at the terminal using +`refmt` at the terminal. See `refmt --help` for the details. + ### Suggested Extensions for VS Code -Most of our team uses VisualStudio Code to write code. If you use VS Code, here -are a few extensions that might be helpful. +Most of our team uses Visual Studio Code (VS Code) to write code. +If you use VS Code, here are a few extensions that might be helpful. - This extension provides full support for editing ReasonML source code and relevant tools: @@ -84,7 +88,7 @@ If you enjoy your Vim binding and Vim setup, the following may help you set up y If you use vim, I recommend you to switch to NeoVim since it has a better support for multi-thread, and thus less likely to block you when you are programming. -To set up the LSP(Language Server Protocal), you need to set up your Language Client for Neovim and Language Server for ocaml. +To set up the LSP (Language Server Protocol), you need to set up your Language Client for Neovim and Language Server for ocaml. - [ocaml-language-server](https://www.npmjs.com/package/ocaml-language-server) - [LanguageClient-neovim](https://github.com/autozimu/LanguageClient-neovim) @@ -107,8 +111,7 @@ nnoremap :call LanguageClient#textDocument_rename() ### Build System Details -Hazel is implemented in Reason (a dialect of OCaml) and is compiled to -Javascript for the web browser via the `js_of_ocaml` compiler. +Hazel is compiled to Javascript for the web browser via the `js_of_ocaml` compiler. Though `make` targets are provided as a convenience, they mostly translate to `dune` commands. @@ -130,7 +133,7 @@ The `make dev` and `make release` commands do three things: (`_build/default/src/hazelweb/www/hazel.js`) using `js_of_ocaml`. For a smoother dev experience, use `make watch` to automatically watch -for file changes. This will require installing `fswatch` (see INSTALL.md). +for file changes. This may require installing `fswatch` (see INSTALL.md). You can also run `make watch-release` to continuously build the release build (takes longer per build). @@ -167,6 +170,9 @@ existing OCaml projects. #### Printing You can print to the browser console using the standard `print_endline` function. This is probably the easiest method right now. +Most datatypes in the codebase have something like `[@deriving (show({with_path: false}), sexp, yojson)]` on them. This generates +helper functions for printing and serializing this data. For a type named `t`, the `show` function will be named `show`. Otherwise, +for a type named something else like `q`, it will be `show_q`. #### Source Maps `js_of_ocaml` does support source maps and has some other flags that might be useful. If you experiment with those and get them to work, please update this README with some notes. @@ -174,14 +180,6 @@ You can print to the browser console using the standard `print_endline` function #### Debug Mode If Hazel is hanging on load or when you perform certain actions, you can load into Debug Mode by appending `#debug` to the URL and reloading. From there, you have some buttons that will change settings or reset local storage. Refresh without the `#debug` flag and hopefully you can resolve the situation from there. -### Testing - -You can run all of the unit tests located in `src/hazelcore/test` by running `make test`. - -Unit tests are written using [ppx_expect](https://github.com/janestreet/ppx_expect/tree/master/example) and [ppx_inline_tests](https://github.com/janestreet/ppx_inline_test/tree/master/example). If you would like to adjust your expect tests to assert for the output that was last printed, run `make fix-test-answers`. - -If the inline test runner causes problems for you, you can likely resolve the issue by running `opam update` then `opam upgrade`. - ### Continuous Integration When you push your branch to the main `hazelgrove/hazel` repository, we diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index c94c805f29..c8e4bee946 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -18,9 +18,11 @@ type t = | List(list(t)); // How to replace this function? -let rec constrains = (c: t, ty: HTyp.t): bool => - switch (c, ty) { - // switch (c, HTyp.head_normalize(InitialContext.ctx, ty)) { +let rec constrains = (c: t, ty: Typ.t): bool => + switch ( + c, + Typ.weak_head_normalize(Builtins.ctx(Builtins.Pervasives.builtins), ty), + ) { | (Truth, _) | (Falsity, _) | (Hole, _) => true @@ -32,10 +34,110 @@ let rec constrains = (c: t, ty: HTyp.t): bool => | (String(_) | NotString(_), _) => false | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) | (Or(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) - | (InjL(c1), Sum(ty1, _)) => constrains(c1, ty1) + // Treates sum as if it is left associative + | (InjL(c1), Sum(map)) => + switch (List.hd(map)) { + | (_, Some(ty1)) => constrains(c1, ty1) + | _ => false + } | (InjL(_), _) => false - | (InjR(c2), Sum(_, ty2)) => constrains(c2, ty2) + | (InjR(c2), Sum(map)) => + switch (List.tl(map)) { + | [] => false + | [(_, Some(ty2))] => constrains(c2, ty2) + | map' => constrains(c2, Sum(map')) + } | (InjR(_), _) => false | (List(c), ty) => List.fold_left((last, x) => last && constrains(x, ty), true, c) }; + +let rec or_constraints = (lst: list(t)): t => + switch (lst) { + | [] => failwith("should have at least one constraint") + | [xi] => xi + | [xi, ...xis] => Or(xi, or_constraints(xis)) + }; + +let rec dual = (c: t): t => + switch (c) { + | Truth => Falsity + | Falsity => Truth + | Hole => Hole + | Int(n) => NotInt(n) + | NotInt(n) => Int(n) + | Float(n) => NotFloat(n) + | NotFloat(n) => Float(n) + | String(n) => NotString(n) + | NotString(n) => String(n) + | And(c1, c2) => Or(dual(c1), dual(c2)) + | Or(c1, c2) => And(dual(c1), dual(c2)) + | InjL(c1) => Or(InjL(dual(c1)), InjR(Truth)) + | InjR(c2) => Or(InjR(dual(c2)), InjL(Truth)) + // Thought: generate all combinations of ways to dual the list (2^n - 1), and connect them with or + | List(l) => + let permutation = List.map(l' => List(l'), List.tl(permutate(l))); + // ``Or'' is associative, so I try to use this way to simplify it + or_constraints(permutation); + } +and permutate = (l: list(t)): list(list(t)) => + switch (l) { + | [] => [[]] + | [hd, ...tl] => + let result_tl = permutate(tl); + List.map(l' => [hd, ...l'], result_tl) + @ List.map(l' => [dual(hd), ...l'], result_tl); + }; + +/** substitute Truth for Hole */ +let rec truify = (c: t): t => + switch (c) { + | Hole => Truth + | Truth + | Falsity + | Int(_) + | NotInt(_) + | Float(_) + | NotFloat(_) + | String(_) + | NotString(_) => c + | And(c1, c2) => And(truify(c1), truify(c2)) + | Or(c1, c2) => Or(truify(c1), truify(c2)) + | InjL(c) => InjL(truify(c)) + | InjR(c) => InjR(truify(c)) + | List(l) => List.map(c => truify(c), l) + }; + +/** substitute Falsity for Hole */ +let rec falsify = (c: t): t => + switch (c) { + | Hole => Falsity + | Truth + | Falsity + | Int(_) + | NotInt(_) + | Float(_) + | NotFloat(_) + | String(_) + | NotString(_) => c + | And(c1, c2) => And(falsify(c1), falsify(c2)) + | Or(c1, c2) => Or(falsify(c1), falsify(c2)) + | InjL(c) => InjL(falsify(c)) + | InjR(c) => InjR(falsify(c)) + | List(l) => List.map(c => falsify(c), l) + }; + +let unwrapL = + fun + | InjL(c) => c + | _ => failwith("input can only be InjL(_)"); + +let unwrapR = + fun + | InjR(c) => c + | _ => failwith("input can only be InjR(_)"); + +let unwrap_list = + fun + | List(l) => l + | _ => failwith("input can only be List([_, ..._])"); \ No newline at end of file From 47c190525804963b9aff63ae00c4cfb7ed88b8ff Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Wed, 16 Aug 2023 18:38:12 +0800 Subject: [PATCH 006/141] Ported `Incon.re` and `Sets.re`. --- src/haz3lcore/dynamics/Constraint.re | 6 +- src/haz3lcore/dynamics/Incon.re | 296 +++++++++++++++++++++------ src/haz3lcore/dynamics/Sets.re | 23 +++ 3 files changed, 265 insertions(+), 60 deletions(-) create mode 100644 src/haz3lcore/dynamics/Sets.re diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index c8e4bee946..1388e2fde6 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -105,7 +105,7 @@ let rec truify = (c: t): t => | Or(c1, c2) => Or(truify(c1), truify(c2)) | InjL(c) => InjL(truify(c)) | InjR(c) => InjR(truify(c)) - | List(l) => List.map(c => truify(c), l) + | List(l) => List(List.map(c => truify(c), l)) }; /** substitute Falsity for Hole */ @@ -124,7 +124,7 @@ let rec falsify = (c: t): t => | Or(c1, c2) => Or(falsify(c1), falsify(c2)) | InjL(c) => InjL(falsify(c)) | InjR(c) => InjR(falsify(c)) - | List(l) => List.map(c => falsify(c), l) + | List(l) => List(List.map(c => falsify(c), l)) }; let unwrapL = @@ -140,4 +140,4 @@ let unwrapR = let unwrap_list = fun | List(l) => l - | _ => failwith("input can only be List([_, ..._])"); \ No newline at end of file + | _ => failwith("input can only be List([_, ..._])"); diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 2d403e1174..204d181cb6 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -1,64 +1,246 @@ -let rec matches = (e: DHExp.t, p: DHPat.t): bool => - switch (e, p) { - | (_, Var(_)) => true - | (_, Wild) => true - | (BoolLit(x), BoolLit(y)) => x == y - | (IntLit(x), IntLit(y)) => x == y - | (FloatLit(x), FloatLit(y)) => x == y - | (StringLit(x), StringLit(y)) => x == y - | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) - // I don't know if my algorithm is correct or not. - | (ListLit(_, _, _, _, []), ListLit(_, [])) - | (Tuple([]), Tuple([])) => true - | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) - | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => - matches(hd1, hd2) && matches(Tuple(tl1), Tuple(tl2)) - | (_, _) => false +open Sets; + +let is_inconsistent_nums = (xis: list(Constraint.t)): bool => { + let (int_set, not_int_list) = + List.fold_left( + ((int_set, not_int_list), xi: Constraint.t) => + switch (xi) { + | Int(n) => (IntSet.add(n, int_set), not_int_list) + | NotInt(n) => (int_set, [n, ...not_int_list]) + | _ => failwith("input can only be Int | NotInt") + }, + (IntSet.empty, []), + xis, + ); + if (IntSet.cardinal(int_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + IntSet.mem(n, int_set); + }, + false, + not_int_list, + ); }; +}; -let rec does_not_match = (e: DHExp.t, p: DHPat.t): bool => - switch (e, p) { - | (BoolLit(x), BoolLit(y)) => x != y - | (IntLit(x), IntLit(y)) => x != y - | (FloatLit(x), FloatLit(y)) => x != y - | (StringLit(x), StringLit(y)) => x != y - | (ListLit(_, _, _, _, []), ListLit(_, [])) - | (Tuple([]), Tuple([])) => false - | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) - | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => - does_not_match(hd1, hd2) || does_not_match(Tuple(tl1), Tuple(tl2)) - | (Inj(_, side1, x), Inj(side2, y)) => - side1 != side2 || does_not_match(x, y) - | (_, _) => false +let is_inconsistent_float = (xis: list(Constraint.t)): bool => { + let (float_set, not_float_list) = + List.fold_left( + ((float_set, not_float_list), xi: Constraint.t) => + switch (xi) { + | Float(n) => (FloatSet.add(n, float_set), not_float_list) + | NotFloat(n) => (float_set, [n, ...not_float_list]) + | _ => failwith("input can only be Float | NotFloat") + }, + (FloatSet.empty, []), + xis, + ); + if (FloatSet.cardinal(float_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + FloatSet.mem(n, float_set); + }, + false, + not_float_list, + ); }; +}; -// It is difficult to write indet_match, so I used the theorem to simplify it. Probably it will execute slower. -let indet_match = (e: DHExp.t, p: DHPat.t): bool => - !(matches(e, p) || does_not_match(e, p)); +let is_inconsistent_string = (xis: list(Constraint.t)): bool => { + let (string_set, not_string_list) = + List.fold_left( + ((string_set, not_string_list), xi: Constraint.t) => + switch (xi) { + | Float(n) => (StringSet.add(n, string_set), not_string_list) + | NotFloat(n) => (string_set, [n, ...not_string_list]) + | _ => failwith("input can only be Float | NotFloat") + }, + (StringSet.empty, []), + xis, + ); + if (StringSet.cardinal(string_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + StringSet.mem(n, string_set); + }, + false, + not_string_list, + ); + }; +}; -let rec is_val = (e: DHExp.t): bool => - switch (e) { - | BoolLit(_) - | IntLit(_) - | StringLit(_) - | Fun(_, _, _, _) - | ListLit(_, _, _, _, []) - | Tuple([]) => true - | ListLit(_, _, _, _, inner) - | Tuple(inner) => - List.fold_left((last_val, e) => last_val && is_val(e), true, inner) - | BinBoolOp(_, e1, e2) - | BinIntOp(_, e1, e2) - | BinFloatOp(_, e1, e2) - | BinStringOp(_, e1, e2) => is_val(e1) ? is_val(e2) : false - | Inj(_, _, e) => is_val(e) - | _ => false +let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => + switch (xis) { + | [] => false + | [xi, ...xis'] => + switch (xi) { + | Truth => is_inconsistent(~may, xis') + | Falsity => true + | Hole => may ? true : is_inconsistent(~may, xis') + | And(xi1, xi2) => is_inconsistent(~may, [xi1, xi2, ...xis']) + | Or(xi1, xi2) => + is_inconsistent(~may, [xi1, ...xis']) + && is_inconsistent(~may, [xi2, ...xis']) + | InjL(_) => + if (List.exists( + fun + | Constraint.InjR(_) => true + | _ => false, + xis, + )) { + true; + } else { + switch ( + List.partition( + fun + | Constraint.InjL(_) => true + | _ => false, + xis, + ) + ) { + | (injLs, []) => + let unwrap = List.map(Constraint.unwrapL, injLs); + is_inconsistent(~may, unwrap); + | (injLs, other) => is_inconsistent(~may, other @ injLs) + }; + } + | InjR(_) => + if (List.exists( + fun + | Constraint.InjL(_) => true + | _ => false, + xis, + )) { + true; + } else { + switch ( + List.partition( + fun + | Constraint.InjR(_) => true + | _ => false, + xis, + ) + ) { + | (injRs, []) => + let unwrap = List.map(Constraint.unwrapR, injRs); + is_inconsistent(~may, unwrap); + | (injRs, other) => is_inconsistent(~may, other @ injRs) + }; + } + | Int(_) + | NotInt(_) => + switch ( + List.partition( + fun + | Constraint.Int(_) + | NotInt(_) => true + | _ => false, + xis, + ) + ) { + | (ns, []) => is_inconsistent_nums(ns) + | (ns, other) => is_inconsistent(~may, other @ ns) + } + | Float(_) + | NotFloat(_) => + switch ( + List.partition( + fun + | Constraint.Float(_) + | NotFloat(_) => true + | _ => false, + xis, + ) + ) { + | (fs, []) => is_inconsistent_float(fs) + | (fs, other) => is_inconsistent(~may, other @ fs) + } + | String(_) + | NotString(_) => + switch ( + List.partition( + fun + | Constraint.String(_) + | NotString(_) => true + | _ => false, + xis, + ) + ) { + | (fs, []) => is_inconsistent_string(fs) + | (fs, other) => is_inconsistent(~may, other @ fs) + } + /* + * Thoughts for porting the Pair judgment to list: + * Two list constraints are automatically inconsistent if they have different length. + * So we first find maximum and minimum list lengths, and determine if they are the same. + * If so, we rearrange them in item-first order, and check each of them. + */ + | List(_) => + switch ( + List.partition( + fun + | Constraint.List(_) => true + | _ => false, + xis, + ) + ) { + | (lists, []) => + let lengths = + List.map(x => List.length(Constraint.unwrap_list(x)), lists); + // check if all lengths are equal + // This could be done with exceptions, but I found nothing related on ReasonML website. + let all_lengths_are_equal = + List.for_all(x => x == List.hd(lengths), List.tl(lengths)); + if (all_lengths_are_equal) { + let order_by_index = + List.fold_left( + // ordered_by_index: list(list(t)); item: packed version of list(t) + (ordered_by_index, lst) => + List.map2( + // We need a function that maps `(list(t), t)` to list(list(t) + (old_list, item) => [item, ...old_list], + ordered_by_index, + Constraint.unwrap_list(lst), + ), + // Initial version of empty list, in list(list(t)) + List.map(x => [x], Constraint.unwrap_list(List.hd(lists))), + // Rest of items + List.tl(lists), + ); + // Check if there are inconsistency in each element + List.fold_left( + (previous, item) => previous || is_inconsistent(~may, item), + may, + order_by_index, + ); + } else { + true; // Automatically inconsistent + }; + | (lists, other) => is_inconsistent(~may, other @ lists) + } + } }; -let rec is_indet = (e: DHExp.t): bool => - switch (e) { - | EmptyHole(_, _) => true - | NonEmptyHole(_, _, _, e) => is_final(e) - | _ => false - } -and is_final = (e: DHExp.t): bool => is_val(e) && is_indet(e); +let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => + is_inconsistent( + ~may=false, + Constraint.[And(truify(xi_cur), dual(falsify(xi_pre)))], + ); + +let is_exhaustive = (xi: Constraint.t): bool => + is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); \ No newline at end of file diff --git a/src/haz3lcore/dynamics/Sets.re b/src/haz3lcore/dynamics/Sets.re new file mode 100644 index 0000000000..67b6099709 --- /dev/null +++ b/src/haz3lcore/dynamics/Sets.re @@ -0,0 +1,23 @@ +module IntSet = + Set.Make({ + type t = int; + let compare = compare; + }); + +module BoolSet = + Set.Make({ + type t = bool; + let compare = compare; + }); + +module FloatSet = + Set.Make({ + type t = float; + let compare = compare; + }); + +module StringSet = + Set.Make({ + type t = float; + let compare = compare; + }); From 80e15bc002e93ef97c586ab4bf236ea7cae859e5 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Wed, 23 Aug 2023 20:13:11 +0800 Subject: [PATCH 007/141] Fixed dependency problem. --- opam.export | 96 +++++++++++++++++---------------- src/haz3lcore/dynamics/Incon.re | 2 +- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/opam.export b/opam.export index 98f8552d3a..9cf1612dd5 100644 --- a/opam.export +++ b/opam.export @@ -2,20 +2,20 @@ opam-version: "2.0" compiler: ["ocaml-base-compiler.5.0.0"] roots: [ "incr_dom.v0.15.1" - "lwt.5.6.1" + "lwt.5.7.0" "lwt-dllist.1.0.1" - "merlin.4.8-500" + "merlin.4.9-500" "ocaml-base-compiler.5.0.0" - "ocaml-lsp-server.1.15.1-5.0" - "ocamlformat.0.25.1" - "omd.1.3.2" + "ocaml-lsp-server.1.16.2" + "ocamlformat.0.26.0" + "omd.2.0.0~alpha4" "ppx_deriving.5.2.1" "ppx_yojson_conv.v0.15.1" "ptmap.2.0.5" - "reason.3.8.2" - "tezt.3.0.0" + "reason.3.9.0" + "tezt.3.1.1" "unionFind.20220122" - "utop.2.11.0" + "utop.2.13.1" ] installed: [ "abstract_algebra.v0.15.0" @@ -36,24 +36,26 @@ installed: [ "bigstringaf.0.9.1" "bin_prot.v0.15.0" "camlp-streams.5.0.1" - "chrome-trace.3.7.0" - "cmdliner.1.1.1" + "chrome-trace.3.10.0" + "cmdliner.1.2.0" + "conf-autoconf.0.1" + "conf-which.1" "core.v0.15.1" "core_kernel.v0.15.0" "cppo.1.6.9" - "csexp.1.5.1" + "csexp.1.5.2" "cstruct.6.2.0" - "dot-merlin-reader.4.6" - "dune.3.7.0" - "dune-build-info.3.7.0" - "dune-configurator.3.7.0" - "dune-rpc.3.6.2" - "dyn.3.6.2" + "dot-merlin-reader.4.9" + "dune.3.10.0" + "dune-build-info.3.10.0" + "dune-configurator.3.10.0" + "dune-rpc.3.10.0" + "dyn.3.10.0" "either.1.0.0" "ezjsonm.1.3.0" - "fiber.3.6.2" + "fiber.3.7.0" "fieldslib.v0.15.0" - "fix.20220121" + "fix.20230505" "fmt.0.9.0" "fpath.0.7.3" "gen.1.1" @@ -65,24 +67,24 @@ installed: [ "incremental.v0.15.0" "int_repr.v0.15.0" "jane-street-headers.v0.15.0" - "js_of_ocaml.4.1.0" - "js_of_ocaml-compiler.4.1.0" - "js_of_ocaml-ppx.4.1.0" + "js_of_ocaml.5.4.0" + "js_of_ocaml-compiler.5.4.0" + "js_of_ocaml-ppx.5.4.0" "jsonm.1.0.2" "jst-config.v0.15.1" - "lambda-term.3.3.1" + "lambda-term.3.3.2" "lambdasoup.1.0.0" "logs.0.7.0" - "lwt.5.6.1" + "lwt.5.7.0" "lwt-dllist.1.0.1" "lwt_react.1.2.0" "markup.1.0.3" - "menhir.20220210" - "menhirLib.20220210" - "menhirSdk.20220210" - "merlin.4.8-500" + "menhir.20230608" + "menhirLib.20230608" + "menhirSdk.20230608" + "merlin.4.9-500" "merlin-extend.0.6.1" - "merlin-lib.4.8-500" + "merlin-lib.4.9-500" "mew.0.1.0" "mew_vi.0.5.0" "num.1.4" @@ -90,28 +92,28 @@ installed: [ "ocaml-base-compiler.5.0.0" "ocaml-compiler-libs.v0.12.4" "ocaml-config.3" - "ocaml-lsp-server.1.15.1-5.0" + "ocaml-lsp-server.1.16.2" "ocaml-options-vanilla.1" "ocaml-syntax-shims.1.0.0" "ocaml-version.3.6.1" "ocamlbuild.0.14.2" - "ocamlc-loc.3.6.2" + "ocamlc-loc.3.10.0" "ocamlfind.1.9.6" - "ocamlformat.0.25.1" - "ocamlformat-lib.0.25.1" - "ocamlformat-rpc-lib.0.25.1" + "ocamlformat.0.26.0" + "ocamlformat-lib.0.26.0" + "ocamlformat-rpc-lib.0.26.0" "ocp-indent.1.8.1" "ocplib-endian.1.2" "octavius.1.2.2" "odoc-parser.2.0.0" "ojs.1.1.2" - "omd.1.3.2" - "ordering.3.6.2" + "omd.2.0.0~alpha4" + "ordering.3.10.0" "parsexp.v0.15.0" "pp.1.1.2" "ppx_assert.v0.15.0" "ppx_base.v0.15.0" - "ppx_bench.v0.15.0" + "ppx_bench.v0.15.1" "ppx_bin_prot.v0.15.0" "ppx_cold.v0.15.0" "ppx_compare.v0.15.0" @@ -126,7 +128,7 @@ installed: [ "ppx_hash.v0.15.0" "ppx_here.v0.15.0" "ppx_ignore_instrumentation.v0.15.0" - "ppx_inline_test.v0.15.0" + "ppx_inline_test.v0.15.1" "ppx_jane.v0.15.0" "ppx_js_style.v0.15.0" "ppx_let.v0.15.0" @@ -145,14 +147,14 @@ installed: [ "ppx_variants_conv.v0.15.0" "ppx_yojson_conv.v0.15.1" "ppx_yojson_conv_lib.v0.15.0" - "ppxlib.0.28.0" + "ppxlib.0.30.0" "protocol_version_header.v0.15.0" "ptmap.2.0.5" "re.1.10.4" "react.1.2.2" - "reason.3.8.2" + "reason.3.9.0" "result.1.5" - "sedlex.3.1" + "sedlex.3.2" "seq.base" "sexplib.v0.15.1" "sexplib0.v0.15.1" @@ -161,9 +163,9 @@ installed: [ "stdcompat.19" "stdio.v0.15.0" "stdlib-shims.0.3.0" - "stdune.3.6.2" + "stdune.3.10.0" "stringext.1.6.0" - "tezt.3.0.0" + "tezt.3.1.1" "time_now.v0.15.0" "topkg.1.0.7" "trie.1.0.0" @@ -173,16 +175,16 @@ installed: [ "unionFind.20220122" "uri.4.2.0" "uri-sexp.4.2.0" - "utop.2.11.0" + "utop.2.13.1" "uucp.15.0.0" "uunf.15.0.0" "uuseg.15.0.0" "uutf.1.0.3" "variantslib.v0.15.0" "virtual_dom.v0.15.1" - "xdg.3.7.0" - "yojson.2.0.2" - "zed.3.2.1" + "xdg.3.10.0" + "yojson.2.1.0" + "zed.3.2.3" ] pinned: [ "async_js.v0.15.1" diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 204d181cb6..8b9bd7b02d 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -243,4 +243,4 @@ let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => ); let is_exhaustive = (xi: Constraint.t): bool => - is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); \ No newline at end of file + is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); From 45751eea66f3346c664231af64a06eb03f31f69b Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 9 Jul 2023 21:54:32 +0800 Subject: [PATCH 008/141] Add some function from injection paper. --- src/haz3lcore/dynamics/Incon.re | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/haz3lcore/dynamics/Incon.re diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re new file mode 100644 index 0000000000..a5d4b8ded2 --- /dev/null +++ b/src/haz3lcore/dynamics/Incon.re @@ -0,0 +1,39 @@ +let rec matches = (e: DHExp.t, p: DHPat.t): bool => + switch (e, p) { + | (_, Var(_)) => true + | (_, Wild) => true + | (BoolLit(x), BoolLit(y)) => x == y + | (IntLit(x), IntLit(y)) => x == y + | (FloatLit(x), FloatLit(y)) => x == y + | (StringLit(x), StringLit(y)) => x == y + | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) + // I don't know how to extend the algorithm for projection into that of list or tuples. + | (_, _) => false + }; + +let rec is_val = (e: DHExp.t): bool => + switch (e) { + | BoolLit(_) + | IntLit(_) + | StringLit(_) + | Fun(_, _, _, _) + | ListLit(_, _, _, _, []) + | Tuple([]) => true + | ListLit(_, _, _, _, inner) + | Tuple(inner) => + List.fold_left((last_val, e) => last_val && is_val(e), true, inner) + | BinBoolOp(_, e1, e2) + | BinIntOp(_, e1, e2) + | BinFloatOp(_, e1, e2) + | BinStringOp(_, e1, e2) => is_val(e1) ? is_val(e2) : false + | Inj(_, _, e) => is_val(e) + | _ => false + }; + +let rec is_indet = (e: DHExp.t): bool => + switch (e) { + | EmptyHole(_, _) => true + | NonEmptyHole(_, _, _, e) => is_final(e) + | _ => false + } +and is_final = (e: DHExp.t): bool => is_val(e) && is_indet(e); From 0b768ecd1b290003e7e371c0f6dde5042d6f754d Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 16 Jul 2023 11:59:57 +0800 Subject: [PATCH 009/141] Finished implementing algorithms from P8. --- src/haz3lcore/dynamics/Incon.re | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index a5d4b8ded2..2d403e1174 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -7,10 +7,35 @@ let rec matches = (e: DHExp.t, p: DHPat.t): bool => | (FloatLit(x), FloatLit(y)) => x == y | (StringLit(x), StringLit(y)) => x == y | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) - // I don't know how to extend the algorithm for projection into that of list or tuples. + // I don't know if my algorithm is correct or not. + | (ListLit(_, _, _, _, []), ListLit(_, [])) + | (Tuple([]), Tuple([])) => true + | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) + | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => + matches(hd1, hd2) && matches(Tuple(tl1), Tuple(tl2)) | (_, _) => false }; +let rec does_not_match = (e: DHExp.t, p: DHPat.t): bool => + switch (e, p) { + | (BoolLit(x), BoolLit(y)) => x != y + | (IntLit(x), IntLit(y)) => x != y + | (FloatLit(x), FloatLit(y)) => x != y + | (StringLit(x), StringLit(y)) => x != y + | (ListLit(_, _, _, _, []), ListLit(_, [])) + | (Tuple([]), Tuple([])) => false + | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) + | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => + does_not_match(hd1, hd2) || does_not_match(Tuple(tl1), Tuple(tl2)) + | (Inj(_, side1, x), Inj(side2, y)) => + side1 != side2 || does_not_match(x, y) + | (_, _) => false + }; + +// It is difficult to write indet_match, so I used the theorem to simplify it. Probably it will execute slower. +let indet_match = (e: DHExp.t, p: DHPat.t): bool => + !(matches(e, p) || does_not_match(e, p)); + let rec is_val = (e: DHExp.t): bool => switch (e) { | BoolLit(_) From 7d9b905f098e422e915f1e249e2c4d332bd345cc Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Fri, 21 Jul 2023 18:10:34 +0800 Subject: [PATCH 010/141] Translating part of old Constraint.re into this version. --- src/haz3lcore/dynamics/Constraint.re | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/haz3lcore/dynamics/Constraint.re diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re new file mode 100644 index 0000000000..c94c805f29 --- /dev/null +++ b/src/haz3lcore/dynamics/Constraint.re @@ -0,0 +1,41 @@ +open Sexplib.Std; + +[@deriving sexp] +type t = + | Truth + | Falsity + | Hole + | Int(int) + | NotInt(int) + | Float(float) + | NotFloat(float) + | String(string) + | NotString(string) + | And(t, t) + | Or(t, t) + | InjL(t) + | InjR(t) + | List(list(t)); + +// How to replace this function? +let rec constrains = (c: t, ty: HTyp.t): bool => + switch (c, ty) { + // switch (c, HTyp.head_normalize(InitialContext.ctx, ty)) { + | (Truth, _) + | (Falsity, _) + | (Hole, _) => true + | (Int(_) | NotInt(_), Int) => true + | (Int(_) | NotInt(_), _) => false + | (Float(_) | NotFloat(_), Float) => true + | (Float(_) | NotFloat(_), _) => false + | (String(_) | NotString(_), String) => true + | (String(_) | NotString(_), _) => false + | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) + | (Or(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) + | (InjL(c1), Sum(ty1, _)) => constrains(c1, ty1) + | (InjL(_), _) => false + | (InjR(c2), Sum(_, ty2)) => constrains(c2, ty2) + | (InjR(_), _) => false + | (List(c), ty) => + List.fold_left((last, x) => last && constrains(x, ty), true, c) + }; From 90d8e980605cfda48b57323c779de544a75fbf6c Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Tue, 1 Aug 2023 21:16:36 +0800 Subject: [PATCH 011/141] Rebase, Part 1. --- src/haz3lcore/dynamics/InvalidOperationError.re | 4 ++++ src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/InvalidOperationError.re b/src/haz3lcore/dynamics/InvalidOperationError.re index ce8c94e888..858e7b0757 100644 --- a/src/haz3lcore/dynamics/InvalidOperationError.re +++ b/src/haz3lcore/dynamics/InvalidOperationError.re @@ -5,6 +5,8 @@ type t = | DivideByZero | NegativeExponent | OutOfFuel + | InvalidIntOfString + | InvalidFloatOfString | InvalidProjection; let err_msg = (err: t): string => @@ -14,5 +16,7 @@ let err_msg = (err: t): string => | DivideByZero => "Error: Divide by Zero" | NegativeExponent => "Error: Negative Exponent in Integer Exponentiation (Consider using **.)" | OutOfFuel => "Error: Out of Fuel" + | InvalidIntOfString => "Error: Invalid String to Int Conversion" + | InvalidFloatOfString => "Error: Invalid String to Float Conversion" | InvalidProjection => "Error: Invalid Projection" }; diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index 2dc53757b5..ead18ee4ff 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -179,7 +179,7 @@ let rec mk = | BoolLit(b) => DHDoc_common.mk_BoolLit(b) | IntLit(n) => DHDoc_common.mk_IntLit(n) | FloatLit(f) => DHDoc_common.mk_FloatLit(f) - | StringLit(s) => DHDoc_common.mk_StringLit(s) + | StringLit(s) => DHDoc_common.mk_StringLit("\"" ++ s ++ "\"") | TestLit(_) => Doc.text(ExpandingKeyword.to_string(Test)) | Sequence(d1, d2) => let (doc1, doc2) = (go'(d1), go'(d2)); From 8c5a214dd13c7420226ce74e017e4979b58b8707 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Mon, 7 Aug 2023 22:23:42 +0800 Subject: [PATCH 012/141] Rebase, Part 2. --- src/haz3lcore/dynamics/Constraint.re | 112 +++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index c94c805f29..c8e4bee946 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -18,9 +18,11 @@ type t = | List(list(t)); // How to replace this function? -let rec constrains = (c: t, ty: HTyp.t): bool => - switch (c, ty) { - // switch (c, HTyp.head_normalize(InitialContext.ctx, ty)) { +let rec constrains = (c: t, ty: Typ.t): bool => + switch ( + c, + Typ.weak_head_normalize(Builtins.ctx(Builtins.Pervasives.builtins), ty), + ) { | (Truth, _) | (Falsity, _) | (Hole, _) => true @@ -32,10 +34,110 @@ let rec constrains = (c: t, ty: HTyp.t): bool => | (String(_) | NotString(_), _) => false | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) | (Or(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) - | (InjL(c1), Sum(ty1, _)) => constrains(c1, ty1) + // Treates sum as if it is left associative + | (InjL(c1), Sum(map)) => + switch (List.hd(map)) { + | (_, Some(ty1)) => constrains(c1, ty1) + | _ => false + } | (InjL(_), _) => false - | (InjR(c2), Sum(_, ty2)) => constrains(c2, ty2) + | (InjR(c2), Sum(map)) => + switch (List.tl(map)) { + | [] => false + | [(_, Some(ty2))] => constrains(c2, ty2) + | map' => constrains(c2, Sum(map')) + } | (InjR(_), _) => false | (List(c), ty) => List.fold_left((last, x) => last && constrains(x, ty), true, c) }; + +let rec or_constraints = (lst: list(t)): t => + switch (lst) { + | [] => failwith("should have at least one constraint") + | [xi] => xi + | [xi, ...xis] => Or(xi, or_constraints(xis)) + }; + +let rec dual = (c: t): t => + switch (c) { + | Truth => Falsity + | Falsity => Truth + | Hole => Hole + | Int(n) => NotInt(n) + | NotInt(n) => Int(n) + | Float(n) => NotFloat(n) + | NotFloat(n) => Float(n) + | String(n) => NotString(n) + | NotString(n) => String(n) + | And(c1, c2) => Or(dual(c1), dual(c2)) + | Or(c1, c2) => And(dual(c1), dual(c2)) + | InjL(c1) => Or(InjL(dual(c1)), InjR(Truth)) + | InjR(c2) => Or(InjR(dual(c2)), InjL(Truth)) + // Thought: generate all combinations of ways to dual the list (2^n - 1), and connect them with or + | List(l) => + let permutation = List.map(l' => List(l'), List.tl(permutate(l))); + // ``Or'' is associative, so I try to use this way to simplify it + or_constraints(permutation); + } +and permutate = (l: list(t)): list(list(t)) => + switch (l) { + | [] => [[]] + | [hd, ...tl] => + let result_tl = permutate(tl); + List.map(l' => [hd, ...l'], result_tl) + @ List.map(l' => [dual(hd), ...l'], result_tl); + }; + +/** substitute Truth for Hole */ +let rec truify = (c: t): t => + switch (c) { + | Hole => Truth + | Truth + | Falsity + | Int(_) + | NotInt(_) + | Float(_) + | NotFloat(_) + | String(_) + | NotString(_) => c + | And(c1, c2) => And(truify(c1), truify(c2)) + | Or(c1, c2) => Or(truify(c1), truify(c2)) + | InjL(c) => InjL(truify(c)) + | InjR(c) => InjR(truify(c)) + | List(l) => List.map(c => truify(c), l) + }; + +/** substitute Falsity for Hole */ +let rec falsify = (c: t): t => + switch (c) { + | Hole => Falsity + | Truth + | Falsity + | Int(_) + | NotInt(_) + | Float(_) + | NotFloat(_) + | String(_) + | NotString(_) => c + | And(c1, c2) => And(falsify(c1), falsify(c2)) + | Or(c1, c2) => Or(falsify(c1), falsify(c2)) + | InjL(c) => InjL(falsify(c)) + | InjR(c) => InjR(falsify(c)) + | List(l) => List.map(c => falsify(c), l) + }; + +let unwrapL = + fun + | InjL(c) => c + | _ => failwith("input can only be InjL(_)"); + +let unwrapR = + fun + | InjR(c) => c + | _ => failwith("input can only be InjR(_)"); + +let unwrap_list = + fun + | List(l) => l + | _ => failwith("input can only be List([_, ..._])"); \ No newline at end of file From b0b6ce66ead2e98d98203d656be14cee934e59fe Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Wed, 16 Aug 2023 18:38:12 +0800 Subject: [PATCH 013/141] Ported `Incon.re` and `Sets.re`. --- src/haz3lcore/dynamics/Constraint.re | 6 +- src/haz3lcore/dynamics/Incon.re | 296 +++++++++++++++++++++------ src/haz3lcore/dynamics/Sets.re | 23 +++ 3 files changed, 265 insertions(+), 60 deletions(-) create mode 100644 src/haz3lcore/dynamics/Sets.re diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index c8e4bee946..1388e2fde6 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -105,7 +105,7 @@ let rec truify = (c: t): t => | Or(c1, c2) => Or(truify(c1), truify(c2)) | InjL(c) => InjL(truify(c)) | InjR(c) => InjR(truify(c)) - | List(l) => List.map(c => truify(c), l) + | List(l) => List(List.map(c => truify(c), l)) }; /** substitute Falsity for Hole */ @@ -124,7 +124,7 @@ let rec falsify = (c: t): t => | Or(c1, c2) => Or(falsify(c1), falsify(c2)) | InjL(c) => InjL(falsify(c)) | InjR(c) => InjR(falsify(c)) - | List(l) => List.map(c => falsify(c), l) + | List(l) => List(List.map(c => falsify(c), l)) }; let unwrapL = @@ -140,4 +140,4 @@ let unwrapR = let unwrap_list = fun | List(l) => l - | _ => failwith("input can only be List([_, ..._])"); \ No newline at end of file + | _ => failwith("input can only be List([_, ..._])"); diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 2d403e1174..204d181cb6 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -1,64 +1,246 @@ -let rec matches = (e: DHExp.t, p: DHPat.t): bool => - switch (e, p) { - | (_, Var(_)) => true - | (_, Wild) => true - | (BoolLit(x), BoolLit(y)) => x == y - | (IntLit(x), IntLit(y)) => x == y - | (FloatLit(x), FloatLit(y)) => x == y - | (StringLit(x), StringLit(y)) => x == y - | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) - // I don't know if my algorithm is correct or not. - | (ListLit(_, _, _, _, []), ListLit(_, [])) - | (Tuple([]), Tuple([])) => true - | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) - | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => - matches(hd1, hd2) && matches(Tuple(tl1), Tuple(tl2)) - | (_, _) => false +open Sets; + +let is_inconsistent_nums = (xis: list(Constraint.t)): bool => { + let (int_set, not_int_list) = + List.fold_left( + ((int_set, not_int_list), xi: Constraint.t) => + switch (xi) { + | Int(n) => (IntSet.add(n, int_set), not_int_list) + | NotInt(n) => (int_set, [n, ...not_int_list]) + | _ => failwith("input can only be Int | NotInt") + }, + (IntSet.empty, []), + xis, + ); + if (IntSet.cardinal(int_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + IntSet.mem(n, int_set); + }, + false, + not_int_list, + ); }; +}; -let rec does_not_match = (e: DHExp.t, p: DHPat.t): bool => - switch (e, p) { - | (BoolLit(x), BoolLit(y)) => x != y - | (IntLit(x), IntLit(y)) => x != y - | (FloatLit(x), FloatLit(y)) => x != y - | (StringLit(x), StringLit(y)) => x != y - | (ListLit(_, _, _, _, []), ListLit(_, [])) - | (Tuple([]), Tuple([])) => false - | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) - | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => - does_not_match(hd1, hd2) || does_not_match(Tuple(tl1), Tuple(tl2)) - | (Inj(_, side1, x), Inj(side2, y)) => - side1 != side2 || does_not_match(x, y) - | (_, _) => false +let is_inconsistent_float = (xis: list(Constraint.t)): bool => { + let (float_set, not_float_list) = + List.fold_left( + ((float_set, not_float_list), xi: Constraint.t) => + switch (xi) { + | Float(n) => (FloatSet.add(n, float_set), not_float_list) + | NotFloat(n) => (float_set, [n, ...not_float_list]) + | _ => failwith("input can only be Float | NotFloat") + }, + (FloatSet.empty, []), + xis, + ); + if (FloatSet.cardinal(float_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + FloatSet.mem(n, float_set); + }, + false, + not_float_list, + ); }; +}; -// It is difficult to write indet_match, so I used the theorem to simplify it. Probably it will execute slower. -let indet_match = (e: DHExp.t, p: DHPat.t): bool => - !(matches(e, p) || does_not_match(e, p)); +let is_inconsistent_string = (xis: list(Constraint.t)): bool => { + let (string_set, not_string_list) = + List.fold_left( + ((string_set, not_string_list), xi: Constraint.t) => + switch (xi) { + | Float(n) => (StringSet.add(n, string_set), not_string_list) + | NotFloat(n) => (string_set, [n, ...not_string_list]) + | _ => failwith("input can only be Float | NotFloat") + }, + (StringSet.empty, []), + xis, + ); + if (StringSet.cardinal(string_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + StringSet.mem(n, string_set); + }, + false, + not_string_list, + ); + }; +}; -let rec is_val = (e: DHExp.t): bool => - switch (e) { - | BoolLit(_) - | IntLit(_) - | StringLit(_) - | Fun(_, _, _, _) - | ListLit(_, _, _, _, []) - | Tuple([]) => true - | ListLit(_, _, _, _, inner) - | Tuple(inner) => - List.fold_left((last_val, e) => last_val && is_val(e), true, inner) - | BinBoolOp(_, e1, e2) - | BinIntOp(_, e1, e2) - | BinFloatOp(_, e1, e2) - | BinStringOp(_, e1, e2) => is_val(e1) ? is_val(e2) : false - | Inj(_, _, e) => is_val(e) - | _ => false +let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => + switch (xis) { + | [] => false + | [xi, ...xis'] => + switch (xi) { + | Truth => is_inconsistent(~may, xis') + | Falsity => true + | Hole => may ? true : is_inconsistent(~may, xis') + | And(xi1, xi2) => is_inconsistent(~may, [xi1, xi2, ...xis']) + | Or(xi1, xi2) => + is_inconsistent(~may, [xi1, ...xis']) + && is_inconsistent(~may, [xi2, ...xis']) + | InjL(_) => + if (List.exists( + fun + | Constraint.InjR(_) => true + | _ => false, + xis, + )) { + true; + } else { + switch ( + List.partition( + fun + | Constraint.InjL(_) => true + | _ => false, + xis, + ) + ) { + | (injLs, []) => + let unwrap = List.map(Constraint.unwrapL, injLs); + is_inconsistent(~may, unwrap); + | (injLs, other) => is_inconsistent(~may, other @ injLs) + }; + } + | InjR(_) => + if (List.exists( + fun + | Constraint.InjL(_) => true + | _ => false, + xis, + )) { + true; + } else { + switch ( + List.partition( + fun + | Constraint.InjR(_) => true + | _ => false, + xis, + ) + ) { + | (injRs, []) => + let unwrap = List.map(Constraint.unwrapR, injRs); + is_inconsistent(~may, unwrap); + | (injRs, other) => is_inconsistent(~may, other @ injRs) + }; + } + | Int(_) + | NotInt(_) => + switch ( + List.partition( + fun + | Constraint.Int(_) + | NotInt(_) => true + | _ => false, + xis, + ) + ) { + | (ns, []) => is_inconsistent_nums(ns) + | (ns, other) => is_inconsistent(~may, other @ ns) + } + | Float(_) + | NotFloat(_) => + switch ( + List.partition( + fun + | Constraint.Float(_) + | NotFloat(_) => true + | _ => false, + xis, + ) + ) { + | (fs, []) => is_inconsistent_float(fs) + | (fs, other) => is_inconsistent(~may, other @ fs) + } + | String(_) + | NotString(_) => + switch ( + List.partition( + fun + | Constraint.String(_) + | NotString(_) => true + | _ => false, + xis, + ) + ) { + | (fs, []) => is_inconsistent_string(fs) + | (fs, other) => is_inconsistent(~may, other @ fs) + } + /* + * Thoughts for porting the Pair judgment to list: + * Two list constraints are automatically inconsistent if they have different length. + * So we first find maximum and minimum list lengths, and determine if they are the same. + * If so, we rearrange them in item-first order, and check each of them. + */ + | List(_) => + switch ( + List.partition( + fun + | Constraint.List(_) => true + | _ => false, + xis, + ) + ) { + | (lists, []) => + let lengths = + List.map(x => List.length(Constraint.unwrap_list(x)), lists); + // check if all lengths are equal + // This could be done with exceptions, but I found nothing related on ReasonML website. + let all_lengths_are_equal = + List.for_all(x => x == List.hd(lengths), List.tl(lengths)); + if (all_lengths_are_equal) { + let order_by_index = + List.fold_left( + // ordered_by_index: list(list(t)); item: packed version of list(t) + (ordered_by_index, lst) => + List.map2( + // We need a function that maps `(list(t), t)` to list(list(t) + (old_list, item) => [item, ...old_list], + ordered_by_index, + Constraint.unwrap_list(lst), + ), + // Initial version of empty list, in list(list(t)) + List.map(x => [x], Constraint.unwrap_list(List.hd(lists))), + // Rest of items + List.tl(lists), + ); + // Check if there are inconsistency in each element + List.fold_left( + (previous, item) => previous || is_inconsistent(~may, item), + may, + order_by_index, + ); + } else { + true; // Automatically inconsistent + }; + | (lists, other) => is_inconsistent(~may, other @ lists) + } + } }; -let rec is_indet = (e: DHExp.t): bool => - switch (e) { - | EmptyHole(_, _) => true - | NonEmptyHole(_, _, _, e) => is_final(e) - | _ => false - } -and is_final = (e: DHExp.t): bool => is_val(e) && is_indet(e); +let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => + is_inconsistent( + ~may=false, + Constraint.[And(truify(xi_cur), dual(falsify(xi_pre)))], + ); + +let is_exhaustive = (xi: Constraint.t): bool => + is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); \ No newline at end of file diff --git a/src/haz3lcore/dynamics/Sets.re b/src/haz3lcore/dynamics/Sets.re new file mode 100644 index 0000000000..67b6099709 --- /dev/null +++ b/src/haz3lcore/dynamics/Sets.re @@ -0,0 +1,23 @@ +module IntSet = + Set.Make({ + type t = int; + let compare = compare; + }); + +module BoolSet = + Set.Make({ + type t = bool; + let compare = compare; + }); + +module FloatSet = + Set.Make({ + type t = float; + let compare = compare; + }); + +module StringSet = + Set.Make({ + type t = float; + let compare = compare; + }); From d9ff68106ee0ec8e28132141b471e62e23d0102f Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Wed, 23 Aug 2023 20:13:11 +0800 Subject: [PATCH 014/141] Fixed dependency problem. --- opam.export | 96 +++++++++++++++++---------------- src/haz3lcore/dynamics/Incon.re | 2 +- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/opam.export b/opam.export index 98f8552d3a..9cf1612dd5 100644 --- a/opam.export +++ b/opam.export @@ -2,20 +2,20 @@ opam-version: "2.0" compiler: ["ocaml-base-compiler.5.0.0"] roots: [ "incr_dom.v0.15.1" - "lwt.5.6.1" + "lwt.5.7.0" "lwt-dllist.1.0.1" - "merlin.4.8-500" + "merlin.4.9-500" "ocaml-base-compiler.5.0.0" - "ocaml-lsp-server.1.15.1-5.0" - "ocamlformat.0.25.1" - "omd.1.3.2" + "ocaml-lsp-server.1.16.2" + "ocamlformat.0.26.0" + "omd.2.0.0~alpha4" "ppx_deriving.5.2.1" "ppx_yojson_conv.v0.15.1" "ptmap.2.0.5" - "reason.3.8.2" - "tezt.3.0.0" + "reason.3.9.0" + "tezt.3.1.1" "unionFind.20220122" - "utop.2.11.0" + "utop.2.13.1" ] installed: [ "abstract_algebra.v0.15.0" @@ -36,24 +36,26 @@ installed: [ "bigstringaf.0.9.1" "bin_prot.v0.15.0" "camlp-streams.5.0.1" - "chrome-trace.3.7.0" - "cmdliner.1.1.1" + "chrome-trace.3.10.0" + "cmdliner.1.2.0" + "conf-autoconf.0.1" + "conf-which.1" "core.v0.15.1" "core_kernel.v0.15.0" "cppo.1.6.9" - "csexp.1.5.1" + "csexp.1.5.2" "cstruct.6.2.0" - "dot-merlin-reader.4.6" - "dune.3.7.0" - "dune-build-info.3.7.0" - "dune-configurator.3.7.0" - "dune-rpc.3.6.2" - "dyn.3.6.2" + "dot-merlin-reader.4.9" + "dune.3.10.0" + "dune-build-info.3.10.0" + "dune-configurator.3.10.0" + "dune-rpc.3.10.0" + "dyn.3.10.0" "either.1.0.0" "ezjsonm.1.3.0" - "fiber.3.6.2" + "fiber.3.7.0" "fieldslib.v0.15.0" - "fix.20220121" + "fix.20230505" "fmt.0.9.0" "fpath.0.7.3" "gen.1.1" @@ -65,24 +67,24 @@ installed: [ "incremental.v0.15.0" "int_repr.v0.15.0" "jane-street-headers.v0.15.0" - "js_of_ocaml.4.1.0" - "js_of_ocaml-compiler.4.1.0" - "js_of_ocaml-ppx.4.1.0" + "js_of_ocaml.5.4.0" + "js_of_ocaml-compiler.5.4.0" + "js_of_ocaml-ppx.5.4.0" "jsonm.1.0.2" "jst-config.v0.15.1" - "lambda-term.3.3.1" + "lambda-term.3.3.2" "lambdasoup.1.0.0" "logs.0.7.0" - "lwt.5.6.1" + "lwt.5.7.0" "lwt-dllist.1.0.1" "lwt_react.1.2.0" "markup.1.0.3" - "menhir.20220210" - "menhirLib.20220210" - "menhirSdk.20220210" - "merlin.4.8-500" + "menhir.20230608" + "menhirLib.20230608" + "menhirSdk.20230608" + "merlin.4.9-500" "merlin-extend.0.6.1" - "merlin-lib.4.8-500" + "merlin-lib.4.9-500" "mew.0.1.0" "mew_vi.0.5.0" "num.1.4" @@ -90,28 +92,28 @@ installed: [ "ocaml-base-compiler.5.0.0" "ocaml-compiler-libs.v0.12.4" "ocaml-config.3" - "ocaml-lsp-server.1.15.1-5.0" + "ocaml-lsp-server.1.16.2" "ocaml-options-vanilla.1" "ocaml-syntax-shims.1.0.0" "ocaml-version.3.6.1" "ocamlbuild.0.14.2" - "ocamlc-loc.3.6.2" + "ocamlc-loc.3.10.0" "ocamlfind.1.9.6" - "ocamlformat.0.25.1" - "ocamlformat-lib.0.25.1" - "ocamlformat-rpc-lib.0.25.1" + "ocamlformat.0.26.0" + "ocamlformat-lib.0.26.0" + "ocamlformat-rpc-lib.0.26.0" "ocp-indent.1.8.1" "ocplib-endian.1.2" "octavius.1.2.2" "odoc-parser.2.0.0" "ojs.1.1.2" - "omd.1.3.2" - "ordering.3.6.2" + "omd.2.0.0~alpha4" + "ordering.3.10.0" "parsexp.v0.15.0" "pp.1.1.2" "ppx_assert.v0.15.0" "ppx_base.v0.15.0" - "ppx_bench.v0.15.0" + "ppx_bench.v0.15.1" "ppx_bin_prot.v0.15.0" "ppx_cold.v0.15.0" "ppx_compare.v0.15.0" @@ -126,7 +128,7 @@ installed: [ "ppx_hash.v0.15.0" "ppx_here.v0.15.0" "ppx_ignore_instrumentation.v0.15.0" - "ppx_inline_test.v0.15.0" + "ppx_inline_test.v0.15.1" "ppx_jane.v0.15.0" "ppx_js_style.v0.15.0" "ppx_let.v0.15.0" @@ -145,14 +147,14 @@ installed: [ "ppx_variants_conv.v0.15.0" "ppx_yojson_conv.v0.15.1" "ppx_yojson_conv_lib.v0.15.0" - "ppxlib.0.28.0" + "ppxlib.0.30.0" "protocol_version_header.v0.15.0" "ptmap.2.0.5" "re.1.10.4" "react.1.2.2" - "reason.3.8.2" + "reason.3.9.0" "result.1.5" - "sedlex.3.1" + "sedlex.3.2" "seq.base" "sexplib.v0.15.1" "sexplib0.v0.15.1" @@ -161,9 +163,9 @@ installed: [ "stdcompat.19" "stdio.v0.15.0" "stdlib-shims.0.3.0" - "stdune.3.6.2" + "stdune.3.10.0" "stringext.1.6.0" - "tezt.3.0.0" + "tezt.3.1.1" "time_now.v0.15.0" "topkg.1.0.7" "trie.1.0.0" @@ -173,16 +175,16 @@ installed: [ "unionFind.20220122" "uri.4.2.0" "uri-sexp.4.2.0" - "utop.2.11.0" + "utop.2.13.1" "uucp.15.0.0" "uunf.15.0.0" "uuseg.15.0.0" "uutf.1.0.3" "variantslib.v0.15.0" "virtual_dom.v0.15.1" - "xdg.3.7.0" - "yojson.2.0.2" - "zed.3.2.1" + "xdg.3.10.0" + "yojson.2.1.0" + "zed.3.2.3" ] pinned: [ "async_js.v0.15.1" diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 204d181cb6..8b9bd7b02d 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -243,4 +243,4 @@ let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => ); let is_exhaustive = (xi: Constraint.t): bool => - is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); \ No newline at end of file + is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); From bfc1fae1201731938a3f9e881eb0c1a4918d98a9 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 27 Aug 2023 09:54:46 -0400 Subject: [PATCH 015/141] Fixed a bug related to incomplete rebasing. --- src/haz3lcore/dynamics/Constraint.re | 5 +---- src/haz3lcore/dynamics/InvalidOperationError.re | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 1388e2fde6..0a4b705a2d 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -19,10 +19,7 @@ type t = // How to replace this function? let rec constrains = (c: t, ty: Typ.t): bool => - switch ( - c, - Typ.weak_head_normalize(Builtins.ctx(Builtins.Pervasives.builtins), ty), - ) { + switch (c, Typ.weak_head_normalize(Builtins.ctx_init, ty)) { | (Truth, _) | (Falsity, _) | (Hole, _) => true diff --git a/src/haz3lcore/dynamics/InvalidOperationError.re b/src/haz3lcore/dynamics/InvalidOperationError.re index 858e7b0757..3a6e31c35f 100644 --- a/src/haz3lcore/dynamics/InvalidOperationError.re +++ b/src/haz3lcore/dynamics/InvalidOperationError.re @@ -5,8 +5,8 @@ type t = | DivideByZero | NegativeExponent | OutOfFuel - | InvalidIntOfString - | InvalidFloatOfString + // | InvalidIntOfString + // | InvalidFloatOfString | InvalidProjection; let err_msg = (err: t): string => @@ -16,7 +16,7 @@ let err_msg = (err: t): string => | DivideByZero => "Error: Divide by Zero" | NegativeExponent => "Error: Negative Exponent in Integer Exponentiation (Consider using **.)" | OutOfFuel => "Error: Out of Fuel" - | InvalidIntOfString => "Error: Invalid String to Int Conversion" - | InvalidFloatOfString => "Error: Invalid String to Float Conversion" + // | InvalidIntOfString => "Error: Invalid String to Int Conversion" + // | InvalidFloatOfString => "Error: Invalid String to Float Conversion" | InvalidProjection => "Error: Invalid Projection" }; From 0beba60e4776577096572923db5b0bb6b6d063c3 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 9 Jul 2023 21:54:32 +0800 Subject: [PATCH 016/141] Add some function from injection paper. --- src/haz3lcore/dynamics/Incon.re | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/haz3lcore/dynamics/Incon.re diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re new file mode 100644 index 0000000000..a5d4b8ded2 --- /dev/null +++ b/src/haz3lcore/dynamics/Incon.re @@ -0,0 +1,39 @@ +let rec matches = (e: DHExp.t, p: DHPat.t): bool => + switch (e, p) { + | (_, Var(_)) => true + | (_, Wild) => true + | (BoolLit(x), BoolLit(y)) => x == y + | (IntLit(x), IntLit(y)) => x == y + | (FloatLit(x), FloatLit(y)) => x == y + | (StringLit(x), StringLit(y)) => x == y + | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) + // I don't know how to extend the algorithm for projection into that of list or tuples. + | (_, _) => false + }; + +let rec is_val = (e: DHExp.t): bool => + switch (e) { + | BoolLit(_) + | IntLit(_) + | StringLit(_) + | Fun(_, _, _, _) + | ListLit(_, _, _, _, []) + | Tuple([]) => true + | ListLit(_, _, _, _, inner) + | Tuple(inner) => + List.fold_left((last_val, e) => last_val && is_val(e), true, inner) + | BinBoolOp(_, e1, e2) + | BinIntOp(_, e1, e2) + | BinFloatOp(_, e1, e2) + | BinStringOp(_, e1, e2) => is_val(e1) ? is_val(e2) : false + | Inj(_, _, e) => is_val(e) + | _ => false + }; + +let rec is_indet = (e: DHExp.t): bool => + switch (e) { + | EmptyHole(_, _) => true + | NonEmptyHole(_, _, _, e) => is_final(e) + | _ => false + } +and is_final = (e: DHExp.t): bool => is_val(e) && is_indet(e); From 414ddffba3b83b086e51e43b7dba085ca128f220 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 16 Jul 2023 11:59:57 +0800 Subject: [PATCH 017/141] Finished implementing algorithms from P8. --- src/haz3lcore/dynamics/Incon.re | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index a5d4b8ded2..2d403e1174 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -7,10 +7,35 @@ let rec matches = (e: DHExp.t, p: DHPat.t): bool => | (FloatLit(x), FloatLit(y)) => x == y | (StringLit(x), StringLit(y)) => x == y | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) - // I don't know how to extend the algorithm for projection into that of list or tuples. + // I don't know if my algorithm is correct or not. + | (ListLit(_, _, _, _, []), ListLit(_, [])) + | (Tuple([]), Tuple([])) => true + | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) + | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => + matches(hd1, hd2) && matches(Tuple(tl1), Tuple(tl2)) | (_, _) => false }; +let rec does_not_match = (e: DHExp.t, p: DHPat.t): bool => + switch (e, p) { + | (BoolLit(x), BoolLit(y)) => x != y + | (IntLit(x), IntLit(y)) => x != y + | (FloatLit(x), FloatLit(y)) => x != y + | (StringLit(x), StringLit(y)) => x != y + | (ListLit(_, _, _, _, []), ListLit(_, [])) + | (Tuple([]), Tuple([])) => false + | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) + | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => + does_not_match(hd1, hd2) || does_not_match(Tuple(tl1), Tuple(tl2)) + | (Inj(_, side1, x), Inj(side2, y)) => + side1 != side2 || does_not_match(x, y) + | (_, _) => false + }; + +// It is difficult to write indet_match, so I used the theorem to simplify it. Probably it will execute slower. +let indet_match = (e: DHExp.t, p: DHPat.t): bool => + !(matches(e, p) || does_not_match(e, p)); + let rec is_val = (e: DHExp.t): bool => switch (e) { | BoolLit(_) From 5b3df76944567c6ffbea539d2427cee03466fb8d Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Fri, 21 Jul 2023 18:10:34 +0800 Subject: [PATCH 018/141] Translating part of old Constraint.re into this version. --- src/haz3lcore/dynamics/Constraint.re | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/haz3lcore/dynamics/Constraint.re diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re new file mode 100644 index 0000000000..c94c805f29 --- /dev/null +++ b/src/haz3lcore/dynamics/Constraint.re @@ -0,0 +1,41 @@ +open Sexplib.Std; + +[@deriving sexp] +type t = + | Truth + | Falsity + | Hole + | Int(int) + | NotInt(int) + | Float(float) + | NotFloat(float) + | String(string) + | NotString(string) + | And(t, t) + | Or(t, t) + | InjL(t) + | InjR(t) + | List(list(t)); + +// How to replace this function? +let rec constrains = (c: t, ty: HTyp.t): bool => + switch (c, ty) { + // switch (c, HTyp.head_normalize(InitialContext.ctx, ty)) { + | (Truth, _) + | (Falsity, _) + | (Hole, _) => true + | (Int(_) | NotInt(_), Int) => true + | (Int(_) | NotInt(_), _) => false + | (Float(_) | NotFloat(_), Float) => true + | (Float(_) | NotFloat(_), _) => false + | (String(_) | NotString(_), String) => true + | (String(_) | NotString(_), _) => false + | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) + | (Or(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) + | (InjL(c1), Sum(ty1, _)) => constrains(c1, ty1) + | (InjL(_), _) => false + | (InjR(c2), Sum(_, ty2)) => constrains(c2, ty2) + | (InjR(_), _) => false + | (List(c), ty) => + List.fold_left((last, x) => last && constrains(x, ty), true, c) + }; From 16e1ba48df66f8809c00a95d7b44ea70f7eaf0a8 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Tue, 1 Aug 2023 21:16:36 +0800 Subject: [PATCH 019/141] Rebase, Part 1. --- src/haz3lcore/dynamics/InvalidOperationError.re | 4 ++++ src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/InvalidOperationError.re b/src/haz3lcore/dynamics/InvalidOperationError.re index ce8c94e888..858e7b0757 100644 --- a/src/haz3lcore/dynamics/InvalidOperationError.re +++ b/src/haz3lcore/dynamics/InvalidOperationError.re @@ -5,6 +5,8 @@ type t = | DivideByZero | NegativeExponent | OutOfFuel + | InvalidIntOfString + | InvalidFloatOfString | InvalidProjection; let err_msg = (err: t): string => @@ -14,5 +16,7 @@ let err_msg = (err: t): string => | DivideByZero => "Error: Divide by Zero" | NegativeExponent => "Error: Negative Exponent in Integer Exponentiation (Consider using **.)" | OutOfFuel => "Error: Out of Fuel" + | InvalidIntOfString => "Error: Invalid String to Int Conversion" + | InvalidFloatOfString => "Error: Invalid String to Float Conversion" | InvalidProjection => "Error: Invalid Projection" }; diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index 2dc53757b5..ead18ee4ff 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -179,7 +179,7 @@ let rec mk = | BoolLit(b) => DHDoc_common.mk_BoolLit(b) | IntLit(n) => DHDoc_common.mk_IntLit(n) | FloatLit(f) => DHDoc_common.mk_FloatLit(f) - | StringLit(s) => DHDoc_common.mk_StringLit(s) + | StringLit(s) => DHDoc_common.mk_StringLit("\"" ++ s ++ "\"") | TestLit(_) => Doc.text(ExpandingKeyword.to_string(Test)) | Sequence(d1, d2) => let (doc1, doc2) = (go'(d1), go'(d2)); From aba862e24adf100e7a2b8e797e4b450a32485452 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Mon, 7 Aug 2023 22:23:42 +0800 Subject: [PATCH 020/141] Rebase, Part 2. --- src/haz3lcore/dynamics/Constraint.re | 112 +++++++++++++++++++++++++-- 1 file changed, 107 insertions(+), 5 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index c94c805f29..c8e4bee946 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -18,9 +18,11 @@ type t = | List(list(t)); // How to replace this function? -let rec constrains = (c: t, ty: HTyp.t): bool => - switch (c, ty) { - // switch (c, HTyp.head_normalize(InitialContext.ctx, ty)) { +let rec constrains = (c: t, ty: Typ.t): bool => + switch ( + c, + Typ.weak_head_normalize(Builtins.ctx(Builtins.Pervasives.builtins), ty), + ) { | (Truth, _) | (Falsity, _) | (Hole, _) => true @@ -32,10 +34,110 @@ let rec constrains = (c: t, ty: HTyp.t): bool => | (String(_) | NotString(_), _) => false | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) | (Or(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) - | (InjL(c1), Sum(ty1, _)) => constrains(c1, ty1) + // Treates sum as if it is left associative + | (InjL(c1), Sum(map)) => + switch (List.hd(map)) { + | (_, Some(ty1)) => constrains(c1, ty1) + | _ => false + } | (InjL(_), _) => false - | (InjR(c2), Sum(_, ty2)) => constrains(c2, ty2) + | (InjR(c2), Sum(map)) => + switch (List.tl(map)) { + | [] => false + | [(_, Some(ty2))] => constrains(c2, ty2) + | map' => constrains(c2, Sum(map')) + } | (InjR(_), _) => false | (List(c), ty) => List.fold_left((last, x) => last && constrains(x, ty), true, c) }; + +let rec or_constraints = (lst: list(t)): t => + switch (lst) { + | [] => failwith("should have at least one constraint") + | [xi] => xi + | [xi, ...xis] => Or(xi, or_constraints(xis)) + }; + +let rec dual = (c: t): t => + switch (c) { + | Truth => Falsity + | Falsity => Truth + | Hole => Hole + | Int(n) => NotInt(n) + | NotInt(n) => Int(n) + | Float(n) => NotFloat(n) + | NotFloat(n) => Float(n) + | String(n) => NotString(n) + | NotString(n) => String(n) + | And(c1, c2) => Or(dual(c1), dual(c2)) + | Or(c1, c2) => And(dual(c1), dual(c2)) + | InjL(c1) => Or(InjL(dual(c1)), InjR(Truth)) + | InjR(c2) => Or(InjR(dual(c2)), InjL(Truth)) + // Thought: generate all combinations of ways to dual the list (2^n - 1), and connect them with or + | List(l) => + let permutation = List.map(l' => List(l'), List.tl(permutate(l))); + // ``Or'' is associative, so I try to use this way to simplify it + or_constraints(permutation); + } +and permutate = (l: list(t)): list(list(t)) => + switch (l) { + | [] => [[]] + | [hd, ...tl] => + let result_tl = permutate(tl); + List.map(l' => [hd, ...l'], result_tl) + @ List.map(l' => [dual(hd), ...l'], result_tl); + }; + +/** substitute Truth for Hole */ +let rec truify = (c: t): t => + switch (c) { + | Hole => Truth + | Truth + | Falsity + | Int(_) + | NotInt(_) + | Float(_) + | NotFloat(_) + | String(_) + | NotString(_) => c + | And(c1, c2) => And(truify(c1), truify(c2)) + | Or(c1, c2) => Or(truify(c1), truify(c2)) + | InjL(c) => InjL(truify(c)) + | InjR(c) => InjR(truify(c)) + | List(l) => List.map(c => truify(c), l) + }; + +/** substitute Falsity for Hole */ +let rec falsify = (c: t): t => + switch (c) { + | Hole => Falsity + | Truth + | Falsity + | Int(_) + | NotInt(_) + | Float(_) + | NotFloat(_) + | String(_) + | NotString(_) => c + | And(c1, c2) => And(falsify(c1), falsify(c2)) + | Or(c1, c2) => Or(falsify(c1), falsify(c2)) + | InjL(c) => InjL(falsify(c)) + | InjR(c) => InjR(falsify(c)) + | List(l) => List.map(c => falsify(c), l) + }; + +let unwrapL = + fun + | InjL(c) => c + | _ => failwith("input can only be InjL(_)"); + +let unwrapR = + fun + | InjR(c) => c + | _ => failwith("input can only be InjR(_)"); + +let unwrap_list = + fun + | List(l) => l + | _ => failwith("input can only be List([_, ..._])"); \ No newline at end of file From 2e526d4a44f07756a2e0c8e94f29cf43757e97c4 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Wed, 16 Aug 2023 18:38:12 +0800 Subject: [PATCH 021/141] Ported `Incon.re` and `Sets.re`. --- src/haz3lcore/dynamics/Constraint.re | 6 +- src/haz3lcore/dynamics/Incon.re | 296 +++++++++++++++++++++------ src/haz3lcore/dynamics/Sets.re | 23 +++ 3 files changed, 265 insertions(+), 60 deletions(-) create mode 100644 src/haz3lcore/dynamics/Sets.re diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index c8e4bee946..1388e2fde6 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -105,7 +105,7 @@ let rec truify = (c: t): t => | Or(c1, c2) => Or(truify(c1), truify(c2)) | InjL(c) => InjL(truify(c)) | InjR(c) => InjR(truify(c)) - | List(l) => List.map(c => truify(c), l) + | List(l) => List(List.map(c => truify(c), l)) }; /** substitute Falsity for Hole */ @@ -124,7 +124,7 @@ let rec falsify = (c: t): t => | Or(c1, c2) => Or(falsify(c1), falsify(c2)) | InjL(c) => InjL(falsify(c)) | InjR(c) => InjR(falsify(c)) - | List(l) => List.map(c => falsify(c), l) + | List(l) => List(List.map(c => falsify(c), l)) }; let unwrapL = @@ -140,4 +140,4 @@ let unwrapR = let unwrap_list = fun | List(l) => l - | _ => failwith("input can only be List([_, ..._])"); \ No newline at end of file + | _ => failwith("input can only be List([_, ..._])"); diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 2d403e1174..204d181cb6 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -1,64 +1,246 @@ -let rec matches = (e: DHExp.t, p: DHPat.t): bool => - switch (e, p) { - | (_, Var(_)) => true - | (_, Wild) => true - | (BoolLit(x), BoolLit(y)) => x == y - | (IntLit(x), IntLit(y)) => x == y - | (FloatLit(x), FloatLit(y)) => x == y - | (StringLit(x), StringLit(y)) => x == y - | (Inj(_, side1, x), Inj(side2, y)) => side1 == side2 && matches(x, y) - // I don't know if my algorithm is correct or not. - | (ListLit(_, _, _, _, []), ListLit(_, [])) - | (Tuple([]), Tuple([])) => true - | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) - | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => - matches(hd1, hd2) && matches(Tuple(tl1), Tuple(tl2)) - | (_, _) => false +open Sets; + +let is_inconsistent_nums = (xis: list(Constraint.t)): bool => { + let (int_set, not_int_list) = + List.fold_left( + ((int_set, not_int_list), xi: Constraint.t) => + switch (xi) { + | Int(n) => (IntSet.add(n, int_set), not_int_list) + | NotInt(n) => (int_set, [n, ...not_int_list]) + | _ => failwith("input can only be Int | NotInt") + }, + (IntSet.empty, []), + xis, + ); + if (IntSet.cardinal(int_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + IntSet.mem(n, int_set); + }, + false, + not_int_list, + ); }; +}; -let rec does_not_match = (e: DHExp.t, p: DHPat.t): bool => - switch (e, p) { - | (BoolLit(x), BoolLit(y)) => x != y - | (IntLit(x), IntLit(y)) => x != y - | (FloatLit(x), FloatLit(y)) => x != y - | (StringLit(x), StringLit(y)) => x != y - | (ListLit(_, _, _, _, []), ListLit(_, [])) - | (Tuple([]), Tuple([])) => false - | (ListLit(_, _, _, _, [hd1, ...tl1]), ListLit(_, [hd2, ...tl2])) - | (Tuple([hd1, ...tl1]), Tuple([hd2, ...tl2])) => - does_not_match(hd1, hd2) || does_not_match(Tuple(tl1), Tuple(tl2)) - | (Inj(_, side1, x), Inj(side2, y)) => - side1 != side2 || does_not_match(x, y) - | (_, _) => false +let is_inconsistent_float = (xis: list(Constraint.t)): bool => { + let (float_set, not_float_list) = + List.fold_left( + ((float_set, not_float_list), xi: Constraint.t) => + switch (xi) { + | Float(n) => (FloatSet.add(n, float_set), not_float_list) + | NotFloat(n) => (float_set, [n, ...not_float_list]) + | _ => failwith("input can only be Float | NotFloat") + }, + (FloatSet.empty, []), + xis, + ); + if (FloatSet.cardinal(float_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + FloatSet.mem(n, float_set); + }, + false, + not_float_list, + ); }; +}; -// It is difficult to write indet_match, so I used the theorem to simplify it. Probably it will execute slower. -let indet_match = (e: DHExp.t, p: DHPat.t): bool => - !(matches(e, p) || does_not_match(e, p)); +let is_inconsistent_string = (xis: list(Constraint.t)): bool => { + let (string_set, not_string_list) = + List.fold_left( + ((string_set, not_string_list), xi: Constraint.t) => + switch (xi) { + | Float(n) => (StringSet.add(n, string_set), not_string_list) + | NotFloat(n) => (string_set, [n, ...not_string_list]) + | _ => failwith("input can only be Float | NotFloat") + }, + (StringSet.empty, []), + xis, + ); + if (StringSet.cardinal(string_set) > 1) { + true; + } else { + List.fold_left( + (incon, n) => + if (incon) { + incon; + } else { + StringSet.mem(n, string_set); + }, + false, + not_string_list, + ); + }; +}; -let rec is_val = (e: DHExp.t): bool => - switch (e) { - | BoolLit(_) - | IntLit(_) - | StringLit(_) - | Fun(_, _, _, _) - | ListLit(_, _, _, _, []) - | Tuple([]) => true - | ListLit(_, _, _, _, inner) - | Tuple(inner) => - List.fold_left((last_val, e) => last_val && is_val(e), true, inner) - | BinBoolOp(_, e1, e2) - | BinIntOp(_, e1, e2) - | BinFloatOp(_, e1, e2) - | BinStringOp(_, e1, e2) => is_val(e1) ? is_val(e2) : false - | Inj(_, _, e) => is_val(e) - | _ => false +let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => + switch (xis) { + | [] => false + | [xi, ...xis'] => + switch (xi) { + | Truth => is_inconsistent(~may, xis') + | Falsity => true + | Hole => may ? true : is_inconsistent(~may, xis') + | And(xi1, xi2) => is_inconsistent(~may, [xi1, xi2, ...xis']) + | Or(xi1, xi2) => + is_inconsistent(~may, [xi1, ...xis']) + && is_inconsistent(~may, [xi2, ...xis']) + | InjL(_) => + if (List.exists( + fun + | Constraint.InjR(_) => true + | _ => false, + xis, + )) { + true; + } else { + switch ( + List.partition( + fun + | Constraint.InjL(_) => true + | _ => false, + xis, + ) + ) { + | (injLs, []) => + let unwrap = List.map(Constraint.unwrapL, injLs); + is_inconsistent(~may, unwrap); + | (injLs, other) => is_inconsistent(~may, other @ injLs) + }; + } + | InjR(_) => + if (List.exists( + fun + | Constraint.InjL(_) => true + | _ => false, + xis, + )) { + true; + } else { + switch ( + List.partition( + fun + | Constraint.InjR(_) => true + | _ => false, + xis, + ) + ) { + | (injRs, []) => + let unwrap = List.map(Constraint.unwrapR, injRs); + is_inconsistent(~may, unwrap); + | (injRs, other) => is_inconsistent(~may, other @ injRs) + }; + } + | Int(_) + | NotInt(_) => + switch ( + List.partition( + fun + | Constraint.Int(_) + | NotInt(_) => true + | _ => false, + xis, + ) + ) { + | (ns, []) => is_inconsistent_nums(ns) + | (ns, other) => is_inconsistent(~may, other @ ns) + } + | Float(_) + | NotFloat(_) => + switch ( + List.partition( + fun + | Constraint.Float(_) + | NotFloat(_) => true + | _ => false, + xis, + ) + ) { + | (fs, []) => is_inconsistent_float(fs) + | (fs, other) => is_inconsistent(~may, other @ fs) + } + | String(_) + | NotString(_) => + switch ( + List.partition( + fun + | Constraint.String(_) + | NotString(_) => true + | _ => false, + xis, + ) + ) { + | (fs, []) => is_inconsistent_string(fs) + | (fs, other) => is_inconsistent(~may, other @ fs) + } + /* + * Thoughts for porting the Pair judgment to list: + * Two list constraints are automatically inconsistent if they have different length. + * So we first find maximum and minimum list lengths, and determine if they are the same. + * If so, we rearrange them in item-first order, and check each of them. + */ + | List(_) => + switch ( + List.partition( + fun + | Constraint.List(_) => true + | _ => false, + xis, + ) + ) { + | (lists, []) => + let lengths = + List.map(x => List.length(Constraint.unwrap_list(x)), lists); + // check if all lengths are equal + // This could be done with exceptions, but I found nothing related on ReasonML website. + let all_lengths_are_equal = + List.for_all(x => x == List.hd(lengths), List.tl(lengths)); + if (all_lengths_are_equal) { + let order_by_index = + List.fold_left( + // ordered_by_index: list(list(t)); item: packed version of list(t) + (ordered_by_index, lst) => + List.map2( + // We need a function that maps `(list(t), t)` to list(list(t) + (old_list, item) => [item, ...old_list], + ordered_by_index, + Constraint.unwrap_list(lst), + ), + // Initial version of empty list, in list(list(t)) + List.map(x => [x], Constraint.unwrap_list(List.hd(lists))), + // Rest of items + List.tl(lists), + ); + // Check if there are inconsistency in each element + List.fold_left( + (previous, item) => previous || is_inconsistent(~may, item), + may, + order_by_index, + ); + } else { + true; // Automatically inconsistent + }; + | (lists, other) => is_inconsistent(~may, other @ lists) + } + } }; -let rec is_indet = (e: DHExp.t): bool => - switch (e) { - | EmptyHole(_, _) => true - | NonEmptyHole(_, _, _, e) => is_final(e) - | _ => false - } -and is_final = (e: DHExp.t): bool => is_val(e) && is_indet(e); +let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => + is_inconsistent( + ~may=false, + Constraint.[And(truify(xi_cur), dual(falsify(xi_pre)))], + ); + +let is_exhaustive = (xi: Constraint.t): bool => + is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); \ No newline at end of file diff --git a/src/haz3lcore/dynamics/Sets.re b/src/haz3lcore/dynamics/Sets.re new file mode 100644 index 0000000000..67b6099709 --- /dev/null +++ b/src/haz3lcore/dynamics/Sets.re @@ -0,0 +1,23 @@ +module IntSet = + Set.Make({ + type t = int; + let compare = compare; + }); + +module BoolSet = + Set.Make({ + type t = bool; + let compare = compare; + }); + +module FloatSet = + Set.Make({ + type t = float; + let compare = compare; + }); + +module StringSet = + Set.Make({ + type t = float; + let compare = compare; + }); From 841224fad5398f9b23af1f648fd2a139d432b447 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 10 Sep 2023 17:09:26 -0400 Subject: [PATCH 022/141] Rebasing trial 2 step 1. --- opam.export | 94 ++++++++++++++++----------------- src/haz3lcore/dynamics/Incon.re | 2 +- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/opam.export b/opam.export index 0928befbcc..44e4bd2db1 100644 --- a/opam.export +++ b/opam.export @@ -3,20 +3,20 @@ compiler: ["ocaml-base-compiler.5.0.0"] roots: [ "ezjs_idb.0.1.1" "incr_dom.v0.15.1" - "lwt.5.6.1" + "lwt.5.7.0" "lwt-dllist.1.0.1" - "merlin.4.8-500" + "merlin.4.9-500" "ocaml-base-compiler.5.0.0" - "ocaml-lsp-server.1.15.1-5.0" - "ocamlformat.0.25.1" - "omd.1.3.2" + "ocaml-lsp-server.1.16.2" + "ocamlformat.0.26.0" + "omd.2.0.0~alpha4" "ppx_deriving.5.2.1" "ppx_yojson_conv.v0.15.1" "ptmap.2.0.5" - "reason.3.8.2" - "tezt.3.0.0" + "reason.3.9.0" + "tezt.3.1.1" "unionFind.20220122" - "utop.2.11.0" + "utop.2.13.1" "uuidm.0.9.8" ] installed: [ @@ -38,28 +38,28 @@ installed: [ "bigstringaf.0.9.1" "bin_prot.v0.15.0" "camlp-streams.5.0.1" - "chrome-trace.3.7.0" - "cmdliner.1.1.1" + "chrome-trace.3.10.0" + "cmdliner.1.2.0" "conf-autoconf.0.1" "conf-which.1" "core.v0.15.1" "core_kernel.v0.15.0" "cppo.1.6.9" - "csexp.1.5.1" + "csexp.1.5.2" "cstruct.6.2.0" - "dot-merlin-reader.4.6" - "dune.3.7.0" - "dune-build-info.3.7.0" - "dune-configurator.3.7.0" - "dune-rpc.3.6.2" - "dyn.3.6.2" + "dot-merlin-reader.4.9" + "dune.3.10.0" + "dune-build-info.3.10.0" + "dune-configurator.3.10.0" + "dune-rpc.3.10.0" + "dyn.3.10.0" "either.1.0.0" "ezjs_idb.0.1.1" "ezjs_min.0.3.0" "ezjsonm.1.3.0" - "fiber.3.6.2" + "fiber.3.7.0" "fieldslib.v0.15.0" - "fix.20220121" + "fix.20230505" "fmt.0.9.0" "fpath.0.7.3" "gen.1.1" @@ -71,24 +71,24 @@ installed: [ "incremental.v0.15.0" "int_repr.v0.15.0" "jane-street-headers.v0.15.0" - "js_of_ocaml.4.1.0" - "js_of_ocaml-compiler.4.1.0" - "js_of_ocaml-ppx.4.1.0" + "js_of_ocaml.5.4.0" + "js_of_ocaml-compiler.5.4.0" + "js_of_ocaml-ppx.5.4.0" "jsonm.1.0.2" "jst-config.v0.15.1" - "lambda-term.3.3.1" + "lambda-term.3.3.2" "lambdasoup.1.0.0" "logs.0.7.0" - "lwt.5.6.1" + "lwt.5.7.0" "lwt-dllist.1.0.1" "lwt_react.1.2.0" "markup.1.0.3" - "menhir.20220210" - "menhirLib.20220210" - "menhirSdk.20220210" - "merlin.4.8-500" + "menhir.20230608" + "menhirLib.20230608" + "menhirSdk.20230608" + "merlin.4.9-500" "merlin-extend.0.6.1" - "merlin-lib.4.8-500" + "merlin-lib.4.9-500" "mew.0.1.0" "mew_vi.0.5.0" "num.1.4" @@ -96,28 +96,28 @@ installed: [ "ocaml-base-compiler.5.0.0" "ocaml-compiler-libs.v0.12.4" "ocaml-config.3" - "ocaml-lsp-server.1.15.1-5.0" + "ocaml-lsp-server.1.16.2" "ocaml-options-vanilla.1" "ocaml-syntax-shims.1.0.0" "ocaml-version.3.6.1" "ocamlbuild.0.14.2" - "ocamlc-loc.3.6.2" + "ocamlc-loc.3.10.0" "ocamlfind.1.9.6" - "ocamlformat.0.25.1" - "ocamlformat-lib.0.25.1" - "ocamlformat-rpc-lib.0.25.1" + "ocamlformat.0.26.0" + "ocamlformat-lib.0.26.0" + "ocamlformat-rpc-lib.0.26.0" "ocp-indent.1.8.1" "ocplib-endian.1.2" "octavius.1.2.2" "odoc-parser.2.0.0" "ojs.1.1.2" - "omd.1.3.2" - "ordering.3.6.2" + "omd.2.0.0~alpha4" + "ordering.3.10.0" "parsexp.v0.15.0" "pp.1.1.2" "ppx_assert.v0.15.0" "ppx_base.v0.15.0" - "ppx_bench.v0.15.0" + "ppx_bench.v0.15.1" "ppx_bin_prot.v0.15.0" "ppx_cold.v0.15.0" "ppx_compare.v0.15.0" @@ -132,7 +132,7 @@ installed: [ "ppx_hash.v0.15.0" "ppx_here.v0.15.0" "ppx_ignore_instrumentation.v0.15.0" - "ppx_inline_test.v0.15.0" + "ppx_inline_test.v0.15.1" "ppx_jane.v0.15.0" "ppx_js_style.v0.15.0" "ppx_let.v0.15.0" @@ -151,14 +151,14 @@ installed: [ "ppx_variants_conv.v0.15.0" "ppx_yojson_conv.v0.15.1" "ppx_yojson_conv_lib.v0.15.0" - "ppxlib.0.28.0" + "ppxlib.0.30.0" "protocol_version_header.v0.15.0" "ptmap.2.0.5" "re.1.10.4" "react.1.2.2" - "reason.3.8.2" + "reason.3.9.0" "result.1.5" - "sedlex.3.1" + "sedlex.3.2" "seq.base" "sexplib.v0.15.1" "sexplib0.v0.15.1" @@ -167,9 +167,9 @@ installed: [ "stdcompat.19" "stdio.v0.15.0" "stdlib-shims.0.3.0" - "stdune.3.6.2" + "stdune.3.10.0" "stringext.1.6.0" - "tezt.3.0.0" + "tezt.3.1.1" "time_now.v0.15.0" "topkg.1.0.7" "trie.1.0.0" @@ -179,7 +179,7 @@ installed: [ "unionFind.20220122" "uri.4.2.0" "uri-sexp.4.2.0" - "utop.2.11.0" + "utop.2.13.1" "uucp.15.0.0" "uuidm.0.9.8" "uunf.15.0.0" @@ -187,9 +187,9 @@ installed: [ "uutf.1.0.3" "variantslib.v0.15.0" "virtual_dom.v0.15.1" - "xdg.3.7.0" - "yojson.2.0.2" - "zed.3.2.1" + "xdg.3.10.0" + "yojson.2.1.0" + "zed.3.2.3" ] pinned: [ "async_js.v0.15.1" diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 204d181cb6..8b9bd7b02d 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -243,4 +243,4 @@ let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => ); let is_exhaustive = (xi: Constraint.t): bool => - is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); \ No newline at end of file + is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); From 1635b427f4a78d51343bc1c5f1e4f6e583ebfac7 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Tue, 1 Aug 2023 21:16:36 +0800 Subject: [PATCH 023/141] Rebase the project on `adt_defs_after` instead of `dev`. --- src/haz3lcore/tiles/Id.re | 67 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/haz3lcore/tiles/Id.re b/src/haz3lcore/tiles/Id.re index c4f3af6036..388087cc11 100644 --- a/src/haz3lcore/tiles/Id.re +++ b/src/haz3lcore/tiles/Id.re @@ -32,6 +32,73 @@ */ +/* ID FAQ + + WHAT ARE IDS USED FOR? + + Unique ids are assigned to tiles (and hence, indirectly, to terms) + at the time of creation of surface syntax. Ids are used as keys in + various maps (mostly notably the Measured map, which tracks screen + coordinates for the view, and the Info map which collects static + data such as type information). + + BUT WHY IS THERE A _LIST_ OF IDS? + + Technically, each tile has a list of ids, to support n-ary forms like + tuples; there are rep_id functions in Term to canonically extract + single representative ids from this list where appropriate. + + HOW ARE NEW IDS CREATED? + + In the parts of the implementation which manipulate Zippers, fresh id + creation is done by threading an IdGen parameter through all of the + (functions which call) functions where new tiles can be created. This + generally follows the state monad pattern. When a fresh Id is required, + the current value of the IdGen is used, and the IdGen is incremented + and must then be returned to the caller. + + The threading of IdGen through essentially all syntax modification + functions presents a significant complication for the action code, + and may eventually be replaced it with a mutable ref. + + WHERE DOES IDGEN LIVE? + + The initial IdGen passed to zipper functions is generally packaged + along with a zipper through the Zipper.state type. Although in + principle the initial IdGen could be set by traversing the zipper + and finding the largest Id, to avoid this traversal we track the + IdGen along with the zipper state. Each editor mode is responsible + for this tracking. Ultimately, each zipper action which can result in + new Ids being created must be sandwiched by calls to + Editors.get_editor_and_id and Editors.put_editor_and_id, to ensure that + IdGen state is tracked between actions and properly serialized to + local storage. + + HOW DO I GENERATE FRESH IDS FOR MY USE CASE? + + Currently there is no easy way to generate fresh IDs in places one + might concievably want them after Term creation, for example in the + elaborator or evaluator. Doing so is a significant change with + indirect implications for architrcture and performance; ask Andrew + about your use case before attempting this. For some uses, a dummy id + may be sufficient; this should be documented and use Id.invalid or + another similar label rather than magic literals. If you do need to + generated genuinely fresh IDs, then you'll need (A) a strategy + to route an IdGen to/from your use site to the aformentioned + Editors functions, and a traversal/mutation strategy within your + context of use. + + IDS IN DYNAMICS: + + Currently, DHExps (as produced by the elaborator and produced/consumed + by the evaluator) do not in general persist ids; the exceptions are + things like holes and tests which have additional metadata which is + accumulated duting evaluation. There are many use cases for tracking + ids more generally during evaluation, but doing so in a principled + way is a large-scale change with architectural implications. + + */ + [@deriving (show({with_path: false}), sexp, yojson)] let sexp_of_t: Uuidm.t => Sexplib.Sexp.t = t => Sexplib.Sexp.Atom(Uuidm.to_string(t)); From 4da6ccb329fad06b964a5fc354ff20dde1bda75f Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sun, 27 Aug 2023 09:54:46 -0400 Subject: [PATCH 024/141] Fixed a bug related to incomplete rebasing. --- src/haz3lcore/dynamics/Constraint.re | 5 +---- src/haz3lcore/dynamics/InvalidOperationError.re | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 1388e2fde6..0a4b705a2d 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -19,10 +19,7 @@ type t = // How to replace this function? let rec constrains = (c: t, ty: Typ.t): bool => - switch ( - c, - Typ.weak_head_normalize(Builtins.ctx(Builtins.Pervasives.builtins), ty), - ) { + switch (c, Typ.weak_head_normalize(Builtins.ctx_init, ty)) { | (Truth, _) | (Falsity, _) | (Hole, _) => true diff --git a/src/haz3lcore/dynamics/InvalidOperationError.re b/src/haz3lcore/dynamics/InvalidOperationError.re index 858e7b0757..3a6e31c35f 100644 --- a/src/haz3lcore/dynamics/InvalidOperationError.re +++ b/src/haz3lcore/dynamics/InvalidOperationError.re @@ -5,8 +5,8 @@ type t = | DivideByZero | NegativeExponent | OutOfFuel - | InvalidIntOfString - | InvalidFloatOfString + // | InvalidIntOfString + // | InvalidFloatOfString | InvalidProjection; let err_msg = (err: t): string => @@ -16,7 +16,7 @@ let err_msg = (err: t): string => | DivideByZero => "Error: Divide by Zero" | NegativeExponent => "Error: Negative Exponent in Integer Exponentiation (Consider using **.)" | OutOfFuel => "Error: Out of Fuel" - | InvalidIntOfString => "Error: Invalid String to Int Conversion" - | InvalidFloatOfString => "Error: Invalid String to Float Conversion" + // | InvalidIntOfString => "Error: Invalid String to Int Conversion" + // | InvalidFloatOfString => "Error: Invalid String to Float Conversion" | InvalidProjection => "Error: Invalid Projection" }; From 7ba2672af57bed7f5276cd5e701d6d41aa74621d Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Wed, 13 Sep 2023 07:16:00 -0400 Subject: [PATCH 025/141] Rebasing trial 2 step 2. --- src/haz3lcore/zipper/Touched.re | 4 +++- src/haz3lweb/util/JsUtil.re | 3 +-- src/haz3lweb/util/WeakMap.re | 6 ++---- src/lwtutil/Lwt_timed.re | 8 ++++++-- src/pretty/Box.rei | 4 +++- src/pretty/MeasuredLayout.rei | 4 +++- src/util/Monads.re | 2 +- src/util/StateMonad.re | 4 +++- src/util/StateMonad.rei | 4 +++- 9 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/haz3lcore/zipper/Touched.re b/src/haz3lcore/zipper/Touched.re index 70644f9c2b..2a428deb28 100644 --- a/src/haz3lcore/zipper/Touched.re +++ b/src/haz3lcore/zipper/Touched.re @@ -1,7 +1,9 @@ include Id.Map; type t = Id.Map.t(Time.t); -module type S = {let touched: t;}; +module type S = { + let touched: t; +}; let update = (t: Time.t, es: list(Effect.t), td: t) => es diff --git a/src/haz3lweb/util/JsUtil.re b/src/haz3lweb/util/JsUtil.re index 87501bbcc1..1b8685f6b3 100644 --- a/src/haz3lweb/util/JsUtil.re +++ b/src/haz3lweb/util/JsUtil.re @@ -11,8 +11,7 @@ let get_elem_by_id = id => { }; let date_now = () => { - %js - new Js.date_now; + [%js new Js.date_now]; }; let timestamp = () => date_now()##valueOf; diff --git a/src/haz3lweb/util/WeakMap.re b/src/haz3lweb/util/WeakMap.re index edf5fda68d..a3ab0951a9 100644 --- a/src/haz3lweb/util/WeakMap.re +++ b/src/haz3lweb/util/WeakMap.re @@ -16,8 +16,7 @@ module JsMap = { let mk: 'k 'v. unit => t('k, 'v) = () => { let c = Js.Unsafe.global##._Map; - %js - new c; + [%js new c]; }; }; @@ -27,8 +26,7 @@ module JsWeakMap = { let mk: 'k 'v. unit => t('k, 'v) = () => { let c = Js.Unsafe.global##._WeakMap; - %js - new c; + [%js new c]; }; }; diff --git a/src/lwtutil/Lwt_timed.re b/src/lwtutil/Lwt_timed.re index 5eeca72433..e17b77e5f8 100644 --- a/src/lwtutil/Lwt_timed.re +++ b/src/lwtutil/Lwt_timed.re @@ -1,8 +1,12 @@ open Lwt.Infix; -module type TIMER = {let delay: (unit => unit, int) => unit;}; +module type TIMER = { + let delay: (unit => unit, int) => unit; +}; -module type S = {let wrap: (int, Lwt.t('a)) => Lwt.t(option('a));}; +module type S = { + let wrap: (int, Lwt.t('a)) => Lwt.t(option('a)); +}; exception TimedOut; module Make = (T: TIMER) => { diff --git a/src/pretty/Box.rei b/src/pretty/Box.rei index f19613be50..67bb197242 100644 --- a/src/pretty/Box.rei +++ b/src/pretty/Box.rei @@ -29,4 +29,6 @@ type t('annot) = | VBox(list(t('annot))) | Annot('annot, t('annot)); -module Make: (MemoTbl.S) => {let mk: Layout.t('annot) => t('annot);}; +module Make: (MemoTbl.S) => { + let mk: Layout.t('annot) => t('annot); + }; diff --git a/src/pretty/MeasuredLayout.rei b/src/pretty/MeasuredLayout.rei index 8ebc6dbf74..428cbb85e6 100644 --- a/src/pretty/MeasuredLayout.rei +++ b/src/pretty/MeasuredLayout.rei @@ -97,4 +97,6 @@ let pos_fold: let next_position: (~indent: int, MeasuredPosition.t, t(_)) => MeasuredPosition.t; -module Make: (MemoTbl.S) => {let mk: Layout.t('annot) => t('annot);}; +module Make: (MemoTbl.S) => { + let mk: Layout.t('annot) => t('annot); + }; diff --git a/src/util/Monads.re b/src/util/Monads.re index 394f695a0e..dea4a3f872 100644 --- a/src/util/Monads.re +++ b/src/util/Monads.re @@ -74,4 +74,4 @@ module Make_Monad_Z = (M: MONAD_ZIP) => { }; module Make_Monad_B = (M: MONAD_BASIC) => - Make_Monad_Z((Make_Zip((Make_Functor(M))))); + Make_Monad_Z(Make_Zip(Make_Functor(M))); diff --git a/src/util/StateMonad.re b/src/util/StateMonad.re index b86fb19fe9..3209f9c1cd 100644 --- a/src/util/StateMonad.re +++ b/src/util/StateMonad.re @@ -1,4 +1,6 @@ -module type STATE = {type t;}; +module type STATE = { + type t; +}; module type S = { type state; diff --git a/src/util/StateMonad.rei b/src/util/StateMonad.rei index 96eed96261..42a668f00e 100644 --- a/src/util/StateMonad.rei +++ b/src/util/StateMonad.rei @@ -5,7 +5,9 @@ /** State type module specification. */ -module type STATE = {type t;}; +module type STATE = { + type t; +}; /** Output of the functor [Make]. From 0e7bbd182d99ee56caba9f73195cbb19a564f7dc Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Wed, 13 Sep 2023 20:39:43 -0400 Subject: [PATCH 026/141] Fixed (?) dependencies and reformat in compilation. --- opam.export | 45 +++++++++++++++++---------------- src/haz3lcore/zipper/Touched.re | 4 +-- src/haz3lweb/util/JsUtil.re | 3 ++- src/haz3lweb/util/WeakMap.re | 6 +++-- src/lwtutil/Lwt_timed.re | 8 ++---- src/pretty/Box.rei | 4 +-- src/pretty/MeasuredLayout.rei | 4 +-- src/util/Monads.re | 2 +- src/util/StateMonad.re | 4 +-- src/util/StateMonad.rei | 4 +-- 10 files changed, 37 insertions(+), 47 deletions(-) diff --git a/opam.export b/opam.export index dff3abe30a..0928befbcc 100644 --- a/opam.export +++ b/opam.export @@ -3,20 +3,20 @@ compiler: ["ocaml-base-compiler.5.0.0"] roots: [ "ezjs_idb.0.1.1" "incr_dom.v0.15.1" - "lwt.5.7.0" + "lwt.5.6.1" "lwt-dllist.1.0.1" - "merlin.4.9-500" + "merlin.4.8-500" "ocaml-base-compiler.5.0.0" - "ocaml-lsp-server.1.16.2" - "ocamlformat.0.26.0" - "omd.2.0.0~alpha4" + "ocaml-lsp-server.1.15.1-5.0" + "ocamlformat.0.25.1" + "omd.1.3.2" "ppx_deriving.5.2.1" "ppx_yojson_conv.v0.15.1" "ptmap.2.0.5" - "reason.3.9.0" - "tezt.3.1.1" + "reason.3.8.2" + "tezt.3.0.0" "unionFind.20220122" - "utop.2.13.1" + "utop.2.11.0" "uuidm.0.9.8" ] installed: [ @@ -38,28 +38,28 @@ installed: [ "bigstringaf.0.9.1" "bin_prot.v0.15.0" "camlp-streams.5.0.1" - "chrome-trace.3.10.0" - "cmdliner.1.2.0" + "chrome-trace.3.7.0" + "cmdliner.1.1.1" "conf-autoconf.0.1" "conf-which.1" "core.v0.15.1" "core_kernel.v0.15.0" "cppo.1.6.9" - "csexp.1.5.2" + "csexp.1.5.1" "cstruct.6.2.0" - "dot-merlin-reader.4.9" - "dune.3.10.0" - "dune-build-info.3.10.0" - "dune-configurator.3.10.0" - "dune-rpc.3.10.0" - "dyn.3.10.0" + "dot-merlin-reader.4.6" + "dune.3.7.0" + "dune-build-info.3.7.0" + "dune-configurator.3.7.0" + "dune-rpc.3.6.2" + "dyn.3.6.2" "either.1.0.0" "ezjs_idb.0.1.1" "ezjs_min.0.3.0" "ezjsonm.1.3.0" - "fiber.3.7.0" + "fiber.3.6.2" "fieldslib.v0.15.0" - "fix.20230505" + "fix.20220121" "fmt.0.9.0" "fpath.0.7.3" "gen.1.1" @@ -71,9 +71,9 @@ installed: [ "incremental.v0.15.0" "int_repr.v0.15.0" "jane-street-headers.v0.15.0" - "js_of_ocaml.5.4.0" - "js_of_ocaml-compiler.5.4.0" - "js_of_ocaml-ppx.5.4.0" + "js_of_ocaml.4.1.0" + "js_of_ocaml-compiler.4.1.0" + "js_of_ocaml-ppx.4.1.0" "jsonm.1.0.2" "jst-config.v0.15.1" "lambda-term.3.3.1" @@ -181,6 +181,7 @@ installed: [ "uri-sexp.4.2.0" "utop.2.11.0" "uucp.15.0.0" + "uuidm.0.9.8" "uunf.15.0.0" "uuseg.15.0.0" "uutf.1.0.3" diff --git a/src/haz3lcore/zipper/Touched.re b/src/haz3lcore/zipper/Touched.re index 2a428deb28..70644f9c2b 100644 --- a/src/haz3lcore/zipper/Touched.re +++ b/src/haz3lcore/zipper/Touched.re @@ -1,9 +1,7 @@ include Id.Map; type t = Id.Map.t(Time.t); -module type S = { - let touched: t; -}; +module type S = {let touched: t;}; let update = (t: Time.t, es: list(Effect.t), td: t) => es diff --git a/src/haz3lweb/util/JsUtil.re b/src/haz3lweb/util/JsUtil.re index 1b8685f6b3..87501bbcc1 100644 --- a/src/haz3lweb/util/JsUtil.re +++ b/src/haz3lweb/util/JsUtil.re @@ -11,7 +11,8 @@ let get_elem_by_id = id => { }; let date_now = () => { - [%js new Js.date_now]; + %js + new Js.date_now; }; let timestamp = () => date_now()##valueOf; diff --git a/src/haz3lweb/util/WeakMap.re b/src/haz3lweb/util/WeakMap.re index a3ab0951a9..edf5fda68d 100644 --- a/src/haz3lweb/util/WeakMap.re +++ b/src/haz3lweb/util/WeakMap.re @@ -16,7 +16,8 @@ module JsMap = { let mk: 'k 'v. unit => t('k, 'v) = () => { let c = Js.Unsafe.global##._Map; - [%js new c]; + %js + new c; }; }; @@ -26,7 +27,8 @@ module JsWeakMap = { let mk: 'k 'v. unit => t('k, 'v) = () => { let c = Js.Unsafe.global##._WeakMap; - [%js new c]; + %js + new c; }; }; diff --git a/src/lwtutil/Lwt_timed.re b/src/lwtutil/Lwt_timed.re index e17b77e5f8..5eeca72433 100644 --- a/src/lwtutil/Lwt_timed.re +++ b/src/lwtutil/Lwt_timed.re @@ -1,12 +1,8 @@ open Lwt.Infix; -module type TIMER = { - let delay: (unit => unit, int) => unit; -}; +module type TIMER = {let delay: (unit => unit, int) => unit;}; -module type S = { - let wrap: (int, Lwt.t('a)) => Lwt.t(option('a)); -}; +module type S = {let wrap: (int, Lwt.t('a)) => Lwt.t(option('a));}; exception TimedOut; module Make = (T: TIMER) => { diff --git a/src/pretty/Box.rei b/src/pretty/Box.rei index 67bb197242..f19613be50 100644 --- a/src/pretty/Box.rei +++ b/src/pretty/Box.rei @@ -29,6 +29,4 @@ type t('annot) = | VBox(list(t('annot))) | Annot('annot, t('annot)); -module Make: (MemoTbl.S) => { - let mk: Layout.t('annot) => t('annot); - }; +module Make: (MemoTbl.S) => {let mk: Layout.t('annot) => t('annot);}; diff --git a/src/pretty/MeasuredLayout.rei b/src/pretty/MeasuredLayout.rei index 428cbb85e6..8ebc6dbf74 100644 --- a/src/pretty/MeasuredLayout.rei +++ b/src/pretty/MeasuredLayout.rei @@ -97,6 +97,4 @@ let pos_fold: let next_position: (~indent: int, MeasuredPosition.t, t(_)) => MeasuredPosition.t; -module Make: (MemoTbl.S) => { - let mk: Layout.t('annot) => t('annot); - }; +module Make: (MemoTbl.S) => {let mk: Layout.t('annot) => t('annot);}; diff --git a/src/util/Monads.re b/src/util/Monads.re index dea4a3f872..394f695a0e 100644 --- a/src/util/Monads.re +++ b/src/util/Monads.re @@ -74,4 +74,4 @@ module Make_Monad_Z = (M: MONAD_ZIP) => { }; module Make_Monad_B = (M: MONAD_BASIC) => - Make_Monad_Z(Make_Zip(Make_Functor(M))); + Make_Monad_Z((Make_Zip((Make_Functor(M))))); diff --git a/src/util/StateMonad.re b/src/util/StateMonad.re index 3209f9c1cd..b86fb19fe9 100644 --- a/src/util/StateMonad.re +++ b/src/util/StateMonad.re @@ -1,6 +1,4 @@ -module type STATE = { - type t; -}; +module type STATE = {type t;}; module type S = { type state; diff --git a/src/util/StateMonad.rei b/src/util/StateMonad.rei index 42a668f00e..96eed96261 100644 --- a/src/util/StateMonad.rei +++ b/src/util/StateMonad.rei @@ -5,9 +5,7 @@ /** State type module specification. */ -module type STATE = { - type t; -}; +module type STATE = {type t;}; /** Output of the functor [Make]. From da33210b4e396231db8ea763aeab1605a0fef4bb Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Fri, 15 Sep 2023 19:24:20 -0400 Subject: [PATCH 027/141] Revised the description of inconsistency checking for list to Nil/Cons model. --- src/haz3lcore/dynamics/Incon.re | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 8b9bd7b02d..5732904d1f 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -185,10 +185,12 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => | (fs, other) => is_inconsistent(~may, other @ fs) } /* - * Thoughts for porting the Pair judgment to list: - * Two list constraints are automatically inconsistent if they have different length. - * So we first find maximum and minimum list lengths, and determine if they are the same. - * If so, we rearrange them in item-first order, and check each of them. + * Explanation for the check of inconsistency for list: + * List can be thought as the type (Nil(Unit) + Cons(Item, List)), or alternatively (Unit + (Item × List)). + * Thus by analogy with InjL and InjR, an empty list is inconsistent with a non-empty one, which means that two + * lists of different lengths are automatically inconsistent. If all lists are having the same length, then I + * will compare them from left to right (aka in the order of unfolding them) to see if any item in the same + * position are inconsistent. This version may be inefficient, but I am running out of ideas to optimize it. */ | List(_) => switch ( From a19bc2f8141262be83146155df200fae6a1cbf4c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 20 Sep 2023 18:31:50 -0400 Subject: [PATCH 028/141] Init --- src/haz3lcore/statics/Statics.re | 1 + 1 file changed, 1 insertion(+) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index f5962cce77..2878b18f04 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -283,6 +283,7 @@ and uexp_to_info_map = es, p_ctxs, ); + let rec ruls_to_info_map = (xi_pre: Constraint.t, m) => (xi_pre, m); let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); From e0fbe8da05619ecc0263d05b6d9a642c04ef65f6 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sat, 23 Sep 2023 21:49:07 -0400 Subject: [PATCH 029/141] Return `Constraint.re` and `Incon.re` to their old version. --- src/haz3lcore/dynamics/Constraint.re | 48 ++++++++++--------------- src/haz3lcore/dynamics/Incon.re | 53 +++++++--------------------- 2 files changed, 31 insertions(+), 70 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 0a4b705a2d..21cb280ad3 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -15,9 +15,8 @@ type t = | Or(t, t) | InjL(t) | InjR(t) - | List(list(t)); + | Pair(t, t); -// How to replace this function? let rec constrains = (c: t, ty: Typ.t): bool => switch (c, Typ.weak_head_normalize(Builtins.ctx_init, ty)) { | (Truth, _) @@ -45,15 +44,7 @@ let rec constrains = (c: t, ty: Typ.t): bool => | map' => constrains(c2, Sum(map')) } | (InjR(_), _) => false - | (List(c), ty) => - List.fold_left((last, x) => last && constrains(x, ty), true, c) - }; - -let rec or_constraints = (lst: list(t)): t => - switch (lst) { - | [] => failwith("should have at least one constraint") - | [xi] => xi - | [xi, ...xis] => Or(xi, or_constraints(xis)) + | (Pair(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) }; let rec dual = (c: t): t => @@ -71,19 +62,11 @@ let rec dual = (c: t): t => | Or(c1, c2) => And(dual(c1), dual(c2)) | InjL(c1) => Or(InjL(dual(c1)), InjR(Truth)) | InjR(c2) => Or(InjR(dual(c2)), InjL(Truth)) - // Thought: generate all combinations of ways to dual the list (2^n - 1), and connect them with or - | List(l) => - let permutation = List.map(l' => List(l'), List.tl(permutate(l))); - // ``Or'' is associative, so I try to use this way to simplify it - or_constraints(permutation); - } -and permutate = (l: list(t)): list(list(t)) => - switch (l) { - | [] => [[]] - | [hd, ...tl] => - let result_tl = permutate(tl); - List.map(l' => [hd, ...l'], result_tl) - @ List.map(l' => [dual(hd), ...l'], result_tl); + | Pair(c1, c2) => + Or( + Pair(c1, dual(c2)), + Or(Pair(dual(c1), c2), Pair(dual(c1), dual(c2))), + ) }; /** substitute Truth for Hole */ @@ -102,7 +85,7 @@ let rec truify = (c: t): t => | Or(c1, c2) => Or(truify(c1), truify(c2)) | InjL(c) => InjL(truify(c)) | InjR(c) => InjR(truify(c)) - | List(l) => List(List.map(c => truify(c), l)) + | Pair(c1, c2) => Pair(truify(c1), truify(c2)) }; /** substitute Falsity for Hole */ @@ -121,7 +104,7 @@ let rec falsify = (c: t): t => | Or(c1, c2) => Or(falsify(c1), falsify(c2)) | InjL(c) => InjL(falsify(c)) | InjR(c) => InjR(falsify(c)) - | List(l) => List(List.map(c => falsify(c), l)) + | Pair(c1, c2) => Pair(falsify(c1), falsify(c2)) }; let unwrapL = @@ -134,7 +117,14 @@ let unwrapR = | InjR(c) => c | _ => failwith("input can only be InjR(_)"); -let unwrap_list = +let unwrap_pair = fun - | List(l) => l - | _ => failwith("input can only be List([_, ..._])"); + | Pair(c1, c2) => (c1, c2) + | _ => failwith("input can only be pair(_, _)"); + +let rec or_constraints = (lst: list(t)): t => + switch (lst) { + | [] => failwith("should have at least one constraint") + | [xi] => xi + | [xi, ...xis] => Or(xi, or_constraints(xis)) + }; diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 5732904d1f..5d41604928 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -184,56 +184,27 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => | (fs, []) => is_inconsistent_string(fs) | (fs, other) => is_inconsistent(~may, other @ fs) } - /* - * Explanation for the check of inconsistency for list: - * List can be thought as the type (Nil(Unit) + Cons(Item, List)), or alternatively (Unit + (Item × List)). - * Thus by analogy with InjL and InjR, an empty list is inconsistent with a non-empty one, which means that two - * lists of different lengths are automatically inconsistent. If all lists are having the same length, then I - * will compare them from left to right (aka in the order of unfolding them) to see if any item in the same - * position are inconsistent. This version may be inefficient, but I am running out of ideas to optimize it. - */ - | List(_) => + | Pair(_, _) => switch ( List.partition( fun - | Constraint.List(_) => true + | Constraint.Pair(_) => true | _ => false, xis, ) ) { - | (lists, []) => - let lengths = - List.map(x => List.length(Constraint.unwrap_list(x)), lists); - // check if all lengths are equal - // This could be done with exceptions, but I found nothing related on ReasonML website. - let all_lengths_are_equal = - List.for_all(x => x == List.hd(lengths), List.tl(lengths)); - if (all_lengths_are_equal) { - let order_by_index = - List.fold_left( - // ordered_by_index: list(list(t)); item: packed version of list(t) - (ordered_by_index, lst) => - List.map2( - // We need a function that maps `(list(t), t)` to list(list(t) - (old_list, item) => [item, ...old_list], - ordered_by_index, - Constraint.unwrap_list(lst), - ), - // Initial version of empty list, in list(list(t)) - List.map(x => [x], Constraint.unwrap_list(List.hd(lists))), - // Rest of items - List.tl(lists), - ); - // Check if there are inconsistency in each element + | (pairs, []) => + let (xisL, xisR) = List.fold_left( - (previous, item) => previous || is_inconsistent(~may, item), - may, - order_by_index, + ((xisL, xisR), pair) => { + let (xiL, xiR) = Constraint.unwrap_pair(pair); + ([xiL, ...xisL], [xiR, ...xisR]); + }, + ([], []), + pairs, ); - } else { - true; // Automatically inconsistent - }; - | (lists, other) => is_inconsistent(~may, other @ lists) + is_inconsistent(~may, xisL) || is_inconsistent(~may, xisR); + | (pairs, other) => is_inconsistent(~may, other @ pairs) } } }; From 1022c550dab82613922b411fd5a0750bc3813da7 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 27 Sep 2023 12:58:24 -0400 Subject: [PATCH 030/141] Initialized error_exp.InexhaustiveMatch --- src/haz3lcore/statics/Info.re | 1 + src/haz3lcore/statics/Statics.re | 2 +- src/haz3lweb/view/CursorInspector.re | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 69d3871db6..7fcc9b16d8 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -64,6 +64,7 @@ type error_common = [@deriving (show({with_path: false}), sexp, yojson)] type error_exp = | FreeVariable(Var.t) /* Unbound variable (not in typing context) */ + | InexhaustiveMatch(option(error_common)) /* Inexhaustive match (optional inconsistent types error) */ | Common(error_common); [@deriving (show({with_path: false}), sexp, yojson)] diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 9aa4142d94..2da2ca6bb4 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -283,7 +283,7 @@ and uexp_to_info_map = es, p_ctxs, ); - let rec ruls_to_info_map = (xi_pre: Constraint.t, m) => (xi_pre, m); + // let rec ruls_to_info_map = (xi_pre: Constraint.t, m) => (xi_pre, m); let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 821e92a48a..86070d4ed0 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -161,6 +161,16 @@ let exp_view = (cls: Term.Cls.t, status: Info.status_exp) => switch (status) { | InHole(FreeVariable(name)) => div_err([code_err(name), text("not found")]) + | InHole(InexhaustiveMatch(type_err)) => + let inexhaustive_err_text = "Case expression is necessarily inexhaustive"; + switch (type_err) { + | None => div_err([text(inexhaustive_err_text)]) + | Some(type_err) => + div_err([ + text(inexhaustive_err_text ++ "; "), + ...common_err_view(Exp(Match), type_err), + ]) + }; | InHole(Common(error)) => div_err(common_err_view(cls, error)) | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) }; From 70996ad1a13366406f17c55faf3b40e9469c19f8 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 27 Sep 2023 14:46:21 -0400 Subject: [PATCH 031/141] Add a new reason to have DHExp.InconsistentBranches in elaborator --- src/haz3lcore/dynamics/Elaborator.re | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 47e2d484c2..e9b433b629 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -267,7 +267,8 @@ let rec dhexp_of_uexp = |> OptUtil.sequence; let d = DHExp.Case(d_scrut, d_rules, 0); switch (err_status) { - | InHole(Common(Inconsistent(Internal(_)))) => + | InHole(Common(Inconsistent(Internal(_)))) + | InHole(InexhaustiveMatch(Some(Inconsistent(Internal(_))))) => DHExp.InconsistentBranches(id, 0, d) | _ => ConsistentCase(d) }; From e179d767dfdefa3451d8a426bc5792d5bef75062 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 27 Sep 2023 14:49:30 -0400 Subject: [PATCH 032/141] Initialized Self.exp.InexhaustiveMatch --- src/haz3lcore/statics/Self.re | 1 + 1 file changed, 1 insertion(+) diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index f30c1e2e13..73be27fc01 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -35,6 +35,7 @@ type t = [@deriving (show({with_path: false}), sexp, yojson)] type exp = | Free(Var.t) + | InexhaustiveMatch(t) | Common(t); [@deriving (show({with_path: false}), sexp, yojson)] From f0b9fef18945b0a99e4d8c4bb1ed8592d62572a3 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 27 Sep 2023 15:42:57 -0400 Subject: [PATCH 033/141] Added more guards & updated Info.status_exp --- src/haz3lcore/statics/Info.re | 9 +++++++++ src/haz3lweb/view/CursorInspector.re | 12 ++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 7fcc9b16d8..8705e6c221 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -322,6 +322,15 @@ let status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => let status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => switch (self, mode) { | (Free(name), _) => InHole(FreeVariable(name)) + | (InexhaustiveMatch(self_pat), _) => + let inconsistent_err = + switch (status_common(ctx, mode, self_pat)) { + | NotInHole(_) => None + | InHole(Inconsistent(Internal(_)) as inconsistent_err) => + Some(inconsistent_err) + | _ => failwith("InexhaustiveMatch(non-inconsistent-types-error)") + }; + InexhaustiveMatch(inconsistent_err); | (Common(self_pat), _) => switch (status_common(ctx, mode, self_pat)) { | NotInHole(ok_exp) => NotInHole(ok_exp) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 86070d4ed0..1809245f22 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -161,15 +161,19 @@ let exp_view = (cls: Term.Cls.t, status: Info.status_exp) => switch (status) { | InHole(FreeVariable(name)) => div_err([code_err(name), text("not found")]) - | InHole(InexhaustiveMatch(type_err)) => + | InHole(InexhaustiveMatch(inconsistent_err)) => let inexhaustive_err_text = "Case expression is necessarily inexhaustive"; - switch (type_err) { + switch (inconsistent_err) { | None => div_err([text(inexhaustive_err_text)]) - | Some(type_err) => + | Some(Inconsistent(Internal(_)) as inconsistent_err) => div_err([ text(inexhaustive_err_text ++ "; "), - ...common_err_view(Exp(Match), type_err), + ...common_err_view(Exp(Match), inconsistent_err), ]) + | _ => + failwith( + "Case expression is necessarily inexhaustive; non-inconsistent-types-error", + ) }; | InHole(Common(error)) => div_err(common_err_view(cls, error)) | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) From b66c0ccf18e90a3dbc65922d63d62fa37cadee5a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 27 Sep 2023 15:54:24 -0400 Subject: [PATCH 034/141] Complete new self --- src/haz3lcore/statics/Info.re | 2 +- src/haz3lcore/statics/Self.re | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 8705e6c221..c8e3f456d5 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -330,7 +330,7 @@ let status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => Some(inconsistent_err) | _ => failwith("InexhaustiveMatch(non-inconsistent-types-error)") }; - InexhaustiveMatch(inconsistent_err); + InHole(InexhaustiveMatch(inconsistent_err)); | (Common(self_pat), _) => switch (status_common(ctx, mode, self_pat)) { | NotInHole(ok_exp) => NotInHole(ok_exp) diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index 73be27fc01..500ab0d89b 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -57,7 +57,8 @@ let typ_of: (Ctx.t, t) => option(Typ.t) = let typ_of_exp: (Ctx.t, exp) => option(Typ.t) = ctx => fun - | Free(_) => None + | Free(_) + | InexhaustiveMatch(_) => None | Common(self) => typ_of(ctx, self); let typ_of_pat: (Ctx.t, pat) => option(Typ.t) = From f8ff3c45caac7404a22006783c243493da2691da Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 27 Sep 2023 16:43:05 -0400 Subject: [PATCH 035/141] Fixed the bug about type inconsistency --- src/haz3lcore/statics/Info.re | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index c8e3f456d5..ec068a44ca 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -325,10 +325,11 @@ let status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => | (InexhaustiveMatch(self_pat), _) => let inconsistent_err = switch (status_common(ctx, mode, self_pat)) { - | NotInHole(_) => None | InHole(Inconsistent(Internal(_)) as inconsistent_err) => Some(inconsistent_err) - | _ => failwith("InexhaustiveMatch(non-inconsistent-types-error)") + | NotInHole(_) + | InHole(Inconsistent(Expectation(_) | WithArrow(_))) => None /* Type checking should fail */ + | InHole(NoType(_)) => failwith("InHole(InexhaustiveMatch(impossible_err))") }; InHole(InexhaustiveMatch(inconsistent_err)); | (Common(self_pat), _) => From bf4c052895dd4ae507b37b028c4765778845ac76 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 27 Sep 2023 16:44:47 -0400 Subject: [PATCH 036/141] Formatted --- src/haz3lcore/statics/Info.re | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index ec068a44ca..a770863dab 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -329,7 +329,8 @@ let status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => Some(inconsistent_err) | NotInHole(_) | InHole(Inconsistent(Expectation(_) | WithArrow(_))) => None /* Type checking should fail */ - | InHole(NoType(_)) => failwith("InHole(InexhaustiveMatch(impossible_err))") + | InHole(NoType(_)) => + failwith("InHole(InexhaustiveMatch(impossible_err))") }; InHole(InexhaustiveMatch(inconsistent_err)); | (Common(self_pat), _) => From 213ad9648e35e26229d50634e5039bcef0b6fc2a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 29 Sep 2023 09:15:02 -0400 Subject: [PATCH 037/141] Made InexhaustiveMatch more general --- src/haz3lcore/statics/Info.re | 13 +++++++------ src/haz3lcore/statics/Self.re | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index a770863dab..1480f3b154 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -319,17 +319,18 @@ let status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => depending on the mode, which represents the expectations of the surrounding syntactic context, and the self which represents the makeup of the expression / pattern itself. */ -let status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => +let rec status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => switch (self, mode) { | (Free(name), _) => InHole(FreeVariable(name)) - | (InexhaustiveMatch(self_pat), _) => + | (InexhaustiveMatch(self), _) => let inconsistent_err = - switch (status_common(ctx, mode, self_pat)) { - | InHole(Inconsistent(Internal(_)) as inconsistent_err) => + switch (status_exp(ctx, mode, self)) { + | InHole(Common(Inconsistent(Internal(_)) as inconsistent_err)) => Some(inconsistent_err) | NotInHole(_) - | InHole(Inconsistent(Expectation(_) | WithArrow(_))) => None /* Type checking should fail */ - | InHole(NoType(_)) => + | InHole(Common(Inconsistent(Expectation(_) | WithArrow(_)))) => None /* Type checking should fail */ + | InHole(Common(NoType(_))) + | InHole(FreeVariable(_) | InexhaustiveMatch(_)) => failwith("InHole(InexhaustiveMatch(impossible_err))") }; InHole(InexhaustiveMatch(inconsistent_err)); diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index 500ab0d89b..684b19b01b 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -35,7 +35,7 @@ type t = [@deriving (show({with_path: false}), sexp, yojson)] type exp = | Free(Var.t) - | InexhaustiveMatch(t) + | InexhaustiveMatch(exp) | Common(t); [@deriving (show({with_path: false}), sexp, yojson)] From c226608633887c2f47db6eb4515eb045735d5a66 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 29 Sep 2023 09:32:35 -0400 Subject: [PATCH 038/141] Making InexhaustiveMatch even more general! --- src/haz3lcore/dynamics/Elaborator.re | 4 +++- src/haz3lcore/statics/Info.re | 10 +++++----- src/haz3lweb/view/CursorInspector.re | 14 +++++--------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index e9b433b629..126dee2e21 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -268,7 +268,9 @@ let rec dhexp_of_uexp = let d = DHExp.Case(d_scrut, d_rules, 0); switch (err_status) { | InHole(Common(Inconsistent(Internal(_)))) - | InHole(InexhaustiveMatch(Some(Inconsistent(Internal(_))))) => + | InHole( + InexhaustiveMatch(Some(Common(Inconsistent(Internal(_))))), + ) => DHExp.InconsistentBranches(id, 0, d) | _ => ConsistentCase(d) }; diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 1480f3b154..57d9f71b4e 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -64,7 +64,7 @@ type error_common = [@deriving (show({with_path: false}), sexp, yojson)] type error_exp = | FreeVariable(Var.t) /* Unbound variable (not in typing context) */ - | InexhaustiveMatch(option(error_common)) /* Inexhaustive match (optional inconsistent types error) */ + | InexhaustiveMatch(option(error_exp)) | Common(error_common); [@deriving (show({with_path: false}), sexp, yojson)] @@ -323,17 +323,17 @@ let rec status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => switch (self, mode) { | (Free(name), _) => InHole(FreeVariable(name)) | (InexhaustiveMatch(self), _) => - let inconsistent_err = + let additional_err = switch (status_exp(ctx, mode, self)) { - | InHole(Common(Inconsistent(Internal(_)) as inconsistent_err)) => + | InHole(Common(Inconsistent(Internal(_))) as inconsistent_err) => Some(inconsistent_err) | NotInHole(_) - | InHole(Common(Inconsistent(Expectation(_) | WithArrow(_)))) => None /* Type checking should fail */ + | InHole(Common(Inconsistent(Expectation(_) | WithArrow(_)))) => None /* Type checking should fail and these errors would be nullified */ | InHole(Common(NoType(_))) | InHole(FreeVariable(_) | InexhaustiveMatch(_)) => failwith("InHole(InexhaustiveMatch(impossible_err))") }; - InHole(InexhaustiveMatch(inconsistent_err)); + InHole(InexhaustiveMatch(additional_err)); | (Common(self_pat), _) => switch (status_common(ctx, mode, self_pat)) { | NotInHole(ok_exp) => NotInHole(ok_exp) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 1809245f22..9576602b41 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -157,23 +157,19 @@ let typ_err_view = (ok: Info.error_typ) => ] }; -let exp_view = (cls: Term.Cls.t, status: Info.status_exp) => +let rec exp_view = (cls: Term.Cls.t, status: Info.status_exp) => switch (status) { | InHole(FreeVariable(name)) => div_err([code_err(name), text("not found")]) - | InHole(InexhaustiveMatch(inconsistent_err)) => + | InHole(InexhaustiveMatch(additional_err)) => let inexhaustive_err_text = "Case expression is necessarily inexhaustive"; - switch (inconsistent_err) { + switch (additional_err) { | None => div_err([text(inexhaustive_err_text)]) - | Some(Inconsistent(Internal(_)) as inconsistent_err) => + | Some(err) => div_err([ text(inexhaustive_err_text ++ "; "), - ...common_err_view(Exp(Match), inconsistent_err), + exp_view(Exp(Match), InHole(err)), ]) - | _ => - failwith( - "Case expression is necessarily inexhaustive; non-inconsistent-types-error", - ) }; | InHole(Common(error)) => div_err(common_err_view(cls, error)) | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) From 74b947a125b48ccd7fb9faf28aece4f3282a18bb Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 29 Sep 2023 09:40:32 -0400 Subject: [PATCH 039/141] Test --- src/haz3lcore/statics/Statics.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 2da2ca6bb4..70b92567ce 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -287,8 +287,8 @@ and uexp_to_info_map = let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - add( - ~self=Self.match(ctx, e_tys, branch_ids), + add'( + ~self=InexhaustiveMatch(Common(Self.match(ctx, e_tys, branch_ids))), ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m, ); From bbc8406e90642933d4abbb9370d79a04375ef833 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 29 Sep 2023 09:48:26 -0400 Subject: [PATCH 040/141] Make it less akaward --- src/haz3lweb/view/CursorInspector.re | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 9576602b41..6cc2adf8f6 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -162,15 +162,14 @@ let rec exp_view = (cls: Term.Cls.t, status: Info.status_exp) => | InHole(FreeVariable(name)) => div_err([code_err(name), text("not found")]) | InHole(InexhaustiveMatch(additional_err)) => - let inexhaustive_err_text = "Case expression is necessarily inexhaustive"; switch (additional_err) { - | None => div_err([text(inexhaustive_err_text)]) + | None => div_err([text("Case expression is necessarily inexhaustive")]) | Some(err) => div_err([ - text(inexhaustive_err_text ++ "; "), exp_view(Exp(Match), InHole(err)), + text("; case expression is necessarily inexhaustive"), ]) - }; + } | InHole(Common(error)) => div_err(common_err_view(cls, error)) | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) }; From 56d33fd0abf9c79fddcc67cd2004d0dabd720149 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 29 Sep 2023 10:21:47 -0400 Subject: [PATCH 041/141] Revert Id.re --- src/haz3lcore/tiles/Id.re | 67 --------------------------------------- 1 file changed, 67 deletions(-) diff --git a/src/haz3lcore/tiles/Id.re b/src/haz3lcore/tiles/Id.re index 00fcb693b7..29205c49e6 100644 --- a/src/haz3lcore/tiles/Id.re +++ b/src/haz3lcore/tiles/Id.re @@ -32,73 +32,6 @@ */ -/* ID FAQ - - WHAT ARE IDS USED FOR? - - Unique ids are assigned to tiles (and hence, indirectly, to terms) - at the time of creation of surface syntax. Ids are used as keys in - various maps (mostly notably the Measured map, which tracks screen - coordinates for the view, and the Info map which collects static - data such as type information). - - BUT WHY IS THERE A _LIST_ OF IDS? - - Technically, each tile has a list of ids, to support n-ary forms like - tuples; there are rep_id functions in Term to canonically extract - single representative ids from this list where appropriate. - - HOW ARE NEW IDS CREATED? - - In the parts of the implementation which manipulate Zippers, fresh id - creation is done by threading an IdGen parameter through all of the - (functions which call) functions where new tiles can be created. This - generally follows the state monad pattern. When a fresh Id is required, - the current value of the IdGen is used, and the IdGen is incremented - and must then be returned to the caller. - - The threading of IdGen through essentially all syntax modification - functions presents a significant complication for the action code, - and may eventually be replaced it with a mutable ref. - - WHERE DOES IDGEN LIVE? - - The initial IdGen passed to zipper functions is generally packaged - along with a zipper through the Zipper.state type. Although in - principle the initial IdGen could be set by traversing the zipper - and finding the largest Id, to avoid this traversal we track the - IdGen along with the zipper state. Each editor mode is responsible - for this tracking. Ultimately, each zipper action which can result in - new Ids being created must be sandwiched by calls to - Editors.get_editor_and_id and Editors.put_editor_and_id, to ensure that - IdGen state is tracked between actions and properly serialized to - local storage. - - HOW DO I GENERATE FRESH IDS FOR MY USE CASE? - - Currently there is no easy way to generate fresh IDs in places one - might concievably want them after Term creation, for example in the - elaborator or evaluator. Doing so is a significant change with - indirect implications for architrcture and performance; ask Andrew - about your use case before attempting this. For some uses, a dummy id - may be sufficient; this should be documented and use Id.invalid or - another similar label rather than magic literals. If you do need to - generated genuinely fresh IDs, then you'll need (A) a strategy - to route an IdGen to/from your use site to the aformentioned - Editors functions, and a traversal/mutation strategy within your - context of use. - - IDS IN DYNAMICS: - - Currently, DHExps (as produced by the elaborator and produced/consumed - by the evaluator) do not in general persist ids; the exceptions are - things like holes and tests which have additional metadata which is - accumulated duting evaluation. There are many use cases for tracking - ids more generally during evaluation, but doing so in a principled - way is a large-scale change with architectural implications. - - */ - [@deriving (show({with_path: false}), sexp, yojson)] let sexp_of_t: Uuidm.t => Sexplib.Sexp.t = t => Sexplib.Sexp.Atom(Uuidm.to_string(t)); From bae6457068e48b957a89a1c710531aaf4e9a850e Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 29 Sep 2023 10:24:24 -0400 Subject: [PATCH 042/141] Revert DHDoc_Exp.re --- src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index ead18ee4ff..2dc53757b5 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -179,7 +179,7 @@ let rec mk = | BoolLit(b) => DHDoc_common.mk_BoolLit(b) | IntLit(n) => DHDoc_common.mk_IntLit(n) | FloatLit(f) => DHDoc_common.mk_FloatLit(f) - | StringLit(s) => DHDoc_common.mk_StringLit("\"" ++ s ++ "\"") + | StringLit(s) => DHDoc_common.mk_StringLit(s) | TestLit(_) => Doc.text(ExpandingKeyword.to_string(Test)) | Sequence(d1, d2) => let (doc1, doc2) = (go'(d1), go'(d2)); From 19589e175b2e26cc35f919eebeda8fa77f49f37a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 29 Sep 2023 11:46:51 -0400 Subject: [PATCH 043/141] Add constraint_ to Info.pat --- src/haz3lcore/dynamics/Constraint.re | 2 +- src/haz3lcore/statics/Info.re | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 21cb280ad3..c7d325b844 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -1,6 +1,6 @@ open Sexplib.Std; -[@deriving sexp] +[@deriving (show({with_path: false}), sexp, yojson)] type t = | Truth | Falsity diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 57d9f71b4e..9c2015a65d 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -201,6 +201,7 @@ type pat = { cls: Term.Cls.t, status: status_pat, ty: Typ.t, + constraint_: Constraint.t, }; [@deriving (show({with_path: false}), sexp, yojson)] @@ -461,7 +462,17 @@ let derived_pat = (~upat: UPat.t, ~ctx, ~mode, ~ancestors, ~self): pat => { let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); - {cls, self, mode, ty, status, ctx, ancestors, term: upat}; + { + cls, + self, + mode, + ty, + status, + ctx, + ancestors, + term: upat, + constraint_: Falsity, + }; }; /* Add derivable attributes for types */ From 6f89c095067d765be23644d4ceb83686593615cc Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sun, 1 Oct 2023 15:01:50 -0400 Subject: [PATCH 044/141] Added ruls_to_info to statics.re --- src/haz3lcore/statics/Statics.re | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 70b92567ce..1d1631d7f4 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -283,7 +283,26 @@ and uexp_to_info_map = es, p_ctxs, ); - // let rec ruls_to_info_map = (xi_pre: Constraint.t, m) => (xi_pre, m); + + let type_of_exp = (rule: UExp.t): Typ.t => { + let (inf, _) = + uexp_to_info_map( + ~ctx=Builtins.ctx_init, + ~ancestors=[], + rule, + Id.Map.empty, + ); + inf.ty; + }; + + let rec ruls_to_info_map = (rules: list(UExp.t)): list(Typ.t) => { + List.fold_left( + (acc, rule) => {List.append(acc, [type_of_exp(rule)])}, + [], + rules, + ); + }; + let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); From ed3759ffff9c2daf9caf00172688ddf2768e5fbe Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 8 Oct 2023 01:08:24 -0400 Subject: [PATCH 045/141] Added Constraint.Bool/NotBool --- src/haz3lcore/dynamics/Constraint.re | 10 +++++++ src/haz3lcore/dynamics/Incon.re | 42 ++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index c7d325b844..24b5b40180 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -9,6 +9,8 @@ type t = | NotInt(int) | Float(float) | NotFloat(float) + | Bool(bool) + | NotBool(bool) | String(string) | NotString(string) | And(t, t) @@ -26,6 +28,8 @@ let rec constrains = (c: t, ty: Typ.t): bool => | (Int(_) | NotInt(_), _) => false | (Float(_) | NotFloat(_), Float) => true | (Float(_) | NotFloat(_), _) => false + | (Bool(_) | NotBool(_), Bool) => true + | (Bool(_) | NotBool(_), _) => false | (String(_) | NotString(_), String) => true | (String(_) | NotString(_), _) => false | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) @@ -56,6 +60,8 @@ let rec dual = (c: t): t => | NotInt(n) => Int(n) | Float(n) => NotFloat(n) | NotFloat(n) => Float(n) + | Bool(n) => NotBool(n) + | NotBool(n) => Bool(n) | String(n) => NotString(n) | NotString(n) => String(n) | And(c1, c2) => Or(dual(c1), dual(c2)) @@ -79,6 +85,8 @@ let rec truify = (c: t): t => | NotInt(_) | Float(_) | NotFloat(_) + | Bool(_) + | NotBool(_) | String(_) | NotString(_) => c | And(c1, c2) => And(truify(c1), truify(c2)) @@ -98,6 +106,8 @@ let rec falsify = (c: t): t => | NotInt(_) | Float(_) | NotFloat(_) + | Bool(_) + | NotBool(_) | String(_) | NotString(_) => c | And(c1, c2) => And(falsify(c1), falsify(c2)) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 5d41604928..d52fa6662b 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -56,6 +56,34 @@ let is_inconsistent_float = (xis: list(Constraint.t)): bool => { }; }; +let is_inconsistent_bool = (xis: list(Constraint.t)): bool => { + let (bool_set, not_bool_list) = + List.fold_left( + ((bool_set, not_bool_list), xi: Constraint.t) => + switch (xi) { + | Bool(b) => (BoolSet.add(b, bool_set), not_bool_list) + | NotBool(b) => (bool_set, [b, ...not_bool_list]) + | _ => failwith("input can only be Bool | NotBool") + }, + (BoolSet.empty, []), + xis, + ); + if (BoolSet.cardinal(bool_set) > 1) { + true; + } else { + List.fold_left( + (incon, b) => + if (incon) { + incon; + } else { + BoolSet.mem(b, bool_set); + }, + false, + not_bool_list, + ); + }; +}; + let is_inconsistent_string = (xis: list(Constraint.t)): bool => { let (string_set, not_string_list) = List.fold_left( @@ -170,6 +198,20 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => | (fs, []) => is_inconsistent_float(fs) | (fs, other) => is_inconsistent(~may, other @ fs) } + | Bool(_) + | NotBool(_) => + switch ( + List.partition( + fun + | Constraint.Bool(_) + | NotBool(_) => true + | _ => false, + xis, + ) + ) { + | (fs, []) => is_inconsistent_bool(fs) + | (fs, other) => is_inconsistent(~may, other @ fs) + } | String(_) | NotString(_) => switch ( From 45c9e474f10f011cb9814a2bde37557eeff4b1ce Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 8 Oct 2023 03:51:52 -0400 Subject: [PATCH 046/141] Add fixed_constraint_pat --- src/haz3lcore/statics/Info.re | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 9c2015a65d..242e0b059a 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -442,6 +442,14 @@ let fixed_typ_pat = (ctx, mode: Mode.t, self: Self.pat): Typ.t => | NotInHole(ok) => fixed_typ_ok(ok) }; +let fixed_constraint_pat = + (ctx, mode: Mode.t, self: Self.pat, constraint_: Constraint.t) + : Constraint.t => + switch (status_pat(ctx, mode, self)) { + | InHole(_) => Constraint.Hole + | NotInHole(_) => constraint_ + }; + let fixed_typ_exp = (ctx, mode: Mode.t, self: Self.exp): Typ.t => switch (status_exp(ctx, mode, self)) { | InHole(_) => Unknown(Internal) @@ -458,21 +466,13 @@ let derived_exp = }; /* Add derivable attributes for pattern terms */ -let derived_pat = (~upat: UPat.t, ~ctx, ~mode, ~ancestors, ~self): pat => { +let derived_pat = + (~upat: UPat.t, ~ctx, ~mode, ~ancestors, ~self, ~constraint_): pat => { let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); - { - cls, - self, - mode, - ty, - status, - ctx, - ancestors, - term: upat, - constraint_: Falsity, - }; + let constraint_ = fixed_constraint_pat(ctx, mode, self, constraint_); + {cls, self, mode, ty, status, ctx, ancestors, term: upat, constraint_}; }; /* Add derivable attributes for types */ From 0f631197ac9283321937184f03ad1206d3eb1575 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 8 Oct 2023 04:12:13 -0400 Subject: [PATCH 047/141] Implemented constraint emission for simple cases --- src/haz3lcore/statics/Statics.re | 41 +++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 1d1631d7f4..ccefc4eb6d 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -370,12 +370,19 @@ and upat_to_info_map = m: Map.t, ) : (Info.pat, Map.t) => { - let add = (~self, ~ctx, m) => { + let add = (~self, ~ctx, ~constraint_, m) => { let info = - Info.derived_pat(~upat, ~ctx, ~mode, ~ancestors, ~self=Common(self)); + Info.derived_pat( + ~upat, + ~ctx, + ~mode, + ~ancestors, + ~self=Common(self), + ~constraint_, + ); (info, add_info(ids, InfoPat(info), m)); }; - let atomic = self => add(~self, ~ctx, m); + let atomic = (self, constraint_) => add(~self, ~ctx, ~constraint_, m); let ancestors = [UPat.rep_id(upat)] @ ancestors; let go = upat_to_info_map(~is_synswitch, ~ancestors); let unknown = Typ.Unknown(is_synswitch ? SynSwitch : Internal); @@ -386,17 +393,18 @@ and upat_to_info_map = |> (((info, m)) => (info.ctx, tys @ [info.ty], m)), (ctx, [], m), ); + let hole = self => atomic(self, Constraint.Hole); switch (term) { | MultiHole(tms) => let (_, m) = multi(~ctx, ~ancestors, m, tms); - add(~self=IsMulti, ~ctx, m); - | Invalid(token) => atomic(BadToken(token)) - | EmptyHole => atomic(Just(unknown)) - | Int(_) => atomic(Just(Int)) - | Float(_) => atomic(Just(Float)) + add(~self=IsMulti, ~ctx, ~constraint_=Constraint.Hole, m); + | Invalid(token) => hole(BadToken(token)) + | EmptyHole => hole(Just(unknown)) + | Int(int) => atomic(Just(Int), Constraint.Int(int)) + | Float(float) => atomic(Just(Float), Constraint.Float(float)) | Triv => atomic(Just(Prod([]))) - | Bool(_) => atomic(Just(Bool)) - | String(_) => atomic(Just(String)) + | Bool(bool) => atomic(Just(Bool), Constraint.Bool(bool)) + | String(string) => atomic(Just(String), Constraint.String(string)) | ListLit(ps) => let ids = List.map(UPat.rep_id, ps); let modes = Mode.of_list_lit(ctx, List.length(ps), mode); @@ -407,7 +415,7 @@ and upat_to_info_map = let (tl, m) = go(~ctx=hd.ctx, ~mode=Mode.of_cons_tl(ctx, mode, hd.ty), tl, m); add(~self=Just(List(hd.ty)), ~ctx=tl.ctx, m); - | Wild => atomic(Just(unknown)) + | Wild => atomic(Just(unknown), Constraint.Truth) | Var(name) => /* NOTE: The self type assigned to pattern variables (Unknown) may be SynSwitch, but SynSwitch is never added to the context; @@ -415,14 +423,19 @@ and upat_to_info_map = let ctx_typ = Info.fixed_typ_pat(ctx, mode, Common(Just(Unknown(Internal)))); let entry = Ctx.VarEntry({name, id: UPat.rep_id(upat), typ: ctx_typ}); - add(~self=Just(unknown), ~ctx=Ctx.extend(ctx, entry), m); + add( + ~self=Just(unknown), + ~ctx=Ctx.extend(ctx, entry), + ~constraint_=Constraint.Truth, + m, + ); | Tuple(ps) => let modes = Mode.of_prod(ctx, mode, List.length(ps)); let (ctx, tys, m) = ctx_fold(ctx, m, ps, modes); add(~self=Just(Prod(tys)), ~ctx, m); | Parens(p) => let (p, m) = go(~ctx, ~mode, p, m); - add(~self=Just(p.ty), ~ctx=p.ctx, m); + add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); | Constructor(ctr) => atomic(Self.of_ctr(ctx, ctr)) | Ap(fn, arg) => let fn_mode = Mode.of_ap(ctx, mode, UPat.ctr_name(fn)); @@ -433,7 +446,7 @@ and upat_to_info_map = | TypeAnn(p, ann) => let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); let (p, m) = go(~ctx, ~mode=Ana(ann.ty), p, m); - add(~self=Just(ann.ty), ~ctx=p.ctx, m); + add(~self=Just(ann.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); }; } and utyp_to_info_map = From d73d4ac084acb7452635962332a3252b0cd04190 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Mon, 9 Oct 2023 09:39:47 -0400 Subject: [PATCH 048/141] Wrote pattern to constraint for unit, tuple and list. --- src/haz3lcore/statics/Statics.re | 57 ++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index ccefc4eb6d..5ac79c1c2c 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -388,10 +388,17 @@ and upat_to_info_map = let unknown = Typ.Unknown(is_synswitch ? SynSwitch : Internal); let ctx_fold = (ctx: Ctx.t, m) => List.fold_left2( - ((ctx, tys, m), e, mode) => + ((ctx, tys, cons, m), e, mode) => go(~ctx, ~mode, e, m) - |> (((info, m)) => (info.ctx, tys @ [info.ty], m)), - (ctx, [], m), + |> ( + ((info, m)) => ( + info.ctx, + tys @ [info.ty], + cons @ [info.constraint_], + m, + ) + ), + (ctx, [], [], m), ); let hole = self => atomic(self, Constraint.Hole); switch (term) { @@ -402,19 +409,36 @@ and upat_to_info_map = | EmptyHole => hole(Just(unknown)) | Int(int) => atomic(Just(Int), Constraint.Int(int)) | Float(float) => atomic(Just(Float), Constraint.Float(float)) - | Triv => atomic(Just(Prod([]))) + | Triv => atomic(Just(Prod([])), Constraint.Truth) | Bool(bool) => atomic(Just(Bool), Constraint.Bool(bool)) | String(string) => atomic(Just(String), Constraint.String(string)) | ListLit(ps) => let ids = List.map(UPat.rep_id, ps); let modes = Mode.of_list_lit(ctx, List.length(ps), mode); - let (ctx, tys, m) = ctx_fold(ctx, m, ps, modes); - add(~self=Self.listlit(~empty=unknown, ctx, tys, ids), ~ctx, m); + let (ctx, tys, cons, m) = ctx_fold(ctx, m, ps, modes); + let rec cons_fold_list = cs => + switch (cs) { + | [] => Constraint.InjL(Constraint.Truth) // Left = nil, Right = cons + | [hd, ...tl] => + Constraint.InjR(Constraint.Pair(hd, cons_fold_list(tl))) + }; + add( + ~self=Self.listlit(~empty=unknown, ctx, tys, ids), + ~ctx, + ~constraint_=cons_fold_list(cons), + m, + ); | Cons(hd, tl) => let (hd, m) = go(~ctx, ~mode=Mode.of_cons_hd(ctx, mode), hd, m); let (tl, m) = go(~ctx=hd.ctx, ~mode=Mode.of_cons_tl(ctx, mode, hd.ty), tl, m); - add(~self=Just(List(hd.ty)), ~ctx=tl.ctx, m); + add( + ~self=Just(List(hd.ty)), + ~ctx=tl.ctx, + ~constraint_= + Constraint.InjR(Constraint.Pair(hd.constraint_, tl.constraint_)), + m, + ); | Wild => atomic(Just(unknown), Constraint.Truth) | Var(name) => /* NOTE: The self type assigned to pattern variables (Unknown) @@ -431,18 +455,29 @@ and upat_to_info_map = ); | Tuple(ps) => let modes = Mode.of_prod(ctx, mode, List.length(ps)); - let (ctx, tys, m) = ctx_fold(ctx, m, ps, modes); - add(~self=Just(Prod(tys)), ~ctx, m); + let (ctx, tys, cons, m) = ctx_fold(ctx, m, ps, modes); + let rec cons_fold_tuple = cs => + switch (cs) { + | [] => Constraint.Truth + | [elt] => elt + | [hd, ...tl] => Constraint.Pair(hd, cons_fold_tuple(tl)) + }; + add( + ~self=Just(Prod(tys)), + ~ctx, + ~constraint_=cons_fold_tuple(cons), + m, + ); | Parens(p) => let (p, m) = go(~ctx, ~mode, p, m); add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); - | Constructor(ctr) => atomic(Self.of_ctr(ctx, ctr)) + | Constructor(ctr) => atomic(Self.of_ctr(ctx, ctr), Constraint.Falsity) // TODO | Ap(fn, arg) => let fn_mode = Mode.of_ap(ctx, mode, UPat.ctr_name(fn)); let (fn, m) = go(~ctx, ~mode=fn_mode, fn, m); let (ty_in, ty_out) = Typ.matched_arrow(ctx, fn.ty); let (arg, m) = go(~ctx, ~mode=Ana(ty_in), arg, m); - add(~self=Just(ty_out), ~ctx=arg.ctx, m); + add(~self=Just(ty_out), ~ctx=arg.ctx, ~constraint_=arg.constraint_, m); | TypeAnn(p, ann) => let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); let (p, m) = go(~ctx, ~mode=Ana(ann.ty), p, m); From 46b6d864c61b9d3258858eb50330a024e142a589 Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sat, 14 Oct 2023 16:56:03 -0400 Subject: [PATCH 049/141] Generating Self.exp from constraints --- src/haz3lcore/statics/Statics.re | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 5ac79c1c2c..542cf136e4 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -302,8 +302,28 @@ and uexp_to_info_map = rules, ); }; - - let e_tys = List.map(Info.exp_ty, es); + let (pats, exps) = List.split(rules); + let final_constraint = + List.map( + (pat: UPat.t): Constraint.t => { + let (patInfo, _) = + upat_to_info_map( + ~is_synswitch=true, + ~ctx, + ~ancestors, + ~mode, + pat, + m, + ); + patInfo.constraint_; + }, + pats, + ); + let exhaustive = Incon.is_exhaustive(final_constraint); + let generatedSelf= switch(exhaustive){ + |true =>Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids)); + |false =>InexhaustiveMatch(Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids))); + }; let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); add'( From 932eff310a67101c116038f990df8fa4655b9bfb Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sat, 14 Oct 2023 17:26:00 -0400 Subject: [PATCH 050/141] Folded result of is_exhaustive to generate Self.exp --- src/haz3lcore/statics/Statics.re | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 542cf136e4..ae8be2617c 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -303,7 +303,7 @@ and uexp_to_info_map = ); }; let (pats, exps) = List.split(rules); - let final_constraint = + let get_constraints = List.map( (pat: UPat.t): Constraint.t => { let (patInfo, _) = @@ -319,8 +319,12 @@ and uexp_to_info_map = }, pats, ); - let exhaustive = Incon.is_exhaustive(final_constraint); - let generatedSelf= switch(exhaustive){ + let final_constraint = List.fold_left( + (acc,c) => {Incon.is_exhaustive(c) && acc}, + true, + get_constraints, + ); + let generatedSelf= switch(final_constraint){ |true =>Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids)); |false =>InexhaustiveMatch(Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids))); }; From 4149adcdfa0a0738b006dd9e5d26389e20c658ef Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sat, 14 Oct 2023 17:46:39 -0400 Subject: [PATCH 051/141] Indicated that InexhaustiveMatch is from Self.re --- src/haz3lcore/statics/Statics.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index ae8be2617c..4ac3bcda39 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -325,8 +325,8 @@ and uexp_to_info_map = get_constraints, ); let generatedSelf= switch(final_constraint){ - |true =>Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids)); - |false =>InexhaustiveMatch(Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids))); + |true =>Self.Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids)); + |false =>Self.InexhaustiveMatch(Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids))); }; let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); From 188d22225a2007b22beb2388feaaf11dc939fc6a Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sat, 14 Oct 2023 18:00:03 -0400 Subject: [PATCH 052/141] Error fixes --- src/haz3lcore/statics/Statics.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 4ac3bcda39..1918892641 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -324,9 +324,9 @@ and uexp_to_info_map = true, get_constraints, ); - let generatedSelf= switch(final_constraint){ + let generatedSelf: Self.exp= switch(final_constraint){ |true =>Self.Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids)); - |false =>Self.InexhaustiveMatch(Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids))); + |false =>InexhaustiveMatch(Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids))); }; let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); From fc6f0ce5d2c18d1e82c29696bc2f9ef18f03ccb9 Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sat, 14 Oct 2023 18:08:10 -0400 Subject: [PATCH 053/141] used Info.exp_ty over ruls_to_info_map --- src/haz3lcore/statics/Statics.re | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 1918892641..784e542e23 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -324,10 +324,12 @@ and uexp_to_info_map = true, get_constraints, ); + let e_tys = List.map(Info.exp_ty, es); let generatedSelf: Self.exp= switch(final_constraint){ - |true =>Self.Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids)); - |false =>InexhaustiveMatch(Common(Self.match(ctx, ruls_to_info_map(exps), branch_ids))); + |true =>Self.Common(Self.match(ctx, e_tys, branch_ids)); + |false =>InexhaustiveMatch(Common(Self.match(ctx, e_tys, branch_ids))); }; + let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); add'( From 38d1232f11188463cc5ca02e5503186bc185f8ef Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sun, 15 Oct 2023 21:42:48 -0400 Subject: [PATCH 054/141] Combined constraints with or_constraints() --- src/haz3lcore/statics/Statics.re | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 784e542e23..80d0685295 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -295,15 +295,17 @@ and uexp_to_info_map = inf.ty; }; - let rec ruls_to_info_map = (rules: list(UExp.t)): list(Typ.t) => { + //ruls_to_info_map was implemented but not sure where to use yet + [@warning "-26"] + let ruls_to_info_map = (rules: list(UExp.t)): list(Typ.t) => { List.fold_left( (acc, rule) => {List.append(acc, [type_of_exp(rule)])}, [], rules, ); }; - let (pats, exps) = List.split(rules); - let get_constraints = + let (pats, _) = List.split(rules); + let get_constraints = List.map( (pat: UPat.t): Constraint.t => { let (patInfo, _) = @@ -319,17 +321,16 @@ and uexp_to_info_map = }, pats, ); - let final_constraint = List.fold_left( - (acc,c) => {Incon.is_exhaustive(c) && acc}, - true, - get_constraints, - ); + let final_constraint = Constraint.or_constraints(get_constraints); let e_tys = List.map(Info.exp_ty, es); - let generatedSelf: Self.exp= switch(final_constraint){ - |true =>Self.Common(Self.match(ctx, e_tys, branch_ids)); - |false =>InexhaustiveMatch(Common(Self.match(ctx, e_tys, branch_ids))); - }; - + + //generate_self is generating a Self.exp that is yet to be utilized + [@warning "-26"] + let generate_self: Self.exp = + Incon.is_exhaustive(final_constraint) + ? Self.Common(Self.match(ctx, e_tys, branch_ids)) + : InexhaustiveMatch(Common(Self.match(ctx, e_tys, branch_ids))); + let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); add'( From 6ff3c31e4fc93ea422a69c831ce707fa6e1b6681 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Thu, 19 Oct 2023 23:55:43 -0400 Subject: [PATCH 055/141] Extended ConstructorEntry, Part I --- src/haz3lcore/statics/Statics.re | 7 ++++++- src/haz3lcore/statics/TypBase.re | 8 ++++---- src/haz3lweb/view/CtxInspector.re | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 80d0685295..1e0392c80c 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -504,7 +504,12 @@ and upat_to_info_map = let (fn, m) = go(~ctx, ~mode=fn_mode, fn, m); let (ty_in, ty_out) = Typ.matched_arrow(ctx, fn.ty); let (arg, m) = go(~ctx, ~mode=Ana(ty_in), arg, m); - add(~self=Just(ty_out), ~ctx=arg.ctx, ~constraint_=arg.constraint_, m); + add( + ~self=Just(ty_out), + ~ctx=arg.ctx, + ~constraint_=Constraint.Falsity, + m, + ); // TODO | TypeAnn(p, ann) => let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); let (p, m) = go(~ctx, ~mode=Ana(ann.ty), p, m); diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 3f614145ab..4babadf994 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -443,7 +443,7 @@ and Ctx: { [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) - | ConstructorEntry(var_entry) + | ConstructorEntry(var_entry, Constraint.t => Constraint.t) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -482,7 +482,7 @@ and Ctx: { [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) - | ConstructorEntry(var_entry) + | ConstructorEntry(var_entry, Constraint.t => Constraint.t) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -517,7 +517,7 @@ and Ctx: { let get_id: entry => Id.t = fun | VarEntry({id, _}) - | ConstructorEntry({id, _}) + | ConstructorEntry({id, _}, _) | TVarEntry({id, _}) => id; let lookup_var = (ctx: t, name: string): option(var_entry) => @@ -591,7 +591,7 @@ and Ctx: { ((ctx, term_set, typ_set), entry) => { switch (entry) { | VarEntry({name, _}) - | ConstructorEntry({name, _}) => + | ConstructorEntry({name, _}, _) => VarSet.mem(name, term_set) ? (ctx, term_set, typ_set) : ([entry, ...ctx], VarSet.add(name, term_set), typ_set) diff --git a/src/haz3lweb/view/CtxInspector.re b/src/haz3lweb/view/CtxInspector.re index a148f149cc..dbfe664b38 100644 --- a/src/haz3lweb/view/CtxInspector.re +++ b/src/haz3lweb/view/CtxInspector.re @@ -16,7 +16,7 @@ let context_entry_view = (~inject, entry: Haz3lcore.Ctx.entry): Node.t => { ); switch (entry) { | VarEntry({name, typ, _}) - | ConstructorEntry({name, typ, _}) => + | ConstructorEntry({name, typ, _}, _) => div_c( "context-entry", [ From d719567d5cc36038da5ece27a969d37f89af31ab Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 00:45:37 -0400 Subject: [PATCH 056/141] Extended ConstructorEntry, Part II --- src/haz3lcore/statics/TypBase.re | 51 ++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 4babadf994..bbffd4d7d1 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -531,7 +531,7 @@ and Ctx: { let lookup_ctr = (ctx: t, name: string): option(var_entry) => List.find_map( fun - | ConstructorEntry(t) when t.name == name => Some(t) + | ConstructorEntry(t, _) when t.name == name => Some(t) | _ => None, ctx, ); @@ -542,21 +542,40 @@ and Ctx: { | None => false }; - let add_ctrs = (ctx: t, name: TypVar.t, id: Id.t, ctrs: Typ.sum_map): t => - List.map( - ((ctr, typ)) => - ConstructorEntry({ - name: ctr, - id, - typ: - switch (typ) { - | None => Var(name) - | Some(typ) => Arrow(typ, Var(name)) - }, - }), - ctrs, - ) - @ ctx; + let add_ctrs = (ctx: t, name: TypVar.t, id: Id.t, ctrs: Typ.sum_map): t => { + let (ctx, _, _) = + List.fold_left( + ((ctx, nth, wrap), (ctr, typ)) => { + // List.length(ctrs) == 0: EmptyHole + // List.length(ctrs) == 1: Type variable not found + assert(List.length(ctrs) > 1); + + // List.length(ctrs) == 2: + // nth == 0: xi => InjL(xi) + // nth == 1: xi => InjR(InjL(xi)) + // nth == 2: xi => InjR(InjR(xi)) + let constraint_ctor = xi => + wrap(nth == List.length(ctrs) - 1 ? Constraint.InjL(xi) : xi); + let entry = + ConstructorEntry( + { + name: ctr, + id, + typ: + switch (typ) { + | None => Var(name) + | Some(typ) => Arrow(typ, Var(name)) + }, + }, + constraint_ctor, + ); + ([entry, ...ctx], nth + 1, xi => wrap(Constraint.InjR(xi))); + }, + (ctx, 0, Fun.id), + ctrs, + ); + ctx; + }; let subtract_prefix = (ctx: t, prefix_ctx: t): option(t) => { // NOTE: does not check that the prefix is an actual prefix From f132e82b9e9baf9515974c8f03be64246cfaa76f Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 01:24:00 -0400 Subject: [PATCH 057/141] Extended ConstructorEntry, Part III --- src/haz3lcore/statics/TypBase.re | 57 ++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index bbffd4d7d1..5192c96314 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -443,7 +443,8 @@ and Ctx: { [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) - | ConstructorEntry(var_entry, Constraint.t => Constraint.t) + // | ConstructorEntry(var_entry, Constraint.t => Constraint.t) /* obselete because of dependency cycle */ + | ConstructorEntry(var_entry, int) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -482,7 +483,8 @@ and Ctx: { [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) - | ConstructorEntry(var_entry, Constraint.t => Constraint.t) + // | ConstructorEntry(var_entry, Constraint.t => Constraint.t) /* obselete because of dependency cycle */ + | ConstructorEntry(var_entry, int) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -543,19 +545,40 @@ and Ctx: { }; let add_ctrs = (ctx: t, name: TypVar.t, id: Id.t, ctrs: Typ.sum_map): t => { - let (ctx, _, _) = + // let (ctx, _, _) = + // List.fold_left( + // ((ctx, nth, wrap), (ctr, typ)) => { + // // List.length(ctrs) == 0: EmptyHole + // // List.length(ctrs) == 1: Type variable not found + // assert(List.length(ctrs) > 1); + + // // List.length(ctrs) == 2: + // // nth == 0: xi => InjL(xi) + // // nth == 1: xi => InjR(InjL(xi)) + // // nth == 2: xi => InjR(InjR(xi)) + // let constraint_ctor = xi => + // wrap(nth == List.length(ctrs) - 1 ? Constraint.InjL(xi) : xi); + // let entry = + // ConstructorEntry( + // { + // name: ctr, + // id, + // typ: + // switch (typ) { + // | None => Var(name) + // | Some(typ) => Arrow(typ, Var(name)) + // }, + // }, + // constraint_ctor, + // ); + // ([entry, ...ctx], nth + 1, xi => wrap(Constraint.InjR(xi))); + // }, + // (ctx, 0, Fun.id), + // ctrs, + // ); + let (ctx, _) = List.fold_left( - ((ctx, nth, wrap), (ctr, typ)) => { - // List.length(ctrs) == 0: EmptyHole - // List.length(ctrs) == 1: Type variable not found - assert(List.length(ctrs) > 1); - - // List.length(ctrs) == 2: - // nth == 0: xi => InjL(xi) - // nth == 1: xi => InjR(InjL(xi)) - // nth == 2: xi => InjR(InjR(xi)) - let constraint_ctor = xi => - wrap(nth == List.length(ctrs) - 1 ? Constraint.InjL(xi) : xi); + ((ctx, nth), (ctr, typ)) => { let entry = ConstructorEntry( { @@ -567,11 +590,11 @@ and Ctx: { | Some(typ) => Arrow(typ, Var(name)) }, }, - constraint_ctor, + nth, ); - ([entry, ...ctx], nth + 1, xi => wrap(Constraint.InjR(xi))); + ([entry, ...ctx], nth + 1); }, - (ctx, 0, Fun.id), + (ctx, 0), ctrs, ); ctx; From 1e543d546df00a452f78d92f906a48a948cdee63 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 03:06:52 -0400 Subject: [PATCH 058/141] Fixed the Pair bug in Constraint.constrains --- src/haz3lcore/dynamics/Constraint.re | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 24b5b40180..6d869336f4 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -18,6 +18,7 @@ type t = | InjL(t) | InjR(t) | Pair(t, t); +// | Tuple(list(t)); let rec constrains = (c: t, ty: Typ.t): bool => switch (c, Typ.weak_head_normalize(Builtins.ctx_init, ty)) { @@ -48,7 +49,12 @@ let rec constrains = (c: t, ty: Typ.t): bool => | map' => constrains(c2, Sum(map')) } | (InjR(_), _) => false - | (Pair(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) + | (Pair(c1, c2), Prod([ty_hd, ...ty_tl])) => + constrains(c1, ty_hd) && constrains(c2, Prod(ty_tl)) + | (Pair(_), _) => false + // | (Tuple(cs), Prod(tys)) when List.length(cs) == List.length(tys) => + // List.for_all2(constrains, cs, tys) + // | (Tuple(_), _) => false }; let rec dual = (c: t): t => @@ -60,8 +66,8 @@ let rec dual = (c: t): t => | NotInt(n) => Int(n) | Float(n) => NotFloat(n) | NotFloat(n) => Float(n) - | Bool(n) => NotBool(n) - | NotBool(n) => Bool(n) + | Bool(b) => NotBool(b) + | NotBool(b) => Bool(b) | String(n) => NotString(n) | NotString(n) => String(n) | And(c1, c2) => Or(dual(c1), dual(c2)) @@ -73,6 +79,7 @@ let rec dual = (c: t): t => Pair(c1, dual(c2)), Or(Pair(dual(c1), c2), Pair(dual(c1), dual(c2))), ) + // | Tuple(cs) => // TODO }; /** substitute Truth for Hole */ From cb1963da11ec935541431cc74b6c3220cb08eaf4 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 03:07:07 -0400 Subject: [PATCH 059/141] Added Constraint.of_nth_variant --- src/haz3lcore/dynamics/Constraint.re | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 6d869336f4..5fb678367d 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -145,3 +145,13 @@ let rec or_constraints = (lst: list(t)): t => | [xi] => xi | [xi, ...xis] => Or(xi, or_constraints(xis)) }; + +// Temporary name +let rec of_nth_variant = (num_variants, nth): (t => t) => + if (num_variants == 1) { + Fun.id; + } else if (nth == 0) { + xi => InjL(xi); + } else { + xi => InjR(xi |> of_nth_variant(num_variants - 1, nth - 1)); + }; From ffd083977c420c9e6310d07767e349b694e554b5 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 03:15:23 -0400 Subject: [PATCH 060/141] Extended ConstructorEntry, Part IV --- src/haz3lcore/statics/TypBase.re | 50 ++++++++++++++++++++----------- src/haz3lweb/view/CtxInspector.re | 2 +- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 5192c96314..323a49c031 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -440,11 +440,19 @@ and Ctx: { kind: Kind.t, }; + [@deriving (show({with_path: false}), sexp, yojson)] + type constructor_entry = { + name: Var.t, + id: Id.t, + typ: Typ.t, + nth: int // temporary name + }; + [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) // | ConstructorEntry(var_entry, Constraint.t => Constraint.t) /* obselete because of dependency cycle */ - | ConstructorEntry(var_entry, int) + | ConstructorEntry(constructor_entry) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -458,7 +466,7 @@ and Ctx: { let lookup_alias: (t, TypVar.t) => option(Typ.t); let get_id: entry => Id.t; let lookup_var: (t, string) => option(var_entry); - let lookup_ctr: (t, string) => option(var_entry); + let lookup_ctr: (t, string) => option(constructor_entry); let is_alias: (t, TypVar.t) => bool; let add_ctrs: (t, TypVar.t, Id.t, Typ.sum_map) => t; let subtract_prefix: (t, t) => option(t); @@ -480,11 +488,19 @@ and Ctx: { kind: Kind.t, }; + [@deriving (show({with_path: false}), sexp, yojson)] + type constructor_entry = { + name: Var.t, + id: Id.t, + typ: Typ.t, + nth: int // temporary name + }; + [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) // | ConstructorEntry(var_entry, Constraint.t => Constraint.t) /* obselete because of dependency cycle */ - | ConstructorEntry(var_entry, int) + | ConstructorEntry(constructor_entry) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -519,7 +535,7 @@ and Ctx: { let get_id: entry => Id.t = fun | VarEntry({id, _}) - | ConstructorEntry({id, _}, _) + | ConstructorEntry({id, _}) | TVarEntry({id, _}) => id; let lookup_var = (ctx: t, name: string): option(var_entry) => @@ -530,10 +546,10 @@ and Ctx: { ctx, ); - let lookup_ctr = (ctx: t, name: string): option(var_entry) => + let lookup_ctr = (ctx: t, name: string): option(constructor_entry) => List.find_map( fun - | ConstructorEntry(t, _) when t.name == name => Some(t) + | ConstructorEntry(t) when t.name == name => Some(t) | _ => None, ctx, ); @@ -580,18 +596,16 @@ and Ctx: { List.fold_left( ((ctx, nth), (ctr, typ)) => { let entry = - ConstructorEntry( - { - name: ctr, - id, - typ: - switch (typ) { - | None => Var(name) - | Some(typ) => Arrow(typ, Var(name)) - }, - }, + ConstructorEntry({ + name: ctr, + id, + typ: + switch (typ) { + | None => Var(name) + | Some(typ) => Arrow(typ, Var(name)) + }, nth, - ); + }); ([entry, ...ctx], nth + 1); }, (ctx, 0), @@ -633,7 +647,7 @@ and Ctx: { ((ctx, term_set, typ_set), entry) => { switch (entry) { | VarEntry({name, _}) - | ConstructorEntry({name, _}, _) => + | ConstructorEntry({name, _}) => VarSet.mem(name, term_set) ? (ctx, term_set, typ_set) : ([entry, ...ctx], VarSet.add(name, term_set), typ_set) diff --git a/src/haz3lweb/view/CtxInspector.re b/src/haz3lweb/view/CtxInspector.re index dbfe664b38..a148f149cc 100644 --- a/src/haz3lweb/view/CtxInspector.re +++ b/src/haz3lweb/view/CtxInspector.re @@ -16,7 +16,7 @@ let context_entry_view = (~inject, entry: Haz3lcore.Ctx.entry): Node.t => { ); switch (entry) { | VarEntry({name, typ, _}) - | ConstructorEntry({name, typ, _}, _) => + | ConstructorEntry({name, typ, _}) => div_c( "context-entry", [ From 5445ddf142cecca8aeb4dd88a048b5bfac6aa9ad Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 04:47:05 -0400 Subject: [PATCH 061/141] Added Constraint.of_ap and Constraint.of_ctr --- src/haz3lcore/dynamics/Constraint.re | 13 +++++++++++++ src/haz3lcore/statics/Statics.re | 3 ++- src/haz3lcore/statics/TypBase.re | 10 ++++++++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 5fb678367d..a8d453233c 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -155,3 +155,16 @@ let rec of_nth_variant = (num_variants, nth): (t => t) => } else { xi => InjR(xi |> of_nth_variant(num_variants - 1, nth - 1)); }; + +let of_ap = (ctx, ctr: option(Constructor.t), arg: t): t => + switch (ctr) { + | Some(name) => + switch (Ctx.lookup_ctr(ctx, name)) { + | None => Hole // TODO: review + | Some({num_variants, nth, _}) => + arg |> of_nth_variant(num_variants, nth) + } + | None => Hole // TODO: review + }; + +let of_ctr = (ctx, name) => of_ap(ctx, Some(name), Truth); diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 1e0392c80c..f9b90450ee 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -500,7 +500,8 @@ and upat_to_info_map = add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); | Constructor(ctr) => atomic(Self.of_ctr(ctx, ctr), Constraint.Falsity) // TODO | Ap(fn, arg) => - let fn_mode = Mode.of_ap(ctx, mode, UPat.ctr_name(fn)); + let ctr = UPat.ctr_name(fn); + let fn_mode = Mode.of_ap(ctx, mode, ctr); let (fn, m) = go(~ctx, ~mode=fn_mode, fn, m); let (ty_in, ty_out) = Typ.matched_arrow(ctx, fn.ty); let (arg, m) = go(~ctx, ~mode=Ana(ty_in), arg, m); diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 323a49c031..e80fa6e972 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -445,7 +445,9 @@ and Ctx: { name: Var.t, id: Id.t, typ: Typ.t, - nth: int // temporary name + /* Temporary variables. Better implementation is a TO-DO. */ + nth: int, + num_variants: int, }; [@deriving (show({with_path: false}), sexp, yojson)] @@ -493,7 +495,9 @@ and Ctx: { name: Var.t, id: Id.t, typ: Typ.t, - nth: int // temporary name + /* Temporary variables. Better implementation is a TO-DO. */ + nth: int, + num_variants: int, }; [@deriving (show({with_path: false}), sexp, yojson)] @@ -592,6 +596,7 @@ and Ctx: { // (ctx, 0, Fun.id), // ctrs, // ); + let num_variants = List.length(ctrs); let (ctx, _) = List.fold_left( ((ctx, nth), (ctr, typ)) => { @@ -605,6 +610,7 @@ and Ctx: { | Some(typ) => Arrow(typ, Var(name)) }, nth, + num_variants, }); ([entry, ...ctx], nth + 1); }, From 1500efe5baff21f0b28d9afb74a6ac96faa2ddff Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 04:53:43 -0400 Subject: [PATCH 062/141] Constraint emission for Constructor and Ap --- src/haz3lcore/dynamics/Constraint.re | 6 +++--- src/haz3lcore/statics/Statics.re | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index a8d453233c..f2ed742299 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -147,13 +147,13 @@ let rec or_constraints = (lst: list(t)): t => }; // Temporary name -let rec of_nth_variant = (num_variants, nth): (t => t) => +let rec ctr_of_nth_variant = (num_variants, nth): (t => t) => if (num_variants == 1) { Fun.id; } else if (nth == 0) { xi => InjL(xi); } else { - xi => InjR(xi |> of_nth_variant(num_variants - 1, nth - 1)); + xi => InjR(xi |> ctr_of_nth_variant(num_variants - 1, nth - 1)); }; let of_ap = (ctx, ctr: option(Constructor.t), arg: t): t => @@ -162,7 +162,7 @@ let of_ap = (ctx, ctr: option(Constructor.t), arg: t): t => switch (Ctx.lookup_ctr(ctx, name)) { | None => Hole // TODO: review | Some({num_variants, nth, _}) => - arg |> of_nth_variant(num_variants, nth) + arg |> ctr_of_nth_variant(num_variants, nth) } | None => Hole // TODO: review }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index f9b90450ee..61f97aa64a 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -498,7 +498,8 @@ and upat_to_info_map = | Parens(p) => let (p, m) = go(~ctx, ~mode, p, m); add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); - | Constructor(ctr) => atomic(Self.of_ctr(ctx, ctr), Constraint.Falsity) // TODO + | Constructor(ctr) => + atomic(Self.of_ctr(ctx, ctr), Constraint.of_ctr(ctx, ctr)) | Ap(fn, arg) => let ctr = UPat.ctr_name(fn); let fn_mode = Mode.of_ap(ctx, mode, ctr); @@ -508,9 +509,9 @@ and upat_to_info_map = add( ~self=Just(ty_out), ~ctx=arg.ctx, - ~constraint_=Constraint.Falsity, + ~constraint_=Constraint.of_ap(ctx, ctr, arg.constraint_), m, - ); // TODO + ); | TypeAnn(p, ann) => let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); let (p, m) = go(~ctx, ~mode=Ana(ann.ty), p, m); From aa7906ec5b87860dce2e1d15984a07d3b187647f Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 05:02:38 -0400 Subject: [PATCH 063/141] Match Self generation code simplification --- src/haz3lcore/statics/Statics.re | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 61f97aa64a..27b794a34a 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -324,20 +324,15 @@ and uexp_to_info_map = let final_constraint = Constraint.or_constraints(get_constraints); let e_tys = List.map(Info.exp_ty, es); - //generate_self is generating a Self.exp that is yet to be utilized - [@warning "-26"] - let generate_self: Self.exp = + let unwrapped_self: Self.exp = + Common(Self.match(ctx, e_tys, branch_ids)); + let self = Incon.is_exhaustive(final_constraint) - ? Self.Common(Self.match(ctx, e_tys, branch_ids)) - : InexhaustiveMatch(Common(Self.match(ctx, e_tys, branch_ids))); + ? unwrapped_self : InexhaustiveMatch(unwrapped_self); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - add'( - ~self=InexhaustiveMatch(Common(Self.match(ctx, e_tys, branch_ids))), - ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), - m, - ); + add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => let m = utpat_to_info_map(~ctx, ~ancestors, typat, m) |> snd; switch (typat.term) { From 7a8389001e9db96b614f17e4b27b9365a79dce23 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 05:05:26 -0400 Subject: [PATCH 064/141] Code simplification part II --- src/haz3lcore/statics/Statics.re | 35 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 27b794a34a..0f7e91c410 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -272,6 +272,22 @@ and uexp_to_info_map = let (scrut, m) = go(~mode=Syn, scrut, m); let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); + let xis = + List.map( + (pat: UPat.t): Constraint.t => { + let (patInfo, _) = + upat_to_info_map( + ~is_synswitch=true, + ~ctx, + ~ancestors, + ~mode, + pat, + m, + ); + patInfo.constraint_; + }, + ps, + ); let (ps, m) = map_m(go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty)), ps, m); let p_ctxs = List.map(Info.pat_ctx, ps); @@ -304,24 +320,7 @@ and uexp_to_info_map = rules, ); }; - let (pats, _) = List.split(rules); - let get_constraints = - List.map( - (pat: UPat.t): Constraint.t => { - let (patInfo, _) = - upat_to_info_map( - ~is_synswitch=true, - ~ctx, - ~ancestors, - ~mode, - pat, - m, - ); - patInfo.constraint_; - }, - pats, - ); - let final_constraint = Constraint.or_constraints(get_constraints); + let final_constraint = Constraint.or_constraints(xis); let e_tys = List.map(Info.exp_ty, es); let unwrapped_self: Self.exp = From 8ab8464cb7d079bd891c72c4e9cf15115f026aae Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 05:51:52 -0400 Subject: [PATCH 065/141] rules_to_info_map --- src/haz3lcore/statics/Info.re | 1 + src/haz3lcore/statics/Statics.re | 73 ++++++++++---------------------- 2 files changed, 23 insertions(+), 51 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 242e0b059a..a68171bc52 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -257,6 +257,7 @@ let exp_co_ctx: exp => CoCtx.t = ({co_ctx, _}) => co_ctx; let exp_ty: exp => Typ.t = ({ty, _}) => ty; let pat_ctx: pat => Ctx.t = ({ctx, _}) => ctx; let pat_ty: pat => Typ.t = ({ty, _}) => ty; +let pat_constraint: pat => Constraint.t = ({constraint_, _}) => constraint_; let rec status_common = (ctx: Ctx.t, mode: Mode.t, self: Self.t): status_common => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 0f7e91c410..69035e9e21 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -270,67 +270,38 @@ and uexp_to_info_map = ); | Match(scrut, rules) => let (scrut, m) = go(~mode=Syn, scrut, m); - let (ps, es) = List.split(rules); - let branch_ids = List.map(UExp.rep_id, es); - let xis = - List.map( - (pat: UPat.t): Constraint.t => { - let (patInfo, _) = - upat_to_info_map( - ~is_synswitch=true, - ~ctx, - ~ancestors, - ~mode, - pat, - m, - ); - patInfo.constraint_; - }, - ps, - ); - let (ps, m) = - map_m(go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty)), ps, m); - let p_ctxs = List.map(Info.pat_ctx, ps); - let (es, m) = - List.fold_left2( - ((es, m), e, ctx) => - go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), - ([], m), - es, - p_ctxs, - ); - - let type_of_exp = (rule: UExp.t): Typ.t => { - let (inf, _) = - uexp_to_info_map( - ~ctx=Builtins.ctx_init, - ~ancestors=[], - rule, - Id.Map.empty, + let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { + let (ps, es) = List.split(rules); + let branch_ids = List.map(UExp.rep_id, es); + let (ps, m) = + map_m(go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty)), ps, m); + let p_constraints = List.map(Info.pat_constraint, ps); + let p_ctxs = List.map(Info.pat_ctx, ps); + let (es, m) = + List.fold_left2( + ((es, m), e, ctx) => + go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), + ([], m), + es, + p_ctxs, ); - inf.ty; - }; - - //ruls_to_info_map was implemented but not sure where to use yet - [@warning "-26"] - let ruls_to_info_map = (rules: list(UExp.t)): list(Typ.t) => { - List.fold_left( - (acc, rule) => {List.append(acc, [type_of_exp(rule)])}, - [], - rules, + ( + es, + List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)), + branch_ids, + Constraint.or_constraints(p_constraints), + m, ); }; - let final_constraint = Constraint.or_constraints(xis); + let (es, e_co_ctxs, branch_ids, final_constraint, m) = + rules_to_info_map(rules, m); let e_tys = List.map(Info.exp_ty, es); - let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); let self = Incon.is_exhaustive(final_constraint) ? unwrapped_self : InexhaustiveMatch(unwrapped_self); - let e_co_ctxs = - List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => let m = utpat_to_info_map(~ctx, ~ancestors, typat, m) |> snd; From f61ab29e955b0bd7fc04d638b311857997984835 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 13:33:33 -0400 Subject: [PATCH 066/141] Fixed 0 rules bug --- src/haz3lcore/dynamics/Constraint.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index f2ed742299..90823edded 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -141,7 +141,7 @@ let unwrap_pair = let rec or_constraints = (lst: list(t)): t => switch (lst) { - | [] => failwith("should have at least one constraint") + | [] => Falsity | [xi] => xi | [xi, ...xis] => Or(xi, or_constraints(xis)) }; From 186cb1e651dfb29020b42055a5dcbf9a17d8739d Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 14:02:55 -0400 Subject: [PATCH 067/141] Init --- src/haz3lcore/statics/Info.re | 1 + 1 file changed, 1 insertion(+) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index a68171bc52..869a7f7a22 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -70,6 +70,7 @@ type error_exp = [@deriving (show({with_path: false}), sexp, yojson)] type error_pat = | ExpectedConstructor /* Only construtors can be applied */ + // TODO | Common(error_common); [@deriving (show({with_path: false}), sexp, yojson)] From 33c484eeea9369191910fb56c8f5ca831d9eef59 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 20:19:53 -0400 Subject: [PATCH 068/141] Added error_pat.Redundant --- src/haz3lcore/statics/Info.re | 5 +++-- src/haz3lweb/view/CursorInspector.re | 11 ++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 869a7f7a22..6708f39ffb 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -70,7 +70,7 @@ type error_exp = [@deriving (show({with_path: false}), sexp, yojson)] type error_pat = | ExpectedConstructor /* Only construtors can be applied */ - // TODO + | Redundant(option(error_pat)) | Common(error_common); [@deriving (show({with_path: false}), sexp, yojson)] @@ -301,8 +301,9 @@ let rec status_common = InHole(Inconsistent(Internal(Typ.of_source(tys)))) }; -let status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => +let rec status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => switch (mode, self) { + // TODO: | | (Syn | Ana(_), Common(self_pat)) | (SynFun, Common(IsConstructor(_) as self_pat)) => /* Little bit of a hack. Anything other than a bound ctr will, in diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 6cc2adf8f6..86db8d7aa9 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -174,9 +174,18 @@ let rec exp_view = (cls: Term.Cls.t, status: Info.status_exp) => | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) }; -let pat_view = (cls: Term.Cls.t, status: Info.status_pat) => +let rec pat_view = (cls: Term.Cls.t, status: Info.status_pat) => switch (status) { | InHole(ExpectedConstructor) => div_err([text("Expected a constructor")]) + | InHole(Redundant(additional_err)) => + switch (additional_err) { + | None => div_err([text("Pattern is necessarily redundant")]) + | Some(err) => + div_err([ + pat_view(cls, InHole(err)), + text("; pattern is necessarily redundant"), + ]) + } | InHole(Common(error)) => div_err(common_err_view(cls, error)) | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) }; From 7276a41aa5e0b5811793f35090e06075b75cc7c2 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 20:52:44 -0400 Subject: [PATCH 069/141] Added Self.pat --- src/haz3lcore/statics/Info.re | 13 ++++++++++++- src/haz3lcore/statics/Self.re | 2 ++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 6708f39ffb..8674eec840 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -303,7 +303,18 @@ let rec status_common = let rec status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => switch (mode, self) { - // TODO: | + | (_, Redundant(self)) => + let additional_err = + switch (status_pat(ctx, mode, self)) { + | InHole(Common(Inconsistent(Internal(_) | Expectation(_))) as err) + | InHole(Common(NoType(_)) as err) => Some(err) + | NotInHole(_) => None + | InHole(Common(Inconsistent(WithArrow(_)))) + | InHole(ExpectedConstructor | Redundant(_)) => + // ExpectedConstructor cannot be a reason to hole-wrap the entire pattern + failwith("InHole(Redundant(impossible_err))") + }; + InHole(Redundant(additional_err)); | (Syn | Ana(_), Common(self_pat)) | (SynFun, Common(IsConstructor(_) as self_pat)) => /* Little bit of a hack. Anything other than a bound ctr will, in diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index 684b19b01b..9f4f7d48ed 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -40,6 +40,7 @@ type exp = [@deriving (show({with_path: false}), sexp, yojson)] type pat = + | Redundant(pat) | Common(t); /* What the type would be if the position had been @@ -64,6 +65,7 @@ let typ_of_exp: (Ctx.t, exp) => option(Typ.t) = let typ_of_pat: (Ctx.t, pat) => option(Typ.t) = ctx => fun + | Redundant(_) => None | Common(self) => typ_of(ctx, self); /* The self of a var depends on the ctx; if the From 50193838dda12ed47415cc456cd71fd68a8e7fdc Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 23:17:02 -0400 Subject: [PATCH 070/141] Fixed Bool bug --- src/haz3lcore/dynamics/Constraint.re | 5 +++-- src/haz3lcore/statics/Statics.re | 8 +++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 90823edded..704f83ca44 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -9,8 +9,8 @@ type t = | NotInt(int) | Float(float) | NotFloat(float) - | Bool(bool) - | NotBool(bool) + | Bool(bool) // Wrong + | NotBool(bool) // Wrong | String(string) | NotString(string) | And(t, t) @@ -20,6 +20,7 @@ type t = | Pair(t, t); // | Tuple(list(t)); +// Unused let rec constrains = (c: t, ty: Typ.t): bool => switch (c, Typ.weak_head_normalize(Builtins.ctx_init, ty)) { | (Truth, _) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 69035e9e21..547e8a8913 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -402,7 +402,13 @@ and upat_to_info_map = | Int(int) => atomic(Just(Int), Constraint.Int(int)) | Float(float) => atomic(Just(Float), Constraint.Float(float)) | Triv => atomic(Just(Prod([])), Constraint.Truth) - | Bool(bool) => atomic(Just(Bool), Constraint.Bool(bool)) + | Bool(bool) => + atomic( + Just(Bool), + bool + ? Constraint.InjL(Constraint.Truth) + : Constraint.InjR(Constraint.Truth), + ) | String(string) => atomic(Just(String), Constraint.String(string)) | ListLit(ps) => let ids = List.map(UPat.rep_id, ps); From c1bc4254baa56123e1d9571a08750653eb2e95f1 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Fri, 20 Oct 2023 23:27:32 -0400 Subject: [PATCH 071/141] Reviewed Constraint.dual --- src/haz3lcore/dynamics/Constraint.re | 1 + 1 file changed, 1 insertion(+) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 704f83ca44..933da40b65 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -62,6 +62,7 @@ let rec dual = (c: t): t => switch (c) { | Truth => Falsity | Falsity => Truth + // The complement of an indeterministic set is still indeterministic | Hole => Hole | Int(n) => NotInt(n) | NotInt(n) => Int(n) From 643e1237898cdf52ecc073fb94abc9e9292e651a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 21 Oct 2023 11:34:42 -0400 Subject: [PATCH 072/141] Fixed String bug --- src/haz3lcore/dynamics/Incon.re | 7 ++++--- src/haz3lcore/dynamics/Sets.re | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index d52fa6662b..12e2616a40 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -89,9 +89,9 @@ let is_inconsistent_string = (xis: list(Constraint.t)): bool => { List.fold_left( ((string_set, not_string_list), xi: Constraint.t) => switch (xi) { - | Float(n) => (StringSet.add(n, string_set), not_string_list) - | NotFloat(n) => (string_set, [n, ...not_string_list]) - | _ => failwith("input can only be Float | NotFloat") + | String(n) => (StringSet.add(n, string_set), not_string_list) + | NotString(n) => (string_set, [n, ...not_string_list]) + | _ => failwith("input can only be String | NotString") }, (StringSet.empty, []), xis, @@ -251,6 +251,7 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => } }; +// xi_cur must not indeterminately entail xi_pre let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => is_inconsistent( ~may=false, diff --git a/src/haz3lcore/dynamics/Sets.re b/src/haz3lcore/dynamics/Sets.re index 67b6099709..5c2179da68 100644 --- a/src/haz3lcore/dynamics/Sets.re +++ b/src/haz3lcore/dynamics/Sets.re @@ -18,6 +18,6 @@ module FloatSet = module StringSet = Set.Make({ - type t = float; + type t = string; let compare = compare; }); From b3d8cce65376c4046e1ec6a1c7257f6b73f11af3 Mon Sep 17 00:00:00 2001 From: Karan Anand Date: Sat, 21 Oct 2023 14:31:06 -0400 Subject: [PATCH 073/141] Generating pattern constraints sequentially --- src/haz3lcore/statics/Statics.re | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 547e8a8913..ed8438a730 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -44,6 +44,21 @@ let map_m = (f, xs, m: Map.t) => xs, ); +let map_m_constraint = (f, xs, m: Map.t) => + List.fold_left( + ((xs, m, acc_cons), x) => + f(x, m) + |> ( + ((x, m)) => ( + xs @ [x], + m, + Constraint.or_constraints([acc_cons, Info.pat_constraint(x)]), + ) + ), + ([], m, Constraint.Falsity), + xs, + ); + let add_info = (ids: list(Id.t), info: Info.t, m: Map.t): Map.t => ids |> List.fold_left((m, id) => Id.Map.add(id, info, m), m); @@ -273,8 +288,14 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); - let (ps, m) = - map_m(go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty)), ps, m); + [@warning "-27"] + //final_cons is the final constraint generated during the mapping process + let (ps, m, final_cons) = + map_m_constraint( + go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty)), + ps, + m, + ); let p_constraints = List.map(Info.pat_constraint, ps); let p_ctxs = List.map(Info.pat_ctx, ps); let (es, m) = From 5b311bcda07961f80a6420aea7e00f2e2be4b463 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 00:28:42 -0400 Subject: [PATCH 074/141] Incon code simplification I --- src/haz3lcore/dynamics/Constraint.re | 11 ++++ src/haz3lcore/dynamics/Incon.re | 88 ++++++++++------------------ 2 files changed, 42 insertions(+), 57 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 933da40b65..88e2b90de8 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -126,6 +126,17 @@ let rec falsify = (c: t): t => | Pair(c1, c2) => Pair(falsify(c1), falsify(c2)) }; +// temporary name +let is_injL = + fun + | InjL(_) => true + | _ => false; + +let is_injR = + fun + | InjR(_) => true + | _ => false; + let unwrapL = fun | InjL(c) => c diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 12e2616a40..237c4b63c5 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -115,60 +115,47 @@ let is_inconsistent_string = (xis: list(Constraint.t)): bool => { let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => switch (xis) { | [] => false + | _ + when + List.exists(Constraint.is_injL, xis) + && List.exists(Constraint.is_injR, xis) => + true | [xi, ...xis'] => switch (xi) { | Truth => is_inconsistent(~may, xis') | Falsity => true - | Hole => may ? true : is_inconsistent(~may, xis') + | Hole => assert(false) // Impossible | And(xi1, xi2) => is_inconsistent(~may, [xi1, xi2, ...xis']) | Or(xi1, xi2) => is_inconsistent(~may, [xi1, ...xis']) && is_inconsistent(~may, [xi2, ...xis']) | InjL(_) => - if (List.exists( - fun - | Constraint.InjR(_) => true - | _ => false, - xis, - )) { - true; - } else { - switch ( - List.partition( - fun - | Constraint.InjL(_) => true - | _ => false, - xis, - ) - ) { - | (injLs, []) => - let unwrap = List.map(Constraint.unwrapL, injLs); - is_inconsistent(~may, unwrap); - | (injLs, other) => is_inconsistent(~may, other @ injLs) - }; + switch ( + List.partition( + fun + | Constraint.InjL(_) => true + | _ => false, + xis, + ) + ) { + | (injLs, []) => + let unwrap = List.map(Constraint.unwrapL, injLs); + is_inconsistent(~may, unwrap); + | (injLs, other) => is_inconsistent(~may, other @ injLs) } | InjR(_) => - if (List.exists( - fun - | Constraint.InjL(_) => true - | _ => false, - xis, - )) { - true; - } else { - switch ( - List.partition( - fun - | Constraint.InjR(_) => true - | _ => false, - xis, - ) - ) { - | (injRs, []) => - let unwrap = List.map(Constraint.unwrapR, injRs); - is_inconsistent(~may, unwrap); - | (injRs, other) => is_inconsistent(~may, other @ injRs) - }; + switch ( + List.partition( + fun + | Constraint.InjR(_) => true + | _ => false, + xis, + ) + ) { + | (injRs, []) => + let unwrap = List.map(Constraint.unwrapR, injRs); + is_inconsistent(~may, unwrap); + | (injRs, other) => is_inconsistent(~may, other @ injRs) } | Int(_) | NotInt(_) => @@ -199,19 +186,7 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => | (fs, other) => is_inconsistent(~may, other @ fs) } | Bool(_) - | NotBool(_) => - switch ( - List.partition( - fun - | Constraint.Bool(_) - | NotBool(_) => true - | _ => false, - xis, - ) - ) { - | (fs, []) => is_inconsistent_bool(fs) - | (fs, other) => is_inconsistent(~may, other @ fs) - } + | NotBool(_) => assert(false) // Unused | String(_) | NotString(_) => switch ( @@ -251,7 +226,6 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => } }; -// xi_cur must not indeterminately entail xi_pre let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => is_inconsistent( ~may=false, From 9ec5fe030e19bc70b8b51736fb22777b525f9a16 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 00:58:53 -0400 Subject: [PATCH 075/141] Applied Constraint.is_inl and Constraint.is_inr --- src/haz3lcore/dynamics/Constraint.re | 4 ++-- src/haz3lcore/dynamics/Incon.re | 22 ++++------------------ 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 88e2b90de8..14984c575c 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -127,12 +127,12 @@ let rec falsify = (c: t): t => }; // temporary name -let is_injL = +let is_inl = fun | InjL(_) => true | _ => false; -let is_injR = +let is_inr = fun | InjR(_) => true | _ => false; diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 237c4b63c5..dfe2698fe1 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -117,8 +117,8 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => | [] => false | _ when - List.exists(Constraint.is_injL, xis) - && List.exists(Constraint.is_injR, xis) => + List.exists(Constraint.is_inl, xis) + && List.exists(Constraint.is_inr, xis) => true | [xi, ...xis'] => switch (xi) { @@ -130,28 +130,14 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => is_inconsistent(~may, [xi1, ...xis']) && is_inconsistent(~may, [xi2, ...xis']) | InjL(_) => - switch ( - List.partition( - fun - | Constraint.InjL(_) => true - | _ => false, - xis, - ) - ) { + switch (List.partition(Constraint.is_inl, xis)) { | (injLs, []) => let unwrap = List.map(Constraint.unwrapL, injLs); is_inconsistent(~may, unwrap); | (injLs, other) => is_inconsistent(~may, other @ injLs) } | InjR(_) => - switch ( - List.partition( - fun - | Constraint.InjR(_) => true - | _ => false, - xis, - ) - ) { + switch (List.partition(Constraint.is_inr, xis)) { | (injRs, []) => let unwrap = List.map(Constraint.unwrapR, injRs); is_inconsistent(~may, unwrap); From 7561afdf7edbbf0cfd2ca6895df1a8f71a6a694c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 01:19:37 -0400 Subject: [PATCH 076/141] Incon code simplification II --- src/haz3lcore/dynamics/Incon.re | 49 ++------------------------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index dfe2698fe1..a38c0cb964 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -16,12 +16,7 @@ let is_inconsistent_nums = (xis: list(Constraint.t)): bool => { true; } else { List.fold_left( - (incon, n) => - if (incon) { - incon; - } else { - IntSet.mem(n, int_set); - }, + (incon, n) => incon || IntSet.mem(n, int_set), false, not_int_list, ); @@ -44,46 +39,13 @@ let is_inconsistent_float = (xis: list(Constraint.t)): bool => { true; } else { List.fold_left( - (incon, n) => - if (incon) { - incon; - } else { - FloatSet.mem(n, float_set); - }, + (incon, n) => incon || FloatSet.mem(n, float_set), false, not_float_list, ); }; }; -let is_inconsistent_bool = (xis: list(Constraint.t)): bool => { - let (bool_set, not_bool_list) = - List.fold_left( - ((bool_set, not_bool_list), xi: Constraint.t) => - switch (xi) { - | Bool(b) => (BoolSet.add(b, bool_set), not_bool_list) - | NotBool(b) => (bool_set, [b, ...not_bool_list]) - | _ => failwith("input can only be Bool | NotBool") - }, - (BoolSet.empty, []), - xis, - ); - if (BoolSet.cardinal(bool_set) > 1) { - true; - } else { - List.fold_left( - (incon, b) => - if (incon) { - incon; - } else { - BoolSet.mem(b, bool_set); - }, - false, - not_bool_list, - ); - }; -}; - let is_inconsistent_string = (xis: list(Constraint.t)): bool => { let (string_set, not_string_list) = List.fold_left( @@ -100,12 +62,7 @@ let is_inconsistent_string = (xis: list(Constraint.t)): bool => { true; } else { List.fold_left( - (incon, n) => - if (incon) { - incon; - } else { - StringSet.mem(n, string_set); - }, + (incon, n) => incon || StringSet.mem(n, string_set), false, not_string_list, ); From 65c8b1458f580427d437c2dc8da3dd91bf83d70c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 01:25:31 -0400 Subject: [PATCH 077/141] Deleted the argument ~may in Incon.re --- src/haz3lcore/dynamics/Incon.re | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index a38c0cb964..0136380ba3 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -69,7 +69,7 @@ let is_inconsistent_string = (xis: list(Constraint.t)): bool => { }; }; -let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => +let rec is_inconsistent = (xis: list(Constraint.t)): bool => switch (xis) { | [] => false | _ @@ -79,26 +79,25 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => true | [xi, ...xis'] => switch (xi) { - | Truth => is_inconsistent(~may, xis') + | Truth => is_inconsistent(xis') | Falsity => true | Hole => assert(false) // Impossible - | And(xi1, xi2) => is_inconsistent(~may, [xi1, xi2, ...xis']) + | And(xi1, xi2) => is_inconsistent([xi1, xi2, ...xis']) | Or(xi1, xi2) => - is_inconsistent(~may, [xi1, ...xis']) - && is_inconsistent(~may, [xi2, ...xis']) + is_inconsistent([xi1, ...xis']) && is_inconsistent([xi2, ...xis']) | InjL(_) => switch (List.partition(Constraint.is_inl, xis)) { | (injLs, []) => let unwrap = List.map(Constraint.unwrapL, injLs); - is_inconsistent(~may, unwrap); - | (injLs, other) => is_inconsistent(~may, other @ injLs) + is_inconsistent(unwrap); + | (injLs, other) => is_inconsistent(other @ injLs) } | InjR(_) => switch (List.partition(Constraint.is_inr, xis)) { | (injRs, []) => let unwrap = List.map(Constraint.unwrapR, injRs); - is_inconsistent(~may, unwrap); - | (injRs, other) => is_inconsistent(~may, other @ injRs) + is_inconsistent(unwrap); + | (injRs, other) => is_inconsistent(other @ injRs) } | Int(_) | NotInt(_) => @@ -112,7 +111,7 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => ) ) { | (ns, []) => is_inconsistent_nums(ns) - | (ns, other) => is_inconsistent(~may, other @ ns) + | (ns, other) => is_inconsistent(other @ ns) } | Float(_) | NotFloat(_) => @@ -126,7 +125,7 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => ) ) { | (fs, []) => is_inconsistent_float(fs) - | (fs, other) => is_inconsistent(~may, other @ fs) + | (fs, other) => is_inconsistent(other @ fs) } | Bool(_) | NotBool(_) => assert(false) // Unused @@ -142,7 +141,7 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => ) ) { | (fs, []) => is_inconsistent_string(fs) - | (fs, other) => is_inconsistent(~may, other @ fs) + | (fs, other) => is_inconsistent(other @ fs) } | Pair(_, _) => switch ( @@ -163,17 +162,16 @@ let rec is_inconsistent = (~may=false, xis: list(Constraint.t)): bool => ([], []), pairs, ); - is_inconsistent(~may, xisL) || is_inconsistent(~may, xisR); - | (pairs, other) => is_inconsistent(~may, other @ pairs) + is_inconsistent(xisL) || is_inconsistent(xisR); + | (pairs, other) => is_inconsistent(other @ pairs) } } }; let is_redundant = (xi_cur: Constraint.t, xi_pre: Constraint.t): bool => is_inconsistent( - ~may=false, Constraint.[And(truify(xi_cur), dual(falsify(xi_pre)))], ); let is_exhaustive = (xi: Constraint.t): bool => - is_inconsistent(~may=true, Constraint.[dual(truify(xi))]); + is_inconsistent(Constraint.[dual(truify(xi))]); From 3c8e0f690f8263626c75013ca5562db2392e4700 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 02:10:59 -0400 Subject: [PATCH 078/141] Incon code simplification III --- src/haz3lcore/dynamics/Incon.re | 66 +++++++++------------------------ 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 0136380ba3..0d23a8309b 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -1,6 +1,6 @@ open Sets; -let is_inconsistent_nums = (xis: list(Constraint.t)): bool => { +let is_inconsistent_int = (xis: list(Constraint.t)): bool => { let (int_set, not_int_list) = List.fold_left( ((int_set, not_int_list), xi: Constraint.t) => @@ -12,15 +12,8 @@ let is_inconsistent_nums = (xis: list(Constraint.t)): bool => { (IntSet.empty, []), xis, ); - if (IntSet.cardinal(int_set) > 1) { - true; - } else { - List.fold_left( - (incon, n) => incon || IntSet.mem(n, int_set), - false, - not_int_list, - ); - }; + IntSet.cardinal(int_set) > 1 + || List.exists(IntSet.mem(_, int_set), not_int_list); }; let is_inconsistent_float = (xis: list(Constraint.t)): bool => { @@ -35,15 +28,8 @@ let is_inconsistent_float = (xis: list(Constraint.t)): bool => { (FloatSet.empty, []), xis, ); - if (FloatSet.cardinal(float_set) > 1) { - true; - } else { - List.fold_left( - (incon, n) => incon || FloatSet.mem(n, float_set), - false, - not_float_list, - ); - }; + FloatSet.cardinal(float_set) > 1 + || List.exists(FloatSet.mem(_, float_set), not_float_list); }; let is_inconsistent_string = (xis: list(Constraint.t)): bool => { @@ -58,15 +44,8 @@ let is_inconsistent_string = (xis: list(Constraint.t)): bool => { (StringSet.empty, []), xis, ); - if (StringSet.cardinal(string_set) > 1) { - true; - } else { - List.fold_left( - (incon, n) => incon || StringSet.mem(n, string_set), - false, - not_string_list, - ); - }; + StringSet.cardinal(string_set) > 1 + || List.exists(StringSet.mem(_, string_set), not_string_list); }; let rec is_inconsistent = (xis: list(Constraint.t)): bool => @@ -88,16 +67,14 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => | InjL(_) => switch (List.partition(Constraint.is_inl, xis)) { | (injLs, []) => - let unwrap = List.map(Constraint.unwrapL, injLs); - is_inconsistent(unwrap); - | (injLs, other) => is_inconsistent(other @ injLs) + injLs |> List.map(Constraint.unwrapL) |> is_inconsistent + | (injLs, others) => is_inconsistent(others @ injLs) } | InjR(_) => switch (List.partition(Constraint.is_inr, xis)) { | (injRs, []) => - let unwrap = List.map(Constraint.unwrapR, injRs); - is_inconsistent(unwrap); - | (injRs, other) => is_inconsistent(other @ injRs) + injRs |> List.map(Constraint.unwrapR) |> is_inconsistent + | (injRs, others) => is_inconsistent(others @ injRs) } | Int(_) | NotInt(_) => @@ -110,8 +87,8 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => xis, ) ) { - | (ns, []) => is_inconsistent_nums(ns) - | (ns, other) => is_inconsistent(other @ ns) + | (ns, []) => is_inconsistent_int(ns) + | (ns, others) => is_inconsistent(others @ ns) } | Float(_) | NotFloat(_) => @@ -125,7 +102,7 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => ) ) { | (fs, []) => is_inconsistent_float(fs) - | (fs, other) => is_inconsistent(other @ fs) + | (fs, others) => is_inconsistent(others @ fs) } | Bool(_) | NotBool(_) => assert(false) // Unused @@ -140,8 +117,8 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => xis, ) ) { - | (fs, []) => is_inconsistent_string(fs) - | (fs, other) => is_inconsistent(other @ fs) + | (ss, []) => is_inconsistent_string(ss) + | (ss, others) => is_inconsistent(others @ ss) } | Pair(_, _) => switch ( @@ -154,16 +131,9 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => ) { | (pairs, []) => let (xisL, xisR) = - List.fold_left( - ((xisL, xisR), pair) => { - let (xiL, xiR) = Constraint.unwrap_pair(pair); - ([xiL, ...xisL], [xiR, ...xisR]); - }, - ([], []), - pairs, - ); + pairs |> List.map(Constraint.unwrap_pair) |> List.split; is_inconsistent(xisL) || is_inconsistent(xisR); - | (pairs, other) => is_inconsistent(other @ pairs) + | (pairs, others) => is_inconsistent(others @ pairs) } } }; From f31485b28d3a5b7b982422dc213ecc439f193a31 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 02:14:55 -0400 Subject: [PATCH 079/141] Deleted Constraint.Bool/NotBool --- src/haz3lcore/dynamics/Constraint.re | 10 ---------- src/haz3lcore/dynamics/Incon.re | 2 -- 2 files changed, 12 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 14984c575c..156546957a 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -9,8 +9,6 @@ type t = | NotInt(int) | Float(float) | NotFloat(float) - | Bool(bool) // Wrong - | NotBool(bool) // Wrong | String(string) | NotString(string) | And(t, t) @@ -30,8 +28,6 @@ let rec constrains = (c: t, ty: Typ.t): bool => | (Int(_) | NotInt(_), _) => false | (Float(_) | NotFloat(_), Float) => true | (Float(_) | NotFloat(_), _) => false - | (Bool(_) | NotBool(_), Bool) => true - | (Bool(_) | NotBool(_), _) => false | (String(_) | NotString(_), String) => true | (String(_) | NotString(_), _) => false | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) @@ -68,8 +64,6 @@ let rec dual = (c: t): t => | NotInt(n) => Int(n) | Float(n) => NotFloat(n) | NotFloat(n) => Float(n) - | Bool(b) => NotBool(b) - | NotBool(b) => Bool(b) | String(n) => NotString(n) | NotString(n) => String(n) | And(c1, c2) => Or(dual(c1), dual(c2)) @@ -94,8 +88,6 @@ let rec truify = (c: t): t => | NotInt(_) | Float(_) | NotFloat(_) - | Bool(_) - | NotBool(_) | String(_) | NotString(_) => c | And(c1, c2) => And(truify(c1), truify(c2)) @@ -115,8 +107,6 @@ let rec falsify = (c: t): t => | NotInt(_) | Float(_) | NotFloat(_) - | Bool(_) - | NotBool(_) | String(_) | NotString(_) => c | And(c1, c2) => And(falsify(c1), falsify(c2)) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 0d23a8309b..15497f7b91 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -104,8 +104,6 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => | (fs, []) => is_inconsistent_float(fs) | (fs, others) => is_inconsistent(others @ fs) } - | Bool(_) - | NotBool(_) => assert(false) // Unused | String(_) | NotString(_) => switch ( From 0d5f5b55774b2ba692aa794ff12f0a268a9eb801 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 02:34:14 -0400 Subject: [PATCH 080/141] Inlined map_m_constraint Co-Authored-By: Karan Anand <58492510+karananand01@users.noreply.github.com> --- src/haz3lcore/statics/Statics.re | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index ed8438a730..cc917e42e5 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -44,21 +44,6 @@ let map_m = (f, xs, m: Map.t) => xs, ); -let map_m_constraint = (f, xs, m: Map.t) => - List.fold_left( - ((xs, m, acc_cons), x) => - f(x, m) - |> ( - ((x, m)) => ( - xs @ [x], - m, - Constraint.or_constraints([acc_cons, Info.pat_constraint(x)]), - ) - ), - ([], m, Constraint.Falsity), - xs, - ); - let add_info = (ids: list(Id.t), info: Info.t, m: Map.t): Map.t => ids |> List.fold_left((m, id) => Id.Map.add(id, info, m), m); @@ -291,10 +276,18 @@ and uexp_to_info_map = [@warning "-27"] //final_cons is the final constraint generated during the mapping process let (ps, m, final_cons) = - map_m_constraint( - go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty)), + List.fold_left( + ((xs, m, acc_cons), x) => + go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty), x, m) + |> ( + ((x, m)) => ( + xs @ [x], + m, + Constraint.Or(acc_cons, Info.pat_constraint(x)), + ) + ), + ([], m, Constraint.Falsity), ps, - m, ); let p_constraints = List.map(Info.pat_constraint, ps); let p_ctxs = List.map(Info.pat_ctx, ps); From 5361ce690aeb044eddee6fbe3f65c0731921e6a0 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 22 Oct 2023 03:59:29 -0400 Subject: [PATCH 081/141] Adjusted info for redundant patterns --- src/haz3lcore/statics/Info.re | 3 ++- src/haz3lcore/statics/Statics.re | 42 +++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 8674eec840..cf692f8f71 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -460,8 +460,9 @@ let fixed_constraint_pat = (ctx, mode: Mode.t, self: Self.pat, constraint_: Constraint.t) : Constraint.t => switch (status_pat(ctx, mode, self)) { - | InHole(_) => Constraint.Hole + | InHole(Redundant(None)) | NotInHole(_) => constraint_ + | InHole(_) => Constraint.Hole }; let fixed_typ_exp = (ctx, mode: Mode.t, self: Self.exp): Typ.t => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index cc917e42e5..840f2a5292 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -273,23 +273,37 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); - [@warning "-27"] - //final_cons is the final constraint generated during the mapping process - let (ps, m, final_cons) = + let (ps, m, final_constraint) = List.fold_left( - ((xs, m, acc_cons), x) => - go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty), x, m) - |> ( - ((x, m)) => ( - xs @ [x], - m, - Constraint.Or(acc_cons, Info.pat_constraint(x)), - ) - ), + ((ps, m, acc_constraint), p) => { + let (p, m) = + go_pat(~is_synswitch=false, ~mode=Mode.Ana(scrut.ty), p, m); + let p_constraint = Info.pat_constraint(p); + if (!Incon.is_redundant(p_constraint, acc_constraint)) { + (ps @ [p], m, Constraint.Or(p_constraint, acc_constraint)); + } else { + let info = + Info.derived_pat( + ~upat=p.term, + ~ctx=p.ctx, + ~mode=p.mode, + ~ancestors=p.ancestors, + ~self=Redundant(p.self), + // Mark patterns as redundant at the top level + // because redundancy doesn't make sense in a smaller context + ~constraint_=p_constraint, + ); + ( + ps @ [info], + // Override the info for the single upat + add_info(p.term.ids, InfoPat(info), m), + acc_constraint // Redundant patterns are ignored + ); + }; + }, ([], m, Constraint.Falsity), ps, ); - let p_constraints = List.map(Info.pat_constraint, ps); let p_ctxs = List.map(Info.pat_ctx, ps); let (es, m) = List.fold_left2( @@ -303,7 +317,7 @@ and uexp_to_info_map = es, List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)), branch_ids, - Constraint.or_constraints(p_constraints), + final_constraint, m, ); }; From e9a8896e1dc0ae270ec10066c074c82ecd685f69 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang <108375845+pigumar1@users.noreply.github.com> Date: Sun, 22 Oct 2023 12:42:02 -0400 Subject: [PATCH 082/141] Revert InvalidOperationError.re --- src/haz3lcore/dynamics/InvalidOperationError.re | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/haz3lcore/dynamics/InvalidOperationError.re b/src/haz3lcore/dynamics/InvalidOperationError.re index 3a6e31c35f..ce8c94e888 100644 --- a/src/haz3lcore/dynamics/InvalidOperationError.re +++ b/src/haz3lcore/dynamics/InvalidOperationError.re @@ -5,8 +5,6 @@ type t = | DivideByZero | NegativeExponent | OutOfFuel - // | InvalidIntOfString - // | InvalidFloatOfString | InvalidProjection; let err_msg = (err: t): string => @@ -16,7 +14,5 @@ let err_msg = (err: t): string => | DivideByZero => "Error: Divide by Zero" | NegativeExponent => "Error: Negative Exponent in Integer Exponentiation (Consider using **.)" | OutOfFuel => "Error: Out of Fuel" - // | InvalidIntOfString => "Error: Invalid String to Int Conversion" - // | InvalidFloatOfString => "Error: Invalid String to Float Conversion" | InvalidProjection => "Error: Invalid Projection" }; From 3c4e58db465c8038b9385a9ded0d37b90957044f Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Mon, 23 Oct 2023 00:11:02 -0400 Subject: [PATCH 083/141] Made redundancy not a runtime error --- src/haz3lcore/dynamics/Elaborator.re | 7 +++++++ src/haz3lcore/statics/Info.re | 9 ++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 126dee2e21..28d271688a 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -284,6 +284,13 @@ let rec dhexp_of_uexp = and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.t) => { switch (Id.Map.find_opt(Term.UPat.rep_id(upat), m)) { | Some(InfoPat({mode, self, ctx, _})) => + // NOTE: for the current implementation, redundancy is considered a static error + // but not a runtime error. + let self = + switch (self) { + | Redundant(self) => self + | _ => self + }; let err_status = Info.status_pat(ctx, mode, self); let maybe_reason: option(ErrStatus.HoleReason.t) = switch (err_status) { diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index cf692f8f71..69bbb1c6db 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -450,11 +450,18 @@ let fixed_typ_ok: ok_pat => Typ.t = | Ana(Consistent({join, _})) => join | Ana(InternallyInconsistent({ana, _})) => ana; -let fixed_typ_pat = (ctx, mode: Mode.t, self: Self.pat): Typ.t => +let fixed_typ_pat = (ctx, mode: Mode.t, self: Self.pat): Typ.t => { + // TODO: get rid of unwrapping (probably by changing the implementation of error_exp.Redundant) + let self = + switch (self) { + | Redundant(self) => self + | _ => self + }; switch (status_pat(ctx, mode, self)) { | InHole(_) => Unknown(Internal) | NotInHole(ok) => fixed_typ_ok(ok) }; +}; let fixed_constraint_pat = (ctx, mode: Mode.t, self: Self.pat, constraint_: Constraint.t) From cd03276cb320285b358f2e6fbbb2a6457708f3c4 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang <108375845+pigumar1@users.noreply.github.com> Date: Mon, 23 Oct 2023 12:58:26 -0400 Subject: [PATCH 084/141] Allowed redundant patterns to have types in Self.typ_of_pat --- src/haz3lcore/statics/Self.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index 9f4f7d48ed..3b4e1b7cc8 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -62,10 +62,10 @@ let typ_of_exp: (Ctx.t, exp) => option(Typ.t) = | InexhaustiveMatch(_) => None | Common(self) => typ_of(ctx, self); -let typ_of_pat: (Ctx.t, pat) => option(Typ.t) = +let rec typ_of_pat: (Ctx.t, pat) => option(Typ.t) = ctx => fun - | Redundant(_) => None + | Redundant(pat) => typ_of_pat(ctx, pat) | Common(self) => typ_of(ctx, self); /* The self of a var depends on the ctx; if the From dd9aed58a11c02f61f7be985563c6aedcd11100c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang <108375845+pigumar1@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:22:22 -0400 Subject: [PATCH 085/141] Having applications of non-ctrs and unbounded ctrs emit Falsity --- src/haz3lcore/dynamics/Constraint.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 933da40b65..241db9ef92 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -162,11 +162,11 @@ let of_ap = (ctx, ctr: option(Constructor.t), arg: t): t => switch (ctr) { | Some(name) => switch (Ctx.lookup_ctr(ctx, name)) { - | None => Hole // TODO: review + | None => Falsity // TODO: review | Some({num_variants, nth, _}) => arg |> ctr_of_nth_variant(num_variants, nth) } - | None => Hole // TODO: review + | None => Falsity // TODO: review }; let of_ctr = (ctx, name) => of_ap(ctx, Some(name), Truth); From 8403af349c9eb62699c36e750a047a1481759042 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Wed, 25 Oct 2023 21:29:17 -0400 Subject: [PATCH 086/141] Fixed multiple-error-holes bug --- src/haz3lweb/view/Deco.re | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/haz3lweb/view/Deco.re b/src/haz3lweb/view/Deco.re index d349e91c92..1de355ce09 100644 --- a/src/haz3lweb/view/Deco.re +++ b/src/haz3lweb/view/Deco.re @@ -300,6 +300,11 @@ module Deco = // faster infomap traversal let err_holes = (_z: Zipper.t) => { + let is_rep = (id: Id.t) => + switch (Id.Map.find_opt(id, M.terms)) { + | None => false + | Some(term) => id == Term.rep_id(term) + }; Id.Map.fold( (id, info, acc) => /* Because of artefacts in Maketerm ID handling, @@ -309,7 +314,12 @@ module Deco = * when iterating over the info_map should have no * effect, beyond supressing the resulting Not_found exs */ switch (Id.Map.find_opt(id, M.term_ranges)) { - | Some(_) when Info.is_error(info) => [ + /* Without filtering out non-rep ids, there will be + * multiple error holes wrapping around a case expression + * or a list literal that has at least one comma, since the + * rules of case expressions and the inner commas of list + * literals are technically different forms */ + | Some(_) when is_rep(id) && Info.is_error(info) => [ term_highlight(~clss=["err-hole"], id), ...acc, ] From 5d8a674926469534a9cdf846885829aa2f5b9743 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang <108375845+pigumar1@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:22:31 -0400 Subject: [PATCH 087/141] =?UTF-8?q?Removed=20=E2=80=9Cnecessarily=E2=80=9D?= =?UTF-8?q?=20in=20the=20user-facing=20message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/haz3lweb/view/CursorInspector.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 6cc2adf8f6..cf181113fb 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -163,11 +163,11 @@ let rec exp_view = (cls: Term.Cls.t, status: Info.status_exp) => div_err([code_err(name), text("not found")]) | InHole(InexhaustiveMatch(additional_err)) => switch (additional_err) { - | None => div_err([text("Case expression is necessarily inexhaustive")]) + | None => div_err([text("Case expression is inexhaustive")]) | Some(err) => div_err([ exp_view(Exp(Match), InHole(err)), - text("; case expression is necessarily inexhaustive"), + text("; case expression is inexhaustive"), ]) } | InHole(Common(error)) => div_err(common_err_view(cls, error)) From df04be9cdde305c4a498d1cbfcd9b68f884b7e6b Mon Sep 17 00:00:00 2001 From: Jiezhong Yang <108375845+pigumar1@users.noreply.github.com> Date: Thu, 26 Oct 2023 12:25:38 -0400 Subject: [PATCH 088/141] =?UTF-8?q?=20Removed=20=E2=80=9Cnecessarily?= =?UTF-8?q?=E2=80=9D=20in=20the=20user-facing=20message?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/haz3lweb/view/CursorInspector.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 78fd8b9922..b586e6dfe2 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -179,11 +179,11 @@ let rec pat_view = (cls: Term.Cls.t, status: Info.status_pat) => | InHole(ExpectedConstructor) => div_err([text("Expected a constructor")]) | InHole(Redundant(additional_err)) => switch (additional_err) { - | None => div_err([text("Pattern is necessarily redundant")]) + | None => div_err([text("Pattern is redundant")]) | Some(err) => div_err([ pat_view(cls, InHole(err)), - text("; pattern is necessarily redundant"), + text("; pattern is redundant"), ]) } | InHole(Common(error)) => div_err(common_err_view(cls, error)) From ed3138ebdb66a5ae61042f5b9eb680fbcd5e071b Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Thu, 26 Oct 2023 12:31:31 -0400 Subject: [PATCH 089/141] Reformatted --- src/haz3lweb/view/CursorInspector.re | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index b586e6dfe2..027b0320c4 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -181,10 +181,7 @@ let rec pat_view = (cls: Term.Cls.t, status: Info.status_pat) => switch (additional_err) { | None => div_err([text("Pattern is redundant")]) | Some(err) => - div_err([ - pat_view(cls, InHole(err)), - text("; pattern is redundant"), - ]) + div_err([pat_view(cls, InHole(err)), text("; pattern is redundant")]) } | InHole(Common(error)) => div_err(common_err_view(cls, error)) | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) From 32230474b2ff3039561cf9081a7910293813788b Mon Sep 17 00:00:00 2001 From: disconcision Date: Thu, 26 Oct 2023 15:26:06 -0400 Subject: [PATCH 090/141] fix dhexp error hole formatting --- src/haz3lweb/www/style.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/haz3lweb/www/style.css b/src/haz3lweb/www/style.css index 6a646dc172..a8ea7bcae0 100644 --- a/src/haz3lweb/www/style.css +++ b/src/haz3lweb/www/style.css @@ -1517,6 +1517,7 @@ svg.expandable path { } .result { + padding-top: 0.1em; min-height: 1.6em; width: 100%; overflow-y: hidden; @@ -1548,8 +1549,6 @@ svg.expandable path { .DHCode svg.err-hole { fill: #d001; - transform: scaleY(0.8); - /* HACK(andrew) */ stroke-dasharray: 1, 1; stroke: var(--err-color); stroke-width: 1.2px; From 717fe511b1d54974a524c540b1f66955ae7f5592 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 18 Nov 2023 16:10:33 -0500 Subject: [PATCH 091/141] Small adjustments --- src/haz3lcore/dynamics/Constraint.re | 6 ++---- src/haz3lcore/dynamics/Incon.re | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 29bb54b9d3..f5e6c7b256 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -16,7 +16,6 @@ type t = | InjL(t) | InjR(t) | Pair(t, t); -// | Tuple(list(t)); // Unused let rec constrains = (c: t, ty: Typ.t): bool => @@ -58,14 +57,13 @@ let rec dual = (c: t): t => switch (c) { | Truth => Falsity | Falsity => Truth - // The complement of an indeterministic set is still indeterministic | Hole => Hole | Int(n) => NotInt(n) | NotInt(n) => Int(n) | Float(n) => NotFloat(n) | NotFloat(n) => Float(n) - | String(n) => NotString(n) - | NotString(n) => String(n) + | String(s) => NotString(s) + | NotString(s) => String(s) | And(c1, c2) => Or(dual(c1), dual(c2)) | Or(c1, c2) => And(dual(c1), dual(c2)) | InjL(c1) => Or(InjL(dual(c1)), InjR(Truth)) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 15497f7b91..460c3c14f6 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -37,8 +37,8 @@ let is_inconsistent_string = (xis: list(Constraint.t)): bool => { List.fold_left( ((string_set, not_string_list), xi: Constraint.t) => switch (xi) { - | String(n) => (StringSet.add(n, string_set), not_string_list) - | NotString(n) => (string_set, [n, ...not_string_list]) + | String(s) => (StringSet.add(n, string_set), not_string_list) + | NotString(s) => (string_set, [n, ...not_string_list]) | _ => failwith("input can only be String | NotString") }, (StringSet.empty, []), From 9a8a8ec6b1c568f7db19b9ac1766337a77916f34 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 18 Nov 2023 16:11:55 -0500 Subject: [PATCH 092/141] Removed Constraint.constrains --- src/haz3lcore/dynamics/Constraint.re | 36 ---------------------------- 1 file changed, 36 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index f5e6c7b256..6348456c19 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -17,42 +17,6 @@ type t = | InjR(t) | Pair(t, t); -// Unused -let rec constrains = (c: t, ty: Typ.t): bool => - switch (c, Typ.weak_head_normalize(Builtins.ctx_init, ty)) { - | (Truth, _) - | (Falsity, _) - | (Hole, _) => true - | (Int(_) | NotInt(_), Int) => true - | (Int(_) | NotInt(_), _) => false - | (Float(_) | NotFloat(_), Float) => true - | (Float(_) | NotFloat(_), _) => false - | (String(_) | NotString(_), String) => true - | (String(_) | NotString(_), _) => false - | (And(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) - | (Or(c1, c2), _) => constrains(c1, ty) && constrains(c2, ty) - // Treates sum as if it is left associative - | (InjL(c1), Sum(map)) => - switch (List.hd(map)) { - | (_, Some(ty1)) => constrains(c1, ty1) - | _ => false - } - | (InjL(_), _) => false - | (InjR(c2), Sum(map)) => - switch (List.tl(map)) { - | [] => false - | [(_, Some(ty2))] => constrains(c2, ty2) - | map' => constrains(c2, Sum(map')) - } - | (InjR(_), _) => false - | (Pair(c1, c2), Prod([ty_hd, ...ty_tl])) => - constrains(c1, ty_hd) && constrains(c2, Prod(ty_tl)) - | (Pair(_), _) => false - // | (Tuple(cs), Prod(tys)) when List.length(cs) == List.length(tys) => - // List.for_all2(constrains, cs, tys) - // | (Tuple(_), _) => false - }; - let rec dual = (c: t): t => switch (c) { | Truth => Falsity From 079bef956099c22d80681b1e5151408d5b71e85a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 18 Nov 2023 16:17:02 -0500 Subject: [PATCH 093/141] Compile --- src/haz3lcore/dynamics/Incon.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 460c3c14f6..68cd54f48c 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -37,8 +37,8 @@ let is_inconsistent_string = (xis: list(Constraint.t)): bool => { List.fold_left( ((string_set, not_string_list), xi: Constraint.t) => switch (xi) { - | String(s) => (StringSet.add(n, string_set), not_string_list) - | NotString(s) => (string_set, [n, ...not_string_list]) + | String(s) => (StringSet.add(s, string_set), not_string_list) + | NotString(s) => (string_set, [s, ...not_string_list]) | _ => failwith("input can only be String | NotString") }, (StringSet.empty, []), From 24a2c2e5b9e38fb41553dd0740d8f2514eee2319 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 18 Nov 2023 16:27:15 -0500 Subject: [PATCH 094/141] Replaced is_inl/r with is_injL/R --- src/haz3lcore/dynamics/Constraint.re | 6 ++---- src/haz3lcore/dynamics/Incon.re | 8 ++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 6348456c19..6d45857893 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -37,7 +37,6 @@ let rec dual = (c: t): t => Pair(c1, dual(c2)), Or(Pair(dual(c1), c2), Pair(dual(c1), dual(c2))), ) - // | Tuple(cs) => // TODO }; /** substitute Truth for Hole */ @@ -78,13 +77,12 @@ let rec falsify = (c: t): t => | Pair(c1, c2) => Pair(falsify(c1), falsify(c2)) }; -// temporary name -let is_inl = +let is_injL = fun | InjL(_) => true | _ => false; -let is_inr = +let is_injR = fun | InjR(_) => true | _ => false; diff --git a/src/haz3lcore/dynamics/Incon.re b/src/haz3lcore/dynamics/Incon.re index 68cd54f48c..6f5c6af13f 100644 --- a/src/haz3lcore/dynamics/Incon.re +++ b/src/haz3lcore/dynamics/Incon.re @@ -53,8 +53,8 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => | [] => false | _ when - List.exists(Constraint.is_inl, xis) - && List.exists(Constraint.is_inr, xis) => + List.exists(Constraint.is_injL, xis) + && List.exists(Constraint.is_injR, xis) => true | [xi, ...xis'] => switch (xi) { @@ -65,13 +65,13 @@ let rec is_inconsistent = (xis: list(Constraint.t)): bool => | Or(xi1, xi2) => is_inconsistent([xi1, ...xis']) && is_inconsistent([xi2, ...xis']) | InjL(_) => - switch (List.partition(Constraint.is_inl, xis)) { + switch (List.partition(Constraint.is_injL, xis)) { | (injLs, []) => injLs |> List.map(Constraint.unwrapL) |> is_inconsistent | (injLs, others) => is_inconsistent(others @ injLs) } | InjR(_) => - switch (List.partition(Constraint.is_inr, xis)) { + switch (List.partition(Constraint.is_injR, xis)) { | (injRs, []) => injRs |> List.map(Constraint.unwrapR) |> is_inconsistent | (injRs, others) => is_inconsistent(others @ injRs) From e1bbb70ceed73016df3ac92f0b7c68db24aa6d22 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sat, 18 Nov 2023 20:56:01 -0500 Subject: [PATCH 095/141] New structure for non-exhaustive case matches --- src/haz3lcore/statics/Statics.re | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index f1d304c726..6a3c700ce4 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -299,9 +299,13 @@ and uexp_to_info_map = let e_tys = List.map(Info.exp_ty, es); let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); + let is_exhaustive = Incon.is_exhaustive(final_constraint); let self = - Incon.is_exhaustive(final_constraint) - ? unwrapped_self : InexhaustiveMatch(unwrapped_self); + is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); + if (!is_exhaustive) { + let dual_constraint = Constraint.dual(Constraint.or_constraints(final_constraint)); + // TODO + } add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => From 5b72b62b3169f2ad8682b6ce0282fb4c1c41b2a0 Mon Sep 17 00:00:00 2001 From: DavidFangWJ <2500097466@qq.com> Date: Sat, 18 Nov 2023 21:55:09 -0500 Subject: [PATCH 096/141] Fix bug from last commit. --- src/haz3lcore/statics/Statics.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 6a3c700ce4..2a03c1e705 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -303,7 +303,7 @@ and uexp_to_info_map = let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); if (!is_exhaustive) { - let dual_constraint = Constraint.dual(Constraint.or_constraints(final_constraint)); + let dual_constraint = Constraint.dual(final_constraint); // TODO } From 2ebb54a335f958896dd95a597d4c73e11004994f Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 21 Nov 2023 19:06:29 -0500 Subject: [PATCH 097/141] init --- src/haz3lcore/statics/Statics.re | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 2a03c1e705..bb23968c0d 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -302,10 +302,10 @@ and uexp_to_info_map = let is_exhaustive = Incon.is_exhaustive(final_constraint); let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); - if (!is_exhaustive) { - let dual_constraint = Constraint.dual(final_constraint); - // TODO - } + // if (!is_exhaustive) { + // let dual_constraint = Constraint.dual(final_constraint); + // // TODO + // } add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => From 3e9e158584127e3057998033f5820ef5eecc49ff Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 16 Dec 2023 20:12:46 -0500 Subject: [PATCH 098/141] Changed argument from ctx to mode in of_ap and of_ctr --- src/haz3lcore/dynamics/Constraint.re | 36 +++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 6d45857893..df220f6903 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -119,15 +119,39 @@ let rec ctr_of_nth_variant = (num_variants, nth): (t => t) => xi => InjR(xi |> ctr_of_nth_variant(num_variants - 1, nth - 1)); }; -let of_ap = (ctx, ctr: option(Constructor.t), arg: t): t => +let of_ap = (mode, ctr: option(Constructor.t), arg: t): t => switch (ctr) { | Some(name) => - switch (Ctx.lookup_ctr(ctx, name)) { - | None => Falsity // TODO: review - | Some({num_variants, nth, _}) => - arg |> ctr_of_nth_variant(num_variants, nth) + switch (mode) { + | Mode.Ana(Sum(map)) => + let num_variants = List.length(map); + let map_sorted = + List.sort( + ((ctr1, _), (ctr2, _)) => String.compare(ctr1, ctr2), + map, + ); + // available for OCaml 5.1 + // switch (List.find_index((ctr, _) => ctr == name, map_sorted)) { + // } + let (nth_opt, _) = + List.fold_left( + ((_, index), (ctr, _)): (option(int), int) => + (ctr == name ? Some(index) : None, index + 1), + (None, 0), + map_sorted, + ); + switch (nth_opt) { + | Some(nth) => arg |> ctr_of_nth_variant(num_variants, nth) + | None => Falsity // TODO: review + }; + | _ => Falsity // TODO: review } + // switch (Ctx.lookup_ctr(ctx, name)) { + // | None => Falsity // TODO: review + // | Some({num_variants, nth, _}) => + // arg |> ctr_of_nth_variant(num_variants, nth) + // } | None => Falsity // TODO: review }; -let of_ctr = (ctx, name) => of_ap(ctx, Some(name), Truth); +let of_ctr = (mode, name) => of_ap(mode, Some(name), Truth); From 4241f409e3b2ea8fa055dd147cb9be33d7267e6a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 16 Dec 2023 20:24:12 -0500 Subject: [PATCH 099/141] weak_head_normalized --- src/haz3lcore/dynamics/Constraint.re | 50 +++++++++++++++------------- src/haz3lcore/statics/Statics.re | 4 +-- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index df220f6903..9b6562b7ee 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -119,31 +119,35 @@ let rec ctr_of_nth_variant = (num_variants, nth): (t => t) => xi => InjR(xi |> ctr_of_nth_variant(num_variants - 1, nth - 1)); }; -let of_ap = (mode, ctr: option(Constructor.t), arg: t): t => +let of_ap = (ctx, mode, ctr: option(Constructor.t), arg: t): t => switch (ctr) { | Some(name) => switch (mode) { - | Mode.Ana(Sum(map)) => - let num_variants = List.length(map); - let map_sorted = - List.sort( - ((ctr1, _), (ctr2, _)) => String.compare(ctr1, ctr2), - map, - ); - // available for OCaml 5.1 - // switch (List.find_index((ctr, _) => ctr == name, map_sorted)) { - // } - let (nth_opt, _) = - List.fold_left( - ((_, index), (ctr, _)): (option(int), int) => - (ctr == name ? Some(index) : None, index + 1), - (None, 0), - map_sorted, - ); - switch (nth_opt) { - | Some(nth) => arg |> ctr_of_nth_variant(num_variants, nth) - | None => Falsity // TODO: review - }; + | Mode.Ana(ty) => + switch (Typ.weak_head_normalize(ctx, ty)) { + | Sum(map) => + let num_variants = List.length(map); + let map_sorted = + List.sort( + ((ctr1, _), (ctr2, _)) => String.compare(ctr1, ctr2), + map, + ); + // available for OCaml 5.1 + // switch (List.find_index((ctr, _) => ctr == name, map_sorted)) { + // } + let (nth_opt, _) = + List.fold_left( + ((_, index), (ctr, _)): (option(int), int) => + (ctr == name ? Some(index) : None, index + 1), + (None, 0), + map_sorted, + ); + switch (nth_opt) { + | Some(nth) => arg |> ctr_of_nth_variant(num_variants, nth) + | None => Falsity // TODO: review + }; + | _ => Falsity // TODO: review + } | _ => Falsity // TODO: review } // switch (Ctx.lookup_ctr(ctx, name)) { @@ -154,4 +158,4 @@ let of_ap = (mode, ctr: option(Constructor.t), arg: t): t => | None => Falsity // TODO: review }; -let of_ctr = (mode, name) => of_ap(mode, Some(name), Truth); +let of_ctr = (ctx, mode, name) => of_ap(ctx, mode, Some(name), Truth); diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index bb23968c0d..8eab3761f2 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -475,7 +475,7 @@ and upat_to_info_map = let (p, m) = go(~ctx, ~mode, p, m); add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); | Constructor(ctr) => - atomic(Self.of_ctr(ctx, ctr), Constraint.of_ctr(ctx, ctr)) + atomic(Self.of_ctr(ctx, ctr), Constraint.of_ctr(ctx, mode, ctr)) | Ap(fn, arg) => let ctr = UPat.ctr_name(fn); let fn_mode = Mode.of_ap(ctx, mode, ctr); @@ -485,7 +485,7 @@ and upat_to_info_map = add( ~self=Just(ty_out), ~ctx=arg.ctx, - ~constraint_=Constraint.of_ap(ctx, ctr, arg.constraint_), + ~constraint_=Constraint.of_ap(ctx, mode, ctr, arg.constraint_), m, ); | TypeAnn(p, ann) => From 63f3f397e2e4141208f01370da961bcf26c77e8b Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 16 Dec 2023 20:50:55 -0500 Subject: [PATCH 100/141] Bug fix --- src/haz3lcore/dynamics/Constraint.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 9b6562b7ee..f927cf3bbf 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -137,8 +137,8 @@ let of_ap = (ctx, mode, ctr: option(Constructor.t), arg: t): t => // } let (nth_opt, _) = List.fold_left( - ((_, index), (ctr, _)): (option(int), int) => - (ctr == name ? Some(index) : None, index + 1), + ((nth_opt, index), (ctr, _)): (option(int), int) => + (ctr == name ? Some(index) : nth_opt, index + 1), (None, 0), map_sorted, ); From a6b03f625d3cdc8ad5e86cf2de52be14d3bd1920 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 16 Dec 2023 20:54:46 -0500 Subject: [PATCH 101/141] Clean --- src/haz3lcore/statics/Statics.re | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 8eab3761f2..e7f21b1025 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -302,10 +302,6 @@ and uexp_to_info_map = let is_exhaustive = Incon.is_exhaustive(final_constraint); let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); - // if (!is_exhaustive) { - // let dual_constraint = Constraint.dual(final_constraint); - // // TODO - // } add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => From 8c308adddb541bbab2f359de788f60abb53c862e Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 16 Dec 2023 22:48:49 -0500 Subject: [PATCH 102/141] Added CtorMap.nth --- src/haz3lcore/dynamics/Constraint.re | 19 ++----------------- src/haz3lcore/statics/ConstructorMap.re | 9 +++++++++ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index f927cf3bbf..bfcad35dbd 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -126,23 +126,8 @@ let of_ap = (ctx, mode, ctr: option(Constructor.t), arg: t): t => | Mode.Ana(ty) => switch (Typ.weak_head_normalize(ctx, ty)) { | Sum(map) => - let num_variants = List.length(map); - let map_sorted = - List.sort( - ((ctr1, _), (ctr2, _)) => String.compare(ctr1, ctr2), - map, - ); - // available for OCaml 5.1 - // switch (List.find_index((ctr, _) => ctr == name, map_sorted)) { - // } - let (nth_opt, _) = - List.fold_left( - ((nth_opt, index), (ctr, _)): (option(int), int) => - (ctr == name ? Some(index) : nth_opt, index + 1), - (None, 0), - map_sorted, - ); - switch (nth_opt) { + let num_variants = ConstructorMap.cardinal(map); + switch (ConstructorMap.nth(name, map)) { | Some(nth) => arg |> ctr_of_nth_variant(num_variants, nth) | None => Falsity // TODO: review }; diff --git a/src/haz3lcore/statics/ConstructorMap.re b/src/haz3lcore/statics/ConstructorMap.re index c9ff0667dc..a3e1def0ee 100644 --- a/src/haz3lcore/statics/ConstructorMap.re +++ b/src/haz3lcore/statics/ConstructorMap.re @@ -99,3 +99,12 @@ let rec is_ground = (is_ground_value: 'a => bool, map: t('a)): bool => | [(_, head), ...tail] => is_ground_value(head) && tail |> is_ground(is_ground_value) }; + +let nth = (ctr: Constructor.t, map: t('a)): option(int) => { + // TODO: used List.find_index instead, which is available for OCaml 5.1 + let ctrs_sorted = map |> sort |> ctrs_of; + List.find_opt( + nth => List.nth(ctrs_sorted, nth) == ctr, + List.init(List.length(ctrs_sorted), Fun.id), + ); +}; From a69e23aa6fbf943507c9440c1a2363ac375e2c1d Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 16 Dec 2023 22:56:13 -0500 Subject: [PATCH 103/141] Clean --- src/haz3lcore/dynamics/Constraint.re | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index bfcad35dbd..8174f6e816 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -135,11 +135,6 @@ let of_ap = (ctx, mode, ctr: option(Constructor.t), arg: t): t => } | _ => Falsity // TODO: review } - // switch (Ctx.lookup_ctr(ctx, name)) { - // | None => Falsity // TODO: review - // | Some({num_variants, nth, _}) => - // arg |> ctr_of_nth_variant(num_variants, nth) - // } | None => Falsity // TODO: review }; From 4f510c1f484d8b1333d40af240dc999a4ef5b107 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Mon, 18 Dec 2023 12:58:55 -0500 Subject: [PATCH 104/141] Update ConstructorMap.re --- src/haz3lcore/statics/ConstructorMap.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/ConstructorMap.re b/src/haz3lcore/statics/ConstructorMap.re index a3e1def0ee..f871173adc 100644 --- a/src/haz3lcore/statics/ConstructorMap.re +++ b/src/haz3lcore/statics/ConstructorMap.re @@ -101,7 +101,7 @@ let rec is_ground = (is_ground_value: 'a => bool, map: t('a)): bool => }; let nth = (ctr: Constructor.t, map: t('a)): option(int) => { - // TODO: used List.find_index instead, which is available for OCaml 5.1 + // TODO: use List.find_index instead, which is available for OCaml 5.1 let ctrs_sorted = map |> sort |> ctrs_of; List.find_opt( nth => List.nth(ctrs_sorted, nth) == ctr, From 606abc4569caa7575535edbc59548ca8bdc3af6c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 23 Dec 2023 23:17:02 -0500 Subject: [PATCH 105/141] InexhaustiveMatch(option(error_exp)) => (option(error_common)) --- src/haz3lcore/dynamics/Elaborator.re | 4 +--- src/haz3lcore/statics/Info.re | 4 ++-- src/haz3lcore/statics/Statics.re | 4 ---- src/haz3lweb/view/CursorInspector.re | 2 +- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 2e7963a7de..4b7cf2aee5 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -269,9 +269,7 @@ let rec dhexp_of_uexp = let d = DHExp.Case(d_scrut, d_rules, 0); switch (err_status) { | InHole(Common(Inconsistent(Internal(_)))) - | InHole( - InexhaustiveMatch(Some(Common(Inconsistent(Internal(_))))), - ) => + | InHole(InexhaustiveMatch(Some(Inconsistent(Internal(_))))) => DHExp.InconsistentBranches(id, 0, d) | _ => ConsistentCase(d) }; diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index a68171bc52..68189a2a53 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -64,7 +64,7 @@ type error_common = [@deriving (show({with_path: false}), sexp, yojson)] type error_exp = | FreeVariable(Var.t) /* Unbound variable (not in typing context) */ - | InexhaustiveMatch(option(error_exp)) + | InexhaustiveMatch(option(error_common)) | Common(error_common); [@deriving (show({with_path: false}), sexp, yojson)] @@ -327,7 +327,7 @@ let rec status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => | (InexhaustiveMatch(self), _) => let additional_err = switch (status_exp(ctx, mode, self)) { - | InHole(Common(Inconsistent(Internal(_))) as inconsistent_err) => + | InHole(Common(Inconsistent(Internal(_)) as inconsistent_err)) => Some(inconsistent_err) | NotInHole(_) | InHole(Common(Inconsistent(Expectation(_) | WithArrow(_)))) => None /* Type checking should fail and these errors would be nullified */ diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 2a03c1e705..6b1536ed08 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -302,10 +302,6 @@ and uexp_to_info_map = let is_exhaustive = Incon.is_exhaustive(final_constraint); let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); - if (!is_exhaustive) { - let dual_constraint = Constraint.dual(final_constraint); - // TODO - } add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index cf181113fb..f0bb32b32c 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -166,7 +166,7 @@ let rec exp_view = (cls: Term.Cls.t, status: Info.status_exp) => | None => div_err([text("Case expression is inexhaustive")]) | Some(err) => div_err([ - exp_view(Exp(Match), InHole(err)), + exp_view(Exp(Match), InHole(Common(err))), text("; case expression is inexhaustive"), ]) } From 60d4aa0728052fb0a320e9bb6c0950284072cb61 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 23 Dec 2023 23:47:42 -0500 Subject: [PATCH 106/141] reformatted --- src/haz3lcore/statics/Info.re | 16 ++++++++++-- src/haz3lcore/statics/Statics.re | 43 +++++++++++++++++++------------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 7a9eea3929..84d8e21622 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -497,12 +497,24 @@ let derived_exp = /* Add derivable attributes for pattern terms */ let derived_pat = - (~upat: UPat.t, ~ctx, ~co_ctx, ~mode, ~ancestors, ~self, ~constraint_): pat => { + (~upat: UPat.t, ~ctx, ~co_ctx, ~mode, ~ancestors, ~self, ~constraint_) + : pat => { let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); let constraint_ = fixed_constraint_pat(ctx, mode, self, constraint_); - {cls, self, mode, ty, status, ctx, co_ctx, ancestors, term: upat, constraint_}; + { + cls, + self, + mode, + ty, + status, + ctx, + co_ctx, + ancestors, + term: upat, + constraint_, + }; }; /* Add derivable attributes for types */ diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 551bf9b32e..f1961a9f9d 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -305,7 +305,15 @@ and uexp_to_info_map = let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); let (ps', m) = - map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, ~mode=Mode.Ana(scrut.ty)), ps, m); + map_m( + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=Mode.Ana(scrut.ty), + ), + ps, + m, + ); let p_constraints = List.map(Info.pat_constraint, ps'); let p_ctxs = List.map(Info.pat_ctx, ps'); let (es, m) = @@ -316,9 +324,24 @@ and uexp_to_info_map = es, p_ctxs, ); + let e_co_ctxs = + List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); + /* Add co-ctxs to patterns */ + let (_, m) = + map_m( + ((p, co_ctx)) => + go_pat( + ~is_synswitch=false, + ~co_ctx, + ~mode=Mode.Ana(scrut.ty), + p, + ), + List.combine(ps, e_co_ctxs), + m, + ); ( es, - List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)), + e_co_ctxs, branch_ids, Constraint.or_constraints(p_constraints), m, @@ -327,26 +350,12 @@ and uexp_to_info_map = let (es, e_co_ctxs, branch_ids, final_constraint, m) = rules_to_info_map(rules, m); let e_tys = List.map(Info.exp_ty, es); - let e_co_ctxs = - List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - /* Add co-ctxs to patterns */ - let (_, m) = - map_m( - ((p, co_ctx)) => - go_pat(~is_synswitch=false, ~co_ctx, ~mode=Mode.Ana(scrut.ty), p), - List.combine(ps, e_co_ctxs), - m, - ); let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); let is_exhaustive = Incon.is_exhaustive(final_constraint); let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); - add'( - ~self, - ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), - m, - ); + add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => let m = utpat_to_info_map(~ctx, ~ancestors, typat, m) |> snd; switch (typat.term) { From c81ee313fc8190086aa6058124e26eb5666b8247 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Mon, 25 Dec 2023 09:20:34 -0500 Subject: [PATCH 107/141] Update Statics.re --- src/haz3lcore/statics/Statics.re | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 0febe2ceaf..3a92c49722 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -308,7 +308,13 @@ and uexp_to_info_map = List.fold_left( ((ps', m, acc_constraint), p) => { let (p, m) = - go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, ~mode=Mode.Ana(scrut.ty), p, m); + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=Mode.Ana(scrut.ty), + p, + m, + ); let p_constraint = Info.pat_constraint(p); if (!Incon.is_redundant(p_constraint, acc_constraint)) { (ps' @ [p], m, Constraint.Or(p_constraint, acc_constraint)); @@ -317,6 +323,7 @@ and uexp_to_info_map = Info.derived_pat( ~upat=p.term, ~ctx=p.ctx, + ~co_ctx=p.co_ctx, ~mode=p.mode, ~ancestors=p.ancestors, ~self=Redundant(p.self), @@ -359,13 +366,7 @@ and uexp_to_info_map = List.combine(ps, e_co_ctxs), m, ); - ( - es, - e_co_ctxs, - branch_ids, - final_constraint, - m, - ); + (es, e_co_ctxs, branch_ids, final_constraint, m); }; let (es, e_co_ctxs, branch_ids, final_constraint, m) = rules_to_info_map(rules, m); From bd3a3864b278a917ab00b1e2fb5073e9bec3eb57 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 6 Jan 2024 02:21:15 -0500 Subject: [PATCH 108/141] Switch nth's argument position --- src/haz3lcore/dynamics/Constraint.re | 2 +- src/haz3lcore/statics/ConstructorMap.re | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 8174f6e816..da5ae548df 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -127,7 +127,7 @@ let of_ap = (ctx, mode, ctr: option(Constructor.t), arg: t): t => switch (Typ.weak_head_normalize(ctx, ty)) { | Sum(map) => let num_variants = ConstructorMap.cardinal(map); - switch (ConstructorMap.nth(name, map)) { + switch (ConstructorMap.nth(map, name)) { | Some(nth) => arg |> ctr_of_nth_variant(num_variants, nth) | None => Falsity // TODO: review }; diff --git a/src/haz3lcore/statics/ConstructorMap.re b/src/haz3lcore/statics/ConstructorMap.re index f871173adc..a350d16d92 100644 --- a/src/haz3lcore/statics/ConstructorMap.re +++ b/src/haz3lcore/statics/ConstructorMap.re @@ -100,7 +100,7 @@ let rec is_ground = (is_ground_value: 'a => bool, map: t('a)): bool => is_ground_value(head) && tail |> is_ground(is_ground_value) }; -let nth = (ctr: Constructor.t, map: t('a)): option(int) => { +let nth = (map: t('a), ctr: Constructor.t): option(int) => { // TODO: use List.find_index instead, which is available for OCaml 5.1 let ctrs_sorted = map |> sort |> ctrs_of; List.find_opt( From dca454f60baa6ef3db6b095b902ac7e190ce9384 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 6 Jan 2024 03:13:50 -0500 Subject: [PATCH 109/141] Constraint emission for synthesized Ap pattern --- src/haz3lcore/dynamics/Constraint.re | 32 +++++++++++++++++++--------- src/haz3lcore/statics/Statics.re | 6 ++++-- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index da5ae548df..a56f435e55 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -109,7 +109,6 @@ let rec or_constraints = (lst: list(t)): t => | [xi, ...xis] => Or(xi, or_constraints(xis)) }; -// Temporary name let rec ctr_of_nth_variant = (num_variants, nth): (t => t) => if (num_variants == 1) { Fun.id; @@ -119,23 +118,36 @@ let rec ctr_of_nth_variant = (num_variants, nth): (t => t) => xi => InjR(xi |> ctr_of_nth_variant(num_variants - 1, nth - 1)); }; -let of_ap = (ctx, mode, ctr: option(Constructor.t), arg: t): t => +let of_ap = (ctx, mode, ctr: option(Constructor.t), arg: t, syn_ty): t => switch (ctr) { | Some(name) => - switch (mode) { - | Mode.Ana(ty) => + let ty = + switch (mode) { + | Mode.Ana(ty) => Some(ty) + | Syn => syn_ty + | _ => None + }; + switch (ty) { + | Some(ty) => switch (Typ.weak_head_normalize(ctx, ty)) { | Sum(map) => let num_variants = ConstructorMap.cardinal(map); switch (ConstructorMap.nth(map, name)) { | Some(nth) => arg |> ctr_of_nth_variant(num_variants, nth) - | None => Falsity // TODO: review + | None => Falsity }; - | _ => Falsity // TODO: review + | _ => Falsity } - | _ => Falsity // TODO: review - } - | None => Falsity // TODO: review + | None => Falsity + }; + | None => Falsity }; -let of_ctr = (ctx, mode, name) => of_ap(ctx, mode, Some(name), Truth); +let of_ctr = (ctx, mode, name, self) => { + let syn_ty = + switch (self) { + | Self.IsConstructor({syn_ty, _}) => syn_ty + | _ => assert(false) // impossible + }; + of_ap(ctx, mode, Some(name), Truth, syn_ty); +}; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 6d7aac4169..e927649956 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -525,7 +525,8 @@ and upat_to_info_map = let (p, m) = go(~ctx, ~mode, p, m); add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); | Constructor(ctr) => - atomic(Self.of_ctr(ctx, ctr), Constraint.of_ctr(ctx, mode, ctr)) + let self = Self.of_ctr(ctx, ctr); + atomic(self, Constraint.of_ctr(ctx, mode, ctr, self)); | Ap(fn, arg) => let ctr = UPat.ctr_name(fn); let fn_mode = Mode.of_ap(ctx, mode, ctr); @@ -535,7 +536,8 @@ and upat_to_info_map = add( ~self=Just(ty_out), ~ctx=arg.ctx, - ~constraint_=Constraint.of_ap(ctx, mode, ctr, arg.constraint_), + ~constraint_= + Constraint.of_ap(ctx, mode, ctr, arg.constraint_, Some(ty_out)), m, ); | TypeAnn(p, ann) => From c8c00e6565b8c0bd3169a064b9c9e17ba0db435a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 16 Jan 2024 09:51:23 -0500 Subject: [PATCH 110/141] Fixed inf recursion bug --- src/haz3lcore/statics/Info.re | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 84d8e21622..296fe47976 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -475,9 +475,9 @@ let fixed_typ_pat = (ctx, mode: Mode.t, self: Self.pat): Typ.t => let fixed_constraint_pat = (ctx, mode: Mode.t, self: Self.pat, constraint_: Constraint.t) : Constraint.t => - switch (status_pat(ctx, mode, self)) { - | InHole(_) => Constraint.Hole - | NotInHole(_) => constraint_ + switch (fixed_typ_pat(ctx, mode, self)) { + | Unknown(_) => Constraint.Hole + | _ => constraint_ }; let fixed_typ_exp = (ctx, mode: Mode.t, self: Self.exp): Typ.t => From 42266ceb1e4d6959fafbb5da72d160cc6294dc3b Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Thu, 18 Jan 2024 18:22:17 -0500 Subject: [PATCH 111/141] Fixed overwritten-map bug --- src/haz3lcore/statics/Statics.re | 57 +++++++++++++++----------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 3a92c49722..d9be5dc2ff 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -304,20 +304,42 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); - let (ps', m, final_constraint) = + let (ps', m) = + map_m( + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=Mode.Ana(scrut.ty), + ), + ps, + m, + ); + let p_ctxs = List.map(Info.pat_ctx, ps'); + let (es, m) = + List.fold_left2( + ((es, m), e, ctx) => + go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), + ([], m), + es, + p_ctxs, + ); + let e_co_ctxs = + List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); + /* Add co-ctxs to patterns */ + let (m, final_constraint) = List.fold_left( - ((ps', m, acc_constraint), p) => { + ((m, acc_constraint), (p, co_ctx)) => { let (p, m) = go_pat( ~is_synswitch=false, - ~co_ctx=CoCtx.empty, + ~co_ctx, ~mode=Mode.Ana(scrut.ty), p, m, ); let p_constraint = Info.pat_constraint(p); if (!Incon.is_redundant(p_constraint, acc_constraint)) { - (ps' @ [p], m, Constraint.Or(p_constraint, acc_constraint)); + (m, Constraint.Or(p_constraint, acc_constraint)); } else { let info = Info.derived_pat( @@ -332,39 +354,14 @@ and uexp_to_info_map = ~constraint_=p_constraint, ); ( - ps' @ [info], // Override the info for the single upat add_info(p.term.ids, InfoPat(info), m), acc_constraint // Redundant patterns are ignored ); }; }, - ([], m, Constraint.Falsity), - ps, - ); - let p_ctxs = List.map(Info.pat_ctx, ps'); - let (es, m) = - List.fold_left2( - ((es, m), e, ctx) => - go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), - ([], m), - es, - p_ctxs, - ); - let e_co_ctxs = - List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - /* Add co-ctxs to patterns */ - let (_, m) = - map_m( - ((p, co_ctx)) => - go_pat( - ~is_synswitch=false, - ~co_ctx, - ~mode=Mode.Ana(scrut.ty), - p, - ), + (m, Constraint.Falsity), List.combine(ps, e_co_ctxs), - m, ); (es, e_co_ctxs, branch_ids, final_constraint, m); }; From 493cdc7149280e69e99e07e0904b7077500f4a53 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 13 Feb 2024 10:07:16 -0500 Subject: [PATCH 112/141] Resolve merge conflicts --- src/haz3lweb/view/Deco.re | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/src/haz3lweb/view/Deco.re b/src/haz3lweb/view/Deco.re index 3c79f6376f..e5cfacc04d 100644 --- a/src/haz3lweb/view/Deco.re +++ b/src/haz3lweb/view/Deco.re @@ -277,36 +277,6 @@ module Deco = }; // faster infomap traversal - let err_holes = (_z: Zipper.t) => { - let is_rep = (id: Id.t) => - switch (Id.Map.find_opt(id, M.terms)) { - | None => false - | Some(term) => id == Term.rep_id(term) - }; - Id.Map.fold( - (id, info, acc) => - /* Because of artefacts in Maketerm ID handling, - * there are be situations where ids appear in the - * info_map which do not occur in term_ranges. These - * ids should be purely duplicative, so skipping them - * when iterating over the info_map should have no - * effect, beyond supressing the resulting Not_found exs */ - switch (Id.Map.find_opt(id, M.term_ranges)) { - /* Without filtering out non-rep ids, there will be - * multiple error holes wrapping around a case expression - * or a list literal that has at least one comma, since the - * rules of case expressions and the inner commas of list - * literals are technically different forms */ - | Some(_) when is_rep(id) && Info.is_error(info) => [ - term_highlight(~clss=["err-hole"], id), - ...acc, - ] - | _ => acc - }, - M.info_map, - [], - ); - }; let err_holes = (_z: Zipper.t) => List.map(term_highlight(~clss=["err-hole"]), M.error_ids); From 129fcf25e2152fcc579bafe8ff9b6499738086f4 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 13 Feb 2024 11:00:57 -0500 Subject: [PATCH 113/141] Generalize frontend, part I --- src/haz3lweb/view/CursorInspector.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 2b8ec57578..b04c9cf1e8 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -175,7 +175,7 @@ let rec exp_view = (cls: Term.Cls.t, status: Info.status_exp) => | None => div_err([text("Case expression is inexhaustive")]) | Some(err) => div_err([ - exp_view(Exp(Match), InHole(Common(err))), + exp_view(cls, InHole(Common(err))), text("; case expression is inexhaustive"), ]) } From 51dec0320a3c29cc0a2b70a2effe3dd43c849fac Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 13 Feb 2024 13:43:26 -0500 Subject: [PATCH 114/141] Inexhaustive self for functions --- src/haz3lcore/statics/Statics.re | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 9217cf4f86..918882a1ce 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -306,11 +306,12 @@ and uexp_to_info_map = /* add co_ctx to pattern */ let (p, m) = go_pat(~is_synswitch=false, ~co_ctx=e.co_ctx, ~mode=mode_pat, p, m); - add( - ~self=Just(Arrow(p.ty, e.ty)), - ~co_ctx=CoCtx.mk(ctx, p.ctx, e.co_ctx), - m, - ); + // TODO: factor out code + let unwrapped_self: Self.exp = Common(Just(Arrow(p.ty, e.ty))); + let is_exhaustive = p |> Info.pat_constraint |> Incon.is_exhaustive; + let self = + is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); + add'(~self, ~co_ctx=CoCtx.mk(ctx, p.ctx, e.co_ctx), m); | Let(p, def, body) => let (p_syn, _) = go_pat(~is_synswitch=true, ~co_ctx=CoCtx.empty, ~mode=Syn, p, m); From c47bc6610559e3cf148d1f0ed253e36ebef185ee Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 13 Feb 2024 17:46:04 -0500 Subject: [PATCH 115/141] Inexhaustive self for let expressions --- src/haz3lcore/statics/Statics.re | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 918882a1ce..17bba316e8 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -336,8 +336,13 @@ and uexp_to_info_map = p, m, ); - add( - ~self=Just(body.ty), + // TODO: factor out code + let unwrapped_self: Self.exp = Common(Just(body.ty)); + let is_exhaustive = p_ana |> Info.pat_constraint |> Incon.is_exhaustive; + let self = + is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); + add'( + ~self, ~co_ctx= CoCtx.union([def.co_ctx, CoCtx.mk(ctx, p_ana.ctx, body.co_ctx)]), m, From d35b283d70ddcdcd8b0abb9aea37c4808460e305 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 13 Feb 2024 18:15:40 -0500 Subject: [PATCH 116/141] Fixed TypeAnn escape checking bug --- src/haz3lcore/statics/Info.re | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index fe40e0456d..c7462ccac5 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -516,11 +516,21 @@ let fixed_typ_pat = (ctx, mode: Mode.t, self: Self.pat): Typ.t => { }; let fixed_constraint_pat = - (ctx, mode: Mode.t, self: Self.pat, constraint_: Constraint.t) + ( + upat: UPat.t, + ctx, + mode: Mode.t, + self: Self.pat, + constraint_: Constraint.t, + ) : Constraint.t => - switch (fixed_typ_pat(ctx, mode, self)) { - | Unknown(_) => Constraint.Hole - | _ => constraint_ + switch (upat.term) { + | TypeAnn(_) => constraint_ + | _ => + switch (fixed_typ_pat(ctx, mode, self)) { + | Unknown(_) => Constraint.Hole + | _ => constraint_ + } }; let fixed_typ_exp = (ctx, mode: Mode.t, self: Self.exp): Typ.t => @@ -545,7 +555,7 @@ let derived_pat = let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); - let constraint_ = fixed_constraint_pat(ctx, mode, self, constraint_); + let constraint_ = fixed_constraint_pat(upat, ctx, mode, self, constraint_); { cls, self, From a53f02d2eac8e6561868a2bbadbeb2e8dc25a1a8 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 13 Feb 2024 18:37:40 -0500 Subject: [PATCH 117/141] Update CursorInspector.re --- src/haz3lweb/view/CursorInspector.re | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 6070b73bf0..af2d14918e 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -171,14 +171,16 @@ let rec exp_view = (cls: Term.Cls.t, status: Info.status_exp) => | InHole(FreeVariable(name)) => div_err([code_err(name), text("not found")]) | InHole(InexhaustiveMatch(additional_err)) => + let cls_str = Term.Cls.show(cls); switch (additional_err) { - | None => div_err([text("Case expression is inexhaustive")]) + | None => div_err([text(cls_str ++ " is inexhaustive")]) | Some(err) => + let cls_str = String.uncapitalize_ascii(cls_str); div_err([ exp_view(cls, InHole(Common(err))), - text("; case expression is inexhaustive"), - ]) - } + text("; " ++ cls_str ++ " is inexhaustive"), + ]); + }; | InHole(Common(error)) => div_err(common_err_view(cls, error)) | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) }; From e37b742ad095f7d7d2ed00fa4ffdb2ae42688aea Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 14 Apr 2024 11:07:10 -0400 Subject: [PATCH 118/141] Resolve merge issue --- src/haz3lcore/statics/Info.re | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 84de41d77e..8f3d75079c 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -400,7 +400,10 @@ let rec status_exp = (ctx: Ctx.t, mode: Mode.t, self: Self.exp): status_exp => | NotInHole(_) | InHole(Common(Inconsistent(Expectation(_) | WithArrow(_)))) => None /* Type checking should fail and these errors would be nullified */ | InHole(Common(NoType(_))) - | InHole(FreeVariable(_) | InexhaustiveMatch(_)) => + | InHole( + FreeVariable(_) | InexhaustiveMatch(_) | UnusedDeferral | + BadPartialAp(_), + ) => failwith("InHole(InexhaustiveMatch(impossible_err))") }; InHole(InexhaustiveMatch(additional_err)); From a511ce98807f45d388cee059df51a47682f06f49 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 14 Apr 2024 12:50:56 -0400 Subject: [PATCH 119/141] add constraint_ty --- src/haz3lcore/statics/Info.re | 19 +++++++++++++++++-- src/haz3lcore/statics/Statics.re | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 8f3d75079c..43acfb0e10 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -561,12 +561,27 @@ let derived_exp = /* Add derivable attributes for pattern terms */ let derived_pat = - (~upat: UPat.t, ~ctx, ~co_ctx, ~mode, ~ancestors, ~self, ~constraint_) + ( + ~upat: UPat.t, + ~ctx, + ~co_ctx, + ~mode, + ~ancestors, + ~self, + ~constraint_, + ~constraint_ty, + ) : pat => { let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); - let constraint_ = fixed_constraint_pat(upat, ctx, mode, self, constraint_); + let constraint_mode = + switch (constraint_ty) { + | None => mode + | Some(ty) => Ana(ty) + }; + let constraint_ = + fixed_constraint_pat(upat, ctx, constraint_mode, self, constraint_); { cls, self, diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 414e583287..ee4535f717 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -419,6 +419,28 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); + // let rec get_scrut_ty = ps => { + // switch (ps) { + // | [] => scrut.ty + // | [p, ...ps] => + // let (p', _m) = + // go_pat( + // ~is_synswitch=false, + // ~co_ctx=CoCtx.empty, + // p, + // m, + // ); + // switch (Info.pat_ty(p')) { + // | Unknown(_) => get_scrut_ty(ps) + // | ty => ty + // }; + // }; + // }; + // let scrut_ty = + // switch (scrut.ty) { + // | Unknown(_) => get_scrut_ty(ps) + // | _ => scrut.ty + // }; let (ps', m) = map_m( go_pat( @@ -545,6 +567,7 @@ and upat_to_info_map = ~co_ctx, ~ancestors: Info.ancestors, ~mode: Mode.t=Mode.Syn, + ~constraint_ty: option(Typ.t)=None, {ids, term} as upat: UPat.t, m: Map.t, ) @@ -559,6 +582,7 @@ and upat_to_info_map = ~ancestors, ~self=Common(self), ~constraint_, + ~constraint_ty, ); (info, add_info(ids, InfoPat(info), m)); }; From 405bfcc24864f3c5e6713cf6db2f0450b1ce315b Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 14 Apr 2024 12:54:55 -0400 Subject: [PATCH 120/141] implement constraint_ty --- src/haz3lcore/statics/Statics.re | 40 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index ee4535f717..0bfac2a762 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -419,28 +419,23 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); - // let rec get_scrut_ty = ps => { - // switch (ps) { - // | [] => scrut.ty - // | [p, ...ps] => - // let (p', _m) = - // go_pat( - // ~is_synswitch=false, - // ~co_ctx=CoCtx.empty, - // p, - // m, - // ); - // switch (Info.pat_ty(p')) { - // | Unknown(_) => get_scrut_ty(ps) - // | ty => ty - // }; - // }; - // }; - // let scrut_ty = - // switch (scrut.ty) { - // | Unknown(_) => get_scrut_ty(ps) - // | _ => scrut.ty - // }; + let rec get_constraint_ty = ps => { + switch (ps) { + | [] => scrut.ty + | [p, ...ps] => + let (p', _m) = + go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, p, m); + switch (Info.pat_ty(p')) { + | Unknown(_) => get_constraint_ty(ps) + | ty => ty + }; + }; + }; + let constraint_ty = + switch (scrut.ty) { + | Unknown(_) => get_constraint_ty(ps) + | _ => scrut.ty + }; let (ps', m) = map_m( go_pat( @@ -471,6 +466,7 @@ and uexp_to_info_map = ~is_synswitch=false, ~co_ctx, ~mode=Mode.Ana(scrut.ty), + ~constraint_ty=Some(constraint_ty), p, m, ); From b3510ee982899b6d4b14f2b3ebd0cfd74ea6c09c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 14 Apr 2024 15:27:42 -0400 Subject: [PATCH 121/141] add Mode.of_constraint --- src/haz3lcore/statics/Info.re | 6 +----- src/haz3lcore/statics/Mode.re | 6 ++++++ src/haz3lcore/statics/Statics.re | 21 +++++++++++++-------- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 43acfb0e10..b71de65ccf 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -575,11 +575,7 @@ let derived_pat = let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); - let constraint_mode = - switch (constraint_ty) { - | None => mode - | Some(ty) => Ana(ty) - }; + let constraint_mode = Mode.of_constraint(mode, constraint_ty); let constraint_ = fixed_constraint_pat(upat, ctx, constraint_mode, self, constraint_); { diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index f1e3550091..c0d2f65429 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -127,3 +127,9 @@ let of_deferred_ap_args = (length: int, ty_ins: list(Typ.t)): list(t) => ? ty_ins : List.init(length, _ => Typ.Unknown(Internal)) ) |> List.map(ty => Ana(ty)); + +let of_constraint = (mode: t, constraint_ty: option(Typ.t)): t => + switch (constraint_ty) { + | None => mode + | Some(ty) => Ana(ty) + }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 0bfac2a762..c161b55086 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -485,6 +485,7 @@ and uexp_to_info_map = // Mark patterns as redundant at the top level // because redundancy doesn't make sense in a smaller context ~constraint_=p_constraint, + ~constraint_ty=Some(constraint_ty), ); ( // Override the info for the single upat @@ -679,20 +680,24 @@ and upat_to_info_map = add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); | Constructor(ctr) => let self = Self.of_ctr(ctx, ctr); - atomic(self, Constraint.of_ctr(ctx, mode, ctr, self)); + let constraint_mode = Mode.of_constraint(mode, constraint_ty); + atomic(self, Constraint.of_ctr(ctx, constraint_mode, ctr, self)); | Ap(fn, arg) => let ctr = UPat.ctr_name(fn); let fn_mode = Mode.of_ap(ctx, mode, ctr); let (fn, m) = go(~ctx, ~mode=fn_mode, fn, m); let (ty_in, ty_out) = Typ.matched_arrow(ctx, fn.ty); let (arg, m) = go(~ctx, ~mode=Ana(ty_in), arg, m); - add( - ~self=Just(ty_out), - ~ctx=arg.ctx, - ~constraint_= - Constraint.of_ap(ctx, mode, ctr, arg.constraint_, Some(ty_out)), - m, - ); + let constraint_mode = Mode.of_constraint(mode, constraint_ty); + let constraint_ = + Constraint.of_ap( + ctx, + constraint_mode, + ctr, + arg.constraint_, + Some(ty_out), + ); + add(~self=Just(ty_out), ~ctx=arg.ctx, ~constraint_, m); | TypeAnn(p, ann) => let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); let (p, m) = go(~ctx, ~mode=Ana(ann.ty), p, m); From 6365947779ef339f45357d2a32923b748d0ccfdc Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 14 Apr 2024 16:04:26 -0400 Subject: [PATCH 122/141] upstream constraint_ty in Statics.re --- src/haz3lcore/statics/Statics.re | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index c161b55086..9073342576 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -433,8 +433,8 @@ and uexp_to_info_map = }; let constraint_ty = switch (scrut.ty) { - | Unknown(_) => get_constraint_ty(ps) - | _ => scrut.ty + | Unknown(_) => Some(get_constraint_ty(ps)) + | _ => None }; let (ps', m) = map_m( @@ -466,7 +466,7 @@ and uexp_to_info_map = ~is_synswitch=false, ~co_ctx, ~mode=Mode.Ana(scrut.ty), - ~constraint_ty=Some(constraint_ty), + ~constraint_ty, p, m, ); @@ -485,7 +485,7 @@ and uexp_to_info_map = // Mark patterns as redundant at the top level // because redundancy doesn't make sense in a smaller context ~constraint_=p_constraint, - ~constraint_ty=Some(constraint_ty), + ~constraint_ty, ); ( // Override the info for the single upat From f1ce59dae9014f50d95230b90ed770c7b08c97a7 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 13:36:19 -0400 Subject: [PATCH 123/141] Revert "upstream constraint_ty in Statics.re" This reverts commit 6365947779ef339f45357d2a32923b748d0ccfdc. --- src/haz3lcore/statics/Statics.re | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 9073342576..c161b55086 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -433,8 +433,8 @@ and uexp_to_info_map = }; let constraint_ty = switch (scrut.ty) { - | Unknown(_) => Some(get_constraint_ty(ps)) - | _ => None + | Unknown(_) => get_constraint_ty(ps) + | _ => scrut.ty }; let (ps', m) = map_m( @@ -466,7 +466,7 @@ and uexp_to_info_map = ~is_synswitch=false, ~co_ctx, ~mode=Mode.Ana(scrut.ty), - ~constraint_ty, + ~constraint_ty=Some(constraint_ty), p, m, ); @@ -485,7 +485,7 @@ and uexp_to_info_map = // Mark patterns as redundant at the top level // because redundancy doesn't make sense in a smaller context ~constraint_=p_constraint, - ~constraint_ty, + ~constraint_ty=Some(constraint_ty), ); ( // Override the info for the single upat From 1ba9e2e845eec81083d591764cb9570fc1b0598c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 13:36:23 -0400 Subject: [PATCH 124/141] Revert "add Mode.of_constraint" This reverts commit b3510ee982899b6d4b14f2b3ebd0cfd74ea6c09c. --- src/haz3lcore/statics/Info.re | 6 +++++- src/haz3lcore/statics/Mode.re | 6 ------ src/haz3lcore/statics/Statics.re | 21 ++++++++------------- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index b71de65ccf..43acfb0e10 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -575,7 +575,11 @@ let derived_pat = let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); - let constraint_mode = Mode.of_constraint(mode, constraint_ty); + let constraint_mode = + switch (constraint_ty) { + | None => mode + | Some(ty) => Ana(ty) + }; let constraint_ = fixed_constraint_pat(upat, ctx, constraint_mode, self, constraint_); { diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index c0d2f65429..f1e3550091 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -127,9 +127,3 @@ let of_deferred_ap_args = (length: int, ty_ins: list(Typ.t)): list(t) => ? ty_ins : List.init(length, _ => Typ.Unknown(Internal)) ) |> List.map(ty => Ana(ty)); - -let of_constraint = (mode: t, constraint_ty: option(Typ.t)): t => - switch (constraint_ty) { - | None => mode - | Some(ty) => Ana(ty) - }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index c161b55086..0bfac2a762 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -485,7 +485,6 @@ and uexp_to_info_map = // Mark patterns as redundant at the top level // because redundancy doesn't make sense in a smaller context ~constraint_=p_constraint, - ~constraint_ty=Some(constraint_ty), ); ( // Override the info for the single upat @@ -680,24 +679,20 @@ and upat_to_info_map = add(~self=Just(p.ty), ~ctx=p.ctx, ~constraint_=p.constraint_, m); | Constructor(ctr) => let self = Self.of_ctr(ctx, ctr); - let constraint_mode = Mode.of_constraint(mode, constraint_ty); - atomic(self, Constraint.of_ctr(ctx, constraint_mode, ctr, self)); + atomic(self, Constraint.of_ctr(ctx, mode, ctr, self)); | Ap(fn, arg) => let ctr = UPat.ctr_name(fn); let fn_mode = Mode.of_ap(ctx, mode, ctr); let (fn, m) = go(~ctx, ~mode=fn_mode, fn, m); let (ty_in, ty_out) = Typ.matched_arrow(ctx, fn.ty); let (arg, m) = go(~ctx, ~mode=Ana(ty_in), arg, m); - let constraint_mode = Mode.of_constraint(mode, constraint_ty); - let constraint_ = - Constraint.of_ap( - ctx, - constraint_mode, - ctr, - arg.constraint_, - Some(ty_out), - ); - add(~self=Just(ty_out), ~ctx=arg.ctx, ~constraint_, m); + add( + ~self=Just(ty_out), + ~ctx=arg.ctx, + ~constraint_= + Constraint.of_ap(ctx, mode, ctr, arg.constraint_, Some(ty_out)), + m, + ); | TypeAnn(p, ann) => let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); let (p, m) = go(~ctx, ~mode=Ana(ann.ty), p, m); From fd86321a50e12449039b2489ac9698e38573265e Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 13:36:26 -0400 Subject: [PATCH 125/141] Revert "implement constraint_ty" This reverts commit 405bfcc24864f3c5e6713cf6db2f0450b1ce315b. --- src/haz3lcore/statics/Statics.re | 40 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 0bfac2a762..ee4535f717 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -419,23 +419,28 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); - let rec get_constraint_ty = ps => { - switch (ps) { - | [] => scrut.ty - | [p, ...ps] => - let (p', _m) = - go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, p, m); - switch (Info.pat_ty(p')) { - | Unknown(_) => get_constraint_ty(ps) - | ty => ty - }; - }; - }; - let constraint_ty = - switch (scrut.ty) { - | Unknown(_) => get_constraint_ty(ps) - | _ => scrut.ty - }; + // let rec get_scrut_ty = ps => { + // switch (ps) { + // | [] => scrut.ty + // | [p, ...ps] => + // let (p', _m) = + // go_pat( + // ~is_synswitch=false, + // ~co_ctx=CoCtx.empty, + // p, + // m, + // ); + // switch (Info.pat_ty(p')) { + // | Unknown(_) => get_scrut_ty(ps) + // | ty => ty + // }; + // }; + // }; + // let scrut_ty = + // switch (scrut.ty) { + // | Unknown(_) => get_scrut_ty(ps) + // | _ => scrut.ty + // }; let (ps', m) = map_m( go_pat( @@ -466,7 +471,6 @@ and uexp_to_info_map = ~is_synswitch=false, ~co_ctx, ~mode=Mode.Ana(scrut.ty), - ~constraint_ty=Some(constraint_ty), p, m, ); From 17f55a4dc706ed06e51b351568055bcd25b08475 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 13:36:30 -0400 Subject: [PATCH 126/141] Revert "add constraint_ty" This reverts commit a511ce98807f45d388cee059df51a47682f06f49. --- src/haz3lcore/statics/Info.re | 19 ++----------------- src/haz3lcore/statics/Statics.re | 24 ------------------------ 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 43acfb0e10..8f3d75079c 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -561,27 +561,12 @@ let derived_exp = /* Add derivable attributes for pattern terms */ let derived_pat = - ( - ~upat: UPat.t, - ~ctx, - ~co_ctx, - ~mode, - ~ancestors, - ~self, - ~constraint_, - ~constraint_ty, - ) + (~upat: UPat.t, ~ctx, ~co_ctx, ~mode, ~ancestors, ~self, ~constraint_) : pat => { let cls = Cls.Pat(UPat.cls_of_term(upat.term)); let status = status_pat(ctx, mode, self); let ty = fixed_typ_pat(ctx, mode, self); - let constraint_mode = - switch (constraint_ty) { - | None => mode - | Some(ty) => Ana(ty) - }; - let constraint_ = - fixed_constraint_pat(upat, ctx, constraint_mode, self, constraint_); + let constraint_ = fixed_constraint_pat(upat, ctx, mode, self, constraint_); { cls, self, diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index ee4535f717..414e583287 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -419,28 +419,6 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); - // let rec get_scrut_ty = ps => { - // switch (ps) { - // | [] => scrut.ty - // | [p, ...ps] => - // let (p', _m) = - // go_pat( - // ~is_synswitch=false, - // ~co_ctx=CoCtx.empty, - // p, - // m, - // ); - // switch (Info.pat_ty(p')) { - // | Unknown(_) => get_scrut_ty(ps) - // | ty => ty - // }; - // }; - // }; - // let scrut_ty = - // switch (scrut.ty) { - // | Unknown(_) => get_scrut_ty(ps) - // | _ => scrut.ty - // }; let (ps', m) = map_m( go_pat( @@ -567,7 +545,6 @@ and upat_to_info_map = ~co_ctx, ~ancestors: Info.ancestors, ~mode: Mode.t=Mode.Syn, - ~constraint_ty: option(Typ.t)=None, {ids, term} as upat: UPat.t, m: Map.t, ) @@ -582,7 +559,6 @@ and upat_to_info_map = ~ancestors, ~self=Common(self), ~constraint_, - ~constraint_ty, ); (info, add_info(ids, InfoPat(info), m)); }; From b17a16523a5e25d2175078c860ae723d4d60706a Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 14:52:54 -0400 Subject: [PATCH 127/141] scrut.ty => scrut_ty --- src/haz3lcore/statics/Statics.re | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 414e583287..0a3ecb3f81 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -419,12 +419,28 @@ and uexp_to_info_map = let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); + // switch (scrut.ty) { + // | Unknown(_) => + // let (ps', _m) = + // map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty), ps, m); + // print_endline( + // Typ.join_all( + // ~empty=Unknown(Internal), + // ctx, + // List.map(Info.pat_ty, ps'), + // ) + // == None + // ? "some" : "none", + // ); + // | _ => () + // }; + // switch () let (ps', m) = map_m( go_pat( ~is_synswitch=false, ~co_ctx=CoCtx.empty, - ~mode=Mode.Ana(scrut.ty), + ~mode=Mode.Ana(scrut_ty), ), ps, m, @@ -448,7 +464,7 @@ and uexp_to_info_map = go_pat( ~is_synswitch=false, ~co_ctx, - ~mode=Mode.Ana(scrut.ty), + ~mode=Mode.Ana(scrut_ty), p, m, ); From 368785c9ae83715ce15ffea9978472da0b9d334d Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 15:09:47 -0400 Subject: [PATCH 128/141] changed rules_to_info_map signature --- src/haz3lcore/statics/Statics.re | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 0a3ecb3f81..2ba107adfd 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -416,9 +416,9 @@ and uexp_to_info_map = ); | Match(scrut, rules) => let (scrut, m) = go(~mode=Syn, scrut, m); - let rules_to_info_map = (rules: list((UPat.t, UExp.t)), m) => { - let (ps, es) = List.split(rules); - let branch_ids = List.map(UExp.rep_id, es); + let (ps, es) = List.split(rules); + let branch_ids = List.map(UExp.rep_id, es); + let rules_to_info_map = (ps: list(UPat.t), es: list(UExp.t), m) => { // switch (scrut.ty) { // | Unknown(_) => // let (ps', _m) = @@ -494,10 +494,9 @@ and uexp_to_info_map = (m, Constraint.Falsity), List.combine(ps, e_co_ctxs), ); - (es, e_co_ctxs, branch_ids, final_constraint, m); + (es, e_co_ctxs, final_constraint, m); }; - let (es, e_co_ctxs, branch_ids, final_constraint, m) = - rules_to_info_map(rules, m); + let (es, e_co_ctxs, final_constraint, m) = rules_to_info_map(ps, es, m); let e_tys = List.map(Info.exp_ty, es); let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); From 14af4794819e9501552e571b575643bf4ac764f8 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 15:10:04 -0400 Subject: [PATCH 129/141] moved join check draft outside --- src/haz3lcore/statics/Statics.re | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 2ba107adfd..6ef69e8d9e 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -418,23 +418,23 @@ and uexp_to_info_map = let (scrut, m) = go(~mode=Syn, scrut, m); let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); + // switch (scrut.ty) { + // | Unknown(_) => + // let (ps', _m) = + // map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty), ps, m); + // print_endline( + // Typ.join_all( + // ~empty=Unknown(Internal), + // ctx, + // List.map(Info.pat_ty, ps'), + // ) + // == None + // ? "some" : "none", + // ); + // | _ => () + // }; + // switch () let rules_to_info_map = (ps: list(UPat.t), es: list(UExp.t), m) => { - // switch (scrut.ty) { - // | Unknown(_) => - // let (ps', _m) = - // map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty), ps, m); - // print_endline( - // Typ.join_all( - // ~empty=Unknown(Internal), - // ctx, - // List.map(Info.pat_ty, ps'), - // ) - // == None - // ? "some" : "none", - // ); - // | _ => () - // }; - // switch () let (ps', m) = map_m( go_pat( From cfad199f495efc491884e6abf6e1e469c312df87 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 15:16:40 -0400 Subject: [PATCH 130/141] created branch for join check --- src/haz3lcore/statics/Statics.re | 140 ++++++++++++++++--------------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 6ef69e8d9e..6322da5dac 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -434,75 +434,83 @@ and uexp_to_info_map = // | _ => () // }; // switch () - let rules_to_info_map = (ps: list(UPat.t), es: list(UExp.t), m) => { - let (ps', m) = - map_m( - go_pat( - ~is_synswitch=false, - ~co_ctx=CoCtx.empty, - ~mode=Mode.Ana(scrut_ty), - ), - ps, - m, - ); - let p_ctxs = List.map(Info.pat_ctx, ps'); - let (es, m) = - List.fold_left2( - ((es, m), e, ctx) => - go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), - ([], m), - es, - p_ctxs, - ); - let e_co_ctxs = - List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - /* Add co-ctxs to patterns */ - let (m, final_constraint) = - List.fold_left( - ((m, acc_constraint), (p, co_ctx)) => { - let (p, m) = + let scrut_ty = Some(scrut.ty); + let (self, e_co_ctxs, m) = + switch (scrut_ty) { + | Some(scrut_ty) => + let rules_to_info_map = (ps: list(UPat.t), es: list(UExp.t), m) => { + let (ps', m) = + map_m( go_pat( ~is_synswitch=false, - ~co_ctx, + ~co_ctx=CoCtx.empty, ~mode=Mode.Ana(scrut_ty), - p, - m, - ); - let p_constraint = Info.pat_constraint(p); - if (!Incon.is_redundant(p_constraint, acc_constraint)) { - (m, Constraint.Or(p_constraint, acc_constraint)); - } else { - let info = - Info.derived_pat( - ~upat=p.term, - ~ctx=p.ctx, - ~co_ctx=p.co_ctx, - ~mode=p.mode, - ~ancestors=p.ancestors, - ~self=Redundant(p.self), - // Mark patterns as redundant at the top level - // because redundancy doesn't make sense in a smaller context - ~constraint_=p_constraint, - ); - ( - // Override the info for the single upat - add_info(p.term.ids, InfoPat(info), m), - acc_constraint // Redundant patterns are ignored - ); - }; - }, - (m, Constraint.Falsity), - List.combine(ps, e_co_ctxs), - ); - (es, e_co_ctxs, final_constraint, m); - }; - let (es, e_co_ctxs, final_constraint, m) = rules_to_info_map(ps, es, m); - let e_tys = List.map(Info.exp_ty, es); - let unwrapped_self: Self.exp = - Common(Self.match(ctx, e_tys, branch_ids)); - let is_exhaustive = Incon.is_exhaustive(final_constraint); - let self = - is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); + ), + ps, + m, + ); + let p_ctxs = List.map(Info.pat_ctx, ps'); + let (es, m) = + List.fold_left2( + ((es, m), e, ctx) => + go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), + ([], m), + es, + p_ctxs, + ); + let e_co_ctxs = + List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); + /* Add co-ctxs to patterns */ + let (m, final_constraint) = + List.fold_left( + ((m, acc_constraint), (p, co_ctx)) => { + let (p, m) = + go_pat( + ~is_synswitch=false, + ~co_ctx, + ~mode=Mode.Ana(scrut_ty), + p, + m, + ); + let p_constraint = Info.pat_constraint(p); + if (!Incon.is_redundant(p_constraint, acc_constraint)) { + (m, Constraint.Or(p_constraint, acc_constraint)); + } else { + let info = + Info.derived_pat( + ~upat=p.term, + ~ctx=p.ctx, + ~co_ctx=p.co_ctx, + ~mode=p.mode, + ~ancestors=p.ancestors, + ~self=Redundant(p.self), + // Mark patterns as redundant at the top level + // because redundancy doesn't make sense in a smaller context + ~constraint_=p_constraint, + ); + ( + // Override the info for the single upat + add_info(p.term.ids, InfoPat(info), m), + acc_constraint // Redundant patterns are ignored + ); + }; + }, + (m, Constraint.Falsity), + List.combine(ps, e_co_ctxs), + ); + (es, e_co_ctxs, final_constraint, m); + }; + let (es, e_co_ctxs, final_constraint, m) = + rules_to_info_map(ps, es, m); + let e_tys = List.map(Info.exp_ty, es); + let unwrapped_self: Self.exp = + Common(Self.match(ctx, e_tys, branch_ids)); + let is_exhaustive = Incon.is_exhaustive(final_constraint); + let self = + is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); + (self, e_co_ctxs, m); + | None => failwith("unimplemented") + }; add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => let m = utpat_to_info_map(~ctx, ~ancestors, typat, m) |> snd; From a389e836fd9a028406cb1d61842a232360244f1c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 15:30:47 -0400 Subject: [PATCH 131/141] none branch for join check --- src/haz3lcore/statics/Statics.re | 43 +++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 6322da5dac..6e3fb58f2a 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -438,7 +438,8 @@ and uexp_to_info_map = let (self, e_co_ctxs, m) = switch (scrut_ty) { | Some(scrut_ty) => - let rules_to_info_map = (ps: list(UPat.t), es: list(UExp.t), m) => { + let rules_to_info_map = + (ps: list(UPat.t), es: list(UExp.t), scrut_ty: Typ.t, m) => { let (ps', m) = map_m( go_pat( @@ -501,7 +502,7 @@ and uexp_to_info_map = (es, e_co_ctxs, final_constraint, m); }; let (es, e_co_ctxs, final_constraint, m) = - rules_to_info_map(ps, es, m); + rules_to_info_map(ps, es, scrut_ty, m); let e_tys = List.map(Info.exp_ty, es); let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); @@ -509,7 +510,43 @@ and uexp_to_info_map = let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); (self, e_co_ctxs, m); - | None => failwith("unimplemented") + | None => + let (ps', _) = + map_m( + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=Mode.Ana(scrut.ty), + ), + ps, + m, + ); + let p_ctxs = List.map(Info.pat_ctx, ps'); + let (es, m) = + List.fold_left2( + ((es, m), e, ctx) => + go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), + ([], m), + es, + p_ctxs, + ); + let e_tys = List.map(Info.exp_ty, es); + let e_co_ctxs = + List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); + /* Add co-ctxs to patterns */ + let (_, m) = + map_m( + ((p, co_ctx)) => + go_pat( + ~is_synswitch=false, + ~co_ctx, + ~mode=Mode.Ana(scrut.ty), + p, + ), + List.combine(ps, e_co_ctxs), + m, + ); + (Common(Self.match(ctx, e_tys, branch_ids)), e_co_ctxs, m); }; add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => From 64075dba90233cc9390ff16d81da166f86056ade Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sat, 4 May 2024 16:04:06 -0400 Subject: [PATCH 132/141] factor out code --- src/haz3lcore/statics/Statics.re | 74 +++++++++++--------------------- 1 file changed, 25 insertions(+), 49 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 6e3fb58f2a..d2a249d836 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -418,6 +418,28 @@ and uexp_to_info_map = let (scrut, m) = go(~mode=Syn, scrut, m); let (ps, es) = List.split(rules); let branch_ids = List.map(UExp.rep_id, es); + let (ps', _) = + map_m( + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=Mode.Ana(scrut.ty), + ), + ps, + m, + ); + let p_ctxs = List.map(Info.pat_ctx, ps'); + let (es, m) = + List.fold_left2( + ((es, m), e, ctx) => + go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), + ([], m), + es, + p_ctxs, + ); + let e_tys = List.map(Info.exp_ty, es); + let e_co_ctxs = + List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); // switch (scrut.ty) { // | Unknown(_) => // let (ps', _m) = @@ -438,29 +460,7 @@ and uexp_to_info_map = let (self, e_co_ctxs, m) = switch (scrut_ty) { | Some(scrut_ty) => - let rules_to_info_map = - (ps: list(UPat.t), es: list(UExp.t), scrut_ty: Typ.t, m) => { - let (ps', m) = - map_m( - go_pat( - ~is_synswitch=false, - ~co_ctx=CoCtx.empty, - ~mode=Mode.Ana(scrut_ty), - ), - ps, - m, - ); - let p_ctxs = List.map(Info.pat_ctx, ps'); - let (es, m) = - List.fold_left2( - ((es, m), e, ctx) => - go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), - ([], m), - es, - p_ctxs, - ); - let e_co_ctxs = - List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); + let rules_to_info_map = (ps: list(UPat.t), scrut_ty: Typ.t, m) => { /* Add co-ctxs to patterns */ let (m, final_constraint) = List.fold_left( @@ -499,11 +499,9 @@ and uexp_to_info_map = (m, Constraint.Falsity), List.combine(ps, e_co_ctxs), ); - (es, e_co_ctxs, final_constraint, m); + (final_constraint, m); }; - let (es, e_co_ctxs, final_constraint, m) = - rules_to_info_map(ps, es, scrut_ty, m); - let e_tys = List.map(Info.exp_ty, es); + let (final_constraint, m) = rules_to_info_map(ps, scrut_ty, m); let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); let is_exhaustive = Incon.is_exhaustive(final_constraint); @@ -511,28 +509,6 @@ and uexp_to_info_map = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); (self, e_co_ctxs, m); | None => - let (ps', _) = - map_m( - go_pat( - ~is_synswitch=false, - ~co_ctx=CoCtx.empty, - ~mode=Mode.Ana(scrut.ty), - ), - ps, - m, - ); - let p_ctxs = List.map(Info.pat_ctx, ps'); - let (es, m) = - List.fold_left2( - ((es, m), e, ctx) => - go'(~ctx, ~mode, e, m) |> (((e, m)) => (es @ [e], m)), - ([], m), - es, - p_ctxs, - ); - let e_tys = List.map(Info.exp_ty, es); - let e_co_ctxs = - List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); /* Add co-ctxs to patterns */ let (_, m) = map_m( From d736500e50c4cef06570eed03f76e230d678f1be Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 14:28:23 -0400 Subject: [PATCH 133/141] code simplification --- src/haz3lcore/statics/Statics.re | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index d2a249d836..0ac6f0553a 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -457,7 +457,7 @@ and uexp_to_info_map = // }; // switch () let scrut_ty = Some(scrut.ty); - let (self, e_co_ctxs, m) = + let (self, m) = switch (scrut_ty) { | Some(scrut_ty) => let rules_to_info_map = (ps: list(UPat.t), scrut_ty: Typ.t, m) => { @@ -507,7 +507,7 @@ and uexp_to_info_map = let is_exhaustive = Incon.is_exhaustive(final_constraint); let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); - (self, e_co_ctxs, m); + (self, m); | None => /* Add co-ctxs to patterns */ let (_, m) = @@ -522,7 +522,7 @@ and uexp_to_info_map = List.combine(ps, e_co_ctxs), m, ); - (Common(Self.match(ctx, e_tys, branch_ids)), e_co_ctxs, m); + (Common(Self.match(ctx, e_tys, branch_ids)), m); }; add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => From 804f5e289c191b224caa276f24c00f2a5e2a6a3c Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 14:38:25 -0400 Subject: [PATCH 134/141] rules_to_info_map => pats_to_info_map --- src/haz3lcore/statics/Statics.re | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 0ac6f0553a..8efa67851a 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -460,7 +460,7 @@ and uexp_to_info_map = let (self, m) = switch (scrut_ty) { | Some(scrut_ty) => - let rules_to_info_map = (ps: list(UPat.t), scrut_ty: Typ.t, m) => { + let pats_to_info_map = (ps: list(UPat.t), m) => { /* Add co-ctxs to patterns */ let (m, final_constraint) = List.fold_left( @@ -469,7 +469,7 @@ and uexp_to_info_map = go_pat( ~is_synswitch=false, ~co_ctx, - ~mode=Mode.Ana(scrut_ty), + ~mode=Mode.Ana(scrut.ty), p, m, ); @@ -501,7 +501,7 @@ and uexp_to_info_map = ); (final_constraint, m); }; - let (final_constraint, m) = rules_to_info_map(ps, scrut_ty, m); + let (final_constraint, m) = pats_to_info_map(ps, m); let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); let is_exhaustive = Incon.is_exhaustive(final_constraint); From 81fa2865f55de2b3b9dfafda0d7337e7b126784b Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 15:28:30 -0400 Subject: [PATCH 135/141] some branch for join check --- src/haz3lcore/statics/Statics.re | 52 +++++++++++++++++++------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 8efa67851a..76f8d4f5fb 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -465,6 +465,16 @@ and uexp_to_info_map = let (m, final_constraint) = List.fold_left( ((m, acc_constraint), (p, co_ctx)) => { + let p_constraint = + go_pat( + ~is_synswitch=false, + ~co_ctx, + ~mode=Mode.Ana(scrut_ty), + p, + m, + ) + |> fst + |> Info.pat_constraint; let (p, m) = go_pat( ~is_synswitch=false, @@ -473,28 +483,28 @@ and uexp_to_info_map = p, m, ); - let p_constraint = Info.pat_constraint(p); - if (!Incon.is_redundant(p_constraint, acc_constraint)) { - (m, Constraint.Or(p_constraint, acc_constraint)); - } else { - let info = - Info.derived_pat( - ~upat=p.term, - ~ctx=p.ctx, - ~co_ctx=p.co_ctx, - ~mode=p.mode, - ~ancestors=p.ancestors, - ~self=Redundant(p.self), - // Mark patterns as redundant at the top level - // because redundancy doesn't make sense in a smaller context - ~constraint_=p_constraint, - ); - ( - // Override the info for the single upat - add_info(p.term.ids, InfoPat(info), m), - acc_constraint // Redundant patterns are ignored + let is_redundant = + Incon.is_redundant(p_constraint, acc_constraint); + let self = is_redundant ? Self.Redundant(p.self) : p.self; + let info = + Info.derived_pat( + ~upat=p.term, + ~ctx=p.ctx, + ~co_ctx=p.co_ctx, + ~mode=p.mode, + ~ancestors=p.ancestors, + ~self, + // Mark patterns as redundant at the top level + // because redundancy doesn't make sense in a smaller context + ~constraint_=p_constraint, ); - }; + ( + // Override the info for the single upat + add_info(p.term.ids, InfoPat(info), m), + is_redundant + ? acc_constraint // Redundant patterns are ignored + : Constraint.Or(p_constraint, acc_constraint), + ); }, (m, Constraint.Falsity), List.combine(ps, e_co_ctxs), From 3efe0611ddd40ba6ff0d3427ddf4e41e14eda7c1 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 15:37:17 -0400 Subject: [PATCH 136/141] unknown scrutinee type handling mostly done --- src/haz3lcore/statics/Statics.re | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 76f8d4f5fb..f52617a7bc 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -440,7 +440,6 @@ and uexp_to_info_map = let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - // switch (scrut.ty) { // | Unknown(_) => // let (ps', _m) = // map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty), ps, m); @@ -456,7 +455,11 @@ and uexp_to_info_map = // | _ => () // }; // switch () - let scrut_ty = Some(scrut.ty); + let scrut_ty = + switch (scrut.ty) { + | Unknown(_) => None + | ty => Some(ty) + }; let (self, m) = switch (scrut_ty) { | Some(scrut_ty) => From 9f7087b1e0d7ac430e2c65317e8d3041992b66ff Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 15:48:38 -0400 Subject: [PATCH 137/141] unknown scrutinee type handling done --- src/haz3lcore/statics/Statics.re | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index f52617a7bc..857ba17b9b 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -440,24 +440,13 @@ and uexp_to_info_map = let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - // | Unknown(_) => - // let (ps', _m) = - // map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty), ps, m); - // print_endline( - // Typ.join_all( - // ~empty=Unknown(Internal), - // ctx, - // List.map(Info.pat_ty, ps'), - // ) - // == None - // ? "some" : "none", - // ); - // | _ => () - // }; - // switch () let scrut_ty = switch (scrut.ty) { - | Unknown(_) => None + | Unknown(_) => + map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty), ps, m) + |> fst + |> List.map(Info.pat_ty) + |> Typ.join_all(~empty=Unknown(Internal), ctx) | ty => Some(ty) }; let (self, m) = From 9a021ce9da81699b5503bf11aba39f2929ed9d0f Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 15:56:20 -0400 Subject: [PATCH 138/141] scrut_ty => constraint_ty --- src/haz3lcore/statics/Statics.re | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 857ba17b9b..fcee5a4b0d 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -440,7 +440,7 @@ and uexp_to_info_map = let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); - let scrut_ty = + let constraint_ty = switch (scrut.ty) { | Unknown(_) => map_m(go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty), ps, m) @@ -450,8 +450,8 @@ and uexp_to_info_map = | ty => Some(ty) }; let (self, m) = - switch (scrut_ty) { - | Some(scrut_ty) => + switch (constraint_ty) { + | Some(constraint_ty) => let pats_to_info_map = (ps: list(UPat.t), m) => { /* Add co-ctxs to patterns */ let (m, final_constraint) = @@ -461,7 +461,7 @@ and uexp_to_info_map = go_pat( ~is_synswitch=false, ~co_ctx, - ~mode=Mode.Ana(scrut_ty), + ~mode=Mode.Ana(constraint_ty), p, m, ) From f780316856dc4d047a2734ad21670564253b7380 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 16:12:31 -0400 Subject: [PATCH 139/141] code simplification --- src/haz3lcore/statics/Statics.re | 94 ++++++++++++++++---------------- 1 file changed, 46 insertions(+), 48 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index fcee5a4b0d..7b4973ddb7 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -454,56 +454,54 @@ and uexp_to_info_map = | Some(constraint_ty) => let pats_to_info_map = (ps: list(UPat.t), m) => { /* Add co-ctxs to patterns */ - let (m, final_constraint) = - List.fold_left( - ((m, acc_constraint), (p, co_ctx)) => { - let p_constraint = - go_pat( - ~is_synswitch=false, - ~co_ctx, - ~mode=Mode.Ana(constraint_ty), - p, - m, - ) - |> fst - |> Info.pat_constraint; - let (p, m) = - go_pat( - ~is_synswitch=false, - ~co_ctx, - ~mode=Mode.Ana(scrut.ty), - p, - m, - ); - let is_redundant = - Incon.is_redundant(p_constraint, acc_constraint); - let self = is_redundant ? Self.Redundant(p.self) : p.self; - let info = - Info.derived_pat( - ~upat=p.term, - ~ctx=p.ctx, - ~co_ctx=p.co_ctx, - ~mode=p.mode, - ~ancestors=p.ancestors, - ~self, - // Mark patterns as redundant at the top level - // because redundancy doesn't make sense in a smaller context - ~constraint_=p_constraint, - ); - ( - // Override the info for the single upat - add_info(p.term.ids, InfoPat(info), m), - is_redundant - ? acc_constraint // Redundant patterns are ignored - : Constraint.Or(p_constraint, acc_constraint), + List.fold_left( + ((m, acc_constraint), (p, co_ctx)) => { + let p_constraint = + go_pat( + ~is_synswitch=false, + ~co_ctx, + ~mode=Mode.Ana(constraint_ty), + p, + m, + ) + |> fst + |> Info.pat_constraint; + let (p, m) = + go_pat( + ~is_synswitch=false, + ~co_ctx, + ~mode=Mode.Ana(scrut.ty), + p, + m, ); - }, - (m, Constraint.Falsity), - List.combine(ps, e_co_ctxs), - ); - (final_constraint, m); + let is_redundant = + Incon.is_redundant(p_constraint, acc_constraint); + let self = is_redundant ? Self.Redundant(p.self) : p.self; + let info = + Info.derived_pat( + ~upat=p.term, + ~ctx=p.ctx, + ~co_ctx=p.co_ctx, + ~mode=p.mode, + ~ancestors=p.ancestors, + ~self, + // Mark patterns as redundant at the top level + // because redundancy doesn't make sense in a smaller context + ~constraint_=p_constraint, + ); + ( + // Override the info for the single upat + add_info(p.term.ids, InfoPat(info), m), + is_redundant + ? acc_constraint // Redundant patterns are ignored + : Constraint.Or(p_constraint, acc_constraint), + ); + }, + (m, Constraint.Falsity), + List.combine(ps, e_co_ctxs), + ); }; - let (final_constraint, m) = pats_to_info_map(ps, m); + let (m, final_constraint) = pats_to_info_map(ps, m); let unwrapped_self: Self.exp = Common(Self.match(ctx, e_tys, branch_ids)); let is_exhaustive = Incon.is_exhaustive(final_constraint); From 58f568b068b29b9106874164f6abce7667fc8608 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Sun, 5 May 2024 16:18:53 -0400 Subject: [PATCH 140/141] code simplification --- src/haz3lcore/statics/Statics.re | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 7b4973ddb7..b445c41452 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -440,6 +440,8 @@ and uexp_to_info_map = let e_tys = List.map(Info.exp_ty, es); let e_co_ctxs = List.map2(CoCtx.mk(ctx), p_ctxs, List.map(Info.exp_co_ctx, es)); + let unwrapped_self: Self.exp = + Common(Self.match(ctx, e_tys, branch_ids)); let constraint_ty = switch (scrut.ty) { | Unknown(_) => @@ -502,8 +504,6 @@ and uexp_to_info_map = ); }; let (m, final_constraint) = pats_to_info_map(ps, m); - let unwrapped_self: Self.exp = - Common(Self.match(ctx, e_tys, branch_ids)); let is_exhaustive = Incon.is_exhaustive(final_constraint); let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); @@ -522,7 +522,7 @@ and uexp_to_info_map = List.combine(ps, e_co_ctxs), m, ); - (Common(Self.match(ctx, e_tys, branch_ids)), m); + (unwrapped_self, m); }; add'(~self, ~co_ctx=CoCtx.union([scrut.co_ctx] @ e_co_ctxs), m); | TyAlias(typat, utyp, body) => From d6d61c8cb43db1d11778d965aed5262cb3a3c4f9 Mon Sep 17 00:00:00 2001 From: Jiezhong Yang Date: Tue, 14 May 2024 13:55:27 -0400 Subject: [PATCH 141/141] code clean --- src/haz3lcore/statics/TypBase.re | 100 ++++++------------------------- 1 file changed, 19 insertions(+), 81 deletions(-) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 576f368b6b..58690c3aec 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -559,21 +559,10 @@ and Ctx: { kind: Kind.t, }; - [@deriving (show({with_path: false}), sexp, yojson)] - type constructor_entry = { - name: Var.t, - id: Id.t, - typ: Typ.t, - /* Temporary variables. Better implementation is a TO-DO. */ - nth: int, - num_variants: int, - }; - [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) - // | ConstructorEntry(var_entry, Constraint.t => Constraint.t) /* obselete because of dependency cycle */ - | ConstructorEntry(constructor_entry) + | ConstructorEntry(var_entry) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -587,7 +576,7 @@ and Ctx: { let lookup_alias: (t, TypVar.t) => option(Typ.t); let get_id: entry => Id.t; let lookup_var: (t, string) => option(var_entry); - let lookup_ctr: (t, string) => option(constructor_entry); + let lookup_ctr: (t, string) => option(var_entry); let is_alias: (t, TypVar.t) => bool; let is_abstract: (t, TypVar.t) => bool; let add_ctrs: (t, TypVar.t, Id.t, Typ.sum_map) => t; @@ -610,21 +599,10 @@ and Ctx: { kind: Kind.t, }; - [@deriving (show({with_path: false}), sexp, yojson)] - type constructor_entry = { - name: Var.t, - id: Id.t, - typ: Typ.t, - /* Temporary variables. Better implementation is a TO-DO. */ - nth: int, - num_variants: int, - }; - [@deriving (show({with_path: false}), sexp, yojson)] type entry = | VarEntry(var_entry) - // | ConstructorEntry(var_entry, Constraint.t => Constraint.t) /* obselete because of dependency cycle */ - | ConstructorEntry(constructor_entry) + | ConstructorEntry(var_entry) | TVarEntry(tvar_entry); [@deriving (show({with_path: false}), sexp, yojson)] @@ -670,7 +648,7 @@ and Ctx: { ctx, ); - let lookup_ctr = (ctx: t, name: string): option(constructor_entry) => + let lookup_ctr = (ctx: t, name: string): option(var_entry) => List.find_map( fun | ConstructorEntry(t) when t.name == name => Some(t) @@ -690,61 +668,21 @@ and Ctx: { | _ => false }; - let add_ctrs = (ctx: t, name: TypVar.t, id: Id.t, ctrs: Typ.sum_map): t => { - // let (ctx, _, _) = - // List.fold_left( - // ((ctx, nth, wrap), (ctr, typ)) => { - // // List.length(ctrs) == 0: EmptyHole - // // List.length(ctrs) == 1: Type variable not found - // assert(List.length(ctrs) > 1); - - // // List.length(ctrs) == 2: - // // nth == 0: xi => InjL(xi) - // // nth == 1: xi => InjR(InjL(xi)) - // // nth == 2: xi => InjR(InjR(xi)) - // let constraint_ctor = xi => - // wrap(nth == List.length(ctrs) - 1 ? Constraint.InjL(xi) : xi); - // let entry = - // ConstructorEntry( - // { - // name: ctr, - // id, - // typ: - // switch (typ) { - // | None => Var(name) - // | Some(typ) => Arrow(typ, Var(name)) - // }, - // }, - // constraint_ctor, - // ); - // ([entry, ...ctx], nth + 1, xi => wrap(Constraint.InjR(xi))); - // }, - // (ctx, 0, Fun.id), - // ctrs, - // ); - let num_variants = List.length(ctrs); - let (ctx, _) = - List.fold_left( - ((ctx, nth), (ctr, typ)) => { - let entry = - ConstructorEntry({ - name: ctr, - id, - typ: - switch (typ) { - | None => Var(name) - | Some(typ) => Arrow(typ, Var(name)) - }, - nth, - num_variants, - }); - ([entry, ...ctx], nth + 1); - }, - (ctx, 0), - ctrs, - ); - ctx; - }; + let add_ctrs = (ctx: t, name: TypVar.t, id: Id.t, ctrs: Typ.sum_map): t => + List.map( + ((ctr, typ)) => + ConstructorEntry({ + name: ctr, + id, + typ: + switch (typ) { + | None => Var(name) + | Some(typ) => Arrow(typ, Var(name)) + }, + }), + ctrs, + ) + @ ctx; let subtract_prefix = (ctx: t, prefix_ctx: t): option(t) => { // NOTE: does not check that the prefix is an actual prefix