From 3d2a3515ac32ee28a713acda198e7778beaf75fc Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 23 Feb 2024 16:50:14 -0500 Subject: [PATCH 001/108] labeled tuple rewrite --- src/haz3lcore/LabeledTuple.re | 134 ++++++++++++++ src/haz3lcore/dynamics/DH.re | 22 ++- src/haz3lcore/dynamics/DHPat.re | 3 + src/haz3lcore/dynamics/Elaborator.re | 10 +- src/haz3lcore/dynamics/EvalCtx.re | 4 + src/haz3lcore/dynamics/EvaluatorPost.re | 9 + src/haz3lcore/dynamics/EvaluatorStep.re | 4 + src/haz3lcore/dynamics/FilterMatcher.re | 5 + src/haz3lcore/dynamics/PatternMatch.re | 107 +++++++---- src/haz3lcore/dynamics/Stepper.re | 3 + src/haz3lcore/dynamics/Substitution.re | 1 + src/haz3lcore/dynamics/Transition.re | 6 + src/haz3lcore/lang/Form.re | 3 + src/haz3lcore/statics/MakeTerm.re | 23 +++ src/haz3lcore/statics/Mode.re | 13 +- src/haz3lcore/statics/Statics.re | 27 ++- src/haz3lcore/statics/Term.re | 19 ++ src/haz3lcore/statics/TermBase.re | 8 + src/haz3lcore/statics/TypBase.re | 185 ++++++++++++++++++- src/haz3lcore/zipper/EditorUtil.re | 1 + src/haz3lschool/SyntaxTest.re | 7 + src/haz3lweb/view/ExplainThis.re | 10 + src/haz3lweb/view/Type.re | 1 + src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 9 + src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re | 4 + src/haz3lweb/view/dhcode/layout/HTypDoc.re | 1 + 26 files changed, 570 insertions(+), 49 deletions(-) create mode 100644 src/haz3lcore/LabeledTuple.re diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re new file mode 100644 index 0000000000..171ed78c80 --- /dev/null +++ b/src/haz3lcore/LabeledTuple.re @@ -0,0 +1,134 @@ +open Sexplib.Std; + +[@deriving (show({with_path: false}), sexp, yojson)] +type t = string; + +let eq = String.equal; + +let length = String.length; + +let valid_regex = + Re.Str.regexp("^\\([a-zA-Z]\\|_[_a-zA-Z0-9]\\)[_a-zA-Z0-9']*$"); +let is_valid = s => Re.Str.string_match(valid_regex, s, 0); + +let compare = String.compare; + +let find_opt: ('a => bool, list('a)) => option('a) = List.find_opt; + +// filt returns Some(string) if TupLabel or None if not a TupLabel +// returns ordered list of (Some(string), TupLabel) +// and another of (None, not-TupLabel) +// TODO: Make more efficient +let validate_uniqueness: + ('a => option(t), list('a)) => (bool, list((option(t), 'a)), list('a)) = + (filt, es) => { + let results = + List.fold_left( + ((b, ls, ns), e) => + switch (filt(e)) { + | Some(s1) + when + b + && List.fold_left( + (v, l) => + switch (l) { + | (Some(s2), _) when v => compare(s1, s2) != 0 + | _ => false + }, + true, + ls, + ) => ( + b, + ls @ [(filt(e), e)], + ns, + ) + | None => (b, ls, ns @ [e]) + | _ => (false, ls, ns) + }, + (true, [], []), + es, + ); + results; + }; + +// Rename and clean this +// Assumes all labels are unique +// filt returns Some(string) if TupLabel or None if not a TupLabel +// In order of operations: +// Checks all labeled pairs in l2 are in l1 and performs f on each pair +// Checks all labeled pairs in l1 are in l2 and performs f on each pair +// Checks remaining None pairs in order and performs f on each pair +let ana_tuple: + ( + 'b => option(string), + 'c => option(string), + ('a, 'b, 'c) => 'a, + 'a, + 'a, + list('b), + list('c) + ) => + 'a = + (filt1, filt2, f, accu, accu_fail, l1, l2) => { + let (l1_valid, l1_lab, l1_none) = validate_uniqueness(filt1, l1); + let (l2_valid, l2_lab, l2_none) = validate_uniqueness(filt2, l2); + // temporary solution if mess up earlier in tuple, such as make_term + if (!l1_valid || !l2_valid) { + accu_fail; + } else if (List.length(l1_none) != List.length(l2_none)) { + accu_fail; + } else { + let accu = + List.fold_left( + (accu, l2_item) => { + let l1_item = + List.find_opt( + l1_item => { + switch (l1_item, l2_item) { + | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l1_lab, + ); + switch (l1_item, l2_item) { + | (Some((_, l1_val)), (_, l2_val)) => f(accu, l1_val, l2_val) + | (None, _) => accu_fail + }; + }, + accu, + l2_lab, + ); + // TODO: Currently duplicating checks, for both directions + let accu = + List.fold_left( + (accu, l1_item) => { + let l2_item = + List.find_opt( + l2_item => { + switch (l1_item, l2_item) { + | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l1_item, l2_item) { + | ((_, l1_val), Some((_, l2_val))) => f(accu, l1_val, l2_val) + | (_, None) => accu_fail + }; + }, + accu, + l1_lab, + ); + // None checks + let accu = + List.fold_left2( + (accu, l1_val, l2_val) => f(accu, l1_val, l2_val), + accu, + l1_none, + l2_none, + ); + accu; + }; + }; diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index daf30b8158..8e079870cb 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -36,6 +36,7 @@ module rec DHExp: { | ListLit(MetaVar.t, MetaVarInst.t, Typ.t, list(t)) | Cons(t, t) | ListConcat(t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Prj(t, int) | Constructor(string) @@ -93,6 +94,7 @@ module rec DHExp: { | ListLit(MetaVar.t, MetaVarInst.t, Typ.t, list(t)) | Cons(t, t) | ListConcat(t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Prj(t, int) | Constructor(string) @@ -135,6 +137,7 @@ module rec DHExp: { | ListLit(_) => "ListLit" | Cons(_, _) => "Cons" | ListConcat(_, _) => "ListConcat" + | TupLabel(_) => "Labeled Tuple Item" | Tuple(_) => "Tuple" | Prj(_) => "Prj" | Constructor(_) => "Constructor" @@ -167,6 +170,7 @@ module rec DHExp: { | Closure(ei, d) => Closure(ei, strip_casts(d)) | Cast(d, _, _) => strip_casts(d) | FailedCast(d, _, _) => strip_casts(d) + | TupLabel(s, d) => TupLabel(s, 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)) @@ -246,9 +250,24 @@ module rec DHExp: { fast_equal(d11, d12) && fast_equal(d21, d22) | (ListConcat(d11, d21), ListConcat(d12, d22)) => fast_equal(d11, d12) && fast_equal(d21, d22) + | (TupLabel(s1, d1), TupLabel(s2, d2)) => + LabeledTuple.compare(s1, s2) == 0 && fast_equal(d1, d2) | (Tuple(ds1), Tuple(ds2)) => + let filt: t => option(LabeledTuple.t) = ( + d => + switch (d) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let f = (b, ds1_val, ds2_val) => { + switch (b) { + | false => false + | true => fast_equal(ds1_val, ds2_val) + }; + }; List.length(ds1) == List.length(ds2) - && List.for_all2(fast_equal, ds1, ds2) + && LabeledTuple.ana_tuple(filt, filt, f, true, false, ds1, ds2); | (Prj(d1, n), Prj(d2, m)) => n == m && fast_equal(d1, d2) | (ApBuiltin(f1, d1), ApBuiltin(f2, d2)) => f1 == f2 && d1 == d2 | (BuiltinFun(f1), BuiltinFun(f2)) => f1 == f2 @@ -289,6 +308,7 @@ module rec DHExp: { | (Cons(_), _) | (ListConcat(_), _) | (ListLit(_), _) + | (TupLabel(_, _), _) | (Tuple(_), _) | (Prj(_), _) | (BinBoolOp(_), _) diff --git a/src/haz3lcore/dynamics/DHPat.re b/src/haz3lcore/dynamics/DHPat.re index 4909fce337..d72c5a9caf 100644 --- a/src/haz3lcore/dynamics/DHPat.re +++ b/src/haz3lcore/dynamics/DHPat.re @@ -15,6 +15,7 @@ type t = | StringLit(string) | ListLit(Typ.t, list(t)) | Cons(t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Constructor(string) | Ap(t, t); @@ -42,6 +43,7 @@ let rec binds_var = (x: Var.t, dp: t): bool => | Constructor(_) | ExpandingKeyword(_, _, _) => false | Var(y) => Var.eq(x, y) + | TupLabel(_, dp) => binds_var(x, dp) | Tuple(dps) => dps |> List.exists(binds_var(x)) | Cons(dp1, dp2) => binds_var(x, dp1) || binds_var(x, dp2) | ListLit(_, d_list) => @@ -64,6 +66,7 @@ let rec bound_vars = (dp: t): list(Var.t) => | Constructor(_) | ExpandingKeyword(_, _, _) => [] | Var(y) => [y] + | TupLabel(_, dp) => bound_vars(dp) | Tuple(dps) => List.flatten(List.map(bound_vars, dps)) | Cons(dp1, dp2) => bound_vars(dp1) @ bound_vars(dp2) | ListLit(_, dps) => List.flatten(List.map(bound_vars, dps)) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 93439cb732..c044e785db 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -27,6 +27,7 @@ let fixed_pat_typ = (m: Statics.Map.t, p: Term.UPat.t): option(Typ.t) => | _ => None }; +// TODO (Anthony): Where to put TupLabel? let cast = (ctx: Ctx.t, mode: Mode.t, self_ty: Typ.t, d: DHExp.t) => switch (mode) { | Syn => d @@ -73,6 +74,7 @@ let cast = (ctx: Ctx.t, mode: Mode.t, self_ty: Typ.t, d: DHExp.t) => | IfThenElse(_) | Sequence(_) | Let(_) + | TupLabel(_, _) | FixF(_) => d /* Hole-like forms: Don't cast */ | InvalidText(_) @@ -152,6 +154,9 @@ let rec dhexp_of_uexp = let* d1 = dhexp_of_uexp(m, body); let+ ty = fixed_pat_typ(m, p); DHExp.Fun(dp, ty, d1, None); + | TupLabel(s, e) => + let+ de = dhexp_of_uexp(m, e); + DHExp.TupLabel(s, de); | Tuple(es) => let+ ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; DHExp.Tuple(ds); @@ -335,9 +340,12 @@ and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.t) => { let* d_hd = dhpat_of_upat(m, hd); let* d_tl = dhpat_of_upat(m, tl); wrap(Cons(d_hd, d_tl)); + | TupLabel(s, dp) => + let* dp2 = dhpat_of_upat(m, dp); + wrap(TupLabel(s, dp2)); | Tuple(ps) => let* ds = ps |> List.map(dhpat_of_upat(m)) |> OptUtil.sequence; - wrap(DHPat.Tuple(ds)); + wrap(Tuple(ds)); | Var(name) => Some(Var(name)) | Parens(p) => dhpat_of_upat(m, p) | Ap(p1, p2) => diff --git a/src/haz3lcore/dynamics/EvalCtx.re b/src/haz3lcore/dynamics/EvalCtx.re index 85ba47f5dd..5bde0655cb 100644 --- a/src/haz3lcore/dynamics/EvalCtx.re +++ b/src/haz3lcore/dynamics/EvalCtx.re @@ -26,6 +26,7 @@ type cls = | IfThenElse1 | IfThenElse2 | IfThenElse3 + | TupLabel | Tuple(int) | ListLit(int) | ApBuiltin @@ -71,6 +72,7 @@ type t = | BinFloatOp2(TermBase.UExp.op_bin_float, DHExp.t, t) | BinStringOp1(TermBase.UExp.op_bin_string, t, DHExp.t) | BinStringOp2(TermBase.UExp.op_bin_string, DHExp.t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(t, (list(DHExp.t), list(DHExp.t))) | ApBuiltin(string, t) | Test(KeywordID.t, t) @@ -139,6 +141,7 @@ let rec fuzzy_mark = | BinFloatOp2(_) | BinStringOp1(_) | BinStringOp2(_) + | TupLabel(_) | Tuple(_) | ApBuiltin(_) | ListLit(_) @@ -190,6 +193,7 @@ let rec unwrap = (ctx: t, sel: cls): option(t) => { | (ListConcat1, ListConcat1(c, _)) | (ListConcat2, ListConcat2(_, c)) | (Test, Test(_, c)) + | (TupLabel, TupLabel(_, c)) | (Prj, Prj(c, _)) => Some(c) | (ListLit(n), ListLit(_, _, _, c, (ld, _))) | (Tuple(n), Tuple(c, (ld, _))) => diff --git a/src/haz3lcore/dynamics/EvaluatorPost.re b/src/haz3lcore/dynamics/EvaluatorPost.re index 4966e7a914..b850ec1093 100644 --- a/src/haz3lcore/dynamics/EvaluatorPost.re +++ b/src/haz3lcore/dynamics/EvaluatorPost.re @@ -111,6 +111,10 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => ); ListLit(a, b, c, ds); + | TupLabel(dp, d1) => + let* d1' = pp_eval(d1); + TupLabel(dp, d1') |> return; + | Tuple(ds) => let+ ds = ds @@ -356,6 +360,10 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => ); ListLit(a, b, c, ds); + | TupLabel(dp, d1) => + let* d1' = pp_uneval(env, d1); + TupLabel(dp, d1') |> return; + | Tuple(ds) => let+ ds = ds @@ -466,6 +474,7 @@ let rec track_children_of_hole = | Prj(d, _) | Cast(d, _, _) | FailedCast(d, _, _) + | TupLabel(_, d) | InvalidOperation(d, _) => track_children_of_hole(hii, parent, d) | Sequence(d1, d2) | Let(_, d1, d2) diff --git a/src/haz3lcore/dynamics/EvaluatorStep.re b/src/haz3lcore/dynamics/EvaluatorStep.re index b6fad324f2..2ba3f4155e 100644 --- a/src/haz3lcore/dynamics/EvaluatorStep.re +++ b/src/haz3lcore/dynamics/EvaluatorStep.re @@ -285,6 +285,10 @@ let rec compose = (ctx: EvalCtx.t, d: DHExp.t): DHExp.t => { | ListConcat2(d1, ctx) => let d2 = compose(ctx, d); ListConcat(d1, d2); + // TODO (Anthony): is this right? + | TupLabel(s, ctx) => + let d2 = compose(ctx, d); + TupLabel(s, d2); | Tuple(ctx, (ld, rd)) => let d = compose(ctx, d); Tuple(rev_concat(ld, [d, ...rd])); diff --git a/src/haz3lcore/dynamics/FilterMatcher.re b/src/haz3lcore/dynamics/FilterMatcher.re index dd501b3563..d7872cb340 100644 --- a/src/haz3lcore/dynamics/FilterMatcher.re +++ b/src/haz3lcore/dynamics/FilterMatcher.re @@ -132,6 +132,9 @@ let rec matches_exp = ) | (ListLit(_), _) => false + | (TupLabel(_, dv), TupLabel(_, fv)) => matches_exp(env, dv, fv) + | (TupLabel(_), _) => false + | (Tuple(dv), Tuple(fv)) => List.fold_left2( (acc, d, f) => acc && matches_exp(env, d, f), @@ -231,6 +234,8 @@ and matches_pat = (d: DHPat.t, f: DHPat.t): bool => { | (Constructor(_), _) => false | (Var(dx), Var(fx)) => dx == fx | (Var(_), _) => false + | (TupLabel(_, dx), TupLabel(_, fx)) => dx == fx + | (TupLabel(_), _) => false | (Tuple(dl), Tuple(fl)) => switch ( List.fold_left2((res, d, f) => res && matches_pat(d, f), true, dl, fl) diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 5b4d417406..7348ebcd8c 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -141,27 +141,45 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => matches(dp, d) | (Constructor(_), _) => DoesNotMatch + | (TupLabel(_, dp), TupLabel(_, d)) => matches(dp, d) + | (TupLabel(_, _), _) => DoesNotMatch + | (Tuple(dps), Tuple(ds)) => - if (List.length(dps) != List.length(ds)) { - DoesNotMatch; - } else { - List.fold_left2( - (result, dp, d) => - switch (result) { - | DoesNotMatch => DoesNotMatch - | IndetMatch => IndetMatch - | Matches(env) => - switch (matches(dp, d)) { - | DoesNotMatch => DoesNotMatch - | IndetMatch => IndetMatch - | Matches(env') => Matches(Environment.union(env, env')) - } - }, - Matches(Environment.empty), - dps, - ds, - ); - } + let filt1: DHPat.t => option(LabeledTuple.t) = ( + d => + switch (d) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let filt2: DHExp.t => option(LabeledTuple.t) = ( + d => + switch (d) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let f = (result, dp, d) => { + switch (result) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env) => + switch (matches(dp, d)) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env') => Matches(Environment.union(env, env')) + } + }; + }; + LabeledTuple.ana_tuple( + filt1, + filt2, + f, + Matches(Environment.empty), + DoesNotMatch, + dps, + ds, + ); | (Tuple(dps), Cast(d, Prod(tys), Prod(tys'))) => assert(List.length(tys) == List.length(tys')); matches_cast_Tuple( @@ -265,6 +283,7 @@ and matches_cast_Sum = | FloatLit(_) | StringLit(_) | ListLit(_) + | TupLabel(_, _) | Tuple(_) | Sequence(_, _) | Closure(_) @@ -284,22 +303,41 @@ and matches_cast_Tuple = if (List.length(dps) != List.length(ds)) { DoesNotMatch; } else { + let filt1: DHPat.t => option(LabeledTuple.t) = ( + d => + switch (d) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let filt2: ((DHExp.t, _)) => option(LabeledTuple.t) = ( + ((d, _)) => + switch (d) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); assert(List.length(List.combine(dps, ds)) == List.length(elt_casts)); - List.fold_right( - (((dp, d), casts), result) => { - switch (result) { - | DoesNotMatch - | IndetMatch => result - | Matches(env) => - switch (matches(dp, DHExp.apply_casts(d, casts))) { - | DoesNotMatch => DoesNotMatch - | IndetMatch => IndetMatch - | Matches(env') => Matches(Environment.union(env, env')) - } + let f = (result, dp, (d, casts)) => { + switch (result) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env) => + switch (matches(dp, DHExp.apply_casts(d, casts))) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env') => Matches(Environment.union(env, env')) } - }, - List.combine(List.combine(dps, ds), elt_casts), + }; + }; + LabeledTuple.ana_tuple( + filt1, + filt2, + f, Matches(Environment.empty), + DoesNotMatch, + dps, + List.combine(ds, elt_casts), ); } | Cast(d', Prod(tys), Prod(tys')) => @@ -327,6 +365,8 @@ and matches_cast_Tuple = d', List.map2(List.cons, List.combine(tys, tys'), elt_casts), ); + // What should TupLabel be? + | TupLabel(_, _) => DoesNotMatch | Cast(_, _, _) => DoesNotMatch | BoundVar(_) => DoesNotMatch | FreeVar(_) => IndetMatch @@ -491,6 +531,7 @@ and matches_cast_Cons = | Test(_) => DoesNotMatch | FloatLit(_) => DoesNotMatch | StringLit(_) => DoesNotMatch + | TupLabel(_, _) => DoesNotMatch | Tuple(_) => DoesNotMatch | Prj(_) => IndetMatch | Constructor(_) => DoesNotMatch diff --git a/src/haz3lcore/dynamics/Stepper.re b/src/haz3lcore/dynamics/Stepper.re index 0f481a341e..c30d4f24da 100644 --- a/src/haz3lcore/dynamics/Stepper.re +++ b/src/haz3lcore/dynamics/Stepper.re @@ -123,6 +123,9 @@ let rec matches = | BinStringOp2(op, d1, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); BinStringOp2(op, d1, ctx); + | TupLabel(s, ctx) => + let+ ctx = matches(env, flt, ctx, exp, act, idx); + TupLabel(s, ctx); | Tuple(ctx, ds) => let+ ctx = matches(env, flt, ctx, exp, act, idx); Tuple(ctx, ds); diff --git a/src/haz3lcore/dynamics/Substitution.re b/src/haz3lcore/dynamics/Substitution.re index cb08e83231..078c1aaeb2 100644 --- a/src/haz3lcore/dynamics/Substitution.re +++ b/src/haz3lcore/dynamics/Substitution.re @@ -72,6 +72,7 @@ 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); ListConcat(d3, d4); + | TupLabel(p, d3) => TupLabel(p, subst_var(d1, x, d3)) | Tuple(ds) => Tuple(List.map(subst_var(d1, x), ds)) | Prj(d, n) => Prj(subst_var(d1, x, d), n) | BinBoolOp(op, d3, d4) => diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index dfe896ca06..a4f074f606 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -125,6 +125,7 @@ module CastHelpers = { ? Ground : grounded_Sum(sm) | Arrow(_, _) => grounded_Arrow | List(_) => grounded_List + | Label(_, ty) => ground_cases_of(ty) // TODO (Anthony): what to do here? }; }; }; @@ -462,6 +463,11 @@ module Transition = (EV: EV_MODE) => { kind: BinStringOp(op), value: true, }); + | TupLabel(p, d1) => + // TODO (Anthony): Fix this if needed + let. _ = otherwise(env, d1 => TupLabel(p, d1)) + and. _ = req_final(req(state, env), d1 => TupLabel(p, d1), d1); + Constructor; | Tuple(ds) => let. _ = otherwise(env, ds => Tuple(ds)) and. _ = diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index b43de49332..2768b3b8e2 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -317,6 +317,9 @@ let forms: list((string, t)) = [ "type_alias", mk(ds, ["type", "=", "in"], mk_pre(P.let_, Exp, [TPat, Typ])), ), + ("tuple_label_exp", mk(ss, ["="], mk_bin'(P.ann, Exp, Pat, [], Exp))), // TODO: Rename + ("tuple_label_pat", mk(ss, ["="], mk_bin'(P.ann, Pat, Pat, [], Pat))), // TODO: Rename + ("tuple_label_typ", mk(ss, ["="], mk_bin'(P.ann, Typ, Pat, [], Typ))), // TODO: Rename ("if_", mk(ds, ["if", "then", "else"], mk_pre(P.if_, Exp, [Exp, Exp]))), ]; diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index 8fe8174dde..ff305e1a61 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -213,6 +213,15 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { } | _ => ret(hole(tm)) } + | Bin(Pat(p), tiles, Exp(e)) as tm => + switch (tiles) { + | ([(_id, (["="], []))], []) => + switch (p.term) { + | Var(s) => ret(TupLabel(s, e)) + | _ => ret(hole(tm)) + } + | _ => ret(hole(tm)) + } | Bin(Exp(l), tiles, Exp(r)) as tm => switch (is_tuple_exp(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) @@ -321,6 +330,11 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) | None => switch (tiles) { + | ([(_id, (["="], []))], []) => + switch (l.term) { + | Var(s) => ret(TupLabel(s, r)) + | _ => ret(hole(tm)) + } | ([(_id, (["::"], []))], []) => ret(Cons(l, r)) | _ => ret(hole(tm)) } @@ -378,6 +392,15 @@ and typ_term: unsorted => (UTyp.term, list(Id.t)) = { ret(Sum(List.map(parse_sum_term, [t1] @ between_kids @ [t2]))) | None => ret(hole(tm)) } + | Bin(Pat(p), tiles, Typ(t)) as tm => + switch (tiles) { + | ([(_id, (["="], []))], []) => + switch (p.term) { + | Var(s) => ret(TupLabel(s, t)) + | _ => ret(hole(tm)) + } + | _ => ret(hole(tm)) + } | Bin(Typ(l), tiles, Typ(r)) as tm => switch (is_tuple_typ(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index f8dc127b9f..df8d3f814c 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -39,11 +39,18 @@ let of_arrow = (ctx: Ctx.t, mode: t): (t, t) => | Ana(ty) => ty |> Typ.matched_arrow(ctx) |> TupleUtil.map2(ana) }; -let of_prod = (ctx: Ctx.t, mode: t, length): list(t) => +let of_label = (ctx: Ctx.t, mode: t): t => switch (mode) { | Syn - | SynFun => List.init(length, _ => Syn) - | Ana(ty) => ty |> Typ.matched_prod(ctx, length) |> List.map(ana) + | SynFun => Syn + | Ana(ty) => ty |> Typ.matched_label(ctx) |> ana + }; + +let of_prod = (ctx: Ctx.t, mode: t, ts: list('a), filt): list(t) => + switch (mode) { + | Syn + | SynFun => List.init(List.length(ts), _ => Syn) + | Ana(ty) => ty |> Typ.matched_prod(ctx, ts, filt) |> List.map(ana) }; let of_cons_hd = (ctx: Ctx.t, mode: t): t => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 11d68ff1f4..dcbbe821d0 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -246,8 +246,19 @@ and uexp_to_info_map = 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); + | TupLabel(s, e) => + let mode = Mode.of_label(ctx, mode); + let (e, m) = go(~mode, e, m); + add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); | Tuple(es) => - let modes = Mode.of_prod(ctx, mode, List.length(es)); + let filt: UExp.t => option(LabeledTuple.t) = ( + e => + switch (e.term) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let modes = Mode.of_prod(ctx, mode, es, filt); let (es, m) = map_m_go(m, modes, es); add( ~self=Just(Prod(List.map(Info.exp_ty, es))), @@ -486,8 +497,19 @@ and upat_to_info_map = 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); + | TupLabel(s, p) => + let mode = Mode.of_label(ctx, mode); + let (p, m) = go(~ctx, ~mode, p, m); + add(~self=Just(Label(s, p.ty)), ~ctx=p.ctx, m); | Tuple(ps) => - let modes = Mode.of_prod(ctx, mode, List.length(ps)); + let filt: UPat.t => option(LabeledTuple.t) = ( + p => + switch (p.term) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let modes = Mode.of_prod(ctx, mode, ps, filt); let (ctx, tys, m) = ctx_fold(ctx, m, ps, modes); add(~self=Just(Prod(tys)), ~ctx, m); | Parens(p) => @@ -538,6 +560,7 @@ and utyp_to_info_map = /* Names are resolved in Info.status_typ */ add(m) | List(t) + | TupLabel(_, t) | Parens(t) => add(go(t, m) |> snd) | Arrow(t1, t2) => let m = go(t1, m) |> snd; diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index a21a2cf596..d7ebee7701 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -30,6 +30,7 @@ module UTyp = { | Bool | String | Arrow + | TupLabel | Tuple | Sum | List @@ -64,6 +65,7 @@ module UTyp = { | Arrow(_) => Arrow | Var(_) => Var | Constructor(_) => Constructor + | TupLabel(_) => TupLabel | Tuple(_) => Tuple | Parens(_) => Parens | Ap(_) => Ap @@ -82,6 +84,7 @@ module UTyp = { | Constructor => "Sum constructor" | List => "List type" | Arrow => "Function type" + | TupLabel => "Labeled Tuple Item type" | Tuple => "Product type" | Sum => "Sum type" | Parens => "Parenthesized type" @@ -90,6 +93,7 @@ module UTyp = { let rec is_arrow = (typ: t) => { switch (typ.term) { | Parens(typ) => is_arrow(typ) + | TupLabel(_, typ) => is_arrow(typ) | Arrow(_) => true | Invalid(_) | EmptyHole @@ -124,6 +128,7 @@ module UTyp = { | None => Unknown(Free(name)) } | Arrow(u1, u2) => Arrow(to_typ(ctx, u1), to_typ(ctx, u2)) + | TupLabel(s, ut) => Label(s, to_typ(ctx, ut)) | Tuple(us) => Prod(List.map(to_typ(ctx), us)) | Sum(uts) => Sum(to_ctr_map(ctx, uts)) | List(u) => List(to_typ(ctx, u)) @@ -201,6 +206,7 @@ module UPat = { | Constructor | Cons | Var + | TupLabel | Tuple | Parens | Ap @@ -234,6 +240,7 @@ module UPat = { | Constructor(_) => Constructor | Cons(_) => Cons | Var(_) => Var + | TupLabel(_) => TupLabel | Tuple(_) => Tuple | Parens(_) => Parens | Ap(_) => Ap @@ -254,6 +261,7 @@ module UPat = { | Constructor => "Constructor" | Cons => "Cons" | Var => "Variable binding" + | TupLabel => "Labeled Tuple Item pattern" | Tuple => "Tuple" | Parens => "Parenthesized pattern" | Ap => "Constructor application" @@ -262,6 +270,7 @@ module UPat = { let rec is_var = (pat: t) => { switch (pat.term) { | Parens(pat) => is_var(pat) + | TupLabel(_, pat) => is_var(pat) | Var(_) => true | TypeAnn(_) | Invalid(_) @@ -284,6 +293,7 @@ module UPat = { let rec is_fun_var = (pat: t) => { switch (pat.term) { | Parens(pat) => is_fun_var(pat) + | TupLabel(_, pat) => is_fun_var(pat) | TypeAnn(pat, typ) => is_var(pat) && UTyp.is_arrow(typ) | Invalid(_) | EmptyHole @@ -308,6 +318,7 @@ module UPat = { || ( switch (pat.term) { | Parens(pat) => is_tuple_of_arrows(pat) + | TupLabel(_, pat) => is_tuple_of_arrows(pat) | Tuple(pats) => pats |> List.for_all(is_fun_var) | Invalid(_) | EmptyHole @@ -330,6 +341,7 @@ module UPat = { let rec get_var = (pat: t) => { switch (pat.term) { | Parens(pat) => get_var(pat) + | TupLabel(_, pat) => get_var(pat) | Var(x) => Some(x) | TypeAnn(_) | Invalid(_) @@ -352,6 +364,7 @@ module UPat = { let rec get_fun_var = (pat: t) => { switch (pat.term) { | Parens(pat) => get_fun_var(pat) + | TupLabel(_, pat) => get_fun_var(pat) | TypeAnn(pat, typ) => if (UTyp.is_arrow(typ)) { get_var(pat) |> Option.map(var => var); @@ -382,6 +395,7 @@ module UPat = { | None => switch (pat.term) { | Parens(pat) => get_recursive_bindings(pat) + | TupLabel(_, pat) => get_recursive_bindings(pat) | Tuple(pats) => let fun_vars = pats |> List.map(get_fun_var); if (List.exists(Option.is_none, fun_vars)) { @@ -431,6 +445,7 @@ module UExp = { | ListLit | Constructor | Fun + | TupLabel | Tuple | Var | MetaVar @@ -473,6 +488,7 @@ module UExp = { | ListLit(_) => ListLit | Constructor(_) => Constructor | Fun(_) => Fun + | TupLabel(_, _) => TupLabel | Tuple(_) => Tuple | Var(_) => Var | Let(_) => Let @@ -566,6 +582,7 @@ module UExp = { | ListLit => "List literal" | Constructor => "Constructor" | Fun => "Function literal" + | TupLabel => "Labeled Tuple literal" | Tuple => "Tuple literal" | Var => "Variable reference" | MetaVar => "Meta variable reference" @@ -587,6 +604,7 @@ module UExp = { let rec is_fun = (e: t) => { switch (e.term) { | Parens(e) => is_fun(e) + | TupLabel(_, e) => is_fun(e) | Fun(_) => true | Invalid(_) | EmptyHole @@ -621,6 +639,7 @@ module UExp = { || ( switch (e.term) { | Parens(e) => is_tuple_of_functions(e) + | TupLabel(_, e) => is_tuple_of_functions(e) | Tuple(es) => es |> List.for_all(is_fun) | Invalid(_) | EmptyHole diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index e0f756b0dd..d9525003eb 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -115,6 +115,7 @@ and UExp: { | ListLit | Tag | Fun + | TupLabel | Tuple | Var | Let @@ -143,6 +144,7 @@ and UExp: { | ListLit(list(t)) | Constructor(string) | Fun(UPat.t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Var(Var.t) | Let(UPat.t, t, t) @@ -246,6 +248,7 @@ and UExp: { | ListLit | Tag | Fun + | TupLabel | Tuple | Var | Let @@ -274,6 +277,7 @@ and UExp: { | ListLit(list(t)) | Constructor(string) | Fun(UPat.t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Var(Var.t) | Let(UPat.t, t, t) @@ -358,6 +362,7 @@ and UPat: { | Constructor(string) | Cons(t, t) | Var(Var.t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Parens(t) | Ap(t, t) @@ -382,6 +387,7 @@ and UPat: { | Constructor(string) | Cons(t, t) | Var(Var.t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Parens(t) | Ap(t, t) @@ -405,6 +411,7 @@ and UTyp: { | Var(string) | Constructor(string) | Arrow(t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Parens(t) | Ap(t, t) @@ -430,6 +437,7 @@ and UTyp: { | Var(string) | Constructor(string) | Arrow(t, t) + | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) | Parens(t) | Ap(t, t) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 15620b1ac9..9a0807f52d 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -33,6 +33,7 @@ module rec Typ: { | Sum(sum_map) | Prod(list(t)) | Rec(TypVar.t, t) + | Label(string, t) and sum_map = ConstructorMap.t(option(t)); [@deriving (show({with_path: false}), sexp, yojson)] @@ -52,7 +53,9 @@ module rec Typ: { let join_type_provenance: (type_provenance, type_provenance) => type_provenance; let matched_arrow: (Ctx.t, t) => (t, t); - let matched_prod: (Ctx.t, int, t) => list(t); + let matched_label: (Ctx.t, t) => t; + let matched_prod: + (Ctx.t, list('a), 'a => option(LabeledTuple.t), t) => list(t); let matched_list: (Ctx.t, t) => t; let precedence: t => int; let subst: (t, TypVar.t, t) => t; @@ -90,6 +93,7 @@ module rec Typ: { | Sum(sum_map) | Prod(list(t)) | Rec(TypVar.t, t) + | Label(string, t) and sum_map = ConstructorMap.t(option(t)); [@deriving (show({with_path: false}), sexp, yojson)] @@ -130,6 +134,7 @@ module rec Typ: { | Unknown(_) | Var(_) | Rec(_) + | Label(_, _) => precedence_Sum | Sum(_) => precedence_Sum | List(_) => precedence_Const | Prod(_) => precedence_Prod @@ -150,6 +155,7 @@ module rec Typ: { | 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) + | Label(st, ty) => Label(st, subst(s, x, ty)) }; }; @@ -163,6 +169,9 @@ module rec Typ: { but this will change when polymorphic types are implemented */ let rec eq = (t1: t, t2: t): bool => { switch (t1, t2) { + | (Label(s1, t1), Label(s2, t2)) => compare(s1, s2) == 0 && eq(t1, t2) + | (Label(_, t1), t2) => eq(t1, t2) + | (t1, Label(_, t2)) => eq(t1, t2) | (Rec(x1, t1), Rec(x2, t2)) => eq(t1, subst(Var(x1), x2, t2)) | (Rec(_), _) => false | (Int, Int) => true @@ -177,7 +186,22 @@ module rec Typ: { | (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(tys1), Prod(tys2)) => + let filt: t => option(LabeledTuple.t) = ( + d => + switch (d) { + | Label(s, _) => Some(s) + | _ => None + } + ); + let f = (b, tys1_val, tys2_val) => { + switch (b) { + | false => false + | true => eq(tys1_val, tys2_val) + }; + }; + List.length(tys1) == List.length(tys2) + && LabeledTuple.ana_tuple(filt, filt, f, true, false, tys1, tys2); | (Prod(_), _) => false | (List(t1), List(t2)) => eq(t1, t2) | (List(_), _) => false @@ -208,6 +232,7 @@ module rec Typ: { ) | Prod(tys) => ListUtil.flat_map(free_vars(~bound), tys) | Rec(x, ty) => free_vars(~bound=[x, ...bound], ty) + | Label(_, ty) => free_vars(~bound, ty) }; /* Lattice join on types. This is a LUB join in the hazel2 @@ -255,6 +280,19 @@ module rec Typ: { let+ ty_body = join(~resolve, ~fix, ctx, ty1, subst(Var(x1), x2, ty2)); Rec(x1, ty_body); + | (Label(s1, ty1), Label(s2, ty2)) => + if (compare(s1, s2) == 0) { + let+ ty = join'(ty1, ty2); + Label(s1, ty); + } else { + None; + } + | (Label(s1, ty1), ty2) => + let+ ty = join'(ty1, ty2); + Label(s1, ty); + | (ty1, Label(s2, ty2)) => + let+ ty = join'(ty1, ty2); + Label(s2, ty); | (Rec(_), _) => None | (Int, Int) => Some(Int) | (Int, _) => None @@ -270,9 +308,68 @@ module rec Typ: { Arrow(ty1, ty2); | (Arrow(_), _) => None | (Prod(tys1), Prod(tys2)) => - let* tys = ListUtil.map2_opt(join', tys1, tys2); - let+ tys = OptUtil.sequence(tys); - Prod(tys); + let filt: t => option(LabeledTuple.t) = ( + d => + switch (d) { + | Label(s, _) => Some(s) + | _ => None + } + ); + let filt2: t => (option(LabeledTuple.t), t) = ( + d => + switch (d) { + | Label(s, ty) => (Some(s), ty) + | ty => (None, ty) + } + ); + //TODO (Anthony): Clean up the repetition + let (l1_valid, _, l1_none) = + LabeledTuple.validate_uniqueness(filt, tys1); + let (l2_valid, l2_lab, l2_none) = + LabeledTuple.validate_uniqueness(filt, tys2); + // TODO (Anthony): clean up error handling + if (!l1_valid + || !l2_valid + || List.length(l1_none) != List.length(l2_none)) { + let* tys = Some(List.init(List.length(tys1), _ => None)); + let+ tys = OptUtil.sequence(tys); + Prod(tys); + } else { + let l1 = List.map(filt2, tys1); + let rec f = + (l1: list('a), l2_lab: list('a), l2_none: list('b)) + : list(option(t)) => + switch (l1) { + | [hd, ...tl] => + switch (hd) { + | (Some(s1), l1_val) => + let l2_item = + List.find_opt( + l2_item => { + switch (l2_item) { + | (Some(s2), _) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l2_item) { + | Some((_, l2_val)) => + [join'(l1_val, l2_val)] @ f(tl, l2_lab, l2_none) + | None => [None] @ f(tl, l2_lab, l2_none) + }; + | (None, l1_val) => + switch (l2_none) { + | [t2, ...tl2] => [join'(l1_val, t2)] @ f(tl, l2_lab, tl2) + | [] => [None] @ f(tl, l2_lab, l2_none) + } + } + | [] => [] + }; + let* tys = Some(f(l1, l2_lab, l2_none)); + let+ tys = OptUtil.sequence(tys); + Prod(tys); + }; | (Prod(_), _) => None | (Sum(sm1), Sum(sm2)) => let (sorted1, sorted2) = @@ -355,6 +452,7 @@ module rec Typ: { 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)) + | Label(s, t) => Label(s, normalize(ctx, t)) }; }; @@ -365,12 +463,81 @@ module rec Typ: { | _ => (Unknown(Internal), Unknown(Internal)) }; - let matched_prod = (ctx, length, ty) => + let matched_label = (ctx, ty) => + switch (weak_head_normalize(ctx, ty)) { + | Label(_, ty) => ty + | Unknown(SynSwitch) => Unknown(SynSwitch) + | _ => Unknown(Internal) + }; + + let matched_prod = (ctx, ts, filt, ty) => { + // TODO: rearrange tys to fit ts + //TODO (Anthony): Clean up the repetition + let filt2 = d => + switch (d) { + | Label(s, _) => Some(s) + | _ => None + }; switch (weak_head_normalize(ctx, ty)) { - | Prod(tys) when List.length(tys) == length => tys - | Unknown(SynSwitch) => List.init(length, _ => Unknown(SynSwitch)) - | _ => List.init(length, _ => Unknown(Internal)) + | Prod(tys) + when + List.length(tys) == List.length(ts) + && LabeledTuple.ana_tuple( + filt, + filt2, + (a, _, _) => a, + true, + false, + ts, + tys, + ) => + let (l1_valid, _, l1_none) = + LabeledTuple.validate_uniqueness(filt, ts); + let (l2_valid, l2_lab, l2_none) = + LabeledTuple.validate_uniqueness(filt2, tys); + if (!l1_valid + || !l2_valid + || List.length(l1_none) != List.length(l2_none)) { + List.init(List.length(ts), _ => Unknown(Internal)); + } else { + print_endline("of_prod"); + let rec f = + (l1: list('a), l2_lab: list('b), l2_none: list('c)) + : list(t) => + switch (l1) { + | [hd, ...tl] => + switch (filt(hd)) { + | Some(s1) => + let l2_item = + List.find_opt( + l2_item => { + switch (l2_item) { + | (Some(s2), _) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l2_item) { + | Some((_, l2_val)) => [l2_val] @ f(tl, l2_lab, l2_none) + | None => [Unknown(Internal)] @ f(tl, l2_lab, l2_none) + }; + | None => + switch (l2_none) { + | [t2, ...tl2] => [t2] @ f(tl, l2_lab, tl2) + | [] => [Unknown(Internal)] @ f(tl, l2_lab, l2_none) + } + } + | [] => [] + }; + let tys = f(ts, l2_lab, l2_none); + tys; + }; + | Unknown(SynSwitch) => + List.init(List.length(ts), _ => Unknown(SynSwitch)) + | _ => List.init(List.length(ts), _ => Unknown(Internal)) }; + }; let matched_list = (ctx, ty) => switch (weak_head_normalize(ctx, ty)) { diff --git a/src/haz3lcore/zipper/EditorUtil.re b/src/haz3lcore/zipper/EditorUtil.re index 0f4d093980..e22e5f6285 100644 --- a/src/haz3lcore/zipper/EditorUtil.re +++ b/src/haz3lcore/zipper/EditorUtil.re @@ -54,6 +54,7 @@ let rec append_exp = (e1: TermBase.UExp.t, e2: TermBase.UExp.t) => { | ListLit(_) | Constructor(_) | Fun(_) + | TupLabel(_) | Tuple(_) | Var(_) | Ap(_) diff --git a/src/haz3lschool/SyntaxTest.re b/src/haz3lschool/SyntaxTest.re index 110e1c1051..992a286885 100644 --- a/src/haz3lschool/SyntaxTest.re +++ b/src/haz3lschool/SyntaxTest.re @@ -21,6 +21,7 @@ let rec find_var_upat = (name: string, upat: Term.UPat.t): bool => { | String(_) | Constructor(_) => false | Cons(up1, up2) => find_var_upat(name, up1) || find_var_upat(name, up2) + | TupLabel(_, up) => find_var_upat(name, up) | ListLit(l) | Tuple(l) => List.fold_left((acc, up) => {acc || find_var_upat(name, up)}, false, l) @@ -50,6 +51,7 @@ let rec var_mention = (name: string, uexp: Term.UExp.t): bool => { | Let(p, def, body) => find_var_upat(name, p) ? false : var_mention(name, def) || var_mention(name, body) + | TupLabel(_, u) | Test(u) | Parens(u) | UnOp(_, u) @@ -100,6 +102,7 @@ let rec var_applied = (name: string, uexp: Term.UExp.t): bool => { | Parens(u) | UnOp(_, u) | TyAlias(_, _, u) + | TupLabel(_, u) | Filter(_, _, u) => var_applied(name, u) | Ap(u1, u2) => switch (u1.term) { @@ -149,6 +152,8 @@ let rec find_in_let = } else { l; } + | (TupLabel(_, up), TupLabel(_, ue)) => find_in_let(name, up, ue, l) + | (TupLabel(_, up), _) => find_in_let(name, up, def, l) | (Tuple(pl), Tuple(ul)) => if (List.length(pl) != List.length(ul)) { l; @@ -185,6 +190,7 @@ let rec find_fn = | Tuple(ul) => List.fold_left((acc, u1) => {find_fn(name, u1, acc)}, l, ul) | Fun(_, body) => l |> find_fn(name, body) + | TupLabel(_, u1) | Parens(u1) | UnOp(_, u1) | TyAlias(_, _, u1) @@ -255,6 +261,7 @@ let rec tail_check = (name: string, uexp: Term.UExp.t): bool => { | Test(_) => false | TyAlias(_, _, u) | Filter(_, _, u) + | TupLabel(_, u) => tail_check(name, u) | Parens(u) => tail_check(name, u) | UnOp(_, u) => !var_mention(name, u) | Ap(u1, u2) => var_mention(name, u2) ? false : tail_check(name, u1) diff --git a/src/haz3lweb/view/ExplainThis.re b/src/haz3lweb/view/ExplainThis.re index bce9f160f4..0a41e239ab 100644 --- a/src/haz3lweb/view/ExplainThis.re +++ b/src/haz3lweb/view/ExplainThis.re @@ -686,6 +686,8 @@ let get_doc = switch (term) { | TermBase.UExp.Invalid(_) => simple("Not a valid expression") | EmptyHole => get_message(HoleExp.empty_hole_exps) + // TODO (Anthony): put in a real message + | TupLabel(_, _) => get_message(HoleExp.empty_hole_exps) | MultiHole(_children) => get_message(HoleExp.multi_hole_exps) | TyAlias(ty_pat, ty_def, _body) => let tpat_id = List.nth(ty_pat.ids, 0); @@ -744,6 +746,8 @@ let get_doc = let pat_id = List.nth(pat.ids, 0); let body_id = List.nth(body.ids, 0); switch (pat.term) { + // TODO (Anthony): put in a real message + | TupLabel(_, _) | EmptyHole => if (FunctionExp.function_empty_hole_exp.id == get_specificity_level(FunctionExp.functions_empty_hole)) { @@ -1268,6 +1272,8 @@ let get_doc = ); }; switch (pat.term) { + // TODO (Anthony): put in a real message + | TupLabel(_, _) | EmptyHole => if (LetExp.let_empty_hole_exp.id == get_specificity_level(LetExp.lets_emptyhole)) { @@ -1957,6 +1963,8 @@ let get_doc = get_message_exp(term.term); | Some(InfoPat({term, _})) => switch (bypass_parens_pat(term).term) { + // TODO (Anthony): put in a real message + | TupLabel(_, _) | EmptyHole => get_message(HolePat.empty_hole) | MultiHole(_) => get_message(HolePat.multi_hole) | Wild => get_message(TerminalPat.wild) @@ -2180,6 +2188,8 @@ let get_doc = } | Some(InfoTyp({term, cls, _})) => switch (bypass_parens_typ(term).term) { + // TODO (Anthony): put in a real message + | TupLabel(_, _) | EmptyHole => get_message(HoleTyp.empty_hole) | MultiHole(_) => get_message(HoleTyp.multi_hole) | Int => get_message(TerminalTyp.int) diff --git a/src/haz3lweb/view/Type.re b/src/haz3lweb/view/Type.re index ae88419f0e..b8b32cb3be 100644 --- a/src/haz3lweb/view/Type.re +++ b/src/haz3lweb/view/Type.re @@ -34,6 +34,7 @@ let rec view_ty = (ty: Haz3lcore.Typ.t): Node.t => | String => ty_view("String", "String") | Bool => ty_view("Bool", "Bool") | Var(name) => ty_view("Var", name) + | Label(_, ty) => view_ty(ty) // TODO (Anthony): What to do here? | Rec(x, t) => div( ~attr=clss(["typ-view", "Rec"]), diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index 310ce39e2c..12ab56da7a 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -71,6 +71,8 @@ let rec precedence = (~show_casts: bool, d: DHExp.t) => { | ApBuiltin(_) => DHDoc_common.precedence_Ap | Cons(_) => DHDoc_common.precedence_Cons | ListConcat(_) => DHDoc_common.precedence_Plus + // TODO (Anthony): what should this be? + | TupLabel(_) => DHDoc_common.precedence_Comma | Tuple(_) => DHDoc_common.precedence_Comma | Fun(_) => DHDoc_common.precedence_max | Let(_) @@ -411,6 +413,13 @@ let mk = (d2, BinBoolOp2), ); hseps([doc1, mk_bin_bool_op(op), doc2]); + // TODO(Anthony): what to do here? + | TupLabel(s, d) => + Doc.hcats([ + Doc.text(s), + DHDoc_common.Delim.mk("="), + go'(d, TupLabel), + ]) | Tuple([]) => DHDoc_common.Delim.triv | Tuple(ds) => DHDoc_common.mk_Tuple(ds |> List.mapi((i, d) => go'(d, Tuple(i)))) diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re index c27aa21b07..5fadbb7915 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re @@ -16,6 +16,7 @@ let precedence = (dp: DHPat.t) => | StringLit(_) | ListLit(_) | Constructor(_) => DHDoc_common.precedence_const + | TupLabel(_, _) => DHDoc_common.precedence_Comma | Tuple(_) => DHDoc_common.precedence_Comma | Cons(_) => DHDoc_common.precedence_Cons | Ap(_) => DHDoc_common.precedence_Ap @@ -55,6 +56,9 @@ let rec mk = let (doc1, doc2) = mk_right_associative_operands(DHDoc_common.precedence_Cons, dp1, dp2); DHDoc_common.mk_Cons(doc1, doc2); + // TODO (Anthony): What to do for Tuplabel? + | TupLabel(s, d) => + Doc.hcats([Doc.text(s), DHDoc_common.Delim.mk("="), mk'(d)]) | Tuple([]) => DHDoc_common.Delim.triv | Tuple(ds) => DHDoc_common.mk_Tuple(List.map(mk', ds)) | Ap(dp1, dp2) => diff --git a/src/haz3lweb/view/dhcode/layout/HTypDoc.re b/src/haz3lweb/view/dhcode/layout/HTypDoc.re index 8acbc0455f..b3db08521a 100644 --- a/src/haz3lweb/view/dhcode/layout/HTypDoc.re +++ b/src/haz3lweb/view/dhcode/layout/HTypDoc.re @@ -51,6 +51,7 @@ let rec mk = (~parenthesize=false, ~enforce_inline: bool, ty: Typ.t): t => { | Bool => (text("Bool"), parenthesize) | String => (text("String"), parenthesize) | Var(name) => (text(name), parenthesize) + | Label(_, ty) => (mk'(ty), parenthesize) // TODO (Anthony): What to do here? | List(ty) => ( hcats([ mk_delim("["), From c137ded8ac535badd7deda18c6aef1a7b0b13155 Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 22 Mar 2024 20:20:37 -0400 Subject: [PATCH 002/108] working dot operator + bug fixes to precedence --- src/haz3lcore/LabeledTuple.re | 35 ++++++++++++++- src/haz3lcore/dynamics/DH.re | 7 +++ src/haz3lcore/dynamics/Elaborator.re | 4 ++ src/haz3lcore/dynamics/EvalCtx.re | 3 ++ src/haz3lcore/dynamics/EvaluatorPost.re | 9 ++++ src/haz3lcore/dynamics/EvaluatorStep.re | 3 ++ src/haz3lcore/dynamics/FilterMatcher.re | 4 ++ src/haz3lcore/dynamics/PatternMatch.re | 3 ++ src/haz3lcore/dynamics/Stepper.re | 4 ++ src/haz3lcore/dynamics/Substitution.re | 3 +- src/haz3lcore/dynamics/Transition.re | 27 ++++++++++++ src/haz3lcore/lang/Form.re | 12 ++++-- src/haz3lcore/lang/Precedence.re | 43 ++++++++++--------- src/haz3lcore/statics/MakeTerm.re | 23 ++++++++++ src/haz3lcore/statics/Statics.re | 19 ++++++++ src/haz3lcore/statics/Term.re | 5 +++ src/haz3lcore/statics/TermBase.re | 4 ++ src/haz3lcore/statics/TypBase.re | 1 - src/haz3lcore/zipper/EditorUtil.re | 1 + src/haz3lschool/SyntaxTest.re | 4 ++ src/haz3lweb/view/ExplainThis.re | 1 + src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 10 +++++ .../view/dhcode/layout/DHDoc_common.re | 1 + .../view/dhcode/layout/DHDoc_common.rei | 1 + 24 files changed, 198 insertions(+), 29 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 171ed78c80..412b4cf1e7 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -60,8 +60,8 @@ let validate_uniqueness: // Checks remaining None pairs in order and performs f on each pair let ana_tuple: ( - 'b => option(string), - 'c => option(string), + 'b => option(t), + 'c => option(t), ('a, 'b, 'c) => 'a, 'a, 'a, @@ -132,3 +132,34 @@ let ana_tuple: accu; }; }; + +let find_label: ('a => option(t), list('a), t) => option('a) = + (filt, es, label) => { + List.find_opt( + e => { + switch (filt(e)) { + | Some(s) => compare(s, label) == 0 + | None => false + } + }, + es, + ); + }; + +let extract_item: ('a => option(t), list('a), t, 'b) => 'b = + (filt, es, label, none_val) => { + let opt = + List.find_opt( + e => { + switch (filt(e)) { + | Some(s) => compare(s, label) == 0 + | None => false + } + }, + es, + ); + switch (opt) { + | Some(some) => some + | None => none_val + }; + }; diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index de9899d7e5..05d73a8f54 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -38,6 +38,7 @@ module rec DHExp: { | ListConcat(t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) + | Dot(t, LabeledTuple.t) | Prj(t, int) | Constructor(string) | ConsistentCase(case) @@ -96,6 +97,7 @@ module rec DHExp: { | ListConcat(t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) + | Dot(t, LabeledTuple.t) | Prj(t, int) | Constructor(string) | ConsistentCase(case) @@ -139,6 +141,7 @@ module rec DHExp: { | ListConcat(_, _) => "ListConcat" | TupLabel(_) => "Labeled Tuple Item" | Tuple(_) => "Tuple" + | Dot(_) => "DotOp" | Prj(_) => "Prj" | Constructor(_) => "Constructor" | ConsistentCase(_) => "ConsistentCase" @@ -172,6 +175,7 @@ module rec DHExp: { | FailedCast(d, _, _) => strip_casts(d) | TupLabel(s, d) => TupLabel(s, strip_casts(d)) | Tuple(ds) => Tuple(ds |> List.map(strip_casts)) + | Dot(d, s) => Dot(strip_casts(d), s) | Prj(d, n) => Prj(strip_casts(d), n) | Cons(d1, d2) => Cons(strip_casts(d1), strip_casts(d2)) | ListConcat(d1, d2) => ListConcat(strip_casts(d1), strip_casts(d2)) @@ -268,6 +272,8 @@ module rec DHExp: { }; List.length(ds1) == List.length(ds2) && LabeledTuple.ana_tuple(filt, filt, f, true, false, ds1, ds2); + | (Dot(d1, s1), Dot(d2, s2)) => + LabeledTuple.compare(s1, s2) == 0 && d1 == d2 | (Prj(d1, n), Prj(d2, m)) => n == m && fast_equal(d1, d2) | (ApBuiltin(f1, d1), ApBuiltin(f2, d2)) => f1 == f2 && d1 == d2 | (BuiltinFun(f1), BuiltinFun(f2)) => f1 == f2 @@ -310,6 +316,7 @@ module rec DHExp: { | (ListLit(_), _) | (TupLabel(_, _), _) | (Tuple(_), _) + | (Dot(_), _) | (Prj(_), _) | (BinBoolOp(_), _) | (BinIntOp(_), _) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index d30525efe2..49ce3e8d7f 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -103,6 +103,7 @@ let cast = (ctx: Ctx.t, mode: Mode.t, self_ty: Typ.t, d: DHExp.t) => | BinIntOp(_) | BinFloatOp(_) | BinStringOp(_) + | Dot(_) | Test(_) => DHExp.cast(d, self_ty, ana_ty) }; }; @@ -161,6 +162,9 @@ let rec dhexp_of_uexp = | Tuple(es) => let+ ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; DHExp.Tuple(ds); + | Dot(e, s) => + let+ de = dhexp_of_uexp(m, e); + DHExp.Dot(de, s); | Cons(e1, e2) => let* dc1 = dhexp_of_uexp(m, e1); let+ dc2 = dhexp_of_uexp(m, e2); diff --git a/src/haz3lcore/dynamics/EvalCtx.re b/src/haz3lcore/dynamics/EvalCtx.re index 5bde0655cb..d8b6301c87 100644 --- a/src/haz3lcore/dynamics/EvalCtx.re +++ b/src/haz3lcore/dynamics/EvalCtx.re @@ -28,6 +28,7 @@ type cls = | IfThenElse3 | TupLabel | Tuple(int) + | Dot | ListLit(int) | ApBuiltin | Test @@ -74,6 +75,7 @@ type t = | BinStringOp2(TermBase.UExp.op_bin_string, DHExp.t, t) | TupLabel(LabeledTuple.t, t) | Tuple(t, (list(DHExp.t), list(DHExp.t))) + | Dot(t, LabeledTuple.t) | ApBuiltin(string, t) | Test(KeywordID.t, t) | ListLit( @@ -141,6 +143,7 @@ let rec fuzzy_mark = | BinFloatOp2(_) | BinStringOp1(_) | BinStringOp2(_) + | Dot(_) | TupLabel(_) | Tuple(_) | ApBuiltin(_) diff --git a/src/haz3lcore/dynamics/EvaluatorPost.re b/src/haz3lcore/dynamics/EvaluatorPost.re index 8518f54730..b42d4d5a7e 100644 --- a/src/haz3lcore/dynamics/EvaluatorPost.re +++ b/src/haz3lcore/dynamics/EvaluatorPost.re @@ -128,6 +128,10 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => ); Tuple(ds); + | Dot(d1, s) => + let* d1' = pp_eval(d1); + Dot(d1', s) |> return; + | Prj(d, n) => let+ d = pp_eval(d); Prj(d, n); @@ -377,6 +381,10 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => ); Tuple(ds); + | Dot(d, s) => + let+ d = pp_uneval(env, d); + Dot(d, s); + | Prj(d, n) => let+ d = pp_uneval(env, d); Prj(d, n); @@ -475,6 +483,7 @@ let rec track_children_of_hole = | Cast(d, _, _) | FailedCast(d, _, _) | TupLabel(_, d) + | Dot(d, _) | InvalidOperation(d, _) => track_children_of_hole(hii, parent, d) | Sequence(d1, d2) | Let(_, d1, d2) diff --git a/src/haz3lcore/dynamics/EvaluatorStep.re b/src/haz3lcore/dynamics/EvaluatorStep.re index 2ba3f4155e..4472236a19 100644 --- a/src/haz3lcore/dynamics/EvaluatorStep.re +++ b/src/haz3lcore/dynamics/EvaluatorStep.re @@ -289,6 +289,9 @@ let rec compose = (ctx: EvalCtx.t, d: DHExp.t): DHExp.t => { | TupLabel(s, ctx) => let d2 = compose(ctx, d); TupLabel(s, d2); + | Dot(ctx, s) => + let d2 = compose(ctx, d); + Dot(d2, s); | Tuple(ctx, (ld, rd)) => let d = compose(ctx, d); Tuple(rev_concat(ld, [d, ...rd])); diff --git a/src/haz3lcore/dynamics/FilterMatcher.re b/src/haz3lcore/dynamics/FilterMatcher.re index d7872cb340..d080df58df 100644 --- a/src/haz3lcore/dynamics/FilterMatcher.re +++ b/src/haz3lcore/dynamics/FilterMatcher.re @@ -132,9 +132,13 @@ let rec matches_exp = ) | (ListLit(_), _) => false + // TODO (Anthony): Is this right? | (TupLabel(_, dv), TupLabel(_, fv)) => matches_exp(env, dv, fv) | (TupLabel(_), _) => false + | (Dot(dv, _), Dot(fv, _)) => matches_exp(env, dv, fv) + | (Dot(_), _) => false + | (Tuple(dv), Tuple(fv)) => List.fold_left2( (acc, d, f) => acc && matches_exp(env, d, f), diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 7348ebcd8c..8c38726d20 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -285,6 +285,7 @@ and matches_cast_Sum = | ListLit(_) | TupLabel(_, _) | Tuple(_) + | Dot(_, _) | Sequence(_, _) | Closure(_) | Filter(_) @@ -367,6 +368,7 @@ and matches_cast_Tuple = ); // What should TupLabel be? | TupLabel(_, _) => DoesNotMatch + | Dot(_, _) | Cast(_, _, _) => DoesNotMatch | BoundVar(_) => DoesNotMatch | FreeVar(_) => IndetMatch @@ -533,6 +535,7 @@ and matches_cast_Cons = | StringLit(_) => DoesNotMatch | TupLabel(_, _) => DoesNotMatch | Tuple(_) => DoesNotMatch + | Dot(_, _) => DoesNotMatch | Prj(_) => IndetMatch | Constructor(_) => DoesNotMatch | ConsistentCase(_) diff --git a/src/haz3lcore/dynamics/Stepper.re b/src/haz3lcore/dynamics/Stepper.re index fda7d7c6dc..66cfbc4903 100644 --- a/src/haz3lcore/dynamics/Stepper.re +++ b/src/haz3lcore/dynamics/Stepper.re @@ -122,6 +122,9 @@ let rec matches = | BinStringOp2(op, d1, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); BinStringOp2(op, d1, ctx); + | Dot(ctx, s) => + let+ ctx = matches(env, flt, ctx, exp, act, idx); + Dot(ctx, s); | TupLabel(s, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); TupLabel(s, ctx); @@ -406,6 +409,7 @@ let get_justification: step_kind => string = | BinStringOp(Equals) => "check equality" | BinStringOp(Concat) => "string manipulation" | BinBoolOp(_) => "boolean logic" + | Dot(_) => "dot operation" | Conditional(_) => "conditional" | ListCons => "list manipulation" | ListConcat => "list manipulation" diff --git a/src/haz3lcore/dynamics/Substitution.re b/src/haz3lcore/dynamics/Substitution.re index 078c1aaeb2..929d83ea8e 100644 --- a/src/haz3lcore/dynamics/Substitution.re +++ b/src/haz3lcore/dynamics/Substitution.re @@ -72,8 +72,9 @@ 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); ListConcat(d3, d4); - | TupLabel(p, d3) => TupLabel(p, subst_var(d1, x, d3)) + | TupLabel(p, d) => TupLabel(p, subst_var(d1, x, d)) | Tuple(ds) => Tuple(List.map(subst_var(d1, x), ds)) + | Dot(d, s) => Dot(subst_var(d1, x, d), s) | Prj(d, n) => Prj(subst_var(d1, x, d), n) | BinBoolOp(op, d3, d4) => let d3 = subst_var(d1, x, d3); diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index a4f074f606..fa4181c42b 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -61,6 +61,7 @@ type step_kind = | BinIntOp(TermBase.UExp.op_bin_int) | BinFloatOp(TermBase.UExp.op_bin_float) | BinStringOp(TermBase.UExp.op_bin_string) + | Dot(LabeledTuple.t) | Conditional(bool) | Projection | ListCons @@ -463,6 +464,31 @@ module Transition = (EV: EV_MODE) => { kind: BinStringOp(op), value: true, }); + | Dot(d, s) => + let. _ = otherwise(env, d => Dot(d, s)) + and. _ = req_value(req(state, env), d => Dot(d, s), d); + // TODO (Anthony): fix step if needed + Step({ + apply: () => + switch (d) { + | Tuple(ds) => + let filt: t => option(LabeledTuple.t) = ( + e => + switch (e) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let element = LabeledTuple.find_label(filt, ds, s); + switch (element) { + | Some(exp) => exp + | None => raise(EvaluatorError.Exception(BadPatternMatch)) + }; + | _ => raise(EvaluatorError.Exception(BadPatternMatch)) + }, + kind: Dot(s), + value: true, + }); | TupLabel(p, d1) => // TODO (Anthony): Fix this if needed let. _ = otherwise(env, d1 => TupLabel(p, d1)) @@ -661,6 +687,7 @@ let should_hide_step = (~settings: CoreSettings.Evaluation.t) => | BinIntOp(_) | BinFloatOp(_) | BinStringOp(_) + | Dot(_) | ListCons | ListConcat | CaseApply diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index 2768b3b8e2..d3e8f5a3ed 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -114,7 +114,8 @@ let is_reserved_keyword = /* Potential tokens: These are fallthrough classes which determine * the behavior when inserting a character in contact with a token */ -let is_potential_operand = regexp("^[a-zA-Z0-9_'\\.?]+$"); +let is_potential_operand = x => + regexp("^[a-zA-Z0-9_'?]+$", x) || regexp("^[0-9_'\\.?]+$", x); /* Anything else is considered a potential operator, as long * as it does not contain any whitespace, linebreaks, comment * delimiters, string delimiters, or the instant expanding paired @@ -277,6 +278,12 @@ let forms: list((string, t)) = [ ("cons_exp", mk_infix("::", Exp, P.cons)), ("cons_pat", mk_infix("::", Pat, P.cons)), ("typeann", mk(ss, [":"], mk_bin'(P.ann, Pat, Pat, [], Typ))), + ("tuple_label_exp", mk(ss, ["="], mk_bin'(P.ann, Exp, Pat, [], Exp))), // TODO: Rename + ("tuple_label_pat", mk(ss, ["="], mk_bin'(P.ann, Pat, Pat, [], Pat))), // TODO: Rename + ("tuple_label_typ", mk(ss, ["="], mk_bin'(P.ann, Typ, Pat, [], Typ))), // TODO: Rename + ("dot_exp", mk(ss, ["."], mk_bin'(P.dot, Exp, Exp, [], Pat))), // TODO: Check precedence + // ("dot_pat", mk(ss, ["."], mk_bin'(P.dot, Pat, Pat, [], Pat))), // Only for exp? + // ("dot_typ", mk(ss, ["."], mk_bin'(P.dot, Typ, Typ, [], Pat))), // Only for exp? // UNARY PREFIX OPERATORS ("not", mk(ii, ["!"], mk_pre(5, Exp, []))), //TODO: precedence ("typ_sum_single", mk(ss, ["+"], mk_pre(P.or_, Typ, []))), @@ -317,9 +324,6 @@ let forms: list((string, t)) = [ "type_alias", mk(ds, ["type", "=", "in"], mk_pre(P.let_, Exp, [TPat, Typ])), ), - ("tuple_label_exp", mk(ss, ["="], mk_bin'(P.ann, Exp, Pat, [], Exp))), // TODO: Rename - ("tuple_label_pat", mk(ss, ["="], mk_bin'(P.ann, Pat, Pat, [], Pat))), // TODO: Rename - ("tuple_label_typ", mk(ss, ["="], mk_bin'(P.ann, Typ, Pat, [], Typ))), // TODO: Rename ("if_", mk(ds, ["if", "then", "else"], mk_pre(P.if_, Exp, [Exp, Exp]))), ]; diff --git a/src/haz3lcore/lang/Precedence.re b/src/haz3lcore/lang/Precedence.re index b7d00796a5..41da1f8ed5 100644 --- a/src/haz3lcore/lang/Precedence.re +++ b/src/haz3lcore/lang/Precedence.re @@ -11,28 +11,29 @@ let max: t = 0; let unquote = 1; let ap = 2; -let neg = 3; -let power = 4; -let mult = 5; -let plus = 6; -let cons = 7; -let concat = 8; -let eqs = 9; -let and_ = 10; -let or_ = 11; -let ann = 12; -let if_ = 13; -let fun_ = 14; -let prod = 15; -let semi = 16; -let let_ = 17; -let filter = 18; -let rule_arr = 19; -let rule_pre = 20; -let rule_sep = 21; -let case_ = 22; +let dot = 3; +let neg = 4; +let power = 5; +let mult = 6; +let plus = 7; +let cons = 8; +let concat = 9; +let eqs = 10; +let and_ = 11; +let or_ = 12; +let ann = 13; +let if_ = 14; +let fun_ = 15; +let prod = 16; +let semi = 17; +let let_ = 18; +let filter = 19; +let rule_arr = 20; +let rule_pre = 21; +let rule_sep = 22; +let case_ = 23; -let min = 23; +let min = 24; let compare = (p1: t, p2: t): int => (-1) * Int.compare((p1 :> int), (p2 :> int)); diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index ff305e1a61..2d5f4a19a4 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -222,6 +222,15 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { } | _ => ret(hole(tm)) } + | Bin(Exp(e), tiles, Pat(p)) as tm => + switch (tiles) { + | ([(_id, (["."], []))], []) => + switch (p.term) { + | Var(s) => ret(Dot(e, s)) + | _ => ret(hole(tm)) + } + | _ => ret(hole(tm)) + } | Bin(Exp(l), tiles, Exp(r)) as tm => switch (is_tuple_exp(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) @@ -336,6 +345,11 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { | _ => ret(hole(tm)) } | ([(_id, (["::"], []))], []) => ret(Cons(l, r)) + // | ([(_id, (["."], []))], []) => + // switch (r.term) { + // | Var(s) => ret(Dot(l, s)) + // | _ => ret(hole(tm)) + // } | _ => ret(hole(tm)) } } @@ -401,6 +415,15 @@ and typ_term: unsorted => (UTyp.term, list(Id.t)) = { } | _ => ret(hole(tm)) } + // | Bin(Typ(t), tiles, Pat(p)) as tm => + // switch (tiles) { + // | ([(_id, (["."], []))], []) => + // switch (p.term) { + // | Var(s) => ret(Dot(t, s)) + // | _ => ret(hole(tm)) + // } + // | _ => ret(hole(tm)) + // } | Bin(Typ(l), tiles, Typ(r)) as tm => switch (is_tuple_typ(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 8691359516..49055662cf 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -282,6 +282,25 @@ and uexp_to_info_map = ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es)), m, ); + | Dot(e, s) => + // TODO (Anthony): Fix this + let (e, m) = go(~mode=Syn, e, m); + let filt: Typ.t => option(LabeledTuple.t) = ( + e => + switch (e) { + | Label(s, _) => Some(s) + | _ => None + } + ); + let element: option(Typ.t) = + switch (e.ty) { + | Prod(ts) => LabeledTuple.find_label(filt, ts, s) + | _ => None // TODO (Anthony): other exps + }; + switch (element) { + | Some(exp) => add(~self=Just(exp), ~co_ctx=e.co_ctx, m) + | None => add(~self=Just(Unknown(Internal)), ~co_ctx=e.co_ctx, m) + }; | Test(e) => let (e, m) = go(~mode=Ana(Bool), e, m); add(~self=Just(Prod([])), ~co_ctx=e.co_ctx, m); diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index d7ebee7701..627c925dd9 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -447,6 +447,7 @@ module UExp = { | Fun | TupLabel | Tuple + | Dot | Var | MetaVar | Let @@ -490,6 +491,7 @@ module UExp = { | Fun(_) => Fun | TupLabel(_, _) => TupLabel | Tuple(_) => Tuple + | Dot(_) => Dot | Var(_) => Var | Let(_) => Let | TyAlias(_) => TyAlias @@ -584,6 +586,7 @@ module UExp = { | Fun => "Function literal" | TupLabel => "Labeled Tuple literal" | Tuple => "Tuple literal" + | Dot => "Dot operator" | Var => "Variable reference" | MetaVar => "Meta variable reference" | Let => "Let expression" @@ -606,6 +609,7 @@ module UExp = { | Parens(e) => is_fun(e) | TupLabel(_, e) => is_fun(e) | Fun(_) => true + | Dot(_) // TODO (Anthony): Special case | Invalid(_) | EmptyHole | MultiHole(_) @@ -641,6 +645,7 @@ module UExp = { | Parens(e) => is_tuple_of_functions(e) | TupLabel(_, e) => is_tuple_of_functions(e) | Tuple(es) => es |> List.for_all(is_fun) + | Dot(_) // TODO (Anthony): Special case | Invalid(_) | EmptyHole | MultiHole(_) diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index d9525003eb..6e933d8493 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -117,6 +117,7 @@ and UExp: { | Fun | TupLabel | Tuple + | Dot | Var | Let | Ap @@ -146,6 +147,7 @@ and UExp: { | Fun(UPat.t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) + | Dot(t, string) | Var(Var.t) | Let(UPat.t, t, t) | TyAlias(UTPat.t, UTyp.t, t) @@ -250,6 +252,7 @@ and UExp: { | Fun | TupLabel | Tuple + | Dot | Var | Let | Ap @@ -279,6 +282,7 @@ and UExp: { | Fun(UPat.t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) + | Dot(t, string) | Var(Var.t) | Let(UPat.t, t, t) | TyAlias(UTPat.t, UTyp.t, t) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 9a0807f52d..6d3aaf7591 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -500,7 +500,6 @@ module rec Typ: { || List.length(l1_none) != List.length(l2_none)) { List.init(List.length(ts), _ => Unknown(Internal)); } else { - print_endline("of_prod"); let rec f = (l1: list('a), l2_lab: list('b), l2_none: list('c)) : list(t) => diff --git a/src/haz3lcore/zipper/EditorUtil.re b/src/haz3lcore/zipper/EditorUtil.re index 303397ce3d..1cd118c689 100644 --- a/src/haz3lcore/zipper/EditorUtil.re +++ b/src/haz3lcore/zipper/EditorUtil.re @@ -66,6 +66,7 @@ let rec append_exp = (e1: TermBase.UExp.t, e2: TermBase.UExp.t) => { | ListConcat(_) | UnOp(_) | BinOp(_) + | Dot(_) | Match(_) => TermBase.UExp.{ids: [Id.mk()], term: Seq(e1, e2)} | Seq(e11, e12) => let e12' = append_exp(e12, e2); diff --git a/src/haz3lschool/SyntaxTest.re b/src/haz3lschool/SyntaxTest.re index 992a286885..2eb425335d 100644 --- a/src/haz3lschool/SyntaxTest.re +++ b/src/haz3lschool/SyntaxTest.re @@ -52,6 +52,7 @@ let rec var_mention = (name: string, uexp: Term.UExp.t): bool => { find_var_upat(name, p) ? false : var_mention(name, def) || var_mention(name, body) | TupLabel(_, u) + | Dot(u, _) | Test(u) | Parens(u) | UnOp(_, u) @@ -103,6 +104,7 @@ let rec var_applied = (name: string, uexp: Term.UExp.t): bool => { | UnOp(_, u) | TyAlias(_, _, u) | TupLabel(_, u) + | Dot(u, _) | Filter(_, _, u) => var_applied(name, u) | Ap(u1, u2) => switch (u1.term) { @@ -191,6 +193,7 @@ let rec find_fn = List.fold_left((acc, u1) => {find_fn(name, u1, acc)}, l, ul) | Fun(_, body) => l |> find_fn(name, body) | TupLabel(_, u1) + | Dot(u1, _) | Parens(u1) | UnOp(_, u1) | TyAlias(_, _, u1) @@ -263,6 +266,7 @@ let rec tail_check = (name: string, uexp: Term.UExp.t): bool => { | Filter(_, _, u) | TupLabel(_, u) => tail_check(name, u) | Parens(u) => tail_check(name, u) + | Dot(u, _) | UnOp(_, u) => !var_mention(name, u) | Ap(u1, u2) => var_mention(name, u2) ? false : tail_check(name, u1) | Seq(u1, u2) => var_mention(name, u1) ? false : tail_check(name, u2) diff --git a/src/haz3lweb/view/ExplainThis.re b/src/haz3lweb/view/ExplainThis.re index a0c62fd269..a33e03b734 100644 --- a/src/haz3lweb/view/ExplainThis.re +++ b/src/haz3lweb/view/ExplainThis.re @@ -525,6 +525,7 @@ let get_doc = | EmptyHole => get_message(HoleExp.empty_hole_exps) // TODO (Anthony): put in a real message | TupLabel(_, _) => get_message(HoleExp.empty_hole_exps) + | Dot(_, _) => get_message(HoleExp.empty_hole_exps) | MultiHole(_children) => get_message(HoleExp.multi_hole_exps) | TyAlias(ty_pat, ty_def, _body) => let tpat_id = List.nth(ty_pat.ids, 0); diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index 07dd23ff13..3e0064e4d6 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -74,6 +74,7 @@ let rec precedence = (~show_casts: bool, d: DHExp.t) => { // TODO (Anthony): what should this be? | TupLabel(_) => DHDoc_common.precedence_Comma | Tuple(_) => DHDoc_common.precedence_Comma + | Dot(_) => DHDoc_common.precedence_Dot | Fun(_) => DHDoc_common.precedence_max | Let(_) | FixF(_) @@ -151,6 +152,7 @@ let mk = | (BinIntOp(_), _) | (BinFloatOp(_), _) | (BinStringOp(_), _) + | (Dot(_), _) | (Projection, _) | (ListCons, _) | (ListConcat, _) @@ -420,6 +422,14 @@ let mk = DHDoc_common.Delim.mk("="), go'(d, TupLabel), ]) + | Dot(d, s) => + Doc.hcats([ + DHDoc_common.Delim.open_Parenthesized, + go'(d, Dot), + DHDoc_common.Delim.close_Parenthesized, + DHDoc_common.Delim.mk("."), + Doc.text(s), + ]) | Tuple([]) => DHDoc_common.Delim.triv | Tuple(ds) => DHDoc_common.mk_Tuple(ds |> List.mapi((i, d) => go'(d, Tuple(i)))) diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re index 4ccc57da62..13549a27af 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re @@ -20,6 +20,7 @@ let precedence_GreaterThan = P.eqs; let precedence_And = P.and_; let precedence_Or = P.or_; let precedence_Comma = P.prod; +let precedence_Dot = P.dot; let precedence_max = P.min; let pad_child = diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei index b3b9e2e264..9516480a91 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei @@ -16,6 +16,7 @@ let precedence_GreaterThan: int; let precedence_And: int; let precedence_Or: int; let precedence_Comma: int; +let precedence_Dot: int; let precedence_max: int; let pad_child: From 5af500fa3a924d7ef6aef56de3cd3d00d5dc43f2 Mon Sep 17 00:00:00 2001 From: WondAli Date: Sun, 31 Mar 2024 16:00:09 -0400 Subject: [PATCH 003/108] may need to revert some tuplabel code since no longer consistent with wrapped element --- src/haz3lcore/LabeledTuple.re | 18 ------------- src/haz3lcore/dynamics/DH.re | 8 +++--- src/haz3lcore/dynamics/EvaluatorStep.re | 1 - src/haz3lcore/dynamics/FilterMatcher.re | 18 ++++++++----- src/haz3lcore/dynamics/PatternMatch.re | 20 +++++++++----- src/haz3lcore/dynamics/Transition.re | 11 ++++---- src/haz3lcore/lang/Precedence.re | 4 +-- src/haz3lcore/statics/Mode.re | 8 +++--- src/haz3lcore/statics/Statics.re | 24 +++++++++++------ src/haz3lcore/statics/Term.re | 36 +++++++++++++++++++++++-- src/haz3lcore/statics/TypBase.re | 9 ++++--- 11 files changed, 98 insertions(+), 59 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 412b4cf1e7..c00b6252cd 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -145,21 +145,3 @@ let find_label: ('a => option(t), list('a), t) => option('a) = es, ); }; - -let extract_item: ('a => option(t), list('a), t, 'b) => 'b = - (filt, es, label, none_val) => { - let opt = - List.find_opt( - e => { - switch (filt(e)) { - | Some(s) => compare(s, label) == 0 - | None => false - } - }, - es, - ); - switch (opt) { - | Some(some) => some - | None => none_val - }; - }; diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index 05d73a8f54..6bc678e4f0 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -227,6 +227,11 @@ module rec DHExp: { let rec fast_equal = (d1: t, d2: t): bool => { switch (d1, d2) { + /* TODO: Labels are a special case, but should they be?*/ + | (TupLabel(s1, d1), TupLabel(s2, d2)) => + LabeledTuple.compare(s1, s2) == 0 && fast_equal(d1, d2) + | (TupLabel(_, d1), _) => fast_equal(d1, d2) + | (_, TupLabel(_, d2)) => fast_equal(d1, d2) /* Primitive forms: regular structural equality */ | (BoundVar(_), _) /* TODO: Not sure if this is right... */ @@ -254,8 +259,6 @@ module rec DHExp: { fast_equal(d11, d12) && fast_equal(d21, d22) | (ListConcat(d11, d21), ListConcat(d12, d22)) => fast_equal(d11, d12) && fast_equal(d21, d22) - | (TupLabel(s1, d1), TupLabel(s2, d2)) => - LabeledTuple.compare(s1, s2) == 0 && fast_equal(d1, d2) | (Tuple(ds1), Tuple(ds2)) => let filt: t => option(LabeledTuple.t) = ( d => @@ -314,7 +317,6 @@ module rec DHExp: { | (Cons(_), _) | (ListConcat(_), _) | (ListLit(_), _) - | (TupLabel(_, _), _) | (Tuple(_), _) | (Dot(_), _) | (Prj(_), _) diff --git a/src/haz3lcore/dynamics/EvaluatorStep.re b/src/haz3lcore/dynamics/EvaluatorStep.re index 4472236a19..8daee392ed 100644 --- a/src/haz3lcore/dynamics/EvaluatorStep.re +++ b/src/haz3lcore/dynamics/EvaluatorStep.re @@ -285,7 +285,6 @@ let rec compose = (ctx: EvalCtx.t, d: DHExp.t): DHExp.t => { | ListConcat2(d1, ctx) => let d2 = compose(ctx, d); ListConcat(d1, d2); - // TODO (Anthony): is this right? | TupLabel(s, ctx) => let d2 = compose(ctx, d); TupLabel(s, d2); diff --git a/src/haz3lcore/dynamics/FilterMatcher.re b/src/haz3lcore/dynamics/FilterMatcher.re index d080df58df..d9565be125 100644 --- a/src/haz3lcore/dynamics/FilterMatcher.re +++ b/src/haz3lcore/dynamics/FilterMatcher.re @@ -4,6 +4,12 @@ let rec matches_exp = | (Constructor("$e"), _) => failwith("$e in matched expression") | (Constructor("$v"), _) => failwith("$v in matched expression") + // TODO (Anthony): Is this right? + /* Labels are a special case*/ + | (TupLabel(_, dv), TupLabel(_, fv)) => matches_exp(env, dv, fv) + | (TupLabel(_, dv), _) => matches_exp(env, dv, f) + | (_, TupLabel(_, fv)) => matches_exp(env, d, fv) + // HACK[Matt]: ignore fixpoints in comparison, to allow pausing on fixpoint steps | (FixF(dp, _, dc), f) => matches_exp( @@ -132,10 +138,7 @@ let rec matches_exp = ) | (ListLit(_), _) => false - // TODO (Anthony): Is this right? - | (TupLabel(_, dv), TupLabel(_, fv)) => matches_exp(env, dv, fv) - | (TupLabel(_), _) => false - + // TODO (Anthony): Is this right | (Dot(dv, _), Dot(fv, _)) => matches_exp(env, dv, fv) | (Dot(_), _) => false @@ -215,6 +218,11 @@ let rec matches_exp = } and matches_pat = (d: DHPat.t, f: DHPat.t): bool => { switch (d, f) { + /* Labels are a special case*/ + | (TupLabel(s1, dx), TupLabel(s2, fx)) => + LabeledTuple.compare(s1, s2) == 0 && matches_pat(dx, fx) + | (TupLabel(_, dx), _) => matches_pat(dx, f) + | (_, TupLabel(_, fx)) => matches_pat(d, fx) | (_, EmptyHole(_)) => true | (Wild, Wild) => true | (Wild, _) => false @@ -238,8 +246,6 @@ and matches_pat = (d: DHPat.t, f: DHPat.t): bool => { | (Constructor(_), _) => false | (Var(dx), Var(fx)) => dx == fx | (Var(_), _) => false - | (TupLabel(_, dx), TupLabel(_, fx)) => dx == fx - | (TupLabel(_), _) => false | (Tuple(dl), Tuple(fl)) => switch ( List.fold_left2((res, d, f) => res && matches_pat(d, f), true, dl, fl) diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 8c38726d20..85b98005a7 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -30,6 +30,16 @@ let cast_sum_maps = let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => switch (dp, d) { + /* Labels are a special case */ + | (TupLabel(s1, dp), TupLabel(s2, d)) => + if (LabeledTuple.compare(s1, s2) == 0) { + matches(dp, d); + } else { + DoesNotMatch; + } + | (TupLabel(_, dp), _) => matches(dp, d) + | (_, TupLabel(_, d)) => matches(dp, d) + | (_, BoundVar(_)) => DoesNotMatch | (EmptyHole(_), _) | (NonEmptyHole(_), _) => IndetMatch @@ -141,9 +151,6 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => matches(dp, d) | (Constructor(_), _) => DoesNotMatch - | (TupLabel(_, dp), TupLabel(_, d)) => matches(dp, d) - | (TupLabel(_, _), _) => DoesNotMatch - | (Tuple(dps), Tuple(ds)) => let filt1: DHPat.t => option(LabeledTuple.t) = ( d => @@ -254,6 +261,7 @@ and matches_cast_Sum = | Cast(d', Sum(_) | Rec(_, Sum(_)), Unknown(_)) | Cast(d', Unknown(_), Sum(_) | Rec(_, Sum(_))) => matches_cast_Sum(ctr, dp, d', castmaps) + | TupLabel(_, d') => matches_cast_Sum(ctr, dp, d', castmaps) | FreeVar(_) | ExpandingKeyword(_) | InvalidText(_) @@ -283,7 +291,6 @@ and matches_cast_Sum = | FloatLit(_) | StringLit(_) | ListLit(_) - | TupLabel(_, _) | Tuple(_) | Dot(_, _) | Sequence(_, _) @@ -366,8 +373,7 @@ and matches_cast_Tuple = d', List.map2(List.cons, List.combine(tys, tys'), elt_casts), ); - // What should TupLabel be? - | TupLabel(_, _) => DoesNotMatch + | TupLabel(_, d') => matches_cast_Tuple(dps, d', elt_casts) | Dot(_, _) | Cast(_, _, _) => DoesNotMatch | BoundVar(_) => DoesNotMatch @@ -509,6 +515,7 @@ and matches_cast_Cons = matches_cast_Cons(dp, d', [(ty1, Unknown(Internal)), ...elt_casts]) | Cast(d', Unknown(_), List(ty2)) => matches_cast_Cons(dp, d', [(Unknown(Internal), ty2), ...elt_casts]) + | TupLabel(_, d') => matches_cast_Cons(dp, d', elt_casts) | Cast(_, _, _) => DoesNotMatch | BoundVar(_) => DoesNotMatch | FreeVar(_) => IndetMatch @@ -533,7 +540,6 @@ and matches_cast_Cons = | Test(_) => DoesNotMatch | FloatLit(_) => DoesNotMatch | StringLit(_) => DoesNotMatch - | TupLabel(_, _) => DoesNotMatch | Tuple(_) => DoesNotMatch | Dot(_, _) => DoesNotMatch | Prj(_) => IndetMatch diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index fa4181c42b..b01f8db412 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -466,11 +466,11 @@ module Transition = (EV: EV_MODE) => { }); | Dot(d, s) => let. _ = otherwise(env, d => Dot(d, s)) - and. _ = req_value(req(state, env), d => Dot(d, s), d); + and. d' = req_final(req(state, env), d => Dot(d, s), d); // TODO (Anthony): fix step if needed Step({ apply: () => - switch (d) { + switch (d') { | Tuple(ds) => let filt: t => option(LabeledTuple.t) = ( e => @@ -481,8 +481,8 @@ module Transition = (EV: EV_MODE) => { ); let element = LabeledTuple.find_label(filt, ds, s); switch (element) { - | Some(exp) => exp - | None => raise(EvaluatorError.Exception(BadPatternMatch)) + | Some(TupLabel(_, exp)) => exp + | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }; | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }, @@ -492,7 +492,8 @@ module Transition = (EV: EV_MODE) => { | TupLabel(p, d1) => // TODO (Anthony): Fix this if needed let. _ = otherwise(env, d1 => TupLabel(p, d1)) - and. _ = req_final(req(state, env), d1 => TupLabel(p, d1), d1); + and. _ = req_value(req(state, env), d1 => TupLabel(p, d1), d1); + // Hidden step Constructor; | Tuple(ds) => let. _ = otherwise(env, ds => Tuple(ds)) diff --git a/src/haz3lcore/lang/Precedence.re b/src/haz3lcore/lang/Precedence.re index 41da1f8ed5..0eaf6ce07a 100644 --- a/src/haz3lcore/lang/Precedence.re +++ b/src/haz3lcore/lang/Precedence.re @@ -10,8 +10,8 @@ type t = int; let max: t = 0; let unquote = 1; -let ap = 2; -let dot = 3; +let dot = 2; +let ap = 3; let neg = 4; let power = 5; let mult = 6; diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index df8d3f814c..1c3989e92a 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -39,11 +39,13 @@ let of_arrow = (ctx: Ctx.t, mode: t): (t, t) => | Ana(ty) => ty |> Typ.matched_arrow(ctx) |> TupleUtil.map2(ana) }; -let of_label = (ctx: Ctx.t, mode: t): t => +let of_label = (ctx: Ctx.t, mode: t): (bool, t) => switch (mode) { | Syn - | SynFun => Syn - | Ana(ty) => ty |> Typ.matched_label(ctx) |> ana + | SynFun => (true, Syn) + | Ana(ty) => + let (b, t) = Typ.matched_label(ctx, ty); + (b, ana(t)); }; let of_prod = (ctx: Ctx.t, mode: t, ts: list('a), filt): list(t) => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 49055662cf..e1d34be986 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -264,9 +264,13 @@ and uexp_to_info_map = 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); | TupLabel(s, e) => - let mode = Mode.of_label(ctx, mode); + let (isLab, mode) = Mode.of_label(ctx, mode); let (e, m) = go(~mode, e, m); - add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); + if (isLab) { + add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); + } else { + add(~self=Just(e.ty), ~co_ctx=e.co_ctx, m); + }; | Tuple(es) => let filt: UExp.t => option(LabeledTuple.t) = ( e => @@ -286,8 +290,8 @@ and uexp_to_info_map = // TODO (Anthony): Fix this let (e, m) = go(~mode=Syn, e, m); let filt: Typ.t => option(LabeledTuple.t) = ( - e => - switch (e) { + t => + switch (t) { | Label(s, _) => Some(s) | _ => None } @@ -298,8 +302,8 @@ and uexp_to_info_map = | _ => None // TODO (Anthony): other exps }; switch (element) { - | Some(exp) => add(~self=Just(exp), ~co_ctx=e.co_ctx, m) - | None => add(~self=Just(Unknown(Internal)), ~co_ctx=e.co_ctx, m) + | Some(Label(_, exp)) => add(~self=Just(exp), ~co_ctx=e.co_ctx, m) + | _ => add(~self=Just(Unknown(Internal)), ~co_ctx=e.co_ctx, m) }; | Test(e) => let (e, m) = go(~mode=Ana(Bool), e, m); @@ -534,9 +538,13 @@ and upat_to_info_map = let entry = Ctx.VarEntry({name, id: UPat.rep_id(upat), typ: ctx_typ}); add(~self=Just(unknown), ~ctx=Ctx.extend(ctx, entry), m); | TupLabel(s, p) => - let mode = Mode.of_label(ctx, mode); + let (isLab, mode) = Mode.of_label(ctx, mode); let (p, m) = go(~ctx, ~mode, p, m); - add(~self=Just(Label(s, p.ty)), ~ctx=p.ctx, m); + if (isLab) { + add(~self=Just(Label(s, p.ty)), ~ctx=p.ctx, m); + } else { + add(~self=Just(p.ty), ~ctx=p.ctx, m); + }; | Tuple(ps) => let filt: UPat.t => option(LabeledTuple.t) = ( p => diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index 627c925dd9..a3bd03c2ac 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -609,7 +609,23 @@ module UExp = { | Parens(e) => is_fun(e) | TupLabel(_, e) => is_fun(e) | Fun(_) => true - | Dot(_) // TODO (Anthony): Special case + | Dot(e, s) => + let filt: t => option(LabeledTuple.t) = ( + e => + switch (e.term) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let element: option(t) = + switch (e.term) { + | Tuple(ts) => LabeledTuple.find_label(filt, ts, s) + | _ => None // TODO (Anthony): other exps + }; + switch (element) { + | Some(exp) => is_fun(exp) + | None => false + }; | Invalid(_) | EmptyHole | MultiHole(_) @@ -645,7 +661,23 @@ module UExp = { | Parens(e) => is_tuple_of_functions(e) | TupLabel(_, e) => is_tuple_of_functions(e) | Tuple(es) => es |> List.for_all(is_fun) - | Dot(_) // TODO (Anthony): Special case + | Dot(e, s) => + let filt: t => option(LabeledTuple.t) = ( + e => + switch (e.term) { + | TupLabel(s, _) => Some(s) + | _ => None + } + ); + let element: option(t) = + switch (e.term) { + | Tuple(ts) => LabeledTuple.find_label(filt, ts, s) + | _ => None // TODO (Anthony): other exps + }; + switch (element) { + | Some(exp) => is_tuple_of_functions(exp) + | None => false + }; | Invalid(_) | EmptyHole | MultiHole(_) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 6d3aaf7591..d971feeebc 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -53,7 +53,7 @@ module rec Typ: { let join_type_provenance: (type_provenance, type_provenance) => type_provenance; let matched_arrow: (Ctx.t, t) => (t, t); - let matched_label: (Ctx.t, t) => t; + let matched_label: (Ctx.t, t) => (bool, t); let matched_prod: (Ctx.t, list('a), 'a => option(LabeledTuple.t), t) => list(t); let matched_list: (Ctx.t, t) => t; @@ -464,10 +464,11 @@ module rec Typ: { }; let matched_label = (ctx, ty) => + // "true" is for if the label statics are Label(s, ty); "false" for ty switch (weak_head_normalize(ctx, ty)) { - | Label(_, ty) => ty - | Unknown(SynSwitch) => Unknown(SynSwitch) - | _ => Unknown(Internal) + | Label(_, ty) => (true, ty) + | Unknown(SynSwitch) => (true, Unknown(SynSwitch)) + | _ => (false, ty) }; let matched_prod = (ctx, ts, filt, ty) => { From 9927605a708370314aa713e40ae1b7bb9a46d2a9 Mon Sep 17 00:00:00 2001 From: WondAli Date: Sat, 13 Apr 2024 13:57:45 -0400 Subject: [PATCH 004/108] allow for unmatched labels in one direction --- src/haz3lcore/LabeledTuple.re | 113 ++++++----- src/haz3lcore/dynamics/DH.re | 6 +- src/haz3lcore/dynamics/PatternMatch.re | 26 +-- src/haz3lcore/statics/Mode.re | 8 +- src/haz3lcore/statics/Statics.re | 28 +-- src/haz3lcore/statics/TypBase.re | 259 ++++++++++++++++--------- 6 files changed, 264 insertions(+), 176 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index c00b6252cd..c540974d4a 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -7,10 +7,6 @@ let eq = String.equal; let length = String.length; -let valid_regex = - Re.Str.regexp("^\\([a-zA-Z]\\|_[_a-zA-Z0-9]\\)[_a-zA-Z0-9']*$"); -let is_valid = s => Re.Str.string_match(valid_regex, s, 0); - let compare = String.compare; let find_opt: ('a => bool, list('a)) => option('a) = List.find_opt; @@ -18,6 +14,7 @@ let find_opt: ('a => bool, list('a)) => option('a) = List.find_opt; // filt returns Some(string) if TupLabel or None if not a TupLabel // returns ordered list of (Some(string), TupLabel) // and another of (None, not-TupLabel) +// TODO: Need to check uniqueness earlier // TODO: Make more efficient let validate_uniqueness: ('a => option(t), list('a)) => (bool, list((option(t), 'a)), list('a)) = @@ -39,7 +36,7 @@ let validate_uniqueness: ls, ) => ( b, - ls @ [(filt(e), e)], + ls @ [(Some(s1), e)], ns, ) | None => (b, ls, ns @ [e]) @@ -60,8 +57,8 @@ let validate_uniqueness: // Checks remaining None pairs in order and performs f on each pair let ana_tuple: ( - 'b => option(t), - 'c => option(t), + 'b => (option(t), 'b), + 'c => (option(t), 'c), ('a, 'b, 'c) => 'a, 'a, 'a, @@ -70,41 +67,26 @@ let ana_tuple: ) => 'a = (filt1, filt2, f, accu, accu_fail, l1, l2) => { - let (l1_valid, l1_lab, l1_none) = validate_uniqueness(filt1, l1); - let (l2_valid, l2_lab, l2_none) = validate_uniqueness(filt2, l2); + let filt1_lab = x => { + let (s, _) = filt1(x); + s; + }; + let filt2_lab = x => { + let (s, _) = filt2(x); + s; + }; + let (l1_valid, l1_lab, l1_none) = validate_uniqueness(filt1_lab, l1); + let (l2_valid, l2_lab, _) = validate_uniqueness(filt2_lab, l2); // temporary solution if mess up earlier in tuple, such as make_term if (!l1_valid || !l2_valid) { accu_fail; - } else if (List.length(l1_none) != List.length(l2_none)) { - accu_fail; } else { - let accu = - List.fold_left( - (accu, l2_item) => { - let l1_item = - List.find_opt( - l1_item => { - switch (l1_item, l2_item) { - | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l1_lab, - ); - switch (l1_item, l2_item) { - | (Some((_, l1_val)), (_, l2_val)) => f(accu, l1_val, l2_val) - | (None, _) => accu_fail - }; - }, - accu, - l2_lab, - ); - // TODO: Currently duplicating checks, for both directions - let accu = + // this result represents to accu, and the matched l2 labels + let (accu, l2_labels_matched) = List.fold_left( - (accu, l1_item) => { + ((accu, l2_matched), l1_item) => { let l2_item = - List.find_opt( + find_opt( l2_item => { switch (l1_item, l2_item) { | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 @@ -114,28 +96,61 @@ let ana_tuple: l2_lab, ); switch (l1_item, l2_item) { - | ((_, l1_val), Some((_, l2_val))) => f(accu, l1_val, l2_val) - | (_, None) => accu_fail + | ((_, l1_val), Some((l2_lab, l2_val))) => ( + f(accu, l1_val, l2_val), + l2_matched @ [l2_lab], + ) + | (_, None) => (accu_fail, l2_matched) }; }, - accu, + (accu, []), l1_lab, ); - // None checks - let accu = - List.fold_left2( - (accu, l1_val, l2_val) => f(accu, l1_val, l2_val), - accu, - l1_none, - l2_none, - ); - accu; + // short circuit on failure + if (accu == accu_fail) { + accu_fail; + } else { + // filter l2 to remove matched labels and remove labels + // TODO: Can be optimized + let l2_rem = + List.fold_left( + (l2_rem, item) => { + let lab_opt = filt2(item); + switch (lab_opt) { + | (Some(s1), _) + when + List.exists( + l => { + switch (l) { + | Some(s2) => compare(s1, s2) == 0 + | _ => false + } + }, + l2_labels_matched, + ) => l2_rem + | (Some(_), it) + | (None, it) => l2_rem @ [it] + }; + }, + [], + l2, + ); + // remaining checks are in order + let accu = + List.fold_left2( + (accu, l1_val, l2_val) => f(accu, l1_val, l2_val), + accu, + l1_none, + l2_rem, + ); + accu; + }; }; }; let find_label: ('a => option(t), list('a), t) => option('a) = (filt, es, label) => { - List.find_opt( + find_opt( e => { switch (filt(e)) { | Some(s) => compare(s, label) == 0 diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index 6bc678e4f0..1b0c33cc71 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -260,11 +260,11 @@ module rec DHExp: { | (ListConcat(d11, d21), ListConcat(d12, d22)) => fast_equal(d11, d12) && fast_equal(d21, d22) | (Tuple(ds1), Tuple(ds2)) => - let filt: t => option(LabeledTuple.t) = ( + let filt: t => (option(LabeledTuple.t), t) = ( d => switch (d) { - | TupLabel(s, _) => Some(s) - | _ => None + | TupLabel(s, d') => (Some(s), d') + | _ => (None, d) } ); let f = (b, ds1_val, ds2_val) => { diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 85b98005a7..bb0e7bb820 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -152,18 +152,18 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => | (Constructor(_), _) => DoesNotMatch | (Tuple(dps), Tuple(ds)) => - let filt1: DHPat.t => option(LabeledTuple.t) = ( + let filt1: DHPat.t => (option(LabeledTuple.t), DHPat.t) = ( d => switch (d) { - | TupLabel(s, _) => Some(s) - | _ => None + | TupLabel(s, d') => (Some(s), d') + | _ => (None, d) } ); - let filt2: DHExp.t => option(LabeledTuple.t) = ( + let filt2: DHExp.t => (option(LabeledTuple.t), DHExp.t) = ( d => switch (d) { - | TupLabel(s, _) => Some(s) - | _ => None + | TupLabel(s, d') => (Some(s), d') + | _ => (None, d) } ); let f = (result, dp, d) => { @@ -311,18 +311,18 @@ and matches_cast_Tuple = if (List.length(dps) != List.length(ds)) { DoesNotMatch; } else { - let filt1: DHPat.t => option(LabeledTuple.t) = ( + let filt1: DHPat.t => (option(LabeledTuple.t), DHPat.t) = ( d => switch (d) { - | TupLabel(s, _) => Some(s) - | _ => None + | TupLabel(s, d') => (Some(s), d') + | _ => (None, d) } ); - let filt2: ((DHExp.t, _)) => option(LabeledTuple.t) = ( - ((d, _)) => + let filt2: ((DHExp.t, 'a)) => (option(LabeledTuple.t), (DHExp.t, 'a)) = ( + ((d, c)) => switch (d) { - | TupLabel(s, _) => Some(s) - | _ => None + | TupLabel(s, d') => (Some(s), (d', c)) + | _ => (None, (d, c)) } ); assert(List.length(List.combine(dps, ds)) == List.length(elt_casts)); diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index 1c3989e92a..72fdf4f49b 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -39,13 +39,11 @@ let of_arrow = (ctx: Ctx.t, mode: t): (t, t) => | Ana(ty) => ty |> Typ.matched_arrow(ctx) |> TupleUtil.map2(ana) }; -let of_label = (ctx: Ctx.t, mode: t): (bool, t) => +let of_label = (ctx: Ctx.t, mode: t): t => switch (mode) { | Syn - | SynFun => (true, Syn) - | Ana(ty) => - let (b, t) = Typ.matched_label(ctx, ty); - (b, ana(t)); + | SynFun => Syn + | Ana(ty) => Typ.matched_label(ctx, ty) |> ana }; let of_prod = (ctx: Ctx.t, mode: t, ts: list('a), filt): list(t) => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index e1d34be986..f601207c71 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -264,19 +264,15 @@ and uexp_to_info_map = 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); | TupLabel(s, e) => - let (isLab, mode) = Mode.of_label(ctx, mode); + let mode = Mode.of_label(ctx, mode); let (e, m) = go(~mode, e, m); - if (isLab) { - add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); - } else { - add(~self=Just(e.ty), ~co_ctx=e.co_ctx, m); - }; + add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); | Tuple(es) => - let filt: UExp.t => option(LabeledTuple.t) = ( + let filt: UExp.t => (option(LabeledTuple.t), UExp.t) = ( e => switch (e.term) { - | TupLabel(s, _) => Some(s) - | _ => None + | TupLabel(s, e') => (Some(s), e') + | _ => (None, e) } ); let modes = Mode.of_prod(ctx, mode, es, filt); @@ -538,19 +534,15 @@ and upat_to_info_map = let entry = Ctx.VarEntry({name, id: UPat.rep_id(upat), typ: ctx_typ}); add(~self=Just(unknown), ~ctx=Ctx.extend(ctx, entry), m); | TupLabel(s, p) => - let (isLab, mode) = Mode.of_label(ctx, mode); + let mode = Mode.of_label(ctx, mode); let (p, m) = go(~ctx, ~mode, p, m); - if (isLab) { - add(~self=Just(Label(s, p.ty)), ~ctx=p.ctx, m); - } else { - add(~self=Just(p.ty), ~ctx=p.ctx, m); - }; + add(~self=Just(Label(s, p.ty)), ~ctx=p.ctx, m); | Tuple(ps) => - let filt: UPat.t => option(LabeledTuple.t) = ( + let filt: UPat.t => (option(LabeledTuple.t), UPat.t) = ( p => switch (p.term) { - | TupLabel(s, _) => Some(s) - | _ => None + | TupLabel(s, p') => (Some(s), p') + | _ => (None, p) } ); let modes = Mode.of_prod(ctx, mode, ps, filt); diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index d971feeebc..4bc2197de8 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -53,9 +53,9 @@ module rec Typ: { let join_type_provenance: (type_provenance, type_provenance) => type_provenance; let matched_arrow: (Ctx.t, t) => (t, t); - let matched_label: (Ctx.t, t) => (bool, t); + let matched_label: (Ctx.t, t) => t; let matched_prod: - (Ctx.t, list('a), 'a => option(LabeledTuple.t), t) => list(t); + (Ctx.t, list('a), 'a => (option(LabeledTuple.t), 'a), t) => list(t); let matched_list: (Ctx.t, t) => t; let precedence: t => int; let subst: (t, TypVar.t, t) => t; @@ -187,11 +187,11 @@ module rec Typ: { | (Arrow(t1, t2), Arrow(t1', t2')) => eq(t1, t1') && eq(t2, t2') | (Arrow(_), _) => false | (Prod(tys1), Prod(tys2)) => - let filt: t => option(LabeledTuple.t) = ( + let filt: t => (option(LabeledTuple.t), t) = ( d => switch (d) { - | Label(s, _) => Some(s) - | _ => None + | Label(s, d') => (Some(s), d') + | _ => (None, d) } ); let f = (b, tys1_val, tys2_val) => { @@ -280,19 +280,6 @@ module rec Typ: { let+ ty_body = join(~resolve, ~fix, ctx, ty1, subst(Var(x1), x2, ty2)); Rec(x1, ty_body); - | (Label(s1, ty1), Label(s2, ty2)) => - if (compare(s1, s2) == 0) { - let+ ty = join'(ty1, ty2); - Label(s1, ty); - } else { - None; - } - | (Label(s1, ty1), ty2) => - let+ ty = join'(ty1, ty2); - Label(s1, ty); - | (ty1, Label(s2, ty2)) => - let+ ty = join'(ty1, ty2); - Label(s2, ty); | (Rec(_), _) => None | (Int, Int) => Some(Int) | (Int, _) => None @@ -307,7 +294,16 @@ module rec Typ: { let+ ty2 = join'(ty2, ty2'); Arrow(ty1, ty2); | (Arrow(_), _) => None + | (Label(s1, ty1), Label(s2, ty2)) => + if (compare(s1, s2) == 0) { + let+ ty = join'(ty1, ty2); + Label(s2, ty); + } else { + None; + } + | (Label(_), _) => None | (Prod(tys1), Prod(tys2)) => + let (tys1, tys2) = (tys2, tys1); // tessting let filt: t => option(LabeledTuple.t) = ( d => switch (d) { @@ -323,50 +319,100 @@ module rec Typ: { } ); //TODO (Anthony): Clean up the repetition - let (l1_valid, _, l1_none) = + let (l1_valid, l1_lab, _) = LabeledTuple.validate_uniqueness(filt, tys1); - let (l2_valid, l2_lab, l2_none) = + let (l2_valid, l2_lab, _) = LabeledTuple.validate_uniqueness(filt, tys2); + let l1 = List.map(filt2, tys1); + let l2_matched = + List.fold_left( + (l2_matched, l1_item) => { + let l2_item = + LabeledTuple.find_opt( + l2_item => { + switch (l1_item, l2_item) { + | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l2_item) { + | Some((_, l2_val)) => l2_matched @ [filt2(l2_val)] + | None => l2_matched + }; + }, + [], + l1_lab, + ); // TODO (Anthony): clean up error handling - if (!l1_valid - || !l2_valid - || List.length(l1_none) != List.length(l2_none)) { - let* tys = Some(List.init(List.length(tys1), _ => None)); - let+ tys = OptUtil.sequence(tys); - Prod(tys); + // if (!l1_valid + // || !l2_valid + // || List.length(l2_matched) != List.length(l1_lab)) { + // let* tys = Some(List.init(List.length(tys1), _ => None)); + // let+ tys = OptUtil.sequence(tys); + // Prod(tys); + // } + if (!l1_valid || !l2_valid || List.length(tys1) != List.length(tys2)) { + print_endline("fail"); + None; } else { - let l1 = List.map(filt2, tys1); + let l2_rem = + List.fold_left( + (l2_rem, item) => { + let lab_opt = filt2(item); + switch (lab_opt) { + | (Some(s1), _) + when + List.exists( + l => { + switch (l) { + | (Some(s2), _) => compare(s1, s2) == 0 + | _ => false + } + }, + l2_matched, + ) => l2_rem + | (Some(_), it) + | (None, it) => l2_rem @ [it] + }; + }, + [], + tys2, + ); let rec f = - (l1: list('a), l2_lab: list('a), l2_none: list('b)) + (l1: list('a), l2_matched: list('a), l2_rem: list('b)) : list(option(t)) => switch (l1) { | [hd, ...tl] => switch (hd) { | (Some(s1), l1_val) => - let l2_item = - List.find_opt( - l2_item => { - switch (l2_item) { - | (Some(s2), _) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l2_item) { - | Some((_, l2_val)) => - [join'(l1_val, l2_val)] @ f(tl, l2_lab, l2_none) - | None => [None] @ f(tl, l2_lab, l2_none) - }; + switch (l2_matched) { + | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen + | [hd2, ...tl2] => + switch (hd2) { + | (Some(s2), l2_val) when LabeledTuple.compare(s1, s2) == 0 => + [join'(Label(s1, l1_val), Label(s2, l2_val))] + @ f(tl, tl2, l2_rem) + | _ => + switch (l2_rem) { + | [hd2, ...tl2] => + [join'(Label(s1, l1_val), hd2)] + @ f(tl, l2_matched, tl2) + | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen + } + } + } | (None, l1_val) => - switch (l2_none) { - | [t2, ...tl2] => [join'(l1_val, t2)] @ f(tl, l2_lab, tl2) - | [] => [None] @ f(tl, l2_lab, l2_none) + switch (l2_rem) { + | [hd2, ...tl2] => + [join'(l1_val, hd2)] @ f(tl, l2_matched, tl2) + | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen } } | [] => [] }; - let* tys = Some(f(l1, l2_lab, l2_none)); + let* tys = Some(f(l1, l2_matched, l2_rem)); let+ tys = OptUtil.sequence(tys); Prod(tys); }; @@ -466,71 +512,108 @@ module rec Typ: { let matched_label = (ctx, ty) => // "true" is for if the label statics are Label(s, ty); "false" for ty switch (weak_head_normalize(ctx, ty)) { - | Label(_, ty) => (true, ty) - | Unknown(SynSwitch) => (true, Unknown(SynSwitch)) - | _ => (false, ty) + | Label(_, ty) => ty + | Unknown(SynSwitch) => Unknown(SynSwitch) + | _ => Unknown(Internal) }; let matched_prod = (ctx, ts, filt, ty) => { - // TODO: rearrange tys to fit ts //TODO (Anthony): Clean up the repetition let filt2 = d => + switch (d) { + | Label(s, d') => (Some(s), d') + | _ => (None, d) + }; + let filt_lab = d => + switch (filt(d)) { + | (Some(s), _) => Some(s) + | (None, _) => None + }; + let filt2_lab = d => switch (d) { | Label(s, _) => Some(s) | _ => None }; switch (weak_head_normalize(ctx, ty)) { - | Prod(tys) - when - List.length(tys) == List.length(ts) - && LabeledTuple.ana_tuple( - filt, - filt2, - (a, _, _) => a, - true, - false, - ts, - tys, - ) => - let (l1_valid, _, l1_none) = - LabeledTuple.validate_uniqueness(filt, ts); - let (l2_valid, l2_lab, l2_none) = - LabeledTuple.validate_uniqueness(filt2, tys); + | Prod(tys) => + let (l1_valid, l1_lab, _) = + LabeledTuple.validate_uniqueness(filt_lab, ts); + let (l2_valid, l2_lab, _) = + LabeledTuple.validate_uniqueness(filt2_lab, tys); + let l2_matched = + List.fold_left( + (l2_matched, l1_item) => { + let l2_item = + LabeledTuple.find_opt( + l2_item => { + switch (l1_item, l2_item) { + | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l2_item) { + | Some(l2_item) => l2_matched @ [l2_item] + | None => l2_matched + }; + }, + [], + l1_lab, + ); if (!l1_valid || !l2_valid - || List.length(l1_none) != List.length(l2_none)) { + || List.length(l2_matched) != List.length(l1_lab)) { List.init(List.length(ts), _ => Unknown(Internal)); } else { + let l2_rem = + List.fold_left( + (l2_rem, item) => { + let lab_opt = filt2(item); + switch (lab_opt) { + | (Some(s1), _) + when + List.exists( + l => { + switch (l) { + | (Some(s2), _) => compare(s1, s2) == 0 + | _ => false + } + }, + l2_matched, + ) => l2_rem + | (Some(_), it) + | (None, it) => l2_rem @ [it] + }; + }, + [], + tys, + ); let rec f = - (l1: list('a), l2_lab: list('b), l2_none: list('c)) + (l1: list('a), l2_matched: list('b), l2_rem: list('c)) : list(t) => switch (l1) { | [hd, ...tl] => - switch (filt(hd)) { + switch (filt_lab(hd)) { | Some(s1) => - let l2_item = - List.find_opt( - l2_item => { - switch (l2_item) { - | (Some(s2), _) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l2_item) { - | Some((_, l2_val)) => [l2_val] @ f(tl, l2_lab, l2_none) - | None => [Unknown(Internal)] @ f(tl, l2_lab, l2_none) - }; + switch (l2_matched) { + | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) // should never happen + | [hd2, ...tl2] => + switch (hd2) { + | (Some(s2), l2_val) when compare(s1, s2) == 0 => + [l2_val] @ f(tl, tl2, l2_rem) + | _ => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) + } + } | None => - switch (l2_none) { - | [t2, ...tl2] => [t2] @ f(tl, l2_lab, tl2) - | [] => [Unknown(Internal)] @ f(tl, l2_lab, l2_none) + switch (l2_rem) { + | [hd2, ...tl2] => [hd2] @ f(tl, l2_lab, tl2) + | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) } } | [] => [] }; - let tys = f(ts, l2_lab, l2_none); + let tys = f(ts, l2_matched, l2_rem); tys; }; | Unknown(SynSwitch) => From 55500e622f1df38c66d285173a5f44cd626b1fc1 Mon Sep 17 00:00:00 2001 From: WondAli Date: Mon, 22 Apr 2024 15:37:48 -0400 Subject: [PATCH 005/108] updated casting for labels --- src/haz3lcore/dynamics/DH.re | 10 ++++++++-- src/haz3lcore/dynamics/PatternMatch.re | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index 1b0c33cc71..c0afeb763f 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -158,12 +158,18 @@ module rec DHExp: { | [_] => failwith("mk_tuple: expected at least 2 elements") | xs => Tuple(xs); - let cast = (d: t, t1: Typ.t, t2: Typ.t): t => - if (Typ.eq(t1, t2) || t2 == Unknown(SynSwitch)) { + let cast = (d: t, t1: Typ.t, t2: Typ.t): t => { + let islabel = + switch (t2) { + | Label(_, Unknown(SynSwitch)) => true + | _ => false + }; + if (Typ.eq(t1, t2) || t2 == Unknown(SynSwitch) || islabel) { d; } else { Cast(d, t1, t2); }; + }; let apply_casts = (d: t, casts: list((Typ.t, Typ.t))): t => List.fold_left((d, (ty1, ty2)) => cast(d, ty1, ty2), d, casts); diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index bb0e7bb820..3ea51464ca 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -30,6 +30,7 @@ let cast_sum_maps = let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => switch (dp, d) { + // TODO: Fix TupLabel matching /* Labels are a special case */ | (TupLabel(s1, dp), TupLabel(s2, d)) => if (LabeledTuple.compare(s1, s2) == 0) { From f08c1145c80d52f5a1c7f96856216a45f47967e3 Mon Sep 17 00:00:00 2001 From: WondAli Date: Thu, 25 Apr 2024 19:43:33 -0400 Subject: [PATCH 006/108] left-associativity for dot operator --- src/haz3lcore/lang/Precedence.re | 1 + 1 file changed, 1 insertion(+) diff --git a/src/haz3lcore/lang/Precedence.re b/src/haz3lcore/lang/Precedence.re index 0eaf6ce07a..62beab79dd 100644 --- a/src/haz3lcore/lang/Precedence.re +++ b/src/haz3lcore/lang/Precedence.re @@ -48,6 +48,7 @@ let associativity_map: IntMap.t(Direction.t) = (concat, Right), (ann, Left), (eqs, Left), + (dot, Left), ] |> List.to_seq |> IntMap.of_seq; From 7ab1470ace9fae188b513bfe1b3ae3dcfbb23e52 Mon Sep 17 00:00:00 2001 From: WondAli Date: Thu, 25 Apr 2024 19:52:56 -0400 Subject: [PATCH 007/108] dot now treats labels as tuples of size 1 --- src/haz3lcore/dynamics/Transition.re | 1 + src/haz3lcore/statics/Statics.re | 1 + 2 files changed, 2 insertions(+) diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index b01f8db412..08d4f66f3c 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -484,6 +484,7 @@ module Transition = (EV: EV_MODE) => { | Some(TupLabel(_, exp)) => exp | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }; + | TupLabel(l, e) when LabeledTuple.compare(s, l) == 0 => e | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }, kind: Dot(s), diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index f601207c71..270fafb3f8 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -295,6 +295,7 @@ and uexp_to_info_map = let element: option(Typ.t) = switch (e.ty) { | Prod(ts) => LabeledTuple.find_label(filt, ts, s) + | Label(l, t) when LabeledTuple.compare(s, l) == 0 => Some(t) | _ => None // TODO (Anthony): other exps }; switch (element) { From 1cdeb3a0b0bf64c09371a6aaca68e9c43500bf4a Mon Sep 17 00:00:00 2001 From: WondAli Date: Sun, 28 Apr 2024 15:40:02 -0400 Subject: [PATCH 008/108] multiple bug fixes and implemented labels as function arguments. TODO: optimize hacks for cleaner code, fix more bugs --- src/haz3lcore/dynamics/DH.re | 1 + src/haz3lcore/dynamics/PatternMatch.re | 90 ++++++++++++++++++++------ src/haz3lcore/dynamics/Transition.re | 18 +++++- src/haz3lcore/statics/Statics.re | 19 +++++- src/haz3lcore/statics/TypBase.re | 51 ++++++++++----- 5 files changed, 140 insertions(+), 39 deletions(-) diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index c0afeb763f..1bf0eecf1f 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -159,6 +159,7 @@ module rec DHExp: { | xs => Tuple(xs); let cast = (d: t, t1: Typ.t, t2: Typ.t): t => { + // TODO (Anthony): Other cases for label casting? let islabel = switch (t2) { | Label(_, Unknown(SynSwitch)) => true diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 3ea51464ca..a180cfe67b 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -179,15 +179,42 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => } }; }; - LabeledTuple.ana_tuple( - filt1, - filt2, - f, - Matches(Environment.empty), - DoesNotMatch, - dps, - ds, - ); + // TODO (Anthony): optimize to work both way intead of run-twice hack. + let f_reverse = (result, d, dp) => { + switch (result) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env) => + switch (matches(dp, d)) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env') => Matches(Environment.union(env, env')) + } + }; + }; + let fin = + LabeledTuple.ana_tuple( + filt1, + filt2, + f, + Matches(Environment.empty), + DoesNotMatch, + dps, + ds, + ); + switch (fin) { + | DoesNotMatch => + LabeledTuple.ana_tuple( + filt2, + filt1, + f_reverse, + Matches(Environment.empty), + DoesNotMatch, + ds, + dps, + ) + | _ => fin + }; | (Tuple(dps), Cast(d, Prod(tys), Prod(tys'))) => assert(List.length(tys) == List.length(tys')); matches_cast_Tuple( @@ -339,15 +366,42 @@ and matches_cast_Tuple = } }; }; - LabeledTuple.ana_tuple( - filt1, - filt2, - f, - Matches(Environment.empty), - DoesNotMatch, - dps, - List.combine(ds, elt_casts), - ); + // TODO (Anthony): optimize to work both way intead of run-twice hack. + let f_reverse = (result, (d, casts), dp) => { + switch (result) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env) => + switch (matches(dp, DHExp.apply_casts(d, casts))) { + | DoesNotMatch => DoesNotMatch + | IndetMatch => IndetMatch + | Matches(env') => Matches(Environment.union(env, env')) + } + }; + }; + let fin = + LabeledTuple.ana_tuple( + filt1, + filt2, + f, + Matches(Environment.empty), + DoesNotMatch, + dps, + List.combine(ds, elt_casts), + ); + switch (fin) { + | DoesNotMatch => + LabeledTuple.ana_tuple( + filt2, + filt1, + f_reverse, + Matches(Environment.empty), + DoesNotMatch, + List.combine(ds, elt_casts), + dps, + ) + | _ => fin + }; } | Cast(d', Prod(tys), Prod(tys')) => if (List.length(dps) != List.length(tys)) { diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index 08d4f66f3c..5bcd5cae23 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -219,6 +219,21 @@ module Transition = (EV: EV_MODE) => { Constructor; | Fun(p, t, d, v) => let. _ = otherwise(env, Fun(p, t, d, v)); + let p = + switch (p) { + | Tuple(l) => + DHPat.Tuple( + List.map( + (x): DHPat.t => + switch (x) { + | DHPat.Var(s) => TupLabel(s, x) + | _ => x + }, + l, + ), + ) + | _ => p + }; Step({ apply: () => Fun(p, t, Closure(env, d), v), kind: FunClosure, @@ -493,8 +508,7 @@ module Transition = (EV: EV_MODE) => { | TupLabel(p, d1) => // TODO (Anthony): Fix this if needed let. _ = otherwise(env, d1 => TupLabel(p, d1)) - and. _ = req_value(req(state, env), d1 => TupLabel(p, d1), d1); - // Hidden step + and. _ = req_final(req(state, env), d1 => TupLabel(p, d1), d1); Constructor; | Tuple(ds) => let. _ = otherwise(env, ds => Tuple(ds)) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 270fafb3f8..b38c746b20 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -335,11 +335,24 @@ and uexp_to_info_map = go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, ~mode=mode_pat, p, m); let (e, m) = go'(~ctx=p'.ctx, ~mode=mode_body, e, m); /* add co_ctx to pattern */ - let (p, m) = + let (p'', m) = go_pat(~is_synswitch=false, ~co_ctx=e.co_ctx, ~mode=mode_pat, p, m); + let rec get_var = (p1: UPat.t, p2) => + switch (p1.term) { + | UPat.Var(s) => Typ.Label(s, p2) + | TypeAnn(s, _) => get_var(s, p2) + | _ => p2 + }; + let pty: Typ.t = + switch (p.term, p''.ty) { + | (Tuple(l1), Prod(l2)) => + let pt: list(Typ.t) = List.map2(get_var, l1, l2); + Prod(pt); + | _ => p''.ty + }; add( - ~self=Just(Arrow(p.ty, e.ty)), - ~co_ctx=CoCtx.mk(ctx, p.ctx, e.co_ctx), + ~self=Just(Arrow(pty, e.ty)), + ~co_ctx=CoCtx.mk(ctx, p''.ctx, e.co_ctx), m, ); | Let(p, def, body) => diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 4bc2197de8..a30f2f5376 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -200,8 +200,12 @@ module rec Typ: { | true => eq(tys1_val, tys2_val) }; }; + // TODO (Anthony): optimize to work both way intead of run-twice hack. List.length(tys1) == List.length(tys2) - && LabeledTuple.ana_tuple(filt, filt, f, true, false, tys1, tys2); + && ( + LabeledTuple.ana_tuple(filt, filt, f, true, false, tys1, tys2) + || LabeledTuple.ana_tuple(filt, filt, f, true, false, tys2, tys1) + ); | (Prod(_), _) => false | (List(t1), List(t2)) => eq(t1, t2) | (List(_), _) => false @@ -268,6 +272,16 @@ module rec Typ: { 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! */ + /* Labels have special rules. TODO (Anthony): Fix them */ + | (Label(s1, ty1), Label(s2, ty2)) => + if (compare(s1, s2) == 0) { + let+ ty = join'(ty1, ty2); + Label(s2, ty); + } else { + None; + } + | (Label(_, ty1), ty) => join'(ty1, ty) + | (ty, Label(_, ty2)) => join'(ty, ty2) | (Rec(x1, ty1), Rec(x2, ty2)) => /* TODO: This code isn't fully correct, as we may be doing @@ -294,16 +308,7 @@ module rec Typ: { let+ ty2 = join'(ty2, ty2'); Arrow(ty1, ty2); | (Arrow(_), _) => None - | (Label(s1, ty1), Label(s2, ty2)) => - if (compare(s1, s2) == 0) { - let+ ty = join'(ty1, ty2); - Label(s2, ty); - } else { - None; - } - | (Label(_), _) => None | (Prod(tys1), Prod(tys2)) => - let (tys1, tys2) = (tys2, tys1); // tessting let filt: t => option(LabeledTuple.t) = ( d => switch (d) { @@ -354,7 +359,7 @@ module rec Typ: { // Prod(tys); // } if (!l1_valid || !l2_valid || List.length(tys1) != List.length(tys2)) { - print_endline("fail"); + print_endline("Tuple join fail"); None; } else { let l2_rem = @@ -373,7 +378,7 @@ module rec Typ: { }, l2_matched, ) => l2_rem - | (Some(_), it) + | (Some(s), it) => l2_rem @ [Label(s, it)] | (None, it) => l2_rem @ [it] }; }, @@ -388,7 +393,12 @@ module rec Typ: { switch (hd) { | (Some(s1), l1_val) => switch (l2_matched) { - | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen + | [] => + switch (l2_rem) { + | [hd2, ...tl2] => + [join'(Label(s1, l1_val), hd2)] @ f(tl, l2_matched, tl2) + | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen + } | [hd2, ...tl2] => switch (hd2) { | (Some(s2), l2_val) when LabeledTuple.compare(s1, s2) == 0 => @@ -600,14 +610,23 @@ module rec Typ: { | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) // should never happen | [hd2, ...tl2] => switch (hd2) { - | (Some(s2), l2_val) when compare(s1, s2) == 0 => + | (Some(s2), l2_val) when LabeledTuple.compare(s1, s2) == 0 => [l2_val] @ f(tl, tl2, l2_rem) - | _ => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) + | _ => + switch (l2_rem) { + | [hd2, ...tl2] => + switch (hd2) { + | Label(_) => + [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) + | _ => [Label(s1, hd2)] @ f(tl, l2_matched, tl2) + } + | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) + } } } | None => switch (l2_rem) { - | [hd2, ...tl2] => [hd2] @ f(tl, l2_lab, tl2) + | [hd2, ...tl2] => [hd2] @ f(tl, l2_matched, tl2) | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) } } From 0598c9c22664e6ad3706ff4cbeca8f879eb1e521 Mon Sep 17 00:00:00 2001 From: WondAli Date: Thu, 6 Jun 2024 21:50:01 -0400 Subject: [PATCH 009/108] code cleanup, quality improvement. Also fixes to casting (mostly) --- src/haz3lcore/LabeledTuple.re | 157 ++++++++++++--- src/haz3lcore/dynamics/DH.re | 34 ++-- src/haz3lcore/dynamics/DHPat.re | 5 + src/haz3lcore/dynamics/PatternMatch.re | 158 ++++++++++----- src/haz3lcore/dynamics/Transition.re | 32 +-- src/haz3lcore/lang/Form.re | 6 +- src/haz3lcore/lang/Precedence.re | 19 +- src/haz3lcore/statics/Statics.re | 27 +-- src/haz3lcore/statics/Term.re | 32 +-- src/haz3lcore/statics/TypBase.re | 263 ++++--------------------- 10 files changed, 344 insertions(+), 389 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index c540974d4a..5b033784d8 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -1,5 +1,7 @@ open Sexplib.Std; +exception Exception; + [@deriving (show({with_path: false}), sexp, yojson)] type t = string; @@ -11,19 +13,19 @@ let compare = String.compare; let find_opt: ('a => bool, list('a)) => option('a) = List.find_opt; -// filt returns Some(string) if TupLabel or None if not a TupLabel // returns ordered list of (Some(string), TupLabel) // and another of (None, not-TupLabel) // TODO: Need to check uniqueness earlier // TODO: Make more efficient let validate_uniqueness: - ('a => option(t), list('a)) => (bool, list((option(t), 'a)), list('a)) = - (filt, es) => { + ('a => option((t, 'a)), list('a)) => + (bool, list((option(t), 'a)), list('a)) = + (get_label, es) => { let results = List.fold_left( ((b, ls, ns), e) => - switch (filt(e)) { - | Some(s1) + switch (get_label(e)) { + | Some((s1, _)) when b && List.fold_left( @@ -48,6 +50,119 @@ let validate_uniqueness: results; }; +// Assumes all labels are unique +// filt returns Some(string) if TupLabel or None if not a TupLabel +// returns a permutation of l2 that matches labels in l1 +let rearrange: + ( + 'a => option((t, 'a)), + 'b => option((t, 'b)), + list('a), + list('b), + (t, 'b) => 'b + ) => + list('b) = + (get_label1, get_label2, l1, l2, constructor) => { + // TODO: Error handling in case of bad arguments + let (_, l1_lab, _) = validate_uniqueness(get_label1, l1); + let (_, l2_lab, _) = validate_uniqueness(get_label2, l2); + // Second item in the pair is the full tuplabel + let l2_matched = + List.fold_left( + (l2_matched, l1_item) => { + let l2_item = + find_opt( + l2_item => { + switch (l1_item, l2_item) { + | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l2_item) { + | Some(l2_item) => l2_matched @ [l2_item] + | None => l2_matched + }; + }, + [], + l1_lab, + ); + // Second item in the pair is just the element half of the tuplabel + let l2_rem = + List.fold_left( + (l2_rem, item) => { + switch (get_label2(item)) { + | Some((s1, _)) + when + List.exists( + l => { + switch (l) { + | (Some(s2), _) => compare(s1, s2) == 0 + | _ => false + } + }, + l2_matched, + ) => l2_rem + | Some((s1, it)) => l2_rem @ [(Some(s1), it)] + | _ => l2_rem @ [(None, item)] + } + }, + [], + l2, + ); + let rec rearrange_helper = + ( + l1: list('x), + l2_matched: list((option(t), 'y)), + l2_rem: list((option(t), 'y)), + ) + : list('y) => + switch (l1) { + | [hd, ...tl] => + switch (get_label1(hd)) { + | Some((s1, _)) => + switch (l2_matched) { + | [] => + switch (l2_rem) { + | [hd2, ...tl2] => + switch (hd2) { + | (Some(_), _) => raise(Exception) + | (None, rem_val) => + [constructor(s1, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) + } + | [] => raise(Exception) + } + | [hd2, ...tl2] => + switch (hd2) { + | (Some(s2), l2_val) when compare(s1, s2) == 0 => + [l2_val] @ rearrange_helper(tl, tl2, l2_rem) + | _ => + switch (l2_rem) { + | [hd2, ...tl2] => + switch (hd2) { + | (Some(_), _) => raise(Exception) + | (None, rem_val) => + [constructor(s1, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) + } + | [] => raise(Exception) + } + } + } + | None => + switch (l2_rem) { + | [(_, hd2), ...tl2] => + [hd2] @ rearrange_helper(tl, l2_matched, tl2) + | [] => raise(Exception) + } + } + | [] => [] + }; + rearrange_helper(l1, l2_matched, l2_rem); + }; + // Rename and clean this // Assumes all labels are unique // filt returns Some(string) if TupLabel or None if not a TupLabel @@ -57,8 +172,8 @@ let validate_uniqueness: // Checks remaining None pairs in order and performs f on each pair let ana_tuple: ( - 'b => (option(t), 'b), - 'c => (option(t), 'c), + 'b => option((t, 'b)), + 'c => option((t, 'c)), ('a, 'b, 'c) => 'a, 'a, 'a, @@ -66,17 +181,9 @@ let ana_tuple: list('c) ) => 'a = - (filt1, filt2, f, accu, accu_fail, l1, l2) => { - let filt1_lab = x => { - let (s, _) = filt1(x); - s; - }; - let filt2_lab = x => { - let (s, _) = filt2(x); - s; - }; - let (l1_valid, l1_lab, l1_none) = validate_uniqueness(filt1_lab, l1); - let (l2_valid, l2_lab, _) = validate_uniqueness(filt2_lab, l2); + (get_label1, get_label2, f, accu, accu_fail, l1, l2) => { + let (l1_valid, l1_lab, l1_none) = validate_uniqueness(get_label1, l1); + let (l2_valid, l2_lab, _) = validate_uniqueness(get_label2, l2); // temporary solution if mess up earlier in tuple, such as make_term if (!l1_valid || !l2_valid) { accu_fail; @@ -115,9 +222,8 @@ let ana_tuple: let l2_rem = List.fold_left( (l2_rem, item) => { - let lab_opt = filt2(item); - switch (lab_opt) { - | (Some(s1), _) + switch (get_label2(item)) { + | Some((s1, _)) when List.exists( l => { @@ -128,9 +234,8 @@ let ana_tuple: }, l2_labels_matched, ) => l2_rem - | (Some(_), it) - | (None, it) => l2_rem @ [it] - }; + | _ => l2_rem @ [item] + } }, [], l2, @@ -148,12 +253,12 @@ let ana_tuple: }; }; -let find_label: ('a => option(t), list('a), t) => option('a) = +let find_label: ('a => option((t, 'a)), list('a), t) => option('a) = (filt, es, label) => { find_opt( e => { switch (filt(e)) { - | Some(s) => compare(s, label) == 0 + | Some((s, _)) => compare(s, label) == 0 | None => false } }, diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index 1bf0eecf1f..852b3e4925 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -61,6 +61,8 @@ module rec DHExp: { let strip_casts: t => t; let fast_equal: (t, t) => bool; + + let get_label: t => option((LabeledTuple.t, t)); } = { [@deriving (show({with_path: false}), sexp, yojson)] type t = @@ -158,15 +160,22 @@ module rec DHExp: { | [_] => failwith("mk_tuple: expected at least 2 elements") | xs => Tuple(xs); + let get_label: t => option((LabeledTuple.t, t)) = + fun + | TupLabel(s, t') => Some((s, t')) + | _ => None; + let cast = (d: t, t1: Typ.t, t2: Typ.t): t => { // TODO (Anthony): Other cases for label casting? - let islabel = + let (islabel, lab) = switch (t2) { - | Label(_, Unknown(SynSwitch)) => true - | _ => false + | Label(s, Unknown(SynSwitch)) => (true, s) + | _ => (false, "") }; - if (Typ.eq(t1, t2) || t2 == Unknown(SynSwitch) || islabel) { + if (Typ.eq(t1, t2) || t2 == Unknown(SynSwitch)) { d; + } else if (islabel) { + TupLabel(lab, d); } else { Cast(d, t1, t2); }; @@ -267,13 +276,6 @@ module rec DHExp: { | (ListConcat(d11, d21), ListConcat(d12, d22)) => fast_equal(d11, d12) && fast_equal(d21, d22) | (Tuple(ds1), Tuple(ds2)) => - let filt: t => (option(LabeledTuple.t), t) = ( - d => - switch (d) { - | TupLabel(s, d') => (Some(s), d') - | _ => (None, d) - } - ); let f = (b, ds1_val, ds2_val) => { switch (b) { | false => false @@ -281,7 +283,15 @@ module rec DHExp: { }; }; List.length(ds1) == List.length(ds2) - && LabeledTuple.ana_tuple(filt, filt, f, true, false, ds1, ds2); + && LabeledTuple.ana_tuple( + get_label, + get_label, + f, + true, + false, + ds1, + ds2, + ); | (Dot(d1, s1), Dot(d2, s2)) => LabeledTuple.compare(s1, s2) == 0 && d1 == d2 | (Prj(d1, n), Prj(d2, m)) => n == m && fast_equal(d1, d2) diff --git a/src/haz3lcore/dynamics/DHPat.re b/src/haz3lcore/dynamics/DHPat.re index d72c5a9caf..0e31524cec 100644 --- a/src/haz3lcore/dynamics/DHPat.re +++ b/src/haz3lcore/dynamics/DHPat.re @@ -72,3 +72,8 @@ let rec bound_vars = (dp: t): list(Var.t) => | ListLit(_, dps) => List.flatten(List.map(bound_vars, dps)) | Ap(_, dp1) => bound_vars(dp1) }; + +let get_label: t => option((LabeledTuple.t, t)) = + fun + | TupLabel(s, t') => Some((s, t')) + | _ => None; diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index a180cfe67b..0952cc0d9b 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -28,9 +28,16 @@ let cast_sum_maps = }; }; -let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => +let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => { switch (dp, d) { // TODO: Fix TupLabel matching + | (_, BoundVar(_)) => DoesNotMatch + | (EmptyHole(_), _) + | (NonEmptyHole(_), _) => IndetMatch + | (Wild, _) => Matches(Environment.empty) + | (ExpandingKeyword(_), _) => DoesNotMatch + | (InvalidText(_), _) => IndetMatch + | (BadConstructor(_), _) => IndetMatch /* Labels are a special case */ | (TupLabel(s1, dp), TupLabel(s2, d)) => if (LabeledTuple.compare(s1, s2) == 0) { @@ -38,16 +45,32 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => } else { DoesNotMatch; } + | (Var(x), TupLabel(s, d)) when LabeledTuple.compare(x, s) == 0 => + let env = Environment.extend(Environment.empty, (x, d)); + Matches(env); + // | (_, Cast(TupLabel(_, d), t1, t2)) => matches(dp, Cast(d, t1, t2)) + | (TupLabel(_), Cast(d, Label(_, _), Unknown(_))) => + switch (d) { + | TupLabel(_, d) => matches(dp, d) + | _ => matches(dp, d) + } + | (TupLabel(_), Cast(d, Unknown(_), Label(s2, _))) => + switch (d) { + | TupLabel(_, d) => matches(dp, TupLabel(s2, d)) + | _ => matches(dp, TupLabel(s2, d)) + } + | (_, Cast(d, Label(_, ty1), ty2)) => + switch (d) { + | TupLabel(_, d) => matches(dp, Cast(d, ty1, ty2)) + | _ => matches(dp, Cast(d, ty1, ty2)) + } + | (_, Cast(d, ty1, Label(_, ty2))) => + switch (d) { + | TupLabel(_, d) => matches(dp, Cast(d, ty1, ty2)) // shouldn't happen? + | _ => matches(dp, Cast(d, ty1, ty2)) + } | (TupLabel(_, dp), _) => matches(dp, d) | (_, TupLabel(_, d)) => matches(dp, d) - - | (_, BoundVar(_)) => DoesNotMatch - | (EmptyHole(_), _) - | (NonEmptyHole(_), _) => IndetMatch - | (Wild, _) => Matches(Environment.empty) - | (ExpandingKeyword(_), _) => DoesNotMatch - | (InvalidText(_), _) => IndetMatch - | (BadConstructor(_), _) => IndetMatch | (Var(x), _) => let env = Environment.extend(Environment.empty, (x, d)); Matches(env); @@ -153,20 +176,6 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => | (Constructor(_), _) => DoesNotMatch | (Tuple(dps), Tuple(ds)) => - let filt1: DHPat.t => (option(LabeledTuple.t), DHPat.t) = ( - d => - switch (d) { - | TupLabel(s, d') => (Some(s), d') - | _ => (None, d) - } - ); - let filt2: DHExp.t => (option(LabeledTuple.t), DHExp.t) = ( - d => - switch (d) { - | TupLabel(s, d') => (Some(s), d') - | _ => (None, d) - } - ); let f = (result, dp, d) => { switch (result) { | DoesNotMatch => DoesNotMatch @@ -194,8 +203,8 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => }; let fin = LabeledTuple.ana_tuple( - filt1, - filt2, + DHPat.get_label, + DHExp.get_label, f, Matches(Environment.empty), DoesNotMatch, @@ -205,8 +214,8 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => switch (fin) { | DoesNotMatch => LabeledTuple.ana_tuple( - filt2, - filt1, + DHExp.get_label, + DHPat.get_label, f_reverse, Matches(Environment.empty), DoesNotMatch, @@ -217,11 +226,36 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => }; | (Tuple(dps), Cast(d, Prod(tys), Prod(tys'))) => assert(List.length(tys) == List.length(tys')); - matches_cast_Tuple( - dps, - d, - List.map(p => [p], List.combine(tys, tys')), - ); + switch (d) { + | TupLabel(_, Tuple(ds)) + | Tuple(ds) => + let d_typ_pairs = List.combine(ds, tys); + let get_label_pair: + ((DHExp.t, Typ.t)) => option((LabeledTuple.t, (DHExp.t, Typ.t))) = ( + ((d, t)) => + switch (t) { + | Label(s, t') => Some((s, (d, t'))) + | _ => None + } + ); + let d_typ_pairs = + LabeledTuple.rearrange( + Typ.get_label, get_label_pair, tys', d_typ_pairs, (s, (d, t)) => + (TupLabel(s, d), Label(s, t)) + ); + let (ds, tys) = List.split(d_typ_pairs); + matches_cast_Tuple( + dps, + DHExp.Tuple(ds), + List.map(p => [p], List.combine(tys, tys')), + ); + | _ => + matches_cast_Tuple( + dps, + d, + List.map(p => [p], List.combine(tys, tys')), + ) + }; | (Tuple(dps), Cast(d, Prod(tys), Unknown(_))) => matches_cast_Tuple( dps, @@ -253,7 +287,8 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => | (Cons(_, _), ListLit(_)) | (ListLit(_), ListLit(_)) => matches_cast_Cons(dp, d, []) | (Cons(_) | ListLit(_), _) => DoesNotMatch - } + }; +} and matches_cast_Sum = ( ctr: string, @@ -339,18 +374,12 @@ and matches_cast_Tuple = if (List.length(dps) != List.length(ds)) { DoesNotMatch; } else { - let filt1: DHPat.t => (option(LabeledTuple.t), DHPat.t) = ( - d => - switch (d) { - | TupLabel(s, d') => (Some(s), d') - | _ => (None, d) - } - ); - let filt2: ((DHExp.t, 'a)) => (option(LabeledTuple.t), (DHExp.t, 'a)) = ( + let ds_elts = List.combine(ds, elt_casts); + let filt2: ((DHExp.t, 'a)) => option((LabeledTuple.t, (DHExp.t, 'a))) = ( ((d, c)) => switch (d) { - | TupLabel(s, d') => (Some(s), (d', c)) - | _ => (None, (d, c)) + | TupLabel(s, d') => Some((s, (d', c))) + | _ => None } ); assert(List.length(List.combine(dps, ds)) == List.length(elt_casts)); @@ -381,23 +410,23 @@ and matches_cast_Tuple = }; let fin = LabeledTuple.ana_tuple( - filt1, + DHPat.get_label, filt2, f, Matches(Environment.empty), DoesNotMatch, dps, - List.combine(ds, elt_casts), + ds_elts, ); switch (fin) { | DoesNotMatch => LabeledTuple.ana_tuple( filt2, - filt1, + DHPat.get_label, f_reverse, Matches(Environment.empty), DoesNotMatch, - List.combine(ds, elt_casts), + ds_elts, dps, ) | _ => fin @@ -408,11 +437,36 @@ and matches_cast_Tuple = DoesNotMatch; } else { assert(List.length(tys) == List.length(tys')); - matches_cast_Tuple( - dps, - d', - List.map2(List.cons, List.combine(tys, tys'), elt_casts), - ); + switch (d') { + | TupLabel(_, Tuple(ds)) + | Tuple(ds) => + let d_typ_pairs = List.combine(ds, tys); + let get_label_pair: + ((DHExp.t, Typ.t)) => option((LabeledTuple.t, (DHExp.t, Typ.t))) = ( + ((d, t)) => + switch (t) { + | Label(s, t') => Some((s, (d, t'))) + | _ => None + } + ); + let d_typ_pairs = + LabeledTuple.rearrange( + Typ.get_label, get_label_pair, tys', d_typ_pairs, (s, (d, t)) => + (TupLabel(s, d), Label(s, t)) + ); + let (ds, tys) = List.split(d_typ_pairs); + matches_cast_Tuple( + dps, + DHExp.Tuple(ds), + List.map2(List.cons, List.combine(tys, tys'), elt_casts), + ); + | _ => + matches_cast_Tuple( + dps, + d', + List.map2(List.cons, List.combine(tys, tys'), elt_casts), + ) + }; } | Cast(d', Prod(tys), Unknown(_)) => let tys' = List.init(List.length(tys), const_unknown); diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index 5bcd5cae23..1f43b05e1c 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -109,6 +109,7 @@ module CastHelpers = { | Var(_) | Rec(_) | Arrow(Unknown(_), Unknown(_)) + | Label(_, Unknown(_)) | List(Unknown(_)) => Ground | Prod(tys) => if (List.for_all( @@ -126,7 +127,8 @@ module CastHelpers = { ? Ground : grounded_Sum(sm) | Arrow(_, _) => grounded_Arrow | List(_) => grounded_List - | Label(_, ty) => ground_cases_of(ty) // TODO (Anthony): what to do here? + | Label(_, _) => NotGroundOrHole(Unknown(Internal)) + // | Label(_, ty) => ground_cases_of(ty) }; }; }; @@ -195,7 +197,7 @@ module Transition = (EV: EV_MODE) => { | Matches(env') => r(evaluate_extend_env(env', env)) }; - let transition = (req, state, env, d): 'a => + let transition = (req, state, env, d): 'a => { switch (d) { | BoundVar(x) => let. _ = otherwise(env, BoundVar(x)); @@ -219,21 +221,6 @@ module Transition = (EV: EV_MODE) => { Constructor; | Fun(p, t, d, v) => let. _ = otherwise(env, Fun(p, t, d, v)); - let p = - switch (p) { - | Tuple(l) => - DHPat.Tuple( - List.map( - (x): DHPat.t => - switch (x) { - | DHPat.Var(s) => TupLabel(s, x) - | _ => x - }, - l, - ), - ) - | _ => p - }; Step({ apply: () => Fun(p, t, Closure(env, d), v), kind: FunClosure, @@ -487,14 +474,7 @@ module Transition = (EV: EV_MODE) => { apply: () => switch (d') { | Tuple(ds) => - let filt: t => option(LabeledTuple.t) = ( - e => - switch (e) { - | TupLabel(s, _) => Some(s) - | _ => None - } - ); - let element = LabeledTuple.find_label(filt, ds, s); + let element = LabeledTuple.find_label(DHExp.get_label, ds, s); switch (element) { | Some(TupLabel(_, exp)) => exp | _ => raise(EvaluatorError.Exception(BadPatternMatch)) @@ -627,7 +607,6 @@ module Transition = (EV: EV_MODE) => { Indet; | Cast(d, t1, t2) => open CastHelpers; /* Cast calculus */ - let. _ = otherwise(env, d => Cast(d, t1, t2)) and. d' = req_final(req(state, env), d => Cast(d, t1, t2), d); switch (ground_cases_of(t1), ground_cases_of(t2)) { @@ -690,6 +669,7 @@ module Transition = (EV: EV_MODE) => { and. d1 = req_final(req(state, env), d1 => Filter(f1, d1), d1); Step({apply: () => d1, kind: CompleteFilter, value: true}); }; + }; }; let should_hide_step = (~settings: CoreSettings.Evaluation.t) => diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index d3e8f5a3ed..8c28b4dfeb 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -278,9 +278,9 @@ let forms: list((string, t)) = [ ("cons_exp", mk_infix("::", Exp, P.cons)), ("cons_pat", mk_infix("::", Pat, P.cons)), ("typeann", mk(ss, [":"], mk_bin'(P.ann, Pat, Pat, [], Typ))), - ("tuple_label_exp", mk(ss, ["="], mk_bin'(P.ann, Exp, Pat, [], Exp))), // TODO: Rename - ("tuple_label_pat", mk(ss, ["="], mk_bin'(P.ann, Pat, Pat, [], Pat))), // TODO: Rename - ("tuple_label_typ", mk(ss, ["="], mk_bin'(P.ann, Typ, Pat, [], Typ))), // TODO: Rename + ("tuple_label_exp", mk(ss, ["="], mk_bin'(P.lab, Exp, Pat, [], Exp))), // TODO: Rename + ("tuple_label_pat", mk(ss, ["="], mk_bin'(P.lab, Pat, Pat, [], Pat))), // TODO: Rename + ("tuple_label_typ", mk(ss, ["="], mk_bin'(P.lab, Typ, Pat, [], Typ))), // TODO: Rename ("dot_exp", mk(ss, ["."], mk_bin'(P.dot, Exp, Exp, [], Pat))), // TODO: Check precedence // ("dot_pat", mk(ss, ["."], mk_bin'(P.dot, Pat, Pat, [], Pat))), // Only for exp? // ("dot_typ", mk(ss, ["."], mk_bin'(P.dot, Typ, Typ, [], Pat))), // Only for exp? diff --git a/src/haz3lcore/lang/Precedence.re b/src/haz3lcore/lang/Precedence.re index 62beab79dd..d7e226bb0d 100644 --- a/src/haz3lcore/lang/Precedence.re +++ b/src/haz3lcore/lang/Precedence.re @@ -24,16 +24,17 @@ let or_ = 12; let ann = 13; let if_ = 14; let fun_ = 15; -let prod = 16; -let semi = 17; -let let_ = 18; -let filter = 19; -let rule_arr = 20; -let rule_pre = 21; -let rule_sep = 22; -let case_ = 23; +let lab = 16; +let prod = 17; +let semi = 18; +let let_ = 19; +let filter = 20; +let rule_arr = 21; +let rule_pre = 22; +let rule_sep = 23; +let case_ = 24; -let min = 24; +let min = 25; let compare = (p1: t, p2: t): int => (-1) * Int.compare((p1 :> int), (p2 :> int)); diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index b38c746b20..a5ae823084 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -268,14 +268,7 @@ and uexp_to_info_map = let (e, m) = go(~mode, e, m); add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); | Tuple(es) => - let filt: UExp.t => (option(LabeledTuple.t), UExp.t) = ( - e => - switch (e.term) { - | TupLabel(s, e') => (Some(s), e') - | _ => (None, e) - } - ); - let modes = Mode.of_prod(ctx, mode, es, filt); + let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); let (es, m) = map_m_go(m, modes, es); add( ~self=Just(Prod(List.map(Info.exp_ty, es))), @@ -285,16 +278,9 @@ and uexp_to_info_map = | Dot(e, s) => // TODO (Anthony): Fix this let (e, m) = go(~mode=Syn, e, m); - let filt: Typ.t => option(LabeledTuple.t) = ( - t => - switch (t) { - | Label(s, _) => Some(s) - | _ => None - } - ); let element: option(Typ.t) = switch (e.ty) { - | Prod(ts) => LabeledTuple.find_label(filt, ts, s) + | Prod(ts) => LabeledTuple.find_label(Typ.get_label, ts, s) | Label(l, t) when LabeledTuple.compare(s, l) == 0 => Some(t) | _ => None // TODO (Anthony): other exps }; @@ -552,14 +538,7 @@ and upat_to_info_map = let (p, m) = go(~ctx, ~mode, p, m); add(~self=Just(Label(s, p.ty)), ~ctx=p.ctx, m); | Tuple(ps) => - let filt: UPat.t => (option(LabeledTuple.t), UPat.t) = ( - p => - switch (p.term) { - | TupLabel(s, p') => (Some(s), p') - | _ => (None, p) - } - ); - let modes = Mode.of_prod(ctx, mode, ps, filt); + let modes = Mode.of_prod(ctx, mode, ps, UPat.get_label); let (ctx, tys, m) = ctx_fold(ctx, m, ps, modes); add(~self=Just(Prod(tys)), ~ctx, m); | Parens(p) => diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index a3bd03c2ac..0efb7678e6 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -427,6 +427,13 @@ module UPat = { | Constructor(name) => Some(name) | _ => None }; + + let get_label: t => option((LabeledTuple.t, t)) = + p => + switch (p.term) { + | TupLabel(s, p') => Some((s, p')) + | _ => None + }; }; module UExp = { @@ -604,22 +611,22 @@ module UExp = { | UnOp(op) => show_unop(op) | Match => "Case expression"; + let get_label: t => option((LabeledTuple.t, t)) = + e => + switch (e.term) { + | TupLabel(s, e') => Some((s, e')) + | _ => None + }; + let rec is_fun = (e: t) => { switch (e.term) { | Parens(e) => is_fun(e) | TupLabel(_, e) => is_fun(e) | Fun(_) => true | Dot(e, s) => - let filt: t => option(LabeledTuple.t) = ( - e => - switch (e.term) { - | TupLabel(s, _) => Some(s) - | _ => None - } - ); let element: option(t) = switch (e.term) { - | Tuple(ts) => LabeledTuple.find_label(filt, ts, s) + | Tuple(ts) => LabeledTuple.find_label(get_label, ts, s) | _ => None // TODO (Anthony): other exps }; switch (element) { @@ -662,16 +669,9 @@ module UExp = { | TupLabel(_, e) => is_tuple_of_functions(e) | Tuple(es) => es |> List.for_all(is_fun) | Dot(e, s) => - let filt: t => option(LabeledTuple.t) = ( - e => - switch (e.term) { - | TupLabel(s, _) => Some(s) - | _ => None - } - ); let element: option(t) = switch (e.term) { - | Tuple(ts) => LabeledTuple.find_label(filt, ts, s) + | Tuple(ts) => LabeledTuple.find_label(get_label, ts, s) | _ => None // TODO (Anthony): other exps }; switch (element) { diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index a30f2f5376..0f7c4a679b 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -55,7 +55,7 @@ module rec Typ: { let matched_arrow: (Ctx.t, t) => (t, t); let matched_label: (Ctx.t, t) => t; let matched_prod: - (Ctx.t, list('a), 'a => (option(LabeledTuple.t), 'a), t) => list(t); + (Ctx.t, list('a), 'a => option((LabeledTuple.t, 'a)), t) => list(t); let matched_list: (Ctx.t, t) => t; let precedence: t => int; let subst: (t, TypVar.t, t) => t; @@ -71,6 +71,7 @@ module rec Typ: { let sum_entry: (Constructor.t, sum_map) => option(sum_entry); let get_sum_constructors: (Ctx.t, t) => option(sum_map); let is_unknown: t => bool; + let get_label: t => option((LabeledTuple.t, t)); } = { [@deriving (show({with_path: false}), sexp, yojson)] type type_provenance = @@ -165,6 +166,11 @@ module rec Typ: { | _ => ty }; + let get_label: t => option((LabeledTuple.t, t)) = + fun + | Label(s, t') => Some((s, t')) + | _ => None; + /* 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 => { @@ -187,13 +193,6 @@ module rec Typ: { | (Arrow(t1, t2), Arrow(t1', t2')) => eq(t1, t1') && eq(t2, t2') | (Arrow(_), _) => false | (Prod(tys1), Prod(tys2)) => - let filt: t => (option(LabeledTuple.t), t) = ( - d => - switch (d) { - | Label(s, d') => (Some(s), d') - | _ => (None, d) - } - ); let f = (b, tys1_val, tys2_val) => { switch (b) { | false => false @@ -203,8 +202,24 @@ module rec Typ: { // TODO (Anthony): optimize to work both way intead of run-twice hack. List.length(tys1) == List.length(tys2) && ( - LabeledTuple.ana_tuple(filt, filt, f, true, false, tys1, tys2) - || LabeledTuple.ana_tuple(filt, filt, f, true, false, tys2, tys1) + LabeledTuple.ana_tuple( + get_label, + get_label, + f, + true, + false, + tys1, + tys2, + ) + || LabeledTuple.ana_tuple( + get_label, + get_label, + f, + true, + false, + tys2, + tys1, + ) ); | (Prod(_), _) => false | (List(t1), List(t2)) => eq(t1, t2) @@ -309,120 +324,19 @@ module rec Typ: { Arrow(ty1, ty2); | (Arrow(_), _) => None | (Prod(tys1), Prod(tys2)) => - let filt: t => option(LabeledTuple.t) = ( - d => - switch (d) { - | Label(s, _) => Some(s) - | _ => None - } - ); - let filt2: t => (option(LabeledTuple.t), t) = ( - d => - switch (d) { - | Label(s, ty) => (Some(s), ty) - | ty => (None, ty) - } - ); //TODO (Anthony): Clean up the repetition - let (l1_valid, l1_lab, _) = - LabeledTuple.validate_uniqueness(filt, tys1); - let (l2_valid, l2_lab, _) = - LabeledTuple.validate_uniqueness(filt, tys2); - let l1 = List.map(filt2, tys1); - let l2_matched = - List.fold_left( - (l2_matched, l1_item) => { - let l2_item = - LabeledTuple.find_opt( - l2_item => { - switch (l1_item, l2_item) { - | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l2_item) { - | Some((_, l2_val)) => l2_matched @ [filt2(l2_val)] - | None => l2_matched - }; - }, - [], - l1_lab, - ); - // TODO (Anthony): clean up error handling - // if (!l1_valid - // || !l2_valid - // || List.length(l2_matched) != List.length(l1_lab)) { - // let* tys = Some(List.init(List.length(tys1), _ => None)); - // let+ tys = OptUtil.sequence(tys); - // Prod(tys); - // } + let (l1_valid, _, _) = + LabeledTuple.validate_uniqueness(get_label, tys1); + let (l2_valid, _, _) = + LabeledTuple.validate_uniqueness(get_label, tys2); if (!l1_valid || !l2_valid || List.length(tys1) != List.length(tys2)) { - print_endline("Tuple join fail"); None; } else { - let l2_rem = - List.fold_left( - (l2_rem, item) => { - let lab_opt = filt2(item); - switch (lab_opt) { - | (Some(s1), _) - when - List.exists( - l => { - switch (l) { - | (Some(s2), _) => compare(s1, s2) == 0 - | _ => false - } - }, - l2_matched, - ) => l2_rem - | (Some(s), it) => l2_rem @ [Label(s, it)] - | (None, it) => l2_rem @ [it] - }; - }, - [], - tys2, + let tys2 = + LabeledTuple.rearrange(get_label, get_label, tys1, tys2, (t, b) => + Label(t, b) ); - let rec f = - (l1: list('a), l2_matched: list('a), l2_rem: list('b)) - : list(option(t)) => - switch (l1) { - | [hd, ...tl] => - switch (hd) { - | (Some(s1), l1_val) => - switch (l2_matched) { - | [] => - switch (l2_rem) { - | [hd2, ...tl2] => - [join'(Label(s1, l1_val), hd2)] @ f(tl, l2_matched, tl2) - | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen - } - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), l2_val) when LabeledTuple.compare(s1, s2) == 0 => - [join'(Label(s1, l1_val), Label(s2, l2_val))] - @ f(tl, tl2, l2_rem) - | _ => - switch (l2_rem) { - | [hd2, ...tl2] => - [join'(Label(s1, l1_val), hd2)] - @ f(tl, l2_matched, tl2) - | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen - } - } - } - | (None, l1_val) => - switch (l2_rem) { - | [hd2, ...tl2] => - [join'(l1_val, hd2)] @ f(tl, l2_matched, tl2) - | [] => [None] @ f(tl, l2_matched, l2_rem) // should never happen - } - } - | [] => [] - }; - let* tys = Some(f(l1, l2_matched, l2_rem)); + let* tys = ListUtil.map2_opt(join', tys1, tys2); let+ tys = OptUtil.sequence(tys); Prod(tys); }; @@ -527,113 +441,20 @@ module rec Typ: { | _ => Unknown(Internal) }; - let matched_prod = (ctx, ts, filt, ty) => { + let matched_prod = (ctx, ts, get_label_ts, ty) => { //TODO (Anthony): Clean up the repetition - let filt2 = d => - switch (d) { - | Label(s, d') => (Some(s), d') - | _ => (None, d) - }; - let filt_lab = d => - switch (filt(d)) { - | (Some(s), _) => Some(s) - | (None, _) => None - }; - let filt2_lab = d => - switch (d) { - | Label(s, _) => Some(s) - | _ => None - }; switch (weak_head_normalize(ctx, ty)) { | Prod(tys) => - let (l1_valid, l1_lab, _) = - LabeledTuple.validate_uniqueness(filt_lab, ts); - let (l2_valid, l2_lab, _) = - LabeledTuple.validate_uniqueness(filt2_lab, tys); - let l2_matched = - List.fold_left( - (l2_matched, l1_item) => { - let l2_item = - LabeledTuple.find_opt( - l2_item => { - switch (l1_item, l2_item) { - | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l2_item) { - | Some(l2_item) => l2_matched @ [l2_item] - | None => l2_matched - }; - }, - [], - l1_lab, - ); - if (!l1_valid - || !l2_valid - || List.length(l2_matched) != List.length(l1_lab)) { + let (l1_valid, _, _) = + LabeledTuple.validate_uniqueness(get_label_ts, ts); + let (l2_valid, _, _) = + LabeledTuple.validate_uniqueness(get_label, tys); + if (!l1_valid || !l2_valid || List.length(ts) != List.length(tys)) { List.init(List.length(ts), _ => Unknown(Internal)); } else { - let l2_rem = - List.fold_left( - (l2_rem, item) => { - let lab_opt = filt2(item); - switch (lab_opt) { - | (Some(s1), _) - when - List.exists( - l => { - switch (l) { - | (Some(s2), _) => compare(s1, s2) == 0 - | _ => false - } - }, - l2_matched, - ) => l2_rem - | (Some(_), it) - | (None, it) => l2_rem @ [it] - }; - }, - [], - tys, - ); - let rec f = - (l1: list('a), l2_matched: list('b), l2_rem: list('c)) - : list(t) => - switch (l1) { - | [hd, ...tl] => - switch (filt_lab(hd)) { - | Some(s1) => - switch (l2_matched) { - | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) // should never happen - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), l2_val) when LabeledTuple.compare(s1, s2) == 0 => - [l2_val] @ f(tl, tl2, l2_rem) - | _ => - switch (l2_rem) { - | [hd2, ...tl2] => - switch (hd2) { - | Label(_) => - [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) - | _ => [Label(s1, hd2)] @ f(tl, l2_matched, tl2) - } - | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) - } - } - } - | None => - switch (l2_rem) { - | [hd2, ...tl2] => [hd2] @ f(tl, l2_matched, tl2) - | [] => [Unknown(Internal)] @ f(tl, l2_matched, l2_rem) - } - } - | [] => [] - }; - let tys = f(ts, l2_matched, l2_rem); - tys; + LabeledTuple.rearrange(get_label_ts, get_label, ts, tys, (t, b) => + Label(t, b) + ); }; | Unknown(SynSwitch) => List.init(List.length(ts), _ => Unknown(SynSwitch)) From b3e7c8414b33b1c016373294d9080fcbda293a4c Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 7 Jun 2024 00:33:24 -0400 Subject: [PATCH 010/108] casting bug fix --- src/haz3lcore/dynamics/PatternMatch.re | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 0952cc0d9b..6b804c0315 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -229,6 +229,11 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => { switch (d) { | TupLabel(_, Tuple(ds)) | Tuple(ds) => + let ds = + LabeledTuple.rearrange( + Typ.get_label, DHExp.get_label, tys, ds, (s, e) => + TupLabel(s, e) + ); let d_typ_pairs = List.combine(ds, tys); let get_label_pair: ((DHExp.t, Typ.t)) => option((LabeledTuple.t, (DHExp.t, Typ.t))) = ( @@ -440,6 +445,11 @@ and matches_cast_Tuple = switch (d') { | TupLabel(_, Tuple(ds)) | Tuple(ds) => + let ds = + LabeledTuple.rearrange( + Typ.get_label, DHExp.get_label, tys, ds, (s, e) => + TupLabel(s, e) + ); let d_typ_pairs = List.combine(ds, tys); let get_label_pair: ((DHExp.t, Typ.t)) => option((LabeledTuple.t, (DHExp.t, Typ.t))) = ( From 07275dbab313b66e620e9861949ac882abe8edf0 Mon Sep 17 00:00:00 2001 From: WondAli Date: Tue, 25 Jun 2024 16:56:10 -0400 Subject: [PATCH 011/108] minor changes to dot in statics and matching --- src/haz3lcore/dynamics/PatternMatch.re | 1 + src/haz3lcore/dynamics/Transition.re | 9 +++++++-- src/haz3lcore/statics/Statics.re | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index f47f2c87a4..3d5232b2c7 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -85,6 +85,7 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => { | (_, BinBoolOp(_)) => IndetMatch | (_, BinIntOp(_)) => IndetMatch | (_, BinFloatOp(_)) => IndetMatch + | (_, Dot(_)) => IndetMatch | (_, ConsistentCase(Case(_))) => IndetMatch /* Closure should match like underlying expression. */ diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index 99f95cc23d..61ec2c6a27 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -217,6 +217,7 @@ module Transition = (EV: EV_MODE) => { }; let transition = (req, state, env, d): 'a => { + // print_endline(DHExp.show(d)); switch (d) { | BoundVar(x) => let. _ = otherwise(env, BoundVar(x)); @@ -547,6 +548,8 @@ module Transition = (EV: EV_MODE) => { | Dot(d, s) => let. _ = otherwise(env, d => Dot(d, s)) and. d' = req_final(req(state, env), d => Dot(d, s), d); + // print_endline("dot final"); + // print_endline(DHExp.show(d')); // TODO (Anthony): fix step if needed Step({ apply: () => @@ -557,11 +560,11 @@ module Transition = (EV: EV_MODE) => { | Some(TupLabel(_, exp)) => exp | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }; - | TupLabel(l, e) when LabeledTuple.compare(s, l) == 0 => e + | TupLabel(l, exp) when LabeledTuple.compare(s, l) == 0 => exp | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }, kind: Dot(s), - value: true, + value: false, }); | TupLabel(p, d1) => // TODO (Anthony): Fix this if needed @@ -680,6 +683,8 @@ module Transition = (EV: EV_MODE) => { open CastHelpers; /* Cast calculus */ let. _ = otherwise(env, d => Cast(d, t1, t2)) and. d' = req_final(req(state, env), d => Cast(d, t1, t2), d); + // print_endline("cast final"); + // print_endline(DHExp.show(d')); switch (ground_cases_of(t1), ground_cases_of(t2)) { | (Hole, Hole) | (Ground, Ground) => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 03ae049266..58ae69bca6 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -306,7 +306,8 @@ and uexp_to_info_map = }; switch (element) { | Some(Label(_, exp)) => add(~self=Just(exp), ~co_ctx=e.co_ctx, m) - | _ => add(~self=Just(Unknown(Internal)), ~co_ctx=e.co_ctx, m) + | Some(exp) => add(~self=Just(exp), ~co_ctx=e.co_ctx, m) + | None => add(~self=Just(Unknown(Internal)), ~co_ctx=e.co_ctx, m) }; | Test(e) => let (e, m) = go(~mode=Ana(Bool), e, m); From 44841b89394239e432b715a28a090b5c00860fdd Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 28 Jun 2024 16:16:03 -0400 Subject: [PATCH 012/108] standalone labels as singleton tuples + shifting error handling for unmatched labels in function parameters --- src/haz3lcore/LabeledTuple.re | 26 ++++++++++++++++++++++++-- src/haz3lcore/statics/Statics.re | 23 +++++++++++++++++++---- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 5b033784d8..9cd84145f3 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -13,6 +13,23 @@ let compare = String.compare; let find_opt: ('a => bool, list('a)) => option('a) = List.find_opt; +// returns a pair containing a list of option(t) and a list of 'a +let seperate_labels: + ('a => option((t, 'a)), list('a)) => (list(option(t)), list('a)) = + (get_label, es) => { + let results = + List.fold_left( + ((ls, ns), e) => + switch (get_label(e)) { + | Some((s1, e)) => (ls @ [Some(s1)], ns @ [e]) + | None => (ls @ [None], ns @ [e]) + }, + ([], []), + es, + ); + results; + }; + // returns ordered list of (Some(string), TupLabel) // and another of (None, not-TupLabel) // TODO: Need to check uniqueness earlier @@ -53,6 +70,7 @@ let validate_uniqueness: // Assumes all labels are unique // filt returns Some(string) if TupLabel or None if not a TupLabel // returns a permutation of l2 that matches labels in l1 +// other labels are in order, even if not matching. let rearrange: ( 'a => option((t, 'a)), @@ -127,7 +145,9 @@ let rearrange: switch (l2_rem) { | [hd2, ...tl2] => switch (hd2) { - | (Some(_), _) => raise(Exception) + | (Some(s2), rem_val) => + [constructor(s2, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) | (None, rem_val) => [constructor(s1, rem_val)] @ rearrange_helper(tl, l2_matched, tl2) @@ -142,7 +162,9 @@ let rearrange: switch (l2_rem) { | [hd2, ...tl2] => switch (hd2) { - | (Some(_), _) => raise(Exception) + | (Some(s2), rem_val) => + [constructor(s2, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) | (None, rem_val) => [constructor(s1, rem_val)] @ rearrange_helper(tl, l2_matched, tl2) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 58ae69bca6..f097274baa 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -171,6 +171,7 @@ and uexp_to_info_map = ~ctx: Ctx.t, ~mode=Mode.Syn, ~is_in_filter=false, + ~is_contained=false, ~ancestors, {ids, term} as uexp: UExp.t, m: Map.t, @@ -194,18 +195,27 @@ and uexp_to_info_map = ~ctx, ~mode=Mode.Syn, ~is_in_filter=is_in_filter, + ~is_contained=false, ~ancestors=ancestors, uexp: UExp.t, m: Map.t, ) => { - uexp_to_info_map(~ctx, ~mode, ~is_in_filter, ~ancestors, uexp, m); + uexp_to_info_map( + ~ctx, + ~mode, + ~is_in_filter, + ~is_contained, + ~ancestors, + uexp, + m, + ); }; 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)), + go(~mode, e, m, ~is_contained=true) |> (((e, m)) => (es @ [e], m)), ([], m), ); let go_pat = upat_to_info_map(~ctx, ~ancestors); @@ -283,10 +293,15 @@ and uexp_to_info_map = 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); - | TupLabel(s, e) => + | TupLabel(s, e) when is_contained => let mode = Mode.of_label(ctx, mode); let (e, m) = go(~mode, e, m); + // treating standalone labeled expressions as within a tuple of size 1 add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); + | TupLabel(s, e) => + let mode = Mode.of_label(ctx, mode); + let (e, m) = go(~mode, e, m); + add(~self=Just(Prod([Label(s, e.ty)])), ~co_ctx=e.co_ctx, m); | Tuple(es) => let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); let (es, m) = map_m_go(m, modes, es); @@ -301,7 +316,7 @@ and uexp_to_info_map = let element: option(Typ.t) = switch (e.ty) { | Prod(ts) => LabeledTuple.find_label(Typ.get_label, ts, s) - | Label(l, t) when LabeledTuple.compare(s, l) == 0 => Some(t) + // | Label(l, t) when LabeledTuple.compare(s, l) == 0 => Some(t) | _ => None // TODO (Anthony): other exps }; switch (element) { From 56d9a506f6c493951285e321ba4eabdf1989bbf3 Mon Sep 17 00:00:00 2001 From: WondAli Date: Wed, 3 Jul 2024 19:57:37 -0400 Subject: [PATCH 013/108] fixed bug concerning rearranging function arguments --- src/haz3lcore/dynamics/PatternMatch.re | 2 +- src/haz3lcore/dynamics/Transition.re | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 3d5232b2c7..8cd1b61518 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -47,7 +47,7 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => { | (Var(x), TupLabel(s, d)) when LabeledTuple.compare(x, s) == 0 => let env = Environment.extend(Environment.empty, (x, d)); Matches(env); - // | (_, Cast(TupLabel(_, d), t1, t2)) => matches(dp, Cast(d, t1, t2)) + // TODO: Label casting need fixing? | (TupLabel(_), Cast(d, Label(_, _), Unknown(_))) => switch (d) { | TupLabel(_, d) => matches(dp, d) diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index 61ec2c6a27..85d4be09fd 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -343,6 +343,22 @@ module Transition = (EV: EV_MODE) => { switch (d1') { | Constructor(_) => Constructor | Fun(dp, _, Closure(env', d3), _) => + // Wrap the arguments into labels for label rearrangement + let dp: DHPat.t = + switch (dp) { + | Tuple(args) => + Tuple( + List.map( + (p): DHPat.t => + switch (p) { + | DHPat.Var(s) => TupLabel(s, p) + | _ => p + }, + args, + ), + ) + | _ => dp + }; let.match env'' = (env', matches(dp, d2')); Step({apply: () => Closure(env'', d3), kind: FunAp, value: false}); | Cast(d3', Arrow(ty1, ty2), Arrow(ty1', ty2')) => From 3d294dd2e048b8a97ced9ec2339b3e67702b432d Mon Sep 17 00:00:00 2001 From: WondAli Date: Tue, 30 Jul 2024 11:36:56 -0400 Subject: [PATCH 014/108] documentation in progress --- src/haz3lweb/explainthis/Example.re | 4 ++ src/haz3lweb/explainthis/ExplainThisForm.re | 15 +++++ src/haz3lweb/explainthis/data/DotExp.re | 27 +++++++++ src/haz3lweb/explainthis/data/FunctionExp.re | 31 ++++++++++ src/haz3lweb/explainthis/data/LabelExp.re | 32 ++++++++++ src/haz3lweb/explainthis/data/LabelPat.re | 22 +++++++ src/haz3lweb/explainthis/data/LabelTyp.re | 16 +++++ src/haz3lweb/explainthis/data/LetExp.re | 38 ++++++++++++ src/haz3lweb/view/ExplainThis.re | 63 ++++++++++++++++---- 9 files changed, 238 insertions(+), 10 deletions(-) create mode 100644 src/haz3lweb/explainthis/data/DotExp.re create mode 100644 src/haz3lweb/explainthis/data/LabelExp.re create mode 100644 src/haz3lweb/explainthis/data/LabelPat.re create mode 100644 src/haz3lweb/explainthis/data/LabelTyp.re diff --git a/src/haz3lweb/explainthis/Example.re b/src/haz3lweb/explainthis/Example.re index aa52317ced..50caa95513 100644 --- a/src/haz3lweb/explainthis/Example.re +++ b/src/haz3lweb/explainthis/Example.re @@ -112,6 +112,10 @@ let comma_exp = () => mk_monotile(Form.get("comma_exp")); let comma_pat = () => mk_monotile(Form.get("comma_pat")); let comma_typ = () => mk_monotile(Form.get("comma_typ")); let pipeline = () => mk_monotile(Form.get("pipeline")); +let label_exp = () => mk_monotile(Form.get("tuple_label_exp")); +let label_pat = () => mk_monotile(Form.get("tuple_label_pat")); +let label_typ = () => mk_monotile(Form.get("tuple_label_typ")); +let dot = () => mk_monotile(Form.get("dot_exp")); let nil = () => exp("[]"); let deferral = () => exp("_"); let typeann = () => mk_monotile(Form.get("typeann")); diff --git a/src/haz3lweb/explainthis/ExplainThisForm.re b/src/haz3lweb/explainthis/ExplainThisForm.re index b0a71f68a0..ede84ffe4a 100644 --- a/src/haz3lweb/explainthis/ExplainThisForm.re +++ b/src/haz3lweb/explainthis/ExplainThisForm.re @@ -33,6 +33,7 @@ type fun_examples = | ConsSnd | VarIncr | VarAnd + | TupLabel | Tuple2 | Tuple3 | Ctr @@ -52,6 +53,7 @@ type let_examples = | ConsHd | ConsSnd | Var + | TupLabel | Tuple2 | Tuple3 | Ctr @@ -84,6 +86,10 @@ type example_id = | List(list_examples) | TypFun(typfun_examples) | Fun(fun_examples) + | Label1 + | Label2 + | Dot1 + | Dot2 | Tuple1 | Tuple2 | Let(let_examples) @@ -139,6 +145,7 @@ type pat_sub_form_id = | ListLit | ListCons | Var + | TupLabel | Tuple | Tuple2 | Tuple3 @@ -162,6 +169,8 @@ type form_id = | ListConcatExp | TypFunctionExp | FunctionExp(pat_sub_form_id) + | LabelExp + | DotExp | TupleExp | Tuple2Exp | Tuple3Exp @@ -191,6 +200,7 @@ type form_id = | ListNilPat | ConsPat | Cons2Pat + | LabelPat | TuplePat | Tuple2Pat | Tuple3Pat @@ -208,6 +218,7 @@ type form_id = | RecTyp | ArrowTyp | Arrow3Typ + | LabelTyp | TupleTyp | Tuple0Typ | Tuple2Typ @@ -253,6 +264,8 @@ type group_id = | ListConcatExp | TypFunctionExp | FunctionExp(pat_sub_form_id) + | LabelExp + | DotExp | TupleExp | Tuple2Exp | Tuple3Exp @@ -283,6 +296,7 @@ type group_id = | ListNilPat | ConsPat | Cons2Pat + | LabelPat | TuplePat | Tuple2Pat | Tuple3Pat @@ -300,6 +314,7 @@ type group_id = | RecTyp | ArrowTyp | Arrow3Typ + | LabelTyp | TupleTyp | Tuple0Typ | Tuple2Typ diff --git a/src/haz3lweb/explainthis/data/DotExp.re b/src/haz3lweb/explainthis/data/DotExp.re new file mode 100644 index 0000000000..8c7081b6f3 --- /dev/null +++ b/src/haz3lweb/explainthis/data/DotExp.re @@ -0,0 +1,27 @@ +// open Haz3lcore; +open ExplainThisForm; +open Example; + +let dot_example_1 = { + sub_id: Dot1, + term: mk_example("(x=1, y=2).x"), + message: "Gives the element in the tuple associated with the label 'x', which in this example is 1.", +}; +let dot_exp: form = { + let explanation = "Dot Operator explanation"; + { + id: DotExp, + syntactic_form: [exp("(x=e)"), dot(), pat("x")], + expandable_id: None, + explanation, + examples: [dot_example_1], + }; +}; +// let _exp1 = exp("e1"); +// let _exp2 = exp("e2"); +// let tuple_exp_size2_coloring_ids = +// (~exp1_id: Id.t, ~exp2_id: Id.t): list((Id.t, Id.t)) => { +// [(Piece.id(_exp1), exp1_id), (Piece.id(_exp2), exp2_id)]; +// } + +let dot_exp: group = {id: DotExp, forms: [dot_exp]}; diff --git a/src/haz3lweb/explainthis/data/FunctionExp.re b/src/haz3lweb/explainthis/data/FunctionExp.re index 895f9d7db6..0b6fd05354 100644 --- a/src/haz3lweb/explainthis/data/FunctionExp.re +++ b/src/haz3lweb/explainthis/data/FunctionExp.re @@ -77,6 +77,11 @@ let tuple3_fun_ex = { term: mk_example("fun (a, b, c) ->\na && b && c"), message: "When given a 3-tuple of booleans, the function evaluates to the logical-and of the three booleans.", }; +let label_fun_ex = { + sub_id: Fun(TupLabel), + term: mk_example("fun x=y, y=z ->\ny"), + message: "When given a 2-tuple of elements, the function evaluates to the first element (not the second).", +}; let ctr_fun_ex = { sub_id: Fun(Ctr), term: mk_example("fun None -> 1"), @@ -311,6 +316,27 @@ let function_var_exp: form = { examples: [basic_fun_ex, var_incr_fun_ex, var_and_fun_ex], }; }; + +let _label_pat = label_pat(); +let _exp = exp("e"); +let function_label_exp_coloring_ids = + _pat_body_function_exp_coloring_ids(Piece.id(_label_pat), Piece.id(_exp)); +let function_label_exp: form = { + let explanation = "Any unlabeled value matches with the [*argument*]. Only labeled elements that match the [*name*](%s) 'x' are accepted, and evaluate using the [*value*](%s) 'y' to the function [*body*](%s)."; + let form = [ + mk_fun([[space(), pat("x"), _label_pat, pat("y"), space()]]), + space(), + _exp, + ]; + { + id: FunctionExp(TupLabel), + syntactic_form: form, + expandable_id: + Some((Piece.id(_label_pat), [pat("x"), label_pat(), pat("y")])), + explanation, + examples: [label_fun_ex], + }; +}; let _comma = comma_pat(); let _exp = exp("e"); let function_tuple_exp_coloring_ids = @@ -501,6 +527,11 @@ let functions_var = { forms: [function_var_exp, function_exp], }; +let functions_tuplabel = { + id: FunctionExp(TupLabel), + forms: [function_label_exp, function_exp], +}; + let functions_tuple = { id: FunctionExp(Tuple), forms: [function_tuple_exp, function_exp], diff --git a/src/haz3lweb/explainthis/data/LabelExp.re b/src/haz3lweb/explainthis/data/LabelExp.re new file mode 100644 index 0000000000..af2936cd49 --- /dev/null +++ b/src/haz3lweb/explainthis/data/LabelExp.re @@ -0,0 +1,32 @@ +// open Haz3lcore; +open ExplainThisForm; +open Example; + +let label_example_1 = { + sub_id: Label1, + term: mk_example("(x=1)"), + message: "A labeled expression within a singleton tuple, where the element 1 is assigned the label 'x'. ", +}; +let label_example_2 = { + sub_id: Label2, + term: mk_example("(1, 2, y=3)"), + message: "A tuple with first element 1, second element 2, and third element 3 with the label 'y'.", +}; +let label_exp: form = { + let explanation = "Labeled Expession explanation"; + { + id: LabelExp, + syntactic_form: [exp("x"), label_exp(), exp("e")], + expandable_id: None, + explanation, + examples: [label_example_1, label_example_2], + }; +}; +// let _exp1 = exp("e1"); +// let _exp2 = exp("e2"); +// let tuple_exp_size2_coloring_ids = +// (~exp1_id: Id.t, ~exp2_id: Id.t): list((Id.t, Id.t)) => { +// [(Piece.id(_exp1), exp1_id), (Piece.id(_exp2), exp2_id)]; +// } + +let label_exp: group = {id: LabelExp, forms: [label_exp]}; diff --git a/src/haz3lweb/explainthis/data/LabelPat.re b/src/haz3lweb/explainthis/data/LabelPat.re new file mode 100644 index 0000000000..8362810e66 --- /dev/null +++ b/src/haz3lweb/explainthis/data/LabelPat.re @@ -0,0 +1,22 @@ +// open Haz3lcore; +open Example; +open ExplainThisForm; +// let _pat = pat("p"); +// let _typ = typ("ty"); +// let labeled_pat_coloring_ids = +// (~pat_id: Id.t, ~typ_id: Id.t): list((Id.t, Id.t)) => [ +// (Piece.id(_pat), pat_id), +// (Piece.id(_typ), typ_id), +// ]; +let label_pat: form = { + let explanation = "labeled pattern explanation"; + { + id: LabelPat, + syntactic_form: [pat("x"), label_pat(), pat("p")], + expandable_id: None, + explanation, + examples: [], + }; +}; + +let label_pat: group = {id: LabelPat, forms: [label_pat]}; diff --git a/src/haz3lweb/explainthis/data/LabelTyp.re b/src/haz3lweb/explainthis/data/LabelTyp.re new file mode 100644 index 0000000000..2774e4ce46 --- /dev/null +++ b/src/haz3lweb/explainthis/data/LabelTyp.re @@ -0,0 +1,16 @@ +open Example; +open ExplainThisForm; +// open Haz3lcore; + +let label_typ: form = { + let explanation = "label type explanation"; + { + id: LabelTyp, + syntactic_form: [pat("x"), label_typ(), typ("t")], + expandable_id: None, + explanation, + examples: [], + }; +}; + +let label_typ: group = {id: LabelTyp, forms: [label_typ]}; diff --git a/src/haz3lweb/explainthis/data/LetExp.re b/src/haz3lweb/explainthis/data/LetExp.re index 59b6d41d98..dee429f288 100644 --- a/src/haz3lweb/explainthis/data/LetExp.re +++ b/src/haz3lweb/explainthis/data/LetExp.re @@ -62,6 +62,11 @@ let let_var_ex = { term: mk_example("let x = 1 in \nx + 2"), message: "The variable x is bound to 1, so the expression evaluates to 1 + 2, which is 3.", }; +let let_label_ex = { + sub_id: Let(TupLabel), + term: mk_example("let (a=x, b=y) = (1, a=2) in \nx + 2"), + message: "The variable x is bound to 2 and the y is bound to 2, so the expression evaluates to 2 + 2, which is 4.", +}; let let_tuple2_ex = { sub_id: Let(Tuple2), term: mk_example("let (x, y) = (1, 2) in \nx + y"), @@ -399,6 +404,34 @@ let let_var_exp: form = { // TODO Does this example being slightly different actually add anything? }; }; +let _label_pat = label_pat(); +let _exp_def = exp("e_def"); +let _exp_body = exp("e_body"); +let let_label_exp_coloring_ids = + _pat_def_body_let_exp_coloring_ids( + Piece.id(_label_pat), + Piece.id(_exp_def), + Piece.id(_exp_body), + ); +let let_label_exp: form = { + let explanation = "TODO: label explanation %s%s%s%s%s"; + let form = [ + mk_let([ + [space(), pat("x"), _label_pat, pat("a"), space()], + [space(), _exp_def, space()], + ]), + linebreak(), + _exp_body, + ]; + { + id: LetExp(TupLabel), + syntactic_form: form, + expandable_id: + Some((Piece.id(_label_pat), [pat("x"), label_pat(), pat("e")])), + explanation, + examples: [let_label_ex], + }; +}; let _comma = comma_pat(); let _exp_def = exp("e_def"); let let_tuple_exp_coloring_ids = @@ -604,6 +637,11 @@ let lets_cons: group = { let lets_var: group = {id: LetExp(Var), forms: [let_var_exp, let_base_exp]}; +let lets_label: group = { + id: LetExp(TupLabel), + forms: [let_label_exp, let_base_exp], +}; + let lets_tuple: group = { id: LetExp(Tuple), forms: [let_tuple_exp, let_base_exp], diff --git a/src/haz3lweb/view/ExplainThis.re b/src/haz3lweb/view/ExplainThis.re index 38f9872be0..5ac97825dd 100644 --- a/src/haz3lweb/view/ExplainThis.re +++ b/src/haz3lweb/view/ExplainThis.re @@ -523,9 +523,6 @@ let get_doc = switch (term) { | TermBase.UExp.Invalid(_) => simple("Not a valid expression") | EmptyHole => get_message(HoleExp.empty_hole_exps) - // TODO (Anthony): put in a real message - | TupLabel(_, _) => get_message(HoleExp.empty_hole_exps) - | Dot(_, _) => get_message(HoleExp.empty_hole_exps) | MultiHole(_children) => get_message(HoleExp.multi_hole_exps) | TyAlias(ty_pat, ty_def, _body) => let tpat_id = List.nth(ty_pat.ids, 0); @@ -610,7 +607,6 @@ let get_doc = let body_id = List.nth(body.ids, 0); switch (pat.term) { // TODO (Anthony): put in a real message - | TupLabel(_, _) | EmptyHole => if (FunctionExp.function_empty_hole_exp.id == get_specificity_level(FunctionExp.functions_empty_hole)) { @@ -897,6 +893,31 @@ let get_doc = } else { basic(FunctionExp.functions_var); } + | TupLabel(_, p) => + if (FunctionExp.function_label_exp.id + == get_specificity_level(FunctionExp.functions_tuplabel)) { + let p_id = List.nth(p.ids, 0); + get_message( + ~colorings= + FunctionExp.function_label_exp_coloring_ids( + ~pat_id, + ~body_id, + ), + ~format= + Some( + msg => + Printf.sprintf( + Scanf.format_from_string(msg, "%s%s%s"), + Id.to_string(pat_id), + Id.to_string(p_id), + Id.to_string(body_id), + ), + ), + FunctionExp.functions_tuplabel, + ); + } else { + basic(FunctionExp.functions_tuplabel); + } | Tuple(elements) => let pat_id = List.nth(pat.ids, 0); let body_id = List.nth(body.ids, 0); @@ -1047,6 +1068,8 @@ let get_doc = | Parens(_) => default // Shouldn't get hit? | TypeAnn(_) => default // Shouldn't get hit? }; + | TupLabel(_, _) => get_message(LabelExp.label_exp) + | Dot(_, _) => get_message(DotExp.dot_exp) | Tuple(terms) => let basic = group_id => get_message( @@ -1135,8 +1158,6 @@ let get_doc = ); }; switch (pat.term) { - // TODO (Anthony): put in a real message - | TupLabel(_, _) | EmptyHole => if (LetExp.let_empty_hole_exp.id == get_specificity_level(LetExp.lets_emptyhole)) { @@ -1418,6 +1439,30 @@ let get_doc = } else { basic(LetExp.lets_var); } + | TupLabel(s, p) => + if (LetExp.let_label_exp.id + == get_specificity_level(LetExp.lets_label)) { + let p_id = List.nth(p.ids, 0); + get_message( + ~colorings= + LetExp.let_label_exp_coloring_ids(~pat_id, ~def_id, ~body_id), + ~format= + Some( + msg => + Printf.sprintf( + Scanf.format_from_string(msg, "%s%s%s%s%s"), + Id.to_string(def_id), + Id.to_string(pat_id), + s, + Id.to_string(body_id), + Id.to_string(p_id), + ), + ), + LetExp.lets_label, + ); + } else { + basic(LetExp.lets_label); + } | Tuple(elements) => let basic_tuple = group_id => { get_message( @@ -1888,8 +1933,6 @@ let get_doc = get_message_exp(term.term); | Some(InfoPat({term, _})) => switch (bypass_parens_pat(term).term) { - // TODO (Anthony): put in a real message - | TupLabel(_, _) | EmptyHole => get_message(HolePat.empty_hole) | MultiHole(_) => get_message(HolePat.multi_hole) | Wild => get_message(TerminalPat.wild) @@ -2000,6 +2043,7 @@ let get_doc = ), TerminalPat.var(v), ) + | TupLabel(_, _) => get_message(LabelPat.label_pat) | Tuple(elements) => let basic = group => get_message( @@ -2113,8 +2157,6 @@ let get_doc = } | Some(InfoTyp({term, cls, _})) => switch (bypass_parens_typ(term).term) { - // TODO (Anthony): put in a real message - | TupLabel(_, _) | EmptyHole => get_message(HoleTyp.empty_hole) | MultiHole(_) => get_message(HoleTyp.multi_hole) | Int => get_message(TerminalTyp.int) @@ -2213,6 +2255,7 @@ let get_doc = } | _ => basic(ArrowTyp.arrow) }; + | TupLabel(_, _) => get_message(LabelTyp.label_typ) | Tuple(elements) => let basic = group => get_message( From e0952dfd939c5ed5e44b0af3309c8676822d1e77 Mon Sep 17 00:00:00 2001 From: WondAli Date: Thu, 8 Aug 2024 14:20:59 -0400 Subject: [PATCH 015/108] renamed some variables to be more accurate --- src/haz3lcore/lang/Form.re | 6 +++--- src/haz3lcore/statics/Statics.re | 6 +++--- src/haz3lcore/statics/Term.re | 2 +- src/haz3lweb/explainthis/Example.re | 6 +++--- src/haz3lweb/explainthis/ExplainThisForm.re | 14 ++++++++------ src/haz3lweb/explainthis/data/FunctionExp.re | 17 ++++++++++------- src/haz3lweb/explainthis/data/Label.re | 16 ++++++++++++++++ .../data/{LabelExp.re => LabeledExp.re} | 14 +++++++------- .../data/{LabelPat.re => LabeledPat.re} | 8 ++++---- .../data/{LabelTyp.re => LabeledTyp.re} | 8 ++++---- src/haz3lweb/explainthis/data/LetExp.re | 18 +++++++++--------- src/haz3lweb/view/ExplainThis.re | 18 +++++++++++------- 12 files changed, 79 insertions(+), 54 deletions(-) create mode 100644 src/haz3lweb/explainthis/data/Label.re rename src/haz3lweb/explainthis/data/{LabelExp.re => LabeledExp.re} (71%) rename src/haz3lweb/explainthis/data/{LabelPat.re => LabeledPat.re} (70%) rename src/haz3lweb/explainthis/data/{LabelTyp.re => LabeledTyp.re} (51%) diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index 04c5cb92b6..4fee72aea9 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -287,9 +287,9 @@ let forms: list((string, t)) = [ ("cons_exp", mk_infix("::", Exp, P.cons)), ("cons_pat", mk_infix("::", Pat, P.cons)), ("typeann", mk(ss, [":"], mk_bin'(P.ann, Pat, Pat, [], Typ))), - ("tuple_label_exp", mk(ss, ["="], mk_bin'(P.lab, Exp, Pat, [], Exp))), // TODO: Rename - ("tuple_label_pat", mk(ss, ["="], mk_bin'(P.lab, Pat, Pat, [], Pat))), // TODO: Rename - ("tuple_label_typ", mk(ss, ["="], mk_bin'(P.lab, Typ, Pat, [], Typ))), // TODO: Rename + ("tuple_labeled_exp", mk(ss, ["="], mk_bin'(P.lab, Exp, Pat, [], Exp))), // TODO: Rename + ("tuple_labeled_pat", mk(ss, ["="], mk_bin'(P.lab, Pat, Pat, [], Pat))), // TODO: Rename + ("tuple_labeled_typ", mk(ss, ["="], mk_bin'(P.lab, Typ, Pat, [], Typ))), // TODO: Rename ("dot_exp", mk(ss, ["."], mk_bin'(P.dot, Exp, Exp, [], Pat))), // TODO: Check precedence // ("dot_pat", mk(ss, ["."], mk_bin'(P.dot, Pat, Pat, [], Pat))), // Only for exp? // ("dot_typ", mk(ss, ["."], mk_bin'(P.dot, Typ, Typ, [], Pat))), // Only for exp? diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index c38d428f0d..f1c38d3625 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -312,7 +312,7 @@ and uexp_to_info_map = m, ); | Dot(e, s) => - // TODO (Anthony): Fix this + // TODO (Anthony): Fix this, look at module pr let (e, m) = go(~mode=Syn, e, m); let element: option(Typ.t) = switch (e.ty) { @@ -321,8 +321,8 @@ and uexp_to_info_map = | _ => None // TODO (Anthony): other exps }; switch (element) { - | Some(Label(_, exp)) => add(~self=Just(exp), ~co_ctx=e.co_ctx, m) - | Some(exp) => add(~self=Just(exp), ~co_ctx=e.co_ctx, m) + | Some(Label(_, typ)) => add(~self=Just(typ), ~co_ctx=e.co_ctx, m) + | Some(typ) => add(~self=Just(typ), ~co_ctx=e.co_ctx, m) | None => add(~self=Just(Unknown(Internal)), ~co_ctx=e.co_ctx, m) }; | Test(e) => diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index 10380ff158..a2a11c8f09 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -714,7 +714,7 @@ module UExp = { | ListLit => "List literal" | Constructor => "Constructor" | Fun => "Function literal" - | TupLabel => "Labeled Tuple literal" + | TupLabel => "Labeled Tuple Item literal" | TypFun => "Type Function Literal" | Tuple => "Tuple literal" | Dot => "Dot operator" diff --git a/src/haz3lweb/explainthis/Example.re b/src/haz3lweb/explainthis/Example.re index 50caa95513..49f776ff64 100644 --- a/src/haz3lweb/explainthis/Example.re +++ b/src/haz3lweb/explainthis/Example.re @@ -112,9 +112,9 @@ let comma_exp = () => mk_monotile(Form.get("comma_exp")); let comma_pat = () => mk_monotile(Form.get("comma_pat")); let comma_typ = () => mk_monotile(Form.get("comma_typ")); let pipeline = () => mk_monotile(Form.get("pipeline")); -let label_exp = () => mk_monotile(Form.get("tuple_label_exp")); -let label_pat = () => mk_monotile(Form.get("tuple_label_pat")); -let label_typ = () => mk_monotile(Form.get("tuple_label_typ")); +let labeled_exp = () => mk_monotile(Form.get("tuple_labeled_exp")); +let labeled_pat = () => mk_monotile(Form.get("tuple_labeled_pat")); +let labeled_typ = () => mk_monotile(Form.get("tuple_labeled_typ")); let dot = () => mk_monotile(Form.get("dot_exp")); let nil = () => exp("[]"); let deferral = () => exp("_"); diff --git a/src/haz3lweb/explainthis/ExplainThisForm.re b/src/haz3lweb/explainthis/ExplainThisForm.re index a0d5477d16..d490861255 100644 --- a/src/haz3lweb/explainthis/ExplainThisForm.re +++ b/src/haz3lweb/explainthis/ExplainThisForm.re @@ -173,7 +173,7 @@ type form_id = | ListConcatExp | TypFunctionExp | FunctionExp(pat_sub_form_id) - | LabelExp + | LabeledExp | DotExp | TupleExp | Tuple2Exp @@ -204,7 +204,7 @@ type form_id = | ListNilPat | ConsPat | Cons2Pat - | LabelPat + | LabeledPat | TuplePat | Tuple2Pat | Tuple3Pat @@ -222,7 +222,7 @@ type form_id = | RecTyp | ArrowTyp | Arrow3Typ - | LabelTyp + | LabeledTyp | TupleTyp | Tuple0Typ | Tuple2Typ @@ -234,6 +234,7 @@ type form_id = | MultiHoleTPat | VarTPat | PipelineExp + | Label | FilterPause | FilterEval | FilterDebug @@ -269,7 +270,7 @@ type group_id = | ListConcatExp | TypFunctionExp | FunctionExp(pat_sub_form_id) - | LabelExp + | LabeledExp | DotExp | TupleExp | Tuple2Exp @@ -301,7 +302,7 @@ type group_id = | ListNilPat | ConsPat | Cons2Pat - | LabelPat + | LabeledPat | TuplePat | Tuple2Pat | Tuple3Pat @@ -319,7 +320,7 @@ type group_id = | RecTyp | ArrowTyp | Arrow3Typ - | LabelTyp + | LabeledTyp | TupleTyp | Tuple0Typ | Tuple2Typ @@ -330,6 +331,7 @@ type group_id = | EmptyHoleTPat | MultiHoleTPat | VarTPat + | Label | FilterPause | FilterEval | FilterDebug diff --git a/src/haz3lweb/explainthis/data/FunctionExp.re b/src/haz3lweb/explainthis/data/FunctionExp.re index 0b6fd05354..70e6ce0953 100644 --- a/src/haz3lweb/explainthis/data/FunctionExp.re +++ b/src/haz3lweb/explainthis/data/FunctionExp.re @@ -317,14 +317,17 @@ let function_var_exp: form = { }; }; -let _label_pat = label_pat(); +let _labeled_pat = labeled_pat(); let _exp = exp("e"); -let function_label_exp_coloring_ids = - _pat_body_function_exp_coloring_ids(Piece.id(_label_pat), Piece.id(_exp)); -let function_label_exp: form = { +let function_labeled_exp_coloring_ids = + _pat_body_function_exp_coloring_ids( + Piece.id(_labeled_pat), + Piece.id(_exp), + ); +let function_labeled_exp: form = { let explanation = "Any unlabeled value matches with the [*argument*]. Only labeled elements that match the [*name*](%s) 'x' are accepted, and evaluate using the [*value*](%s) 'y' to the function [*body*](%s)."; let form = [ - mk_fun([[space(), pat("x"), _label_pat, pat("y"), space()]]), + mk_fun([[space(), pat("x"), _labeled_pat, pat("y"), space()]]), space(), _exp, ]; @@ -332,7 +335,7 @@ let function_label_exp: form = { id: FunctionExp(TupLabel), syntactic_form: form, expandable_id: - Some((Piece.id(_label_pat), [pat("x"), label_pat(), pat("y")])), + Some((Piece.id(_labeled_pat), [pat("x"), labeled_pat(), pat("y")])), explanation, examples: [label_fun_ex], }; @@ -529,7 +532,7 @@ let functions_var = { let functions_tuplabel = { id: FunctionExp(TupLabel), - forms: [function_label_exp, function_exp], + forms: [function_labeled_exp, function_exp], }; let functions_tuple = { diff --git a/src/haz3lweb/explainthis/data/Label.re b/src/haz3lweb/explainthis/data/Label.re new file mode 100644 index 0000000000..4625c904f9 --- /dev/null +++ b/src/haz3lweb/explainthis/data/Label.re @@ -0,0 +1,16 @@ +// open ExplainThisForm; + // open Example; + // let label_exp = (n: string): form => { + // let explanation = "`%s` is a label (or name) for an item within a tuple."; + // { + // id: LabelExp, + // syntactic_form: [n], + // expandable_id: None, + // explanation, + // examples: [], + // }; + // }; + // let label_exps = (n: string): group => { + // id: LabelExp, + // forms: [label_exps(n)], + // }; diff --git a/src/haz3lweb/explainthis/data/LabelExp.re b/src/haz3lweb/explainthis/data/LabeledExp.re similarity index 71% rename from src/haz3lweb/explainthis/data/LabelExp.re rename to src/haz3lweb/explainthis/data/LabeledExp.re index af2936cd49..c3bb7a3966 100644 --- a/src/haz3lweb/explainthis/data/LabelExp.re +++ b/src/haz3lweb/explainthis/data/LabeledExp.re @@ -2,24 +2,24 @@ open ExplainThisForm; open Example; -let label_example_1 = { +let labeled_example_1 = { sub_id: Label1, term: mk_example("(x=1)"), message: "A labeled expression within a singleton tuple, where the element 1 is assigned the label 'x'. ", }; -let label_example_2 = { +let labeled_example_2 = { sub_id: Label2, term: mk_example("(1, 2, y=3)"), message: "A tuple with first element 1, second element 2, and third element 3 with the label 'y'.", }; -let label_exp: form = { +let labeled_exp: form = { let explanation = "Labeled Expession explanation"; { - id: LabelExp, - syntactic_form: [exp("x"), label_exp(), exp("e")], + id: LabeledExp, + syntactic_form: [exp("x"), labeled_exp(), exp("e")], expandable_id: None, explanation, - examples: [label_example_1, label_example_2], + examples: [labeled_example_1, labeled_example_2], }; }; // let _exp1 = exp("e1"); @@ -29,4 +29,4 @@ let label_exp: form = { // [(Piece.id(_exp1), exp1_id), (Piece.id(_exp2), exp2_id)]; // } -let label_exp: group = {id: LabelExp, forms: [label_exp]}; +let labeled_exp: group = {id: LabeledExp, forms: [labeled_exp]}; diff --git a/src/haz3lweb/explainthis/data/LabelPat.re b/src/haz3lweb/explainthis/data/LabeledPat.re similarity index 70% rename from src/haz3lweb/explainthis/data/LabelPat.re rename to src/haz3lweb/explainthis/data/LabeledPat.re index 8362810e66..1653d7aba4 100644 --- a/src/haz3lweb/explainthis/data/LabelPat.re +++ b/src/haz3lweb/explainthis/data/LabeledPat.re @@ -8,15 +8,15 @@ open ExplainThisForm; // (Piece.id(_pat), pat_id), // (Piece.id(_typ), typ_id), // ]; -let label_pat: form = { +let labeled_pat: form = { let explanation = "labeled pattern explanation"; { - id: LabelPat, - syntactic_form: [pat("x"), label_pat(), pat("p")], + id: LabeledPat, + syntactic_form: [pat("x"), labeled_pat(), pat("p")], expandable_id: None, explanation, examples: [], }; }; -let label_pat: group = {id: LabelPat, forms: [label_pat]}; +let labeled_pat: group = {id: LabeledPat, forms: [labeled_pat]}; diff --git a/src/haz3lweb/explainthis/data/LabelTyp.re b/src/haz3lweb/explainthis/data/LabeledTyp.re similarity index 51% rename from src/haz3lweb/explainthis/data/LabelTyp.re rename to src/haz3lweb/explainthis/data/LabeledTyp.re index 2774e4ce46..9227c30f51 100644 --- a/src/haz3lweb/explainthis/data/LabelTyp.re +++ b/src/haz3lweb/explainthis/data/LabeledTyp.re @@ -2,15 +2,15 @@ open Example; open ExplainThisForm; // open Haz3lcore; -let label_typ: form = { +let labeled_typ: form = { let explanation = "label type explanation"; { - id: LabelTyp, - syntactic_form: [pat("x"), label_typ(), typ("t")], + id: LabeledTyp, + syntactic_form: [pat("x"), labeled_typ(), typ("t")], expandable_id: None, explanation, examples: [], }; }; -let label_typ: group = {id: LabelTyp, forms: [label_typ]}; +let labeled_typ: group = {id: LabeledTyp, forms: [labeled_typ]}; diff --git a/src/haz3lweb/explainthis/data/LetExp.re b/src/haz3lweb/explainthis/data/LetExp.re index dee429f288..94ea0412e6 100644 --- a/src/haz3lweb/explainthis/data/LetExp.re +++ b/src/haz3lweb/explainthis/data/LetExp.re @@ -62,7 +62,7 @@ let let_var_ex = { term: mk_example("let x = 1 in \nx + 2"), message: "The variable x is bound to 1, so the expression evaluates to 1 + 2, which is 3.", }; -let let_label_ex = { +let let_labeled_ex = { sub_id: Let(TupLabel), term: mk_example("let (a=x, b=y) = (1, a=2) in \nx + 2"), message: "The variable x is bound to 2 and the y is bound to 2, so the expression evaluates to 2 + 2, which is 4.", @@ -404,20 +404,20 @@ let let_var_exp: form = { // TODO Does this example being slightly different actually add anything? }; }; -let _label_pat = label_pat(); +let _labeled_pat = labeled_pat(); let _exp_def = exp("e_def"); let _exp_body = exp("e_body"); -let let_label_exp_coloring_ids = +let let_labeled_exp_coloring_ids = _pat_def_body_let_exp_coloring_ids( - Piece.id(_label_pat), + Piece.id(_labeled_pat), Piece.id(_exp_def), Piece.id(_exp_body), ); -let let_label_exp: form = { +let let_labeled_exp: form = { let explanation = "TODO: label explanation %s%s%s%s%s"; let form = [ mk_let([ - [space(), pat("x"), _label_pat, pat("a"), space()], + [space(), pat("x"), _labeled_pat, pat("a"), space()], [space(), _exp_def, space()], ]), linebreak(), @@ -427,9 +427,9 @@ let let_label_exp: form = { id: LetExp(TupLabel), syntactic_form: form, expandable_id: - Some((Piece.id(_label_pat), [pat("x"), label_pat(), pat("e")])), + Some((Piece.id(_labeled_pat), [pat("x"), labeled_pat(), pat("e")])), explanation, - examples: [let_label_ex], + examples: [let_labeled_ex], }; }; let _comma = comma_pat(); @@ -639,7 +639,7 @@ let lets_var: group = {id: LetExp(Var), forms: [let_var_exp, let_base_exp]}; let lets_label: group = { id: LetExp(TupLabel), - forms: [let_label_exp, let_base_exp], + forms: [let_labeled_exp, let_base_exp], }; let lets_tuple: group = { diff --git a/src/haz3lweb/view/ExplainThis.re b/src/haz3lweb/view/ExplainThis.re index f7f4b18e71..9ecc05118a 100644 --- a/src/haz3lweb/view/ExplainThis.re +++ b/src/haz3lweb/view/ExplainThis.re @@ -912,12 +912,12 @@ let get_doc = basic(FunctionExp.functions_var); } | TupLabel(_, p) => - if (FunctionExp.function_label_exp.id + if (FunctionExp.function_labeled_exp.id == get_specificity_level(FunctionExp.functions_tuplabel)) { let p_id = List.nth(p.ids, 0); get_message( ~colorings= - FunctionExp.function_label_exp_coloring_ids( + FunctionExp.function_labeled_exp_coloring_ids( ~pat_id, ~body_id, ), @@ -1086,7 +1086,7 @@ let get_doc = | Parens(_) => default // Shouldn't get hit? | TypeAnn(_) => default // Shouldn't get hit? }; - | TupLabel(_, _) => get_message(LabelExp.label_exp) + | TupLabel(_, _) => get_message(LabeledExp.labeled_exp) | Dot(_, _) => get_message(DotExp.dot_exp) | Tuple(terms) => let basic = group_id => @@ -1458,12 +1458,16 @@ let get_doc = basic(LetExp.lets_var); } | TupLabel(s, p) => - if (LetExp.let_label_exp.id + if (LetExp.let_labeled_exp.id == get_specificity_level(LetExp.lets_label)) { let p_id = List.nth(p.ids, 0); get_message( ~colorings= - LetExp.let_label_exp_coloring_ids(~pat_id, ~def_id, ~body_id), + LetExp.let_labeled_exp_coloring_ids( + ~pat_id, + ~def_id, + ~body_id, + ), ~format= Some( msg => @@ -2061,7 +2065,7 @@ let get_doc = ), TerminalPat.var(v), ) - | TupLabel(_, _) => get_message(LabelPat.label_pat) + | TupLabel(_, _) => get_message(LabeledPat.labeled_pat) | Tuple(elements) => let basic = group => get_message( @@ -2273,7 +2277,7 @@ let get_doc = } | _ => basic(ArrowTyp.arrow) }; - | TupLabel(_, _) => get_message(LabelTyp.label_typ) + | TupLabel(_, _) => get_message(LabeledTyp.labeled_typ) | Tuple(elements) => let basic = group => get_message( From bf1137ca06c9497708dddd027e83540e61967da8 Mon Sep 17 00:00:00 2001 From: WondAli Date: Mon, 12 Aug 2024 13:46:55 -0400 Subject: [PATCH 016/108] dot operator update --- src/haz3lcore/dynamics/DH.re | 12 ++-- src/haz3lcore/dynamics/Elaborator.re | 7 +- src/haz3lcore/dynamics/EvalCtx.re | 14 +++- src/haz3lcore/dynamics/EvaluatorPost.re | 14 ++-- src/haz3lcore/dynamics/EvaluatorStep.re | 14 ++-- src/haz3lcore/dynamics/FilterMatcher.re | 4 +- src/haz3lcore/dynamics/PatternMatch.re | 4 +- src/haz3lcore/dynamics/Stepper.re | 9 ++- src/haz3lcore/dynamics/Substitution.re | 5 +- src/haz3lcore/dynamics/Transition.re | 70 ++++++++++++++----- src/haz3lcore/dynamics/TypeAssignment.re | 11 +-- src/haz3lcore/lang/Form.re | 11 ++- src/haz3lcore/statics/Info.re | 19 +++++ src/haz3lcore/statics/MakeTerm.re | 25 +------ src/haz3lcore/statics/Statics.re | 60 ++++++++++++---- src/haz3lcore/statics/Term.re | 54 ++++++++++++-- src/haz3lcore/statics/TermBase.re | 6 +- src/haz3lschool/SyntaxTest.re | 8 +-- src/haz3lweb/explainthis/Example.re | 3 +- src/haz3lweb/explainthis/ExplainThisForm.re | 3 + src/haz3lweb/explainthis/data/DotExp.re | 4 +- src/haz3lweb/explainthis/data/DotTyp.re | 21 ++++++ src/haz3lweb/view/CursorInspector.re | 1 + src/haz3lweb/view/ExplainThis.re | 1 + src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 14 ++-- .../view/dhcode/layout/DHDoc_common.re | 2 + .../view/dhcode/layout/DHDoc_common.rei | 2 + 27 files changed, 280 insertions(+), 118 deletions(-) create mode 100644 src/haz3lweb/explainthis/data/DotTyp.re diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index 5086d89f26..7b65113ac8 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -40,7 +40,7 @@ module rec DHExp: { | ListConcat(t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) - | Dot(t, LabeledTuple.t) + | Dot(t, t) | Prj(t, int) | Constructor(string, Typ.t) | ConsistentCase(case) @@ -105,7 +105,7 @@ module rec DHExp: { | ListConcat(t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) - | Dot(t, LabeledTuple.t) + | Dot(t, t) | Prj(t, int) | Constructor(string, Typ.t) | ConsistentCase(case) @@ -199,7 +199,7 @@ module rec DHExp: { | FailedCast(d, _, _) => strip_casts(d) | TupLabel(s, d) => TupLabel(s, strip_casts(d)) | Tuple(ds) => Tuple(ds |> List.map(strip_casts)) - | Dot(d, s) => Dot(strip_casts(d), s) + | Dot(a, b) => Dot(strip_casts(a), strip_casts(b)) | Prj(d, n) => Prj(strip_casts(d), n) | Cons(d1, d2) => Cons(strip_casts(d1), strip_casts(d2)) | ListConcat(d1, d2) => ListConcat(strip_casts(d1), strip_casts(d2)) @@ -306,8 +306,8 @@ module rec DHExp: { ds1, ds2, ); - | (Dot(d1, s1), Dot(d2, s2)) => - LabeledTuple.compare(s1, s2) == 0 && d1 == d2 + | (Dot(d11, d21), Dot(d12, d22)) => + fast_equal(d11, d12) && fast_equal(d21, d22) | (Prj(d1, n), Prj(d2, m)) => n == m && fast_equal(d1, d2) | (ApBuiltin(f1, d1), ApBuiltin(f2, d2)) => f1 == f2 && d1 == d2 | (BuiltinFun(f1), BuiltinFun(f2)) => f1 == f2 @@ -443,7 +443,7 @@ module rec DHExp: { | ListConcat(t1, t2) => ListConcat(re(t1), re(t2)) | Tuple(args) => Tuple(List.map(re, args)) | TupLabel(s, t) => TupLabel(s, re(t)) - | Dot(t, s) => Dot(re(t), s) + | Dot(t1, t2) => Dot(re(t1), re(t2)) | Prj(t, n) => Prj(re(t), n) | ConsistentCase(case) => ConsistentCase(ty_subst_case(s, x, case)) | InvalidOperation(t, err) => InvalidOperation(re(t), err) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index a29493474b..2bf9117778 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -186,9 +186,10 @@ let rec dhexp_of_uexp = | Tuple(es) => let+ ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; DHExp.Tuple(ds); - | Dot(e, s) => - let+ de = dhexp_of_uexp(m, e); - DHExp.Dot(de, s); + | Dot(e1, e2) => + let* e1 = dhexp_of_uexp(m, e1); + let+ e2 = dhexp_of_uexp(m, e2); + DHExp.Dot(e1, e2); | Cons(e1, e2) => let* dc1 = dhexp_of_uexp(m, e1); let+ dc2 = dhexp_of_uexp(m, e2); diff --git a/src/haz3lcore/dynamics/EvalCtx.re b/src/haz3lcore/dynamics/EvalCtx.re index 160893573b..82fd48fa1c 100644 --- a/src/haz3lcore/dynamics/EvalCtx.re +++ b/src/haz3lcore/dynamics/EvalCtx.re @@ -30,7 +30,8 @@ type cls = | IfThenElse3 | TupLabel | Tuple(int) - | Dot + | Dot1 + | Dot2 | ListLit(int) | ApBuiltin | Test @@ -78,7 +79,8 @@ type t = | BinStringOp2(TermBase.UExp.op_bin_string, DHExp.t, t) | TupLabel(LabeledTuple.t, t) | Tuple(t, (list(DHExp.t), list(DHExp.t))) - | Dot(t, LabeledTuple.t) + | Dot1(t, DHExp.t) + | Dot2(DHExp.t, t) | ApBuiltin(string, t) | Test(KeywordID.t, t) | ListLit( @@ -147,7 +149,8 @@ let rec fuzzy_mark = | BinFloatOp2(_) | BinStringOp1(_) | BinStringOp2(_) - | Dot(_) + | Dot1(_) + | Dot2(_) | TupLabel(_) | Tuple(_) | ApBuiltin(_) @@ -180,6 +183,8 @@ let rec unwrap = (ctx: t, sel: cls): option(t) => { | (Sequence2, Sequence2(_, c)) | (Let1, Let1(_, c, _)) | (Let2, Let2(_, _, c)) + | (Dot1, Dot1(c, _)) + | (Dot2, Dot2(_, c)) | (Fun, Fun(_, _, c, _)) | (FixF, FixF(_, _, c)) | (TypAp, TypAp(c, _)) @@ -236,6 +241,9 @@ let rec unwrap = (ctx: t, sel: cls): option(t) => { | (IfThenElse3, IfThenElse2(_)) | (Let1, Let2(_)) | (Let2, Let1(_)) + // | (TupLabel, TupLabel(_, _)) + // | (Dot1, Dot1(_, _)) + // | (Dot2, Dot2(_, _)) | (BinBoolOp1, BinBoolOp2(_)) | (BinBoolOp2, BinBoolOp1(_)) | (BinIntOp1, BinIntOp2(_)) diff --git a/src/haz3lcore/dynamics/EvaluatorPost.re b/src/haz3lcore/dynamics/EvaluatorPost.re index ebfc627922..5d28c9dc4a 100644 --- a/src/haz3lcore/dynamics/EvaluatorPost.re +++ b/src/haz3lcore/dynamics/EvaluatorPost.re @@ -133,9 +133,10 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => ); Tuple(ds); - | Dot(d1, s) => + | Dot(d1, d2) => let* d1' = pp_eval(d1); - Dot(d1', s) |> return; + let* d2' = pp_eval(d2); + Dot(d1', d2') |> return; | Prj(d, n) => let+ d = pp_eval(d); @@ -399,9 +400,10 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => ); Tuple(ds); - | Dot(d, s) => - let+ d = pp_uneval(env, d); - Dot(d, s); + | Dot(d1, d2) => + let* d1' = pp_uneval(env, d1); + let* d2' = pp_uneval(env, d2); + Dot(d1', d2') |> return; | Prj(d, n) => let+ d = pp_uneval(env, d); @@ -500,7 +502,6 @@ let rec track_children_of_hole = | Cast(d, _, _) | FailedCast(d, _, _) | TupLabel(_, d) - | Dot(d, _) | InvalidOperation(d, _) => track_children_of_hole(hii, parent, d) | Sequence(d1, d2) | Let(_, d1, d2) @@ -509,6 +510,7 @@ let rec track_children_of_hole = | BinIntOp(_, d1, d2) | BinFloatOp(_, d1, d2) | BinStringOp(_, d1, d2) + | Dot(d1, d2) | Cons(d1, d2) => let hii = track_children_of_hole(hii, parent, d1); track_children_of_hole(hii, parent, d2); diff --git a/src/haz3lcore/dynamics/EvaluatorStep.re b/src/haz3lcore/dynamics/EvaluatorStep.re index 4873e68acd..ed8b06d5d6 100644 --- a/src/haz3lcore/dynamics/EvaluatorStep.re +++ b/src/haz3lcore/dynamics/EvaluatorStep.re @@ -282,9 +282,12 @@ let rec compose = (ctx: EvalCtx.t, d: DHExp.t): DHExp.t => { | TupLabel(s, ctx) => let d2 = compose(ctx, d); TupLabel(s, d2); - | Dot(ctx, s) => + | Dot1(ctx, d2) => + let d1 = compose(ctx, d); + Dot(d1, d2); + | Dot2(d1, ctx) => let d2 = compose(ctx, d); - Dot(d2, s); + Dot(d1, d2); | Tuple(ctx, (ld, rd)) => let d = compose(ctx, d); Tuple(rev_concat(ld, [d, ...rd])); @@ -454,9 +457,12 @@ let rec matches = | TupLabel(s, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); TupLabel(s, ctx); - | Dot(ctx, s) => + | Dot1(ctx, d2) => + let+ ctx = matches(env, flt, ctx, exp, act, idx); + Dot1(ctx, d2); + | Dot2(d1, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); - Dot(ctx, s); + Dot2(d1, ctx); | ApBuiltin(name, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); ApBuiltin(name, ctx); diff --git a/src/haz3lcore/dynamics/FilterMatcher.re b/src/haz3lcore/dynamics/FilterMatcher.re index 2e5675d202..d9a1367a9d 100644 --- a/src/haz3lcore/dynamics/FilterMatcher.re +++ b/src/haz3lcore/dynamics/FilterMatcher.re @@ -221,8 +221,8 @@ let rec matches_exp = ) | (ListLit(_), _) => false - // TODO (Anthony): Is this right - | (Dot(dv, _), Dot(fv, _)) => matches_exp(dv, fv) + | (Dot(d1, d2), Dot(f1, f2)) => + matches_exp(d1, f1) && matches_exp(d2, f2) | (Dot(_), _) => false | (Tuple(dv), Tuple(fv)) => diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 44ee63d4aa..cea5964a5d 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -496,7 +496,7 @@ and matches_cast_Tuple = List.map2(List.cons, List.combine(tys, tys'), elt_casts), ); | TupLabel(_, d') => matches_cast_Tuple(dps, d', elt_casts) - | Dot(_, _) + | Dot(_, _) => IndetMatch | Cast(_, _, _) => DoesNotMatch | BoundVar(_) => DoesNotMatch | FreeVar(_) => IndetMatch @@ -666,7 +666,7 @@ and matches_cast_Cons = | FloatLit(_) => DoesNotMatch | StringLit(_) => DoesNotMatch | Tuple(_) => DoesNotMatch - | Dot(_, _) => DoesNotMatch + | Dot(_, _) => IndetMatch | Prj(_) => IndetMatch | Constructor(_) => DoesNotMatch | ConsistentCase(_) diff --git a/src/haz3lcore/dynamics/Stepper.re b/src/haz3lcore/dynamics/Stepper.re index 0dee7806c4..54fb63f1bc 100644 --- a/src/haz3lcore/dynamics/Stepper.re +++ b/src/haz3lcore/dynamics/Stepper.re @@ -131,9 +131,12 @@ let rec matches = | BinStringOp2(op, d1, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); BinStringOp2(op, d1, ctx); - | Dot(ctx, s) => + | Dot1(ctx, d2) => let+ ctx = matches(env, flt, ctx, exp, act, idx); - Dot(ctx, s); + Dot1(ctx, d2); + | Dot2(d1, ctx) => + let+ ctx = matches(env, flt, ctx, exp, act, idx); + Dot2(d1, ctx); | TupLabel(s, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); TupLabel(s, ctx); @@ -402,7 +405,7 @@ let get_justification: step_kind => string = | BinStringOp(Equals) => "check equality" | BinStringOp(Concat) => "string manipulation" | BinBoolOp(_) => "boolean logic" - | Dot(_) => "dot operation" + | Dot => "dot operation" | Conditional(_) => "conditional" | ListCons => "list manipulation" | ListConcat => "list manipulation" diff --git a/src/haz3lcore/dynamics/Substitution.re b/src/haz3lcore/dynamics/Substitution.re index c6779eb1e8..b1e58ef007 100644 --- a/src/haz3lcore/dynamics/Substitution.re +++ b/src/haz3lcore/dynamics/Substitution.re @@ -74,7 +74,10 @@ let rec subst_var = (d1: DHExp.t, x: Var.t, d2: DHExp.t): DHExp.t => ListConcat(d3, d4); | TupLabel(p, d) => TupLabel(p, subst_var(d1, x, d)) | Tuple(ds) => Tuple(List.map(subst_var(d1, x), ds)) - | Dot(d, s) => Dot(subst_var(d1, x, d), s) + | Dot(d3, d4) => + let d3 = subst_var(d1, x, d3); + let d4 = subst_var(d1, x, d4); + Dot(d3, d4); | Prj(d, n) => Prj(subst_var(d1, x, d), n) | BinBoolOp(op, d3, d4) => let d3 = subst_var(d1, x, d3); diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index f6515232ab..f649f83474 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -63,7 +63,7 @@ type step_kind = | BinIntOp(TermBase.UExp.op_bin_int) | BinFloatOp(TermBase.UExp.op_bin_float) | BinStringOp(TermBase.UExp.op_bin_string) - | Dot(LabeledTuple.t) + | Dot | Conditional(bool) | Projection | ListCons @@ -560,27 +560,61 @@ module Transition = (EV: EV_MODE) => { kind: BinStringOp(op), value: true, }); - | Dot(d, s) => - let. _ = otherwise(env, d => Dot(d, s)) - and. d' = req_final(req(state, env), d => Dot(d, s), d); - // print_endline("dot final"); - // print_endline(DHExp.show(d')); - // TODO (Anthony): fix step if needed - Step({ - apply: () => - switch (d') { - | Tuple(ds) => - let element = LabeledTuple.find_label(DHExp.get_label, ds, s); + | Dot(d1, d2) => + let. _ = otherwise(env, d1 => Dot(d1, d2)) + and. d1' = req_value(req(state, env), d1 => Dot1(d1, d2), d1); + switch (d1', d2) { + | (Tuple(ds), BoundVar(name)) => + Step({ + apply: () => { + let element = LabeledTuple.find_label(DHExp.get_label, ds, name); switch (element) { | Some(TupLabel(_, exp)) => exp | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }; - | TupLabel(l, exp) when LabeledTuple.compare(s, l) == 0 => exp - | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }, - kind: Dot(s), - value: false, - }); + kind: Dot, + value: false, + }) + | (_, Cast(d2', ty, ty')) => + Step({ + apply: () => Cast(Dot(d1, d2'), ty, ty'), + kind: CastAp, + value: false, + }) + | (Cast(d3', Prod(ts), Prod(ts')), BoundVar(name)) => + let ty = + switch (LabeledTuple.find_label(Typ.get_label, ts, name)) { + | Some(Label(_, ty)) => ty + | _ => Typ.Unknown(Internal) + }; + let ty' = + switch (LabeledTuple.find_label(Typ.get_label, ts', name)) { + | Some(Label(_, ty)) => ty + | _ => Typ.Unknown(Internal) + }; + Step({ + apply: () => Cast(Dot(d3', d2), ty, ty'), + kind: CastAp, + value: false, + }); + | _ => Indet + }; + // Step({ + // apply: () => + // switch (d') { + // | Tuple(ds) => + // let element = LabeledTuple.find_label(DHExp.get_label, ds, s); + // switch (element) { + // | Some(TupLabel(_, exp)) => exp + // | _ => raise(EvaluatorError.Exception(BadPatternMatch)) + // }; + // | TupLabel(l, exp) when LabeledTuple.compare(s, l) == 0 => exp + // | _ => raise(EvaluatorError.Exception(BadPatternMatch)) + // }, + // kind: Dot(s), + // value: false, + // }); | TupLabel(p, d1) => // TODO (Anthony): Fix this if needed let. _ = otherwise(env, d1 => TupLabel(p, d1)) @@ -784,7 +818,7 @@ let should_hide_step_kind = (~settings: CoreSettings.Evaluation.t) => | BinIntOp(_) | BinFloatOp(_) | BinStringOp(_) - | Dot(_) + | Dot | ListCons | ListConcat | CaseApply diff --git a/src/haz3lcore/dynamics/TypeAssignment.re b/src/haz3lcore/dynamics/TypeAssignment.re index 1347025bf2..b112eeaae0 100644 --- a/src/haz3lcore/dynamics/TypeAssignment.re +++ b/src/haz3lcore/dynamics/TypeAssignment.re @@ -283,15 +283,16 @@ let rec typ_of_dhexp = | Some(ty) => Some(Typ.Label(s, ty)) | None => None }; - | Dot(d, s) => - switch (d) { - | Tuple(ds) => - let element = LabeledTuple.find_label(DHExp.get_label, ds, s); + | Dot(d1, d2) => + switch (d1, d2) { + | (Tuple(ds), BoundVar(name)) => + let element = LabeledTuple.find_label(DHExp.get_label, ds, name); switch (element) { | Some(TupLabel(_, exp)) => typ_of_dhexp(ctx, m, exp) | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }; - | TupLabel(l, exp) when LabeledTuple.compare(s, l) == 0 => + | (TupLabel(l, exp), BoundVar(name)) + when LabeledTuple.compare(name, l) == 0 => typ_of_dhexp(ctx, m, exp) | _ => raise(EvaluatorError.Exception(BadPatternMatch)) } diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index 4fee72aea9..1132caa96b 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -287,12 +287,11 @@ let forms: list((string, t)) = [ ("cons_exp", mk_infix("::", Exp, P.cons)), ("cons_pat", mk_infix("::", Pat, P.cons)), ("typeann", mk(ss, [":"], mk_bin'(P.ann, Pat, Pat, [], Typ))), - ("tuple_labeled_exp", mk(ss, ["="], mk_bin'(P.lab, Exp, Pat, [], Exp))), // TODO: Rename - ("tuple_labeled_pat", mk(ss, ["="], mk_bin'(P.lab, Pat, Pat, [], Pat))), // TODO: Rename - ("tuple_labeled_typ", mk(ss, ["="], mk_bin'(P.lab, Typ, Pat, [], Typ))), // TODO: Rename - ("dot_exp", mk(ss, ["."], mk_bin'(P.dot, Exp, Exp, [], Pat))), // TODO: Check precedence - // ("dot_pat", mk(ss, ["."], mk_bin'(P.dot, Pat, Pat, [], Pat))), // Only for exp? - // ("dot_typ", mk(ss, ["."], mk_bin'(P.dot, Typ, Typ, [], Pat))), // Only for exp? + ("tuple_labeled_exp", mk(ss, ["="], mk_bin'(P.lab, Exp, Pat, [], Exp))), + ("tuple_labeled_pat", mk(ss, ["="], mk_bin'(P.lab, Pat, Pat, [], Pat))), + ("tuple_labeled_typ", mk(ss, ["="], mk_bin'(P.lab, Typ, Pat, [], Typ))), + ("dot_exp", mk_infix(".", Exp, P.dot)), + ("dot_typ", mk_infix(".", Typ, P.dot)), // UNARY PREFIX OPERATORS ("not", mk(ii, ["!"], mk_pre(5, Exp, []))), //TODO: precedence ("typ_sum_single", mk(ss, ["+"], mk_pre(P.or_, Typ, []))), diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 4c94c0b5d7..83b0a9f8dd 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -133,6 +133,7 @@ type status_variant = [@deriving (show({with_path: false}), sexp, yojson)] type typ_expects = | TypeExpected + | TupleExpected | ConstructorExpected(status_variant, Typ.t) | VariantExpected(status_variant, Typ.t); @@ -146,6 +147,7 @@ type error_typ = | FreeTypeVariable(TypVar.t) /* Free type variable */ | DuplicateConstructor(Constructor.t) /* Duplicate ctr in same sum */ | WantTypeFoundAp + | WantTuple | WantConstructorFoundType(Typ.t) | WantConstructorFoundAp; @@ -456,6 +458,12 @@ let status_typ = | VariantExpected(Duplicate, _) | ConstructorExpected(Duplicate, _) => InHole(DuplicateConstructor(name)) + | TupleExpected => + switch (Ctx.lookup_alias(ctx, name)) { + | Some(Prod(_)) => + NotInHole(TypeAlias(name, Typ.weak_head_normalize(ctx, ty))) + | _ => InHole(WantTuple) + } | TypeExpected => switch (Ctx.is_alias(ctx, name)) { | false => @@ -476,11 +484,22 @@ let status_typ = | _ => NotInHole(VariantIncomplete(Arrow(ty_in, ty_variant))) }; | ConstructorExpected(_) => InHole(WantConstructorFoundAp) + | TupleExpected => InHole(WantTuple) | TypeExpected => InHole(WantTypeFoundAp) } + | Dot(t1, _) => + switch (expects, ty) { + | (TupleExpected, _) => + switch (t1.term) { + | Tuple(_) => NotInHole(Type(ty)) + | _ => InHole(WantTuple) + } + | _ => NotInHole(Type(ty)) + } | _ => switch (expects) { | TypeExpected => NotInHole(Type(ty)) + | TupleExpected => InHole(WantTuple) | ConstructorExpected(_) | VariantExpected(_) => InHole(WantConstructorFoundType(ty)) } diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index 55af9b237f..25e7ba988c 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -245,15 +245,6 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { } | _ => ret(hole(tm)) } - | Bin(Exp(e), tiles, Pat(p)) as tm => - switch (tiles) { - | ([(_id, (["."], []))], []) => - switch (p.term) { - | Var(s) => ret(Dot(e, s)) - | _ => ret(hole(tm)) - } - | _ => ret(hole(tm)) - } | Bin(Exp(l), tiles, Exp(r)) as tm => switch (is_tuple_exp(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) @@ -290,6 +281,7 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { | ([";"], []) => Seq(l, r) | (["++"], []) => BinOp(String(Concat), l, r) | (["$=="], []) => BinOp(String(Equals), l, r) + | (["."], []) => Dot(l, r) | (["|>"], []) => Pipeline(l, r) | (["@"], []) => ListConcat(l, r) | _ => hole(tm) @@ -367,11 +359,6 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { | _ => ret(hole(tm)) } | ([(_id, (["::"], []))], []) => ret(Cons(l, r)) - // | ([(_id, (["."], []))], []) => - // switch (r.term) { - // | Var(s) => ret(Dot(l, s)) - // | _ => ret(hole(tm)) - // } | _ => ret(hole(tm)) } } @@ -444,21 +431,13 @@ and typ_term: unsorted => (UTyp.term, list(Id.t)) = { } | _ => ret(hole(tm)) } - // | Bin(Typ(t), tiles, Pat(p)) as tm => - // switch (tiles) { - // | ([(_id, (["."], []))], []) => - // switch (p.term) { - // | Var(s) => ret(Dot(t, s)) - // | _ => ret(hole(tm)) - // } - // | _ => ret(hole(tm)) - // } | Bin(Typ(l), tiles, Typ(r)) as tm => switch (is_tuple_typ(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) | None => switch (tiles) { | ([(_id, (["->"], []))], []) => ret(Arrow(l, r)) + | ([(_id, (["."], []))], []) => ret(Dot(l, r)) | _ => ret(hole(tm)) } } diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index f1c38d3625..d6d97c2f23 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -311,19 +311,49 @@ and uexp_to_info_map = ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es)), m, ); - | Dot(e, s) => - // TODO (Anthony): Fix this, look at module pr - let (e, m) = go(~mode=Syn, e, m); - let element: option(Typ.t) = - switch (e.ty) { - | Prod(ts) => LabeledTuple.find_label(Typ.get_label, ts, s) - // | Label(l, t) when LabeledTuple.compare(s, l) == 0 => Some(t) - | _ => None // TODO (Anthony): other exps + | Dot(e1, e2) => + let (ty, m) = { + let (info_e1, m) = go(~mode=Syn, e1, m); + switch (e2.term, info_e1.ty) { + | (Var(name), Unknown(_)) + | (Constructor(name), Unknown(_)) => + let ty = Typ.Prod([Label(name, Unknown(Internal))]); + let (_, m) = go(~mode=Mode.Ana(ty), e1, m); + (ty, m); + | _ => (info_e1.ty, m) }; - switch (element) { - | Some(Label(_, typ)) => add(~self=Just(typ), ~co_ctx=e.co_ctx, m) - | Some(typ) => add(~self=Just(typ), ~co_ctx=e.co_ctx, m) - | None => add(~self=Just(Unknown(Internal)), ~co_ctx=e.co_ctx, m) + }; + switch (ty) { + | Prod(ts) => + switch (e2.term) { + | Var(name) => + let (body, m) = go'(~ctx=[], ~mode, e2, m); + let element: option(Typ.t) = + LabeledTuple.find_label(Typ.get_label, ts, name) + let m = + e2.ids + |> List.fold_left( + (m, id) => + Id.Map.update( + id, + fun + | Some(Info.InfoExp(exp)) => + Some(Info.InfoExp({...exp, ctx})) + | _ as info => info, + m, + ), + m, + ); + switch (element) { + | Some(Label(_, typ)) => add(~self=Just(typ), ~co_ctx=body.co_ctx, m) + | Some(typ) => add(~self=Just(typ), ~co_ctx=body.co_ctx, m) + | None => add(~self=Just(Unknown(Internal)), ~co_ctx=body.co_ctx, m) + }; + | _ => add(~self=Just(Unknown(Internal)), ~co_ctx=body.co_ctx, m) + }; + | _ => + let (body, m) = go'(~ctx=[], ~mode, e2, m); + add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); }; | Test(e) => let (e, m) = go(~mode=Ana(Bool), e, m); @@ -879,6 +909,12 @@ and utyp_to_info_map = variants, ); add(m); + | Dot(ty1, ty2) => + // TODO: Fix this + let (_, m) = + utyp_to_info_map(~ctx, ~expects=TupleExpected, ~ancestors, ty1, m); + let m = go(ty2, m) |> snd; + add(m); | Forall({term: Var(name), _} as utpat, tbody) => let body_ctx = Ctx.extend_tvar( diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index a2a11c8f09..91cfd68b2f 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -74,6 +74,7 @@ module UTyp = { | Arrow | TupLabel | Tuple + | Dot | Sum | List | Var @@ -111,6 +112,7 @@ module UTyp = { | Constructor(_) => Constructor | TupLabel(_) => TupLabel | Tuple(_) => Tuple + | Dot(_) => Dot | Parens(_) => Parens | Ap(_) => Ap | Sum(_) => Sum @@ -132,12 +134,20 @@ module UTyp = { | Arrow => "Function type" | TupLabel => "Labeled Tuple Item type" | Tuple => "Product type" + | Dot => "Dot type" | Sum => "Sum type" | Parens => "Parenthesized type" | Ap => "Constructor application" | Forall => "Forall Type" | Rec => "Recursive Type"; + let get_label: t => option((LabeledTuple.t, t)) = + ty => + switch (ty.term) { + | TupLabel(s, ty') => Some((s, ty')) + | _ => None + }; + let rec is_arrow = (typ: t) => { switch (typ.term) { | Parens(typ) @@ -152,6 +162,7 @@ module UTyp = { | String | List(_) | Tuple(_) + | Dot(_) | Var(_) | Constructor(_) | Ap(_) @@ -176,6 +187,7 @@ module UTyp = { | Arrow(_) | List(_) | Tuple(_) + | Dot(_) | Var(_) | Constructor(_) | Ap(_) @@ -203,6 +215,25 @@ module UTyp = { | Arrow(u1, u2) => Arrow(to_typ(ctx, u1), to_typ(ctx, u2)) | TupLabel(s, ut) => Label(s, to_typ(ctx, ut)) | Tuple(us) => Prod(List.map(to_typ(ctx), us)) + | Dot(typ1, typ2) => + // TODO: Fix this + switch (typ1.term) { + | Tuple(ts) => + let element: option(t) = + switch (typ2.term) { + | Var(name) => LabeledTuple.find_label(get_label, ts, name) + | _ => None + }; + switch (element) { + | Some(ut) => + switch (ut.term) { + | TupLabel(_, ut') => to_typ(ctx, ut') + | _ => Unknown(Internal) + } + | None => Unknown(Internal) + }; + | _ => Unknown(Internal) + } | Sum(uts) => Sum(to_ctr_map(ctx, uts)) | List(u) => List(to_typ(ctx, u)) | Parens(u) => to_typ(ctx, u) @@ -752,10 +783,15 @@ module UExp = { | TupLabel(_, e) => is_fun(e) | TypFun(_) | Fun(_) => true - | Dot(e, s) => + | Dot(e1, e2) => let element: option(t) = - switch (e.term) { - | Tuple(ts) => LabeledTuple.find_label(get_label, ts, s) + switch (e1.term) { + | Tuple(ts) => + switch (e2.term) { + | Var(name) + | Constructor(name) => LabeledTuple.find_label(get_label, ts, name) + | _ => None + } | _ => None // TODO (Anthony): other exps }; switch (element) { @@ -801,10 +837,16 @@ module UExp = { | Parens(e) => is_tuple_of_functions(e) | TupLabel(_, e) => is_tuple_of_functions(e) | Tuple(es) => es |> List.for_all(is_fun) - | Dot(e, s) => + | Dot(e1, e2) => let element: option(t) = - switch (e.term) { - | Tuple(ts) => LabeledTuple.find_label(get_label, ts, s) + switch (e1.term) { + | Tuple(ts) => + switch (e2.term) { + | Var(name) + | Constructor(name) => + LabeledTuple.find_label(get_label, ts, name) + | _ => None + } | _ => None // TODO (Anthony): other exps }; switch (element) { diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index c41c5000cb..65d2014626 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -159,7 +159,7 @@ and UExp: { | TupLabel(LabeledTuple.t, t) | TypFun(UTPat.t, t) | Tuple(list(t)) - | Dot(t, string) + | Dot(t, t) | Var(Var.t) | Let(UPat.t, t, t) | TyAlias(UTPat.t, UTyp.t, t) @@ -308,7 +308,7 @@ and UExp: { | TupLabel(LabeledTuple.t, t) | TypFun(UTPat.t, t) | Tuple(list(t)) - | Dot(t, string) + | Dot(t, t) | Var(Var.t) | Let(UPat.t, t, t) | TyAlias(UTPat.t, UTyp.t, t) @@ -445,6 +445,7 @@ and UTyp: { | Arrow(t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) + | Dot(t, t) | Parens(t) | Ap(t, t) | Sum(list(variant)) @@ -473,6 +474,7 @@ and UTyp: { | Arrow(t, t) | TupLabel(LabeledTuple.t, t) | Tuple(list(t)) + | Dot(t, t) | Parens(t) | Ap(t, t) | Sum(list(variant)) diff --git a/src/haz3lschool/SyntaxTest.re b/src/haz3lschool/SyntaxTest.re index cd568d5a10..07f7cec09c 100644 --- a/src/haz3lschool/SyntaxTest.re +++ b/src/haz3lschool/SyntaxTest.re @@ -102,7 +102,6 @@ let rec find_fn = | TypFun(_, body) | Fun(_, body) => l |> find_fn(name, body) | TupLabel(_, u1) - | Dot(u1, _) | TypAp(u1, _) | Parens(u1) | UnOp(_, u1) @@ -110,6 +109,7 @@ let rec find_fn = | Test(u1) | Filter(_, _, u1) => l |> find_fn(name, u1) | Ap(u1, u2) + | Dot(u1, u2) | Pipeline(u1, u2) | Seq(u1, u2) | Cons(u1, u2) @@ -207,9 +207,9 @@ let rec var_mention = (name: string, uexp: Term.UExp.t): bool => { | UnOp(_, u) | TyAlias(_, _, u) | TupLabel(_, u) - | Dot(u, _) | Filter(_, _, u) => var_mention(name, u) | Ap(u1, u2) + | Dot(u1, u2) | Pipeline(u1, u2) | Seq(u1, u2) | Cons(u1, u2) @@ -264,7 +264,6 @@ let rec var_applied = (name: string, uexp: Term.UExp.t): bool => { | UnOp(_, u) | TyAlias(_, _, u) | TupLabel(_, u) - | Dot(u, _) | Filter(_, _, u) => var_applied(name, u) | TypAp(u, _) => switch (u.term) { @@ -289,6 +288,7 @@ let rec var_applied = (name: string, uexp: Term.UExp.t): bool => { | Cons(u1, u2) | Seq(u1, u2) | ListConcat(u1, u2) + | Dot(u1, u2) | BinOp(_, u1, u2) => var_applied(name, u1) || var_applied(name, u2) | If(u1, u2, u3) => var_applied(name, u1) || var_applied(name, u2) || var_applied(name, u3) @@ -356,7 +356,6 @@ let rec tail_check = (name: string, uexp: Term.UExp.t): bool => { | TypFun(_, u) | TypAp(u, _) | Parens(u) => tail_check(name, u) - | Dot(u, _) | UnOp(_, u) => !var_mention(name, u) | Ap(u1, u2) => var_mention(name, u2) ? false : tail_check(name, u1) | DeferredAp(fn, args) => @@ -368,6 +367,7 @@ let rec tail_check = (name: string, uexp: Term.UExp.t): bool => { | Seq(u1, u2) => var_mention(name, u1) ? false : tail_check(name, u2) | Cons(u1, u2) | ListConcat(u1, u2) + | Dot(u1, u2) | BinOp(_, u1, u2) => !(var_mention(name, u1) || var_mention(name, u2)) | If(u1, u2, u3) => var_mention(name, u1) diff --git a/src/haz3lweb/explainthis/Example.re b/src/haz3lweb/explainthis/Example.re index 49f776ff64..bd01964acd 100644 --- a/src/haz3lweb/explainthis/Example.re +++ b/src/haz3lweb/explainthis/Example.re @@ -115,7 +115,8 @@ let pipeline = () => mk_monotile(Form.get("pipeline")); let labeled_exp = () => mk_monotile(Form.get("tuple_labeled_exp")); let labeled_pat = () => mk_monotile(Form.get("tuple_labeled_pat")); let labeled_typ = () => mk_monotile(Form.get("tuple_labeled_typ")); -let dot = () => mk_monotile(Form.get("dot_exp")); +let dot_exp = () => mk_monotile(Form.get("dot_exp")); +let dot_typ = () => mk_monotile(Form.get("dot_typ")); let nil = () => exp("[]"); let deferral = () => exp("_"); let typeann = () => mk_monotile(Form.get("typeann")); diff --git a/src/haz3lweb/explainthis/ExplainThisForm.re b/src/haz3lweb/explainthis/ExplainThisForm.re index d490861255..9aadba8015 100644 --- a/src/haz3lweb/explainthis/ExplainThisForm.re +++ b/src/haz3lweb/explainthis/ExplainThisForm.re @@ -91,6 +91,7 @@ type example_id = | Label2 | Dot1 | Dot2 + | DotTyp | Tuple1 | Tuple2 | Let(let_examples) @@ -227,6 +228,7 @@ type form_id = | Tuple0Typ | Tuple2Typ | Tuple3Typ + | DotTyp | LabelledSumTyp | SumTypUnaryConstructorDef | SumTypNullaryConstructorDef @@ -325,6 +327,7 @@ type group_id = | Tuple0Typ | Tuple2Typ | Tuple3Typ + | DotTyp | LabelledSumTyp | SumTypUnaryConstructorDef | SumTypNullaryConstructorDef diff --git a/src/haz3lweb/explainthis/data/DotExp.re b/src/haz3lweb/explainthis/data/DotExp.re index 8c7081b6f3..bacafdfb7a 100644 --- a/src/haz3lweb/explainthis/data/DotExp.re +++ b/src/haz3lweb/explainthis/data/DotExp.re @@ -5,13 +5,13 @@ open Example; let dot_example_1 = { sub_id: Dot1, term: mk_example("(x=1, y=2).x"), - message: "Gives the element in the tuple associated with the label 'x', which in this example is 1.", + message: "Retrieves the element in the tuple associated with the label 'x', which in this example is 1.", }; let dot_exp: form = { let explanation = "Dot Operator explanation"; { id: DotExp, - syntactic_form: [exp("(x=e)"), dot(), pat("x")], + syntactic_form: [exp("(x=e)"), dot_exp(), pat("x")], expandable_id: None, explanation, examples: [dot_example_1], diff --git a/src/haz3lweb/explainthis/data/DotTyp.re b/src/haz3lweb/explainthis/data/DotTyp.re new file mode 100644 index 0000000000..e4a65d8f0b --- /dev/null +++ b/src/haz3lweb/explainthis/data/DotTyp.re @@ -0,0 +1,21 @@ +// open Haz3lcore; +open ExplainThisForm; +open Example; +let dot_typ: form = { + let explanation = "Dot Operator Typ explanation"; + { + id: DotTyp, + syntactic_form: [exp("(x=t)"), dot_typ(), pat("x")], + expandable_id: None, + explanation, + examples: [], + }; +}; +// let _exp1 = exp("e1"); +// let _exp2 = exp("e2"); +// let tuple_exp_size2_coloring_ids = +// (~exp1_id: Id.t, ~exp2_id: Id.t): list((Id.t, Id.t)) => { +// [(Piece.id(_exp1), exp1_id), (Piece.id(_exp2), exp2_id)]; +// } + +let dot_typ: group = {id: DotTyp, forms: [dot_typ]}; diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index c62c7e64bf..8dfc741281 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -168,6 +168,7 @@ let typ_err_view = (ok: Info.error_typ) => | WantConstructorFoundAp | WantConstructorFoundType(_) => [text("Expected a constructor")] | WantTypeFoundAp => [text("Must be part of a sum type")] + | WantTuple => [text("Expect a valid tuple")] | DuplicateConstructor(name) => [ Type.view(Var(name)), text("already used in this sum"), diff --git a/src/haz3lweb/view/ExplainThis.re b/src/haz3lweb/view/ExplainThis.re index 9ecc05118a..28bd419b49 100644 --- a/src/haz3lweb/view/ExplainThis.re +++ b/src/haz3lweb/view/ExplainThis.re @@ -2278,6 +2278,7 @@ let get_doc = | _ => basic(ArrowTyp.arrow) }; | TupLabel(_, _) => get_message(LabeledTyp.labeled_typ) + | Dot(_, _) => get_message(DotTyp.dot_typ) | Tuple(elements) => let basic = group => get_message( diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index 6ca846d8e1..374bd2afd1 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -157,7 +157,7 @@ let mk = | (BinIntOp(_), _) | (BinFloatOp(_), _) | (BinStringOp(_), _) - | (Dot(_), _) + | (Dot, _) | (Projection, _) | (ListCons, _) | (ListConcat, _) @@ -446,14 +446,10 @@ let mk = DHDoc_common.Delim.mk("="), go'(d, TupLabel), ]) - | Dot(d, s) => - Doc.hcats([ - DHDoc_common.Delim.open_Parenthesized, - go'(d, Dot), - DHDoc_common.Delim.close_Parenthesized, - DHDoc_common.Delim.mk("."), - Doc.text(s), - ]) + | Dot(d1, d2) => + let doc1 = go'(d1, Dot1); + let doc2 = go'(d2, Dot2); + DHDoc_common.mk_Dot(doc1, doc2); | Tuple([]) => DHDoc_common.Delim.triv | Tuple(ds) => DHDoc_common.mk_Tuple(ds |> List.mapi((i, d) => go'(d, Tuple(i)))) diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re index 48e0520c0c..c96aa3b7e0 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re @@ -142,4 +142,6 @@ let mk_Ap = (doc1, doc2) => let mk_Prj = (targ, n) => Doc.hcats([targ, Delim.projection_dot, Doc.text(string_of_int(n))]); +let mk_Dot = (doc1, doc2) => Doc.(hcats([doc1, text("."), doc2])); + let mk_Undefined = () => Doc.text("undefined"); diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei index d5927df180..70792ab2a8 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei @@ -95,4 +95,6 @@ let mk_Ap: (Pretty.Doc.t('a), Pretty.Doc.t('a)) => Pretty.Doc.t('a); let mk_Prj: (Pretty.Doc.t(DHAnnot.t), int) => Pretty.Doc.t(DHAnnot.t); +let mk_Dot: (Pretty.Doc.t('a), Pretty.Doc.t('a)) => Pretty.Doc.t('a); + let mk_Undefined: unit => Pretty.Doc.t('a); From 9ab0f49b2e9d8530d0c31df5742d4bd8ccc651b8 Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 16 Aug 2024 12:01:34 -0400 Subject: [PATCH 017/108] dot operator static fixes --- src/haz3lcore/dynamics/Transition.re | 1 + src/haz3lcore/dynamics/TypeAssignment.re | 4 +- src/haz3lcore/statics/Statics.re | 52 +++++++++++++++--------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index f649f83474..f6b9a99592 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -570,6 +570,7 @@ module Transition = (EV: EV_MODE) => { let element = LabeledTuple.find_label(DHExp.get_label, ds, name); switch (element) { | Some(TupLabel(_, exp)) => exp + // TODO (Anthony): operate on casts instead of the original tuple, like static checking. | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }; }, diff --git a/src/haz3lcore/dynamics/TypeAssignment.re b/src/haz3lcore/dynamics/TypeAssignment.re index b112eeaae0..dbcd2c37e7 100644 --- a/src/haz3lcore/dynamics/TypeAssignment.re +++ b/src/haz3lcore/dynamics/TypeAssignment.re @@ -289,12 +289,12 @@ let rec typ_of_dhexp = let element = LabeledTuple.find_label(DHExp.get_label, ds, name); switch (element) { | Some(TupLabel(_, exp)) => typ_of_dhexp(ctx, m, exp) - | _ => raise(EvaluatorError.Exception(BadPatternMatch)) + | _ => None }; | (TupLabel(l, exp), BoundVar(name)) when LabeledTuple.compare(name, l) == 0 => typ_of_dhexp(ctx, m, exp) - | _ => raise(EvaluatorError.Exception(BadPatternMatch)) + | _ => None } | Tuple(dhs) => let+ typ_list = diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index d6d97c2f23..5e4fe6b88a 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -297,11 +297,11 @@ and uexp_to_info_map = | TupLabel(s, e) when is_contained => let mode = Mode.of_label(ctx, mode); let (e, m) = go(~mode, e, m); - // treating standalone labeled expressions as within a tuple of size 1 add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); | TupLabel(s, e) => let mode = Mode.of_label(ctx, mode); let (e, m) = go(~mode, e, m); + // treating standalone labeled expressions as within a tuple of size 1 add(~self=Just(Prod([Label(s, e.ty)])), ~co_ctx=e.co_ctx, m); | Tuple(es) => let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); @@ -312,14 +312,17 @@ and uexp_to_info_map = m, ); | Dot(e1, e2) => + let (info_e1, m) = go(~mode=Syn, e1, m); let (ty, m) = { - let (info_e1, m) = go(~mode=Syn, e1, m); + print_endline("e1 info"); + print_endline(Info.show_exp(info_e1)); switch (e2.term, info_e1.ty) { | (Var(name), Unknown(_)) | (Constructor(name), Unknown(_)) => let ty = Typ.Prod([Label(name, Unknown(Internal))]); let (_, m) = go(~mode=Mode.Ana(ty), e1, m); (ty, m); + | (_, Var(_)) => (Typ.weak_head_normalize(ctx, info_e1.ty), m) | _ => (info_e1.ty, m) }; }; @@ -327,30 +330,41 @@ and uexp_to_info_map = | Prod(ts) => switch (e2.term) { | Var(name) => - let (body, m) = go'(~ctx=[], ~mode, e2, m); let element: option(Typ.t) = - LabeledTuple.find_label(Typ.get_label, ts, name) + LabeledTuple.find_label(Typ.get_label, ts, name); let m = e2.ids |> List.fold_left( - (m, id) => - Id.Map.update( - id, - fun - | Some(Info.InfoExp(exp)) => - Some(Info.InfoExp({...exp, ctx})) - | _ as info => info, - m, - ), + (m, id) => + Id.Map.update( + id, + fun + | Some(Info.InfoExp(exp)) => + Some(Info.InfoExp({...exp, ctx})) + | _ as info => info, + m, + ), + m, + ); + switch (element) { + | Some(Label(_, typ)) + | Some(typ) => + let (body, m) = + go'( + ~ctx=[VarEntry({name, id: List.nth(e2.ids, 0), typ})], + ~mode, + e2, m, ); - switch (element) { - | Some(Label(_, typ)) => add(~self=Just(typ), ~co_ctx=body.co_ctx, m) - | Some(typ) => add(~self=Just(typ), ~co_ctx=body.co_ctx, m) - | None => add(~self=Just(Unknown(Internal)), ~co_ctx=body.co_ctx, m) + add(~self=Just(typ), ~co_ctx=body.co_ctx, m); + | None => + let (body, m) = go'(~ctx=[], ~mode, e2, m); + add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); }; - | _ => add(~self=Just(Unknown(Internal)), ~co_ctx=body.co_ctx, m) - }; + | _ => + let (body, m) = go'(~ctx=[], ~mode, e2, m); + add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); + } | _ => let (body, m) = go'(~ctx=[], ~mode, e2, m); add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); From db194f85fc565392ad02f8f49cea85dbb1dd90bc Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 23 Aug 2024 01:18:17 -0400 Subject: [PATCH 018/108] Creation of Label term, bug fixes, documentation updates --- src/haz3lcore/LabeledTuple.re | 8 +- src/haz3lcore/dynamics/Constraint.re | 8 +- src/haz3lcore/dynamics/DH.re | 30 ++++--- src/haz3lcore/dynamics/DHPat.re | 7 +- src/haz3lcore/dynamics/Elaborator.re | 15 ++-- src/haz3lcore/dynamics/EvalCtx.re | 2 +- src/haz3lcore/dynamics/EvaluatorPost.re | 15 ++-- src/haz3lcore/dynamics/EvaluatorStep.re | 10 +-- src/haz3lcore/dynamics/FilterMatcher.re | 13 ++- src/haz3lcore/dynamics/PatternMatch.re | 52 +++++++----- src/haz3lcore/dynamics/Stepper.re | 4 +- src/haz3lcore/dynamics/Substitution.re | 3 +- src/haz3lcore/dynamics/Transition.re | 20 ++--- src/haz3lcore/dynamics/TypeAssignment.re | 28 ++++--- src/haz3lcore/lang/Form.re | 6 +- src/haz3lcore/statics/MakeTerm.re | 37 ++++----- src/haz3lcore/statics/Statics.re | 70 +++++++++------- src/haz3lcore/statics/Term.re | 43 +++++++++- src/haz3lcore/statics/TermBase.re | 20 +++-- src/haz3lcore/statics/TypBase.re | 63 +++++++++------ src/haz3lcore/zipper/EditorUtil.re | 1 + src/haz3lschool/SyntaxTest.re | 7 ++ src/haz3lweb/explainthis/ExplainThisForm.re | 1 + src/haz3lweb/explainthis/data/FunctionExp.re | 25 +++++- src/haz3lweb/explainthis/data/Label.re | 16 ---- src/haz3lweb/explainthis/data/LabelTerm.re | 14 ++++ src/haz3lweb/explainthis/data/LabeledExp.re | 6 +- src/haz3lweb/explainthis/data/LabeledPat.re | 4 +- src/haz3lweb/explainthis/data/LabeledTyp.re | 4 +- src/haz3lweb/explainthis/data/LetExp.re | 31 ++++++- src/haz3lweb/view/ExplainThis.re | 81 +++++++++++++++++-- src/haz3lweb/view/Type.re | 3 +- src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re | 6 +- src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re | 6 +- .../view/dhcode/layout/DHDoc_common.re | 2 + .../view/dhcode/layout/DHDoc_common.rei | 2 + src/haz3lweb/view/dhcode/layout/HTypDoc.re | 3 +- 37 files changed, 460 insertions(+), 206 deletions(-) delete mode 100644 src/haz3lweb/explainthis/data/Label.re create mode 100644 src/haz3lweb/explainthis/data/LabelTerm.re diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 4e756288a1..c7bb24bf79 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -5,7 +5,13 @@ exception Exception; [@deriving (show({with_path: false}), sexp, yojson)] type t = string; -let eq = String.equal; +let equal: (option((t, 'a)), option((t, 'b))) => bool = + (left, right) => { + switch (left, right) { + | (Some((s1, _)), Some((s2, _))) => String.equal(s1, s2) + | (_, _) => false + }; + }; let length = String.length; diff --git a/src/haz3lcore/dynamics/Constraint.re b/src/haz3lcore/dynamics/Constraint.re index 590e59ece6..1c6e74a460 100644 --- a/src/haz3lcore/dynamics/Constraint.re +++ b/src/haz3lcore/dynamics/Constraint.re @@ -15,7 +15,7 @@ type t = | Or(t, t) | InjL(t) | InjR(t) - | TupLabel(LabeledTuple.t, t) + | TupLabel(t, t) | Pair(t, t); let rec dual = (c: t): t => @@ -33,7 +33,7 @@ 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)) - | TupLabel(s, c) => TupLabel(s, dual(c)) + | TupLabel(c1, c2) => TupLabel(dual(c1), dual(c2)) | Pair(c1, c2) => Or( Pair(c1, dual(c2)), @@ -57,7 +57,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)) - | TupLabel(s, c) => TupLabel(s, truify(c)) + | TupLabel(c1, c2) => TupLabel(truify(c1), truify(c2)) | Pair(c1, c2) => Pair(truify(c1), truify(c2)) }; @@ -77,7 +77,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)) - | TupLabel(s, c) => TupLabel(s, falsify(c)) + | TupLabel(c1, c2) => TupLabel(falsify(c1), falsify(c2)) | Pair(c1, c2) => Pair(falsify(c1), falsify(c2)) }; diff --git a/src/haz3lcore/dynamics/DH.re b/src/haz3lcore/dynamics/DH.re index 7b65113ac8..92213a0e09 100644 --- a/src/haz3lcore/dynamics/DH.re +++ b/src/haz3lcore/dynamics/DH.re @@ -38,7 +38,8 @@ module rec DHExp: { | ListLit(MetaVar.t, MetaVarInst.t, Typ.t, list(t)) | Cons(t, t) | ListConcat(t, t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | Tuple(list(t)) | Dot(t, t) | Prj(t, int) @@ -103,7 +104,8 @@ module rec DHExp: { | ListLit(MetaVar.t, MetaVarInst.t, Typ.t, list(t)) | Cons(t, t) | ListConcat(t, t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | Tuple(list(t)) | Dot(t, t) | Prj(t, int) @@ -149,6 +151,7 @@ module rec DHExp: { | ListLit(_) => "ListLit" | Cons(_, _) => "Cons" | ListConcat(_, _) => "ListConcat" + | Label(_) => "Label" | TupLabel(_) => "Labeled Tuple Item" | Tuple(_) => "Tuple" | Dot(_) => "DotOp" @@ -170,20 +173,20 @@ module rec DHExp: { let get_label: t => option((LabeledTuple.t, t)) = fun - | TupLabel(s, t') => Some((s, t')) + | TupLabel(Label(name), t') => Some((name, t')) | _ => None; let cast = (d: t, t1: Typ.t, t2: Typ.t): t => { - // TODO (Anthony): Other cases for label casting? - let (islabel, lab) = + // TODO (Anthony): Other cases for tuplabel casting? + let (islabel, name) = switch (t2) { - | Label(s, Unknown(SynSwitch)) => (true, s) + | TupLabel(Label(name), Unknown(SynSwitch)) => (true, name) | _ => (false, "") }; if (Typ.eq(t1, t2) || t2 == Unknown(SynSwitch)) { d; } else if (islabel) { - TupLabel(lab, d); + TupLabel(Label(name), d); } else { Cast(d, t1, t2); }; @@ -197,7 +200,7 @@ module rec DHExp: { | Closure(ei, d) => Closure(ei, strip_casts(d)) | Cast(d, _, _) => strip_casts(d) | FailedCast(d, _, _) => strip_casts(d) - | TupLabel(s, d) => TupLabel(s, strip_casts(d)) + | TupLabel(a, b) => TupLabel(strip_casts(a), strip_casts(b)) | Tuple(ds) => Tuple(ds |> List.map(strip_casts)) | Dot(a, b) => Dot(strip_casts(a), strip_casts(b)) | Prj(d, n) => Prj(strip_casts(d), n) @@ -240,6 +243,7 @@ module rec DHExp: { | IntLit(_) as d | FloatLit(_) as d | StringLit(_) as d + | Label(_) as d | Constructor(_) as d | InvalidOperation(_) as d => d | IfThenElse(consistent, c, d1, d2) => @@ -254,8 +258,9 @@ module rec DHExp: { let rec fast_equal = (d1: t, d2: t): bool => { switch (d1, d2) { /* TODO: Labels are a special case, but should they be?*/ - | (TupLabel(s1, d1), TupLabel(s2, d2)) => - LabeledTuple.compare(s1, s2) == 0 && fast_equal(d1, d2) + | (TupLabel(_, d1'), TupLabel(_, d2')) => + LabeledTuple.equal(get_label(d1), get_label(d2)) + && fast_equal(d1', d2') | (TupLabel(_, d1), _) => fast_equal(d1, d2) | (_, TupLabel(_, d2)) => fast_equal(d1, d2) | (Undefined, _) @@ -268,6 +273,8 @@ module rec DHExp: { | (Constructor(_), _) => d1 == d2 | (StringLit(s1), StringLit(s2)) => String.equal(s1, s2) | (StringLit(_), _) => false + | (Label(name1), Label(name2)) => String.equal(name1, name2) + | (Label(_), _) => false /* Non-hole forms: recurse */ | (Test(id1, d1), Test(id2, d2)) => id1 == id2 && fast_equal(d1, d2) @@ -442,7 +449,7 @@ module rec DHExp: { | Cons(t1, t2) => Cons(re(t1), re(t2)) | ListConcat(t1, t2) => ListConcat(re(t1), re(t2)) | Tuple(args) => Tuple(List.map(re, args)) - | TupLabel(s, t) => TupLabel(s, re(t)) + | TupLabel(t1, t2) => TupLabel(re(t1), re(t2)) | Dot(t1, t2) => Dot(re(t1), re(t2)) | Prj(t, n) => Prj(re(t), n) | ConsistentCase(case) => ConsistentCase(ty_subst_case(s, x, case)) @@ -462,6 +469,7 @@ module rec DHExp: { | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | FailedCast(_, _, _) => exp }; } diff --git a/src/haz3lcore/dynamics/DHPat.re b/src/haz3lcore/dynamics/DHPat.re index c35cb13564..8a7392ecac 100644 --- a/src/haz3lcore/dynamics/DHPat.re +++ b/src/haz3lcore/dynamics/DHPat.re @@ -14,7 +14,8 @@ type t = | StringLit(string) | ListLit(Typ.t, list(t)) | Cons(t, t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | Tuple(list(t)) | Constructor(string, Typ.t) | Ap(t, t); @@ -39,6 +40,7 @@ let rec binds_var = (x: Var.t, dp: t): bool => | FloatLit(_) | BoolLit(_) | StringLit(_) + | Label(_) | Constructor(_) => false | Var(y) => Var.eq(x, y) | TupLabel(_, dp) => binds_var(x, dp) @@ -61,6 +63,7 @@ let rec bound_vars = (dp: t): list(Var.t) => | FloatLit(_) | BoolLit(_) | StringLit(_) + | Label(_) | Constructor(_) => [] | Var(y) => [y] | TupLabel(_, dp) => bound_vars(dp) @@ -72,5 +75,5 @@ let rec bound_vars = (dp: t): list(Var.t) => let get_label: t => option((LabeledTuple.t, t)) = fun - | TupLabel(s, t') => Some((s, t')) + | TupLabel(Label(name), t') => Some((name, t')) | _ => None; diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 2bf9117778..b08fa6415b 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -114,6 +114,7 @@ let cast = (ctx: Ctx.t, mode: Mode.t, self_ty: Typ.t, d: DHExp.t) => | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | BinBoolOp(_) | BinIntOp(_) | BinFloatOp(_) @@ -166,6 +167,7 @@ let rec dhexp_of_uexp = | Int(n) => Some(IntLit(n)) | Float(n) => Some(FloatLit(n)) | String(s) => Some(StringLit(s)) + | Label(name) => Some(Label(name)) | ListLit(es) => let* ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; let+ ty = fixed_exp_typ(m, uexp); @@ -180,9 +182,10 @@ let rec dhexp_of_uexp = | TypFun(tpat, body) => let+ d1 = dhexp_of_uexp(m, body); DHExp.TypFun(tpat, d1, None); - | TupLabel(s, e) => + | TupLabel(label, e) => + let* dlab = dhexp_of_uexp(m, label); let+ de = dhexp_of_uexp(m, e); - DHExp.TupLabel(s, de); + DHExp.TupLabel(dlab, de); | Tuple(es) => let+ ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; DHExp.Tuple(ds); @@ -455,6 +458,7 @@ and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.t) => { | Int(n) => wrap(IntLit(n)) | Float(n) => wrap(FloatLit(n)) | String(s) => wrap(StringLit(s)) + | Label(name) => wrap(Label(name)) | Triv => wrap(Tuple([])) | ListLit(ps) => let* ds = ps |> List.map(dhpat_of_upat(m)) |> OptUtil.sequence; @@ -482,9 +486,10 @@ and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.t) => { let* d_hd = dhpat_of_upat(m, hd); let* d_tl = dhpat_of_upat(m, tl); wrap(Cons(d_hd, d_tl)); - | TupLabel(s, dp) => - let* dp2 = dhpat_of_upat(m, dp); - wrap(TupLabel(s, dp2)); + | TupLabel(lab, p) => + let* dlab = dhpat_of_upat(m, lab); + let* dp = dhpat_of_upat(m, p); + wrap(TupLabel(dlab, dp)); | Tuple(ps) => let* ds = ps |> List.map(dhpat_of_upat(m)) |> OptUtil.sequence; wrap(Tuple(ds)); diff --git a/src/haz3lcore/dynamics/EvalCtx.re b/src/haz3lcore/dynamics/EvalCtx.re index 82fd48fa1c..45ae374028 100644 --- a/src/haz3lcore/dynamics/EvalCtx.re +++ b/src/haz3lcore/dynamics/EvalCtx.re @@ -77,7 +77,7 @@ type t = | BinFloatOp2(TermBase.UExp.op_bin_float, DHExp.t, t) | BinStringOp1(TermBase.UExp.op_bin_string, t, DHExp.t) | BinStringOp2(TermBase.UExp.op_bin_string, DHExp.t, t) - | TupLabel(LabeledTuple.t, t) + | TupLabel(DHExp.t, t) | Tuple(t, (list(DHExp.t), list(DHExp.t))) | Dot1(t, DHExp.t) | Dot2(DHExp.t, t) diff --git a/src/haz3lcore/dynamics/EvaluatorPost.re b/src/haz3lcore/dynamics/EvaluatorPost.re index 5d28c9dc4a..2aa3d48665 100644 --- a/src/haz3lcore/dynamics/EvaluatorPost.re +++ b/src/haz3lcore/dynamics/EvaluatorPost.re @@ -46,6 +46,7 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | Undefined | Constructor(_) => d |> return @@ -116,9 +117,9 @@ let rec pp_eval = (d: DHExp.t): m(DHExp.t) => ); ListLit(a, b, c, ds); - | TupLabel(dp, d1) => - let* d1' = pp_eval(d1); - TupLabel(dp, d1') |> return; + | TupLabel(dlab, d) => + let* d' = pp_eval(d); + TupLabel(dlab, d') |> return; | Tuple(ds) => let+ ds = @@ -288,6 +289,7 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | Undefined | Constructor(_) => d |> return @@ -383,9 +385,9 @@ and pp_uneval = (env: ClosureEnvironment.t, d: DHExp.t): m(DHExp.t) => ); ListLit(a, b, c, ds); - | TupLabel(dp, d1) => - let* d1' = pp_uneval(env, d1); - TupLabel(dp, d1') |> return; + | TupLabel(dlab, d) => + let* d' = pp_uneval(env, d); + TupLabel(dlab, d') |> return; | Tuple(ds) => let+ ds = @@ -490,6 +492,7 @@ let rec track_children_of_hole = | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | BuiltinFun(_) | Undefined | BoundVar(_) => hii diff --git a/src/haz3lcore/dynamics/EvaluatorStep.re b/src/haz3lcore/dynamics/EvaluatorStep.re index ed8b06d5d6..92c47e337c 100644 --- a/src/haz3lcore/dynamics/EvaluatorStep.re +++ b/src/haz3lcore/dynamics/EvaluatorStep.re @@ -279,9 +279,9 @@ let rec compose = (ctx: EvalCtx.t, d: DHExp.t): DHExp.t => { | ListConcat2(d1, ctx) => let d2 = compose(ctx, d); ListConcat(d1, d2); - | TupLabel(s, ctx) => - let d2 = compose(ctx, d); - TupLabel(s, d2); + | TupLabel(label, ctx) => + let d = compose(ctx, d); + TupLabel(label, d); | Dot1(ctx, d2) => let d1 = compose(ctx, d); Dot(d1, d2); @@ -454,9 +454,9 @@ let rec matches = | Tuple(ctx, ds) => let+ ctx = matches(env, flt, ctx, exp, act, idx); Tuple(ctx, ds); - | TupLabel(s, ctx) => + | TupLabel(label, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); - TupLabel(s, ctx); + TupLabel(label, ctx); | Dot1(ctx, d2) => let+ ctx = matches(env, flt, ctx, exp, act, idx); Dot1(ctx, d2); diff --git a/src/haz3lcore/dynamics/FilterMatcher.re b/src/haz3lcore/dynamics/FilterMatcher.re index d9a1367a9d..e1ece2139c 100644 --- a/src/haz3lcore/dynamics/FilterMatcher.re +++ b/src/haz3lcore/dynamics/FilterMatcher.re @@ -17,7 +17,8 @@ let rec matches_exp = // TODO (Anthony): Is this right? /* Labels are a special case*/ - | (TupLabel(_, dv), TupLabel(_, fv)) => matches_exp(dv, fv) + | (TupLabel(dl, dv), TupLabel(fl, fv)) => + matches_exp(dl, fl) && matches_exp(dv, fv) | (TupLabel(_, dv), _) => matches_exp(dv, f) | (_, TupLabel(_, fv)) => matches_exp(d, fv) @@ -153,6 +154,9 @@ let rec matches_exp = | (StringLit(dv), StringLit(fv)) => dv == fv | (StringLit(_), _) => false + | (Label(dv), Label(fv)) => dv == fv + | (Label(_), _) => false + | (Constructor(_), Ap(Constructor("~MVal", _), Tuple([]))) => true | (Constructor(dt, _), Constructor(ft, _)) => dt == ft | (Constructor(_), _) => false @@ -309,8 +313,9 @@ and matches_fun = and matches_pat = (d: DHPat.t, f: DHPat.t): bool => { switch (d, f) { /* Labels are a special case*/ - | (TupLabel(s1, dx), TupLabel(s2, fx)) => - LabeledTuple.compare(s1, s2) == 0 && matches_pat(dx, fx) + | (TupLabel(_, dx), TupLabel(_, fx)) => + LabeledTuple.equal(DHPat.get_label(d), DHPat.get_label(f)) + && matches_pat(dx, fx) | (TupLabel(_, dx), _) => matches_pat(dx, f) | (_, TupLabel(_, fx)) => matches_pat(d, fx) | (_, EmptyHole(_)) => true @@ -324,6 +329,8 @@ and matches_pat = (d: DHPat.t, f: DHPat.t): bool => { | (BoolLit(_), _) => false | (StringLit(dv), StringLit(fv)) => dv == fv | (StringLit(_), _) => false + | (Label(dv), Label(fv)) => dv == fv + | (Label(_), _) => false | (ListLit(dty1, dl), ListLit(fty1, fl)) => switch ( List.fold_left2((res, d, f) => res && matches_pat(d, f), true, dl, fl) diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index cea5964a5d..912e59cba7 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -38,32 +38,33 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => { | (InvalidText(_), _) => IndetMatch | (BadConstructor(_), _) => IndetMatch /* Labels are a special case */ - | (TupLabel(s1, dp), TupLabel(s2, d)) => - if (LabeledTuple.compare(s1, s2) == 0) { - matches(dp, d); + | (TupLabel(_, dp'), TupLabel(_, d')) => + if (LabeledTuple.equal(DHPat.get_label(dp), DHExp.get_label(d))) { + matches(dp', d'); } else { DoesNotMatch; } - | (Var(x), TupLabel(s, d)) when LabeledTuple.compare(x, s) == 0 => - let env = Environment.extend(Environment.empty, (x, d)); + | (Var(x), TupLabel(_, d')) + when LabeledTuple.equal(Some((x, dp)), DHExp.get_label(d)) => + let env = Environment.extend(Environment.empty, (x, d')); Matches(env); // TODO: Label casting need fixing? - | (TupLabel(_), Cast(d, Label(_, _), Unknown(_))) => + | (TupLabel(_), Cast(d, TupLabel(_, _), Unknown(_))) => switch (d) { | TupLabel(_, d) => matches(dp, d) | _ => matches(dp, d) } - | (TupLabel(_), Cast(d, Unknown(_), Label(s2, _))) => + | (TupLabel(_), Cast(d, Unknown(_), TupLabel(Typ.Label(tlab), _))) => switch (d) { - | TupLabel(_, d) => matches(dp, TupLabel(s2, d)) - | _ => matches(dp, TupLabel(s2, d)) + | TupLabel(_, d) => matches(dp, TupLabel(DHExp.Label(tlab), d)) + | _ => matches(dp, TupLabel(DHExp.Label(tlab), d)) } - | (_, Cast(d, Label(_, ty1), ty2)) => + | (_, Cast(d, TupLabel(_, ty1), ty2)) => switch (d) { | TupLabel(_, d) => matches(dp, Cast(d, ty1, ty2)) | _ => matches(dp, Cast(d, ty1, ty2)) } - | (_, Cast(d, ty1, Label(_, ty2))) => + | (_, Cast(d, ty1, TupLabel(_, ty2))) => switch (d) { | TupLabel(_, d) => matches(dp, Cast(d, ty1, ty2)) // shouldn't happen? | _ => matches(dp, Cast(d, ty1, ty2)) @@ -130,6 +131,18 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => { | (StringLit(_), Cast(d, Unknown(_), String)) => matches(dp, d) | (StringLit(_), _) => DoesNotMatch + | (Label(s1), Label(s2)) => + if (s1 == s2) { + Matches(Environment.empty); + } else { + DoesNotMatch; + } + | (Label(name), Cast(d, Label(name'), Unknown(_))) when name == name' => + matches(dp, d) + | (Label(name), Cast(d, Unknown(_), Label(name'))) when name == name' => + matches(dp, d) + | (Label(_), _) => DoesNotMatch + | (Ap(dp1, dp2), Ap(d1, d2)) => switch (matches(dp1, d1)) { | DoesNotMatch => DoesNotMatch @@ -233,21 +246,21 @@ let rec matches = (dp: DHPat.t, d: DHExp.t): match_result => { let ds = LabeledTuple.rearrange( Typ.get_label, DHExp.get_label, tys, ds, (s, e) => - TupLabel(s, e) + TupLabel(DHExp.Label(s), e) ); let d_typ_pairs = List.combine(ds, tys); let get_label_pair: ((DHExp.t, Typ.t)) => option((LabeledTuple.t, (DHExp.t, Typ.t))) = ( ((d, t)) => switch (t) { - | Label(s, t') => Some((s, (d, t'))) + | TupLabel(Label(name), t') => Some((name, (d, t'))) | _ => None } ); let d_typ_pairs = LabeledTuple.rearrange( Typ.get_label, get_label_pair, tys', d_typ_pairs, (s, (d, t)) => - (TupLabel(s, d), Label(s, t)) + (TupLabel(Label(s), d), TupLabel(Label(s), t)) ); let (ds, tys) = List.split(d_typ_pairs); matches_cast_Tuple( @@ -361,6 +374,7 @@ and matches_cast_Sum = | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | ListLit(_) | Tuple(_) | Dot(_, _) @@ -386,7 +400,7 @@ and matches_cast_Tuple = let filt2: ((DHExp.t, 'a)) => option((LabeledTuple.t, (DHExp.t, 'a))) = ( ((d, c)) => switch (d) { - | TupLabel(s, d') => Some((s, (d', c))) + | TupLabel(DHExp.Label(name), d') => Some((name, (d', c))) | _ => None } ); @@ -451,21 +465,21 @@ and matches_cast_Tuple = let ds = LabeledTuple.rearrange( Typ.get_label, DHExp.get_label, tys, ds, (s, e) => - TupLabel(s, e) + TupLabel(DHExp.Label(s), e) ); let d_typ_pairs = List.combine(ds, tys); let get_label_pair: ((DHExp.t, Typ.t)) => option((LabeledTuple.t, (DHExp.t, Typ.t))) = ( ((d, t)) => switch (t) { - | Label(s, t') => Some((s, (d, t'))) + | TupLabel(Label(name), t') => Some((name, (d, t'))) | _ => None } ); let d_typ_pairs = LabeledTuple.rearrange( Typ.get_label, get_label_pair, tys', d_typ_pairs, (s, (d, t)) => - (TupLabel(s, d), Label(s, t)) + (TupLabel(DHExp.Label(s), d), TupLabel(Typ.Label(s), t)) ); let (ds, tys) = List.split(d_typ_pairs); matches_cast_Tuple( @@ -522,6 +536,7 @@ and matches_cast_Tuple = | Test(_) => DoesNotMatch | FloatLit(_) => DoesNotMatch | StringLit(_) => DoesNotMatch + | Label(_) => DoesNotMatch | ListLit(_) => DoesNotMatch | Cons(_, _) => DoesNotMatch | ListConcat(_) => DoesNotMatch @@ -665,6 +680,7 @@ and matches_cast_Cons = | Test(_) => DoesNotMatch | FloatLit(_) => DoesNotMatch | StringLit(_) => DoesNotMatch + | Label(_) => DoesNotMatch | Tuple(_) => DoesNotMatch | Dot(_, _) => IndetMatch | Prj(_) => IndetMatch diff --git a/src/haz3lcore/dynamics/Stepper.re b/src/haz3lcore/dynamics/Stepper.re index 54fb63f1bc..8bc368e0be 100644 --- a/src/haz3lcore/dynamics/Stepper.re +++ b/src/haz3lcore/dynamics/Stepper.re @@ -137,9 +137,9 @@ let rec matches = | Dot2(d1, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); Dot2(d1, ctx); - | TupLabel(s, ctx) => + | TupLabel(label, ctx) => let+ ctx = matches(env, flt, ctx, exp, act, idx); - TupLabel(s, ctx); + TupLabel(label, ctx); | Tuple(ctx, ds) => let+ ctx = matches(env, flt, ctx, exp, act, idx); Tuple(ctx, ds); diff --git a/src/haz3lcore/dynamics/Substitution.re b/src/haz3lcore/dynamics/Substitution.re index b1e58ef007..abbc85bd51 100644 --- a/src/haz3lcore/dynamics/Substitution.re +++ b/src/haz3lcore/dynamics/Substitution.re @@ -61,6 +61,7 @@ let rec subst_var = (d1: DHExp.t, x: Var.t, d2: DHExp.t): DHExp.t => | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | Constructor(_) => d2 | ListLit(a, b, c, ds) => ListLit(a, b, c, List.map(subst_var(d1, x), ds)) @@ -72,7 +73,7 @@ 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); ListConcat(d3, d4); - | TupLabel(p, d) => TupLabel(p, subst_var(d1, x, d)) + | TupLabel(label, d) => TupLabel(label, subst_var(d1, x, d)) | Tuple(ds) => Tuple(List.map(subst_var(d1, x), ds)) | Dot(d3, d4) => let d3 = subst_var(d1, x, d3); diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index f6b9a99592..fff334ab85 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -111,11 +111,12 @@ module CastHelpers = { | Int | Float | String + | Label(_) | Var(_) | Rec(_) | Forall(_, Unknown(_)) | Arrow(Unknown(_), Unknown(_)) - | Label(_, Unknown(_)) + | TupLabel(_, Unknown(_)) | List(Unknown(_)) => Ground | Prod(tys) => if (List.for_all( @@ -134,8 +135,8 @@ module CastHelpers = { | Arrow(_, _) => grounded_Arrow | Forall(_) => grounded_Forall | List(_) => grounded_List - | Label(_, _) => NotGroundOrHole(Unknown(Internal)) - // | Label(_, ty) => ground_cases_of(ty) + | TupLabel(_, _) => NotGroundOrHole(Unknown(Internal)) + // | TupLabel(_, ty) => ground_cases_of(ty) }; }; }; @@ -350,7 +351,7 @@ module Transition = (EV: EV_MODE) => { List.map( (p): DHPat.t => switch (p) { - | DHPat.Var(s) => TupLabel(s, p) + | DHPat.Var(name) => TupLabel(DHPat.Label(name), p) | _ => p }, args, @@ -407,6 +408,7 @@ module Transition = (EV: EV_MODE) => { | IntLit(_) | FloatLit(_) | StringLit(_) + | Label(_) | Constructor(_) | BuiltinFun(_) => let. _ = otherwise(env, d); @@ -586,12 +588,12 @@ module Transition = (EV: EV_MODE) => { | (Cast(d3', Prod(ts), Prod(ts')), BoundVar(name)) => let ty = switch (LabeledTuple.find_label(Typ.get_label, ts, name)) { - | Some(Label(_, ty)) => ty + | Some(TupLabel(_, ty)) => ty | _ => Typ.Unknown(Internal) }; let ty' = switch (LabeledTuple.find_label(Typ.get_label, ts', name)) { - | Some(Label(_, ty)) => ty + | Some(TupLabel(_, ty)) => ty | _ => Typ.Unknown(Internal) }; Step({ @@ -616,10 +618,10 @@ module Transition = (EV: EV_MODE) => { // kind: Dot(s), // value: false, // }); - | TupLabel(p, d1) => + | TupLabel(label, d1) => // TODO (Anthony): Fix this if needed - let. _ = otherwise(env, d1 => TupLabel(p, d1)) - and. _ = req_final(req(state, env), d1 => TupLabel(p, d1), d1); + let. _ = otherwise(env, d1 => TupLabel(label, d1)) + and. _ = req_final(req(state, env), d1 => TupLabel(label, d1), d1); Constructor; | Tuple(ds) => let. _ = otherwise(env, ds => Tuple(ds)) diff --git a/src/haz3lcore/dynamics/TypeAssignment.re b/src/haz3lcore/dynamics/TypeAssignment.re index dbcd2c37e7..077e8d2a4a 100644 --- a/src/haz3lcore/dynamics/TypeAssignment.re +++ b/src/haz3lcore/dynamics/TypeAssignment.re @@ -37,15 +37,17 @@ let dhpat_extend_ctx = let ty' = ty; let ty = switch (ty) { - | Label(_, ty) => ty + | TupLabel(_, ty) => ty | _ => ty }; switch (dhpat) { - | TupLabel(s1, dp1) => + | TupLabel(_, dp1) => switch (ty') { - | Label(s2, ty2) when LabeledTuple.compare(s1, s2) == 0 => + | TupLabel(_, ty2) + when + LabeledTuple.equal(DHPat.get_label(dhpat), Typ.get_label(ty')) => dhpat_var_entry(dp1, ty2) - | Label(_, _) => None + | TupLabel(_, _) => None | _ => dhpat_var_entry(dp1, ty) } | Var(name) => @@ -98,6 +100,7 @@ let dhpat_extend_ctx = | FloatLit(_) => Typ.eq(ty, Float) ? Some([]) : None | BoolLit(_) => Typ.eq(ty, Bool) ? Some([]) : None | StringLit(_) => Typ.eq(ty, String) ? Some([]) : None + | Label(name) => Typ.eq(ty, Label(name)) ? Some([]) : None | Constructor(_, typ) => Typ.eq(ty, typ) ? Some([]) : None }; }; @@ -207,6 +210,7 @@ let rec typ_of_dhexp = | IntLit(_) => Some(Int) | FloatLit(_) => Some(Float) | StringLit(_) => Some(String) + | Label(name) => Some(Label(name)) | BinBoolOp(_, d1, d2) => let* ty1 = typ_of_dhexp(ctx, m, d1); let* ty2 = typ_of_dhexp(ctx, m, d2); @@ -277,12 +281,10 @@ let rec typ_of_dhexp = | (List(ty1), List(ty2)) when Typ.eq(ty1, ty2) => Some(Typ.List(ty1)) | _ => None }; - | TupLabel(s, d) => - let ty = typ_of_dhexp(ctx, m, d); - switch (ty) { - | Some(ty) => Some(Typ.Label(s, ty)) - | None => None - }; + | TupLabel(dlab, d) => + let* tlab = typ_of_dhexp(ctx, m, dlab); + let* ty = typ_of_dhexp(ctx, m, d); + Some(Typ.TupLabel(tlab, ty)); | Dot(d1, d2) => switch (d1, d2) { | (Tuple(ds), BoundVar(name)) => @@ -291,9 +293,9 @@ let rec typ_of_dhexp = | Some(TupLabel(_, exp)) => typ_of_dhexp(ctx, m, exp) | _ => None }; - | (TupLabel(l, exp), BoundVar(name)) - when LabeledTuple.compare(name, l) == 0 => - typ_of_dhexp(ctx, m, exp) + | (TupLabel(_, de), BoundVar(name)) + when LabeledTuple.equal(DHExp.get_label(d1), Some((name, d2))) => + typ_of_dhexp(ctx, m, de) | _ => None } | Tuple(dhs) => diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index 1132caa96b..8372cc26db 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -287,9 +287,9 @@ let forms: list((string, t)) = [ ("cons_exp", mk_infix("::", Exp, P.cons)), ("cons_pat", mk_infix("::", Pat, P.cons)), ("typeann", mk(ss, [":"], mk_bin'(P.ann, Pat, Pat, [], Typ))), - ("tuple_labeled_exp", mk(ss, ["="], mk_bin'(P.lab, Exp, Pat, [], Exp))), - ("tuple_labeled_pat", mk(ss, ["="], mk_bin'(P.lab, Pat, Pat, [], Pat))), - ("tuple_labeled_typ", mk(ss, ["="], mk_bin'(P.lab, Typ, Pat, [], Typ))), + ("tuple_labeled_exp", mk_infix("=", Exp, P.lab)), + ("tuple_labeled_pat", mk_infix("=", Pat, P.lab)), + ("tuple_labeled_typ", mk_infix("=", Typ, P.lab)), ("dot_exp", mk_infix(".", Exp, P.dot)), ("dot_typ", mk_infix(".", Typ, P.dot)), // UNARY PREFIX OPERATORS diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index 25e7ba988c..7142980db4 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -236,15 +236,6 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { } | _ => ret(hole(tm)) } - | Bin(Pat(p), tiles, Exp(e)) as tm => - switch (tiles) { - | ([(_id, (["="], []))], []) => - switch (p.term) { - | Var(s) => ret(TupLabel(s, e)) - | _ => ret(hole(tm)) - } - | _ => ret(hole(tm)) - } | Bin(Exp(l), tiles, Exp(r)) as tm => switch (is_tuple_exp(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) @@ -281,6 +272,13 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { | ([";"], []) => Seq(l, r) | (["++"], []) => BinOp(String(Concat), l, r) | (["$=="], []) => BinOp(String(Equals), l, r) + | (["="], []) => + // TODO (Anthony): Other cases to convert to string + switch (l.term) { + | String(name) + | Var(name) => TupLabel({ids: l.ids, term: Label(name)}, r) + | _ => TupLabel(l, r) + } | (["."], []) => Dot(l, r) | (["|>"], []) => Pipeline(l, r) | (["@"], []) => ListConcat(l, r) @@ -354,9 +352,11 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { | None => switch (tiles) { | ([(_id, (["="], []))], []) => + // TODO (Anthony): Other cases to convert to string switch (l.term) { - | Var(s) => ret(TupLabel(s, r)) - | _ => ret(hole(tm)) + | String(name) + | Var(name) => ret(TupLabel({ids: l.ids, term: Label(name)}, r)) + | _ => ret(TupLabel(l, r)) } | ([(_id, (["::"], []))], []) => ret(Cons(l, r)) | _ => ret(hole(tm)) @@ -422,21 +422,18 @@ and typ_term: unsorted => (UTyp.term, list(Id.t)) = { ret(Sum(List.map(parse_sum_term, [t1] @ between_kids @ [t2]))) | None => ret(hole(tm)) } - | Bin(Pat(p), tiles, Typ(t)) as tm => - switch (tiles) { - | ([(_id, (["="], []))], []) => - switch (p.term) { - | Var(s) => ret(TupLabel(s, t)) - | _ => ret(hole(tm)) - } - | _ => ret(hole(tm)) - } | Bin(Typ(l), tiles, Typ(r)) as tm => switch (is_tuple_typ(tiles)) { | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) | None => switch (tiles) { | ([(_id, (["->"], []))], []) => ret(Arrow(l, r)) + | ([(_id, (["="], []))], []) => + // TODO (Anthony): Other cases to convert to string + switch (l.term) { + | Var(name) => ret(TupLabel({ids: l.ids, term: Label(name)}, r)) + | _ => ret(TupLabel(l, r)) + } | ([(_id, (["."], []))], []) => ret(Dot(l, r)) | _ => ret(hole(tm)) } diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 5e4fe6b88a..3bc9789d0f 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -234,6 +234,7 @@ and uexp_to_info_map = | Int(_) => atomic(Just(Int)) | Float(_) => atomic(Just(Float)) | String(_) => atomic(Just(String)) + | Label(name) => atomic(Just(Label(name))) | ListLit(es) => let ids = List.map(UExp.rep_id, es); let modes = Mode.of_list_lit(ctx, List.length(es), mode); @@ -294,15 +295,25 @@ and uexp_to_info_map = 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); - | TupLabel(s, e) when is_contained => + | TupLabel(label, e) when is_contained => let mode = Mode.of_label(ctx, mode); + let (lab, m) = go(~mode=Syn, label, m); let (e, m) = go(~mode, e, m); - add(~self=Just(Label(s, e.ty)), ~co_ctx=e.co_ctx, m); - | TupLabel(s, e) => + add( + ~self=Just(TupLabel(lab.ty, e.ty)), + ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), + m, + ); + | TupLabel(label, e) => let mode = Mode.of_label(ctx, mode); + let (lab, m) = go(~mode=Syn, label, m); let (e, m) = go(~mode, e, m); // treating standalone labeled expressions as within a tuple of size 1 - add(~self=Just(Prod([Label(s, e.ty)])), ~co_ctx=e.co_ctx, m); + add( + ~self=Just(Prod([TupLabel(lab.ty, e.ty)])), + ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), + m, + ); | Tuple(es) => let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); let (es, m) = map_m_go(m, modes, es); @@ -314,12 +325,10 @@ and uexp_to_info_map = | Dot(e1, e2) => let (info_e1, m) = go(~mode=Syn, e1, m); let (ty, m) = { - print_endline("e1 info"); - print_endline(Info.show_exp(info_e1)); switch (e2.term, info_e1.ty) { | (Var(name), Unknown(_)) | (Constructor(name), Unknown(_)) => - let ty = Typ.Prod([Label(name, Unknown(Internal))]); + let ty = Typ.Prod([TupLabel(Var(name), Unknown(Internal))]); let (_, m) = go(~mode=Mode.Ana(ty), e1, m); (ty, m); | (_, Var(_)) => (Typ.weak_head_normalize(ctx, info_e1.ty), m) @@ -332,22 +341,22 @@ and uexp_to_info_map = | Var(name) => let element: option(Typ.t) = LabeledTuple.find_label(Typ.get_label, ts, name); - let m = - e2.ids - |> List.fold_left( - (m, id) => - Id.Map.update( - id, - fun - | Some(Info.InfoExp(exp)) => - Some(Info.InfoExp({...exp, ctx})) - | _ as info => info, - m, - ), - m, - ); + // let m = + // e2.ids + // |> List.fold_left( + // (m, id) => + // Id.Map.update( + // id, + // fun + // | Some(Info.InfoExp(exp)) => + // Some(Info.InfoExp({...exp, ctx})) + // | _ as info => info, + // m, + // ), + // m, + // ); switch (element) { - | Some(Label(_, typ)) + | Some(TupLabel(_, typ)) | Some(typ) => let (body, m) = go'( @@ -428,7 +437,7 @@ and uexp_to_info_map = go_pat(~is_synswitch=false, ~co_ctx=e.co_ctx, ~mode=mode_pat, p, m); let rec get_var = (p1: UPat.t, p2) => switch (p1.term) { - | UPat.Var(s) => Typ.Label(s, p2) + | UPat.Var(s) => Typ.TupLabel(Label(s), p2) | TypeAnn(s, _) => get_var(s, p2) | _ => p2 }; @@ -771,6 +780,7 @@ and upat_to_info_map = : Constraint.InjR(Constraint.Truth), ) | String(string) => atomic(Just(String), Constraint.String(string)) + | Label(name) => atomic(Just(Label(name)), Constraint.Truth) | ListLit(ps) => let ids = List.map(UPat.rep_id, ps); let modes = Mode.of_list_lit(ctx, List.length(ps), mode); @@ -812,14 +822,14 @@ and upat_to_info_map = ~constraint_=Constraint.Truth, m, ); - | TupLabel(s, p) => + | TupLabel(label, p) => let mode = Mode.of_label(ctx, mode); + let (lab, m) = go(~ctx, ~mode=Syn, label, m); let (p, m) = go(~ctx, ~mode, p, m); - //TODO: Add label to contraint add( - ~self=Just(Label(s, p.ty)), + ~self=Just(TupLabel(lab.ty, p.ty)), ~ctx=p.ctx, - ~constraint_=Constraint.TupLabel(s, p.constraint_), + ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), m, ); | Tuple(ps) => @@ -889,17 +899,21 @@ and utyp_to_info_map = | Float | Bool | String => add(m) + | Label(_) => add(m) | Var(_) | Constructor(_) => /* Names are resolved in Info.status_typ */ add(m) | List(t) - | TupLabel(_, t) | Parens(t) => add(go(t, m) |> snd) | Arrow(t1, t2) => let m = go(t1, m) |> snd; let m = go(t2, m) |> snd; add(m); + | TupLabel(label, t) => + let m = go(label, m) |> snd; + let m = go(t, m) |> snd; + add(m); | Tuple(ts) => let m = map_m(go, ts, m) |> snd; add(m); diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index 91cfd68b2f..6798e5c8a6 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -72,6 +72,7 @@ module UTyp = { | Bool | String | Arrow + | Label | TupLabel | Tuple | Dot @@ -110,6 +111,7 @@ module UTyp = { | Arrow(_) => Arrow | Var(_) => Var | Constructor(_) => Constructor + | Label(_) => Label | TupLabel(_) => TupLabel | Tuple(_) => Tuple | Dot(_) => Dot @@ -132,6 +134,7 @@ module UTyp = { | Constructor => "Sum constructor" | List => "List type" | Arrow => "Function type" + | Label => "Label type" | TupLabel => "Labeled Tuple Item type" | Tuple => "Product type" | Dot => "Dot type" @@ -144,7 +147,11 @@ module UTyp = { let get_label: t => option((LabeledTuple.t, t)) = ty => switch (ty.term) { - | TupLabel(s, ty') => Some((s, ty')) + | TupLabel(tlab, ty') => + switch (tlab.term) { + | Label(name) => Some((name, ty')) + | _ => None + } | _ => None }; @@ -160,6 +167,7 @@ module UTyp = { | Float | Bool | String + | Label(_) | List(_) | Tuple(_) | Dot(_) @@ -184,6 +192,7 @@ module UTyp = { | Float | Bool | String + | Label(_) | Arrow(_) | List(_) | Tuple(_) @@ -207,13 +216,14 @@ module UTyp = { | Int => Int | Float => Float | String => String + | Label(name) => Label(name) | 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)) - | TupLabel(s, ut) => Label(s, to_typ(ctx, ut)) + | TupLabel(ut1, ut2) => TupLabel(to_typ(ctx, ut1), to_typ(ctx, ut2)) | Tuple(us) => Prod(List.map(to_typ(ctx), us)) | Dot(typ1, typ2) => // TODO: Fix this @@ -296,6 +306,7 @@ module UPat = { | Constructor | Cons | Var + | Label | TupLabel | Tuple | Parens @@ -330,6 +341,7 @@ module UPat = { | Constructor(_) => Constructor | Cons(_) => Cons | Var(_) => Var + | Label(_) => Label | TupLabel(_) => TupLabel | Tuple(_) => Tuple | Parens(_) => Parens @@ -351,6 +363,7 @@ module UPat = { | Constructor => "Constructor" | Cons => "Cons" | Var => "Variable binding" + | Label => "Label" | TupLabel => "Labeled Tuple Item pattern" | Tuple => "Tuple" | Parens => "Parenthesized pattern" @@ -371,6 +384,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -394,6 +408,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -419,6 +434,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -445,6 +461,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -468,6 +485,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -495,6 +513,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -523,6 +542,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -555,6 +575,7 @@ module UPat = { | Float(_) | Bool(_) | String(_) + | Label(_) | Triv | ListLit(_) | Cons(_, _) @@ -573,7 +594,11 @@ module UPat = { let get_label: t => option((LabeledTuple.t, t)) = p => switch (p.term) { - | TupLabel(s, p') => Some((s, p')) + | TupLabel(plab, p') => + switch (plab.term) { + | Label(name) => Some((name, p')) + | _ => None + } | _ => None }; }; @@ -596,6 +621,7 @@ module UExp = { | ListLit | Constructor | Fun + | Label | TupLabel | TypFun | Tuple @@ -645,6 +671,7 @@ module UExp = { | ListLit(_) => ListLit | Constructor(_) => Constructor | Fun(_) => Fun + | Label(_) => Label | TupLabel(_, _) => TupLabel | TypFun(_) => TypFun | Tuple(_) => Tuple @@ -745,6 +772,7 @@ module UExp = { | ListLit => "List literal" | Constructor => "Constructor" | Fun => "Function literal" + | Label => "Label" | TupLabel => "Labeled Tuple Item literal" | TypFun => "Type Function Literal" | Tuple => "Tuple literal" @@ -771,7 +799,11 @@ module UExp = { let get_label: t => option((LabeledTuple.t, t)) = e => switch (e.term) { - | TupLabel(s, e') => Some((s, e')) + | TupLabel(elab, e') => + switch (elab.term) { + | Label(name) => Some((name, e')) + | _ => None + } | _ => None }; @@ -808,6 +840,7 @@ module UExp = { | Int(_) | Float(_) | String(_) + | Label(_) | ListLit(_) | Tuple(_) | Var(_) @@ -863,6 +896,7 @@ module UExp = { | Int(_) | Float(_) | String(_) + | Label(_) | ListLit(_) | Fun(_) | TypFun(_) @@ -918,6 +952,7 @@ module UExp = { | Int(_) | Float(_) | String(_) + | Label(_) | ListLit(_) | Fun(_) | TypFun(_) diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index 65d2014626..2efbd2ca97 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -116,6 +116,7 @@ and UExp: { | ListLit | Constructor | Fun + | Label | TupLabel | TypFun | Tuple @@ -156,7 +157,8 @@ and UExp: { | ListLit(list(t)) | Constructor(string) | Fun(UPat.t, t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | TypFun(UTPat.t, t) | Tuple(list(t)) | Dot(t, t) @@ -265,6 +267,7 @@ and UExp: { | ListLit | Constructor | Fun + | Label | TupLabel | TypFun | Tuple @@ -305,7 +308,8 @@ and UExp: { | ListLit(list(t)) | Constructor(string) | Fun(UPat.t, t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | TypFun(UTPat.t, t) | Tuple(list(t)) | Dot(t, t) @@ -394,7 +398,8 @@ and UPat: { | Constructor(string) | Cons(t, t) | Var(Var.t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | Tuple(list(t)) | Parens(t) | Ap(t, t) @@ -419,7 +424,8 @@ and UPat: { | Constructor(string) | Cons(t, t) | Var(Var.t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | Tuple(list(t)) | Parens(t) | Ap(t, t) @@ -443,7 +449,8 @@ and UTyp: { | Var(string) | Constructor(string) | Arrow(t, t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | Tuple(list(t)) | Dot(t, t) | Parens(t) @@ -472,7 +479,8 @@ and UTyp: { | Var(string) | Constructor(string) | Arrow(t, t) - | TupLabel(LabeledTuple.t, t) + | Label(string) + | TupLabel(t, t) | Tuple(list(t)) | Dot(t, t) | Parens(t) diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 3247f4cbe7..7855407a07 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -32,7 +32,8 @@ module rec Typ: { | Sum(sum_map) | Prod(list(t)) | Rec(TypVar.t, t) - | Label(string, t) + | Label(string) + | TupLabel(t, t) | Forall(TypVar.t, t) and sum_map = ConstructorMap.t(option(t)); @@ -98,7 +99,8 @@ module rec Typ: { | Sum(sum_map) | Prod(list(t)) | Rec(TypVar.t, t) - | Label(string, t) + | Label(string) + | TupLabel(t, t) | Forall(TypVar.t, t) and sum_map = ConstructorMap.t(option(t)); @@ -140,7 +142,8 @@ module rec Typ: { | Unknown(_) | Var(_) | Rec(_) - | Label(_, _) + | Label(_) + | TupLabel(_, _) | Forall(_) | Sum(_) => precedence_Sum | List(_) => precedence_Const @@ -154,6 +157,7 @@ module rec Typ: { | Int | Float | Bool + | Label(_) | String => [] | Var(v) => List.mem(v, bound) ? [] : [v] | List(ty) => free_vars(~bound, ty) @@ -167,7 +171,7 @@ module rec Typ: { ) | Prod(tys) => ListUtil.flat_map(free_vars(~bound), tys) | Rec(x, ty) => free_vars(~bound=[x, ...bound], ty) - | Label(_, ty) => free_vars(~bound, ty) + | TupLabel(_, ty) => free_vars(~bound, ty) | Forall(x, ty) => free_vars(~bound=[x, ...bound], ty) }; @@ -184,6 +188,7 @@ module rec Typ: { | Float => Float | Bool => Bool | String => String + | Label(name) => Label(name) | 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)) @@ -200,7 +205,7 @@ module rec Typ: { | Forall(y, ty) => Forall(y, subst(s, x, ty)) | List(ty) => List(subst(s, x, ty)) | Var(y) => TypVar.eq(x, y) ? s : Var(y) - | Label(st, ty) => Label(st, subst(s, x, ty)) + | TupLabel(tlab, ty) => TupLabel(tlab, subst(s, x, ty)) }; }; @@ -211,17 +216,18 @@ module rec Typ: { }; let get_label: t => option((LabeledTuple.t, t)) = fun - | Label(s, t') => Some((s, t')) + | TupLabel(Label(name), t') => Some((name, t')) | _ => None; /* Type Equality: This coincides with alpha equivalence for normalized types. Other types may be equivalent but this will not detect so if they are not normalized. */ let rec eq_internal = (n: int, t1: t, t2: t) => { switch (t1, t2) { - | (Label(s1, t1), Label(s2, t2)) => - compare(s1, s2) == 0 && eq_internal(n, t1, t2) - | (Label(_, t1), t2) => eq_internal(n, t1, t2) - | (t1, Label(_, t2)) => eq_internal(n, t1, t2) + | (TupLabel(_, t1'), TupLabel(_, t2')) => + LabeledTuple.equal(get_label(t1), get_label(t2)) + && eq_internal(n, t1', t2') + | (TupLabel(_, t1), t2) => eq_internal(n, t1, t2) + | (t1, TupLabel(_, t2)) => eq_internal(n, t1, t2) | (Rec(x1, t1), Rec(x2, t2)) | (Forall(x1, t1), Forall(x2, t2)) => eq_internal( @@ -239,6 +245,8 @@ module rec Typ: { | (Bool, _) => false | (String, String) => true | (String, _) => false + | (Label(name1), Label(name2)) => String.equal(name1, name2) + | (Label(_), _) => false | (Unknown(_), Unknown(_)) => true | (Unknown(_), _) => false | (Arrow(t1, t2), Arrow(t1', t2')) => @@ -321,15 +329,15 @@ module rec Typ: { !resolve && eq(ty_name, ty_join) ? Var(name) : ty_join; /* Note: Ordering of Unknown, Var, and Rec above is load-bearing! */ /* Labels have special rules. TODO (Anthony): Fix them */ - | (Label(s1, ty1), Label(s2, ty2)) => - if (compare(s1, s2) == 0) { - let+ ty = join'(ty1, ty2); - Label(s2, ty); + | (TupLabel(_, ty1'), TupLabel(lab2, ty2')) => + if (LabeledTuple.equal(get_label(ty1), get_label(ty2))) { + let+ ty = join'(ty1', ty2'); + TupLabel(lab2, ty); } else { None; } - | (Label(_, ty1), ty) => join'(ty1, ty) - | (ty, Label(_, ty2)) => join'(ty, ty2) + | (TupLabel(_, ty1), ty) => join'(ty1, ty) + | (ty, TupLabel(_, ty2)) => join'(ty, ty2) | (Rec(x1, ty1), Rec(x2, ty2)) => let ctx = Ctx.extend_dummy_tvar(ctx, x1); let+ ty_body = @@ -356,6 +364,9 @@ module rec Typ: { | (Bool, _) => None | (String, String) => Some(String) | (String, _) => None + | (Label(name1), Label(name2)) when String.equal(name1, name2) => + Some(Label(name1)) + | (Label(_), _) => None | (Arrow(ty1, ty2), Arrow(ty1', ty2')) => let* ty1 = join'(ty1, ty1'); let+ ty2 = join'(ty2, ty2'); @@ -372,7 +383,7 @@ module rec Typ: { } else { let tys2 = LabeledTuple.rearrange(get_label, get_label, tys1, tys2, (t, b) => - Label(t, b) + TupLabel(Label(t), b) ); let* tys = ListUtil.map2_opt(join', tys1, tys2); let+ tys = OptUtil.sequence(tys); @@ -450,7 +461,8 @@ module rec Typ: { | Int | Float | Bool - | String => ty + | String + | Label(_) => 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)) @@ -460,7 +472,7 @@ module rec Typ: { 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)) - | Label(s, t) => Label(s, normalize(ctx, t)) + | TupLabel(label, t) => TupLabel(label, normalize(ctx, t)) | Forall(name, ty) => Forall(name, normalize(Ctx.extend_dummy_tvar(ctx, name), ty)) }; @@ -482,9 +494,9 @@ module rec Typ: { let matched_label = (ctx, ty) => switch (weak_head_normalize(ctx, ty)) { - | Label(_, ty) => ty + | TupLabel(_, ty) => ty | Unknown(SynSwitch) => Unknown(SynSwitch) - | _ => Unknown(Internal) + | _ => ty }; let matched_prod = (ctx, ts, get_label_ts, ty) => { @@ -498,8 +510,8 @@ module rec Typ: { if (!l1_valid || !l2_valid || List.length(ts) != List.length(tys)) { List.init(List.length(ts), _ => Unknown(Internal)); } else { - LabeledTuple.rearrange(get_label_ts, get_label, ts, tys, (t, b) => - Label(t, b) + LabeledTuple.rearrange(get_label_ts, get_label, ts, tys, (name, b) => + TupLabel(Label(name), b) ); }; | Unknown(SynSwitch) => @@ -577,6 +589,7 @@ module rec Typ: { | String | Bool | Label(_) + | TupLabel(_) | Var(_) => false | Rec(_, _) | Forall(_, _) => true @@ -594,6 +607,7 @@ module rec Typ: { | Float => "Float" | Bool => "Bool" | String => "String" + | Label(name) => name | Var(tvar) => tvar | List(t) => "[" ++ pretty_print(t) ++ "]" | Arrow(t1, t2) => paren_pretty_print(t1) ++ "->" ++ pretty_print(t2) @@ -608,7 +622,8 @@ module rec Typ: { ts, ) } - | Label(s, t) => s ++ "=" ++ pretty_print(t) + | TupLabel(Label(name), t) => name ++ "=" ++ pretty_print(t) + | TupLabel(_, t) => "[Unk]=" ++ pretty_print(t) | Prod([]) => "()" | Prod([t0, ...ts]) => "(" diff --git a/src/haz3lcore/zipper/EditorUtil.re b/src/haz3lcore/zipper/EditorUtil.re index 5fb7635a3d..3331a71b19 100644 --- a/src/haz3lcore/zipper/EditorUtil.re +++ b/src/haz3lcore/zipper/EditorUtil.re @@ -56,6 +56,7 @@ let rec append_exp = (e1: TermBase.UExp.t, e2: TermBase.UExp.t) => { | ListLit(_) | Constructor(_) | Fun(_) + | Label(_) | TupLabel(_) | TypFun(_) | Tuple(_) diff --git a/src/haz3lschool/SyntaxTest.re b/src/haz3lschool/SyntaxTest.re index 07f7cec09c..e6dbcc16fd 100644 --- a/src/haz3lschool/SyntaxTest.re +++ b/src/haz3lschool/SyntaxTest.re @@ -26,6 +26,7 @@ let rec find_var_upat = (name: string, upat: Term.UPat.t): bool => { | Float(_) | Bool(_) | String(_) + | Label(_) | Constructor(_) => false | Cons(up1, up2) => find_var_upat(name, up1) || find_var_upat(name, up2) | TupLabel(_, up) => find_var_upat(name, up) @@ -78,6 +79,7 @@ let rec find_in_let = EmptyHole | Wild | Triv | Invalid(_) | MultiHole(_) | Int(_) | Float(_) | Bool(_) | String(_) | + Label(_) | ListLit(_) | Constructor(_) | Cons(_, _) | @@ -136,6 +138,7 @@ let rec find_fn = | Int(_) | Float(_) | String(_) + | Label(_) | Constructor(_) | Undefined | Var(_) => l @@ -157,6 +160,7 @@ let rec var_mention_upat = (name: string, upat: Term.UPat.t): bool => { | Float(_) | Bool(_) | String(_) + | Label(_) | Constructor(_) => false | Cons(up1, up2) => var_mention_upat(name, up1) || var_mention_upat(name, up2) @@ -189,6 +193,7 @@ let rec var_mention = (name: string, uexp: Term.UExp.t): bool => { | Int(_) | Float(_) | String(_) + | Label(_) | Constructor(_) | Undefined | Deferral(_) => false @@ -247,6 +252,7 @@ let rec var_applied = (name: string, uexp: Term.UExp.t): bool => { | Int(_) | Float(_) | String(_) + | Label(_) | Constructor(_) | Undefined | Deferral(_) => false @@ -337,6 +343,7 @@ let rec tail_check = (name: string, uexp: Term.UExp.t): bool => { | Int(_) | Float(_) | String(_) + | Label(_) | Constructor(_) | Undefined | Var(_) => true diff --git a/src/haz3lweb/explainthis/ExplainThisForm.re b/src/haz3lweb/explainthis/ExplainThisForm.re index 9aadba8015..d196c5cad7 100644 --- a/src/haz3lweb/explainthis/ExplainThisForm.re +++ b/src/haz3lweb/explainthis/ExplainThisForm.re @@ -144,6 +144,7 @@ type pat_sub_form_id = | Float | Bool | String + | Label | Triv | ListNil | ListLit diff --git a/src/haz3lweb/explainthis/data/FunctionExp.re b/src/haz3lweb/explainthis/data/FunctionExp.re index 70e6ce0953..ea6f454ebe 100644 --- a/src/haz3lweb/explainthis/data/FunctionExp.re +++ b/src/haz3lweb/explainthis/data/FunctionExp.re @@ -77,7 +77,7 @@ let tuple3_fun_ex = { term: mk_example("fun (a, b, c) ->\na && b && c"), message: "When given a 3-tuple of booleans, the function evaluates to the logical-and of the three booleans.", }; -let label_fun_ex = { +let tuplabel_fun_ex = { sub_id: Fun(TupLabel), term: mk_example("fun x=y, y=z ->\ny"), message: "When given a 2-tuple of elements, the function evaluates to the first element (not the second).", @@ -224,6 +224,22 @@ let function_strlit_exp: form = { examples: [strlit_fun_ex], }; }; +let _pat = pat("Label"); +let _exp = exp("e"); +let function_label_coloring_ids = + _pat_body_function_exp_coloring_ids(Piece.id(_pat), Piece.id(_exp)); +let function_label: form = { + let explanation = "[TODO: Label docs] %s"; + + let form = [mk_fun([[space(), _pat, space()]]), space(), _exp]; + { + id: FunctionExp(Label), + syntactic_form: form, + expandable_id: Some((Piece.id(_pat), [pat("Label")])), + explanation, + examples: [], + }; +}; let _pat = pat("()"); let _exp = exp("e"); let function_triv_exp_coloring_ids = @@ -337,7 +353,7 @@ let function_labeled_exp: form = { expandable_id: Some((Piece.id(_labeled_pat), [pat("x"), labeled_pat(), pat("y")])), explanation, - examples: [label_fun_ex], + examples: [tuplabel_fun_ex], }; }; let _comma = comma_pat(); @@ -505,6 +521,11 @@ let functions_str = { forms: [function_strlit_exp, function_exp], }; +let functions_label = { + id: FunctionExp(Label), + forms: [function_label, function_exp], +}; + let functions_triv = { id: FunctionExp(Triv), forms: [function_triv_exp, function_exp], diff --git a/src/haz3lweb/explainthis/data/Label.re b/src/haz3lweb/explainthis/data/Label.re deleted file mode 100644 index 4625c904f9..0000000000 --- a/src/haz3lweb/explainthis/data/Label.re +++ /dev/null @@ -1,16 +0,0 @@ -// open ExplainThisForm; - // open Example; - // let label_exp = (n: string): form => { - // let explanation = "`%s` is a label (or name) for an item within a tuple."; - // { - // id: LabelExp, - // syntactic_form: [n], - // expandable_id: None, - // explanation, - // examples: [], - // }; - // }; - // let label_exps = (n: string): group => { - // id: LabelExp, - // forms: [label_exps(n)], - // }; diff --git a/src/haz3lweb/explainthis/data/LabelTerm.re b/src/haz3lweb/explainthis/data/LabelTerm.re new file mode 100644 index 0000000000..bab179c553 --- /dev/null +++ b/src/haz3lweb/explainthis/data/LabelTerm.re @@ -0,0 +1,14 @@ +open ExplainThisForm; +open Example; + +let label = (n: string): form => { + let explanation = "`%s` is a label (or name) for an item within a tuple."; + { + id: Label, + syntactic_form: [n |> abbreviate |> tpat], // TODO: Fix this + expandable_id: None, + explanation, + examples: [], + }; +}; +let labels = (n: string): group => {id: Label, forms: [label(n)]}; diff --git a/src/haz3lweb/explainthis/data/LabeledExp.re b/src/haz3lweb/explainthis/data/LabeledExp.re index c3bb7a3966..707e553f0f 100644 --- a/src/haz3lweb/explainthis/data/LabeledExp.re +++ b/src/haz3lweb/explainthis/data/LabeledExp.re @@ -5,7 +5,7 @@ open Example; let labeled_example_1 = { sub_id: Label1, term: mk_example("(x=1)"), - message: "A labeled expression within a singleton tuple, where the element 1 is assigned the label 'x'. ", + message: "A labeled expression within a singleton tuple, where the element 1 is assigned the label 'x'.", }; let labeled_example_2 = { sub_id: Label2, @@ -13,7 +13,7 @@ let labeled_example_2 = { message: "A tuple with first element 1, second element 2, and third element 3 with the label 'y'.", }; let labeled_exp: form = { - let explanation = "Labeled Expession explanation"; + let explanation = "Assigns a label (name) to an expression within a tuple. Labeled expressions cannot exist outside of a tuple; by default, labeled expressions that are not contained within a tuple are implied to be in a singleton tuple."; { id: LabeledExp, syntactic_form: [exp("x"), labeled_exp(), exp("e")], @@ -29,4 +29,4 @@ let labeled_exp: form = { // [(Piece.id(_exp1), exp1_id), (Piece.id(_exp2), exp2_id)]; // } -let labeled_exp: group = {id: LabeledExp, forms: [labeled_exp]}; +let labeled_exps: group = {id: LabeledExp, forms: [labeled_exp]}; diff --git a/src/haz3lweb/explainthis/data/LabeledPat.re b/src/haz3lweb/explainthis/data/LabeledPat.re index 1653d7aba4..de8150f26d 100644 --- a/src/haz3lweb/explainthis/data/LabeledPat.re +++ b/src/haz3lweb/explainthis/data/LabeledPat.re @@ -9,7 +9,7 @@ open ExplainThisForm; // (Piece.id(_typ), typ_id), // ]; let labeled_pat: form = { - let explanation = "labeled pattern explanation"; + let explanation = "Assigns a label (name) to a pattern within a tuple. Labeled patterns cannot exist outside of a tuple; by default, labeled pattens that are not contained within a tuple are implied to be in a singleton tuple."; { id: LabeledPat, syntactic_form: [pat("x"), labeled_pat(), pat("p")], @@ -19,4 +19,4 @@ let labeled_pat: form = { }; }; -let labeled_pat: group = {id: LabeledPat, forms: [labeled_pat]}; +let labeled_pats: group = {id: LabeledPat, forms: [labeled_pat]}; diff --git a/src/haz3lweb/explainthis/data/LabeledTyp.re b/src/haz3lweb/explainthis/data/LabeledTyp.re index 9227c30f51..7bfaac386d 100644 --- a/src/haz3lweb/explainthis/data/LabeledTyp.re +++ b/src/haz3lweb/explainthis/data/LabeledTyp.re @@ -3,7 +3,7 @@ open ExplainThisForm; // open Haz3lcore; let labeled_typ: form = { - let explanation = "label type explanation"; + let explanation = "Assigns a label (name) to a type within a tuple. Labeled types cannot exist outside of a tuple; by default, labeled pattens that are not contained within a tuple are implied to be in a singleton tuple."; { id: LabeledTyp, syntactic_form: [pat("x"), labeled_typ(), typ("t")], @@ -13,4 +13,4 @@ let labeled_typ: form = { }; }; -let labeled_typ: group = {id: LabeledTyp, forms: [labeled_typ]}; +let labeled_typs: group = {id: LabeledTyp, forms: [labeled_typ]}; diff --git a/src/haz3lweb/explainthis/data/LetExp.re b/src/haz3lweb/explainthis/data/LetExp.re index 94ea0412e6..e997765ab7 100644 --- a/src/haz3lweb/explainthis/data/LetExp.re +++ b/src/haz3lweb/explainthis/data/LetExp.re @@ -282,6 +282,30 @@ let let_str_exp: form = { examples: [let_str_ex], }; }; +let _pat = pat("Label"); +let _exp_def = exp("e_def"); +let _exp_body = exp("e_body"); +let let_label_coloring_ids = + _pat_def_body_let_exp_coloring_ids( + Piece.id(_pat), + Piece.id(_exp_def), + Piece.id(_exp_body), + ); +let let_label: form = { + let explanation = "[TODO: Label docs] %s"; + let form = [ + mk_let([[space(), _pat, space()], [space(), _exp_def, space()]]), + linebreak(), + _exp_body, + ]; + { + id: LetExp(Label), + syntactic_form: form, + expandable_id: Some((Piece.id(_pat), [pat("Label")])), + explanation, + examples: [], + }; +}; let _pat = pat("()"); let _exp_def = exp("e_def"); let _exp_body = exp("e_body"); @@ -615,6 +639,11 @@ let lets_str: group = { forms: [let_str_exp, let_base_exp], }; +let lets_label: group = { + id: LetExp(Label), + forms: [let_label, let_base_exp], +}; + let lets_triv: group = { id: LetExp(Triv), forms: [let_triv_exp, let_base_exp], @@ -637,7 +666,7 @@ let lets_cons: group = { let lets_var: group = {id: LetExp(Var), forms: [let_var_exp, let_base_exp]}; -let lets_label: group = { +let lets_tuplabel: group = { id: LetExp(TupLabel), forms: [let_labeled_exp, let_base_exp], }; diff --git a/src/haz3lweb/view/ExplainThis.re b/src/haz3lweb/view/ExplainThis.re index 28bd419b49..2304b14ff0 100644 --- a/src/haz3lweb/view/ExplainThis.re +++ b/src/haz3lweb/view/ExplainThis.re @@ -791,6 +791,25 @@ let get_doc = } else { basic(FunctionExp.functions_str); } + | Label(name) => + if (FunctionExp.function_label.id + == get_specificity_level(FunctionExp.functions_label)) { + get_message( + ~colorings= + FunctionExp.function_label_coloring_ids(~pat_id, ~body_id), + ~format= + Some( + msg => + Printf.sprintf( + Scanf.format_from_string(msg, "%s"), + name, + ), + ), + FunctionExp.functions_label, + ); + } else { + basic(FunctionExp.functions_label); + } | Triv => if (FunctionExp.function_triv_exp.id == get_specificity_level(FunctionExp.functions_triv)) { @@ -1086,7 +1105,16 @@ let get_doc = | Parens(_) => default // Shouldn't get hit? | TypeAnn(_) => default // Shouldn't get hit? }; - | TupLabel(_, _) => get_message(LabeledExp.labeled_exp) + | Label(name) => + get_message( + ~format= + Some( + msg => + Printf.sprintf(Scanf.format_from_string(msg, "%s"), name), + ), + LabelTerm.labels(name), + ) + | TupLabel(_, _) => get_message(LabeledExp.labeled_exps) | Dot(_, _) => get_message(DotExp.dot_exp) | Tuple(terms) => let basic = group_id => @@ -1341,6 +1369,27 @@ let get_doc = LetExp.lets_str, ); } + | Label(name) => + if (LetExp.let_label.id == get_specificity_level(LetExp.lets_label)) { + get_message( + ~colorings= + LetExp.let_label_coloring_ids(~pat_id, ~def_id, ~body_id), + ~format= + Some( + msg => + Printf.sprintf( + Scanf.format_from_string(msg, "%s"), + name, + ), + ), + LetExp.lets_label, + ); + } else { + /* TODO The coloring for the syntactic form is sometimes wrong here... */ + basic( + LetExp.lets_label, + ); + } | Triv => if (LetExp.let_triv_exp.id == get_specificity_level(LetExp.lets_triv)) { @@ -1457,9 +1506,9 @@ let get_doc = } else { basic(LetExp.lets_var); } - | TupLabel(s, p) => + | TupLabel(_, p) => if (LetExp.let_labeled_exp.id - == get_specificity_level(LetExp.lets_label)) { + == get_specificity_level(LetExp.lets_tuplabel)) { let p_id = List.nth(p.ids, 0); get_message( ~colorings= @@ -1475,15 +1524,15 @@ let get_doc = Scanf.format_from_string(msg, "%s%s%s%s%s"), Id.to_string(def_id), Id.to_string(pat_id), - s, + "[label placeholder]", Id.to_string(body_id), Id.to_string(p_id), ), ), - LetExp.lets_label, + LetExp.lets_tuplabel, ); } else { - basic(LetExp.lets_label); + basic(LetExp.lets_tuplabel); } | Tuple(elements) => let basic_tuple = group_id => { @@ -2065,7 +2114,15 @@ let get_doc = ), TerminalPat.var(v), ) - | TupLabel(_, _) => get_message(LabeledPat.labeled_pat) + | Label(name) => + get_message( + ~format= + Some( + msg => Printf.sprintf(Scanf.format_from_string(msg, "%s"), name), + ), + LabelTerm.labels(name), + ) + | TupLabel(_, _) => get_message(LabeledPat.labeled_pats) | Tuple(elements) => let basic = group => get_message( @@ -2277,7 +2334,15 @@ let get_doc = } | _ => basic(ArrowTyp.arrow) }; - | TupLabel(_, _) => get_message(LabeledTyp.labeled_typ) + | Label(name) => + get_message( + ~format= + Some( + msg => Printf.sprintf(Scanf.format_from_string(msg, "%s"), name), + ), + LabelTerm.labels(name), + ) + | TupLabel(_, _) => get_message(LabeledTyp.labeled_typs) | Dot(_, _) => get_message(DotTyp.dot_typ) | Tuple(elements) => let basic = group => diff --git a/src/haz3lweb/view/Type.re b/src/haz3lweb/view/Type.re index f28fe3340b..551503dbed 100644 --- a/src/haz3lweb/view/Type.re +++ b/src/haz3lweb/view/Type.re @@ -32,9 +32,10 @@ let rec view_ty = (~strip_outer_parens=false, ty: Haz3lcore.Typ.t): Node.t => | Int => ty_view("Int", "Int") | Float => ty_view("Float", "Float") | String => ty_view("String", "String") + | Label(name) => ty_view("Label", name) | Bool => ty_view("Bool", "Bool") | Var(name) => ty_view("Var", name) - | Label(_, ty) => view_ty(ty) // TODO (Anthony): What to do here? + | TupLabel(_, ty) => view_ty(ty) // TODO (Anthony): What to do here? | Rec(name, t) => div( ~attrs=[clss(["typ-view", "Rec"])], diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re index 374bd2afd1..d7e66941f4 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Exp.re @@ -54,6 +54,7 @@ let rec precedence = (~show_casts: bool, d: DHExp.t) => { | Test(_) | FloatLit(_) | StringLit(_) + | Label(_) | ListLit(_) | Prj(_) | EmptyHole(_) @@ -362,6 +363,7 @@ let mk = | IntLit(n) => DHDoc_common.mk_IntLit(n) | FloatLit(f) => DHDoc_common.mk_FloatLit(f) | StringLit(s) => DHDoc_common.mk_StringLit(s) + | Label(name) => DHDoc_common.mk_Label(name) | Undefined => DHDoc_common.mk_Undefined() | Test(_, d) => DHDoc_common.mk_Test(go'(d, Test)) | Sequence(d1, d2) => @@ -440,9 +442,9 @@ let mk = ); hseps([doc1, mk_bin_bool_op(op), doc2]); // TODO(Anthony): what to do here? - | TupLabel(s, d) => + | TupLabel(l, d) => Doc.hcats([ - Doc.text(s), + go'(l, TupLabel), DHDoc_common.Delim.mk("="), go'(d, TupLabel), ]) diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re b/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re index ce65f73d80..20053cc6e0 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_Pat.re @@ -13,6 +13,7 @@ let precedence = (dp: DHPat.t) => | FloatLit(_) | BoolLit(_) | StringLit(_) + | Label(_) | ListLit(_) | Constructor(_) => DHDoc_common.precedence_const | TupLabel(_, _) => DHDoc_common.precedence_Comma @@ -46,6 +47,7 @@ let rec mk = | FloatLit(f) => DHDoc_common.mk_FloatLit(f) | BoolLit(b) => DHDoc_common.mk_BoolLit(b) | StringLit(s) => DHDoc_common.mk_StringLit(s) + | Label(name) => DHDoc_common.mk_Label(name) | ListLit(_, d_list) => let ol = List.map(mk', d_list); DHDoc_common.mk_ListLit(ol); @@ -54,8 +56,8 @@ let rec mk = mk_right_associative_operands(DHDoc_common.precedence_Cons, dp1, dp2); DHDoc_common.mk_Cons(doc1, doc2); // TODO (Anthony): What to do for Tuplabel? - | TupLabel(s, d) => - Doc.hcats([Doc.text(s), DHDoc_common.Delim.mk("="), mk'(d)]) + | TupLabel(l, d) => + Doc.hcats([mk'(l), DHDoc_common.Delim.mk("="), mk'(d)]) | Tuple([]) => DHDoc_common.Delim.triv | Tuple(ds) => DHDoc_common.mk_Tuple(List.map(mk', ds)) | Ap(dp1, dp2) => diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re index c96aa3b7e0..3ac46848c8 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.re +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.re @@ -101,6 +101,8 @@ let mk_IntLit = n => Doc.text(string_of_int(n)); let mk_StringLit = s => Doc.text(Form.string_quote(s)); +let mk_Label = name => Doc.text(name); + let mk_Test = t => Doc.(hcats([text("Test"), t, text("End")])); let mk_FloatLit = (f: float) => diff --git a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei index 70792ab2a8..b4fad4a2c9 100644 --- a/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei +++ b/src/haz3lweb/view/dhcode/layout/DHDoc_common.rei @@ -81,6 +81,8 @@ let mk_ConstructorLit: string => Pretty.Doc.t('a); let mk_StringLit: string => Pretty.Doc.t('a); +let mk_Label: string => Pretty.Doc.t('a); + let mk_Cons: (Pretty.Doc.t('a), Pretty.Doc.t('a)) => Pretty.Doc.t('a); let mk_ListConcat: (Pretty.Doc.t('a), 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 ec7f054016..3a461c9ae2 100644 --- a/src/haz3lweb/view/dhcode/layout/HTypDoc.re +++ b/src/haz3lweb/view/dhcode/layout/HTypDoc.re @@ -50,8 +50,9 @@ let rec mk = (~parenthesize=false, ~enforce_inline: bool, ty: Typ.t): t => { | Float => (text("Float"), parenthesize) | Bool => (text("Bool"), parenthesize) | String => (text("String"), parenthesize) + | Label(name) => (text(name), parenthesize) | Var(name) => (text(name), parenthesize) - | Label(_, ty) => (mk'(ty), parenthesize) // TODO (Anthony): What to do here? + | TupLabel(_, ty) => (mk'(ty), parenthesize) // TODO (Anthony): What to do here? | List(ty) => ( hcats([ mk_delim("["), From c20706a8ecc6658f4a88980d737e83926e9910db Mon Sep 17 00:00:00 2001 From: WondAli Date: Sat, 24 Aug 2024 15:26:41 -0400 Subject: [PATCH 019/108] fixes to labeled expressions as singleton tuples --- src/haz3lcore/dynamics/Elaborator.re | 48 +++++++++++---- src/haz3lcore/dynamics/Transition.re | 18 ------ src/haz3lcore/statics/Statics.re | 87 +++++++++++++++++++--------- src/haz3lcore/statics/TypBase.re | 1 + 4 files changed, 96 insertions(+), 58 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index b08fa6415b..805fe6ca93 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -142,10 +142,15 @@ let wrap = (ctx: Ctx.t, u: Id.t, mode: Mode.t, self, d: DHExp.t): DHExp.t => }; let rec dhexp_of_uexp = - (m: Statics.Map.t, uexp: Term.UExp.t, in_filter: bool) + ( + m: Statics.Map.t, + uexp: Term.UExp.t, + in_filter: bool, + in_container: bool, + ) : option(DHExp.t) => { - let dhexp_of_uexp = (~in_filter=in_filter, m, uexp) => { - dhexp_of_uexp(m, uexp, in_filter); + let dhexp_of_uexp = (~in_filter=in_filter, ~in_container=false, m, uexp) => { + dhexp_of_uexp(m, uexp, in_filter, in_container); }; switch (Id.Map.find_opt(Term.UExp.rep_id(uexp), m)) { | Some(InfoExp({mode, self, ctx, ancestors, co_ctx, _})) => @@ -174,7 +179,7 @@ let rec dhexp_of_uexp = let ty = Typ.matched_list(ctx, ty); DHExp.ListLit(id, 0, ty, ds); | Fun(p, body) => - let* dp = dhpat_of_upat(m, p); + let* dp = dhpat_of_upat(m, p, false); let* d1 = dhexp_of_uexp(m, body); let+ ty = fixed_pat_typ(m, p); let ty = Typ.normalize(ctx, ty); @@ -185,9 +190,16 @@ let rec dhexp_of_uexp = | TupLabel(label, e) => let* dlab = dhexp_of_uexp(m, label); let+ de = dhexp_of_uexp(m, e); - DHExp.TupLabel(dlab, de); + if (in_container) { + DHExp.TupLabel(dlab, de); + } else { + DHExp.Tuple([DHExp.TupLabel(dlab, de)]); + }; | Tuple(es) => - let+ ds = es |> List.map(dhexp_of_uexp(m)) |> OptUtil.sequence; + let+ ds = + es + |> List.map(dhexp_of_uexp(m, ~in_container=true)) + |> OptUtil.sequence; DHExp.Tuple(ds); | Dot(e1, e2) => let* e1 = dhexp_of_uexp(m, e1); @@ -271,7 +283,7 @@ let rec dhexp_of_uexp = | TypFun(tpat, e, _) => DHExp.TypFun(tpat, e, name) | d => d ); - let* dp = dhpat_of_upat(m, p); + let* dp = dhpat_of_upat(m, p, false); let* ddef = dhexp_of_uexp(m, def); let* dbody = dhexp_of_uexp(m, body); let+ ty = fixed_pat_typ(m, p); @@ -401,7 +413,7 @@ let rec dhexp_of_uexp = let+ d_rules = List.map( ((p, e)) => { - let* d_p = dhpat_of_upat(m, p); + let* d_p = dhpat_of_upat(m, p, false); let+ d_e = dhexp_of_uexp(m, e); DHExp.Rule(d_p, d_e); }, @@ -425,7 +437,12 @@ let rec dhexp_of_uexp = | None => None }; } -and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.t) => { +and dhpat_of_upat = + (m: Statics.Map.t, upat: Term.UPat.t, in_container: bool) + : option(DHPat.t) => { + let dhpat_of_upat = (~in_container=false, m, upat) => { + dhpat_of_upat(m, upat, in_container); + }; 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 @@ -489,9 +506,16 @@ and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.t) => { | TupLabel(lab, p) => let* dlab = dhpat_of_upat(m, lab); let* dp = dhpat_of_upat(m, p); - wrap(TupLabel(dlab, dp)); + if (in_container) { + wrap(TupLabel(dlab, dp)); + } else { + wrap(Tuple([TupLabel(dlab, dp)])); + }; | Tuple(ps) => - let* ds = ps |> List.map(dhpat_of_upat(m)) |> OptUtil.sequence; + let* ds = + ps + |> List.map(dhpat_of_upat(m, ~in_container=true)) + |> OptUtil.sequence; wrap(Tuple(ds)); | Var(name) => Some(Var(name)) | Parens(p) => dhpat_of_upat(m, p) @@ -511,7 +535,7 @@ and dhpat_of_upat = (m: Statics.Map.t, upat: Term.UPat.t): option(DHPat.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, false)) { + switch (dhexp_of_uexp(m, uexp, false, false)) { | None => DoesNotElaborate | Some(d) => //let d = uexp_elab_wrap_builtins(d); diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index fff334ab85..c531348565 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -217,7 +217,6 @@ module Transition = (EV: EV_MODE) => { }; let transition = (req, state, env, d): 'a => { - // print_endline(DHExp.show(d)); switch (d) { | BoundVar(x) => let. _ = otherwise(env, BoundVar(x)); @@ -603,21 +602,6 @@ module Transition = (EV: EV_MODE) => { }); | _ => Indet }; - // Step({ - // apply: () => - // switch (d') { - // | Tuple(ds) => - // let element = LabeledTuple.find_label(DHExp.get_label, ds, s); - // switch (element) { - // | Some(TupLabel(_, exp)) => exp - // | _ => raise(EvaluatorError.Exception(BadPatternMatch)) - // }; - // | TupLabel(l, exp) when LabeledTuple.compare(s, l) == 0 => exp - // | _ => raise(EvaluatorError.Exception(BadPatternMatch)) - // }, - // kind: Dot(s), - // value: false, - // }); | TupLabel(label, d1) => // TODO (Anthony): Fix this if needed let. _ = otherwise(env, d1 => TupLabel(label, d1)) @@ -736,8 +720,6 @@ module Transition = (EV: EV_MODE) => { open CastHelpers; /* Cast calculus */ let. _ = otherwise(env, d => Cast(d, t1, t2)) and. d' = req_final(req(state, env), d => Cast(d, t1, t2), d); - // print_endline("cast final"); - // print_endline(DHExp.show(d')); switch (ground_cases_of(t1), ground_cases_of(t2)) { | (Hole, Hole) | (Ground, Ground) => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 3bc9789d0f..dc165e91f0 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -212,13 +212,13 @@ and uexp_to_info_map = }; let go' = uexp_to_info_map(~ancestors); let go = go'(~ctx); - let map_m_go = m => + let map_m_go = (m, ~is_contained=false) => List.fold_left2( ((es, m), mode, e) => - go(~mode, e, m, ~is_contained=true) |> (((e, m)) => (es @ [e], m)), + go(~mode, e, m, ~is_contained) |> (((e, m)) => (es @ [e], m)), ([], m), ); - let go_pat = upat_to_info_map(~ctx, ~ancestors); + let go_pat = upat_to_info_map(~ctx, ~ancestors, ~is_contained=false); let atomic = self => add(~self, ~co_ctx=CoCtx.empty, m); switch (term) { | MultiHole(tms) => @@ -295,28 +295,26 @@ and uexp_to_info_map = 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); - | TupLabel(label, e) when is_contained => - let mode = Mode.of_label(ctx, mode); - let (lab, m) = go(~mode=Syn, label, m); - let (e, m) = go(~mode, e, m); - add( - ~self=Just(TupLabel(lab.ty, e.ty)), - ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), - m, - ); | TupLabel(label, e) => let mode = Mode.of_label(ctx, mode); let (lab, m) = go(~mode=Syn, label, m); let (e, m) = go(~mode, e, m); - // treating standalone labeled expressions as within a tuple of size 1 - add( - ~self=Just(Prod([TupLabel(lab.ty, e.ty)])), - ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), - m, - ); + if (is_contained) { + add( + ~self=Just(TupLabel(lab.ty, e.ty)), + ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), + m, + ); + } else { + add( + ~self=Just(Prod([TupLabel(lab.ty, e.ty)])), + ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), + m, + ); + }; | Tuple(es) => let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); - let (es, m) = map_m_go(m, modes, es); + let (es, m) = map_m_go(m, modes, es, ~is_contained=true); add( ~self=Just(Prod(List.map(Info.exp_ty, es))), ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es)), @@ -727,6 +725,7 @@ and upat_to_info_map = ~co_ctx, ~ancestors: Info.ancestors, ~mode: Mode.t=Mode.Syn, + ~is_contained=false, {ids, term} as upat: UPat.t, m: Map.t, ) @@ -744,14 +743,36 @@ and upat_to_info_map = ); (info, add_info(ids, InfoPat(info), m)); }; + let upat_to_info_map = + ( + ~is_synswitch, + ~ctx, + ~co_ctx, + ~ancestors, + ~mode, + ~is_contained=false, + upat: UPat.t, + m: Map.t, + ) => { + upat_to_info_map( + ~is_synswitch, + ~ctx, + ~co_ctx, + ~ancestors, + ~mode, + ~is_contained, + upat, + m: Map.t, + ); + }; 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, ~co_ctx); let unknown = Typ.Unknown(is_synswitch ? SynSwitch : Internal); - let ctx_fold = (ctx: Ctx.t, m) => + let ctx_fold = (ctx: Ctx.t, m, ~is_contained=false) => List.fold_left2( ((ctx, tys, cons, m), e, mode) => - go(~ctx, ~mode, e, m) + go(~ctx, ~mode, ~is_contained, e, m) |> ( ((info, m)) => ( info.ctx, @@ -826,15 +847,25 @@ and upat_to_info_map = let mode = Mode.of_label(ctx, mode); let (lab, m) = go(~ctx, ~mode=Syn, label, m); let (p, m) = go(~ctx, ~mode, p, m); - add( - ~self=Just(TupLabel(lab.ty, p.ty)), - ~ctx=p.ctx, - ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), - m, - ); + if (is_contained) { + add( + ~self=Just(TupLabel(lab.ty, p.ty)), + ~ctx=p.ctx, + ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), + m, + ); + } else { + add( + ~self=Just(Prod([TupLabel(lab.ty, p.ty)])), + ~ctx=p.ctx, + ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), + m, + ); + }; | Tuple(ps) => let modes = Mode.of_prod(ctx, mode, ps, UPat.get_label); - let (ctx, tys, cons, m) = ctx_fold(ctx, m, ps, modes); + let (ctx, tys, cons, m) = + ctx_fold(ctx, m, ps, modes, ~is_contained=true); let rec cons_fold_tuple = cs => switch (cs) { | [] => Constraint.Truth diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 7855407a07..1b60b2b842 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -495,6 +495,7 @@ module rec Typ: { let matched_label = (ctx, ty) => switch (weak_head_normalize(ctx, ty)) { | TupLabel(_, ty) => ty + | Prod([ty]) => ty | Unknown(SynSwitch) => Unknown(SynSwitch) | _ => ty }; From fe24986f4ccb668f005cf3db1483a1498adef389 Mon Sep 17 00:00:00 2001 From: WondAli Date: Sat, 24 Aug 2024 17:22:47 -0400 Subject: [PATCH 020/108] minor test_elaboration update --- test/Test_Elaboration.re | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index d584492091..48f89a55b6 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -20,7 +20,8 @@ let dhexp_typ = testable(Fmt.using(dhexp_print, Fmt.string), dhexp_eq); let ids = List.init(12, _ => Id.mk()); let id_at = x => x |> List.nth(ids); let mk_map = CoreSettings.on |> Interface.Statics.mk_map; -let dhexp_of_uexp = u => Elaborator.dhexp_of_uexp(mk_map(u), u, false); +let dhexp_of_uexp = u => + Elaborator.dhexp_of_uexp(mk_map(u), u, false, false); let alco_check = dhexp_typ |> Alcotest.check; let u1: Term.UExp.t = {ids: [id_at(0)], term: Int(8)}; From 773fa9b08eca0f4be6b0cb31ee06c2e63c39d8d9 Mon Sep 17 00:00:00 2001 From: WondAli Date: Tue, 27 Aug 2024 16:51:08 -0400 Subject: [PATCH 021/108] singleton tuple fixes --- src/haz3lcore/dynamics/Transition.re | 19 ++++++++++++++++--- src/haz3lcore/statics/Statics.re | 17 ++++++++++++++--- src/haz3lcore/statics/TypBase.re | 4 ++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index c531348565..fba693b25b 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -343,10 +343,11 @@ module Transition = (EV: EV_MODE) => { | Constructor(_) => Constructor | Fun(dp, _, Closure(env', d3), _) => // Wrap the arguments into labels for label rearrangement + // And implicitly wrap args into singleton tuples if necessary let dp: DHPat.t = switch (dp) { | Tuple(args) => - Tuple( + let labeled_args = List.map( (p): DHPat.t => switch (p) { @@ -354,10 +355,22 @@ module Transition = (EV: EV_MODE) => { | _ => p }, args, - ), - ) + ); + Tuple(labeled_args); | _ => dp }; + // TODO: Probably not the right way to deal with casts + let d2' = + switch (d2', dp) { + | (Tuple(_), Tuple(_)) => d2' + | (Cast(Tuple(_), _, Prod(_)), Tuple(_)) => d2' + | (Cast(d, Prod(t1), Prod(t2)), Tuple(_)) => + Cast(Tuple([d]), Prod(t1), Prod(t2)) + | (Cast(d, t1, Prod(t2)), Tuple(_)) => + Cast(Tuple([d]), Prod([t1]), Prod(t2)) + | (_, Tuple([TupLabel(_)])) => Tuple([d2']) + | (_, _) => d2' + }; let.match env'' = (env', matches(dp, d2')); Step({apply: () => Closure(env'', d3), kind: FunAp, value: false}); | Cast(d3', Arrow(ty1, ty2), Arrow(ty1', ty2')) => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index dc165e91f0..117f1d778d 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -397,6 +397,14 @@ and uexp_to_info_map = 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(ctx, fn.ty); + // In case of singleton tuple for fun ty_in, implicitly convert arg if necessary + // TODO: Is needed for TypAp or Deferred Ap? + let arg = + switch (arg.term, ty_in) { + | (Tuple(_), Prod(_)) => arg + | (_, Prod([TupLabel(_)])) => {UExp.ids: arg.ids, term: Tuple([arg])} + | (_, _) => arg + }; let (arg, m) = go(~mode=Ana(ty_in), arg, m); let self: Self.t = Id.is_nullary_ap_flag(arg.term.ids) @@ -433,19 +441,22 @@ 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); + // convert variables into labeled expressions if needed let rec get_var = (p1: UPat.t, p2) => switch (p1.term) { | UPat.Var(s) => Typ.TupLabel(Label(s), p2) | TypeAnn(s, _) => get_var(s, p2) | _ => p2 }; - let pty: Typ.t = - switch (p.term, p''.ty) { + let rec get_typ = (p: UPat.t, t: Typ.t): Typ.t => + switch (p.term, t) { | (Tuple(l1), Prod(l2)) => let pt: list(Typ.t) = List.map2(get_var, l1, l2); Prod(pt); - | _ => p''.ty + | (TypeAnn(s, _), t) => get_typ(s, t) + | _ => t }; + let pty = get_typ(p, p''.ty); // TODO: factor out code let unwrapped_self: Self.exp = Common(Just(Arrow(pty, e.ty))); let is_exhaustive = p'' |> Info.pat_constraint |> Incon.is_exhaustive; diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 1b60b2b842..8d670f9833 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -480,6 +480,10 @@ module rec Typ: { let matched_arrow = (ctx, ty) => switch (weak_head_normalize(ctx, ty)) { + | Arrow(TupLabel(name, ty_in), ty_out) => ( + Prod([TupLabel(name, ty_in)]), + ty_out, + ) | Arrow(ty_in, ty_out) => (ty_in, ty_out) | Unknown(SynSwitch) => (Unknown(SynSwitch), Unknown(SynSwitch)) | _ => (Unknown(Internal), Unknown(Internal)) From e76f5e2083b3800bd463278dd184c852400ac798 Mon Sep 17 00:00:00 2001 From: WondAli Date: Tue, 27 Aug 2024 17:22:30 -0400 Subject: [PATCH 022/108] fix statics to check for mismatched labels --- src/haz3lcore/statics/Mode.re | 8 +++++--- src/haz3lcore/statics/Statics.re | 8 ++++---- src/haz3lcore/statics/TypBase.re | 10 +++++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index 26ed7d9499..23d23d74c8 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -56,12 +56,14 @@ let of_forall = (ctx: Ctx.t, name_opt: option(TypVar.t), mode: t): t => }; }; -let of_label = (ctx: Ctx.t, mode: t): t => +let of_label = (ctx: Ctx.t, mode: t): (t, t) => switch (mode) { | Syn | SynFun - | SynTypFun => Syn - | Ana(ty) => Typ.matched_label(ctx, ty) |> ana + | SynTypFun => (Syn, Syn) + | Ana(ty) => + let (ty1, ty2) = Typ.matched_label(ctx, ty); + (ana(ty1), ana(ty2)); }; let of_prod = (ctx: Ctx.t, mode: t, ts: list('a), filt): list(t) => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 117f1d778d..d86df4204f 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -296,8 +296,8 @@ and uexp_to_info_map = 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); | TupLabel(label, e) => - let mode = Mode.of_label(ctx, mode); - let (lab, m) = go(~mode=Syn, label, m); + let (labmode, mode) = Mode.of_label(ctx, mode); + let (lab, m) = go(~mode=labmode, label, m); let (e, m) = go(~mode, e, m); if (is_contained) { add( @@ -855,8 +855,8 @@ and upat_to_info_map = m, ); | TupLabel(label, p) => - let mode = Mode.of_label(ctx, mode); - let (lab, m) = go(~ctx, ~mode=Syn, label, m); + let (labmode, mode) = Mode.of_label(ctx, mode); + let (lab, m) = go(~ctx, ~mode=labmode, label, m); let (p, m) = go(~ctx, ~mode, p, m); if (is_contained) { add( diff --git a/src/haz3lcore/statics/TypBase.re b/src/haz3lcore/statics/TypBase.re index 8d670f9833..5f7e6c60bd 100644 --- a/src/haz3lcore/statics/TypBase.re +++ b/src/haz3lcore/statics/TypBase.re @@ -55,7 +55,7 @@ module rec Typ: { (type_provenance, type_provenance) => type_provenance; let matched_arrow: (Ctx.t, t) => (t, t); let matched_forall: (Ctx.t, t) => (option(string), t); - let matched_label: (Ctx.t, t) => t; + let matched_label: (Ctx.t, t) => (t, t); let matched_prod: (Ctx.t, list('a), 'a => option((LabeledTuple.t, 'a)), t) => list(t); let matched_list: (Ctx.t, t) => t; @@ -498,10 +498,10 @@ module rec Typ: { let matched_label = (ctx, ty) => switch (weak_head_normalize(ctx, ty)) { - | TupLabel(_, ty) => ty - | Prod([ty]) => ty - | Unknown(SynSwitch) => Unknown(SynSwitch) - | _ => ty + | TupLabel(lab, ty) => (lab, ty) + | Prod([TupLabel(lab, ty)]) => (lab, ty) + | Unknown(SynSwitch) => (Unknown(SynSwitch), Unknown(SynSwitch)) + | _ => (Unknown(Internal), ty) }; let matched_prod = (ctx, ts, get_label_ts, ty) => { From a802eb7072488a9afdf3727069575f9881051df5 Mon Sep 17 00:00:00 2001 From: WondAli Date: Wed, 28 Aug 2024 17:35:08 -0400 Subject: [PATCH 023/108] fix to let elaboration so that dot operators operate on annotated types for annotated variables --- src/haz3lcore/dynamics/Elaborator.re | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 805fe6ca93..0505a90d88 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -286,7 +286,21 @@ let rec dhexp_of_uexp = let* dp = dhpat_of_upat(m, p, false); let* ddef = dhexp_of_uexp(m, def); let* dbody = dhexp_of_uexp(m, body); - let+ ty = fixed_pat_typ(m, p); + let* ty = fixed_pat_typ(m, p); + // attach labels if needed for labeled tuples + let+ ddef = + switch (ddef, Typ.normalize(ctx, ty)) { + | (Tuple(ds), Prod(tys)) => + Some( + DHExp.Tuple( + LabeledTuple.rearrange( + Typ.get_label, DHExp.get_label, tys, ds, (t, b) => + TupLabel(Label(t), b) + ), + ), + ) + | (ddef, _) => Some(ddef) + }; let is_recursive = Statics.is_recursive(ctx, p, def, ty) && Term.UPat.get_bindings(p) From 4753f3f7bb9ad41a66c899d343aca3b99fc3c6ed Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 13 Sep 2024 14:09:11 -0400 Subject: [PATCH 024/108] fix to precedence and cast ground_caes_of --- src/haz3lcore/LabeledTuple.re | 1 + src/haz3lcore/dynamics/Casts.re | 5 ++++- src/haz3lcore/lang/Precedence.re | 16 ++++++++-------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index c7bb24bf79..c6b6ea3c90 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -198,6 +198,7 @@ let rearrange: // Checks all labeled pairs in l2 are in l1 and performs f on each pair // Checks all labeled pairs in l1 are in l2 and performs f on each pair // Checks remaining None pairs in order and performs f on each pair +// TODO: Outdated? Rearrange instead. let ana_tuple: ( 'b => option((t, 'b)), diff --git a/src/haz3lcore/dynamics/Casts.re b/src/haz3lcore/dynamics/Casts.re index d5178ca406..6c02edf05a 100644 --- a/src/haz3lcore/dynamics/Casts.re +++ b/src/haz3lcore/dynamics/Casts.re @@ -83,7 +83,10 @@ let rec ground_cases_of = (ty: Typ.t): ground_cases => { | Arrow(_, _) => grounded_Arrow | Forall(_) => grounded_Forall | List(_) => grounded_List - | TupLabel(_, _) => NotGroundOrHole(Unknown(Internal) |> Typ.temp) + | TupLabel(label, _) => + NotGroundOrHole( + TupLabel(label, Unknown(Internal) |> Typ.temp) |> Typ.temp, + ) | Ap(_) => failwith("type application in dynamics") }; }; diff --git a/src/haz3lcore/lang/Precedence.re b/src/haz3lcore/lang/Precedence.re index 5fb1147926..7dbc91a9b5 100644 --- a/src/haz3lcore/lang/Precedence.re +++ b/src/haz3lcore/lang/Precedence.re @@ -25,15 +25,15 @@ let ann = 13; let if_ = 14; let fun_ = 15; let lab = 16; -let semi = 16; -let let_ = 17; -let filter = 18; -let rule_arr = 19; -let rule_pre = 20; -let rule_sep = 21; -let case_ = 22; +let semi = 17; +let let_ = 18; +let filter = 19; +let rule_arr = 20; +let rule_pre = 21; +let rule_sep = 22; +let case_ = 23; -let comma = 17; +let comma = 18; let type_plus = 5; let type_arrow = 6; From cae4bb5a98662be8ff35a18c88cb1e9f403acb3d Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 13 Sep 2024 15:33:23 -0400 Subject: [PATCH 025/108] elaborator fixes --- src/haz3lcore/dynamics/Elaborator.re | 33 +++++++++++++++++++++++++--- src/haz3lcore/dynamics/Evaluator.re | 2 -- src/haz3lcore/dynamics/Transition.re | 2 -- src/haz3lcore/lang/Form.re | 2 +- 4 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 8f73b2ce8b..66dc1e334d 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -154,7 +154,7 @@ let rec elaborate_pattern = |> cast_from(Typ.TupLabel(labty, pty) |> Typ.temp); } else { DHPat.Tuple([DHPat.TupLabel(plab, p') |> rewrap]) - |> rewrap + |> DHPat.fresh |> cast_from( Typ.Prod([Typ.TupLabel(labty, pty) |> Typ.temp]) |> Typ.temp, ); @@ -163,6 +163,11 @@ let rec elaborate_pattern = let (ps', tys) = List.map(elaborate_pattern(m, ~in_container=true), ps) |> ListUtil.unzip; + let ps' = + LabeledTuple.rearrange( + Typ.get_label, DHPat.get_label, tys, ps', (name, p) => + TupLabel(Label(name) |> DHPat.fresh, p) |> DHPat.fresh + ); DHPat.Tuple(ps') |> rewrap |> cast_from(Typ.Prod(tys) |> Typ.temp); | Ap(p1, p2) => let (p1', ty1) = elaborate_pattern(m, p1); @@ -229,6 +234,8 @@ let rec elaborate = (m: Statics.Map.t, uexp: UExp.t, in_container: bool) : (DHExp.t, Typ.t) => { let (elaborated_type, ctx, co_ctx) = elaborated_type(m, uexp); + print_endline("exp: " ++ UExp.show(uexp)); + print_endline("typ: " ++ Typ.show(elaborated_type)); let elaborate = (~in_container=false, m, uexp) => elaborate(m, uexp, in_container); let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); @@ -308,13 +315,19 @@ let rec elaborate = |> cast_from(Typ.TupLabel(labty, ety) |> Typ.temp); } else { Tuple([Exp.TupLabel(label', e') |> rewrap]) - |> rewrap + |> Exp.fresh |> cast_from( Typ.Prod([Typ.TupLabel(labty, ety) |> Typ.temp]) |> Typ.temp, ); }; | Tuple(es) => - let (ds, tys) = List.map(elaborate(m), es) |> ListUtil.unzip; + let (ds, tys) = + List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; + let ds = + LabeledTuple.rearrange( + Typ.get_label, Exp.get_label, tys, ds, (name, p) => + TupLabel(Label(name) |> Exp.fresh, p) |> Exp.fresh + ); Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); @@ -352,6 +365,20 @@ let rec elaborate = } ); let (p, ty1) = elaborate_pattern(m, p, false); + // attach labels if needed for labeled tuples + let (def_term, def_rewrap) = DHExp.unwrap(def); + let def = + switch (def_term, Typ.term_of(Typ.normalize(ctx, ty1))) { + | (Tuple(ds), Prod(tys)) => + Tuple( + LabeledTuple.rearrange( + Typ.get_label, DHExp.get_label, tys, ds, (t, b) => + TupLabel(Label(t) |> Exp.fresh, b) |> Exp.fresh + ), + ) + |> def_rewrap + | (_, _) => def + }; let is_recursive = Statics.is_recursive(ctx, p, def, ty1) && Pat.get_bindings(p) diff --git a/src/haz3lcore/dynamics/Evaluator.re b/src/haz3lcore/dynamics/Evaluator.re index c449e7f93b..fb877accd7 100644 --- a/src/haz3lcore/dynamics/Evaluator.re +++ b/src/haz3lcore/dynamics/Evaluator.re @@ -133,7 +133,6 @@ let rec evaluate = (state, env, d) => { }; let evaluate = (env, {d}: Elaborator.Elaboration.t) => { - print_endline("eval"); let state = ref(EvaluatorState.init); let env = ClosureEnvironment.of_environment(env); let result = evaluate(state, env, d); @@ -143,6 +142,5 @@ let evaluate = (env, {d}: Elaborator.Elaboration.t) => { | (Indet, x) => Indet(x |> DHExp.repair_ids) | (Uneval, x) => Indet(x |> DHExp.repair_ids) }; - print_endline("eval end"); (state^, result); }; diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index f7fd63fb2f..5b992268a6 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -162,8 +162,6 @@ module Transition = (EV: EV_MODE) => { // Split DHExp into term and id information let (term, rewrap) = DHExp.unwrap(d); let wrap_ctx = (term): EvalCtx.t => Term({term, ids: [rep_id(d)]}); - print_endline("transition"); - print_endline(DHExp.show_term(d.term)); // Transition rules switch (term) { diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index 9ddcdcc684..892c679045 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -116,7 +116,7 @@ let is_potential_operand = match(regexp("^[a-zA-Z0-9_'\\.?]+$")); * delimiters, string delimiters, or the instant expanding paired * delimiters: ()[]| */ let potential_operator_regexp = - regexp("^[^a-zA-Z0-9_'?\"#\n\\s\\[\\]\\(\\)]+$"); /* Multiline operators not supported */ + regexp("^[^a-zA-Z0-9_'\\.?\"#\n\\s\\[\\]\\(\\)]+$"); /* Multiline operators not supported */ let is_potential_operator = match(potential_operator_regexp); let is_potential_token = t => is_potential_operand(t) From bc22754b7c2a590a03929561cbd56d31c6e9ab33 Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 13 Sep 2024 15:57:01 -0400 Subject: [PATCH 026/108] updated parser for dot operator --- src/haz3lcore/lang/Form.re | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/lang/Form.re b/src/haz3lcore/lang/Form.re index 892c679045..481b5fee59 100644 --- a/src/haz3lcore/lang/Form.re +++ b/src/haz3lcore/lang/Form.re @@ -110,7 +110,9 @@ let is_keyword = match(keyword_regexp); /* Potential tokens: These are fallthrough classes which determine * the behavior when inserting a character in contact with a token */ -let is_potential_operand = match(regexp("^[a-zA-Z0-9_'\\.?]+$")); +let is_potential_operand = x => + match(regexp("^[a-zA-Z0-9_'?]+$"), x) + || match(regexp("^[0-9_'\\.?]+$"), x); /* Anything else is considered a potential operator, as long * as it does not contain any whitespace, linebreaks, comment * delimiters, string delimiters, or the instant expanding paired From e810400710dea3442b61a58d380c102244f652c2 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 20 Sep 2024 10:04:25 -0400 Subject: [PATCH 027/108] debug --- Makefile | 2 +- src/haz3lcore/LabeledTuple.re | 238 ++++++++++++++++----------- src/haz3lcore/dynamics/Elaborator.re | 66 ++++++-- src/haz3lcore/lang/term/Typ.re | 7 +- 4 files changed, 196 insertions(+), 117 deletions(-) diff --git a/Makefile b/Makefile index c1f5943d07..d6f0004181 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ fmt: dune fmt --auto-promote watch: setup-instructor - dune build @src/fmt --auto-promote src --profile dev --watch + dune build --profile dev --watch watch-release: setup-instructor dune build @src/fmt --auto-promote src --profile release --watch diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index c6b6ea3c90..811d3ad00f 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -77,77 +77,97 @@ let validate_uniqueness: // filt returns Some(string) if TupLabel or None if not a TupLabel // returns a permutation of l2 that matches labels in l1 // other labels are in order, even if not matching. -let rearrange: - ( - 'a => option((t, 'a)), - 'b => option((t, 'b)), - list('a), - list('b), - (t, 'b) => 'b - ) => - list('b) = - (get_label1, get_label2, l1, l2, constructor) => { - // TODO: Error handling in case of bad arguments - let (_, l1_lab, _) = validate_uniqueness(get_label1, l1); - let (_, l2_lab, _) = validate_uniqueness(get_label2, l2); - // Second item in the pair is the full tuplabel - let l2_matched = - List.fold_left( - (l2_matched, l1_item) => { - let l2_item = - find_opt( - l2_item => { - switch (l1_item, l2_item) { - | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l2_item) { - | Some(l2_item) => l2_matched @ [l2_item] - | None => l2_matched +// 'a types +// 'b expressions +let rearrange = + ( + ~show_a: option('a => string)=?, + ~show_b: option('b => string)=?, + get_label1: 'a => option((t, 'a)), + get_label2: 'b => option((t, 'b)), + l1: list('a), + l2: list('b), + constructor: (t, 'b) => 'b, + ) + : list('b) => { + // TODO: Error handling in case of bad arguments + let (_, l1_lab, _) = validate_uniqueness(get_label1, l1); + let (_, l2_lab, _) = validate_uniqueness(get_label2, l2); + // Second item in the pair is the full tuplabel + let l2_matched: list((option(t), 'b)) = + List.fold_left( + (l2_matched, l1_item) => { + let l2_item = + find_opt( + l2_item => { + switch (l1_item, l2_item) { + | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l2_item) { + | Some(l2_item) => l2_matched @ [l2_item] + | None => l2_matched + }; + }, + [], + l1_lab, + ); + // Second item in the pair is just the element half of the tuplabel + let l2_rem: list((option(t), 'b)) = + List.fold_left( + (l2_rem, item) => { + switch (get_label2(item)) { + | Some((s1, _)) + when + List.exists( + l => { + switch (l) { + | (Some(s2), _) => compare(s1, s2) == 0 + | _ => false + } + }, + l2_matched, + ) => l2_rem + | Some((s1, it)) => l2_rem @ [(Some(s1), it)] + | _ => l2_rem @ [(None, item)] + } + }, + [], + l2, + ); + let rec rearrange_helper = + ( + l1: list('a), + l2_matched: list((option(t), 'b)), + l2_rem: list((option(t), 'b)), + ) + : list('y) => { + switch (l1) { + | [hd, ...tl] => + switch (get_label1(hd)) { + | Some((s1, _)) => + switch (l2_matched) { + | [] => + switch (l2_rem) { + | [hd2, ...tl2] => + switch (hd2) { + | (Some(s2), rem_val) => + [constructor(s2, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) + | (None, rem_val) => + [constructor(s1, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) + } + | [] => raise(Exception) }; - }, - [], - l1_lab, - ); - // Second item in the pair is just the element half of the tuplabel - let l2_rem = - List.fold_left( - (l2_rem, item) => { - switch (get_label2(item)) { - | Some((s1, _)) - when - List.exists( - l => { - switch (l) { - | (Some(s2), _) => compare(s1, s2) == 0 - | _ => false - } - }, - l2_matched, - ) => l2_rem - | Some((s1, it)) => l2_rem @ [(Some(s1), it)] - | _ => l2_rem @ [(None, item)] - } - }, - [], - l2, - ); - let rec rearrange_helper = - ( - l1: list('x), - l2_matched: list((option(t), 'y)), - l2_rem: list((option(t), 'y)), - ) - : list('y) => - switch (l1) { - | [hd, ...tl] => - switch (get_label1(hd)) { - | Some((s1, _)) => - switch (l2_matched) { - | [] => + | [hd2, ...tl2] => + switch (hd2) { + | (Some(s2), l2_val) when compare(s1, s2) == 0 => + [l2_val] @ rearrange_helper(tl, tl2, l2_rem) + | _ => switch (l2_rem) { | [hd2, ...tl2] => switch (hd2) { @@ -160,36 +180,60 @@ let rearrange: } | [] => raise(Exception) } - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), l2_val) when compare(s1, s2) == 0 => - [l2_val] @ rearrange_helper(tl, tl2, l2_rem) - | _ => - switch (l2_rem) { - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), rem_val) => - [constructor(s2, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - | (None, rem_val) => - [constructor(s1, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - } - | [] => raise(Exception) - } - } - } - | None => - switch (l2_rem) { - | [(_, hd2), ...tl2] => - [hd2] @ rearrange_helper(tl, l2_matched, tl2) - | [] => raise(Exception) } + }; + | None => + switch (l2_rem) { + | [(_, hd2), ...tl2] => + [hd2] @ rearrange_helper(tl, l2_matched, tl2) + | [] => raise(Exception) } - | [] => [] - }; - rearrange_helper(l1, l2_matched, l2_rem); + } + | [] => [] + }; }; + Option.iter( + sa => print_endline("l1: " ++ String.concat(",", List.map(sa, l1))), + show_a, + ); + Option.iter( + sb => { + print_endline( + "l2_matched: " + ++ String.concat( + ".", + List.map( + (x: (option(t), 'y)) => + "(" + ++ [%derive.show: option(t)](fst(x)) + ++ "," + ++ sb(snd(x)) + ++ ")", + l2_matched, + ), + ), + ); + print_endline( + "l2_rem: " + ++ String.concat( + ".", + List.map( + (x: (option(t), 'y)) => + "(" + ++ [%derive.show: option(t)](fst(x)) + ++ "," + ++ sb(snd(x)) + ++ ")", + l2_rem, + ), + ), + ); + (); + }, + show_b, + ); + rearrange_helper(l1, l2_matched, l2_rem); +}; // Rename and clean this // Assumes all labels are unique diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 66dc1e334d..53f3f0065f 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -234,8 +234,6 @@ let rec elaborate = (m: Statics.Map.t, uexp: UExp.t, in_container: bool) : (DHExp.t, Typ.t) => { let (elaborated_type, ctx, co_ctx) = elaborated_type(m, uexp); - print_endline("exp: " ++ UExp.show(uexp)); - print_endline("typ: " ++ Typ.show(elaborated_type)); let elaborate = (~in_container=false, m, uexp) => elaborate(m, uexp, in_container); let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); @@ -309,26 +307,60 @@ let rec elaborate = | TupLabel(label, e) => let (label', labty) = elaborate(m, label); let (e', ety) = elaborate(m, e); - if (in_container) { - Exp.TupLabel(label', e') - |> rewrap - |> cast_from(Typ.TupLabel(labty, ety) |> Typ.temp); - } else { - Tuple([Exp.TupLabel(label', e') |> rewrap]) - |> Exp.fresh - |> cast_from( - Typ.Prod([Typ.TupLabel(labty, ety) |> Typ.temp]) |> Typ.temp, - ); - }; + let foo = + if (in_container) { + Exp.TupLabel(label', e') + |> rewrap + |> cast_from(Typ.TupLabel(labty, ety) |> Typ.temp); + } else { + Tuple([Exp.TupLabel(label', e') |> rewrap]) + |> Exp.fresh + |> cast_from( + Typ.Prod([Typ.TupLabel(labty, ety) |> Typ.temp]) |> Typ.temp, + ); + }; + + print_endline("exp: " ++ UExp.show(uexp)); + print_endline("typ: " ++ Typ.show(elaborated_type)); + print_endline("dhexp: " ++ DHExp.show(foo)); + foo; | Tuple(es) => - let (ds, tys) = + let (ds: list(DHExp.t), tys: list(Typ.t)) = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; + let (foo : option(list(Typ.t))) = Typ.matched_prod_strict( + ~show_a=DHExp.show, + ~show_b=Typ.show, + ctx, ds, + (d : DHExp.t) => { + switch(d.term) { + | TupLabel({term: Var(l), _}, ty) => Some((l, ty)) + | _ => None + } + } + , elaborated_type); + print_endline("foo " ++ [%derive.show: option(list(Typ.t))](foo)); + + print_endline("tupls ds" ++ [%derive.show: list(DHExp.t)](ds)); + print_endline("tupls tys" ++ [%derive.show: list(Typ.t)](tys)); let ds = LabeledTuple.rearrange( - Typ.get_label, Exp.get_label, tys, ds, (name, p) => - TupLabel(Label(name) |> Exp.fresh, p) |> Exp.fresh + ~show_a=Typ.show, + ~show_b=DHExp.show, + Typ.get_label, + Exp.get_label, + tys, + ds, + (name, p) => { + print_endline("tuple constructor name: " ++ name); + print_endline("tuple constructor p: " ++ DHExp.show(p)); + TupLabel(Label(name) |> Exp.fresh, p) |> Exp.fresh; + }, ); - Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); + let foo = Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); + print_endline("tuple exp: " ++ UExp.show(uexp)); + print_endline("tuple typ: " ++ Typ.show(elaborated_type)); + print_endline("tuple dhexp: " ++ DHExp.show(foo)); + foo; | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); let (e2, ty2) = elaborate(m, e2); diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index 5d662a07cb..c65289d155 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -463,7 +463,9 @@ let matched_label = (ctx, ty) => | _ => (Unknown(Internal) |> temp, ty) }; -let rec matched_prod_strict = (ctx, ts, get_label_ts, ty) => +let rec matched_prod_strict = ( + ~show_a: option('a => string)=?, + ~show_b: option('b => string)=?, ctx, ts, get_label_ts, (ty : t)) => switch (term_of(weak_head_normalize(ctx, ty))) { | Parens(ty) => matched_prod_strict(ctx, ts, get_label_ts, ty) | Prod(tys) => @@ -471,7 +473,8 @@ let rec matched_prod_strict = (ctx, ts, get_label_ts, ty) => None; } else { Some( - LabeledTuple.rearrange(get_label_ts, get_label, ts, tys, (name, b) => + LabeledTuple.rearrange(~show_a=?show_a, + ~show_b=?show_b,get_label_ts, get_label, ts, tys, (name, b) => TupLabel(Label(name) |> temp, b) |> temp ), ); From 840f06ffa96e467772664d71d3013e9b407c46b4 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sat, 21 Sep 2024 13:56:34 -0400 Subject: [PATCH 028/108] Temp commit --- src/haz3lcore/LabeledTuple.re | 313 +++++++++++++++------------ src/haz3lcore/dynamics/Elaborator.re | 39 +--- src/haz3lcore/lang/term/IdTagged.re | 6 + src/haz3lcore/lang/term/Typ.re | 79 +++++-- src/haz3lcore/statics/Mode.re | 4 +- src/haz3lcore/statics/Statics.re | 4 +- 6 files changed, 252 insertions(+), 193 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 811d3ad00f..16e11ae287 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -41,8 +41,10 @@ let seperate_labels: // TODO: Need to check uniqueness earlier // TODO: Make more efficient let validate_uniqueness: + 'a. ('a => option((t, 'a)), list('a)) => - (bool, list((option(t), 'a)), list('a)) = + (bool, list((option(t), 'a)), list('a)) + = (get_label, es) => { let results = List.fold_left( @@ -73,101 +75,156 @@ let validate_uniqueness: results; }; +type label = t; +let seperate_labeled = (xs: list((option(label), 'a))) => { + List.partition_map( + ((l, a)) => + switch (l) { + | None => Right(a) + | Some(l) => Left((l, a)) + }, + xs, + ); +}; + +// TODO Performance +let intersect = (xs, ys) => { + List.filter_map(x => List.find_opt((==)(x), ys), xs); +}; + +// Rearranges all the labels in l2 to match the order of the labels in l1. Labels are optional and should me reordered for all present labels first and then unlabled fields matched up pairwise. So labeled fields can be reordered and unlabeled ones can't. Also add labels to the unlabeled. +// TODO Handle the unequal length case and extra labels case +let rearrange2: + 'a 'b. + (list((option(label), 'a)), list((option(label), 'b))) => + list((option(label), 'b)) + = + (l1: list((option(label), 'a)), l2: list((option(label), 'b))) => { + let l1_labels = List.filter_map(fst, l1); + let l2_labels = List.filter_map(fst, l2); + let common_labels = intersect(l1_labels, l2_labels); + + // let (x : list((option(label), 'b)), _) = List.fold_left(fn, ([], l2), l1); + + let x = + List.fold_left( + ( + ( + matched: list((option(label), 'b)), + remaining: list((option(label), 'b)), + ), + current, + ) => { + let new_matched: list((option(label), 'b)) = + switch (current) { + | (Some(_current_label), _a) => assert(false) + | (None, _a) => + let _potential_matches: list((option(label), 'b)) = + List.filter( + ((rl: option(label), _b: 'b)) => + switch (rl) { + | None => false + | Some(l2) => !List.mem(l2, common_labels) + }, + remaining, + ); + + assert(false); + }; + + (new_matched, remaining); + }, + ([], l2), + l1, + ); + + fst(x); + }; + // Assumes all labels are unique // filt returns Some(string) if TupLabel or None if not a TupLabel // returns a permutation of l2 that matches labels in l1 // other labels are in order, even if not matching. // 'a types // 'b expressions -let rearrange = - ( - ~show_a: option('a => string)=?, - ~show_b: option('b => string)=?, - get_label1: 'a => option((t, 'a)), - get_label2: 'b => option((t, 'b)), - l1: list('a), - l2: list('b), - constructor: (t, 'b) => 'b, - ) - : list('b) => { - // TODO: Error handling in case of bad arguments - let (_, l1_lab, _) = validate_uniqueness(get_label1, l1); - let (_, l2_lab, _) = validate_uniqueness(get_label2, l2); - // Second item in the pair is the full tuplabel - let l2_matched: list((option(t), 'b)) = - List.fold_left( - (l2_matched, l1_item) => { - let l2_item = - find_opt( - l2_item => { - switch (l1_item, l2_item) { - | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l2_item) { - | Some(l2_item) => l2_matched @ [l2_item] - | None => l2_matched - }; - }, - [], - l1_lab, - ); - // Second item in the pair is just the element half of the tuplabel - let l2_rem: list((option(t), 'b)) = - List.fold_left( - (l2_rem, item) => { - switch (get_label2(item)) { - | Some((s1, _)) - when - List.exists( - l => { - switch (l) { - | (Some(s2), _) => compare(s1, s2) == 0 - | _ => false - } - }, - l2_matched, - ) => l2_rem - | Some((s1, it)) => l2_rem @ [(Some(s1), it)] - | _ => l2_rem @ [(None, item)] - } - }, - [], - l2, - ); - let rec rearrange_helper = - ( - l1: list('a), - l2_matched: list((option(t), 'b)), - l2_rem: list((option(t), 'b)), - ) - : list('y) => { - switch (l1) { - | [hd, ...tl] => - switch (get_label1(hd)) { - | Some((s1, _)) => - switch (l2_matched) { - | [] => - switch (l2_rem) { - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), rem_val) => - [constructor(s2, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - | (None, rem_val) => - [constructor(s1, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - } - | [] => raise(Exception) +let rearrange: + 'a 'b. + ( + ~show_a: 'a => string=?, + ~show_b: 'b => string=?, + 'a => option((t, 'a)), + 'b => option((t, 'b)), + list('a), + list('b), + (t, 'b) => 'b + ) => + list('b) + = + (~show_a=?, ~show_b=?, get_label1, get_label2, l1, l2, constructor) => { + let _ = show_b; + let _ = show_a; + // TODO: Error handling in case of bad arguments + let (_, l1_lab, _) = validate_uniqueness(get_label1, l1); + let (_, l2_lab, _) = validate_uniqueness(get_label2, l2); + + // Second item in the pair is the full tuplabel + let l2_matched: list((option(t), 'b)) = + List.fold_left( + (l2_matched, l1_item) => { + let l2_item = + find_opt( + l2_item => { + switch (l1_item, l2_item) { + | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 + | (_, _) => false + } + }, + l2_lab, + ); + switch (l2_item) { + | Some(l2_item) => l2_matched @ [l2_item] + | None => l2_matched }; - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), l2_val) when compare(s1, s2) == 0 => - [l2_val] @ rearrange_helper(tl, tl2, l2_rem) - | _ => + }, + [], + l1_lab, + ); + // Second item in the pair is just the element half of the tuplabel + let l2_rem: list((option(t), 'b)) = + List.fold_left( + (l2_rem, item) => { + switch (get_label2(item)) { + | Some((s1, _)) + when + List.exists( + l => { + switch (l) { + | (Some(s2), _) => compare(s1, s2) == 0 + | _ => false + } + }, + l2_matched, + ) => l2_rem + | Some((s1, it)) => l2_rem @ [(Some(s1), it)] + | _ => l2_rem @ [(None, item)] + } + }, + [], + l2, + ); + let rec rearrange_helper = + ( + l1: list('a), + l2_matched: list((option(t), 'b)), + l2_rem: list((option(t), 'b)), + ) + : list('y) => { + switch (l1) { + | [hd, ...tl] => + switch (get_label1(hd)) { + | Some((s1, _)) => + switch (l2_matched) { + | [] => switch (l2_rem) { | [hd2, ...tl2] => switch (hd2) { @@ -180,60 +237,38 @@ let rearrange = } | [] => raise(Exception) } + | [hd2, ...tl2] => + switch (hd2) { + | (Some(s2), l2_val) when compare(s1, s2) == 0 => + [l2_val] @ rearrange_helper(tl, tl2, l2_rem) + | _ => + switch (l2_rem) { + | [hd2, ...tl2] => + switch (hd2) { + | (Some(s2), rem_val) => + [constructor(s2, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) + | (None, rem_val) => + [constructor(s1, rem_val)] + @ rearrange_helper(tl, l2_matched, tl2) + } + | [] => raise(Exception) + } + } + } + | None => + switch (l2_rem) { + | [(_, hd2), ...tl2] => + [hd2] @ rearrange_helper(tl, l2_matched, tl2) + | [] => raise(Exception) } - }; - | None => - switch (l2_rem) { - | [(_, hd2), ...tl2] => - [hd2] @ rearrange_helper(tl, l2_matched, tl2) - | [] => raise(Exception) } - } - | [] => [] + | [] => [] + }; }; + + rearrange_helper(l1, l2_matched, l2_rem); }; - Option.iter( - sa => print_endline("l1: " ++ String.concat(",", List.map(sa, l1))), - show_a, - ); - Option.iter( - sb => { - print_endline( - "l2_matched: " - ++ String.concat( - ".", - List.map( - (x: (option(t), 'y)) => - "(" - ++ [%derive.show: option(t)](fst(x)) - ++ "," - ++ sb(snd(x)) - ++ ")", - l2_matched, - ), - ), - ); - print_endline( - "l2_rem: " - ++ String.concat( - ".", - List.map( - (x: (option(t), 'y)) => - "(" - ++ [%derive.show: option(t)](fst(x)) - ++ "," - ++ sb(snd(x)) - ++ ")", - l2_rem, - ), - ), - ); - (); - }, - show_b, - ); - rearrange_helper(l1, l2_matched, l2_rem); -}; // Rename and clean this // Assumes all labels are unique diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 53f3f0065f..29be521b83 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -327,40 +327,17 @@ let rec elaborate = | Tuple(es) => let (ds: list(DHExp.t), tys: list(Typ.t)) = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; - let (foo : option(list(Typ.t))) = Typ.matched_prod_strict( - ~show_a=DHExp.show, - ~show_b=Typ.show, - ctx, ds, - (d : DHExp.t) => { - switch(d.term) { - | TupLabel({term: Var(l), _}, ty) => Some((l, ty)) - | _ => None - } - } - , elaborated_type); - print_endline("foo " ++ [%derive.show: option(list(Typ.t))](foo)); - - print_endline("tupls ds" ++ [%derive.show: list(DHExp.t)](ds)); - print_endline("tupls tys" ++ [%derive.show: list(Typ.t)](tys)); + print_endline("ds: " ++ [%derive.show: list(DHExp.t)](ds)); + print_endline("tys: " ++ [%derive.show: list(Typ.t)](tys)); + let foos = Typ.matched_prod(~show_a=DHExp.show, + ctx, ds, DHExp.get_label, elaborated_type); + print_endline("foos: " ++ [%derive.show: list(Typ.t)](foos)); let ds = LabeledTuple.rearrange( - ~show_a=Typ.show, - ~show_b=DHExp.show, - Typ.get_label, - Exp.get_label, - tys, - ds, - (name, p) => { - print_endline("tuple constructor name: " ++ name); - print_endline("tuple constructor p: " ++ DHExp.show(p)); - TupLabel(Label(name) |> Exp.fresh, p) |> Exp.fresh; - }, + Typ.get_label, Exp.get_label, foos, ds, (name, p) => + TupLabel(Label(name) |> Exp.fresh, p) |> Exp.fresh ); - let foo = Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); - print_endline("tuple exp: " ++ UExp.show(uexp)); - print_endline("tuple typ: " ++ Typ.show(elaborated_type)); - print_endline("tuple dhexp: " ++ DHExp.show(foo)); - foo; + Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); let (e2, ty2) = elaborate(m, e2); diff --git a/src/haz3lcore/lang/term/IdTagged.re b/src/haz3lcore/lang/term/IdTagged.re index 084a252de4..ad71087d56 100644 --- a/src/haz3lcore/lang/term/IdTagged.re +++ b/src/haz3lcore/lang/term/IdTagged.re @@ -14,7 +14,13 @@ type t('a) = { term: 'a, }; +let pp: ((Format.formatter, 'a) => unit, Format.formatter, t('a)) => unit = + (fmt_a, formatter, ta) => { + fmt_a(formatter, ta.term); + }; + let fresh = term => { + let _x: ((Format.formatter, 'a) => unit, t('a)) => string = show; {ids: [Id.mk()], copied: false, term}; }; diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index c65289d155..33b9fbc76d 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -463,29 +463,66 @@ let matched_label = (ctx, ty) => | _ => (Unknown(Internal) |> temp, ty) }; -let rec matched_prod_strict = ( - ~show_a: option('a => string)=?, - ~show_b: option('b => string)=?, ctx, ts, get_label_ts, (ty : t)) => - switch (term_of(weak_head_normalize(ctx, ty))) { - | Parens(ty) => matched_prod_strict(ctx, ts, get_label_ts, ty) - | Prod(tys) => - if (List.length(ts) != List.length(tys)) { - None; - } else { - Some( - LabeledTuple.rearrange(~show_a=?show_a, - ~show_b=?show_b,get_label_ts, get_label, ts, tys, (name, b) => - TupLabel(Label(name) |> temp, b) |> temp - ), - ); - } - | Unknown(SynSwitch) => - Some(List.init(List.length(ts), _ => Unknown(SynSwitch) |> temp)) - | _ => None +let rec matched_prod_strict: + 'a 'b. + ( + ~show_a: 'a => string=?, + ~show_b: 'b => string=?, + Ctx.t, + list('a), + 'a => option((string, 'a)), + t + ) => + option(list(t)) + = + (~show_a=?, ~show_b=?, ctx: Ctx.t, ts, get_label_ts, ty: t) => { + let _ = show_b; + let normalized: term = term_of(weak_head_normalize(ctx, ty)); + print_endline("normalized: " ++ show_term(normalized)); + switch (normalized) { + | Parens(ty) => matched_prod_strict(~show_a=?show_a, ~show_b=?show_b, ctx, ts, get_label_ts, ty) + | Prod(tys: list(t)) => + if (List.length(ts) != List.length(tys)) { + None; + } else { + let foo : (t => (option((string, t)))) = get_label; + let get_label_ts2 : 'a => option((string, 'a)) = get_label_ts; + let (baz : list('a)) = LabeledTuple.rearrange( + foo, + get_label_ts2, + tys, + ts, + (_name, b) =>{ + let (returnable : 'a) =b; + returnable} + ); + let bar: option(list(t)) = + Some( + LabeledTuple.rearrange( + get_label_ts, get_label, ts, tys, (name, b) => + TupLabel(Label(name) |> temp, b) |> temp + ), + ); + + Option.iter(sa => print_endline("baz: " ++ String.concat(",", List.map(sa, baz))), show_a); + bar; + } + | Unknown(SynSwitch) => + Some(List.init(List.length(ts), _ => Unknown(SynSwitch) |> temp)) + | _ => None + }; }; -let matched_prod = (ctx, ts, get_label_ts, ty) => - matched_prod_strict(ctx, ts, get_label_ts, ty) +let matched_prod = + ( + ~show_a: option('a => string)=?, + ctx: Ctx.t, + ts: list('a), + get_label_ts: 'a => option((string, 'a)), + ty: t, + ) + : list(t) => + matched_prod_strict(~show_a=?show_a,ctx, ts, get_label_ts, ty) |> Option.value( ~default=List.init(List.length(ts), _ => Unknown(Internal) |> temp), ); diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index 8072473a5e..d6597bbece 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -70,7 +70,9 @@ let of_label = (ctx: Ctx.t, mode: t): (t, t) => (ana(ty1), ana(ty2)); }; -let of_prod = (ctx: Ctx.t, mode: t, ts: list('a), filt): list(t) => +let of_prod = + (ctx: Ctx.t, mode: t, ts: list('a), filt: 'a => option((string, 'a))) + : list(t) => switch (mode) { | Syn | SynFun diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 87fdccd95d..8369f70405 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -329,7 +329,9 @@ and uexp_to_info_map = m, ) | Tuple(es) => - let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); + let filt = (y: UExp.t): option((string, UExp.t)) => UExp.get_label(y); + let elems = es; + let modes = Mode.of_prod(ctx, mode, elems, filt); let (es, m) = map_m_go(m, modes, es, ~is_contained=true); add( ~self=Just(Prod(List.map(Info.exp_ty, es)) |> Typ.temp), From 58fc12cced1f5a249fdf2a54f1ce27e605b35644 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sat, 21 Sep 2024 15:23:53 -0400 Subject: [PATCH 029/108] Add rearrange2 --- src/haz3lcore/LabeledTuple.re | 143 ++++++++++++++++++++------- src/haz3lcore/dynamics/Elaborator.re | 10 +- src/haz3lcore/lang/term/Typ.re | 35 ++++--- test/Test_LabeledTuple.re | 98 ++++++++++++++++++ test/dune | 2 +- test/haz3ltest.re | 5 +- 6 files changed, 238 insertions(+), 55 deletions(-) create mode 100644 test/Test_LabeledTuple.re diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 16e11ae287..96cb731c50 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -94,51 +94,120 @@ let intersect = (xs, ys) => { // Rearranges all the labels in l2 to match the order of the labels in l1. Labels are optional and should me reordered for all present labels first and then unlabled fields matched up pairwise. So labeled fields can be reordered and unlabeled ones can't. Also add labels to the unlabeled. // TODO Handle the unequal length case and extra labels case -let rearrange2: - 'a 'b. - (list((option(label), 'a)), list((option(label), 'b))) => +let rec rearrange2: + 'b. + ( + ~show_b: 'b => string=?, + list(option(label)), + list((option(label), 'b)) + ) => list((option(label), 'b)) = - (l1: list((option(label), 'a)), l2: list((option(label), 'b))) => { - let l1_labels = List.filter_map(fst, l1); + (~show_b=?, l1: list(option(label)), l2: list((option(label), 'b))) => { + let l1_labels = List.filter_map(Fun.id, l1); let l2_labels = List.filter_map(fst, l2); let common_labels = intersect(l1_labels, l2_labels); - // let (x : list((option(label), 'b)), _) = List.fold_left(fn, ([], l2), l1); + let returnable = + switch (l1, l2) { + | ([], _) => l2 + | (_, []) => [] + | ([Some(expected_label), ...remaining_expectations], remaining) => + let maybe_found = List.assoc_opt(Some(expected_label), remaining); - let x = - List.fold_left( - ( - ( - matched: list((option(label), 'b)), - remaining: list((option(label), 'b)), - ), - current, - ) => { - let new_matched: list((option(label), 'b)) = - switch (current) { - | (Some(_current_label), _a) => assert(false) - | (None, _a) => - let _potential_matches: list((option(label), 'b)) = - List.filter( - ((rl: option(label), _b: 'b)) => - switch (rl) { - | None => false - | Some(l2) => !List.mem(l2, common_labels) - }, - remaining, - ); - - assert(false); - }; + switch (maybe_found) { + | Some(found) => + [(Some(expected_label), found)] + @ rearrange2( + ~show_b?, + remaining_expectations, + List.remove_assoc(Some(expected_label), remaining), + ) + | None => + let ( + pre: list((option(label), 'b)), + current: option((option(label), 'b)), + post: list((option(label), 'b)), + ) = + ListUtil.split(remaining, ((label: option(label), _)) => { + switch (label) { + | Some(label) => !List.mem(label, common_labels) + | None => true + } + }); - (new_matched, remaining); - }, - ([], l2), - l1, - ); + switch (current) { + | Some((_existing_label, b)) => + [(Some(expected_label), b)] + @ rearrange2(~show_b?, remaining_expectations, pre @ post) + | None => remaining + }; + }; + | ([None, ...remaining_expectations], remaining) => + // Pick the first one that's not in common labels and then keep the rest in remaining + let ( + pre: list((option(label), 'b)), + current: option((option(label), 'b)), + post: list((option(label), 'b)), + ) = + ListUtil.split(remaining, ((label: option(label), _)) => { + switch (label) { + | Some(label) => !List.mem(label, common_labels) + | None => true + } + }); + switch (current) { + | Some((_existing_label, b)) => + [(None, b)] + @ rearrange2(~show_b?, remaining_expectations, pre @ post) + | None => remaining + }; + }; + print_endline("================"); + print_endline("l1: " ++ [%derive.show: list(option(string))](l1)); + Option.iter( + sa => + print_endline( + "l2: [" + ++ String.concat( + ",", + List.map( + l2e => + "(" + ++ [%derive.show: option(string)](fst(l2e)) + ++ "," + ++ sa(snd(l2e)) + ++ ")", + l2, + ), + ) + ++ "]", + ), + show_b, + ); + Option.iter( + sa => + print_endline( + "returnable: [" + ++ String.concat( + ",", + List.map( + l2e => + "(" + ++ [%derive.show: option(string)](fst(l2e)) + ++ "," + ++ sa(snd(l2e)) + ++ ")", + returnable, + ), + ) + ++ "]", + ), + show_b, + ); + print_endline("================"); - fst(x); + returnable; }; // Assumes all labels are unique diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 29be521b83..d9e673cd28 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -329,8 +329,14 @@ let rec elaborate = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; print_endline("ds: " ++ [%derive.show: list(DHExp.t)](ds)); print_endline("tys: " ++ [%derive.show: list(Typ.t)](tys)); - let foos = Typ.matched_prod(~show_a=DHExp.show, - ctx, ds, DHExp.get_label, elaborated_type); + let foos = + Typ.matched_prod( + ~show_a=DHExp.show, + ctx, + ds, + DHExp.get_label, + elaborated_type, + ); print_endline("foos: " ++ [%derive.show: list(Typ.t)](foos)); let ds = LabeledTuple.rearrange( diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index 33b9fbc76d..f20ee3370e 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -480,22 +480,25 @@ let rec matched_prod_strict: let normalized: term = term_of(weak_head_normalize(ctx, ty)); print_endline("normalized: " ++ show_term(normalized)); switch (normalized) { - | Parens(ty) => matched_prod_strict(~show_a=?show_a, ~show_b=?show_b, ctx, ts, get_label_ts, ty) + | Parens(ty) => + matched_prod_strict(~show_a?, ~show_b?, ctx, ts, get_label_ts, ty) | Prod(tys: list(t)) => if (List.length(ts) != List.length(tys)) { None; } else { - let foo : (t => (option((string, t)))) = get_label; - let get_label_ts2 : 'a => option((string, 'a)) = get_label_ts; - let (baz : list('a)) = LabeledTuple.rearrange( - foo, - get_label_ts2, - tys, - ts, - (_name, b) =>{ - let (returnable : 'a) =b; - returnable} - ); + let foo: t => option((string, t)) = get_label; + let get_label_ts2: 'a => option((string, 'a)) = get_label_ts; + let baz: list('a) = + LabeledTuple.rearrange( + foo, + get_label_ts2, + tys, + ts, + (_name, b) => { + let returnable: 'a = b; + returnable; + }, + ); let bar: option(list(t)) = Some( LabeledTuple.rearrange( @@ -504,7 +507,11 @@ let rec matched_prod_strict: ), ); - Option.iter(sa => print_endline("baz: " ++ String.concat(",", List.map(sa, baz))), show_a); + Option.iter( + sa => + print_endline("baz: " ++ String.concat(",", List.map(sa, baz))), + show_a, + ); bar; } | Unknown(SynSwitch) => @@ -522,7 +529,7 @@ let matched_prod = ty: t, ) : list(t) => - matched_prod_strict(~show_a=?show_a,ctx, ts, get_label_ts, ty) + matched_prod_strict(~show_a?, ctx, ts, get_label_ts, ty) |> Option.value( ~default=List.init(List.length(ts), _ => Unknown(Internal) |> temp), ); diff --git a/test/Test_LabeledTuple.re b/test/Test_LabeledTuple.re new file mode 100644 index 0000000000..6bee6a530c --- /dev/null +++ b/test/Test_LabeledTuple.re @@ -0,0 +1,98 @@ +open Alcotest; +open Haz3lcore; + +let test_rearrange = (name, analyzed_types, actual_values, expected_values) => + test_case( + name, + `Quick, + () => { + let actual = + LabeledTuple.rearrange2( + ~show_b=[%derive.show: int], + analyzed_types, + actual_values, + ); + check( + list(pair(option(string), int)), + name, + expected_values, + actual, + ); + (); + }, + ); +// Create a property test +let tests: list(test_case(return)) = [ + test_rearrange( + "Singleton unlabeled", + [None], + [(None, 1)], + [(None, 1)], + ), + test_rearrange( + "Singleton labeled", + [Some("a")], + [(Some("a"), 1)], + [(Some("a"), 1)], + ), + test_rearrange( + "unlabeled remains same order", + [None, None, None], + [(None, 1), (None, 2), (None, 3)], + [(None, 1), (None, 2), (None, 3)], + ), + test_rearrange( + "fully labeled retains ordering", + [Some("a"), Some("b"), Some("c")], + [(Some("a"), 1), (Some("b"), 2), (Some("c"), 3)], + [(Some("a"), 1), (Some("b"), 2), (Some("c"), 3)], + ), + test_rearrange( + "Missing labels get added", + [Some("a"), Some("b"), Some("c")], + [(None, 1), (None, 2), (None, 3)], + [(Some("a"), 1), (Some("b"), 2), (Some("c"), 3)], + ), + test_rearrange( + "Present labels get reordered", + [Some("a"), Some("b"), Some("c")], + [(Some("b"), 1), (Some("a"), 2), (Some("c"), 3)], + [(Some("a"), 2), (Some("b"), 1), (Some("c"), 3)], + ), + test_rearrange( + "Partial labels get reordered", + [Some("a"), Some("b"), Some("c")], + [(Some("b"), 1), (None, 2), (None, 3)], + [(Some("a"), 2), (Some("b"), 1), (Some("c"), 3)], + ), + test_rearrange( + "Extra labels get reordered", + [Some("a"), Some("b"), Some("c")], + [(Some("d"), 4), (Some("b"), 1), (Some("a"), 2), (Some("c"), 3)], + [(Some("a"), 2), (Some("b"), 1), (Some("c"), 3), (Some("d"), 4)], + ), + test_rearrange( + "pair labeled, unlabled", + [Some("a"), None], + [(Some("a"), 1), (None, 2)], + [(Some("a"), 1), (None, 2)], + ), + test_rearrange( + "Independent label sets with some overlap", + [Some("a"), Some("b"), None, Some("c"), None], + [ + (Some("d"), 4), + (Some("c"), 1), + (Some("e"), 5), + (Some("b"), 3), + (None, 2), + ], + [ + (Some("a"), 4), + (Some("b"), 3), + (None, 5), + (Some("c"), 1), + (None, 2), + ], + ), +]; diff --git a/test/dune b/test/dune index 832c9689f2..12c177c749 100644 --- a/test/dune +++ b/test/dune @@ -5,4 +5,4 @@ (libraries haz3lcore alcotest junit junit_alcotest) (modes js) (preprocess - (pps js_of_ocaml-ppx))) + (pps js_of_ocaml-ppx ppx_deriving.show))) diff --git a/test/haz3ltest.re b/test/haz3ltest.re index e405fba7b8..f1f38fceed 100644 --- a/test/haz3ltest.re +++ b/test/haz3ltest.re @@ -4,6 +4,9 @@ let (suite, _) = run_and_report( ~and_exit=false, "Dynamics", - [("Elaboration", Test_Elaboration.elaboration_tests)], + [ + ("Elaboration", Test_Elaboration.elaboration_tests), + ("LabeledTuple", Test_LabeledTuple.tests), + ], ); Junit.to_file(Junit.make([suite]), "junit_tests.xml"); From 2b1eda81513b6556da16a25cc95f67cd5c9841ba Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sat, 21 Sep 2024 16:03:51 -0400 Subject: [PATCH 030/108] I got some version of elaboration working --- src/haz3lcore/LabeledTuple.re | 86 ++++++++++++++-------------- src/haz3lcore/dynamics/Elaborator.re | 38 ++++++------ src/haz3lcore/lang/term/Typ.re | 38 +++++------- 3 files changed, 76 insertions(+), 86 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 96cb731c50..ae4d81ee1e 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -163,49 +163,49 @@ let rec rearrange2: | None => remaining }; }; - print_endline("================"); - print_endline("l1: " ++ [%derive.show: list(option(string))](l1)); - Option.iter( - sa => - print_endline( - "l2: [" - ++ String.concat( - ",", - List.map( - l2e => - "(" - ++ [%derive.show: option(string)](fst(l2e)) - ++ "," - ++ sa(snd(l2e)) - ++ ")", - l2, - ), - ) - ++ "]", - ), - show_b, - ); - Option.iter( - sa => - print_endline( - "returnable: [" - ++ String.concat( - ",", - List.map( - l2e => - "(" - ++ [%derive.show: option(string)](fst(l2e)) - ++ "," - ++ sa(snd(l2e)) - ++ ")", - returnable, - ), - ) - ++ "]", - ), - show_b, - ); - print_endline("================"); + // print_endline("================"); + // print_endline("l1: " ++ [%derive.show: list(option(string))](l1)); + // Option.iter( + // sa => + // print_endline( + // "l2: [" + // ++ String.concat( + // ",", + // List.map( + // l2e => + // "(" + // ++ [%derive.show: option(string)](fst(l2e)) + // ++ "," + // ++ sa(snd(l2e)) + // ++ ")", + // l2, + // ), + // ) + // ++ "]", + // ), + // show_b, + // ); + // Option.iter( + // sa => + // print_endline( + // "returnable: [" + // ++ String.concat( + // ",", + // List.map( + // l2e => + // "(" + // ++ [%derive.show: option(string)](fst(l2e)) + // ++ "," + // ++ sa(snd(l2e)) + // ++ ")", + // returnable, + // ), + // ) + // ++ "]", + // ), + // show_b, + // ); + // print_endline("================"); returnable; }; diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index d9e673cd28..48b771e20d 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -325,26 +325,28 @@ let rec elaborate = print_endline("dhexp: " ++ DHExp.show(foo)); foo; | Tuple(es) => - let (ds: list(DHExp.t), tys: list(Typ.t)) = + let (ds, tys) = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; - print_endline("ds: " ++ [%derive.show: list(DHExp.t)](ds)); - print_endline("tys: " ++ [%derive.show: list(Typ.t)](tys)); - let foos = - Typ.matched_prod( - ~show_a=DHExp.show, - ctx, - ds, - DHExp.get_label, - elaborated_type, - ); - print_endline("foos: " ++ [%derive.show: list(Typ.t)](foos)); - let ds = - LabeledTuple.rearrange( - Typ.get_label, Exp.get_label, foos, ds, (name, p) => - TupLabel(Label(name) |> Exp.fresh, p) |> Exp.fresh - ); + print_endline("ds: " ++ [%derive.show: list(DHExp.t)] (ds)); + let (expected_labels : list(option(string))) = Typ.get_labels(ctx, elaborated_type); + let (elaborated_labeled : list((option(string), DHExp.t))) = List.map(exp => { + switch(DHExp.term_of(exp)) { + | TupLabel({term: Label(l), _}, exp) => (Some(l), exp) + | _ => (None, exp) + } + }, ds); + print_endline("elaborated_labeled: " ++ [%derive.show: list((option(string), DHExp.t))] (elaborated_labeled)); + let (reordered : list((option(string), DHExp.t))) = LabeledTuple.rearrange2(expected_labels, elaborated_labeled); + + let (ds : list(DHExp.t)) = + List.map(((optional_label, exp : DHExp.t)) => { + switch(optional_label) { + | Some(label) => Exp.TupLabel(Label(label) |> Exp.fresh, exp) |> Exp.fresh + | None => exp + }; + }, reordered); Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); - | Dot(e1, e2) => + | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); let (e2, ty2) = elaborate(m, e2); let ty = diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index f20ee3370e..b6eecfb0d7 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -463,11 +463,19 @@ let matched_label = (ctx, ty) => | _ => (Unknown(Internal) |> temp, ty) }; +let rec get_labels = (ctx, ty): list(option(string)) => { + let ty = weak_head_normalize(ctx, ty); + switch (term_of(ty)) { + | Parens(ty) => get_labels(ctx, ty) + | Prod(tys) => List.map(x =>Option.map(fst, get_label(x)), tys) + | _ => [] + }; +}; + let rec matched_prod_strict: - 'a 'b. + 'a. ( ~show_a: 'a => string=?, - ~show_b: 'b => string=?, Ctx.t, list('a), 'a => option((string, 'a)), @@ -475,30 +483,16 @@ let rec matched_prod_strict: ) => option(list(t)) = - (~show_a=?, ~show_b=?, ctx: Ctx.t, ts, get_label_ts, ty: t) => { - let _ = show_b; + (~show_a=?, ctx: Ctx.t, ts, get_label_ts : 'a => option((string, 'a)), ty: t) => { let normalized: term = term_of(weak_head_normalize(ctx, ty)); print_endline("normalized: " ++ show_term(normalized)); switch (normalized) { - | Parens(ty) => - matched_prod_strict(~show_a?, ~show_b?, ctx, ts, get_label_ts, ty) + | Parens(ty) => matched_prod_strict(~show_a?, ctx, ts, get_label_ts, ty) | Prod(tys: list(t)) => if (List.length(ts) != List.length(tys)) { None; } else { - let foo: t => option((string, t)) = get_label; - let get_label_ts2: 'a => option((string, 'a)) = get_label_ts; - let baz: list('a) = - LabeledTuple.rearrange( - foo, - get_label_ts2, - tys, - ts, - (_name, b) => { - let returnable: 'a = b; - returnable; - }, - ); + let bar: option(list(t)) = Some( LabeledTuple.rearrange( @@ -506,12 +500,6 @@ let rec matched_prod_strict: TupLabel(Label(name) |> temp, b) |> temp ), ); - - Option.iter( - sa => - print_endline("baz: " ++ String.concat(",", List.map(sa, baz))), - show_a, - ); bar; } | Unknown(SynSwitch) => From 2be5a469d3d24791d3585f1670c58634b5c015d3 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sat, 21 Sep 2024 16:21:58 -0400 Subject: [PATCH 031/108] Fix formatting --- src/haz3lcore/dynamics/Elaborator.re | 49 ++++++++++++++++++---------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 48b771e20d..6466452ace 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -327,26 +327,41 @@ let rec elaborate = | Tuple(es) => let (ds, tys) = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; - print_endline("ds: " ++ [%derive.show: list(DHExp.t)] (ds)); - let (expected_labels : list(option(string))) = Typ.get_labels(ctx, elaborated_type); - let (elaborated_labeled : list((option(string), DHExp.t))) = List.map(exp => { - switch(DHExp.term_of(exp)) { - | TupLabel({term: Label(l), _}, exp) => (Some(l), exp) - | _ => (None, exp) - } - }, ds); - print_endline("elaborated_labeled: " ++ [%derive.show: list((option(string), DHExp.t))] (elaborated_labeled)); - let (reordered : list((option(string), DHExp.t))) = LabeledTuple.rearrange2(expected_labels, elaborated_labeled); + print_endline("ds: " ++ [%derive.show: list(DHExp.t)](ds)); + let expected_labels: list(option(string)) = + Typ.get_labels(ctx, elaborated_type); + let elaborated_labeled: list((option(string), DHExp.t)) = + List.map( + exp => { + switch (DHExp.term_of(exp)) { + | TupLabel({term: Label(l), _}, exp) => (Some(l), exp) + | _ => (None, exp) + } + }, + ds, + ); + print_endline( + "elaborated_labeled: " + ++ [%derive.show: list((option(string), DHExp.t))]( + elaborated_labeled, + ), + ); + let reordered: list((option(string), DHExp.t)) = + LabeledTuple.rearrange2(expected_labels, elaborated_labeled); - let (ds : list(DHExp.t)) = - List.map(((optional_label, exp : DHExp.t)) => { - switch(optional_label) { - | Some(label) => Exp.TupLabel(Label(label) |> Exp.fresh, exp) |> Exp.fresh + let ds: list(DHExp.t) = + List.map( + ((optional_label, exp: DHExp.t)) => { + switch (optional_label) { + | Some(label) => + Exp.TupLabel(Label(label) |> Exp.fresh, exp) |> Exp.fresh | None => exp - }; - }, reordered); + } + }, + reordered, + ); Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); - | Dot(e1, e2) => + | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); let (e2, ty2) = elaborate(m, e2); let ty = From f7a2666b801720e53b71b67664f860c17d1413b6 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 23 Sep 2024 10:06:29 -0400 Subject: [PATCH 032/108] Cleanup --- src/haz3lcore/lang/term/Typ.re | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index b6eecfb0d7..2f4a3788b5 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -467,32 +467,24 @@ let rec get_labels = (ctx, ty): list(option(string)) => { let ty = weak_head_normalize(ctx, ty); switch (term_of(ty)) { | Parens(ty) => get_labels(ctx, ty) - | Prod(tys) => List.map(x =>Option.map(fst, get_label(x)), tys) + | Prod(tys) => List.map(x => Option.map(fst, get_label(x)), tys) | _ => [] }; }; let rec matched_prod_strict: 'a. - ( - ~show_a: 'a => string=?, - Ctx.t, - list('a), - 'a => option((string, 'a)), - t - ) => - option(list(t)) + (Ctx.t, list('a), 'a => option((string, 'a)), t) => option(list(t)) = - (~show_a=?, ctx: Ctx.t, ts, get_label_ts : 'a => option((string, 'a)), ty: t) => { + (ctx: Ctx.t, ts, get_label_ts: 'a => option((string, 'a)), ty: t) => { let normalized: term = term_of(weak_head_normalize(ctx, ty)); print_endline("normalized: " ++ show_term(normalized)); switch (normalized) { - | Parens(ty) => matched_prod_strict(~show_a?, ctx, ts, get_label_ts, ty) + | Parens(ty) => matched_prod_strict(ctx, ts, get_label_ts, ty) | Prod(tys: list(t)) => if (List.length(ts) != List.length(tys)) { None; } else { - let bar: option(list(t)) = Some( LabeledTuple.rearrange( @@ -510,14 +502,13 @@ let rec matched_prod_strict: let matched_prod = ( - ~show_a: option('a => string)=?, ctx: Ctx.t, ts: list('a), get_label_ts: 'a => option((string, 'a)), ty: t, ) : list(t) => - matched_prod_strict(~show_a?, ctx, ts, get_label_ts, ty) + matched_prod_strict(ctx, ts, get_label_ts, ty) |> Option.value( ~default=List.init(List.length(ts), _ => Unknown(Internal) |> temp), ); From a2c34dfa6e46aac7abacffe52743b79f1434c9d9 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 23 Sep 2024 10:07:26 -0400 Subject: [PATCH 033/108] Revert makefile changes --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d6f0004181..c1f5943d07 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,7 @@ fmt: dune fmt --auto-promote watch: setup-instructor - dune build --profile dev --watch + dune build @src/fmt --auto-promote src --profile dev --watch watch-release: setup-instructor dune build @src/fmt --auto-promote src --profile release --watch From 50536fed92eccf4a6eee3777a5f257d0238f68ef Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 23 Sep 2024 10:11:56 -0400 Subject: [PATCH 034/108] Cleanup debugging code --- src/haz3lcore/LabeledTuple.re | 125 ++++++++------------------- src/haz3lcore/dynamics/Elaborator.re | 27 +++--- src/haz3lcore/statics/Statics.re | 4 +- 3 files changed, 50 insertions(+), 106 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index ae4d81ee1e..39e06a6525 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -75,6 +75,7 @@ let validate_uniqueness: results; }; +// TODO Just change t to label in the definition and consider adding a t = (option(label), 'a) type label = t; let seperate_labeled = (xs: list((option(label), 'a))) => { List.partition_map( @@ -108,43 +109,21 @@ let rec rearrange2: let l2_labels = List.filter_map(fst, l2); let common_labels = intersect(l1_labels, l2_labels); - let returnable = - switch (l1, l2) { - | ([], _) => l2 - | (_, []) => [] - | ([Some(expected_label), ...remaining_expectations], remaining) => - let maybe_found = List.assoc_opt(Some(expected_label), remaining); + switch (l1, l2) { + | ([], _) => l2 + | (_, []) => [] + | ([Some(expected_label), ...remaining_expectations], remaining) => + let maybe_found = List.assoc_opt(Some(expected_label), remaining); - switch (maybe_found) { - | Some(found) => - [(Some(expected_label), found)] - @ rearrange2( - ~show_b?, - remaining_expectations, - List.remove_assoc(Some(expected_label), remaining), - ) - | None => - let ( - pre: list((option(label), 'b)), - current: option((option(label), 'b)), - post: list((option(label), 'b)), - ) = - ListUtil.split(remaining, ((label: option(label), _)) => { - switch (label) { - | Some(label) => !List.mem(label, common_labels) - | None => true - } - }); - - switch (current) { - | Some((_existing_label, b)) => - [(Some(expected_label), b)] - @ rearrange2(~show_b?, remaining_expectations, pre @ post) - | None => remaining - }; - }; - | ([None, ...remaining_expectations], remaining) => - // Pick the first one that's not in common labels and then keep the rest in remaining + switch (maybe_found) { + | Some(found) => + [(Some(expected_label), found)] + @ rearrange2( + ~show_b?, + remaining_expectations, + List.remove_assoc(Some(expected_label), remaining), + ) + | None => let ( pre: list((option(label), 'b)), current: option((option(label), 'b)), @@ -156,58 +135,34 @@ let rec rearrange2: | None => true } }); + switch (current) { | Some((_existing_label, b)) => - [(None, b)] + [(Some(expected_label), b)] @ rearrange2(~show_b?, remaining_expectations, pre @ post) | None => remaining }; }; - // print_endline("================"); - // print_endline("l1: " ++ [%derive.show: list(option(string))](l1)); - // Option.iter( - // sa => - // print_endline( - // "l2: [" - // ++ String.concat( - // ",", - // List.map( - // l2e => - // "(" - // ++ [%derive.show: option(string)](fst(l2e)) - // ++ "," - // ++ sa(snd(l2e)) - // ++ ")", - // l2, - // ), - // ) - // ++ "]", - // ), - // show_b, - // ); - // Option.iter( - // sa => - // print_endline( - // "returnable: [" - // ++ String.concat( - // ",", - // List.map( - // l2e => - // "(" - // ++ [%derive.show: option(string)](fst(l2e)) - // ++ "," - // ++ sa(snd(l2e)) - // ++ ")", - // returnable, - // ), - // ) - // ++ "]", - // ), - // show_b, - // ); - // print_endline("================"); - - returnable; + | ([None, ...remaining_expectations], remaining) => + // Pick the first one that's not in common labels and then keep the rest in remaining + let ( + pre: list((option(label), 'b)), + current: option((option(label), 'b)), + post: list((option(label), 'b)), + ) = + ListUtil.split(remaining, ((label: option(label), _)) => { + switch (label) { + | Some(label) => !List.mem(label, common_labels) + | None => true + } + }); + switch (current) { + | Some((_existing_label, b)) => + [(None, b)] + @ rearrange2(~show_b?, remaining_expectations, pre @ post) + | None => remaining + }; + }; }; // Assumes all labels are unique @@ -219,8 +174,6 @@ let rec rearrange2: let rearrange: 'a 'b. ( - ~show_a: 'a => string=?, - ~show_b: 'b => string=?, 'a => option((t, 'a)), 'b => option((t, 'b)), list('a), @@ -229,9 +182,7 @@ let rearrange: ) => list('b) = - (~show_a=?, ~show_b=?, get_label1, get_label2, l1, l2, constructor) => { - let _ = show_b; - let _ = show_a; + (get_label1, get_label2, l1, l2, constructor) => { // TODO: Error handling in case of bad arguments let (_, l1_lab, _) = validate_uniqueness(get_label1, l1); let (_, l2_lab, _) = validate_uniqueness(get_label2, l2); diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 6466452ace..7b7110cb28 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -307,23 +307,18 @@ let rec elaborate = | TupLabel(label, e) => let (label', labty) = elaborate(m, label); let (e', ety) = elaborate(m, e); - let foo = - if (in_container) { - Exp.TupLabel(label', e') - |> rewrap - |> cast_from(Typ.TupLabel(labty, ety) |> Typ.temp); - } else { - Tuple([Exp.TupLabel(label', e') |> rewrap]) - |> Exp.fresh - |> cast_from( - Typ.Prod([Typ.TupLabel(labty, ety) |> Typ.temp]) |> Typ.temp, - ); - }; + if (in_container) { + Exp.TupLabel(label', e') + |> rewrap + |> cast_from(Typ.TupLabel(labty, ety) |> Typ.temp); + } else { + Tuple([Exp.TupLabel(label', e') |> rewrap]) + |> Exp.fresh + |> cast_from( + Typ.Prod([Typ.TupLabel(labty, ety) |> Typ.temp]) |> Typ.temp, + ); + }; - print_endline("exp: " ++ UExp.show(uexp)); - print_endline("typ: " ++ Typ.show(elaborated_type)); - print_endline("dhexp: " ++ DHExp.show(foo)); - foo; | Tuple(es) => let (ds, tys) = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 8369f70405..45e3d27dcf 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -329,9 +329,7 @@ and uexp_to_info_map = m, ) | Tuple(es) => - let filt = (y: UExp.t): option((string, UExp.t)) => UExp.get_label(y); - let elems = es; - let modes = Mode.of_prod(ctx, mode, elems, filt); + let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); let (es, m) = map_m_go(m, modes, es, ~is_contained=true); add( ~self=Just(Prod(List.map(Info.exp_ty, es)) |> Typ.temp), From 4226bb4e965ab91420802821224d9ec48ff2b578 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 23 Sep 2024 10:16:19 -0400 Subject: [PATCH 035/108] More cleanup --- src/haz3lcore/dynamics/Elaborator.re | 9 ++------- src/haz3lcore/lang/term/IdTagged.re | 9 +++++---- src/haz3lcore/statics/Statics.re | 2 +- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 7b7110cb28..63e30e190c 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -322,7 +322,7 @@ let rec elaborate = | Tuple(es) => let (ds, tys) = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; - print_endline("ds: " ++ [%derive.show: list(DHExp.t)](ds)); + let expected_labels: list(option(string)) = Typ.get_labels(ctx, elaborated_type); let elaborated_labeled: list((option(string), DHExp.t)) = @@ -335,12 +335,7 @@ let rec elaborate = }, ds, ); - print_endline( - "elaborated_labeled: " - ++ [%derive.show: list((option(string), DHExp.t))]( - elaborated_labeled, - ), - ); + let reordered: list((option(string), DHExp.t)) = LabeledTuple.rearrange2(expected_labels, elaborated_labeled); diff --git a/src/haz3lcore/lang/term/IdTagged.re b/src/haz3lcore/lang/term/IdTagged.re index ad71087d56..9874567881 100644 --- a/src/haz3lcore/lang/term/IdTagged.re +++ b/src/haz3lcore/lang/term/IdTagged.re @@ -14,10 +14,11 @@ type t('a) = { term: 'a, }; -let pp: ((Format.formatter, 'a) => unit, Format.formatter, t('a)) => unit = - (fmt_a, formatter, ta) => { - fmt_a(formatter, ta.term); - }; +// To be used if you want to remove the id from the debug output +// let pp: ((Format.formatter, 'a) => unit, Format.formatter, t('a)) => unit = +// (fmt_a, formatter, ta) => { +// fmt_a(formatter, ta.term); +// }; let fresh = term => { let _x: ((Format.formatter, 'a) => unit, t('a)) => string = show; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 45e3d27dcf..87fdccd95d 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -329,7 +329,7 @@ and uexp_to_info_map = m, ) | Tuple(es) => - let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); + let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); let (es, m) = map_m_go(m, modes, es, ~is_contained=true); add( ~self=Just(Prod(List.map(Info.exp_ty, es)) |> Typ.temp), From 8eef13c29096db8e0ca7a66c8340ddc6237bb411 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 23 Sep 2024 11:45:05 -0400 Subject: [PATCH 036/108] Got a version of evaluation to work Co-authored-by: Matthew Keenan --- src/haz3lcore/dynamics/Transition.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index 5b992268a6..f63c1eb89a 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -678,9 +678,9 @@ module Transition = (EV: EV_MODE) => { | Dot(d1, d2) => let. _ = otherwise(env, (d1, d2) => Dot(d1, d2) |> rewrap) and. d1' = - req_value(req(state, env), d1 => Dot1(d1, d2) |> wrap_ctx, d1) + req_final(req(state, env), d1 => Dot1(d1, d2) |> wrap_ctx, d1) and. d2' = - req_value(req(state, env), d2 => Dot2(d1, d2) |> wrap_ctx, d2); + req_final(req(state, env), d2 => Dot2(d1, d2) |> wrap_ctx, d2); // TODO: Holes and other cases handled? switch (DHExp.term_of(d1'), DHExp.term_of(d2')) { | (Tuple(ds), Var(name)) => From 998caebea4b1492cde55e15294b15acbd267317a Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 27 Sep 2024 11:34:46 -0400 Subject: [PATCH 037/108] Stop elaborating labels in Dot --- src/haz3lcore/dynamics/Elaborator.re | 8 +++++--- src/haz3lcore/dynamics/Transition.re | 8 +------- src/haz3lcore/lang/term/Typ.re | 4 +--- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 63e30e190c..088a4f0430 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -351,11 +351,13 @@ let rec elaborate = reordered, ); Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); + | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); - let (e2, ty2) = elaborate(m, e2); + // I don't think we need to elaborate labels + // let (e2, ty2) = elaborate(m, e2); let ty = - switch (ty1.term, ty2.term) { + switch (Typ.weak_head_normalize(ctx, ty1).term, e2.term) { | (Prod(tys), Var(name)) => let element = LabeledTuple.find_label(Typ.get_label, tys, name); switch (element) { @@ -363,7 +365,7 @@ let rec elaborate = | _ => Unknown(Internal) |> Typ.temp }; | (TupLabel(_, ty), Var(name)) - when LabeledTuple.equal(Typ.get_label(ty1), Some((name, ty2))) => ty + when LabeledTuple.equal(Typ.get_label(ty1), Some((name, e2))) => ty | _ => Unknown(Internal) |> Typ.temp }; // How to freshcast this? diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index f63c1eb89a..a677214439 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -720,13 +720,7 @@ module Transition = (EV: EV_MODE) => { kind: CastAp, is_value: false, }); - | _ => - Step({ - expr: Dot(d1', d2') |> fresh, - state_update, - kind: Dot, - is_value: false, - }) + | _ => raise(EvaluatorError.Exception(BadPatternMatch)) }; | TupLabel(label, d1) => // TODO (Anthony): Fix this if needed diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index 2f4a3788b5..acd15c0db8 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -477,9 +477,7 @@ let rec matched_prod_strict: (Ctx.t, list('a), 'a => option((string, 'a)), t) => option(list(t)) = (ctx: Ctx.t, ts, get_label_ts: 'a => option((string, 'a)), ty: t) => { - let normalized: term = term_of(weak_head_normalize(ctx, ty)); - print_endline("normalized: " ++ show_term(normalized)); - switch (normalized) { + switch (term_of(weak_head_normalize(ctx, ty))) { | Parens(ty) => matched_prod_strict(ctx, ts, get_label_ts, ty) | Prod(tys: list(t)) => if (List.length(ts) != List.length(tys)) { From 000b853e6f9c49ecbd79483d763e9d3634a24bf5 Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 27 Sep 2024 12:43:18 -0400 Subject: [PATCH 038/108] updates to elaboration, label extraction, ap in progress --- src/haz3lcore/dynamics/DHPat.re | 3 +- src/haz3lcore/dynamics/Elaborator.re | 49 ++++++++++++---- src/haz3lcore/dynamics/PatternMatch.re | 4 +- src/haz3lcore/dynamics/Transition.re | 64 +++++++++++++-------- src/haz3lcore/dynamics/TypeAssignment.re | 5 +- src/haz3lcore/lang/term/Typ.re | 46 +++++++++------ src/haz3lcore/statics/Mode.re | 10 +++- src/haz3lcore/statics/Statics.re | 71 ++++++++++++++++++------ src/haz3lcore/statics/Term.re | 6 +- 9 files changed, 179 insertions(+), 79 deletions(-) diff --git a/src/haz3lcore/dynamics/DHPat.re b/src/haz3lcore/dynamics/DHPat.re index 48361b87c8..4639af4554 100644 --- a/src/haz3lcore/dynamics/DHPat.re +++ b/src/haz3lcore/dynamics/DHPat.re @@ -57,9 +57,10 @@ let rec bound_vars = (dp: t): list(Var.t) => | Ap(_, dp1) => bound_vars(dp1) }; -let get_label: t => option((LabeledTuple.t, t)) = +let rec get_label: t => option((LabeledTuple.t, t)) = dp => switch (dp |> term_of) { + | Parens(dp) => get_label(dp) | TupLabel({term: Label(name), _}, t') => Some((name, t')) | _ => None }; diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 66dc1e334d..c5f832f67f 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -234,8 +234,6 @@ let rec elaborate = (m: Statics.Map.t, uexp: UExp.t, in_container: bool) : (DHExp.t, Typ.t) => { let (elaborated_type, ctx, co_ctx) = elaborated_type(m, uexp); - print_endline("exp: " ++ UExp.show(uexp)); - print_endline("typ: " ++ Typ.show(elaborated_type)); let elaborate = (~in_container=false, m, uexp) => elaborate(m, uexp, in_container); let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); @@ -323,28 +321,36 @@ let rec elaborate = | Tuple(es) => let (ds, tys) = List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; + let elab_typ_list = + switch (Typ.weak_head_normalize(ctx, elaborated_type).term) { + | Prod(tys) => tys + | _ => tys + }; let ds = LabeledTuple.rearrange( - Typ.get_label, Exp.get_label, tys, ds, (name, p) => + Typ.get_label, Exp.get_label, elab_typ_list, ds, (name, p) => TupLabel(Label(name) |> Exp.fresh, p) |> Exp.fresh ); Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); - let (e2, ty2) = elaborate(m, e2); - let ty = - switch (ty1.term, ty2.term) { + let (e2, _) = elaborate(m, e2); + let (e1, ty) = + switch (Typ.weak_head_normalize(ctx, ty1).term, e2.term) { | (Prod(tys), Var(name)) => let element = LabeledTuple.find_label(Typ.get_label, tys, name); switch (element) { - | Some({term: TupLabel(_, ty), _}) => ty - | _ => Unknown(Internal) |> Typ.temp + | Some({term: TupLabel(_, ty), _}) => (e1, ty) + | _ => (e1, Unknown(Internal) |> Typ.temp) }; | (TupLabel(_, ty), Var(name)) - when LabeledTuple.equal(Typ.get_label(ty1), Some((name, ty2))) => ty - | _ => Unknown(Internal) |> Typ.temp + when LabeledTuple.equal(Typ.get_label(ty1), Some((name, e2))) => ( + e1, + ty, + ) + | _ => (e1, Unknown(Internal) |> Typ.temp) }; - // How to freshcast this? + // Freshcast this, if necessary? Exp.Dot(e1, e2) |> rewrap |> cast_from(ty); | Var(v) => uexp @@ -414,13 +420,32 @@ let rec elaborate = let (a', tya) = elaborate(m, a); let (tyf1, tyf2) = Typ.matched_arrow(ctx, tyf); let f'' = fresh_cast(f', tyf, Arrow(tyf1, tyf2) |> Typ.temp); + // In case of singleton tuple for fun ty_in, implicitly convert arg if necessary + // TODO: Is needed for other Aps? + let rec get_args = (a, tya, tyf1) => + switch ( + Typ.weak_head_normalize(ctx, tya).term, + Typ.weak_head_normalize(ctx, tyf1).term, + ) { + | (Parens(tya), _) => get_args(a, tya, tyf1) + | (Prod(_), Prod(_)) => (a, tya) + | (_, Prod([{term: TupLabel(_), _}])) => ( + Tuple([a']) |> Exp.fresh, + Prod([tya]) |> Typ.temp, + ) + | (_, _) => (a, tya) + }; + let (a', tya) = get_args(a', tya, tyf1); let a'' = fresh_cast(a', tya, tyf1); Exp.Ap(dir, f'', a'') |> rewrap |> cast_from(tyf2); | DeferredAp(f, args) => let (f', tyf) = elaborate(m, f); let (args', tys) = List.map(elaborate(m), args) |> ListUtil.unzip; let (tyf1, tyf2) = Typ.matched_arrow(ctx, tyf); - let ty_fargs = Typ.matched_prod(ctx, args, Exp.get_label, tyf1); + let (args, ty_fargs) = + Typ.matched_prod(ctx, args, Exp.get_label, tyf1, (name, b) => + TupLabel(Label(name) |> Exp.fresh, b) |> Exp.fresh + ); let f'' = fresh_cast( f', diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index 23a45900f3..b8d6f3f9fc 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -33,8 +33,8 @@ let rec matches = (dp: Pat.t, d: DHExp.t): match_result => | Label(name) => let* name' = Unboxing.unbox(Label, d); name == name' ? Matches(Environment.empty) : DoesNotMatch; - | TupLabel(label, x) => - let* x' = Unboxing.unbox(TupLabel(label), d); + | TupLabel(_, x) => + let* x' = Unboxing.unbox(TupLabel(dp), d); matches(x, x'); | ListLit(xs) => let* s' = Unboxing.unbox(List, d); diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index 5b992268a6..e3abf28d9f 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -162,6 +162,7 @@ module Transition = (EV: EV_MODE) => { // Split DHExp into term and id information let (term, rewrap) = DHExp.unwrap(d); let wrap_ctx = (term): EvalCtx.t => Term({term, ids: [rep_id(d)]}); + // print_endline(Exp.show(d)); // Transition rules switch (term) { @@ -363,18 +364,35 @@ module Transition = (EV: EV_MODE) => { args, ); Tuple(labeled_args) |> DHPat.fresh; + // | TupLabel(_, _) => Tuple([dp]) |> DHPat.fresh + // | Var(name) => + // Tuple([ + // TupLabel(DHPat.Label(name) |> DHPat.fresh, dp) |> DHPat.fresh, + // ]) + // |> DHPat.fresh | _ => dp }; // TODO: Probably not the right way to deal with casts // let d2' = - // switch (DHPat.term_of(d2'), DHPat.term_of(dp)) { + // switch (d2'.term, DHPat.term_of(dp)) { // | (Tuple(_), Tuple(_)) => d2' - // | (Cast(Tuple(_), _, Prod(_)), Tuple(_)) => d2' - // | (Cast(d, Prod(t1), Prod(t2)), Tuple(_)) => - // Cast(Tuple([d]), Prod(t1), Prod(t2)) - // | (Cast(d, t1, Prod(t2)), Tuple(_)) => - // Cast(Tuple([d]), Prod([t1]), Prod(t2)) - // | (_, Tuple([TupLabel(_)])) => Tuple([d2']) + // | (Cast({term: Tuple(_), _}, _, {term: Prod(_), _}), Tuple(_)) => d2' + // | (Cast(d, {term: Prod(t1), _}, {term: Prod(t2), _}), Tuple(_)) => + // Cast( + // Tuple([d]) |> DHExp.fresh, + // Prod(t1) |> Typ.temp, + // Prod(t2) |> Typ.temp, + // ) + // |> DHExp.fresh + // | (Cast(d, t1, {term: Prod(t2), _}), Tuple(_)) => + // Cast( + // Tuple([d]) |> DHExp.fresh, + // Prod([t1]) |> Typ.temp, + // Prod(t2) |> Typ.temp, + // ) + // |> DHExp.fresh + // | (_, Tuple([{term: TupLabel(_), _}])) => + // Tuple([d2']) |> DHExp.fresh // | (_, _) => d2' // }; let.match env'' = (env', matches(dp, d2')); @@ -676,34 +694,40 @@ module Transition = (EV: EV_MODE) => { is_value: true, }); | Dot(d1, d2) => - let. _ = otherwise(env, (d1, d2) => Dot(d1, d2) |> rewrap) + let. _ = otherwise(env, d2 => Dot(d1, d2) |> rewrap) and. d1' = - req_value(req(state, env), d1 => Dot1(d1, d2) |> wrap_ctx, d1) - and. d2' = - req_value(req(state, env), d2 => Dot2(d1, d2) |> wrap_ctx, d2); + req_final(req(state, env), d1 => Dot1(d1, d2) |> wrap_ctx, d1); // TODO: Holes and other cases handled? - switch (DHExp.term_of(d1'), DHExp.term_of(d2')) { + switch (DHExp.term_of(d1'), DHExp.term_of(d2)) { | (Tuple(ds), Var(name)) => Step({ expr: - // let element = LabeledTuple.find_label(DHExp.get_label, ds, name); switch (LabeledTuple.find_label(DHExp.get_label, ds, name)) { | Some({term: TupLabel(_, exp), _}) => exp - // TODO (Anthony): operate on casts instead of the original tuple, like static checking. - | _ => raise(EvaluatorError.Exception(BadPatternMatch)) + | _ => Undefined |> DHExp.fresh }, state_update, kind: Dot, is_value: false, }) | (_, Cast(d2', ty, ty')) => + // TODO: Probably not right Step({ expr: Cast(Dot(d1, d2') |> fresh, ty, ty') |> fresh, state_update, kind: CastAp, is_value: false, }) - | (Cast(d3', {term: Prod(ts), _}, {term: Prod(ts'), _}), Var(name)) => + | (Cast(d3', t2, t3), Var(name)) => + // TODO: doen't work because you get to a cast(1, Unknown, Int) which is Indet + let rec get_typs = (t2, t3) => + switch (Typ.term_of(t2), Typ.term_of(t3)) { + | (Prod(ts), Prod(ts')) => (ts, ts') + | (Parens(t2), _) => get_typs(t2, t3) + | (_, Parens(t3)) => get_typs(t2, t3) + | (_, _) => ([], []) + }; + let (ts, ts') = get_typs(t2, t3); let ty = switch (LabeledTuple.find_label(Typ.get_label, ts, name)) { | Some({term: TupLabel(_, ty), _}) => ty @@ -720,13 +744,7 @@ module Transition = (EV: EV_MODE) => { kind: CastAp, is_value: false, }); - | _ => - Step({ - expr: Dot(d1', d2') |> fresh, - state_update, - kind: Dot, - is_value: false, - }) + | _ => Indet }; | TupLabel(label, d1) => // TODO (Anthony): Fix this if needed diff --git a/src/haz3lcore/dynamics/TypeAssignment.re b/src/haz3lcore/dynamics/TypeAssignment.re index b404e612b1..40f91f172a 100644 --- a/src/haz3lcore/dynamics/TypeAssignment.re +++ b/src/haz3lcore/dynamics/TypeAssignment.re @@ -54,7 +54,10 @@ let dhpat_extend_ctx = (dhpat: DHPat.t, ty: Typ.t, ctx: Ctx.t): option(Ctx.t) => let entry = Ctx.VarEntry({name, id: Id.invalid, typ: ty}); Some([entry]); | Tuple(l1) => - let* ts = Typ.matched_prod_strict(ctx, l1, Pat.get_label, ty); + let (l1, ts) = + Typ.matched_prod(ctx, l1, Pat.get_label, ty, (name, b) => + TupLabel(Label(name) |> Pat.fresh, b) |> Pat.fresh + ); let* l = List.map2((dhp, typ) => {dhpat_var_entry(dhp, typ)}, l1, ts) |> OptUtil.sequence; diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index 5d662a07cb..c599020411 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -159,8 +159,9 @@ let join_type_provenance = | (SynSwitch, SynSwitch) => SynSwitch }; -let get_label = ty => +let rec get_label = ty => switch (term_of(ty)) { + | Parens(ty) => get_label(ty) | TupLabel(label, t') => switch (term_of(label)) { | Label(name) => Some((name, t')) @@ -350,6 +351,10 @@ let rec match_synswitch = (t1: t, t2: t) => { | (Arrow(_), _) => t1 | (Prod(tys1), Prod(tys2)) when List.length(tys1) == List.length(tys2) => // TODO: Rearrange this prod? + let tys1 = + LabeledTuple.rearrange(get_label, get_label, tys1, tys2, (t, x) => + TupLabel(Label(t) |> temp, x) |> temp + ); let tys = List.map2(match_synswitch, tys1, tys2); Prod(tys) |> rewrap1; | (Prod(_), _) => t1 @@ -463,29 +468,36 @@ let matched_label = (ctx, ty) => | _ => (Unknown(Internal) |> temp, ty) }; -let rec matched_prod_strict = (ctx, ts, get_label_ts, ty) => +let rec matched_prod_strict = (ctx, es, get_label_es, ty, constructor) => switch (term_of(weak_head_normalize(ctx, ty))) { - | Parens(ty) => matched_prod_strict(ctx, ts, get_label_ts, ty) + | Parens(ty) => matched_prod_strict(ctx, es, get_label_es, ty, constructor) | Prod(tys) => - if (List.length(ts) != List.length(tys)) { - None; + if (List.length(es) != List.length(tys)) { + (es, None); } else { - Some( - LabeledTuple.rearrange(get_label_ts, get_label, ts, tys, (name, b) => - TupLabel(Label(name) |> temp, b) |> temp - ), + ( + LabeledTuple.rearrange(get_label, get_label_es, tys, es, constructor), + Some(tys), ); } - | Unknown(SynSwitch) => - Some(List.init(List.length(ts), _ => Unknown(SynSwitch) |> temp)) - | _ => None + | Unknown(SynSwitch) => ( + es, + Some(List.init(List.length(es), _ => Unknown(SynSwitch) |> temp)), + ) + | _ => (es, None) }; -let matched_prod = (ctx, ts, get_label_ts, ty) => - matched_prod_strict(ctx, ts, get_label_ts, ty) - |> Option.value( - ~default=List.init(List.length(ts), _ => Unknown(Internal) |> temp), - ); +let matched_prod = (ctx, es, get_label_es, ty, constructor) => { + let (es, tys_opt) = + matched_prod_strict(ctx, es, get_label_es, ty, constructor); + ( + es, + tys_opt + |> Option.value( + ~default=List.init(List.length(es), _ => Unknown(Internal) |> temp), + ), + ); +}; let rec matched_list_strict = (ctx, ty) => switch (term_of(weak_head_normalize(ctx, ty))) { diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index 8072473a5e..e72fff0a6e 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -70,12 +70,16 @@ let of_label = (ctx: Ctx.t, mode: t): (t, t) => (ana(ty1), ana(ty2)); }; -let of_prod = (ctx: Ctx.t, mode: t, ts: list('a), filt): list(t) => +let of_prod = + (ctx: Ctx.t, mode: t, es: list('a), filt, constructor) + : (list('a), list(t)) => switch (mode) { | Syn | SynFun - | SynTypFun => List.init(List.length(ts), _ => Syn) - | Ana(ty) => ty |> Typ.matched_prod(ctx, ts, filt) |> List.map(ana) + | SynTypFun => (es, List.init(List.length(es), _ => Syn)) + | Ana(ty) => + let (es, tys) = Typ.matched_prod(ctx, es, filt, ty, constructor); + (es, tys |> List.map(ana)); }; let of_cons_hd = (ctx: Ctx.t, mode: t): t => diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 87fdccd95d..81f8ba6eb5 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -189,6 +189,19 @@ and uexp_to_info_map = (info, add_info(ids, InfoExp(info), m)); }; let add = (~self, ~co_ctx, m) => add'(~self=Common(self), ~co_ctx, m); + // add if uexp changed + // let add_exp = (~self, ~co_ctx, ~uexp, m) => { + // let info = + // Info.derived_exp( + // ~uexp, + // ~ctx, + // ~mode, + // ~ancestors, + // ~self=Common(self), + // ~co_ctx, + // ); + // (info, add_info(ids, InfoExp(info), m)); + // }; let ancestors = [UExp.rep_id(uexp)] @ ancestors; let uexp_to_info_map = ( @@ -329,11 +342,14 @@ and uexp_to_info_map = m, ) | Tuple(es) => - let modes = Mode.of_prod(ctx, mode, es, UExp.get_label); - let (es, m) = map_m_go(m, modes, es, ~is_contained=true); + let (es, modes) = + Mode.of_prod(ctx, mode, es, UExp.get_label, (name, b) => + TupLabel(Label(name) |> Exp.fresh, b) |> Exp.fresh + ); + let (es', m) = map_m_go(m, modes, es, ~is_contained=true); add( - ~self=Just(Prod(List.map(Info.exp_ty, es)) |> Typ.temp), - ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es)), + ~self=Just(Prod(List.map(Info.exp_ty, es')) |> Typ.temp), + ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es')), m, ); | Dot(e1, e2) => @@ -378,7 +394,13 @@ and uexp_to_info_map = | Some(typ) => let (body, m) = go'( - ~ctx=[VarEntry({name, id: List.nth(e2.ids, 0), typ})], + ~ctx=[ + VarEntry({ + name, + id: List.nth(e2.ids, 0), + typ: Unknown(Internal) |> Typ.temp, + }), + ], ~mode, e2, m, @@ -422,13 +444,9 @@ and uexp_to_info_map = // In case of singleton tuple for fun ty_in, implicitly convert arg if necessary // TODO: Is needed for TypAp or Deferred Ap? let arg = - switch (arg.term, ty_in.term) { + switch (arg.term, Typ.weak_head_normalize(ctx, ty_in).term) { | (Tuple(_), Prod(_)) => arg - | (_, Prod([{term: TupLabel(_), _}])) => { - ids: arg.ids, - copied: arg.copied, - term: Tuple([arg]), - } + | (_, Prod([{term: TupLabel(_), _}])) => Tuple([arg]) |> Exp.fresh | (_, _) => arg }; let (arg, m) = go(~mode=Ana(ty_in), arg, m); @@ -937,7 +955,10 @@ and upat_to_info_map = ); }; | Tuple(ps) => - let modes = Mode.of_prod(ctx, mode, ps, UPat.get_label); + let (ps, modes) = + Mode.of_prod(ctx, mode, ps, UPat.get_label, (name, b) => + TupLabel(Label(name) |> UPat.fresh, b) |> UPat.fresh + ); let (ctx, tys, cons, m) = ctx_fold(ctx, m, ps, modes, ~is_contained=true); let rec cons_fold_tuple = cs => @@ -982,17 +1003,19 @@ and utyp_to_info_map = ~ctx, ~expects=Info.TypeExpected, ~ancestors, + ~is_contained=false, {ids, term, _} as utyp: UTyp.t, m: Map.t, ) : (Info.typ, Map.t) => { - let add = m => { + let add = (~utyp=utyp, 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); + let go = (~is_contained=false) => + go'(~expects=TypeExpected, ~is_contained); switch (term) { | Unknown(Hole(MultiHole(tms))) => let (_, m) = multi(~ctx, ~ancestors, m, tms); @@ -1013,11 +1036,23 @@ and utyp_to_info_map = let m = go(t2, m) |> snd; add(m); | TupLabel(label, t) => - let m = go(label, m) |> snd; - let m = go(t, m) |> snd; - add(m); + if (is_contained) { + let m = go(label, m) |> snd; + let m = go(t, m) |> snd; + add(m); + } else { + let m = map_m(go(~is_contained=true), [utyp], m) |> snd; + add( + ~utyp={ + term: Prod([utyp.term |> Typ.fresh]), + ids, + copied: utyp.copied, + }, + m, + ); + } | Prod(ts) => - let m = map_m(go, ts, m) |> snd; + let m = map_m(go(~is_contained=true), ts, m) |> snd; add(m); | Ap(t1, t2) => let t1_mode: Info.typ_expects = diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index d89233d40d..26f2642d0a 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -294,9 +294,10 @@ module Pat = { | _ => None }; - let get_label: t => option((LabeledTuple.t, t)) = + let rec get_label: t => option((LabeledTuple.t, t)) = p => switch (p.term) { + | Parens(p) => get_label(p) | TupLabel(plab, p') => switch (plab.term) { | Label(name) => Some((name, p')) @@ -451,9 +452,10 @@ module Exp = { | Match => "Case expression" | Cast => "Cast expression"; - let get_label: t => option((LabeledTuple.t, t)) = + let rec get_label: t => option((LabeledTuple.t, t)) = e => switch (e.term) { + | Parens(e) => get_label(e) | TupLabel(elab, e') => switch (elab.term) { | Label(name) => Some((name, e')) From d5dfa8f5f157c421b276e0d963e44b43bb7282fe Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 27 Sep 2024 15:27:28 -0400 Subject: [PATCH 039/108] cleaned LabeledTuple util file --- src/haz3lcore/LabeledTuple.re | 319 ++++++++------------------------ src/haz3lcore/dynamics/DHPat.re | 2 +- src/haz3lcore/lang/term/Typ.re | 8 +- src/haz3lcore/statics/Term.re | 4 +- 4 files changed, 88 insertions(+), 245 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 39e06a6525..35ebb17f75 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -3,9 +3,9 @@ open Util; exception Exception; [@deriving (show({with_path: false}), sexp, yojson)] -type t = string; +type label = string; -let equal: (option((t, 'a)), option((t, 'b))) => bool = +let equal: (option((label, 'a)), option((label, 'b))) => bool = (left, right) => { switch (left, right) { | (Some((s1, _)), Some((s2, _))) => String.equal(s1, s2) @@ -20,8 +20,10 @@ let compare = String.compare; let find_opt: ('a => bool, list('a)) => option('a) = List.find_opt; // returns a pair containing a list of option(t) and a list of 'a -let seperate_labels: - ('a => option((t, 'a)), list('a)) => (list(option(t)), list('a)) = +// if 'a is a tuplabel, separates the label from the element held by it. +let separate_labels: + ('a => option((label, 'a)), list('a)) => + (list(option(label)), list('a)) = (get_label, es) => { let results = List.fold_left( @@ -36,48 +38,67 @@ let seperate_labels: results; }; -// returns ordered list of (Some(string), TupLabel) -// and another of (None, not-TupLabel) -// TODO: Need to check uniqueness earlier -// TODO: Make more efficient -let validate_uniqueness: - 'a. - ('a => option((t, 'a)), list('a)) => - (bool, list((option(t), 'a)), list('a)) - = +// returns a pair containing a list of option(t) and a list of 'a +// if 'a is a tuplabel, extracts the label but keeps the tuplabel together +let separate_and_keep_labels: + ('a => option((label, 'a)), list('a)) => + (list(option(label)), list('a)) = (get_label, es) => { let results = List.fold_left( - ((b, ls, ns), e) => + ((ls, ns), e) => switch (get_label(e)) { - | Some((s1, _)) - when - b - && List.fold_left( - (v, l) => - switch (l) { - | (Some(s2), _) when v => compare(s1, s2) != 0 - | _ => false - }, - true, - ls, - ) => ( - b, - ls @ [(Some(s1), e)], - ns, - ) - | None => (b, ls, ns @ [e]) - | _ => (false, ls, ns) + | Some((s1, _)) => (ls @ [Some(s1)], ns @ [e]) + | None => (ls @ [None], ns @ [e]) }, - (true, [], []), + ([], []), es, ); results; }; -// TODO Just change t to label in the definition and consider adding a t = (option(label), 'a) -type label = t; -let seperate_labeled = (xs: list((option(label), 'a))) => { +// returns ordered list of (Some(string), TupLabel) +// and another of (None, not-TupLabel) +// TODO: Actually validate uniqueness in statics +// TODO: Make more efficient +// let validate_uniqueness: +// 'a. +// ('a => option((t, 'a)), list('a)) => +// (bool, list((option(t), 'a)), list('a)) +// = +// (get_label, es) => { +// let results = +// List.fold_left( +// ((b, ls, ns), e) => +// switch (get_label(e)) { +// | Some((s1, _)) +// when +// b +// && List.fold_left( +// (v, l) => +// switch (l) { +// | (Some(s2), _) when v => compare(s1, s2) != 0 +// | _ => false +// }, +// true, +// ls, +// ) => ( +// b, +// ls @ [(Some(s1), e)], +// ns, +// ) +// | None => (b, ls, ns @ [e]) +// | _ => (false, ls, ns) +// }, +// (true, [], []), +// es, +// ); +// results; +// }; + +// TODO consider adding a t = (option(label), 'a) + +let separate_labeled = (xs: list((option(label), 'a))) => { List.partition_map( ((l, a)) => switch (l) { @@ -93,6 +114,7 @@ let intersect = (xs, ys) => { List.filter_map(x => List.find_opt((==)(x), ys), xs); }; +// Assumes all labels are unique // Rearranges all the labels in l2 to match the order of the labels in l1. Labels are optional and should me reordered for all present labels first and then unlabled fields matched up pairwise. So labeled fields can be reordered and unlabeled ones can't. Also add labels to the unlabeled. // TODO Handle the unequal length case and extra labels case let rec rearrange2: @@ -165,223 +187,42 @@ let rec rearrange2: }; }; -// Assumes all labels are unique -// filt returns Some(string) if TupLabel or None if not a TupLabel -// returns a permutation of l2 that matches labels in l1 -// other labels are in order, even if not matching. -// 'a types -// 'b expressions +// Basically another way to call rearrange2 using the raw lists, functions to extract labels from TupLabels, and constructor for new TupLabels. +// Maintains the same ids if possible +// TODO: clean up more let rearrange: 'a 'b. ( - 'a => option((t, 'a)), - 'b => option((t, 'b)), + 'a => option((label, 'a)), + 'b => option((label, 'b)), list('a), list('b), - (t, 'b) => 'b + (label, 'b) => 'b ) => list('b) = (get_label1, get_label2, l1, l2, constructor) => { // TODO: Error handling in case of bad arguments - let (_, l1_lab, _) = validate_uniqueness(get_label1, l1); - let (_, l2_lab, _) = validate_uniqueness(get_label2, l2); - - // Second item in the pair is the full tuplabel - let l2_matched: list((option(t), 'b)) = - List.fold_left( - (l2_matched, l1_item) => { - let l2_item = - find_opt( - l2_item => { - switch (l1_item, l2_item) { - | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l2_item) { - | Some(l2_item) => l2_matched @ [l2_item] - | None => l2_matched - }; - }, - [], - l1_lab, - ); - // Second item in the pair is just the element half of the tuplabel - let l2_rem: list((option(t), 'b)) = - List.fold_left( - (l2_rem, item) => { - switch (get_label2(item)) { - | Some((s1, _)) - when - List.exists( - l => { - switch (l) { - | (Some(s2), _) => compare(s1, s2) == 0 - | _ => false - } - }, - l2_matched, - ) => l2_rem - | Some((s1, it)) => l2_rem @ [(Some(s1), it)] - | _ => l2_rem @ [(None, item)] + let l1' = fst(separate_and_keep_labels(get_label1, l1)); + let (l2_labels, l2_vals) = separate_and_keep_labels(get_label2, l2); + let l2' = List.combine(l2_labels, l2_vals); + let l2_reordered = rearrange2(l1', l2'); + List.map( + ((optional_label, b)) => + switch (optional_label) { + | Some(label) => + // TODO: probably can keep the same ids in a cleaner way + switch (get_label2(b)) { + | Some(_) => b + | None => constructor(label, b) } + | None => b }, - [], - l2, - ); - let rec rearrange_helper = - ( - l1: list('a), - l2_matched: list((option(t), 'b)), - l2_rem: list((option(t), 'b)), - ) - : list('y) => { - switch (l1) { - | [hd, ...tl] => - switch (get_label1(hd)) { - | Some((s1, _)) => - switch (l2_matched) { - | [] => - switch (l2_rem) { - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), rem_val) => - [constructor(s2, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - | (None, rem_val) => - [constructor(s1, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - } - | [] => raise(Exception) - } - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), l2_val) when compare(s1, s2) == 0 => - [l2_val] @ rearrange_helper(tl, tl2, l2_rem) - | _ => - switch (l2_rem) { - | [hd2, ...tl2] => - switch (hd2) { - | (Some(s2), rem_val) => - [constructor(s2, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - | (None, rem_val) => - [constructor(s1, rem_val)] - @ rearrange_helper(tl, l2_matched, tl2) - } - | [] => raise(Exception) - } - } - } - | None => - switch (l2_rem) { - | [(_, hd2), ...tl2] => - [hd2] @ rearrange_helper(tl, l2_matched, tl2) - | [] => raise(Exception) - } - } - | [] => [] - }; - }; - - rearrange_helper(l1, l2_matched, l2_rem); - }; - -// Rename and clean this -// Assumes all labels are unique -// filt returns Some(string) if TupLabel or None if not a TupLabel -// In order of operations: -// Checks all labeled pairs in l2 are in l1 and performs f on each pair -// Checks all labeled pairs in l1 are in l2 and performs f on each pair -// Checks remaining None pairs in order and performs f on each pair -// TODO: Outdated? Rearrange instead. -let ana_tuple: - ( - 'b => option((t, 'b)), - 'c => option((t, 'c)), - ('a, 'b, 'c) => 'a, - 'a, - 'a, - list('b), - list('c) - ) => - 'a = - (get_label1, get_label2, f, accu, accu_fail, l1, l2) => { - let (l1_valid, l1_lab, l1_none) = validate_uniqueness(get_label1, l1); - let (l2_valid, l2_lab, _) = validate_uniqueness(get_label2, l2); - // temporary solution if mess up earlier in tuple, such as make_term - if (!l1_valid || !l2_valid) { - accu_fail; - } else { - // this result represents to accu, and the matched l2 labels - let (accu, l2_labels_matched) = - List.fold_left( - ((accu, l2_matched), l1_item) => { - let l2_item = - find_opt( - l2_item => { - switch (l1_item, l2_item) { - | ((Some(s1), _), (Some(s2), _)) => compare(s1, s2) == 0 - | (_, _) => false - } - }, - l2_lab, - ); - switch (l1_item, l2_item) { - | ((_, l1_val), Some((l2_lab, l2_val))) => ( - f(accu, l1_val, l2_val), - l2_matched @ [l2_lab], - ) - | (_, None) => (accu_fail, l2_matched) - }; - }, - (accu, []), - l1_lab, - ); - // short circuit on failure - if (accu == accu_fail) { - accu_fail; - } else { - // filter l2 to remove matched labels and remove labels - // TODO: Can be optimized - let l2_rem = - List.fold_left( - (l2_rem, item) => { - switch (get_label2(item)) { - | Some((s1, _)) - when - List.exists( - l => { - switch (l) { - | Some(s2) => compare(s1, s2) == 0 - | _ => false - } - }, - l2_labels_matched, - ) => l2_rem - | _ => l2_rem @ [item] - } - }, - [], - l2, - ); - // remaining checks are in order - let accu = - List.fold_left2( - (accu, l1_val, l2_val) => f(accu, l1_val, l2_val), - accu, - l1_none, - l2_rem, - ); - accu; - }; - }; + l2_reordered, + ); }; -let find_label: ('a => option((t, 'a)), list('a), t) => option('a) = +let find_label: ('a => option((label, 'a)), list('a), label) => option('a) = (filt, es, label) => { find_opt( e => { diff --git a/src/haz3lcore/dynamics/DHPat.re b/src/haz3lcore/dynamics/DHPat.re index 4639af4554..dc0c8456c9 100644 --- a/src/haz3lcore/dynamics/DHPat.re +++ b/src/haz3lcore/dynamics/DHPat.re @@ -57,7 +57,7 @@ let rec bound_vars = (dp: t): list(Var.t) => | Ap(_, dp1) => bound_vars(dp1) }; -let rec get_label: t => option((LabeledTuple.t, t)) = +let rec get_label: t => option((LabeledTuple.label, t)) = dp => switch (dp |> term_of) { | Parens(dp) => get_label(dp) diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index c87918fc20..6a6df7346e 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -298,9 +298,11 @@ let rec join = (~resolve=false, ~fix, ctx: Ctx.t, ty1: t, ty2: t): option(t) => Arrow(ty1, ty2) |> temp; | (Arrow(_), _) => None | (Prod(tys1), Prod(tys2)) => - //TODO (Anthony): Clean up the repetition - let (l1_valid, _, _) = LabeledTuple.validate_uniqueness(get_label, tys1); - let (l2_valid, _, _) = LabeledTuple.validate_uniqueness(get_label, tys2); + //TODO (Anthony): Clean up the repetition and check for validity. Maybe in statics though + // let (l1_valid, _, _) = LabeledTuple.validate_uniqueness(get_label, tys1); + // let (l2_valid, _, _) = LabeledTuple.validate_uniqueness(get_label, tys2); + let l1_valid = true; + let l2_valid = true; if (!l1_valid || !l2_valid || List.length(tys1) != List.length(tys2)) { None; } else { diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index 26f2642d0a..59c003e9a8 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -294,7 +294,7 @@ module Pat = { | _ => None }; - let rec get_label: t => option((LabeledTuple.t, t)) = + let rec get_label: t => option((LabeledTuple.label, t)) = p => switch (p.term) { | Parens(p) => get_label(p) @@ -452,7 +452,7 @@ module Exp = { | Match => "Case expression" | Cast => "Cast expression"; - let rec get_label: t => option((LabeledTuple.t, t)) = + let rec get_label: t => option((LabeledTuple.label, t)) = e => switch (e.term) { | Parens(e) => get_label(e) From 7d707c9734b9a9a71693cf12856a9617968ec4e0 Mon Sep 17 00:00:00 2001 From: WondAli Date: Sat, 28 Sep 2024 22:11:43 -0400 Subject: [PATCH 040/108] Rearranging does not occur past elaboration. Functions reworked to always have labeled tuple arguments past elaboration. Currently not passing tests because of errors with singleton labeled tuples --- src/haz3lcore/LabeledTuple.re | 66 +++++++- src/haz3lcore/dynamics/Elaborator.re | 210 ++++++++++++++++++++----- src/haz3lcore/dynamics/PatternMatch.re | 8 +- src/haz3lcore/dynamics/Transition.re | 47 +++--- src/haz3lcore/dynamics/Unboxing.re | 21 ++- src/haz3lcore/statics/Statics.re | 25 ++- test/Test_LabeledTuple.re | 2 +- 7 files changed, 294 insertions(+), 85 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index 35ebb17f75..fbbfdee19c 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -117,7 +117,7 @@ let intersect = (xs, ys) => { // Assumes all labels are unique // Rearranges all the labels in l2 to match the order of the labels in l1. Labels are optional and should me reordered for all present labels first and then unlabled fields matched up pairwise. So labeled fields can be reordered and unlabeled ones can't. Also add labels to the unlabeled. // TODO Handle the unequal length case and extra labels case -let rec rearrange2: +let rec rearrange_base: 'b. ( ~show_b: 'b => string=?, @@ -140,7 +140,7 @@ let rec rearrange2: switch (maybe_found) { | Some(found) => [(Some(expected_label), found)] - @ rearrange2( + @ rearrange_base( ~show_b?, remaining_expectations, List.remove_assoc(Some(expected_label), remaining), @@ -161,7 +161,7 @@ let rec rearrange2: switch (current) { | Some((_existing_label, b)) => [(Some(expected_label), b)] - @ rearrange2(~show_b?, remaining_expectations, pre @ post) + @ rearrange_base(~show_b?, remaining_expectations, pre @ post) | None => remaining }; }; @@ -181,13 +181,13 @@ let rec rearrange2: switch (current) { | Some((_existing_label, b)) => [(None, b)] - @ rearrange2(~show_b?, remaining_expectations, pre @ post) + @ rearrange_base(~show_b?, remaining_expectations, pre @ post) | None => remaining }; }; }; -// Basically another way to call rearrange2 using the raw lists, functions to extract labels from TupLabels, and constructor for new TupLabels. +// Basically another way to call rearrange_base using the raw lists, functions to extract labels from TupLabels, and constructor for new TupLabels. // Maintains the same ids if possible // TODO: clean up more let rearrange: @@ -206,7 +206,7 @@ let rearrange: let l1' = fst(separate_and_keep_labels(get_label1, l1)); let (l2_labels, l2_vals) = separate_and_keep_labels(get_label2, l2); let l2' = List.combine(l2_labels, l2_vals); - let l2_reordered = rearrange2(l1', l2'); + let l2_reordered = rearrange_base(l1', l2'); List.map( ((optional_label, b)) => switch (optional_label) { @@ -222,6 +222,60 @@ let rearrange: ); }; +// rearrange two other lists to match the first list of labels. +// TODO: Ensure that the two lists match up with each other +// TODO: This function currently exists only to make the elaborator code cleaner. Probably can make more efficient +let rearrange2: + 'a 'b. + ( + list(option(label)), + 'a => option((label, 'a)), + 'b => option((label, 'b)), + list('a), + list('b), + (label, 'a) => 'a, + (label, 'b) => 'b + ) => + (list('a), list('b)) + = + (labels, get_label1, get_label2, l1, l2, constructor1, constructor2) => { + let (l1_labels, l1_vals) = separate_and_keep_labels(get_label1, l1); + let l1' = List.combine(l1_labels, l1_vals); + let l1_reordered = rearrange_base(labels, l1'); + let l1_rearranged = + List.map( + ((optional_label, b)) => + switch (optional_label) { + | Some(label) => + // TODO: probably can keep the same ids in a cleaner way + switch (get_label1(b)) { + | Some(_) => b + | None => constructor1(label, b) + } + | None => b + }, + l1_reordered, + ); + let (l2_labels, l2_vals) = separate_and_keep_labels(get_label2, l2); + let l2' = List.combine(l2_labels, l2_vals); + let l2_reordered = rearrange_base(labels, l2'); + let l2_rearranged = + List.map( + ((optional_label, b)) => + switch (optional_label) { + | Some(label) => + // TODO: probably can keep the same ids in a cleaner way + switch (get_label2(b)) { + | Some(_) => b + | None => constructor2(label, b) + } + | None => b + }, + l2_reordered, + ); + (l1_rearranged, l2_rearranged); + }; + let find_label: ('a => option((label, 'a)), list('a), label) => option('a) = (filt, es, label) => { find_opt( diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index a4ab76e8fa..8210cd7c57 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -163,10 +163,43 @@ let rec elaborate_pattern = let (ps', tys) = List.map(elaborate_pattern(m, ~in_container=true), ps) |> ListUtil.unzip; - let ps' = - LabeledTuple.rearrange( - Typ.get_label, DHPat.get_label, tys, ps', (name, p) => - TupLabel(Label(name) |> DHPat.fresh, p) |> DHPat.fresh + let expected_labels: list(option(string)) = + Typ.get_labels(ctx, elaborated_type); + // let elaborated_labeled: list((option(string), DHPat.t)) = + // List.map( + // pat => { + // switch (DHPat.term_of(pat)) { + // | TupLabel({term: Label(l), _}, pat) => (Some(l), pat) + // | _ => (None, pat) + // } + // }, + // ps', + // ); + + // let reordered: list((option(string), DHPat.t)) = + // LabeledTuple.rearrange_base(expected_labels, elaborated_labeled); + + // let ps': list(DHPat.t) = + // List.map( + // ((optional_label, pat: DHPat.t)) => { + // switch (optional_label) { + // | Some(label) => + // DHPat.TupLabel(Label(label) |> DHPat.fresh, pat) |> DHPat.fresh + // | None => pat + // } + // }, + // reordered, + // ); + let (ps', tys) = + LabeledTuple.rearrange2( + expected_labels, + DHPat.get_label, + Typ.get_label, + ps', + tys, + (name, p) => + DHPat.TupLabel(Label(name) |> DHPat.fresh, p) |> DHPat.fresh, + (name, t) => Typ.TupLabel(Label(name) |> Typ.temp, t) |> Typ.temp, ); DHPat.Tuple(ps') |> rewrap |> cast_from(Typ.Prod(tys) |> Typ.temp); | Ap(p1, p2) => @@ -296,9 +329,75 @@ let rec elaborate = | Fun(p, e, env, n) => let (p', typ) = elaborate_pattern(m, p, false); let (e', tye) = elaborate(m, e); + // ensure that p is a labeled tuple, make it so if needed + let elaborated_typ = + //TODO: better way to get typ' + switch (elaborated_type.term) { + | Arrow(typ', _) => typ' + | Unknown(_) => elaborated_type + | _ => typ + }; + let expected_labels = Typ.get_labels(ctx, elaborated_typ); + // TODO: Factor out code + // TODO: Error handling + let rec get_labels_pat = pat => { + switch (DHPat.term_of(pat)) { + | Parens(pat) => get_labels_pat(pat) + | Tuple(ps) => ps + | _ => [pat] + }; + }; + let rec get_labels_typ = typ => { + switch (Typ.term_of(typ)) { + | Parens(typ) => get_labels_typ(typ) + | Prod(ts) => ts + | _ => [typ] + }; + }; + let p_list = get_labels_pat(p'); + let typ_list = get_labels_typ(typ); + // let reordered_ps = + // LabeledTuple.rearrange_base(expected_labels, p_list); + // let ps: list(DHPat.t) = + // List.map( + // ((optional_label, pat: DHPat.t)) => { + // switch (optional_label) { + // | Some(label) => + // DHPat.TupLabel(Label(label) |> DHPat.fresh, pat) |> DHPat.fresh + // | None => pat + // } + // }, + // reordered_ps, + // ); + // let reordered_ts = + // LabeledTuple.rearrange_base(expected_labels, typ_list); + // let ts: list(Typ.t) = + // List.map( + // ((optional_label, typ: Typ.t)) => { + // switch (optional_label) { + // | Some(label) => + // Typ.TupLabel(Label(label) |> Typ.temp, typ) |> Typ.temp + // | None => typ + // } + // }, + // reordered_ts, + // ); + let (ps, ts) = + LabeledTuple.rearrange2( + expected_labels, + DHPat.get_label, + Typ.get_label, + p_list, + typ_list, + (name, p) => + DHPat.TupLabel(Label(name) |> DHPat.fresh, p) |> DHPat.fresh, + (name, t) => Typ.TupLabel(Label(name) |> Typ.temp, t) |> Typ.temp, + ); + let p' = Tuple(ps) |> DHPat.fresh; + let typ' = Typ.Prod(ts) |> Typ.temp; Exp.Fun(p', e', env, n) |> rewrap - |> cast_from(Arrow(typ, tye) |> Typ.temp); + |> cast_from(Arrow(typ', tye) |> Typ.temp); | TypFun(tpat, e, name) => let (e', tye) = elaborate(m, e); Exp.TypFun(tpat, e', name) @@ -325,30 +424,41 @@ let rec elaborate = let expected_labels: list(option(string)) = Typ.get_labels(ctx, elaborated_type); - let elaborated_labeled: list((option(string), DHExp.t)) = - List.map( - exp => { - switch (DHExp.term_of(exp)) { - | TupLabel({term: Label(l), _}, exp) => (Some(l), exp) - | _ => (None, exp) - } - }, - ds, - ); + // let elaborated_labeled: list((option(string), DHExp.t)) = + // List.map( + // exp => { + // switch (DHExp.term_of(exp)) { + // | TupLabel({term: Label(l), _}, exp) => (Some(l), exp) + // | _ => (None, exp) + // } + // }, + // ds, + // ); - let reordered: list((option(string), DHExp.t)) = - LabeledTuple.rearrange2(expected_labels, elaborated_labeled); + // let reordered: list((option(string), DHExp.t)) = + // LabeledTuple.rearrange_base(expected_labels, elaborated_labeled); - let ds: list(DHExp.t) = - List.map( - ((optional_label, exp: DHExp.t)) => { - switch (optional_label) { - | Some(label) => - Exp.TupLabel(Label(label) |> Exp.fresh, exp) |> Exp.fresh - | None => exp - } - }, - reordered, + // let ds: list(DHExp.t) = + // List.map( + // ((optional_label, exp: DHExp.t)) => { + // switch (optional_label) { + // | Some(label) => + // Exp.TupLabel(Label(label) |> Exp.fresh, exp) |> Exp.fresh + // | None => exp + // } + // }, + // reordered, + // ); + let (ds, tys) = + LabeledTuple.rearrange2( + expected_labels, + DHExp.get_label, + Typ.get_label, + ds, + tys, + (name, e) => + DHExp.TupLabel(Label(name) |> DHExp.fresh, e) |> DHExp.fresh, + (name, t) => Typ.TupLabel(Label(name) |> Typ.temp, t) |> Typ.temp, ); Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); @@ -440,20 +550,38 @@ let rec elaborate = let f'' = fresh_cast(f', tyf, Arrow(tyf1, tyf2) |> Typ.temp); // In case of singleton tuple for fun ty_in, implicitly convert arg if necessary // TODO: Is needed for other Aps? - let rec get_args = (a, tya, tyf1) => - switch ( - Typ.weak_head_normalize(ctx, tya).term, - Typ.weak_head_normalize(ctx, tyf1).term, - ) { - | (Parens(tya), _) => get_args(a, tya, tyf1) - | (Prod(_), Prod(_)) => (a, tya) - | (_, Prod([{term: TupLabel(_), _}])) => ( - Tuple([a']) |> Exp.fresh, - Prod([tya]) |> Typ.temp, - ) - | (_, _) => (a, tya) - }; - let (a', tya) = get_args(a', tya, tyf1); + // let rec get_args = (a: Exp.t, tya, tyf1) => + // switch ( + // a.term, + // Typ.weak_head_normalize(ctx, tya).term, + // Typ.weak_head_normalize(ctx, tyf1).term, + // ) { + // | (Parens(a), _, _) => + // //TODO: make sure weak_head_normalize doesn't unalign a and tya. + // get_args(a, tya, tyf1) + // | (Cast(a, cty1, cty2), _, _) => + // let (a, tya) = get_args(a, tya, tyf1); + // (Cast(a, cty1, cty2) |> Exp.fresh, tya); + // | (Tuple(es), Prod(tyas), Prod(tyf1s)) => + // //rearrange es and tyas to match tyf1s + // let es' = + // LabeledTuple.rearrange( + // Typ.get_label, Exp.get_label, tyf1s, es, (name, e) => + // TupLabel(Label(name) |> Exp.fresh, e) |> Exp.fresh + // ); + // let tyas' = + // LabeledTuple.rearrange( + // Typ.get_label, Typ.get_label, tyf1s, tyas, (name, t) => + // TupLabel(Label(name) |> Typ.temp, t) |> Typ.temp + // ); + // (Tuple(es') |> Exp.fresh, Prod(tyas') |> Typ.temp); + // | (_, _, Prod([{term: TupLabel(_), _}])) => ( + // Tuple([a']) |> Exp.fresh, + // Prod([tya]) |> Typ.temp, + // ) + // | (_, _, _) => (a, tya) + // }; + // let (a', tya) = get_args(a', tya, tyf1); let a'' = fresh_cast(a', tya, tyf1); Exp.Ap(dir, f'', a'') |> rewrap |> cast_from(tyf2); | DeferredAp(f, args) => diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index b8d6f3f9fc..bf72b024fc 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -59,10 +59,10 @@ let rec matches = (dp: Pat.t, d: DHExp.t): match_result => | Var(x) => Matches(Environment.singleton((x, d))) | Tuple(ps) => let* ds = Unboxing.unbox(Tuple(List.length(ps)), d); - let ds = - LabeledTuple.rearrange(DHPat.get_label, DHExp.get_label, ps, ds, (t, e) => - TupLabel(Label(t) |> DHExp.fresh, e) |> DHExp.fresh - ); + // let ds = + // LabeledTuple.rearrange(DHPat.get_label, DHExp.get_label, ps, ds, (t, e) => + // TupLabel(Label(t) |> DHExp.fresh, e) |> DHExp.fresh + // ); List.map2(matches, ps, ds) |> List.fold_left(combine_result, Matches(Environment.empty)); | Parens(p) => matches(p, d) diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index f97a13880e..57bd4931ed 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -349,29 +349,30 @@ module Transition = (EV: EV_MODE) => { | Fun(dp, d3, Some(env'), _) => // Wrap the arguments into labels for label rearrangement // And implicitly wrap args into singleton tuples if necessary - let dp: DHPat.t = - switch (DHPat.term_of(dp)) { - | Tuple(args) => - let labeled_args = - List.map( - (p): DHPat.t => - switch (DHPat.term_of(p)) { - | DHPat.Var(name) => - TupLabel(DHPat.Label(name) |> DHPat.fresh, p) - |> DHPat.fresh - | _ => p - }, - args, - ); - Tuple(labeled_args) |> DHPat.fresh; - // | TupLabel(_, _) => Tuple([dp]) |> DHPat.fresh - // | Var(name) => - // Tuple([ - // TupLabel(DHPat.Label(name) |> DHPat.fresh, dp) |> DHPat.fresh, - // ]) - // |> DHPat.fresh - | _ => dp - }; + // This should be done in elaborator instead + // let dp: DHPat.t = + // switch (DHPat.term_of(dp)) { + // | Tuple(args) => + // let labeled_args = + // List.map( + // (p): DHPat.t => + // switch (DHPat.term_of(p)) { + // | DHPat.Var(name) => + // TupLabel(DHPat.Label(name) |> DHPat.fresh, p) + // |> DHPat.fresh + // | _ => p + // }, + // args, + // ); + // Tuple(labeled_args) |> DHPat.fresh; + // | TupLabel(_, _) => Tuple([dp]) |> DHPat.fresh + // | Var(name) => + // Tuple([ + // TupLabel(DHPat.Label(name) |> DHPat.fresh, dp) |> DHPat.fresh, + // ]) + // |> DHPat.fresh + // | _ => dp + // }; // TODO: Probably not the right way to deal with casts // let d2' = // switch (d2'.term, DHPat.term_of(dp)) { diff --git a/src/haz3lcore/dynamics/Unboxing.re b/src/haz3lcore/dynamics/Unboxing.re index aa8e054d97..1902309b12 100644 --- a/src/haz3lcore/dynamics/Unboxing.re +++ b/src/haz3lcore/dynamics/Unboxing.re @@ -82,6 +82,17 @@ let rec unbox: type a. (unbox_request(a), DHExp.t) => unboxed(a) = // | TupLabel(_, e) => unbox(request, e) // | _ => unbox(request, e) // } + | ( + TupLabel(tl), + Cast(t, {term: TupLabel(_, ty1), _}, {term: TupLabel(_, ty2), _}), + ) => + let* t = unbox(TupLabel(tl), t); + let t = fixup_cast(Cast(t, ty1, ty2) |> DHExp.fresh); + Matches(t); + | (TupLabel(tl), Cast(t, ty1, ty2)) => + let* t = unbox(TupLabel(tl), t); + let t = fixup_cast(Cast(t, ty1, ty2) |> DHExp.fresh); + Matches(t); | (TupLabel(_), _) => Matches(expr) /* Remove Tuplabels from casts otherwise */ @@ -133,11 +144,11 @@ let rec unbox: type a. (unbox_request(a), DHExp.t) => unboxed(a) = | (Tuple(n), Cast(t, {term: Prod(t1s), _}, {term: Prod(t2s), _})) when n == List.length(t1s) && n == List.length(t2s) => let* t = unbox(Tuple(n), t); - let t1s = - LabeledTuple.rearrange( - Typ.get_label, Typ.get_label, t2s, t1s, (name, t) => - Typ.TupLabel(Typ.Label(name) |> Typ.temp, t) |> Typ.temp - ); + // let t1s = + // LabeledTuple.rearrange( + // Typ.get_label, Typ.get_label, t2s, t1s, (name, t) => + // Typ.TupLabel(Typ.Label(name) |> Typ.temp, t) |> Typ.temp + // ); let t = ListUtil.map3( (d, t1, t2) => Cast(d, t1, t2) |> DHExp.fresh, diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 81f8ba6eb5..2d4af4d5f6 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -445,8 +445,23 @@ and uexp_to_info_map = // TODO: Is needed for TypAp or Deferred Ap? let arg = switch (arg.term, Typ.weak_head_normalize(ctx, ty_in).term) { - | (Tuple(_), Prod(_)) => arg - | (_, Prod([{term: TupLabel(_), _}])) => Tuple([arg]) |> Exp.fresh + | (Tuple(es), Prod(ts)) => + let es' = + LabeledTuple.rearrange( + Typ.get_label, Exp.get_label, ts, es, (name, e) => + TupLabel(Label(name) |> Exp.fresh, e) |> Exp.fresh + ); + let arg: Exp.t = { + term: Exp.Tuple(es'), + ids: arg.ids, + copied: arg.copied, + }; + arg; + | (TupLabel(_), Prod([{term: TupLabel(_), _}])) => + Tuple([arg]) |> Exp.fresh + | (_, Prod([{term: TupLabel({term: Label(name), _}, _), _}])) => + Tuple([TupLabel(Label(name) |> Exp.fresh, arg) |> Exp.fresh]) + |> Exp.fresh | (_, _) => arg }; let (arg, m) = go(~mode=Ana(ty_in), arg, m); @@ -484,8 +499,8 @@ 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); - // convert variables into labeled expressions if needed - let rec get_var = (p1: UPat.t, p2) => + // convert variables into labeled types if needed + let rec get_var = (p1: UPat.t, p2: Typ.t) => switch (p1.term) { | UPat.Var(s) => Typ.TupLabel(Label(s) |> Typ.temp, p2) |> Typ.temp | Cast(s, _, _) => get_var(s, p2) @@ -497,7 +512,7 @@ and uexp_to_info_map = let pt: list(Typ.t) = List.map2(get_var, l1, l2); Prod(pt) |> Typ.temp; | (Cast(s, _, _), t) => get_typ(s, t |> Typ.temp) - | _ => t + | _ => Prod([get_var(p, t)]) |> Typ.temp }; let pty = get_typ(p, p''.ty); // TODO: factor out code diff --git a/test/Test_LabeledTuple.re b/test/Test_LabeledTuple.re index 6bee6a530c..e1715207aa 100644 --- a/test/Test_LabeledTuple.re +++ b/test/Test_LabeledTuple.re @@ -7,7 +7,7 @@ let test_rearrange = (name, analyzed_types, actual_values, expected_values) => `Quick, () => { let actual = - LabeledTuple.rearrange2( + LabeledTuple.rearrange_base( ~show_b=[%derive.show: int], analyzed_types, actual_values, From 20c51f98f18bc8c03310924c715043572a2a5f3e Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 2 Oct 2024 11:01:45 -0400 Subject: [PATCH 041/108] Add support for fast_equal on TupLabel expressions --- src/haz3lcore/statics/TermBase.re | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index a2a3687ed4..a60c3f09f5 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -421,6 +421,8 @@ and Exp: { ) | (Cast(e1, t1, t2), Cast(e2, t3, t4)) => fast_equal(e1, e2) && Typ.fast_equal(t1, t3) && Typ.fast_equal(t2, t4) + | (TupLabel(e1, e2), TupLabel(e3, e4)) => + fast_equal(e1, e3) && fast_equal(e2, e4) | (Invalid(_), _) | (FailedCast(_), _) | (Deferral(_), _) From 49c11d9726ecf94ff9d2fd6b6ca06316e2befea7 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 2 Oct 2024 11:02:18 -0400 Subject: [PATCH 042/108] Add test for elaboration adding labels to labeled tuples --- test/Test_Elaboration.re | 71 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 800d75212f..5201a22c55 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -179,6 +179,76 @@ let let_fun = () => dhexp_of_uexp(u9), ); +/* + Label Elaboration test + ```hazel + let add : (street=String, city=String, state=String, zipcode=Int)= ("123 Maple St", + "Ann Arbor", + "MI", + 48103) in add ``` + elaborates to + (street="123 Maple St", city="Ann Arbor", state="MI", zipcode=48103) + */ +let full_program: Exp.t = + Let( + Cast( + Var("add") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("street") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("city") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("state") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("zipcode") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens( + Tuple([ + String("123 Maple St") |> Exp.fresh, + String("Ann Arbor") |> Exp.fresh, + String("MI") |> Exp.fresh, + Int(48103) |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + Var("add") |> Exp.fresh, + ) + |> Exp.fresh; +let elaborated: Exp.term = + Let( + Var("add") |> Pat.fresh, + Tuple([ + TupLabel( + Label("street") |> Exp.fresh, + String("123 Maple St") |> Exp.fresh, + ) + |> Exp.fresh, + TupLabel(Label("city") |> Exp.fresh, String("Ann Arbor") |> Exp.fresh) + |> Exp.fresh, + TupLabel(Label("state") |> Exp.fresh, String("MI") |> Exp.fresh) + |> Exp.fresh, + TupLabel(Label("zipcode") |> Exp.fresh, Int(48103) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("add") |> Exp.fresh, + ); +let elaborated_labeled_tuple = () => + alco_check( + "Labeled Tuple lable introduction", + elaborated |> Exp.fresh, + dhexp_of_uexp(full_program), + ); + let elaboration_tests = [ test_case("Single integer", `Quick, single_integer), test_case("Empty hole", `Quick, empty_hole), @@ -189,4 +259,5 @@ let elaboration_tests = [ test_case("Application of function on free variable", `Quick, ap_fun), test_case("Inconsistent case statement", `Quick, inconsistent_case), test_case("Let expression for a function", `Quick, let_fun), + test_case("Labeled tuple elaboration", `Quick, elaborated_labeled_tuple), ]; From 38b10c18a84b4338707fa6b47b09aa6bec8cd88d Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 2 Oct 2024 11:05:41 -0400 Subject: [PATCH 043/108] Inline expectation --- test/Test_Elaboration.re | 42 +++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 5201a22c55..584b002c57 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -223,29 +223,31 @@ let full_program: Exp.t = Var("add") |> Exp.fresh, ) |> Exp.fresh; -let elaborated: Exp.term = - Let( - Var("add") |> Pat.fresh, - Tuple([ - TupLabel( - Label("street") |> Exp.fresh, - String("123 Maple St") |> Exp.fresh, - ) - |> Exp.fresh, - TupLabel(Label("city") |> Exp.fresh, String("Ann Arbor") |> Exp.fresh) - |> Exp.fresh, - TupLabel(Label("state") |> Exp.fresh, String("MI") |> Exp.fresh) - |> Exp.fresh, - TupLabel(Label("zipcode") |> Exp.fresh, Int(48103) |> Exp.fresh) - |> Exp.fresh, - ]) - |> Exp.fresh, - Var("add") |> Exp.fresh, - ); let elaborated_labeled_tuple = () => alco_check( "Labeled Tuple lable introduction", - elaborated |> Exp.fresh, + Let( + Var("add") |> Pat.fresh, + Tuple([ + TupLabel( + Label("street") |> Exp.fresh, + String("123 Maple St") |> Exp.fresh, + ) + |> Exp.fresh, + TupLabel( + Label("city") |> Exp.fresh, + String("Ann Arbor") |> Exp.fresh, + ) + |> Exp.fresh, + TupLabel(Label("state") |> Exp.fresh, String("MI") |> Exp.fresh) + |> Exp.fresh, + TupLabel(Label("zipcode") |> Exp.fresh, Int(48103) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("add") |> Exp.fresh, + ) + |> Exp.fresh, dhexp_of_uexp(full_program), ); From c315caad2d5f4306359e20115877da26bab9ef7b Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 2 Oct 2024 11:06:20 -0400 Subject: [PATCH 044/108] Fix typos --- test/Test_Elaboration.re | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 584b002c57..fd060f64b4 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -189,7 +189,7 @@ let let_fun = () => elaborates to (street="123 Maple St", city="Ann Arbor", state="MI", zipcode=48103) */ -let full_program: Exp.t = +let full_labeled_tuple_program: Exp.t = Let( Cast( Var("add") |> Pat.fresh, @@ -225,7 +225,7 @@ let full_program: Exp.t = |> Exp.fresh; let elaborated_labeled_tuple = () => alco_check( - "Labeled Tuple lable introduction", + "Labeled Tuple label introduction", Let( Var("add") |> Pat.fresh, Tuple([ @@ -248,7 +248,7 @@ let elaborated_labeled_tuple = () => Var("add") |> Exp.fresh, ) |> Exp.fresh, - dhexp_of_uexp(full_program), + dhexp_of_uexp(full_labeled_tuple_program), ); let elaboration_tests = [ From 5707718cb748b0e98dce4825c4e15cab2eb99def Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 2 Oct 2024 11:14:11 -0400 Subject: [PATCH 045/108] Add test for rearranging labels during elaboration --- test/Test_Elaboration.re | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index fd060f64b4..901a5f4599 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -251,6 +251,67 @@ let elaborated_labeled_tuple = () => dhexp_of_uexp(full_labeled_tuple_program), ); +/* Labeled Tuple Rearranging + ```hazel + let val : (a=Int, b=String, Float, c=Bool)= (1, + 1.0, + c=true, + b="a") in val ``` + elaborates to + (a=1, b="a", 1.0, c=true) + */ +let rearranged_labeled_tuple_program: Exp.t = + Let( + Cast( + Var("val") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("a") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, + TupLabel(Label("b") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, + Float |> Typ.fresh, + TupLabel(Label("c") |> Typ.fresh, Bool |> Typ.fresh) |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens( + Tuple([ + Int(1) |> Exp.fresh, + Float(1.0) |> Exp.fresh, + TupLabel(Label("c") |> Exp.fresh, Bool(true) |> Exp.fresh) + |> Exp.fresh, + TupLabel(Label("b") |> Exp.fresh, String("a") |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + Var("val") |> Exp.fresh, + ) + |> Exp.fresh; +let rearranged_labeled_tuple = () => + alco_check( + "Labeled Tuple rearrangement", + Let( + Var("val") |> Pat.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) |> Exp.fresh, + TupLabel(Label("b") |> Exp.fresh, String("a") |> Exp.fresh) + |> Exp.fresh, + Float(1.0) |> Exp.fresh, + TupLabel(Label("c") |> Exp.fresh, Bool(true) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("val") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(rearranged_labeled_tuple_program), + ); + let elaboration_tests = [ test_case("Single integer", `Quick, single_integer), test_case("Empty hole", `Quick, empty_hole), @@ -262,4 +323,5 @@ let elaboration_tests = [ test_case("Inconsistent case statement", `Quick, inconsistent_case), test_case("Let expression for a function", `Quick, let_fun), test_case("Labeled tuple elaboration", `Quick, elaborated_labeled_tuple), + test_case("Rearranged labeled tuple", `Quick, rearranged_labeled_tuple), ]; From 8d6528e1685f59a7a3dea943d24e3ab2d7ddc97f Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 2 Oct 2024 11:33:18 -0400 Subject: [PATCH 046/108] Add test for labeled tuple projection evaluation --- test/Test_Evaluator.re | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/Test_Evaluator.re b/test/Test_Evaluator.re index fc159425b2..366c7fc1f0 100644 --- a/test/Test_Evaluator.re +++ b/test/Test_Evaluator.re @@ -38,7 +38,29 @@ let test_sum = () => BinOp(Int(Plus), Int(4) |> Exp.fresh, Int(5) |> Exp.fresh) |> Exp.fresh, ); +let test_labeled_tuple_projection = () => + evaluation_test( + "(a=1, b=2, c=?).a", + Int(1) |> Exp.fresh, + Dot( + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) |> Exp.fresh, + TupLabel(Label("b") |> Exp.fresh, Int(2) |> Exp.fresh) |> Exp.fresh, + TupLabel(Label("c") |> Exp.fresh, EmptyHole |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("a") |> Exp.fresh // This is a var now for parsing reasons + ) + |> Exp.fresh, + ); + let tests = [ test_case("Integer literal", `Quick, test_int), test_case("Integer sum", `Quick, test_sum), + test_case( + "Labeled tuple projection", + `Quick, + test_labeled_tuple_projection, + ), ]; From a5c83bc5fc78226f0918d2a08ae61ff7ec7433c1 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 2 Oct 2024 11:47:42 -0400 Subject: [PATCH 047/108] Add statics test for labeled parameter in function --- test/Test_Statics.re | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 71fdafc8ba..206e1a359c 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -8,6 +8,8 @@ module FreshId = { let int = Typ.fresh(Int); let float = Typ.fresh(Float); let prod = a => Prod(a) |> Typ.fresh; + let label = a => Label(a) |> Typ.fresh; + let tup_label = (a, b) => TupLabel(a, b) |> Typ.fresh; let string = Typ.fresh(String); }; let ids = List.init(12, _ => Id.mk()); @@ -74,6 +76,27 @@ let tests = ), ) ), + test_case("Unsure: Function with labeled param", `Quick, () => + alco_check( + "fun (a=x) => 4", + Some( + arrow(prod([tup_label(label("a"), unknown(Internal))]), int), + ), + type_of( + Fun( + Parens( + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + |> Pat.fresh, + ) + |> Pat.fresh, + Int(4) |> Exp.fresh, + None, + None, + ) + |> Exp.fresh, + ), + ) + ), test_case("bifunction", `Quick, () => alco_check( "x : Int, y: Int => x + y", From f4d778e07304794ef7067ff4fb0a1aca6bc0c464 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 4 Oct 2024 15:00:58 -0400 Subject: [PATCH 048/108] Added tests to assure that types are inconsistent when unlabeled variable is appleid to labels --- test/Test_Statics.re | 132 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 4 deletions(-) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 206e1a359c..652315d908 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -2,6 +2,20 @@ open Alcotest; open Haz3lcore; let testable_typ = testable(Fmt.using(Typ.show, Fmt.string), Typ.fast_equal); +let testable_status_exp = + testable( + Fmt.using(Info.show_status_exp, Fmt.string), + // TODO: Fix this + (a, b) => { + switch (a, b) { + | ( + InHole(Common(Inconsistent(Expectation({ana: a1, syn: a2})))), + InHole(Common(Inconsistent(Expectation({ana: b1, syn: b2})))), + ) => + Typ.fast_equal(a1, b1) && Typ.fast_equal(a2, b2) + | _ => false + } + }); module FreshId = { let arrow = (a, b) => Arrow(a, b) |> Typ.fresh; let unknown = a => Unknown(a) |> Typ.fresh; @@ -17,15 +31,123 @@ let id_at = x => x |> List.nth(ids); let statics = Statics.mk(CoreSettings.on, Builtins.ctx_init); let alco_check = Alcotest.option(testable_typ) |> Alcotest.check; -// Get the type from the statics -let type_of = f => { +let info_of_id = (f: UExp.t, id: Id.t) => { let s = statics(f); - switch (Id.Map.find(IdTagged.rep_id(f), s)) { - | InfoExp({ty, _}) => Some(ty) + switch (Id.Map.find(id, s)) { + | InfoExp(ie) => Some(ie) | _ => None }; }; +// Get the type from the statics +let type_of = f => { + Option.map((ie: Info.exp) => ie.ty, info_of_id(f, IdTagged.rep_id(f))); +}; +let reusable_id = Id.mk(); +let unlabeled_tuple_to_labeled_fails = + test_case( + "Typechecking fails for unlabeled variable being assigned to labeled tuple", + `Quick, + () => + Alcotest.check( + Alcotest.option(testable_status_exp), + "let x = (1, 2) in let y : (a=Int, b=Int) = x in y", + Some( + InHole( + Common( + Inconsistent( + Expectation({ + ana: + Parens( + Prod([ + TupLabel(Label("a") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("b") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + syn: Prod([Int |> Typ.fresh, Int |> Typ.fresh]) |> Typ.fresh, + }), + ), + ), + ), + ), + Option.map( + (ie: Info.exp) => ie.status, + info_of_id( + Let( + Var("x") |> Pat.fresh, + Parens( + Tuple([Int(1) |> Exp.fresh, Int(2) |> Exp.fresh]) |> Exp.fresh, + ) + |> Exp.fresh, + Let( + Cast( + Var("y") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("a") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("b") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + {ids: [reusable_id], term: Var("x"), copied: false}, + Var("y") |> Exp.fresh, + ) + |> Exp.fresh, + ) + |> Exp.fresh, + reusable_id, + ), + ), + ) + ); + +let simple_inconsistency = + test_case( + "Typechecking fails for unlabeled variable being assigned to labeled tuple", + `Quick, + () => + Alcotest.check( + Alcotest.option(testable_status_exp), + "let y : String = true", + Some( + InHole( + Common( + Inconsistent( + Expectation({ana: String |> Typ.fresh, syn: Bool |> Typ.fresh}), + ), + ), + ), + ), + Option.map( + (ie: Info.exp) => ie.status, + info_of_id( + Let( + Cast( + Var("y") |> Pat.fresh, + String |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + {ids: [reusable_id], term: Bool(true), copied: false}, + Var("y") |> Exp.fresh, + ) + |> Exp.fresh, + reusable_id, + ), + ), + ) + ); + let unapplied_function = () => alco_check( "Unknown param", @@ -146,4 +268,6 @@ let tests = ), ) ), + unlabeled_tuple_to_labeled_fails, + simple_inconsistency, ]; From 32173eac5cbb958f64729fbb882875e5e5c723bd Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 4 Oct 2024 15:45:44 -0400 Subject: [PATCH 049/108] removed function implicit labelling and rearranging in type consistency join --- src/haz3lcore/dynamics/Elaborator.re | 102 +-------------------------- src/haz3lcore/lang/term/Typ.re | 7 +- src/haz3lcore/statics/Statics.re | 18 +---- 3 files changed, 3 insertions(+), 124 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 8210cd7c57..50b3d535d0 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -329,75 +329,9 @@ let rec elaborate = | Fun(p, e, env, n) => let (p', typ) = elaborate_pattern(m, p, false); let (e', tye) = elaborate(m, e); - // ensure that p is a labeled tuple, make it so if needed - let elaborated_typ = - //TODO: better way to get typ' - switch (elaborated_type.term) { - | Arrow(typ', _) => typ' - | Unknown(_) => elaborated_type - | _ => typ - }; - let expected_labels = Typ.get_labels(ctx, elaborated_typ); - // TODO: Factor out code - // TODO: Error handling - let rec get_labels_pat = pat => { - switch (DHPat.term_of(pat)) { - | Parens(pat) => get_labels_pat(pat) - | Tuple(ps) => ps - | _ => [pat] - }; - }; - let rec get_labels_typ = typ => { - switch (Typ.term_of(typ)) { - | Parens(typ) => get_labels_typ(typ) - | Prod(ts) => ts - | _ => [typ] - }; - }; - let p_list = get_labels_pat(p'); - let typ_list = get_labels_typ(typ); - // let reordered_ps = - // LabeledTuple.rearrange_base(expected_labels, p_list); - // let ps: list(DHPat.t) = - // List.map( - // ((optional_label, pat: DHPat.t)) => { - // switch (optional_label) { - // | Some(label) => - // DHPat.TupLabel(Label(label) |> DHPat.fresh, pat) |> DHPat.fresh - // | None => pat - // } - // }, - // reordered_ps, - // ); - // let reordered_ts = - // LabeledTuple.rearrange_base(expected_labels, typ_list); - // let ts: list(Typ.t) = - // List.map( - // ((optional_label, typ: Typ.t)) => { - // switch (optional_label) { - // | Some(label) => - // Typ.TupLabel(Label(label) |> Typ.temp, typ) |> Typ.temp - // | None => typ - // } - // }, - // reordered_ts, - // ); - let (ps, ts) = - LabeledTuple.rearrange2( - expected_labels, - DHPat.get_label, - Typ.get_label, - p_list, - typ_list, - (name, p) => - DHPat.TupLabel(Label(name) |> DHPat.fresh, p) |> DHPat.fresh, - (name, t) => Typ.TupLabel(Label(name) |> Typ.temp, t) |> Typ.temp, - ); - let p' = Tuple(ps) |> DHPat.fresh; - let typ' = Typ.Prod(ts) |> Typ.temp; Exp.Fun(p', e', env, n) |> rewrap - |> cast_from(Arrow(typ', tye) |> Typ.temp); + |> cast_from(Arrow(typ, tye) |> Typ.temp); | TypFun(tpat, e, name) => let (e', tye) = elaborate(m, e); Exp.TypFun(tpat, e', name) @@ -548,40 +482,6 @@ let rec elaborate = let (a', tya) = elaborate(m, a); let (tyf1, tyf2) = Typ.matched_arrow(ctx, tyf); let f'' = fresh_cast(f', tyf, Arrow(tyf1, tyf2) |> Typ.temp); - // In case of singleton tuple for fun ty_in, implicitly convert arg if necessary - // TODO: Is needed for other Aps? - // let rec get_args = (a: Exp.t, tya, tyf1) => - // switch ( - // a.term, - // Typ.weak_head_normalize(ctx, tya).term, - // Typ.weak_head_normalize(ctx, tyf1).term, - // ) { - // | (Parens(a), _, _) => - // //TODO: make sure weak_head_normalize doesn't unalign a and tya. - // get_args(a, tya, tyf1) - // | (Cast(a, cty1, cty2), _, _) => - // let (a, tya) = get_args(a, tya, tyf1); - // (Cast(a, cty1, cty2) |> Exp.fresh, tya); - // | (Tuple(es), Prod(tyas), Prod(tyf1s)) => - // //rearrange es and tyas to match tyf1s - // let es' = - // LabeledTuple.rearrange( - // Typ.get_label, Exp.get_label, tyf1s, es, (name, e) => - // TupLabel(Label(name) |> Exp.fresh, e) |> Exp.fresh - // ); - // let tyas' = - // LabeledTuple.rearrange( - // Typ.get_label, Typ.get_label, tyf1s, tyas, (name, t) => - // TupLabel(Label(name) |> Typ.temp, t) |> Typ.temp - // ); - // (Tuple(es') |> Exp.fresh, Prod(tyas') |> Typ.temp); - // | (_, _, Prod([{term: TupLabel(_), _}])) => ( - // Tuple([a']) |> Exp.fresh, - // Prod([tya]) |> Typ.temp, - // ) - // | (_, _, _) => (a, tya) - // }; - // let (a', tya) = get_args(a', tya, tyf1); let a'' = fresh_cast(a', tya, tyf1); Exp.Ap(dir, f'', a'') |> rewrap |> cast_from(tyf2); | DeferredAp(f, args) => diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index 6a6df7346e..9a2b757997 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -253,8 +253,7 @@ let rec join = (~resolve=false, ~fix, ctx: Ctx.t, ty1: t, ty2: t): option(t) => } else { None; } - | (TupLabel(_, ty1), _) => join'(ty1, ty2) - | (_, TupLabel(_, ty2)) => join'(ty1, ty2) + | (TupLabel(_), _) => None | (Rec(tp1, ty1), Rec(tp2, ty2)) => let ctx = Ctx.extend_dummy_tvar(ctx, tp1); let ty1' = @@ -306,10 +305,6 @@ let rec join = (~resolve=false, ~fix, ctx: Ctx.t, ty1: t, ty2: t): option(t) => if (!l1_valid || !l2_valid || List.length(tys1) != List.length(tys2)) { None; } else { - let tys2 = - LabeledTuple.rearrange(get_label, get_label, tys1, tys2, (t, b) => - TupLabel(Label(t) |> temp, b) |> temp - ); let* tys = ListUtil.map2_opt(join', tys1, tys2); let+ tys = OptUtil.sequence(tys); Prod(tys) |> temp; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 2d4af4d5f6..d8792fc221 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -499,25 +499,9 @@ 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); - // convert variables into labeled types if needed - let rec get_var = (p1: UPat.t, p2: Typ.t) => - switch (p1.term) { - | UPat.Var(s) => Typ.TupLabel(Label(s) |> Typ.temp, p2) |> Typ.temp - | Cast(s, _, _) => get_var(s, p2) - | _ => p2 - }; - let rec get_typ = (p: UPat.t, t: Typ.t): Typ.t => - switch (p.term, t.term) { - | (Tuple(l1), Prod(l2)) => - let pt: list(Typ.t) = List.map2(get_var, l1, l2); - Prod(pt) |> Typ.temp; - | (Cast(s, _, _), t) => get_typ(s, t |> Typ.temp) - | _ => Prod([get_var(p, t)]) |> Typ.temp - }; - let pty = get_typ(p, p''.ty); // TODO: factor out code let unwrapped_self: Self.exp = - Common(Just(Arrow(pty, e.ty) |> Typ.temp)); + Common(Just(Arrow(p''.ty, e.ty) |> Typ.temp)); let is_exhaustive = p'' |> Info.pat_constraint |> Incon.is_exhaustive; let self = is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); From 318cfb33cf48a04c532385a370cc1cc78909ae4b Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 11 Oct 2024 10:08:31 -0400 Subject: [PATCH 050/108] Add basic elaboration tests for singleton tuples --- test/Test_Elaboration.re | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index b6e553c544..c05f06983c 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -276,6 +276,64 @@ let elaborated_labeled_tuple = () => dhexp_of_uexp(full_labeled_tuple_program), ); +let singleton_labeled_tuple = () => + alco_check( + "Singleton Labeled Tuple", + Tuple([ + TupLabel( + Label("label") |> Exp.fresh, + String("a string value") |> Exp.fresh, + ) + |> Exp.fresh, + ]) + |> Exp.fresh, + dhexp_of_uexp( + Tuple([ + TupLabel( + Label("label") |> Exp.fresh, + String("a string value") |> Exp.fresh, + ) + |> Exp.fresh, + ]) + |> Exp.fresh, + ), + ); + +let singleton_labeled_tuple_elaborates_labels = () => + alco_check( + "Labeled Tuple label introduction", + Let( + Var("x") |> Pat.fresh, + Tuple([ + TupLabel(Label("l") |> Exp.fresh, String("a") |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp( + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens(Tuple([String("a") |> Exp.fresh]) |> Exp.fresh) |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + ), + ); + /* Labeled Tuple Rearranging ```hazel let val : (a=Int, b=String, Float, c=Bool)= (1, @@ -355,4 +413,10 @@ let elaboration_tests = [ ), test_case("Labeled tuple elaboration", `Quick, elaborated_labeled_tuple), test_case("Rearranged labeled tuple", `Quick, rearranged_labeled_tuple), + test_case( + "Singleton labeled tuple adds labels", + `Quick, + singleton_labeled_tuple_elaborates_labels, + ), + test_case("Singleton labeled tuple", `Quick, singleton_labeled_tuple), ]; From c8ef191b7bdbc71a4d68458625402b8727ca0f15 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 11 Oct 2024 10:17:09 -0400 Subject: [PATCH 051/108] Modify singleton labeled tuple elaboration --- test/Test_Elaboration.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index c05f06983c..2bec16bdd3 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -301,7 +301,7 @@ let singleton_labeled_tuple = () => let singleton_labeled_tuple_elaborates_labels = () => alco_check( - "Labeled Tuple label introduction", + "let x : (l=String) = \"a\" in x", Let( Var("x") |> Pat.fresh, Tuple([ @@ -327,7 +327,7 @@ let singleton_labeled_tuple_elaborates_labels = () => Unknown(Internal) |> Typ.fresh, ) |> Pat.fresh, - Parens(Tuple([String("a") |> Exp.fresh]) |> Exp.fresh) |> Exp.fresh, + Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Should we require parens around singleton tables to ascribe labels Var("x") |> Exp.fresh, ) |> Exp.fresh, From 22cd8d6a1749f9c900fba1cc49cb433deeadab5f Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 11 Oct 2024 11:03:22 -0400 Subject: [PATCH 052/108] Add parser tests for singleton tuples --- test/Test_Elaboration.re | 3 ++- test/Test_MakeTerm.re | 37 +++++++++++++++++++++++++++++++++++++ test/haz3ltest.re | 1 + 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/Test_MakeTerm.re diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 2bec16bdd3..b9fe724c63 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -418,5 +418,6 @@ let elaboration_tests = [ `Quick, singleton_labeled_tuple_elaborates_labels, ), - test_case("Singleton labeled tuple", `Quick, singleton_labeled_tuple), + test_case("Singleton labeled tuple", `Quick, singleton_labeled_tuple) // TODO Make consistent with make term + // TODO Add singleton labeled function application ]; diff --git a/test/Test_MakeTerm.re b/test/Test_MakeTerm.re new file mode 100644 index 0000000000..84ce1b4525 --- /dev/null +++ b/test/Test_MakeTerm.re @@ -0,0 +1,37 @@ +/** + * This file contains tests to validate the `MakeTerm` module's ability to convert + * zippers into expressions. + */ +open Alcotest; +open Haz3lcore; + +let exp_typ = testable(Fmt.using(Exp.show, Fmt.string), Exp.fast_equal); + +// TODO Assertion if it doesn't parse +let parse_exp = (s: string) => + MakeTerm.from_zip_for_sem(Option.get(Printer.zipper_of_string(s))).term; +let exp_check = (expected, actual) => + check(exp_typ, actual, expected, parse_exp(actual)); + +let tests = [ + test_case("Singleton Labled Tuple ascription in let", `Quick, () => { + exp_check( + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) // TODO Do we want to wrap the singleton case in a product + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Should we require parens around singleton tables to ascribe labels + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + "let x : (l=String) = \"a\" in x", + ) + }), +]; diff --git a/test/haz3ltest.re b/test/haz3ltest.re index 9fc9952ba1..83ac064967 100644 --- a/test/haz3ltest.re +++ b/test/haz3ltest.re @@ -9,6 +9,7 @@ let (suite, _) = ("LabeledTuple", Test_LabeledTuple.tests), ("Statics", Test_Statics.tests), ("Evaluator", Test_Evaluator.tests), + ("MakeTerm", Test_MakeTerm.tests), ], ); Junit.to_file(Junit.make([suite]), "junit_tests.xml"); From f04c976e943db4816a22eacee7268810d553d23a Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 11 Oct 2024 14:43:49 -0400 Subject: [PATCH 053/108] Wrap all tuplabels in tuples in parser --- src/haz3lcore/statics/MakeTerm.re | 57 +++++++++++++++++++++++++++---- test/Test_MakeTerm.re | 8 +++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index 1d3db77666..2e9bd585df 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -277,7 +277,20 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { } | Bin(Exp(l), tiles, Exp(r)) as tm => switch (is_tuple_exp(tiles)) { - | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) + | Some(between_kids) => + let tuple_children: list(TermBase.Exp.t) = [l] @ between_kids @ [r]; + let mapping_fn: UExp.t => UExp.t = ( + (child: UExp.t) => { + switch (child) { + | {term: Tuple([{term: TupLabel(_), _} as tl]), _} => tl + | _ => child + }; + } + ); + let tuple_children: list(UExp.t) = + List.map(mapping_fn, tuple_children); + + ret(Tuple(tuple_children)); | None => switch (tiles) { | ([(_id, t)], []) => @@ -316,7 +329,13 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { switch (l.term) { | String(name) | Var(name) => - TupLabel({ids: l.ids, copied: l.copied, term: Label(name)}, r) + Tuple([ + TupLabel( + {ids: l.ids, copied: l.copied, term: Label(name)}, + r, + ) + |> Exp.fresh, + ]) | _ => TupLabel(l, r) } | (["."], []) => Dot(l, r) @@ -387,7 +406,17 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { } | Bin(Pat(l), tiles, Pat(r)) as tm => switch (is_tuple_pat(tiles)) { - | Some(between_kids) => ret(Tuple([l] @ between_kids @ [r])) + | Some(between_kids) => + let tuple_children = [l] @ between_kids @ [r]; + let mapping_fn = (child: Pat.t) => { + switch (child) { + | {term: Tuple([{term: TupLabel(_), _} as tl]), _} => tl + | _ => child + }; + }; + let tuple_children = List.map(mapping_fn, tuple_children); + ret(Tuple(tuple_children)); + | None => switch (tiles) { | ([(_id, (["="], []))], []) => @@ -396,7 +425,10 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { | String(name) | Var(name) => ret( - TupLabel({ids: l.ids, copied: l.copied, term: Label(name)}, r), + Tuple([ + TupLabel({ids: l.ids, copied: l.copied, term: Label(name)}, r) + |> Pat.fresh, + ]), ) | _ => ret(TupLabel(l, r)) } @@ -472,7 +504,17 @@ and typ_term: unsorted => (UTyp.term, list(Id.t)) = { } | Bin(Typ(l), tiles, Typ(r)) as tm => switch (is_tuple_typ(tiles)) { - | Some(between_kids) => ret(Prod([l] @ between_kids @ [r])) + | Some(between_kids) => + let tuple_children = [l] @ between_kids @ [r]; + let mapping_fn = (child: Typ.t) => { + switch (child) { + | {term: Prod([{term: TupLabel(_), _} as tl]), _} => tl + | _ => child + }; + }; + let tuple_children: list(Typ.t) = List.map(mapping_fn, tuple_children); + + ret(Prod(tuple_children)); | None => switch (tiles) { | ([(_id, (["->"], []))], []) => ret(Arrow(l, r)) @@ -481,7 +523,10 @@ and typ_term: unsorted => (UTyp.term, list(Id.t)) = { switch (l.term) { | Var(name) => ret( - TupLabel({ids: l.ids, copied: l.copied, term: Label(name)}, r), + Prod([ + TupLabel({ids: l.ids, copied: l.copied, term: Label(name)}, r) + |> Typ.fresh, + ]), ) | _ => ret(TupLabel(l, r)) } diff --git a/test/Test_MakeTerm.re b/test/Test_MakeTerm.re index 84ce1b4525..2a503d64d5 100644 --- a/test/Test_MakeTerm.re +++ b/test/Test_MakeTerm.re @@ -34,4 +34,12 @@ let tests = [ "let x : (l=String) = \"a\" in x", ) }), + test_case("", `Quick, () => { + exp_check( + Int(7) |> Exp.fresh, + "let x = (l=32) in +let y : (l=Int) = x in + ", + ) + }), ]; From 78e817ce0d3ef5dd41d1f85de967d6255fc87f49 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 11 Oct 2024 15:06:33 -0400 Subject: [PATCH 054/108] Remove is_contained logic Co-authored-by: WondAli --- src/haz3lcore/statics/Statics.re | 93 +++++++++----------------------- test/Test_Elaboration.re | 10 ++-- test/Test_Statics.re | 9 ++-- 3 files changed, 35 insertions(+), 77 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index d8792fc221..91b4651255 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -171,7 +171,6 @@ and uexp_to_info_map = ~ctx: Ctx.t, ~mode=Mode.Syn, ~is_in_filter=false, - ~is_contained=false, ~ancestors, {ids, copied: _, term} as uexp: UExp.t, m: Map.t, @@ -208,30 +207,21 @@ and uexp_to_info_map = ~ctx, ~mode=Mode.Syn, ~is_in_filter=is_in_filter, - ~is_contained=false, ~ancestors=ancestors, uexp: UExp.t, m: Map.t, ) => { - uexp_to_info_map( - ~ctx, - ~mode, - ~is_in_filter, - ~is_contained, - ~ancestors, - uexp, - m, - ); + uexp_to_info_map(~ctx, ~mode, ~is_in_filter, ~ancestors, uexp, m); }; let go' = uexp_to_info_map(~ancestors); let go = go'(~ctx); - let map_m_go = (m, ~is_contained=false) => + let map_m_go = m => List.fold_left2( ((es, m), mode, e) => - go(~mode, e, m, ~is_contained) |> (((e, m)) => (es @ [e], m)), + go(~mode, e, m) |> (((e, m)) => (es @ [e], m)), ([], m), ); - let go_pat = upat_to_info_map(~ctx, ~ancestors, ~is_contained=false); + let go_pat = upat_to_info_map(~ctx, ~ancestors); let atomic = self => add(~self, ~co_ctx=CoCtx.empty, m); switch (term) { | Closure(_) => @@ -322,19 +312,11 @@ and uexp_to_info_map = let (labmode, mode) = Mode.of_label(ctx, mode); let (lab, m) = go(~mode=labmode, label, m); let (e, m) = go(~mode, e, m); - if (is_contained) { - add( - ~self=Just(TupLabel(lab.ty, e.ty) |> Typ.temp), - ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), - m, - ); - } else { - add( - ~self=Just(Prod([TupLabel(lab.ty, e.ty) |> Typ.temp]) |> Typ.temp), - ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), - m, - ); - }; + add( + ~self=Just(TupLabel(lab.ty, e.ty) |> Typ.temp), + ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), + m, + ); | BuiltinFun(string) => add'( ~self=Self.of_exp_var(Builtins.ctx_init, string), @@ -346,7 +328,7 @@ and uexp_to_info_map = Mode.of_prod(ctx, mode, es, UExp.get_label, (name, b) => TupLabel(Label(name) |> Exp.fresh, b) |> Exp.fresh ); - let (es', m) = map_m_go(m, modes, es, ~is_contained=true); + let (es', m) = map_m_go(m, modes, es); add( ~self=Just(Prod(List.map(Info.exp_ty, es')) |> Typ.temp), ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es')), @@ -802,7 +784,6 @@ and upat_to_info_map = ~co_ctx, ~ancestors: Info.ancestors, ~mode: Mode.t=Mode.Syn, - ~is_contained=false, {ids, term, _} as upat: UPat.t, m: Map.t, ) @@ -835,7 +816,6 @@ and upat_to_info_map = ~co_ctx, ~ancestors, ~mode, - ~is_contained=false, upat: UPat.t, m: Map.t, ) => { @@ -845,7 +825,6 @@ and upat_to_info_map = ~co_ctx, ~ancestors, ~mode, - ~is_contained, upat, m: Map.t, ); @@ -854,10 +833,10 @@ and upat_to_info_map = let ancestors = [UPat.rep_id(upat)] @ ancestors; let go = upat_to_info_map(~is_synswitch, ~ancestors, ~co_ctx); let unknown = Typ.Unknown(is_synswitch ? SynSwitch : Internal) |> Typ.temp; - let ctx_fold = (ctx: Ctx.t, m, ~is_contained=false) => + let ctx_fold = (ctx: Ctx.t, m) => List.fold_left2( ((ctx, tys, cons, m), e, mode) => - go(~ctx, ~mode, ~is_contained, e, m) + go(~ctx, ~mode, e, m) |> ( ((info, m)) => ( info.ctx, @@ -938,28 +917,18 @@ and upat_to_info_map = let (labmode, mode) = Mode.of_label(ctx, mode); let (lab, m) = go(~ctx, ~mode=labmode, label, m); let (p, m) = go(~ctx, ~mode, p, m); - if (is_contained) { - add( - ~self=Just(TupLabel(lab.ty, p.ty) |> Typ.temp), - ~ctx=p.ctx, - ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), - m, - ); - } else { - add( - ~self=Just(Prod([TupLabel(lab.ty, p.ty) |> Typ.temp]) |> Typ.temp), - ~ctx=p.ctx, - ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), - m, - ); - }; + add( + ~self=Just(TupLabel(lab.ty, p.ty) |> Typ.temp), + ~ctx=p.ctx, + ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), + m, + ); | Tuple(ps) => let (ps, modes) = Mode.of_prod(ctx, mode, ps, UPat.get_label, (name, b) => TupLabel(Label(name) |> UPat.fresh, b) |> UPat.fresh ); - let (ctx, tys, cons, m) = - ctx_fold(ctx, m, ps, modes, ~is_contained=true); + let (ctx, tys, cons, m) = ctx_fold(ctx, m, ps, modes); let rec cons_fold_tuple = cs => switch (cs) { | [] => Constraint.Truth @@ -1002,7 +971,6 @@ and utyp_to_info_map = ~ctx, ~expects=Info.TypeExpected, ~ancestors, - ~is_contained=false, {ids, term, _} as utyp: UTyp.t, m: Map.t, ) @@ -1013,8 +981,7 @@ and utyp_to_info_map = }; let ancestors = [UTyp.rep_id(utyp)] @ ancestors; let go' = utyp_to_info_map(~ctx, ~ancestors); - let go = (~is_contained=false) => - go'(~expects=TypeExpected, ~is_contained); + let go = go'(~expects=TypeExpected); switch (term) { | Unknown(Hole(MultiHole(tms))) => let (_, m) = multi(~ctx, ~ancestors, m, tms); @@ -1035,23 +1002,11 @@ and utyp_to_info_map = let m = go(t2, m) |> snd; add(m); | TupLabel(label, t) => - if (is_contained) { - let m = go(label, m) |> snd; - let m = go(t, m) |> snd; - add(m); - } else { - let m = map_m(go(~is_contained=true), [utyp], m) |> snd; - add( - ~utyp={ - term: Prod([utyp.term |> Typ.fresh]), - ids, - copied: utyp.copied, - }, - m, - ); - } + let m = go(label, m) |> snd; + let m = go(t, m) |> snd; + add(m); | Prod(ts) => - let m = map_m(go(~is_contained=true), ts, m) |> snd; + let m = map_m(go, ts, m) |> snd; add(m); | Ap(t1, t2) => let t1_mode: Info.typ_expects = diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index b9fe724c63..43af68088b 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -413,11 +413,11 @@ let elaboration_tests = [ ), test_case("Labeled tuple elaboration", `Quick, elaborated_labeled_tuple), test_case("Rearranged labeled tuple", `Quick, rearranged_labeled_tuple), - test_case( - "Singleton labeled tuple adds labels", - `Quick, - singleton_labeled_tuple_elaborates_labels, - ), + // test_case( // TODO Not sure if we want this case + // "Singleton labeled tuple adds labels", + // `Quick, + // singleton_labeled_tuple_elaborates_labels, + // ), test_case("Singleton labeled tuple", `Quick, singleton_labeled_tuple) // TODO Make consistent with make term // TODO Add singleton labeled function application ]; diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 652315d908..0d8b6b9535 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -198,16 +198,19 @@ let tests = ), ) ), - test_case("Unsure: Function with labeled param", `Quick, () => + test_case("Function with labeled param", `Quick, () => alco_check( - "fun (a=x) => 4", + "fun (a=x) -> 4", Some( arrow(prod([tup_label(label("a"), unknown(Internal))]), int), ), type_of( Fun( Parens( - TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + Tuple([ + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + |> Pat.fresh, + ]) |> Pat.fresh, ) |> Pat.fresh, From 7008809cc80b83bafb302ea648f619e134ae393b Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 11:36:06 -0400 Subject: [PATCH 055/108] More tests --- test/Test_MakeTerm.re | 45 +++++++++++++++++++++---- test/Test_Statics.re | 76 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 7 deletions(-) diff --git a/test/Test_MakeTerm.re b/test/Test_MakeTerm.re index 2a503d64d5..13894ee3bb 100644 --- a/test/Test_MakeTerm.re +++ b/test/Test_MakeTerm.re @@ -20,26 +20,57 @@ let tests = [ Cast( Var("x") |> Pat.fresh, Parens( - TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) // TODO Do we want to wrap the singleton case in a product + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) |> Typ.fresh, ) |> Typ.fresh, Unknown(Internal) |> Typ.fresh, ) |> Pat.fresh, - Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Should we require parens around singleton tables to ascribe labels + Parens(String("a") |> Exp.fresh) |> Exp.fresh, Var("x") |> Exp.fresh, ) |> Exp.fresh, - "let x : (l=String) = \"a\" in x", + "let x : (l=String) = (\"a\") in x", ) }), - test_case("", `Quick, () => { + test_case("Assigning labeled tuple to variable", `Quick, () => { exp_check( - Int(7) |> Exp.fresh, + Let( + Var("x") |> Pat.fresh, + Parens( + Tuple([ + TupLabel(Label("l") |> Exp.fresh, Int(32) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + Let( + Cast( + Var("y") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Var("x") |> Exp.fresh, + Var("y") |> Exp.fresh, + ) + |> Exp.fresh, + ) + |> Exp.fresh, "let x = (l=32) in -let y : (l=Int) = x in - ", + let y : (l=Int) = x in y", ) }), ]; diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 0d8b6b9535..bca2aea3d8 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -273,4 +273,80 @@ let tests = ), unlabeled_tuple_to_labeled_fails, simple_inconsistency, + test_case("Assigning labeled tuple to variable", `Quick, () => { + alco_check( + "let x = (l=32) in + let y : (l=Int) = x in y", + Some( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, + ]) + |> Typ.fresh, + ), + type_of( + Let( + Var("x") |> Pat.fresh, + Parens( + Tuple([ + TupLabel(Label("l") |> Exp.fresh, Int(32) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + Let( + Cast( + Var("y") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Var("x") |> Exp.fresh, + Var("y") |> Exp.fresh, + ) + |> Exp.fresh, + ) + |> Exp.fresh, + ), + ) + }), + test_case("Singleton Labled Tuple ascription in let", `Quick, () => { + alco_check( + "let x : (l=String) = (\"a\") in x", + Some( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ), + type_of( + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + ), + ) + }), ]; From 59ff548249959fb55d661a1efb25a199c692588f Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 12:27:16 -0400 Subject: [PATCH 056/108] Add assertions that there's no static errors in static tests --- test/Test_Statics.re | 210 ++++++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 90 deletions(-) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index bca2aea3d8..25fd2670bf 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -16,6 +16,9 @@ let testable_status_exp = | _ => false } }); + +let status_exp: testable(Info.status_exp) = + testable(Fmt.using(Info.show_status_exp, Fmt.string), (==)); module FreshId = { let arrow = (a, b) => Arrow(a, b) |> Typ.fresh; let unknown = a => Unknown(a) |> Typ.fresh; @@ -43,6 +46,30 @@ let info_of_id = (f: UExp.t, id: Id.t) => { let type_of = f => { Option.map((ie: Info.exp) => ie.ty, info_of_id(f, IdTagged.rep_id(f))); }; + +let fully_consistent_typecheck = (name, serialized, expected, exp) => { + test_case( + name, + `Quick, + () => { + let s = statics(exp); + let errors = + List.map( + (id: Id.t) => { + let info = Id.Map.find(id, s); + switch (info) { + | InfoExp(ie) => ie.status + | _ => fail("Expected InfoExp") + }; + }, + Statics.Map.error_ids(s), + ); + Alcotest.check(list(status_exp), "Static Errors", [], errors); + alco_check(serialized, expected, type_of(exp)); + }, + ); +}; + let reusable_id = Id.mk(); let unlabeled_tuple_to_labeled_fails = test_case( @@ -244,109 +271,112 @@ let tests = ), ) ), - test_case("function application", `Quick, () => - alco_check( - "float_of_int(1)", - Some(float), - type_of( - Ap(Forward, Var("float_of_int") |> Exp.fresh, Int(1) |> Exp.fresh) - |> Exp.fresh, - ), + fully_consistent_typecheck( + "bifunction", + "x : Int, y: Int => x + y", + Some(arrow(prod([int, int]), int)), + Fun( + Tuple([ + Cast(Var("x") |> Pat.fresh, int, unknown(Internal)) |> Pat.fresh, + Cast(Var("y") |> Pat.fresh, int, unknown(Internal)) |> Pat.fresh, + ]) + |> Pat.fresh, + BinOp(Int(Plus), Var("x") |> Exp.fresh, Var("y") |> Exp.fresh) + |> Exp.fresh, + None, + None, ) + |> Exp.fresh, ), - test_case("function deferral", `Quick, () => - alco_check( - "string_sub(\"hello\", 1, _)", - Some(arrow(int, string)), - type_of( - DeferredAp( - Var("string_sub") |> Exp.fresh, - [ - String("hello") |> Exp.fresh, - Int(1) |> Exp.fresh, - Deferral(InAp) |> Exp.fresh, - ], - ) - |> Exp.fresh, - ), + fully_consistent_typecheck( + "function application", + "float_of_int(1)", + Some(float), + Ap(Forward, Var("float_of_int") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ), + fully_consistent_typecheck( + "function deferral", + "string_sub(\"hello\", 1, _)", + Some(arrow(int, string)), + DeferredAp( + Var("string_sub") |> Exp.fresh, + [ + String("hello") |> Exp.fresh, + Int(1) |> Exp.fresh, + Deferral(InAp) |> Exp.fresh, + ], ) + |> Exp.fresh, ), unlabeled_tuple_to_labeled_fails, simple_inconsistency, - test_case("Assigning labeled tuple to variable", `Quick, () => { - alco_check( - "let x = (l=32) in - let y : (l=Int) = x in y", - Some( - Prod([ - TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, + fully_consistent_typecheck( + "Assigning labeled tuple to variable", + "let x = (l=32) in let y : (l=Int) = x in y", + Some( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, + ]) + |> Typ.fresh, + ), + Let( + Var("x") |> Pat.fresh, + Parens( + Tuple([ + TupLabel(Label("l") |> Exp.fresh, Int(32) |> Exp.fresh) + |> Exp.fresh, ]) - |> Typ.fresh, - ), - type_of( - Let( - Var("x") |> Pat.fresh, + |> Exp.fresh, + ) + |> Exp.fresh, + Let( + Cast( + Var("y") |> Pat.fresh, Parens( - Tuple([ - TupLabel(Label("l") |> Exp.fresh, Int(32) |> Exp.fresh) - |> Exp.fresh, - ]) - |> Exp.fresh, - ) - |> Exp.fresh, - Let( - Cast( - Var("y") |> Pat.fresh, - Parens( - Prod([ - TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) - |> Typ.fresh, - ]) - |> Typ.fresh, - ) + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, - Unknown(Internal) |> Typ.fresh, - ) - |> Pat.fresh, - Var("x") |> Exp.fresh, - Var("y") |> Exp.fresh, + ]) + |> Typ.fresh, ) - |> Exp.fresh, + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, ) - |> Exp.fresh, - ), + |> Pat.fresh, + Var("x") |> Exp.fresh, + Var("y") |> Exp.fresh, + ) + |> Exp.fresh, ) - }), - test_case("Singleton Labled Tuple ascription in let", `Quick, () => { - alco_check( - "let x : (l=String) = (\"a\") in x", - Some( - Prod([ - TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) - |> Typ.fresh, - ]) - |> Typ.fresh, - ), - type_of( - Let( - Cast( - Var("x") |> Pat.fresh, - Parens( - Prod([ - TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) - |> Typ.fresh, - ]) - |> Typ.fresh, - ) + |> Exp.fresh, + ), + fully_consistent_typecheck( + "Singleton Labled Tuple ascription in let", + "let x : (l=String) = (\"a\") in x", + Some( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, + ]) + |> Typ.fresh, + ), + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, - Unknown(Internal) |> Typ.fresh, - ) - |> Pat.fresh, - Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch - Var("x") |> Exp.fresh, + ]) + |> Typ.fresh, ) - |> Exp.fresh, - ), + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Var("x") |> Exp.fresh, ) - }), + |> Exp.fresh, + ), ]; From 0669d9c4f622736354a6eaf96e9d572f0c2b539d Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 13:20:37 -0400 Subject: [PATCH 057/108] Ensure more tests are fully consistent --- test/Test_Statics.re | 122 +++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 25fd2670bf..029cececd8 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -193,83 +193,67 @@ let unapplied_function = () => let tests = FreshId.[ - test_case("Function with unknown param", `Quick, () => - alco_check( - "x => 4 + 5", - Some(arrow(unknown(Internal), int)), - type_of( - Fun( - Var("x") |> Pat.fresh, - BinOp(Int(Plus), Int(4) |> Exp.fresh, Int(5) |> Exp.fresh) - |> Exp.fresh, - None, - None, - ) - |> Exp.fresh, - ), + fully_consistent_typecheck( + "Function with unknown param", + "x => 4 + 5", + Some(arrow(unknown(Internal), int)), + Fun( + Var("x") |> Pat.fresh, + BinOp(Int(Plus), Int(4) |> Exp.fresh, Int(5) |> Exp.fresh) + |> Exp.fresh, + None, + None, ) + |> Exp.fresh, ), - test_case("Function with known param", `Quick, () => - alco_check( - "x : Int => 4 + 5", - Some(arrow(int, int)), - type_of( - Fun( - Cast(Var("x") |> Pat.fresh, int, unknown(Internal)) |> Pat.fresh, - BinOp(Int(Plus), Int(4) |> Exp.fresh, Int(5) |> Exp.fresh) - |> Exp.fresh, - None, - None, - ) - |> Exp.fresh, - ), + fully_consistent_typecheck( + "Function with known param", + "x : Int => 4 + 5", + Some(arrow(int, int)), + Fun( + Cast(Var("x") |> Pat.fresh, int, unknown(Internal)) |> Pat.fresh, + BinOp(Int(Plus), Int(4) |> Exp.fresh, Int(5) |> Exp.fresh) + |> Exp.fresh, + None, + None, ) + |> Exp.fresh, ), - test_case("Function with labeled param", `Quick, () => - alco_check( - "fun (a=x) -> 4", - Some( - arrow(prod([tup_label(label("a"), unknown(Internal))]), int), - ), - type_of( - Fun( - Parens( - Tuple([ - TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) - |> Pat.fresh, - ]) - |> Pat.fresh, - ) + fully_consistent_typecheck( + "Function with labeled param", + "fun (a=x) -> 4", + Some(arrow(prod([tup_label(label("a"), unknown(Internal))]), int)), + Fun( + Parens( + Tuple([ + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) |> Pat.fresh, - Int(4) |> Exp.fresh, - None, - None, - ) - |> Exp.fresh, - ), + ]) + |> Pat.fresh, + ) + |> Pat.fresh, + Int(4) |> Exp.fresh, + None, + None, ) + |> Exp.fresh, ), - test_case("bifunction", `Quick, () => - alco_check( - "x : Int, y: Int => x + y", - Some(arrow(prod([int, int]), int)), - type_of( - Fun( - Tuple([ - Cast(Var("x") |> Pat.fresh, int, unknown(Internal)) - |> Pat.fresh, - Cast(Var("y") |> Pat.fresh, int, unknown(Internal)) - |> Pat.fresh, - ]) - |> Pat.fresh, - BinOp(Int(Plus), Var("x") |> Exp.fresh, Var("y") |> Exp.fresh) - |> Exp.fresh, - None, - None, - ) - |> Exp.fresh, - ), + fully_consistent_typecheck( + "bifunction", + "x : Int, y: Int => x + y", + Some(arrow(prod([int, int]), int)), + Fun( + Tuple([ + Cast(Var("x") |> Pat.fresh, int, unknown(Internal)) |> Pat.fresh, + Cast(Var("y") |> Pat.fresh, int, unknown(Internal)) |> Pat.fresh, + ]) + |> Pat.fresh, + BinOp(Int(Plus), Var("x") |> Exp.fresh, Var("y") |> Exp.fresh) + |> Exp.fresh, + None, + None, ) + |> Exp.fresh, ), fully_consistent_typecheck( "bifunction", From c27642baf05c9fefb343963dc94cda1843b07d1e Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 13:32:05 -0400 Subject: [PATCH 058/108] Stop recalculating statics in tests --- test/Test_Statics.re | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 029cececd8..4734ff342d 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -34,8 +34,12 @@ let id_at = x => x |> List.nth(ids); let statics = Statics.mk(CoreSettings.on, Builtins.ctx_init); let alco_check = Alcotest.option(testable_typ) |> Alcotest.check; -let info_of_id = (f: UExp.t, id: Id.t) => { - let s = statics(f); +let info_of_id = (~statics_map=?, f: UExp.t, id: Id.t) => { + let s = + switch (statics_map) { + | Some(s) => s + | None => statics(f) + }; switch (Id.Map.find(id, s)) { | InfoExp(ie) => Some(ie) | _ => None @@ -43,8 +47,11 @@ let info_of_id = (f: UExp.t, id: Id.t) => { }; // Get the type from the statics -let type_of = f => { - Option.map((ie: Info.exp) => ie.ty, info_of_id(f, IdTagged.rep_id(f))); +let type_of = (~statics_map=?, f) => { + Option.map( + (ie: Info.exp) => ie.ty, + info_of_id(~statics_map?, f, IdTagged.rep_id(f)), + ); }; let fully_consistent_typecheck = (name, serialized, expected, exp) => { @@ -65,7 +72,7 @@ let fully_consistent_typecheck = (name, serialized, expected, exp) => { Statics.Map.error_ids(s), ); Alcotest.check(list(status_exp), "Static Errors", [], errors); - alco_check(serialized, expected, type_of(exp)); + alco_check(serialized, expected, type_of(~statics_map=s, exp)); }, ); }; From bcd9fe279b622d7dc21dd8c4ad30dc32a36699c7 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 17:14:40 -0400 Subject: [PATCH 059/108] Add support for displaying TupLabel with label and type in view_ty function --- src/haz3lweb/view/Type.re | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/haz3lweb/view/Type.re b/src/haz3lweb/view/Type.re index d1ff7c839b..2ca7552a76 100644 --- a/src/haz3lweb/view/Type.re +++ b/src/haz3lweb/view/Type.re @@ -32,7 +32,12 @@ let rec view_ty = (~strip_outer_parens=false, ty: Haz3lcore.Typ.t): Node.t => | Label(name) => ty_view("Label", name) | Bool => ty_view("Bool", "Bool") | Var(name) => ty_view("Var", name) - | TupLabel(_, ty) => view_ty(ty) // TODO (Anthony): What to do here? + | TupLabel({term: Label(l), _}, ty) => + div( + ~attrs=[clss(["typ-view", "TupLabel"])], + [text(l ++ "="), view_ty(ty)], + ) + | TupLabel(_, ty) => view_ty(ty) // This should be impossible | Rec(name, t) => div( ~attrs=[clss(["typ-view", "Rec"])], From 926c5c75d140ea71f76e9ea9bba2a5bd6d2e68a0 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 20:33:00 -0400 Subject: [PATCH 060/108] Add labeled tuples doc page --- src/haz3lweb/Init.ml | 1152 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1148 insertions(+), 4 deletions(-) diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index c3d2de0aba..b3a19e84ec 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -37,10 +37,553 @@ let startup : PersistentData.t = { zipper = "((selection((focus Left)(content())(mode \ - Normal)))(backpack())(relatives((siblings((((Grout((id \ - e87c8d67-9374-4a6f-ba01-5ec8f300b924)(shape \ - Convex))))))(ancestors())))(caret Outer))"; - backup_text = ""; + Normal)))(backpack())(relatives((siblings(((Secondary((id \ + 1d22b099-baac-4811-86f4-3d4b778b8d04)(content(Comment\"# \ + Labeled Tuples #\"))))(Secondary((id \ + 029cce32-17ab-490b-b2f1-e25219197dff)(content(Whitespace\"\\n\"))))(Secondary((id \ + c3e170b1-8aeb-46f6-a78d-49cb6d86915a)(content(Whitespace\"\\n\"))))(Secondary((id \ + b1a9fa5d-4671-44c8-a303-96d7400f23d3)(content(Comment\"# Tuples \ + can have labels#\"))))(Secondary((id \ + 668efc29-986d-4f42-905e-84c7606b176b)(content(Whitespace\"\\n\"))))(Tile((id \ + 23795a9d-fa91-437f-a445-3652ac99fea5)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 0ab08c67-2641-47c5-bad2-bb0fa0b577fa)(content(Whitespace\" \ + \"))))(Tile((id \ + 374004dd-f688-48f3-9aa0-5752419d8775)(label(labeled_tuple))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 776dce9f-e223-4a19-995e-fdb5e9d5fbab)(content(Whitespace\" \ + \")))))((Secondary((id \ + aeeee415-16ca-459f-9fba-3820adc957b6)(content(Whitespace\" \ + \"))))(Tile((id \ + c73cedb9-eef3-4a02-8ea0-dc89c6b0ffce)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 08be2aff-62bb-4bb1-919f-b4d81f5b87eb)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + ba0c2fe0-2a43-4004-b3b1-ced4b85b3449)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 4b14f8cf-7e92-4b28-8495-309f8e6bd981)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 64acb788-0804-4a9e-b065-2235b21c3b02)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + cc891159-5869-4dfc-8f7c-0fd0116b343b)(content(Whitespace\" \ + \"))))(Tile((id \ + 577eb92e-9228-482f-a39b-bc7d25ea3a74)(label(b))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 23e7b4b7-a92a-43eb-93a2-24a4a671161a)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 0e01f92e-4201-4b0c-ab18-c02dd502075e)(label(2.0))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + b6c69ff0-709b-490b-b309-1c9cb38ac5c1)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 96b4438c-a9f8-4b92-971d-d0d4a1b19961)(content(Whitespace\" \ + \"))))(Tile((id \ + cb883be5-c6a8-47d1-8a7e-5f43b07d41cd)(label(c))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 82552269-8149-450d-b422-64c7493c13e1)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 163f4628-edf1-4911-9364-689f5f238c82)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + d60bb231-bfe5-4b6d-8a53-46b2821680dd)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 5038abcb-455b-47da-8ce6-4d3be238998a)(content(Whitespace\"\\n\"))))(Secondary((id \ + ca401b23-4366-4cdf-957a-a6a39b861998)(content(Comment\"# These \ + labels can be projected #\"))))(Secondary((id \ + 4e035ed4-f928-4593-a7f8-491435d7137e)(content(Whitespace\"\\n\"))))(Tile((id \ + 6e28c23a-375a-4f47-80d1-11a0dbdbfd3e)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + cb2d5793-8d88-4d3a-9a4f-5ca82aefc774)(content(Whitespace\" \ + \"))))(Tile((id \ + 7bbbf7b6-ebdc-4e58-bdca-2654b0ccb9d6)(label(prj_a))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + c5b250bb-1fb9-4276-b793-0221b252c8b1)(content(Whitespace\" \ + \"))))(Tile((id \ + 2fad8b7f-6410-47e2-8786-4798001dcdb7)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ + 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + b92af63d-5b68-440d-ac0a-3cc6ae28330f)(content(Whitespace\" \ + \"))))(Tile((id \ + 09a6433d-266d-4aef-b528-7920b2650305)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + f24cff31-85a2-4d6f-ad5c-4a2284b7f17e)(content(Whitespace\" \ + \")))))((Secondary((id \ + 17dbbfc0-656a-46fd-9365-c1c2ea6dd286)(content(Whitespace\" \ + \"))))(Tile((id \ + 2effe10f-7e24-4907-a7b3-cf4b34b663e9)(label(labeled_tuple))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 6d7af305-b6c2-4a5c-bfde-edda62f126bf)(label(.))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 2))(sort Exp))((shape(Concave \ + 2))(sort Exp))))))(shards(0))(children())))(Tile((id \ + bdef8806-3ecc-4c67-be5c-cf7d3ed2fce9)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 4dc7a1ca-8770-467b-a81c-a245429d62ff)(content(Whitespace\" \ + \"))))(Secondary((id \ + 97350724-14de-4cfe-b5dc-820beca6a652)(content(Comment\"# 1 \ + #\"))))(Secondary((id \ + 6e55064c-2947-4769-b4bb-29d560f662f6)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + ca0d2c33-96ef-44c6-ac6e-f8a4d7901280)(content(Whitespace\" \ + \"))))(Secondary((id \ + 98524bad-9684-472a-a0c8-b1204357df66)(content(Whitespace\"\\n\"))))(Secondary((id \ + 38404748-91f8-4ff9-bf3e-6079ab3a3add)(content(Whitespace\"\\n\")))))((Secondary((id \ + fbc19dd7-8fdb-4932-87af-5b52f6a093bb)(content(Comment\"# These \ + can be encoded the types #\"))))(Secondary((id \ + 312fb397-2960-419d-8012-b3844228b045)(content(Whitespace\"\\n\"))))(Tile((id \ + 791f51eb-c011-424e-b6f7-c38517c3c5d3)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 1061312e-02d1-4ac2-b2b5-0432ef53c6c3)(content(Whitespace\" \ + \"))))(Tile((id \ + 1d69bc5e-76dc-4de1-96ba-f3c6e0704a2b)(label(typed_lt))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + be603a96-4fc1-4b57-8dcc-0768264c9798)(content(Whitespace\" \ + \"))))(Tile((id \ + 7eedad44-3ec3-4256-b621-ac301d91dad2)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ + 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 9671104c-9ffa-4912-9f21-f46b308d0335)(content(Whitespace\" \ + \"))))(Tile((id \ + ea52c55a-ba30-473d-8214-a685ffde4eb3)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 2d81cb0d-d4c0-4032-8fe3-b734f68d5343)(label(a))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 1a7028bc-734d-40ce-b63b-baa31eb5966a)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ + 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ + 39fc34a0-cdd6-476f-a0c6-e15de827ad81)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 11f70cfb-7527-4965-8e86-36cd99dd1470)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ + 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 0c00141e-9c75-45aa-bc2b-4927df8fd199)(content(Whitespace\" \ + \"))))(Tile((id \ + b3753058-016c-47ca-b53c-d4e663a9d39f)(label(b))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + c9f6de02-1793-4006-b79b-074ec663efad)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ + 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ + 295bbc9b-86d8-454c-adfb-51b9bbb37abe)(label(Float))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + c7d366ac-c0db-47b5-ba48-9d7a78be4a28)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ + 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + bd447665-f6cf-4bb9-9bfb-a9782e7125b3)(content(Whitespace\" \ + \"))))(Tile((id \ + c6c89a67-1cbb-41c0-98bf-3e5d875fb9cd)(label(c))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + f626e35e-b6af-4e72-b758-df9c9ce90493)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ + 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ + 2041fea5-1d59-4998-9f2e-3d7d20e8f519)(label(Bool))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 7c74d480-0097-4740-a918-7b5345a875eb)(content(Whitespace\" \ + \")))))((Secondary((id \ + 058c6341-431b-4045-98f3-1227ac57bca1)(content(Whitespace\" \ + \"))))(Tile((id \ + cbcebeee-2946-41d7-af56-10acfc3ee98b)(label(labeled_tuple))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 95cf3af0-a1f4-4639-802b-8e6a68b821aa)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 7df90b9b-fc87-4093-8a73-f1dd5f9b4e7b)(content(Whitespace\"\\n\"))))(Secondary((id \ + 87181a2a-7168-4fcb-922c-03c6f08cb29a)(content(Whitespace\"\\n\"))))(Secondary((id \ + 2d1cd3ec-0347-4ad3-8d1d-f90b8ee226bc)(content(Comment\"# Labels \ + are optional and can be interspersed throughout a label \ + #\"))))(Secondary((id \ + 6304d9bb-70f1-4711-af0a-3ceca5abf350)(content(Whitespace\"\\n\"))))(Tile((id \ + c03a5bf0-5b40-4db5-833d-aa7ccc5f1de9)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 8ce73b84-f462-45d0-b8f9-c5b1ec532ece)(content(Whitespace\" \ + \"))))(Tile((id \ + a16b7bdb-34bc-481b-99a2-d9b3fe4c43e9)(label(mixed_labels))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 88c2b5e3-4624-4004-956c-e2c4e56ada6c)(content(Whitespace\" \ + \"))))(Tile((id \ + e1b247ba-d61f-4616-88df-064c2b7fd3a6)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ + 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + e47e4eee-8023-46a0-9f3e-cbd22343c821)(content(Whitespace\" \ + \"))))(Tile((id \ + b1d12b65-0bde-4897-be50-9382a322d257)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 085dbae6-4130-4b47-92ca-5292fe150994)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + e55ee8c2-9a8a-4139-9ea1-682d2d310402)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ + 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 9d5cfb64-78af-4a52-9833-6431217e882c)(content(Whitespace\" \ + \"))))(Tile((id \ + 3b1add0f-323b-4023-a55c-a42fd1032b4d)(label(a))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 977eb5ad-75f9-4480-baa0-50c6e374f0ba)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ + 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ + 19b644d1-a6a0-41ba-8624-61eeaad5e300)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + e54ed288-ac41-4a9f-841d-5243dc7376c1)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ + 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 513ff80c-bf03-4deb-b410-29faeac69a2d)(content(Whitespace\" \ + \"))))(Tile((id \ + 2a77c478-08ea-4569-81ef-c3b7cc56d0e1)(label(Float))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + ab9239e3-4316-44cb-9899-9aa69c755279)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ + 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + c548f75f-47a0-4ab4-86e8-69e634a4cca6)(content(Whitespace\" \ + \"))))(Tile((id \ + 3c55d843-a871-418c-9eff-da75446c297e)(label(flag))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + d1ed7227-a849-44ab-9890-8d264b5f1945)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ + 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ + 020058df-9514-49a0-9645-677851c38bb2)(label(Bool))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 40c93475-ca3b-41e8-8b21-1051f0fa687f)(content(Whitespace\" \ + \")))))((Secondary((id \ + e6102414-8e6a-49d8-8a4b-c30d478ff2c4)(content(Whitespace\" \ + \"))))(Tile((id \ + b28ba9ca-6b59-4d5c-9fcf-6ae44e1e204f)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 88d1e44a-ec5a-4157-ae30-75bf01cad38c)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 21c197df-d99d-4d9d-a358-a67c10d5cccc)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + cb832565-6203-49ff-b53e-64fd5b3c6e49)(content(Whitespace\" \ + \"))))(Tile((id \ + cce72259-be1e-4bc7-8500-1ba2bf15c674)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4a61fc13-383b-47a7-972b-d6faa7503456)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 3a55f509-fd99-44fa-8ee1-3d41554353bf)(label(\"\\\"String \ + Value\\\"\"))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 51c1a82b-60b3-4c5a-8626-08a974105ae1)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 5eb818c5-d046-4862-b6e4-03e135fc56cf)(content(Whitespace\" \ + \"))))(Tile((id \ + 65876d7a-f0ab-4fba-a53a-00bd9b55dcfc)(label(2.5))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + ab3377df-c4ba-45ff-a280-888d3a4c0ae7)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 333f4c49-4a0d-4ea9-841b-e8b6f43a8765)(content(Whitespace\" \ + \"))))(Tile((id \ + 0e51bceb-1bf0-40b1-b825-225d9c42c415)(label(flag))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + d67f063a-acd8-4bb0-86e6-87b8a6314bba)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 3b3683bc-a873-49ff-9aab-9f5d2ff8a384)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + b0a7bb24-0bdd-4ff7-8792-c404acc07832)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 006326dd-00d8-4ffd-99e0-f9e14310393f)(content(Whitespace\"\\n\"))))(Secondary((id \ + 9cee0316-ff16-45fc-8222-5a8004de1f1b)(content(Whitespace\"\\n\"))))(Tile((id \ + ca249965-e64a-4466-9054-2f8b8087e172)(label(type = \ + in))(mold((out Exp)(in_(TPat Typ))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + ce8336b7-fd8f-4766-9bc2-85e041f76ea2)(content(Whitespace\" \ + \"))))(Tile((id \ + dffcb8bd-d722-48ab-93b8-d096a011b106)(label(Person))(mold((out \ + TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ + Convex)(sort TPat))))))(shards(0))(children())))(Secondary((id \ + 6c2dfa03-96af-4244-9ad1-5aca79846f59)(content(Whitespace\" \ + \")))))((Secondary((id \ + 28b30431-f967-4a84-b719-3ee6dd323971)(content(Whitespace\" \ + \"))))(Tile((id \ + d46306e3-6845-4d24-9e26-b4b0292ec03b)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 71962028-dd1f-4b58-8881-6e72e881deb7)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + c087cb02-0d08-4b91-8e34-99a0f2369e1a)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ + 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + a3cc0163-1461-4774-b351-3be27ddb56ec)(content(Whitespace\" \ + \"))))(Tile((id \ + b1c7750d-d878-4561-bfd5-c8583121858b)(label(age))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 03ce37fb-27dc-4b48-a329-d0538384b590)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ + 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ + 083755c0-e2a7-465e-9fb8-b1fb5d73725c)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 745a5f93-acf5-4e56-9ef8-6d9c9e9df676)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ + 18))(sort Typ))))))(shards(0))(children())))(Tile((id \ + 67a5db8b-7000-45f6-ae8f-86027d382414)(label(favorite_color))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 10cf3666-399c-4136-be8f-60a561558bbe)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ + 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ + f095c3a4-97e2-4433-aa7d-33ffa6775118)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 0254047f-2d49-49da-a292-8ae1c8bd9315)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 30456699-1693-415d-a38e-b103a1d4f4ca)(content(Whitespace\"\\n\"))))(Secondary((id \ + 4a35bd2e-ceac-4010-9b5e-b96baa3abef7)(content(Comment\"# These \ + labels can be automatically applied based on the type \ + expectation #\"))))(Secondary((id \ + e9813292-9c79-4183-9279-a341eacd3539)(content(Whitespace\"\\n\"))))(Tile((id \ + 0dfaf809-1beb-41e2-827a-bb9892dc0dbe)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 4911aaae-dcab-49b2-b114-dc86b6af73b8)(content(Whitespace\" \ + \"))))(Tile((id \ + 8b2a6afc-1c96-4e7e-b272-d516fb60c351)(label(alice))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 83a57212-492f-4c9e-b2d4-c5633c00492f)(content(Whitespace\" \ + \"))))(Tile((id \ + 0b4b1269-4a3b-4d77-8573-a57eaa2c2ff2)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ + 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 97236a27-c11a-4f08-a6dc-f2095a2ad44d)(content(Whitespace\" \ + \"))))(Tile((id \ + 221deda5-eb21-40a7-83b8-a4d3f0c72747)(label(Person))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 8c693b47-51a0-4394-a36d-0c55ed746ba2)(content(Whitespace\" \ + \")))))((Secondary((id \ + d84f659d-563b-4065-8352-0b48a0dbbc15)(content(Whitespace\" \ + \"))))(Tile((id \ + 3fce66bd-c247-471c-92b2-baabe04684aa)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + c3e4496d-c777-49da-b359-e87e57f500d8)(label(\"\\\"Alice\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 48ba350a-53b5-4afa-905a-8b113add1293)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 3f69e5d2-93c3-4464-9929-7684a8b4cce8)(content(Whitespace\" \ + \"))))(Tile((id \ + ead66a1a-2749-4c00-8c72-a1be1dbd9138)(label(22))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 8d300e9e-01fb-4ca7-98f9-d0e6761eee55)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 4f18f100-b7fa-4a75-9c20-bc59f55991b1)(content(Whitespace\" \ + \"))))(Tile((id \ + 8658b876-0dbe-41d2-8012-42a1d9eeedbd)(label(\"\\\"Blue\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + c3ebb086-566a-44a9-a3f1-02778e67cd50)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 87947367-9bf5-458f-a957-fd401c6fe62d)(content(Whitespace\"\\n\"))))(Secondary((id \ + 6ee9768e-9165-4e4b-9edc-0f5b431f3b4e)(content(Comment\"# \ + Explicitly Labeled elements are automatically \ + reordered#\"))))(Secondary((id \ + 160bfc3e-2922-46da-8880-6a55ec4e8f08)(content(Whitespace\"\\n\"))))(Tile((id \ + 9fb5dc17-bf6f-42a1-bad6-a7141ab485ff)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 44556e11-4a18-4808-8e3b-96a449991571)(content(Whitespace\" \ + \"))))(Tile((id \ + 1915e41b-fe9e-4d75-8147-05a8de710213)(label(bob))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 936f49f0-7701-46d3-9106-c5a513d9bcd8)(content(Whitespace\" \ + \"))))(Tile((id \ + ea62f713-8e6c-43ee-ad43-7960aa751f42)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ + 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ + cd474fd5-2959-4f9c-a1b4-5fdf2dd5a8bd)(content(Whitespace\" \ + \"))))(Tile((id \ + fd2b6d83-7e76-4bc5-9ee9-acf808142cb2)(label(Person))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 5fc66ce9-3fab-4aef-85a9-4bef5b776355)(content(Whitespace\" \ + \")))))((Secondary((id \ + 6f0cfe1c-1274-4ca6-9230-a41ac4afd6ea)(content(Whitespace\" \ + \"))))(Tile((id \ + d5fcc42c-8f5e-429b-bca3-e0316b162a7a)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + b4672fe9-7b7f-486c-9fd7-31caa7a850dd)(label(age))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + f0bac892-177e-4d96-88de-e4d17dc891c0)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 1c4d0130-d17f-432b-8692-f87ab2c096a8)(label(25))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 05e7f039-2de3-4e31-91eb-a99c4566d90b)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 21495a10-72b3-4ced-9292-fc8c8415cd4b)(content(Whitespace\" \ + \"))))(Tile((id \ + 79158e46-09bb-4bdd-9e94-d43513f0a6cc)(label(favorite_color))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 90a05943-35bb-4045-84d5-1a9d9f4f9933)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ + 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 46b0779f-2d9e-4171-abab-3a5e49ee6f57)(label(\"\\\"Red\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 2fa915a0-88fb-45f9-ba3b-d05260c06e4e)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ + 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ + a08417ac-4577-411a-854a-eda4acf4964b)(content(Whitespace\" \ + \"))))(Tile((id \ + 3a8e7e83-74ec-444a-a7df-06d68f289bc3)(label(\"\\\"Bob\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + db14a17f-90ca-498b-af9e-8690c183c312)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 55d9fe07-3edd-4db1-98c4-881a873ecaa2)(content(Whitespace\" \ + \"))))(Secondary((id \ + 3aeb958c-78e8-41ca-8bd8-e4fe58ab1279)(content(Comment\"# equals \ + (\\\"Bob\\\", age=25, \ + favorite_color=\\\"Red\\\")#\"))))(Secondary((id \ + 3dc6447b-da88-4cc0-8d41-fa06812d2f2b)(content(Whitespace\"\\n\"))))(Secondary((id \ + 105ece24-a726-45da-87f3-6888e1cdedbe)(content(Whitespace\"\\n\"))))(Secondary((id \ + 0a3fa6fe-890f-434b-b9f9-fb84b56a81fb)(content(Comment\"# \ + Destructuring #\"))))(Secondary((id \ + dfcae445-0ba1-4676-91e0-3273c23f9766)(content(Whitespace\"\\n\"))))(Tile((id \ + e91a3973-b16d-49a4-a59d-380a2979c970)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 892a74b8-31ca-477d-abd8-386d58d88f28)(content(Whitespace\" \ + \"))))(Tile((id \ + 88159ab5-30b8-46d7-9f90-475b8d94c1f4)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 60d7049c-eb88-4791-9809-6b99b6678e38)(label(bobs_name))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + f6bff178-21db-4571-99d6-620d4d3d3bcb)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 18))(sort Pat))((shape(Concave \ + 18))(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 1fd05df6-54a0-4a88-b9ea-a3c9d4081260)(content(Whitespace\" \ + \"))))(Tile((id \ + 937f5455-014e-49ee-9582-b8b2d41115b0)(label(age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 060f122d-3e7b-4bc1-bf84-9642626f1555)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort Pat))((shape(Concave \ + 16))(sort Pat))))))(shards(0))(children())))(Tile((id \ + 3206215b-978a-4d6b-8ae9-1b9210b0d49b)(label(bobs_age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 965a3191-2574-4447-b05b-0d40f9d83946)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 18))(sort Pat))((shape(Concave \ + 18))(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 38246b0f-0bee-46e7-b01b-0d8afc2fbd0d)(content(Whitespace\" \ + \"))))(Tile((id \ + 407f97ee-e857-4ce8-83fe-634df9404c38)(label(favorite_color))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 34a291de-b553-482e-92fb-b0ec3a2c6e0a)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort Pat))((shape(Concave \ + 16))(sort Pat))))))(shards(0))(children())))(Tile((id \ + 30328d7c-b472-4dae-b050-6d959fe7be32)(label(bobs_favorite_color))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 2d1138cf-7b53-4891-bbe7-9443bc061639)(content(Whitespace\" \ + \")))))((Secondary((id \ + 90bf31c2-7807-4d05-af22-bfb0803990a2)(content(Whitespace\" \ + \"))))(Tile((id \ + 3d677f5a-b880-49e5-9171-ed5a21307452)(label(bob))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 99c467af-0605-4a51-814b-6fe35edb5b59)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 1672c094-ce77-4a2c-a610-f352d9c00f7f)(content(Whitespace\"\\n\"))))(Secondary((id \ + 183b912f-dde9-4f06-8047-2b73d3e7ac89)(content(Whitespace\"\\n\"))))(Grout((id \ + 108cfcfd-2e17-407c-8380-ec1e63151450)(shape \ + Convex)))(Secondary((id \ + 867bbf01-916d-4d3e-9b99-1d4337659f57)(content(Whitespace\" \ + \"))))(Secondary((id \ + 0342f646-322c-4f68-98cf-de94b4df6e3d)(content(Whitespace\"\\n\"))))(Secondary((id \ + fa4a94d2-5955-4f8a-a958-6d8c8ebeaefb)(content(Whitespace\"\\n\"))))(Secondary((id \ + d6e2d5c6-1ac7-42ca-9894-0f26ea900668)(content(Whitespace\"\\n\")))))))(ancestors())))(caret(Inner \ + 33 13)))"; + backup_text = + "# Labeled Tuples #\n\n\ + # Tuples can have labels#\n\ + let labeled_tuple = (a=1, b=2.0, c=true) in\n\ + # These labels can be projected #\n\ + let prj_a : Int = labeled_tuple.a # 1 # in \n\n\ + # These can be encoded the types #\n\ + let typed_lt : (a=Int, b=Float, c=Bool) = labeled_tuple in\n\n\ + # Labels are optional and can be interspersed throughout a \ + label #\n\ + let mixed_labels : (Int, a=String, Float, flag=Bool) = (1, \ + a=\"String Value\", 2.5, flag=true) in\n\n\ + type Person = (String, age=Int,favorite_color=String) in\n\ + # These labels can be automatically applied based on the type \ + expectation #\n\ + let alice : Person = (\"Alice\", 22, \"Blue\") in\n\ + # Explicitly Labeled elements are automatically reordered#\n\ + let bob : Person = (age=25, favorite_color=\"Red\", \"Bob\") in \ + # equals (\"Bob\", age=25, favorite_color=\"Red\")#\n\n\ + # Destructuring #\n\ + let (bobs_name, age=bobs_age, \ + favorite_color=bobs_favorite_color) = bob in\n\n\ + \ \n\n\n"; }; { zipper = @@ -17555,6 +18098,607 @@ let startup : PersistentData.t = # All output from examples: #\n\ (ex1, ex2, ex3, ex4, ex5)"; } ); + ( "Labeled Tuples", + { + zipper = + "((selection((focus Left)(content())(mode \ + Normal)))(backpack())(relatives((siblings(((Secondary((id \ + 1d22b099-baac-4811-86f4-3d4b778b8d04)(content(Comment\"# \ + Labeled Tuples #\"))))(Secondary((id \ + 029cce32-17ab-490b-b2f1-e25219197dff)(content(Whitespace\"\\n\"))))(Secondary((id \ + c3e170b1-8aeb-46f6-a78d-49cb6d86915a)(content(Whitespace\"\\n\"))))(Secondary((id \ + b1a9fa5d-4671-44c8-a303-96d7400f23d3)(content(Comment\"# \ + Tuples can have labels#\"))))(Secondary((id \ + 668efc29-986d-4f42-905e-84c7606b176b)(content(Whitespace\"\\n\"))))(Tile((id \ + 23795a9d-fa91-437f-a445-3652ac99fea5)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 0ab08c67-2641-47c5-bad2-bb0fa0b577fa)(content(Whitespace\" \ + \"))))(Tile((id \ + 374004dd-f688-48f3-9aa0-5752419d8775)(label(labeled_tuple))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 776dce9f-e223-4a19-995e-fdb5e9d5fbab)(content(Whitespace\" \ + \")))))((Secondary((id \ + aeeee415-16ca-459f-9fba-3820adc957b6)(content(Whitespace\" \ + \"))))(Tile((id \ + c73cedb9-eef3-4a02-8ea0-dc89c6b0ffce)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 08be2aff-62bb-4bb1-919f-b4d81f5b87eb)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + ba0c2fe0-2a43-4004-b3b1-ced4b85b3449)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4b14f8cf-7e92-4b28-8495-309f8e6bd981)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 64acb788-0804-4a9e-b065-2235b21c3b02)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + cc891159-5869-4dfc-8f7c-0fd0116b343b)(content(Whitespace\" \ + \"))))(Tile((id \ + 577eb92e-9228-482f-a39b-bc7d25ea3a74)(label(b))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 23e7b4b7-a92a-43eb-93a2-24a4a671161a)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 0e01f92e-4201-4b0c-ab18-c02dd502075e)(label(2.0))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + b6c69ff0-709b-490b-b309-1c9cb38ac5c1)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 96b4438c-a9f8-4b92-971d-d0d4a1b19961)(content(Whitespace\" \ + \"))))(Tile((id \ + cb883be5-c6a8-47d1-8a7e-5f43b07d41cd)(label(c))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 82552269-8149-450d-b422-64c7493c13e1)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 163f4628-edf1-4911-9364-689f5f238c82)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + d60bb231-bfe5-4b6d-8a53-46b2821680dd)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 5038abcb-455b-47da-8ce6-4d3be238998a)(content(Whitespace\"\\n\"))))(Secondary((id \ + ca401b23-4366-4cdf-957a-a6a39b861998)(content(Comment\"# \ + These labels can be projected #\"))))(Secondary((id \ + 4e035ed4-f928-4593-a7f8-491435d7137e)(content(Whitespace\"\\n\"))))(Tile((id \ + 6e28c23a-375a-4f47-80d1-11a0dbdbfd3e)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + cb2d5793-8d88-4d3a-9a4f-5ca82aefc774)(content(Whitespace\" \ + \"))))(Tile((id \ + 7bbbf7b6-ebdc-4e58-bdca-2654b0ccb9d6)(label(prj_a))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + c5b250bb-1fb9-4276-b793-0221b252c8b1)(content(Whitespace\" \ + \"))))(Tile((id \ + 2fad8b7f-6410-47e2-8786-4798001dcdb7)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + b92af63d-5b68-440d-ac0a-3cc6ae28330f)(content(Whitespace\" \ + \"))))(Tile((id \ + 09a6433d-266d-4aef-b528-7920b2650305)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ + f24cff31-85a2-4d6f-ad5c-4a2284b7f17e)(content(Whitespace\" \ + \")))))((Secondary((id \ + 17dbbfc0-656a-46fd-9365-c1c2ea6dd286)(content(Whitespace\" \ + \"))))(Tile((id \ + 2effe10f-7e24-4907-a7b3-cf4b34b663e9)(label(labeled_tuple))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 6d7af305-b6c2-4a5c-bfde-edda62f126bf)(label(.))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 2))(sort \ + Exp))((shape(Concave 2))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + bdef8806-3ecc-4c67-be5c-cf7d3ed2fce9)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 4dc7a1ca-8770-467b-a81c-a245429d62ff)(content(Whitespace\" \ + \"))))(Secondary((id \ + 97350724-14de-4cfe-b5dc-820beca6a652)(content(Comment\"# 1 \ + #\"))))(Secondary((id \ + 6e55064c-2947-4769-b4bb-29d560f662f6)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + ca0d2c33-96ef-44c6-ac6e-f8a4d7901280)(content(Whitespace\" \ + \"))))(Secondary((id \ + 98524bad-9684-472a-a0c8-b1204357df66)(content(Whitespace\"\\n\"))))(Secondary((id \ + 38404748-91f8-4ff9-bf3e-6079ab3a3add)(content(Whitespace\"\\n\")))))((Secondary((id \ + fbc19dd7-8fdb-4932-87af-5b52f6a093bb)(content(Comment\"# \ + These can be encoded the types #\"))))(Secondary((id \ + 312fb397-2960-419d-8012-b3844228b045)(content(Whitespace\"\\n\"))))(Tile((id \ + 791f51eb-c011-424e-b6f7-c38517c3c5d3)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 1061312e-02d1-4ac2-b2b5-0432ef53c6c3)(content(Whitespace\" \ + \"))))(Tile((id \ + 1d69bc5e-76dc-4de1-96ba-f3c6e0704a2b)(label(typed_lt))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + be603a96-4fc1-4b57-8dcc-0768264c9798)(content(Whitespace\" \ + \"))))(Tile((id \ + 7eedad44-3ec3-4256-b621-ac301d91dad2)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9671104c-9ffa-4912-9f21-f46b308d0335)(content(Whitespace\" \ + \"))))(Tile((id \ + ea52c55a-ba30-473d-8214-a685ffde4eb3)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 2d81cb0d-d4c0-4032-8fe3-b734f68d5343)(label(a))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 1a7028bc-734d-40ce-b63b-baa31eb5966a)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 39fc34a0-cdd6-476f-a0c6-e15de827ad81)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 11f70cfb-7527-4965-8e86-36cd99dd1470)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 0c00141e-9c75-45aa-bc2b-4927df8fd199)(content(Whitespace\" \ + \"))))(Tile((id \ + b3753058-016c-47ca-b53c-d4e663a9d39f)(label(b))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + c9f6de02-1793-4006-b79b-074ec663efad)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 295bbc9b-86d8-454c-adfb-51b9bbb37abe)(label(Float))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + c7d366ac-c0db-47b5-ba48-9d7a78be4a28)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + bd447665-f6cf-4bb9-9bfb-a9782e7125b3)(content(Whitespace\" \ + \"))))(Tile((id \ + c6c89a67-1cbb-41c0-98bf-3e5d875fb9cd)(label(c))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + f626e35e-b6af-4e72-b758-df9c9ce90493)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2041fea5-1d59-4998-9f2e-3d7d20e8f519)(label(Bool))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 7c74d480-0097-4740-a918-7b5345a875eb)(content(Whitespace\" \ + \")))))((Secondary((id \ + 058c6341-431b-4045-98f3-1227ac57bca1)(content(Whitespace\" \ + \"))))(Tile((id \ + cbcebeee-2946-41d7-af56-10acfc3ee98b)(label(labeled_tuple))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 95cf3af0-a1f4-4639-802b-8e6a68b821aa)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 7df90b9b-fc87-4093-8a73-f1dd5f9b4e7b)(content(Whitespace\"\\n\"))))(Secondary((id \ + 87181a2a-7168-4fcb-922c-03c6f08cb29a)(content(Whitespace\"\\n\"))))(Secondary((id \ + 2d1cd3ec-0347-4ad3-8d1d-f90b8ee226bc)(content(Comment\"# \ + Labels are optional and can be interspersed throughout a \ + label #\"))))(Secondary((id \ + 6304d9bb-70f1-4711-af0a-3ceca5abf350)(content(Whitespace\"\\n\"))))(Tile((id \ + c03a5bf0-5b40-4db5-833d-aa7ccc5f1de9)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 8ce73b84-f462-45d0-b8f9-c5b1ec532ece)(content(Whitespace\" \ + \"))))(Tile((id \ + a16b7bdb-34bc-481b-99a2-d9b3fe4c43e9)(label(mixed_labels))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 88c2b5e3-4624-4004-956c-e2c4e56ada6c)(content(Whitespace\" \ + \"))))(Tile((id \ + e1b247ba-d61f-4616-88df-064c2b7fd3a6)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + e47e4eee-8023-46a0-9f3e-cbd22343c821)(content(Whitespace\" \ + \"))))(Tile((id \ + b1d12b65-0bde-4897-be50-9382a322d257)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 085dbae6-4130-4b47-92ca-5292fe150994)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + e55ee8c2-9a8a-4139-9ea1-682d2d310402)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9d5cfb64-78af-4a52-9833-6431217e882c)(content(Whitespace\" \ + \"))))(Tile((id \ + 3b1add0f-323b-4023-a55c-a42fd1032b4d)(label(a))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 977eb5ad-75f9-4480-baa0-50c6e374f0ba)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 19b644d1-a6a0-41ba-8624-61eeaad5e300)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + e54ed288-ac41-4a9f-841d-5243dc7376c1)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 513ff80c-bf03-4deb-b410-29faeac69a2d)(content(Whitespace\" \ + \"))))(Tile((id \ + 2a77c478-08ea-4569-81ef-c3b7cc56d0e1)(label(Float))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + ab9239e3-4316-44cb-9899-9aa69c755279)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + c548f75f-47a0-4ab4-86e8-69e634a4cca6)(content(Whitespace\" \ + \"))))(Tile((id \ + 3c55d843-a871-418c-9eff-da75446c297e)(label(flag))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + d1ed7227-a849-44ab-9890-8d264b5f1945)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 020058df-9514-49a0-9645-677851c38bb2)(label(Bool))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 40c93475-ca3b-41e8-8b21-1051f0fa687f)(content(Whitespace\" \ + \")))))((Secondary((id \ + e6102414-8e6a-49d8-8a4b-c30d478ff2c4)(content(Whitespace\" \ + \"))))(Tile((id \ + b28ba9ca-6b59-4d5c-9fcf-6ae44e1e204f)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 88d1e44a-ec5a-4157-ae30-75bf01cad38c)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 21c197df-d99d-4d9d-a358-a67c10d5cccc)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + cb832565-6203-49ff-b53e-64fd5b3c6e49)(content(Whitespace\" \ + \"))))(Tile((id \ + cce72259-be1e-4bc7-8500-1ba2bf15c674)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 4a61fc13-383b-47a7-972b-d6faa7503456)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 3a55f509-fd99-44fa-8ee1-3d41554353bf)(label(\"\\\"String \ + Value\\\"\"))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 51c1a82b-60b3-4c5a-8626-08a974105ae1)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5eb818c5-d046-4862-b6e4-03e135fc56cf)(content(Whitespace\" \ + \"))))(Tile((id \ + 65876d7a-f0ab-4fba-a53a-00bd9b55dcfc)(label(2.5))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + ab3377df-c4ba-45ff-a280-888d3a4c0ae7)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 333f4c49-4a0d-4ea9-841b-e8b6f43a8765)(content(Whitespace\" \ + \"))))(Tile((id \ + 0e51bceb-1bf0-40b1-b825-225d9c42c415)(label(flag))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + d67f063a-acd8-4bb0-86e6-87b8a6314bba)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 3b3683bc-a873-49ff-9aab-9f5d2ff8a384)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + b0a7bb24-0bdd-4ff7-8792-c404acc07832)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 006326dd-00d8-4ffd-99e0-f9e14310393f)(content(Whitespace\"\\n\"))))(Secondary((id \ + 9cee0316-ff16-45fc-8222-5a8004de1f1b)(content(Whitespace\"\\n\"))))(Tile((id \ + ca249965-e64a-4466-9054-2f8b8087e172)(label(type = \ + in))(mold((out Exp)(in_(TPat Typ))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + ce8336b7-fd8f-4766-9bc2-85e041f76ea2)(content(Whitespace\" \ + \"))))(Tile((id \ + dffcb8bd-d722-48ab-93b8-d096a011b106)(label(Person))(mold((out \ + TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ + Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 6c2dfa03-96af-4244-9ad1-5aca79846f59)(content(Whitespace\" \ + \")))))((Secondary((id \ + 28b30431-f967-4a84-b719-3ee6dd323971)(content(Whitespace\" \ + \"))))(Tile((id \ + d46306e3-6845-4d24-9e26-b4b0292ec03b)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 71962028-dd1f-4b58-8881-6e72e881deb7)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + c087cb02-0d08-4b91-8e34-99a0f2369e1a)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + a3cc0163-1461-4774-b351-3be27ddb56ec)(content(Whitespace\" \ + \"))))(Tile((id \ + b1c7750d-d878-4561-bfd5-c8583121858b)(label(age))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 03ce37fb-27dc-4b48-a329-d0538384b590)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 083755c0-e2a7-465e-9fb8-b1fb5d73725c)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 745a5f93-acf5-4e56-9ef8-6d9c9e9df676)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 67a5db8b-7000-45f6-ae8f-86027d382414)(label(favorite_color))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 10cf3666-399c-4136-be8f-60a561558bbe)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + f095c3a4-97e2-4433-aa7d-33ffa6775118)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 0254047f-2d49-49da-a292-8ae1c8bd9315)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 30456699-1693-415d-a38e-b103a1d4f4ca)(content(Whitespace\"\\n\"))))(Secondary((id \ + 4a35bd2e-ceac-4010-9b5e-b96baa3abef7)(content(Comment\"# \ + These labels can be automatically applied based on the type \ + expectation #\"))))(Secondary((id \ + e9813292-9c79-4183-9279-a341eacd3539)(content(Whitespace\"\\n\"))))(Tile((id \ + 0dfaf809-1beb-41e2-827a-bb9892dc0dbe)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 4911aaae-dcab-49b2-b114-dc86b6af73b8)(content(Whitespace\" \ + \"))))(Tile((id \ + 8b2a6afc-1c96-4e7e-b272-d516fb60c351)(label(alice))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 83a57212-492f-4c9e-b2d4-c5633c00492f)(content(Whitespace\" \ + \"))))(Tile((id \ + 0b4b1269-4a3b-4d77-8573-a57eaa2c2ff2)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 97236a27-c11a-4f08-a6dc-f2095a2ad44d)(content(Whitespace\" \ + \"))))(Tile((id \ + 221deda5-eb21-40a7-83b8-a4d3f0c72747)(label(Person))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 8c693b47-51a0-4394-a36d-0c55ed746ba2)(content(Whitespace\" \ + \")))))((Secondary((id \ + d84f659d-563b-4065-8352-0b48a0dbbc15)(content(Whitespace\" \ + \"))))(Tile((id \ + 3fce66bd-c247-471c-92b2-baabe04684aa)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + c3e4496d-c777-49da-b359-e87e57f500d8)(label(\"\\\"Alice\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 48ba350a-53b5-4afa-905a-8b113add1293)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 3f69e5d2-93c3-4464-9929-7684a8b4cce8)(content(Whitespace\" \ + \"))))(Tile((id \ + ead66a1a-2749-4c00-8c72-a1be1dbd9138)(label(22))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 8d300e9e-01fb-4ca7-98f9-d0e6761eee55)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 4f18f100-b7fa-4a75-9c20-bc59f55991b1)(content(Whitespace\" \ + \"))))(Tile((id \ + 8658b876-0dbe-41d2-8012-42a1d9eeedbd)(label(\"\\\"Blue\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + c3ebb086-566a-44a9-a3f1-02778e67cd50)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 87947367-9bf5-458f-a957-fd401c6fe62d)(content(Whitespace\"\\n\"))))(Secondary((id \ + 6ee9768e-9165-4e4b-9edc-0f5b431f3b4e)(content(Comment\"# \ + Explicitly Labeled elements are automatically \ + reordered#\"))))(Secondary((id \ + 160bfc3e-2922-46da-8880-6a55ec4e8f08)(content(Whitespace\"\\n\"))))(Tile((id \ + 9fb5dc17-bf6f-42a1-bad6-a7141ab485ff)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 44556e11-4a18-4808-8e3b-96a449991571)(content(Whitespace\" \ + \"))))(Tile((id \ + 1915e41b-fe9e-4d75-8147-05a8de710213)(label(bob))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 936f49f0-7701-46d3-9106-c5a513d9bcd8)(content(Whitespace\" \ + \"))))(Tile((id \ + ea62f713-8e6c-43ee-ad43-7960aa751f42)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + cd474fd5-2959-4f9c-a1b4-5fdf2dd5a8bd)(content(Whitespace\" \ + \"))))(Tile((id \ + fd2b6d83-7e76-4bc5-9ee9-acf808142cb2)(label(Person))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 5fc66ce9-3fab-4aef-85a9-4bef5b776355)(content(Whitespace\" \ + \")))))((Secondary((id \ + 6f0cfe1c-1274-4ca6-9230-a41ac4afd6ea)(content(Whitespace\" \ + \"))))(Tile((id \ + d5fcc42c-8f5e-429b-bca3-e0316b162a7a)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + b4672fe9-7b7f-486c-9fd7-31caa7a850dd)(label(age))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + f0bac892-177e-4d96-88de-e4d17dc891c0)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1c4d0130-d17f-432b-8692-f87ab2c096a8)(label(25))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 05e7f039-2de3-4e31-91eb-a99c4566d90b)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 21495a10-72b3-4ced-9292-fc8c8415cd4b)(content(Whitespace\" \ + \"))))(Tile((id \ + 79158e46-09bb-4bdd-9e94-d43513f0a6cc)(label(favorite_color))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 90a05943-35bb-4045-84d5-1a9d9f4f9933)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 46b0779f-2d9e-4171-abab-3a5e49ee6f57)(label(\"\\\"Red\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 2fa915a0-88fb-45f9-ba3b-d05260c06e4e)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + a08417ac-4577-411a-854a-eda4acf4964b)(content(Whitespace\" \ + \"))))(Tile((id \ + 3a8e7e83-74ec-444a-a7df-06d68f289bc3)(label(\"\\\"Bob\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + db14a17f-90ca-498b-af9e-8690c183c312)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 55d9fe07-3edd-4db1-98c4-881a873ecaa2)(content(Whitespace\" \ + \"))))(Secondary((id \ + 3aeb958c-78e8-41ca-8bd8-e4fe58ab1279)(content(Comment\"# \ + equals (\\\"Bob\\\", age=25, \ + favorite_color=\\\"Red\\\")#\"))))(Secondary((id \ + 3dc6447b-da88-4cc0-8d41-fa06812d2f2b)(content(Whitespace\"\\n\"))))(Secondary((id \ + 105ece24-a726-45da-87f3-6888e1cdedbe)(content(Whitespace\"\\n\"))))(Secondary((id \ + 0a3fa6fe-890f-434b-b9f9-fb84b56a81fb)(content(Comment\"# \ + Destructuring #\"))))(Secondary((id \ + dfcae445-0ba1-4676-91e0-3273c23f9766)(content(Whitespace\"\\n\"))))(Tile((id \ + e91a3973-b16d-49a4-a59d-380a2979c970)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 892a74b8-31ca-477d-abd8-386d58d88f28)(content(Whitespace\" \ + \"))))(Tile((id \ + 88159ab5-30b8-46d7-9f90-475b8d94c1f4)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 60d7049c-eb88-4791-9809-6b99b6678e38)(label(bobs_name))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + f6bff178-21db-4571-99d6-620d4d3d3bcb)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 18))(sort \ + Pat))((shape(Concave 18))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1fd05df6-54a0-4a88-b9ea-a3c9d4081260)(content(Whitespace\" \ + \"))))(Tile((id \ + 937f5455-014e-49ee-9582-b8b2d41115b0)(label(age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 060f122d-3e7b-4bc1-bf84-9642626f1555)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort \ + Pat))((shape(Concave 16))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 3206215b-978a-4d6b-8ae9-1b9210b0d49b)(label(bobs_age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 965a3191-2574-4447-b05b-0d40f9d83946)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 18))(sort \ + Pat))((shape(Concave 18))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 38246b0f-0bee-46e7-b01b-0d8afc2fbd0d)(content(Whitespace\" \ + \"))))(Tile((id \ + 407f97ee-e857-4ce8-83fe-634df9404c38)(label(favorite_color))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 34a291de-b553-482e-92fb-b0ec3a2c6e0a)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort \ + Pat))((shape(Concave 16))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 30328d7c-b472-4dae-b050-6d959fe7be32)(label(bobs_favorite_color))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 2d1138cf-7b53-4891-bbe7-9443bc061639)(content(Whitespace\" \ + \")))))((Secondary((id \ + 90bf31c2-7807-4d05-af22-bfb0803990a2)(content(Whitespace\" \ + \"))))(Tile((id \ + 3d677f5a-b880-49e5-9171-ed5a21307452)(label(bob))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 99c467af-0605-4a51-814b-6fe35edb5b59)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 1672c094-ce77-4a2c-a610-f352d9c00f7f)(content(Whitespace\"\\n\"))))(Secondary((id \ + 183b912f-dde9-4f06-8047-2b73d3e7ac89)(content(Whitespace\"\\n\"))))(Grout((id \ + 108cfcfd-2e17-407c-8380-ec1e63151450)(shape \ + Convex)))(Secondary((id \ + 867bbf01-916d-4d3e-9b99-1d4337659f57)(content(Whitespace\" \ + \"))))(Secondary((id \ + 0342f646-322c-4f68-98cf-de94b4df6e3d)(content(Whitespace\"\\n\"))))(Secondary((id \ + fa4a94d2-5955-4f8a-a958-6d8c8ebeaefb)(content(Whitespace\"\\n\"))))(Secondary((id \ + d6e2d5c6-1ac7-42ca-9894-0f26ea900668)(content(Whitespace\"\\n\")))))))(ancestors())))(caret(Inner \ + 33 13)))"; + backup_text = + "# Labeled Tuples #\n\n\ + # Tuples can have labels#\n\ + let labeled_tuple = (a=1, b=2.0, c=true) in\n\ + # These labels can be projected #\n\ + let prj_a : Int = labeled_tuple.a # 1 # in \n\n\ + # These can be encoded the types #\n\ + let typed_lt : (a=Int, b=Float, c=Bool) = labeled_tuple in\n\n\ + # Labels are optional and can be interspersed throughout a \ + label #\n\ + let mixed_labels : (Int, a=String, Float, flag=Bool) = (1, \ + a=\"String Value\", 2.5, flag=true) in\n\n\ + type Person = (String, age=Int,favorite_color=String) in\n\ + # These labels can be automatically applied based on the type \ + expectation #\n\ + let alice : Person = (\"Alice\", 22, \"Blue\") in\n\ + # Explicitly Labeled elements are automatically reordered#\n\ + let bob : Person = (age=25, favorite_color=\"Red\", \"Bob\") \ + in # equals (\"Bob\", age=25, favorite_color=\"Red\")#\n\n\ + # Destructuring #\n\ + let (bobs_name, age=bobs_age, \ + favorite_color=bobs_favorite_color) = bob in\n\n\ + \ \n\n\n"; + } ); ( "Expressive Programming", { zipper = From 5f790cbfa35140ad7f5f23a368b748dc101d3b55 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 20:38:12 -0400 Subject: [PATCH 061/108] revert scratch file --- src/haz3lweb/Init.ml | 601 ------------------------------------------- 1 file changed, 601 deletions(-) diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index b3a19e84ec..89b58a1341 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -18098,607 +18098,6 @@ let startup : PersistentData.t = # All output from examples: #\n\ (ex1, ex2, ex3, ex4, ex5)"; } ); - ( "Labeled Tuples", - { - zipper = - "((selection((focus Left)(content())(mode \ - Normal)))(backpack())(relatives((siblings(((Secondary((id \ - 1d22b099-baac-4811-86f4-3d4b778b8d04)(content(Comment\"# \ - Labeled Tuples #\"))))(Secondary((id \ - 029cce32-17ab-490b-b2f1-e25219197dff)(content(Whitespace\"\\n\"))))(Secondary((id \ - c3e170b1-8aeb-46f6-a78d-49cb6d86915a)(content(Whitespace\"\\n\"))))(Secondary((id \ - b1a9fa5d-4671-44c8-a303-96d7400f23d3)(content(Comment\"# \ - Tuples can have labels#\"))))(Secondary((id \ - 668efc29-986d-4f42-905e-84c7606b176b)(content(Whitespace\"\\n\"))))(Tile((id \ - 23795a9d-fa91-437f-a445-3652ac99fea5)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 0ab08c67-2641-47c5-bad2-bb0fa0b577fa)(content(Whitespace\" \ - \"))))(Tile((id \ - 374004dd-f688-48f3-9aa0-5752419d8775)(label(labeled_tuple))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 776dce9f-e223-4a19-995e-fdb5e9d5fbab)(content(Whitespace\" \ - \")))))((Secondary((id \ - aeeee415-16ca-459f-9fba-3820adc957b6)(content(Whitespace\" \ - \"))))(Tile((id \ - c73cedb9-eef3-4a02-8ea0-dc89c6b0ffce)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - 08be2aff-62bb-4bb1-919f-b4d81f5b87eb)(label(a))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - ba0c2fe0-2a43-4004-b3b1-ced4b85b3449)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort \ - Exp))((shape(Concave 16))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 4b14f8cf-7e92-4b28-8495-309f8e6bd981)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 64acb788-0804-4a9e-b065-2235b21c3b02)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - cc891159-5869-4dfc-8f7c-0fd0116b343b)(content(Whitespace\" \ - \"))))(Tile((id \ - 577eb92e-9228-482f-a39b-bc7d25ea3a74)(label(b))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 23e7b4b7-a92a-43eb-93a2-24a4a671161a)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort \ - Exp))((shape(Concave 16))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 0e01f92e-4201-4b0c-ab18-c02dd502075e)(label(2.0))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - b6c69ff0-709b-490b-b309-1c9cb38ac5c1)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 96b4438c-a9f8-4b92-971d-d0d4a1b19961)(content(Whitespace\" \ - \"))))(Tile((id \ - cb883be5-c6a8-47d1-8a7e-5f43b07d41cd)(label(c))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 82552269-8149-450d-b422-64c7493c13e1)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort \ - Exp))((shape(Concave 16))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 163f4628-edf1-4911-9364-689f5f238c82)(label(true))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - d60bb231-bfe5-4b6d-8a53-46b2821680dd)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 5038abcb-455b-47da-8ce6-4d3be238998a)(content(Whitespace\"\\n\"))))(Secondary((id \ - ca401b23-4366-4cdf-957a-a6a39b861998)(content(Comment\"# \ - These labels can be projected #\"))))(Secondary((id \ - 4e035ed4-f928-4593-a7f8-491435d7137e)(content(Whitespace\"\\n\"))))(Tile((id \ - 6e28c23a-375a-4f47-80d1-11a0dbdbfd3e)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - cb2d5793-8d88-4d3a-9a4f-5ca82aefc774)(content(Whitespace\" \ - \"))))(Tile((id \ - 7bbbf7b6-ebdc-4e58-bdca-2654b0ccb9d6)(label(prj_a))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ - c5b250bb-1fb9-4276-b793-0221b252c8b1)(content(Whitespace\" \ - \"))))(Tile((id \ - 2fad8b7f-6410-47e2-8786-4798001dcdb7)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort \ - Pat))((shape(Concave 13))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - b92af63d-5b68-440d-ac0a-3cc6ae28330f)(content(Whitespace\" \ - \"))))(Tile((id \ - 09a6433d-266d-4aef-b528-7920b2650305)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ - f24cff31-85a2-4d6f-ad5c-4a2284b7f17e)(content(Whitespace\" \ - \")))))((Secondary((id \ - 17dbbfc0-656a-46fd-9365-c1c2ea6dd286)(content(Whitespace\" \ - \"))))(Tile((id \ - 2effe10f-7e24-4907-a7b3-cf4b34b663e9)(label(labeled_tuple))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 6d7af305-b6c2-4a5c-bfde-edda62f126bf)(label(.))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 2))(sort \ - Exp))((shape(Concave 2))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - bdef8806-3ecc-4c67-be5c-cf7d3ed2fce9)(label(a))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 4dc7a1ca-8770-467b-a81c-a245429d62ff)(content(Whitespace\" \ - \"))))(Secondary((id \ - 97350724-14de-4cfe-b5dc-820beca6a652)(content(Comment\"# 1 \ - #\"))))(Secondary((id \ - 6e55064c-2947-4769-b4bb-29d560f662f6)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - ca0d2c33-96ef-44c6-ac6e-f8a4d7901280)(content(Whitespace\" \ - \"))))(Secondary((id \ - 98524bad-9684-472a-a0c8-b1204357df66)(content(Whitespace\"\\n\"))))(Secondary((id \ - 38404748-91f8-4ff9-bf3e-6079ab3a3add)(content(Whitespace\"\\n\")))))((Secondary((id \ - fbc19dd7-8fdb-4932-87af-5b52f6a093bb)(content(Comment\"# \ - These can be encoded the types #\"))))(Secondary((id \ - 312fb397-2960-419d-8012-b3844228b045)(content(Whitespace\"\\n\"))))(Tile((id \ - 791f51eb-c011-424e-b6f7-c38517c3c5d3)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 1061312e-02d1-4ac2-b2b5-0432ef53c6c3)(content(Whitespace\" \ - \"))))(Tile((id \ - 1d69bc5e-76dc-4de1-96ba-f3c6e0704a2b)(label(typed_lt))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ - be603a96-4fc1-4b57-8dcc-0768264c9798)(content(Whitespace\" \ - \"))))(Tile((id \ - 7eedad44-3ec3-4256-b621-ac301d91dad2)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort \ - Pat))((shape(Concave 13))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 9671104c-9ffa-4912-9f21-f46b308d0335)(content(Whitespace\" \ - \"))))(Tile((id \ - ea52c55a-ba30-473d-8214-a685ffde4eb3)(label(\"(\"\")\"))(mold((out \ - Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 2d81cb0d-d4c0-4032-8fe3-b734f68d5343)(label(a))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 1a7028bc-734d-40ce-b63b-baa31eb5966a)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort \ - Typ))((shape(Concave 16))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 39fc34a0-cdd6-476f-a0c6-e15de827ad81)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 11f70cfb-7527-4965-8e86-36cd99dd1470)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort \ - Typ))((shape(Concave 18))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 0c00141e-9c75-45aa-bc2b-4927df8fd199)(content(Whitespace\" \ - \"))))(Tile((id \ - b3753058-016c-47ca-b53c-d4e663a9d39f)(label(b))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - c9f6de02-1793-4006-b79b-074ec663efad)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort \ - Typ))((shape(Concave 16))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 295bbc9b-86d8-454c-adfb-51b9bbb37abe)(label(Float))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - c7d366ac-c0db-47b5-ba48-9d7a78be4a28)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort \ - Typ))((shape(Concave 18))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - bd447665-f6cf-4bb9-9bfb-a9782e7125b3)(content(Whitespace\" \ - \"))))(Tile((id \ - c6c89a67-1cbb-41c0-98bf-3e5d875fb9cd)(label(c))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - f626e35e-b6af-4e72-b758-df9c9ce90493)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort \ - Typ))((shape(Concave 16))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 2041fea5-1d59-4998-9f2e-3d7d20e8f519)(label(Bool))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 7c74d480-0097-4740-a918-7b5345a875eb)(content(Whitespace\" \ - \")))))((Secondary((id \ - 058c6341-431b-4045-98f3-1227ac57bca1)(content(Whitespace\" \ - \"))))(Tile((id \ - cbcebeee-2946-41d7-af56-10acfc3ee98b)(label(labeled_tuple))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 95cf3af0-a1f4-4639-802b-8e6a68b821aa)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 7df90b9b-fc87-4093-8a73-f1dd5f9b4e7b)(content(Whitespace\"\\n\"))))(Secondary((id \ - 87181a2a-7168-4fcb-922c-03c6f08cb29a)(content(Whitespace\"\\n\"))))(Secondary((id \ - 2d1cd3ec-0347-4ad3-8d1d-f90b8ee226bc)(content(Comment\"# \ - Labels are optional and can be interspersed throughout a \ - label #\"))))(Secondary((id \ - 6304d9bb-70f1-4711-af0a-3ceca5abf350)(content(Whitespace\"\\n\"))))(Tile((id \ - c03a5bf0-5b40-4db5-833d-aa7ccc5f1de9)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 8ce73b84-f462-45d0-b8f9-c5b1ec532ece)(content(Whitespace\" \ - \"))))(Tile((id \ - a16b7bdb-34bc-481b-99a2-d9b3fe4c43e9)(label(mixed_labels))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 88c2b5e3-4624-4004-956c-e2c4e56ada6c)(content(Whitespace\" \ - \"))))(Tile((id \ - e1b247ba-d61f-4616-88df-064c2b7fd3a6)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort \ - Pat))((shape(Concave 13))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - e47e4eee-8023-46a0-9f3e-cbd22343c821)(content(Whitespace\" \ - \"))))(Tile((id \ - b1d12b65-0bde-4897-be50-9382a322d257)(label(\"(\"\")\"))(mold((out \ - Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 085dbae6-4130-4b47-92ca-5292fe150994)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - e55ee8c2-9a8a-4139-9ea1-682d2d310402)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort \ - Typ))((shape(Concave 18))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 9d5cfb64-78af-4a52-9833-6431217e882c)(content(Whitespace\" \ - \"))))(Tile((id \ - 3b1add0f-323b-4023-a55c-a42fd1032b4d)(label(a))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 977eb5ad-75f9-4480-baa0-50c6e374f0ba)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort \ - Typ))((shape(Concave 16))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 19b644d1-a6a0-41ba-8624-61eeaad5e300)(label(String))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - e54ed288-ac41-4a9f-841d-5243dc7376c1)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort \ - Typ))((shape(Concave 18))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 513ff80c-bf03-4deb-b410-29faeac69a2d)(content(Whitespace\" \ - \"))))(Tile((id \ - 2a77c478-08ea-4569-81ef-c3b7cc56d0e1)(label(Float))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - ab9239e3-4316-44cb-9899-9aa69c755279)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort \ - Typ))((shape(Concave 18))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - c548f75f-47a0-4ab4-86e8-69e634a4cca6)(content(Whitespace\" \ - \"))))(Tile((id \ - 3c55d843-a871-418c-9eff-da75446c297e)(label(flag))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - d1ed7227-a849-44ab-9890-8d264b5f1945)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort \ - Typ))((shape(Concave 16))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 020058df-9514-49a0-9645-677851c38bb2)(label(Bool))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 40c93475-ca3b-41e8-8b21-1051f0fa687f)(content(Whitespace\" \ - \")))))((Secondary((id \ - e6102414-8e6a-49d8-8a4b-c30d478ff2c4)(content(Whitespace\" \ - \"))))(Tile((id \ - b28ba9ca-6b59-4d5c-9fcf-6ae44e1e204f)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - 88d1e44a-ec5a-4157-ae30-75bf01cad38c)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 21c197df-d99d-4d9d-a358-a67c10d5cccc)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - cb832565-6203-49ff-b53e-64fd5b3c6e49)(content(Whitespace\" \ - \"))))(Tile((id \ - cce72259-be1e-4bc7-8500-1ba2bf15c674)(label(a))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 4a61fc13-383b-47a7-972b-d6faa7503456)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort \ - Exp))((shape(Concave 16))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 3a55f509-fd99-44fa-8ee1-3d41554353bf)(label(\"\\\"String \ - Value\\\"\"))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 51c1a82b-60b3-4c5a-8626-08a974105ae1)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 5eb818c5-d046-4862-b6e4-03e135fc56cf)(content(Whitespace\" \ - \"))))(Tile((id \ - 65876d7a-f0ab-4fba-a53a-00bd9b55dcfc)(label(2.5))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - ab3377df-c4ba-45ff-a280-888d3a4c0ae7)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 333f4c49-4a0d-4ea9-841b-e8b6f43a8765)(content(Whitespace\" \ - \"))))(Tile((id \ - 0e51bceb-1bf0-40b1-b825-225d9c42c415)(label(flag))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - d67f063a-acd8-4bb0-86e6-87b8a6314bba)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort \ - Exp))((shape(Concave 16))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 3b3683bc-a873-49ff-9aab-9f5d2ff8a384)(label(true))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - b0a7bb24-0bdd-4ff7-8792-c404acc07832)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 006326dd-00d8-4ffd-99e0-f9e14310393f)(content(Whitespace\"\\n\"))))(Secondary((id \ - 9cee0316-ff16-45fc-8222-5a8004de1f1b)(content(Whitespace\"\\n\"))))(Tile((id \ - ca249965-e64a-4466-9054-2f8b8087e172)(label(type = \ - in))(mold((out Exp)(in_(TPat Typ))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - ce8336b7-fd8f-4766-9bc2-85e041f76ea2)(content(Whitespace\" \ - \"))))(Tile((id \ - dffcb8bd-d722-48ab-93b8-d096a011b106)(label(Person))(mold((out \ - TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ - Convex)(sort \ - TPat))))))(shards(0))(children())))(Secondary((id \ - 6c2dfa03-96af-4244-9ad1-5aca79846f59)(content(Whitespace\" \ - \")))))((Secondary((id \ - 28b30431-f967-4a84-b719-3ee6dd323971)(content(Whitespace\" \ - \"))))(Tile((id \ - d46306e3-6845-4d24-9e26-b4b0292ec03b)(label(\"(\"\")\"))(mold((out \ - Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 71962028-dd1f-4b58-8881-6e72e881deb7)(label(String))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - c087cb02-0d08-4b91-8e34-99a0f2369e1a)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort \ - Typ))((shape(Concave 18))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - a3cc0163-1461-4774-b351-3be27ddb56ec)(content(Whitespace\" \ - \"))))(Tile((id \ - b1c7750d-d878-4561-bfd5-c8583121858b)(label(age))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 03ce37fb-27dc-4b48-a329-d0538384b590)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort \ - Typ))((shape(Concave 16))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 083755c0-e2a7-465e-9fb8-b1fb5d73725c)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 745a5f93-acf5-4e56-9ef8-6d9c9e9df676)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort \ - Typ))((shape(Concave 18))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 67a5db8b-7000-45f6-ae8f-86027d382414)(label(favorite_color))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ - 10cf3666-399c-4136-be8f-60a561558bbe)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort \ - Typ))((shape(Concave 16))(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - f095c3a4-97e2-4433-aa7d-33ffa6775118)(label(String))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 0254047f-2d49-49da-a292-8ae1c8bd9315)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 30456699-1693-415d-a38e-b103a1d4f4ca)(content(Whitespace\"\\n\"))))(Secondary((id \ - 4a35bd2e-ceac-4010-9b5e-b96baa3abef7)(content(Comment\"# \ - These labels can be automatically applied based on the type \ - expectation #\"))))(Secondary((id \ - e9813292-9c79-4183-9279-a341eacd3539)(content(Whitespace\"\\n\"))))(Tile((id \ - 0dfaf809-1beb-41e2-827a-bb9892dc0dbe)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 4911aaae-dcab-49b2-b114-dc86b6af73b8)(content(Whitespace\" \ - \"))))(Tile((id \ - 8b2a6afc-1c96-4e7e-b272-d516fb60c351)(label(alice))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 83a57212-492f-4c9e-b2d4-c5633c00492f)(content(Whitespace\" \ - \"))))(Tile((id \ - 0b4b1269-4a3b-4d77-8573-a57eaa2c2ff2)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort \ - Pat))((shape(Concave 13))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 97236a27-c11a-4f08-a6dc-f2095a2ad44d)(content(Whitespace\" \ - \"))))(Tile((id \ - 221deda5-eb21-40a7-83b8-a4d3f0c72747)(label(Person))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 8c693b47-51a0-4394-a36d-0c55ed746ba2)(content(Whitespace\" \ - \")))))((Secondary((id \ - d84f659d-563b-4065-8352-0b48a0dbbc15)(content(Whitespace\" \ - \"))))(Tile((id \ - 3fce66bd-c247-471c-92b2-baabe04684aa)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - c3e4496d-c777-49da-b359-e87e57f500d8)(label(\"\\\"Alice\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 48ba350a-53b5-4afa-905a-8b113add1293)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 3f69e5d2-93c3-4464-9929-7684a8b4cce8)(content(Whitespace\" \ - \"))))(Tile((id \ - ead66a1a-2749-4c00-8c72-a1be1dbd9138)(label(22))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 8d300e9e-01fb-4ca7-98f9-d0e6761eee55)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 4f18f100-b7fa-4a75-9c20-bc59f55991b1)(content(Whitespace\" \ - \"))))(Tile((id \ - 8658b876-0dbe-41d2-8012-42a1d9eeedbd)(label(\"\\\"Blue\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - c3ebb086-566a-44a9-a3f1-02778e67cd50)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 87947367-9bf5-458f-a957-fd401c6fe62d)(content(Whitespace\"\\n\"))))(Secondary((id \ - 6ee9768e-9165-4e4b-9edc-0f5b431f3b4e)(content(Comment\"# \ - Explicitly Labeled elements are automatically \ - reordered#\"))))(Secondary((id \ - 160bfc3e-2922-46da-8880-6a55ec4e8f08)(content(Whitespace\"\\n\"))))(Tile((id \ - 9fb5dc17-bf6f-42a1-bad6-a7141ab485ff)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 44556e11-4a18-4808-8e3b-96a449991571)(content(Whitespace\" \ - \"))))(Tile((id \ - 1915e41b-fe9e-4d75-8147-05a8de710213)(label(bob))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 936f49f0-7701-46d3-9106-c5a513d9bcd8)(content(Whitespace\" \ - \"))))(Tile((id \ - ea62f713-8e6c-43ee-ad43-7960aa751f42)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort \ - Pat))((shape(Concave 13))(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - cd474fd5-2959-4f9c-a1b4-5fdf2dd5a8bd)(content(Whitespace\" \ - \"))))(Tile((id \ - fd2b6d83-7e76-4bc5-9ee9-acf808142cb2)(label(Person))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 5fc66ce9-3fab-4aef-85a9-4bef5b776355)(content(Whitespace\" \ - \")))))((Secondary((id \ - 6f0cfe1c-1274-4ca6-9230-a41ac4afd6ea)(content(Whitespace\" \ - \"))))(Tile((id \ - d5fcc42c-8f5e-429b-bca3-e0316b162a7a)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - b4672fe9-7b7f-486c-9fd7-31caa7a850dd)(label(age))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - f0bac892-177e-4d96-88de-e4d17dc891c0)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort \ - Exp))((shape(Concave 16))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 1c4d0130-d17f-432b-8692-f87ab2c096a8)(label(25))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 05e7f039-2de3-4e31-91eb-a99c4566d90b)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 21495a10-72b3-4ced-9292-fc8c8415cd4b)(content(Whitespace\" \ - \"))))(Tile((id \ - 79158e46-09bb-4bdd-9e94-d43513f0a6cc)(label(favorite_color))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 90a05943-35bb-4045-84d5-1a9d9f4f9933)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort \ - Exp))((shape(Concave 16))(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 46b0779f-2d9e-4171-abab-3a5e49ee6f57)(label(\"\\\"Red\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ - 2fa915a0-88fb-45f9-ba3b-d05260c06e4e)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort \ - Exp))((shape(Concave 18))(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - a08417ac-4577-411a-854a-eda4acf4964b)(content(Whitespace\" \ - \"))))(Tile((id \ - 3a8e7e83-74ec-444a-a7df-06d68f289bc3)(label(\"\\\"Bob\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - db14a17f-90ca-498b-af9e-8690c183c312)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 55d9fe07-3edd-4db1-98c4-881a873ecaa2)(content(Whitespace\" \ - \"))))(Secondary((id \ - 3aeb958c-78e8-41ca-8bd8-e4fe58ab1279)(content(Comment\"# \ - equals (\\\"Bob\\\", age=25, \ - favorite_color=\\\"Red\\\")#\"))))(Secondary((id \ - 3dc6447b-da88-4cc0-8d41-fa06812d2f2b)(content(Whitespace\"\\n\"))))(Secondary((id \ - 105ece24-a726-45da-87f3-6888e1cdedbe)(content(Whitespace\"\\n\"))))(Secondary((id \ - 0a3fa6fe-890f-434b-b9f9-fb84b56a81fb)(content(Comment\"# \ - Destructuring #\"))))(Secondary((id \ - dfcae445-0ba1-4676-91e0-3273c23f9766)(content(Whitespace\"\\n\"))))(Tile((id \ - e91a3973-b16d-49a4-a59d-380a2979c970)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 892a74b8-31ca-477d-abd8-386d58d88f28)(content(Whitespace\" \ - \"))))(Tile((id \ - 88159ab5-30b8-46d7-9f90-475b8d94c1f4)(label(\"(\"\")\"))(mold((out \ - Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ - 60d7049c-eb88-4791-9809-6b99b6678e38)(label(bobs_name))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ - f6bff178-21db-4571-99d6-620d4d3d3bcb)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 18))(sort \ - Pat))((shape(Concave 18))(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 1fd05df6-54a0-4a88-b9ea-a3c9d4081260)(content(Whitespace\" \ - \"))))(Tile((id \ - 937f5455-014e-49ee-9582-b8b2d41115b0)(label(age))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ - 060f122d-3e7b-4bc1-bf84-9642626f1555)(label(=))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 16))(sort \ - Pat))((shape(Concave 16))(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 3206215b-978a-4d6b-8ae9-1b9210b0d49b)(label(bobs_age))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ - 965a3191-2574-4447-b05b-0d40f9d83946)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 18))(sort \ - Pat))((shape(Concave 18))(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 38246b0f-0bee-46e7-b01b-0d8afc2fbd0d)(content(Whitespace\" \ - \"))))(Tile((id \ - 407f97ee-e857-4ce8-83fe-634df9404c38)(label(favorite_color))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ - 34a291de-b553-482e-92fb-b0ec3a2c6e0a)(label(=))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 16))(sort \ - Pat))((shape(Concave 16))(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 30328d7c-b472-4dae-b050-6d959fe7be32)(label(bobs_favorite_color))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort \ - Pat))))))(shards(0))(children()))))))))(Secondary((id \ - 2d1138cf-7b53-4891-bbe7-9443bc061639)(content(Whitespace\" \ - \")))))((Secondary((id \ - 90bf31c2-7807-4d05-af22-bfb0803990a2)(content(Whitespace\" \ - \"))))(Tile((id \ - 3d677f5a-b880-49e5-9171-ed5a21307452)(label(bob))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 99c467af-0605-4a51-814b-6fe35edb5b59)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 1672c094-ce77-4a2c-a610-f352d9c00f7f)(content(Whitespace\"\\n\"))))(Secondary((id \ - 183b912f-dde9-4f06-8047-2b73d3e7ac89)(content(Whitespace\"\\n\"))))(Grout((id \ - 108cfcfd-2e17-407c-8380-ec1e63151450)(shape \ - Convex)))(Secondary((id \ - 867bbf01-916d-4d3e-9b99-1d4337659f57)(content(Whitespace\" \ - \"))))(Secondary((id \ - 0342f646-322c-4f68-98cf-de94b4df6e3d)(content(Whitespace\"\\n\"))))(Secondary((id \ - fa4a94d2-5955-4f8a-a958-6d8c8ebeaefb)(content(Whitespace\"\\n\"))))(Secondary((id \ - d6e2d5c6-1ac7-42ca-9894-0f26ea900668)(content(Whitespace\"\\n\")))))))(ancestors())))(caret(Inner \ - 33 13)))"; - backup_text = - "# Labeled Tuples #\n\n\ - # Tuples can have labels#\n\ - let labeled_tuple = (a=1, b=2.0, c=true) in\n\ - # These labels can be projected #\n\ - let prj_a : Int = labeled_tuple.a # 1 # in \n\n\ - # These can be encoded the types #\n\ - let typed_lt : (a=Int, b=Float, c=Bool) = labeled_tuple in\n\n\ - # Labels are optional and can be interspersed throughout a \ - label #\n\ - let mixed_labels : (Int, a=String, Float, flag=Bool) = (1, \ - a=\"String Value\", 2.5, flag=true) in\n\n\ - type Person = (String, age=Int,favorite_color=String) in\n\ - # These labels can be automatically applied based on the type \ - expectation #\n\ - let alice : Person = (\"Alice\", 22, \"Blue\") in\n\ - # Explicitly Labeled elements are automatically reordered#\n\ - let bob : Person = (age=25, favorite_color=\"Red\", \"Bob\") \ - in # equals (\"Bob\", age=25, favorite_color=\"Red\")#\n\n\ - # Destructuring #\n\ - let (bobs_name, age=bobs_age, \ - favorite_color=bobs_favorite_color) = bob in\n\n\ - \ \n\n\n"; - } ); ( "Expressive Programming", { zipper = From 39cbba1ba4ebee444f8d231569c34f5c01a8029a Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 20:43:26 -0400 Subject: [PATCH 062/108] Revert init.ml --- src/haz3lweb/Init.ml | 551 +------------------------------------------ 1 file changed, 4 insertions(+), 547 deletions(-) diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index 89b58a1341..c3d2de0aba 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -37,553 +37,10 @@ let startup : PersistentData.t = { zipper = "((selection((focus Left)(content())(mode \ - Normal)))(backpack())(relatives((siblings(((Secondary((id \ - 1d22b099-baac-4811-86f4-3d4b778b8d04)(content(Comment\"# \ - Labeled Tuples #\"))))(Secondary((id \ - 029cce32-17ab-490b-b2f1-e25219197dff)(content(Whitespace\"\\n\"))))(Secondary((id \ - c3e170b1-8aeb-46f6-a78d-49cb6d86915a)(content(Whitespace\"\\n\"))))(Secondary((id \ - b1a9fa5d-4671-44c8-a303-96d7400f23d3)(content(Comment\"# Tuples \ - can have labels#\"))))(Secondary((id \ - 668efc29-986d-4f42-905e-84c7606b176b)(content(Whitespace\"\\n\"))))(Tile((id \ - 23795a9d-fa91-437f-a445-3652ac99fea5)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 0ab08c67-2641-47c5-bad2-bb0fa0b577fa)(content(Whitespace\" \ - \"))))(Tile((id \ - 374004dd-f688-48f3-9aa0-5752419d8775)(label(labeled_tuple))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 776dce9f-e223-4a19-995e-fdb5e9d5fbab)(content(Whitespace\" \ - \")))))((Secondary((id \ - aeeee415-16ca-459f-9fba-3820adc957b6)(content(Whitespace\" \ - \"))))(Tile((id \ - c73cedb9-eef3-4a02-8ea0-dc89c6b0ffce)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - 08be2aff-62bb-4bb1-919f-b4d81f5b87eb)(label(a))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - ba0c2fe0-2a43-4004-b3b1-ced4b85b3449)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ - 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 4b14f8cf-7e92-4b28-8495-309f8e6bd981)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 64acb788-0804-4a9e-b065-2235b21c3b02)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - cc891159-5869-4dfc-8f7c-0fd0116b343b)(content(Whitespace\" \ - \"))))(Tile((id \ - 577eb92e-9228-482f-a39b-bc7d25ea3a74)(label(b))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 23e7b4b7-a92a-43eb-93a2-24a4a671161a)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ - 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 0e01f92e-4201-4b0c-ab18-c02dd502075e)(label(2.0))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - b6c69ff0-709b-490b-b309-1c9cb38ac5c1)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 96b4438c-a9f8-4b92-971d-d0d4a1b19961)(content(Whitespace\" \ - \"))))(Tile((id \ - cb883be5-c6a8-47d1-8a7e-5f43b07d41cd)(label(c))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 82552269-8149-450d-b422-64c7493c13e1)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ - 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 163f4628-edf1-4911-9364-689f5f238c82)(label(true))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - d60bb231-bfe5-4b6d-8a53-46b2821680dd)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 5038abcb-455b-47da-8ce6-4d3be238998a)(content(Whitespace\"\\n\"))))(Secondary((id \ - ca401b23-4366-4cdf-957a-a6a39b861998)(content(Comment\"# These \ - labels can be projected #\"))))(Secondary((id \ - 4e035ed4-f928-4593-a7f8-491435d7137e)(content(Whitespace\"\\n\"))))(Tile((id \ - 6e28c23a-375a-4f47-80d1-11a0dbdbfd3e)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - cb2d5793-8d88-4d3a-9a4f-5ca82aefc774)(content(Whitespace\" \ - \"))))(Tile((id \ - 7bbbf7b6-ebdc-4e58-bdca-2654b0ccb9d6)(label(prj_a))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - c5b250bb-1fb9-4276-b793-0221b252c8b1)(content(Whitespace\" \ - \"))))(Tile((id \ - 2fad8b7f-6410-47e2-8786-4798001dcdb7)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ - 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - b92af63d-5b68-440d-ac0a-3cc6ae28330f)(content(Whitespace\" \ - \"))))(Tile((id \ - 09a6433d-266d-4aef-b528-7920b2650305)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - f24cff31-85a2-4d6f-ad5c-4a2284b7f17e)(content(Whitespace\" \ - \")))))((Secondary((id \ - 17dbbfc0-656a-46fd-9365-c1c2ea6dd286)(content(Whitespace\" \ - \"))))(Tile((id \ - 2effe10f-7e24-4907-a7b3-cf4b34b663e9)(label(labeled_tuple))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 6d7af305-b6c2-4a5c-bfde-edda62f126bf)(label(.))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 2))(sort Exp))((shape(Concave \ - 2))(sort Exp))))))(shards(0))(children())))(Tile((id \ - bdef8806-3ecc-4c67-be5c-cf7d3ed2fce9)(label(a))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 4dc7a1ca-8770-467b-a81c-a245429d62ff)(content(Whitespace\" \ - \"))))(Secondary((id \ - 97350724-14de-4cfe-b5dc-820beca6a652)(content(Comment\"# 1 \ - #\"))))(Secondary((id \ - 6e55064c-2947-4769-b4bb-29d560f662f6)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - ca0d2c33-96ef-44c6-ac6e-f8a4d7901280)(content(Whitespace\" \ - \"))))(Secondary((id \ - 98524bad-9684-472a-a0c8-b1204357df66)(content(Whitespace\"\\n\"))))(Secondary((id \ - 38404748-91f8-4ff9-bf3e-6079ab3a3add)(content(Whitespace\"\\n\")))))((Secondary((id \ - fbc19dd7-8fdb-4932-87af-5b52f6a093bb)(content(Comment\"# These \ - can be encoded the types #\"))))(Secondary((id \ - 312fb397-2960-419d-8012-b3844228b045)(content(Whitespace\"\\n\"))))(Tile((id \ - 791f51eb-c011-424e-b6f7-c38517c3c5d3)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 1061312e-02d1-4ac2-b2b5-0432ef53c6c3)(content(Whitespace\" \ - \"))))(Tile((id \ - 1d69bc5e-76dc-4de1-96ba-f3c6e0704a2b)(label(typed_lt))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - be603a96-4fc1-4b57-8dcc-0768264c9798)(content(Whitespace\" \ - \"))))(Tile((id \ - 7eedad44-3ec3-4256-b621-ac301d91dad2)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ - 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 9671104c-9ffa-4912-9f21-f46b308d0335)(content(Whitespace\" \ - \"))))(Tile((id \ - ea52c55a-ba30-473d-8214-a685ffde4eb3)(label(\"(\"\")\"))(mold((out \ - Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 2d81cb0d-d4c0-4032-8fe3-b734f68d5343)(label(a))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 1a7028bc-734d-40ce-b63b-baa31eb5966a)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ - 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ - 39fc34a0-cdd6-476f-a0c6-e15de827ad81)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 11f70cfb-7527-4965-8e86-36cd99dd1470)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ - 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 0c00141e-9c75-45aa-bc2b-4927df8fd199)(content(Whitespace\" \ - \"))))(Tile((id \ - b3753058-016c-47ca-b53c-d4e663a9d39f)(label(b))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - c9f6de02-1793-4006-b79b-074ec663efad)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ - 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ - 295bbc9b-86d8-454c-adfb-51b9bbb37abe)(label(Float))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - c7d366ac-c0db-47b5-ba48-9d7a78be4a28)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ - 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - bd447665-f6cf-4bb9-9bfb-a9782e7125b3)(content(Whitespace\" \ - \"))))(Tile((id \ - c6c89a67-1cbb-41c0-98bf-3e5d875fb9cd)(label(c))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - f626e35e-b6af-4e72-b758-df9c9ce90493)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ - 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ - 2041fea5-1d59-4998-9f2e-3d7d20e8f519)(label(Bool))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 7c74d480-0097-4740-a918-7b5345a875eb)(content(Whitespace\" \ - \")))))((Secondary((id \ - 058c6341-431b-4045-98f3-1227ac57bca1)(content(Whitespace\" \ - \"))))(Tile((id \ - cbcebeee-2946-41d7-af56-10acfc3ee98b)(label(labeled_tuple))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 95cf3af0-a1f4-4639-802b-8e6a68b821aa)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 7df90b9b-fc87-4093-8a73-f1dd5f9b4e7b)(content(Whitespace\"\\n\"))))(Secondary((id \ - 87181a2a-7168-4fcb-922c-03c6f08cb29a)(content(Whitespace\"\\n\"))))(Secondary((id \ - 2d1cd3ec-0347-4ad3-8d1d-f90b8ee226bc)(content(Comment\"# Labels \ - are optional and can be interspersed throughout a label \ - #\"))))(Secondary((id \ - 6304d9bb-70f1-4711-af0a-3ceca5abf350)(content(Whitespace\"\\n\"))))(Tile((id \ - c03a5bf0-5b40-4db5-833d-aa7ccc5f1de9)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 8ce73b84-f462-45d0-b8f9-c5b1ec532ece)(content(Whitespace\" \ - \"))))(Tile((id \ - a16b7bdb-34bc-481b-99a2-d9b3fe4c43e9)(label(mixed_labels))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 88c2b5e3-4624-4004-956c-e2c4e56ada6c)(content(Whitespace\" \ - \"))))(Tile((id \ - e1b247ba-d61f-4616-88df-064c2b7fd3a6)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ - 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - e47e4eee-8023-46a0-9f3e-cbd22343c821)(content(Whitespace\" \ - \"))))(Tile((id \ - b1d12b65-0bde-4897-be50-9382a322d257)(label(\"(\"\")\"))(mold((out \ - Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 085dbae6-4130-4b47-92ca-5292fe150994)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - e55ee8c2-9a8a-4139-9ea1-682d2d310402)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ - 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 9d5cfb64-78af-4a52-9833-6431217e882c)(content(Whitespace\" \ - \"))))(Tile((id \ - 3b1add0f-323b-4023-a55c-a42fd1032b4d)(label(a))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 977eb5ad-75f9-4480-baa0-50c6e374f0ba)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ - 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ - 19b644d1-a6a0-41ba-8624-61eeaad5e300)(label(String))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - e54ed288-ac41-4a9f-841d-5243dc7376c1)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ - 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 513ff80c-bf03-4deb-b410-29faeac69a2d)(content(Whitespace\" \ - \"))))(Tile((id \ - 2a77c478-08ea-4569-81ef-c3b7cc56d0e1)(label(Float))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - ab9239e3-4316-44cb-9899-9aa69c755279)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ - 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - c548f75f-47a0-4ab4-86e8-69e634a4cca6)(content(Whitespace\" \ - \"))))(Tile((id \ - 3c55d843-a871-418c-9eff-da75446c297e)(label(flag))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - d1ed7227-a849-44ab-9890-8d264b5f1945)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ - 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ - 020058df-9514-49a0-9645-677851c38bb2)(label(Bool))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 40c93475-ca3b-41e8-8b21-1051f0fa687f)(content(Whitespace\" \ - \")))))((Secondary((id \ - e6102414-8e6a-49d8-8a4b-c30d478ff2c4)(content(Whitespace\" \ - \"))))(Tile((id \ - b28ba9ca-6b59-4d5c-9fcf-6ae44e1e204f)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - 88d1e44a-ec5a-4157-ae30-75bf01cad38c)(label(1))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 21c197df-d99d-4d9d-a358-a67c10d5cccc)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - cb832565-6203-49ff-b53e-64fd5b3c6e49)(content(Whitespace\" \ - \"))))(Tile((id \ - cce72259-be1e-4bc7-8500-1ba2bf15c674)(label(a))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 4a61fc13-383b-47a7-972b-d6faa7503456)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ - 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 3a55f509-fd99-44fa-8ee1-3d41554353bf)(label(\"\\\"String \ - Value\\\"\"))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ - Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 51c1a82b-60b3-4c5a-8626-08a974105ae1)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 5eb818c5-d046-4862-b6e4-03e135fc56cf)(content(Whitespace\" \ - \"))))(Tile((id \ - 65876d7a-f0ab-4fba-a53a-00bd9b55dcfc)(label(2.5))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - ab3377df-c4ba-45ff-a280-888d3a4c0ae7)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 333f4c49-4a0d-4ea9-841b-e8b6f43a8765)(content(Whitespace\" \ - \"))))(Tile((id \ - 0e51bceb-1bf0-40b1-b825-225d9c42c415)(label(flag))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - d67f063a-acd8-4bb0-86e6-87b8a6314bba)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ - 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 3b3683bc-a873-49ff-9aab-9f5d2ff8a384)(label(true))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - b0a7bb24-0bdd-4ff7-8792-c404acc07832)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 006326dd-00d8-4ffd-99e0-f9e14310393f)(content(Whitespace\"\\n\"))))(Secondary((id \ - 9cee0316-ff16-45fc-8222-5a8004de1f1b)(content(Whitespace\"\\n\"))))(Tile((id \ - ca249965-e64a-4466-9054-2f8b8087e172)(label(type = \ - in))(mold((out Exp)(in_(TPat Typ))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - ce8336b7-fd8f-4766-9bc2-85e041f76ea2)(content(Whitespace\" \ - \"))))(Tile((id \ - dffcb8bd-d722-48ab-93b8-d096a011b106)(label(Person))(mold((out \ - TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ - Convex)(sort TPat))))))(shards(0))(children())))(Secondary((id \ - 6c2dfa03-96af-4244-9ad1-5aca79846f59)(content(Whitespace\" \ - \")))))((Secondary((id \ - 28b30431-f967-4a84-b719-3ee6dd323971)(content(Whitespace\" \ - \"))))(Tile((id \ - d46306e3-6845-4d24-9e26-b4b0292ec03b)(label(\"(\"\")\"))(mold((out \ - Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ - Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ - 71962028-dd1f-4b58-8881-6e72e881deb7)(label(String))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - c087cb02-0d08-4b91-8e34-99a0f2369e1a)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ - 18))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - a3cc0163-1461-4774-b351-3be27ddb56ec)(content(Whitespace\" \ - \"))))(Tile((id \ - b1c7750d-d878-4561-bfd5-c8583121858b)(label(age))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 03ce37fb-27dc-4b48-a329-d0538384b590)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ - 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ - 083755c0-e2a7-465e-9fb8-b1fb5d73725c)(label(Int))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 745a5f93-acf5-4e56-9ef8-6d9c9e9df676)(label(,))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 18))(sort Typ))((shape(Concave \ - 18))(sort Typ))))))(shards(0))(children())))(Tile((id \ - 67a5db8b-7000-45f6-ae8f-86027d382414)(label(favorite_color))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Tile((id \ - 10cf3666-399c-4136-be8f-60a561558bbe)(label(=))(mold((out \ - Typ)(in_())(nibs(((shape(Concave 16))(sort Typ))((shape(Concave \ - 16))(sort Typ))))))(shards(0))(children())))(Tile((id \ - f095c3a4-97e2-4433-aa7d-33ffa6775118)(label(String))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children()))))))))(Secondary((id \ - 0254047f-2d49-49da-a292-8ae1c8bd9315)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 30456699-1693-415d-a38e-b103a1d4f4ca)(content(Whitespace\"\\n\"))))(Secondary((id \ - 4a35bd2e-ceac-4010-9b5e-b96baa3abef7)(content(Comment\"# These \ - labels can be automatically applied based on the type \ - expectation #\"))))(Secondary((id \ - e9813292-9c79-4183-9279-a341eacd3539)(content(Whitespace\"\\n\"))))(Tile((id \ - 0dfaf809-1beb-41e2-827a-bb9892dc0dbe)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 4911aaae-dcab-49b2-b114-dc86b6af73b8)(content(Whitespace\" \ - \"))))(Tile((id \ - 8b2a6afc-1c96-4e7e-b272-d516fb60c351)(label(alice))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 83a57212-492f-4c9e-b2d4-c5633c00492f)(content(Whitespace\" \ - \"))))(Tile((id \ - 0b4b1269-4a3b-4d77-8573-a57eaa2c2ff2)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ - 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - 97236a27-c11a-4f08-a6dc-f2095a2ad44d)(content(Whitespace\" \ - \"))))(Tile((id \ - 221deda5-eb21-40a7-83b8-a4d3f0c72747)(label(Person))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 8c693b47-51a0-4394-a36d-0c55ed746ba2)(content(Whitespace\" \ - \")))))((Secondary((id \ - d84f659d-563b-4065-8352-0b48a0dbbc15)(content(Whitespace\" \ - \"))))(Tile((id \ - 3fce66bd-c247-471c-92b2-baabe04684aa)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - c3e4496d-c777-49da-b359-e87e57f500d8)(label(\"\\\"Alice\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 48ba350a-53b5-4afa-905a-8b113add1293)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 3f69e5d2-93c3-4464-9929-7684a8b4cce8)(content(Whitespace\" \ - \"))))(Tile((id \ - ead66a1a-2749-4c00-8c72-a1be1dbd9138)(label(22))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 8d300e9e-01fb-4ca7-98f9-d0e6761eee55)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 4f18f100-b7fa-4a75-9c20-bc59f55991b1)(content(Whitespace\" \ - \"))))(Tile((id \ - 8658b876-0dbe-41d2-8012-42a1d9eeedbd)(label(\"\\\"Blue\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - c3ebb086-566a-44a9-a3f1-02778e67cd50)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 87947367-9bf5-458f-a957-fd401c6fe62d)(content(Whitespace\"\\n\"))))(Secondary((id \ - 6ee9768e-9165-4e4b-9edc-0f5b431f3b4e)(content(Comment\"# \ - Explicitly Labeled elements are automatically \ - reordered#\"))))(Secondary((id \ - 160bfc3e-2922-46da-8880-6a55ec4e8f08)(content(Whitespace\"\\n\"))))(Tile((id \ - 9fb5dc17-bf6f-42a1-bad6-a7141ab485ff)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 44556e11-4a18-4808-8e3b-96a449991571)(content(Whitespace\" \ - \"))))(Tile((id \ - 1915e41b-fe9e-4d75-8147-05a8de710213)(label(bob))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Secondary((id \ - 936f49f0-7701-46d3-9106-c5a513d9bcd8)(content(Whitespace\" \ - \"))))(Tile((id \ - ea62f713-8e6c-43ee-ad43-7960aa751f42)(label(:))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 13))(sort Pat))((shape(Concave \ - 13))(sort Typ))))))(shards(0))(children())))(Secondary((id \ - cd474fd5-2959-4f9c-a1b4-5fdf2dd5a8bd)(content(Whitespace\" \ - \"))))(Tile((id \ - fd2b6d83-7e76-4bc5-9ee9-acf808142cb2)(label(Person))(mold((out \ - Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape Convex)(sort \ - Typ))))))(shards(0))(children())))(Secondary((id \ - 5fc66ce9-3fab-4aef-85a9-4bef5b776355)(content(Whitespace\" \ - \")))))((Secondary((id \ - 6f0cfe1c-1274-4ca6-9230-a41ac4afd6ea)(content(Whitespace\" \ - \"))))(Tile((id \ - d5fcc42c-8f5e-429b-bca3-e0316b162a7a)(label(\"(\"\")\"))(mold((out \ - Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ - Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ - b4672fe9-7b7f-486c-9fd7-31caa7a850dd)(label(age))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - f0bac892-177e-4d96-88de-e4d17dc891c0)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ - 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 1c4d0130-d17f-432b-8692-f87ab2c096a8)(label(25))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 05e7f039-2de3-4e31-91eb-a99c4566d90b)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - 21495a10-72b3-4ced-9292-fc8c8415cd4b)(content(Whitespace\" \ - \"))))(Tile((id \ - 79158e46-09bb-4bdd-9e94-d43513f0a6cc)(label(favorite_color))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 90a05943-35bb-4045-84d5-1a9d9f4f9933)(label(=))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 16))(sort Exp))((shape(Concave \ - 16))(sort Exp))))))(shards(0))(children())))(Tile((id \ - 46b0779f-2d9e-4171-abab-3a5e49ee6f57)(label(\"\\\"Red\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Tile((id \ - 2fa915a0-88fb-45f9-ba3b-d05260c06e4e)(label(,))(mold((out \ - Exp)(in_())(nibs(((shape(Concave 18))(sort Exp))((shape(Concave \ - 18))(sort Exp))))))(shards(0))(children())))(Secondary((id \ - a08417ac-4577-411a-854a-eda4acf4964b)(content(Whitespace\" \ - \"))))(Tile((id \ - 3a8e7e83-74ec-444a-a7df-06d68f289bc3)(label(\"\\\"Bob\\\"\"))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children()))))))))(Secondary((id \ - db14a17f-90ca-498b-af9e-8690c183c312)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 55d9fe07-3edd-4db1-98c4-881a873ecaa2)(content(Whitespace\" \ - \"))))(Secondary((id \ - 3aeb958c-78e8-41ca-8bd8-e4fe58ab1279)(content(Comment\"# equals \ - (\\\"Bob\\\", age=25, \ - favorite_color=\\\"Red\\\")#\"))))(Secondary((id \ - 3dc6447b-da88-4cc0-8d41-fa06812d2f2b)(content(Whitespace\"\\n\"))))(Secondary((id \ - 105ece24-a726-45da-87f3-6888e1cdedbe)(content(Whitespace\"\\n\"))))(Secondary((id \ - 0a3fa6fe-890f-434b-b9f9-fb84b56a81fb)(content(Comment\"# \ - Destructuring #\"))))(Secondary((id \ - dfcae445-0ba1-4676-91e0-3273c23f9766)(content(Whitespace\"\\n\"))))(Tile((id \ - e91a3973-b16d-49a4-a59d-380a2979c970)(label(let = \ - in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ - Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ - 2))(children(((Secondary((id \ - 892a74b8-31ca-477d-abd8-386d58d88f28)(content(Whitespace\" \ - \"))))(Tile((id \ - 88159ab5-30b8-46d7-9f90-475b8d94c1f4)(label(\"(\"\")\"))(mold((out \ - Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ - Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ - 60d7049c-eb88-4791-9809-6b99b6678e38)(label(bobs_name))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - f6bff178-21db-4571-99d6-620d4d3d3bcb)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 18))(sort Pat))((shape(Concave \ - 18))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 1fd05df6-54a0-4a88-b9ea-a3c9d4081260)(content(Whitespace\" \ - \"))))(Tile((id \ - 937f5455-014e-49ee-9582-b8b2d41115b0)(label(age))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 060f122d-3e7b-4bc1-bf84-9642626f1555)(label(=))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 16))(sort Pat))((shape(Concave \ - 16))(sort Pat))))))(shards(0))(children())))(Tile((id \ - 3206215b-978a-4d6b-8ae9-1b9210b0d49b)(label(bobs_age))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 965a3191-2574-4447-b05b-0d40f9d83946)(label(,))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 18))(sort Pat))((shape(Concave \ - 18))(sort Pat))))))(shards(0))(children())))(Secondary((id \ - 38246b0f-0bee-46e7-b01b-0d8afc2fbd0d)(content(Whitespace\" \ - \"))))(Tile((id \ - 407f97ee-e857-4ce8-83fe-634df9404c38)(label(favorite_color))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children())))(Tile((id \ - 34a291de-b553-482e-92fb-b0ec3a2c6e0a)(label(=))(mold((out \ - Pat)(in_())(nibs(((shape(Concave 16))(sort Pat))((shape(Concave \ - 16))(sort Pat))))))(shards(0))(children())))(Tile((id \ - 30328d7c-b472-4dae-b050-6d959fe7be32)(label(bobs_favorite_color))(mold((out \ - Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape Convex)(sort \ - Pat))))))(shards(0))(children()))))))))(Secondary((id \ - 2d1138cf-7b53-4891-bbe7-9443bc061639)(content(Whitespace\" \ - \")))))((Secondary((id \ - 90bf31c2-7807-4d05-af22-bfb0803990a2)(content(Whitespace\" \ - \"))))(Tile((id \ - 3d677f5a-b880-49e5-9171-ed5a21307452)(label(bob))(mold((out \ - Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape Convex)(sort \ - Exp))))))(shards(0))(children())))(Secondary((id \ - 99c467af-0605-4a51-814b-6fe35edb5b59)(content(Whitespace\" \ - \")))))))))(Secondary((id \ - 1672c094-ce77-4a2c-a610-f352d9c00f7f)(content(Whitespace\"\\n\"))))(Secondary((id \ - 183b912f-dde9-4f06-8047-2b73d3e7ac89)(content(Whitespace\"\\n\"))))(Grout((id \ - 108cfcfd-2e17-407c-8380-ec1e63151450)(shape \ - Convex)))(Secondary((id \ - 867bbf01-916d-4d3e-9b99-1d4337659f57)(content(Whitespace\" \ - \"))))(Secondary((id \ - 0342f646-322c-4f68-98cf-de94b4df6e3d)(content(Whitespace\"\\n\"))))(Secondary((id \ - fa4a94d2-5955-4f8a-a958-6d8c8ebeaefb)(content(Whitespace\"\\n\"))))(Secondary((id \ - d6e2d5c6-1ac7-42ca-9894-0f26ea900668)(content(Whitespace\"\\n\")))))))(ancestors())))(caret(Inner \ - 33 13)))"; - backup_text = - "# Labeled Tuples #\n\n\ - # Tuples can have labels#\n\ - let labeled_tuple = (a=1, b=2.0, c=true) in\n\ - # These labels can be projected #\n\ - let prj_a : Int = labeled_tuple.a # 1 # in \n\n\ - # These can be encoded the types #\n\ - let typed_lt : (a=Int, b=Float, c=Bool) = labeled_tuple in\n\n\ - # Labels are optional and can be interspersed throughout a \ - label #\n\ - let mixed_labels : (Int, a=String, Float, flag=Bool) = (1, \ - a=\"String Value\", 2.5, flag=true) in\n\n\ - type Person = (String, age=Int,favorite_color=String) in\n\ - # These labels can be automatically applied based on the type \ - expectation #\n\ - let alice : Person = (\"Alice\", 22, \"Blue\") in\n\ - # Explicitly Labeled elements are automatically reordered#\n\ - let bob : Person = (age=25, favorite_color=\"Red\", \"Bob\") in \ - # equals (\"Bob\", age=25, favorite_color=\"Red\")#\n\n\ - # Destructuring #\n\ - let (bobs_name, age=bobs_age, \ - favorite_color=bobs_favorite_color) = bob in\n\n\ - \ \n\n\n"; + Normal)))(backpack())(relatives((siblings((((Grout((id \ + e87c8d67-9374-4a6f-ba01-5ec8f300b924)(shape \ + Convex))))))(ancestors())))(caret Outer))"; + backup_text = ""; }; { zipper = From b242321284e0981b41d5d58b577a93c4d4991838 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 20:47:59 -0400 Subject: [PATCH 063/108] Add sdocumentation page for labeled tuples --- src/haz3lweb/Init.ml | 601 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 601 insertions(+) diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index c3d2de0aba..e5e3defafe 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -17555,6 +17555,607 @@ let startup : PersistentData.t = # All output from examples: #\n\ (ex1, ex2, ex3, ex4, ex5)"; } ); + ( "Labeled Tuples", + { + zipper = + "((selection((focus Left)(content())(mode \ + Normal)))(backpack())(relatives((siblings(((Secondary((id \ + 1d22b099-baac-4811-86f4-3d4b778b8d04)(content(Comment\"# \ + Labeled Tuples #\"))))(Secondary((id \ + 029cce32-17ab-490b-b2f1-e25219197dff)(content(Whitespace\"\\n\"))))(Secondary((id \ + c3e170b1-8aeb-46f6-a78d-49cb6d86915a)(content(Whitespace\"\\n\"))))(Secondary((id \ + b1a9fa5d-4671-44c8-a303-96d7400f23d3)(content(Comment\"# \ + Tuples can have labels#\"))))(Secondary((id \ + 668efc29-986d-4f42-905e-84c7606b176b)(content(Whitespace\"\\n\"))))(Tile((id \ + 23795a9d-fa91-437f-a445-3652ac99fea5)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 0ab08c67-2641-47c5-bad2-bb0fa0b577fa)(content(Whitespace\" \ + \"))))(Tile((id \ + 374004dd-f688-48f3-9aa0-5752419d8775)(label(labeled_tuple))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 776dce9f-e223-4a19-995e-fdb5e9d5fbab)(content(Whitespace\" \ + \")))))((Secondary((id \ + aeeee415-16ca-459f-9fba-3820adc957b6)(content(Whitespace\" \ + \"))))(Tile((id \ + c73cedb9-eef3-4a02-8ea0-dc89c6b0ffce)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 08be2aff-62bb-4bb1-919f-b4d81f5b87eb)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + ba0c2fe0-2a43-4004-b3b1-ced4b85b3449)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 4b14f8cf-7e92-4b28-8495-309f8e6bd981)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 64acb788-0804-4a9e-b065-2235b21c3b02)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + cc891159-5869-4dfc-8f7c-0fd0116b343b)(content(Whitespace\" \ + \"))))(Tile((id \ + 577eb92e-9228-482f-a39b-bc7d25ea3a74)(label(b))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 23e7b4b7-a92a-43eb-93a2-24a4a671161a)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 0e01f92e-4201-4b0c-ab18-c02dd502075e)(label(2.0))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + b6c69ff0-709b-490b-b309-1c9cb38ac5c1)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 96b4438c-a9f8-4b92-971d-d0d4a1b19961)(content(Whitespace\" \ + \"))))(Tile((id \ + cb883be5-c6a8-47d1-8a7e-5f43b07d41cd)(label(c))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 82552269-8149-450d-b422-64c7493c13e1)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 163f4628-edf1-4911-9364-689f5f238c82)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + d60bb231-bfe5-4b6d-8a53-46b2821680dd)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 5038abcb-455b-47da-8ce6-4d3be238998a)(content(Whitespace\"\\n\"))))(Secondary((id \ + ca401b23-4366-4cdf-957a-a6a39b861998)(content(Comment\"# \ + These labels can be projected #\"))))(Secondary((id \ + 4e035ed4-f928-4593-a7f8-491435d7137e)(content(Whitespace\"\\n\"))))(Tile((id \ + 6e28c23a-375a-4f47-80d1-11a0dbdbfd3e)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + cb2d5793-8d88-4d3a-9a4f-5ca82aefc774)(content(Whitespace\" \ + \"))))(Tile((id \ + 7bbbf7b6-ebdc-4e58-bdca-2654b0ccb9d6)(label(prj_a))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + c5b250bb-1fb9-4276-b793-0221b252c8b1)(content(Whitespace\" \ + \"))))(Tile((id \ + 2fad8b7f-6410-47e2-8786-4798001dcdb7)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + b92af63d-5b68-440d-ac0a-3cc6ae28330f)(content(Whitespace\" \ + \"))))(Tile((id \ + 09a6433d-266d-4aef-b528-7920b2650305)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ + f24cff31-85a2-4d6f-ad5c-4a2284b7f17e)(content(Whitespace\" \ + \")))))((Secondary((id \ + 17dbbfc0-656a-46fd-9365-c1c2ea6dd286)(content(Whitespace\" \ + \"))))(Tile((id \ + 2effe10f-7e24-4907-a7b3-cf4b34b663e9)(label(labeled_tuple))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 6d7af305-b6c2-4a5c-bfde-edda62f126bf)(label(.))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 2))(sort \ + Exp))((shape(Concave 2))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + bdef8806-3ecc-4c67-be5c-cf7d3ed2fce9)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 4dc7a1ca-8770-467b-a81c-a245429d62ff)(content(Whitespace\" \ + \"))))(Secondary((id \ + 97350724-14de-4cfe-b5dc-820beca6a652)(content(Comment\"# 1 \ + #\"))))(Secondary((id \ + 6e55064c-2947-4769-b4bb-29d560f662f6)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + ca0d2c33-96ef-44c6-ac6e-f8a4d7901280)(content(Whitespace\" \ + \"))))(Secondary((id \ + 98524bad-9684-472a-a0c8-b1204357df66)(content(Whitespace\"\\n\"))))(Secondary((id \ + 38404748-91f8-4ff9-bf3e-6079ab3a3add)(content(Whitespace\"\\n\")))))((Secondary((id \ + fbc19dd7-8fdb-4932-87af-5b52f6a093bb)(content(Comment\"# \ + These can be encoded the types #\"))))(Secondary((id \ + 312fb397-2960-419d-8012-b3844228b045)(content(Whitespace\"\\n\"))))(Tile((id \ + 791f51eb-c011-424e-b6f7-c38517c3c5d3)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 1061312e-02d1-4ac2-b2b5-0432ef53c6c3)(content(Whitespace\" \ + \"))))(Tile((id \ + 1d69bc5e-76dc-4de1-96ba-f3c6e0704a2b)(label(typed_lt))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + be603a96-4fc1-4b57-8dcc-0768264c9798)(content(Whitespace\" \ + \"))))(Tile((id \ + 7eedad44-3ec3-4256-b621-ac301d91dad2)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9671104c-9ffa-4912-9f21-f46b308d0335)(content(Whitespace\" \ + \"))))(Tile((id \ + ea52c55a-ba30-473d-8214-a685ffde4eb3)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 2d81cb0d-d4c0-4032-8fe3-b734f68d5343)(label(a))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 1a7028bc-734d-40ce-b63b-baa31eb5966a)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 39fc34a0-cdd6-476f-a0c6-e15de827ad81)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 11f70cfb-7527-4965-8e86-36cd99dd1470)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 0c00141e-9c75-45aa-bc2b-4927df8fd199)(content(Whitespace\" \ + \"))))(Tile((id \ + b3753058-016c-47ca-b53c-d4e663a9d39f)(label(b))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + c9f6de02-1793-4006-b79b-074ec663efad)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 295bbc9b-86d8-454c-adfb-51b9bbb37abe)(label(Float))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + c7d366ac-c0db-47b5-ba48-9d7a78be4a28)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + bd447665-f6cf-4bb9-9bfb-a9782e7125b3)(content(Whitespace\" \ + \"))))(Tile((id \ + c6c89a67-1cbb-41c0-98bf-3e5d875fb9cd)(label(c))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + f626e35e-b6af-4e72-b758-df9c9ce90493)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 2041fea5-1d59-4998-9f2e-3d7d20e8f519)(label(Bool))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 7c74d480-0097-4740-a918-7b5345a875eb)(content(Whitespace\" \ + \")))))((Secondary((id \ + 058c6341-431b-4045-98f3-1227ac57bca1)(content(Whitespace\" \ + \"))))(Tile((id \ + cbcebeee-2946-41d7-af56-10acfc3ee98b)(label(labeled_tuple))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 95cf3af0-a1f4-4639-802b-8e6a68b821aa)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 7df90b9b-fc87-4093-8a73-f1dd5f9b4e7b)(content(Whitespace\"\\n\"))))(Secondary((id \ + 87181a2a-7168-4fcb-922c-03c6f08cb29a)(content(Whitespace\"\\n\"))))(Secondary((id \ + 2d1cd3ec-0347-4ad3-8d1d-f90b8ee226bc)(content(Comment\"# \ + Labels are optional and can be interspersed throughout a \ + label #\"))))(Secondary((id \ + 6304d9bb-70f1-4711-af0a-3ceca5abf350)(content(Whitespace\"\\n\"))))(Tile((id \ + c03a5bf0-5b40-4db5-833d-aa7ccc5f1de9)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 8ce73b84-f462-45d0-b8f9-c5b1ec532ece)(content(Whitespace\" \ + \"))))(Tile((id \ + a16b7bdb-34bc-481b-99a2-d9b3fe4c43e9)(label(mixed_labels))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 88c2b5e3-4624-4004-956c-e2c4e56ada6c)(content(Whitespace\" \ + \"))))(Tile((id \ + e1b247ba-d61f-4616-88df-064c2b7fd3a6)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + e47e4eee-8023-46a0-9f3e-cbd22343c821)(content(Whitespace\" \ + \"))))(Tile((id \ + b1d12b65-0bde-4897-be50-9382a322d257)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 085dbae6-4130-4b47-92ca-5292fe150994)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + e55ee8c2-9a8a-4139-9ea1-682d2d310402)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 9d5cfb64-78af-4a52-9833-6431217e882c)(content(Whitespace\" \ + \"))))(Tile((id \ + 3b1add0f-323b-4023-a55c-a42fd1032b4d)(label(a))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 977eb5ad-75f9-4480-baa0-50c6e374f0ba)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 19b644d1-a6a0-41ba-8624-61eeaad5e300)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + e54ed288-ac41-4a9f-841d-5243dc7376c1)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 513ff80c-bf03-4deb-b410-29faeac69a2d)(content(Whitespace\" \ + \"))))(Tile((id \ + 2a77c478-08ea-4569-81ef-c3b7cc56d0e1)(label(Float))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + ab9239e3-4316-44cb-9899-9aa69c755279)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + c548f75f-47a0-4ab4-86e8-69e634a4cca6)(content(Whitespace\" \ + \"))))(Tile((id \ + 3c55d843-a871-418c-9eff-da75446c297e)(label(flag))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + d1ed7227-a849-44ab-9890-8d264b5f1945)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 020058df-9514-49a0-9645-677851c38bb2)(label(Bool))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 40c93475-ca3b-41e8-8b21-1051f0fa687f)(content(Whitespace\" \ + \")))))((Secondary((id \ + e6102414-8e6a-49d8-8a4b-c30d478ff2c4)(content(Whitespace\" \ + \"))))(Tile((id \ + b28ba9ca-6b59-4d5c-9fcf-6ae44e1e204f)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 88d1e44a-ec5a-4157-ae30-75bf01cad38c)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 21c197df-d99d-4d9d-a358-a67c10d5cccc)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + cb832565-6203-49ff-b53e-64fd5b3c6e49)(content(Whitespace\" \ + \"))))(Tile((id \ + cce72259-be1e-4bc7-8500-1ba2bf15c674)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 4a61fc13-383b-47a7-972b-d6faa7503456)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 3a55f509-fd99-44fa-8ee1-3d41554353bf)(label(\"\\\"String \ + Value\\\"\"))(mold((out Exp)(in_())(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 51c1a82b-60b3-4c5a-8626-08a974105ae1)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5eb818c5-d046-4862-b6e4-03e135fc56cf)(content(Whitespace\" \ + \"))))(Tile((id \ + 65876d7a-f0ab-4fba-a53a-00bd9b55dcfc)(label(2.5))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + ab3377df-c4ba-45ff-a280-888d3a4c0ae7)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 333f4c49-4a0d-4ea9-841b-e8b6f43a8765)(content(Whitespace\" \ + \"))))(Tile((id \ + 0e51bceb-1bf0-40b1-b825-225d9c42c415)(label(flag))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + d67f063a-acd8-4bb0-86e6-87b8a6314bba)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 3b3683bc-a873-49ff-9aab-9f5d2ff8a384)(label(true))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + b0a7bb24-0bdd-4ff7-8792-c404acc07832)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 006326dd-00d8-4ffd-99e0-f9e14310393f)(content(Whitespace\"\\n\"))))(Secondary((id \ + 9cee0316-ff16-45fc-8222-5a8004de1f1b)(content(Whitespace\"\\n\"))))(Tile((id \ + ca249965-e64a-4466-9054-2f8b8087e172)(label(type = \ + in))(mold((out Exp)(in_(TPat Typ))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + ce8336b7-fd8f-4766-9bc2-85e041f76ea2)(content(Whitespace\" \ + \"))))(Tile((id \ + dffcb8bd-d722-48ab-93b8-d096a011b106)(label(Person))(mold((out \ + TPat)(in_())(nibs(((shape Convex)(sort TPat))((shape \ + Convex)(sort \ + TPat))))))(shards(0))(children())))(Secondary((id \ + 6c2dfa03-96af-4244-9ad1-5aca79846f59)(content(Whitespace\" \ + \")))))((Secondary((id \ + 28b30431-f967-4a84-b719-3ee6dd323971)(content(Whitespace\" \ + \"))))(Tile((id \ + d46306e3-6845-4d24-9e26-b4b0292ec03b)(label(\"(\"\")\"))(mold((out \ + Typ)(in_(Typ))(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0 1))(children(((Tile((id \ + 71962028-dd1f-4b58-8881-6e72e881deb7)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + c087cb02-0d08-4b91-8e34-99a0f2369e1a)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + a3cc0163-1461-4774-b351-3be27ddb56ec)(content(Whitespace\" \ + \"))))(Tile((id \ + b1c7750d-d878-4561-bfd5-c8583121858b)(label(age))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 03ce37fb-27dc-4b48-a329-d0538384b590)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 083755c0-e2a7-465e-9fb8-b1fb5d73725c)(label(Int))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 745a5f93-acf5-4e56-9ef8-6d9c9e9df676)(label(,))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 18))(sort \ + Typ))((shape(Concave 18))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + 67a5db8b-7000-45f6-ae8f-86027d382414)(label(favorite_color))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Tile((id \ + 10cf3666-399c-4136-be8f-60a561558bbe)(label(=))(mold((out \ + Typ)(in_())(nibs(((shape(Concave 16))(sort \ + Typ))((shape(Concave 16))(sort \ + Typ))))))(shards(0))(children())))(Tile((id \ + f095c3a4-97e2-4433-aa7d-33ffa6775118)(label(String))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 0254047f-2d49-49da-a292-8ae1c8bd9315)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 30456699-1693-415d-a38e-b103a1d4f4ca)(content(Whitespace\"\\n\"))))(Secondary((id \ + 4a35bd2e-ceac-4010-9b5e-b96baa3abef7)(content(Comment\"# \ + These labels can be automatically applied based on the type \ + expectation #\"))))(Secondary((id \ + e9813292-9c79-4183-9279-a341eacd3539)(content(Whitespace\"\\n\"))))(Tile((id \ + 0dfaf809-1beb-41e2-827a-bb9892dc0dbe)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 4911aaae-dcab-49b2-b114-dc86b6af73b8)(content(Whitespace\" \ + \"))))(Tile((id \ + 8b2a6afc-1c96-4e7e-b272-d516fb60c351)(label(alice))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 83a57212-492f-4c9e-b2d4-c5633c00492f)(content(Whitespace\" \ + \"))))(Tile((id \ + 0b4b1269-4a3b-4d77-8573-a57eaa2c2ff2)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 97236a27-c11a-4f08-a6dc-f2095a2ad44d)(content(Whitespace\" \ + \"))))(Tile((id \ + 221deda5-eb21-40a7-83b8-a4d3f0c72747)(label(Person))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 8c693b47-51a0-4394-a36d-0c55ed746ba2)(content(Whitespace\" \ + \")))))((Secondary((id \ + d84f659d-563b-4065-8352-0b48a0dbbc15)(content(Whitespace\" \ + \"))))(Tile((id \ + 3fce66bd-c247-471c-92b2-baabe04684aa)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + c3e4496d-c777-49da-b359-e87e57f500d8)(label(\"\\\"Alice\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 48ba350a-53b5-4afa-905a-8b113add1293)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 3f69e5d2-93c3-4464-9929-7684a8b4cce8)(content(Whitespace\" \ + \"))))(Tile((id \ + ead66a1a-2749-4c00-8c72-a1be1dbd9138)(label(22))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 8d300e9e-01fb-4ca7-98f9-d0e6761eee55)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 4f18f100-b7fa-4a75-9c20-bc59f55991b1)(content(Whitespace\" \ + \"))))(Tile((id \ + 8658b876-0dbe-41d2-8012-42a1d9eeedbd)(label(\"\\\"Blue\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + c3ebb086-566a-44a9-a3f1-02778e67cd50)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 87947367-9bf5-458f-a957-fd401c6fe62d)(content(Whitespace\"\\n\"))))(Secondary((id \ + 6ee9768e-9165-4e4b-9edc-0f5b431f3b4e)(content(Comment\"# \ + Explicitly Labeled elements are automatically \ + reordered#\"))))(Secondary((id \ + 160bfc3e-2922-46da-8880-6a55ec4e8f08)(content(Whitespace\"\\n\"))))(Tile((id \ + 9fb5dc17-bf6f-42a1-bad6-a7141ab485ff)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 44556e11-4a18-4808-8e3b-96a449991571)(content(Whitespace\" \ + \"))))(Tile((id \ + 1915e41b-fe9e-4d75-8147-05a8de710213)(label(bob))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 936f49f0-7701-46d3-9106-c5a513d9bcd8)(content(Whitespace\" \ + \"))))(Tile((id \ + ea62f713-8e6c-43ee-ad43-7960aa751f42)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + cd474fd5-2959-4f9c-a1b4-5fdf2dd5a8bd)(content(Whitespace\" \ + \"))))(Tile((id \ + fd2b6d83-7e76-4bc5-9ee9-acf808142cb2)(label(Person))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort Typ))))))(shards(0))(children())))(Secondary((id \ + 5fc66ce9-3fab-4aef-85a9-4bef5b776355)(content(Whitespace\" \ + \")))))((Secondary((id \ + 6f0cfe1c-1274-4ca6-9230-a41ac4afd6ea)(content(Whitespace\" \ + \"))))(Tile((id \ + d5fcc42c-8f5e-429b-bca3-e0316b162a7a)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + b4672fe9-7b7f-486c-9fd7-31caa7a850dd)(label(age))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + f0bac892-177e-4d96-88de-e4d17dc891c0)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 1c4d0130-d17f-432b-8692-f87ab2c096a8)(label(25))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 05e7f039-2de3-4e31-91eb-a99c4566d90b)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 21495a10-72b3-4ced-9292-fc8c8415cd4b)(content(Whitespace\" \ + \"))))(Tile((id \ + 79158e46-09bb-4bdd-9e94-d43513f0a6cc)(label(favorite_color))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 90a05943-35bb-4045-84d5-1a9d9f4f9933)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 46b0779f-2d9e-4171-abab-3a5e49ee6f57)(label(\"\\\"Red\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 2fa915a0-88fb-45f9-ba3b-d05260c06e4e)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + a08417ac-4577-411a-854a-eda4acf4964b)(content(Whitespace\" \ + \"))))(Tile((id \ + 3a8e7e83-74ec-444a-a7df-06d68f289bc3)(label(\"\\\"Bob\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + db14a17f-90ca-498b-af9e-8690c183c312)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 55d9fe07-3edd-4db1-98c4-881a873ecaa2)(content(Whitespace\" \ + \"))))(Secondary((id \ + 3aeb958c-78e8-41ca-8bd8-e4fe58ab1279)(content(Comment\"# \ + equals (\\\"Bob\\\", age=25, \ + favorite_color=\\\"Red\\\")#\"))))(Secondary((id \ + 3dc6447b-da88-4cc0-8d41-fa06812d2f2b)(content(Whitespace\"\\n\"))))(Secondary((id \ + 105ece24-a726-45da-87f3-6888e1cdedbe)(content(Whitespace\"\\n\"))))(Secondary((id \ + 0a3fa6fe-890f-434b-b9f9-fb84b56a81fb)(content(Comment\"# \ + Destructuring #\"))))(Secondary((id \ + dfcae445-0ba1-4676-91e0-3273c23f9766)(content(Whitespace\"\\n\"))))(Tile((id \ + e91a3973-b16d-49a4-a59d-380a2979c970)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 892a74b8-31ca-477d-abd8-386d58d88f28)(content(Whitespace\" \ + \"))))(Tile((id \ + 88159ab5-30b8-46d7-9f90-475b8d94c1f4)(label(\"(\"\")\"))(mold((out \ + Pat)(in_(Pat))(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0 1))(children(((Tile((id \ + 60d7049c-eb88-4791-9809-6b99b6678e38)(label(bobs_name))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + f6bff178-21db-4571-99d6-620d4d3d3bcb)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 18))(sort \ + Pat))((shape(Concave 18))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 1fd05df6-54a0-4a88-b9ea-a3c9d4081260)(content(Whitespace\" \ + \"))))(Tile((id \ + 937f5455-014e-49ee-9582-b8b2d41115b0)(label(age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 060f122d-3e7b-4bc1-bf84-9642626f1555)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort \ + Pat))((shape(Concave 16))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 3206215b-978a-4d6b-8ae9-1b9210b0d49b)(label(bobs_age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 965a3191-2574-4447-b05b-0d40f9d83946)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 18))(sort \ + Pat))((shape(Concave 18))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 38246b0f-0bee-46e7-b01b-0d8afc2fbd0d)(content(Whitespace\" \ + \"))))(Tile((id \ + 407f97ee-e857-4ce8-83fe-634df9404c38)(label(favorite_color))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 34a291de-b553-482e-92fb-b0ec3a2c6e0a)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort \ + Pat))((shape(Concave 16))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 30328d7c-b472-4dae-b050-6d959fe7be32)(label(bobs_favorite_color))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort \ + Pat))))))(shards(0))(children()))))))))(Secondary((id \ + 2d1138cf-7b53-4891-bbe7-9443bc061639)(content(Whitespace\" \ + \")))))((Secondary((id \ + 90bf31c2-7807-4d05-af22-bfb0803990a2)(content(Whitespace\" \ + \"))))(Tile((id \ + 3d677f5a-b880-49e5-9171-ed5a21307452)(label(bob))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Secondary((id \ + 99c467af-0605-4a51-814b-6fe35edb5b59)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 1672c094-ce77-4a2c-a610-f352d9c00f7f)(content(Whitespace\"\\n\"))))(Secondary((id \ + 183b912f-dde9-4f06-8047-2b73d3e7ac89)(content(Whitespace\"\\n\"))))(Grout((id \ + 108cfcfd-2e17-407c-8380-ec1e63151450)(shape \ + Convex)))(Secondary((id \ + 867bbf01-916d-4d3e-9b99-1d4337659f57)(content(Whitespace\" \ + \"))))(Secondary((id \ + 0342f646-322c-4f68-98cf-de94b4df6e3d)(content(Whitespace\"\\n\"))))(Secondary((id \ + fa4a94d2-5955-4f8a-a958-6d8c8ebeaefb)(content(Whitespace\"\\n\"))))(Secondary((id \ + d6e2d5c6-1ac7-42ca-9894-0f26ea900668)(content(Whitespace\"\\n\")))))))(ancestors())))(caret(Inner \ + 33 13)))"; + backup_text = + "# Labeled Tuples #\n\n\ + # Tuples can have labels#\n\ + let labeled_tuple = (a=1, b=2.0, c=true) in\n\ + # These labels can be projected #\n\ + let prj_a : Int = labeled_tuple.a # 1 # in \n\n\ + # These can be encoded the types #\n\ + let typed_lt : (a=Int, b=Float, c=Bool) = labeled_tuple in\n\n\ + # Labels are optional and can be interspersed throughout a \ + label #\n\ + let mixed_labels : (Int, a=String, Float, flag=Bool) = (1, \ + a=\"String Value\", 2.5, flag=true) in\n\n\ + type Person = (String, age=Int,favorite_color=String) in\n\ + # These labels can be automatically applied based on the type \ + expectation #\n\ + let alice : Person = (\"Alice\", 22, \"Blue\") in\n\ + # Explicitly Labeled elements are automatically reordered#\n\ + let bob : Person = (age=25, favorite_color=\"Red\", \"Bob\") \ + in # equals (\"Bob\", age=25, favorite_color=\"Red\")#\n\n\ + # Destructuring #\n\ + let (bobs_name, age=bobs_age, \ + favorite_color=bobs_favorite_color) = bob in\n\n\ + \ \n\n\n"; + } ); ( "Expressive Programming", { zipper = From de85c69e1ce5fe9452a6d217644de5d6eea1713a Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 21:05:32 -0400 Subject: [PATCH 064/108] Tests for multiple labels --- test/Test_MakeTerm.re | 34 ++++++++++++++++++++++++++++++++++ test/Test_Statics.re | 22 ++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/test/Test_MakeTerm.re b/test/Test_MakeTerm.re index 13894ee3bb..d5e8bc9a7d 100644 --- a/test/Test_MakeTerm.re +++ b/test/Test_MakeTerm.re @@ -73,4 +73,38 @@ let tests = [ let y : (l=Int) = x in y", ) }), + test_case("Multiple labels in tuple", `Quick, () => { + exp_check( + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("l2") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens( + Tuple([ + TupLabel(Label("l") |> Exp.fresh, Int(32) |> Exp.fresh) + |> Exp.fresh, + TupLabel(Label("l2") |> Exp.fresh, String("") |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + {|let x : (l=Int, l2=String) = (l=32, l2="") in x|}, + ) + }), ]; diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 4734ff342d..e85718e79a 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -370,4 +370,26 @@ let tests = ) |> Exp.fresh, ), + fully_consistent_typecheck( + "Labeled tuple with multiple labels", + {|(l=32, l2="")|}, + Some( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, + TupLabel(Label("l2") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ), + Parens( + Tuple([ + TupLabel(Label("l") |> Exp.fresh, Int(32) |> Exp.fresh) + |> Exp.fresh, + TupLabel(Label("l2") |> Exp.fresh, String("") |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + ), ]; From 3c365668f02fa60e38ef5b4db057447ef48d31bd Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 21:23:09 -0400 Subject: [PATCH 065/108] Update Makefile to include dev profile in watch-test --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c1f5943d07..9bbf3c910a 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ test: node $(TEST_DIR)/haz3ltest.bc.js watch-test: - dune build @fmt @runtest --auto-promote --watch + dune build @fmt @runtest @default --profile dev --auto-promote --watch clean: dune clean From 72b4cacdc509aba4416649eb1542a5e15d0f0335 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Sun, 13 Oct 2024 21:23:30 -0400 Subject: [PATCH 066/108] Add test case for singleton labeled tuple adding label --- test/Test_Elaboration.re | 45 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 43af68088b..e5defe3850 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -418,6 +418,49 @@ let elaboration_tests = [ // `Quick, // singleton_labeled_tuple_elaborates_labels, // ), - test_case("Singleton labeled tuple", `Quick, singleton_labeled_tuple) // TODO Make consistent with make term + test_case("Singleton labeled tuple", `Quick, singleton_labeled_tuple), // TODO Make consistent with make term // TODO Add singleton labeled function application + test_case("Singleton labeld tuple analysis adds label", `Quick, () => + alco_check( + "Singleton labeld tuple analysis adds label", + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens(Tuple([String("a") |> Exp.fresh]) |> Exp.fresh) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp( + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + ), + ) + ), ]; From 828da515dc4335170ffe8a178a54a9a7878aa9ba Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 14 Oct 2024 09:33:51 -0400 Subject: [PATCH 067/108] Make labeled tuple not need parens in display --- src/haz3lcore/lang/term/Typ.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index 9a2b757997..d844d878b3 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -598,13 +598,13 @@ let rec needs_parens = (ty: t): bool => | String | Label(_) | Bool + | TupLabel(_, _) | Var(_) => false | Rec(_, _) | Forall(_, _) => true | List(_) => false /* is already wrapped in [] */ | Arrow(_, _) => true | Prod(_) - | TupLabel(_, _) | Sum(_) => true /* disambiguate between (A + B) -> C and A + (B -> C) */ }; From 7688a2b7acd45ae895da6d628075bfa10225b00f Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 14 Oct 2024 09:45:19 -0400 Subject: [PATCH 068/108] Add test case for let statement that adds labels during elaboration --- test/Test_Statics.re | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index e85718e79a..d73da26fbd 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -392,4 +392,44 @@ let tests = ) |> Exp.fresh, ), + fully_consistent_typecheck( + "Let statement that adds labels during elaboration", + {|let add : (street=String, city=String, state=String, zipcode=Int)= ("123 Maple St", "Ann Arbor", "MI", 48103) |}, + Some( + Prod([ + TupLabel(Label("street") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("city") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ), + Let( + Cast( + Var("add") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("street") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + TupLabel(Label("city") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens( + Tuple([ + String("123 Maple St") |> Exp.fresh, + String("Ann Arbor") |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + Var("add") |> Exp.fresh, + ) + |> Exp.fresh, + ), ]; From c86e5f08edd8548b266b3bb1a4eeaa3b38d185ad Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 14 Oct 2024 11:19:44 -0400 Subject: [PATCH 069/108] Add support for lifting single values into a singleton labeled tuple when the label is not present --- src/haz3lcore/statics/Statics.re | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 91b4651255..be132951f1 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -223,6 +223,29 @@ and uexp_to_info_map = ); let go_pat = upat_to_info_map(~ctx, ~ancestors); let atomic = self => add(~self, ~co_ctx=CoCtx.empty, m); + + // This is to allow lifting single values into a singleton labeled tuple when the label is not present + // TODO Think about this real hard + let uexp = + switch (mode) { + | Ana(ty) => + let ty = Typ.weak_head_normalize(ctx, ty).term; + switch (ty) { + | Prod([{term: TupLabel({term: Label(l1), _}, ty), _}]) => + let (e, m) = go(~mode=Mode.Syn, uexp, m); + switch (Typ.weak_head_normalize(e.ctx, e.ty).term) { + | Prod([{term: TupLabel({term: Label(l2), _}, ty), _}]) + when l1 == l2 => uexp + | _ => + + Tuple([uexp]) |> Exp.fresh; + }; + | _ => uexp + }; + | _ => uexp + }; + let term = uexp.term; + switch (term) { | Closure(_) => failwith( From dac5119ae818287d6fcf583ba11aae78d2072abf Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 14 Oct 2024 11:39:29 -0400 Subject: [PATCH 070/108] Refmt --- src/haz3lcore/statics/Statics.re | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index be132951f1..9d90bdc49c 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -233,12 +233,11 @@ and uexp_to_info_map = switch (ty) { | Prod([{term: TupLabel({term: Label(l1), _}, ty), _}]) => let (e, m) = go(~mode=Mode.Syn, uexp, m); + switch (Typ.weak_head_normalize(e.ctx, e.ty).term) { | Prod([{term: TupLabel({term: Label(l2), _}, ty), _}]) when l1 == l2 => uexp - | _ => - - Tuple([uexp]) |> Exp.fresh; + | _ => Tuple([uexp]) |> Exp.fresh }; | _ => uexp }; From 3420d2cc3a756a6d95e9ae2d527e7b1635a390df Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 14 Oct 2024 15:18:24 -0400 Subject: [PATCH 071/108] Additional test for singleton labels --- test/Test_Statics.re | 109 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 12 deletions(-) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index d73da26fbd..79720aa6e5 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -54,6 +54,32 @@ let type_of = (~statics_map=?, f) => { ); }; +let inconsistent_typecheck = (name, serialized, expected, exp) => { + test_case( + name, + `Quick, + () => { + let s = statics(exp); + let errors = + List.map( + (id: Id.t) => { + let info = Id.Map.find(id, s); + switch (info) { + | InfoExp(ie) => ie.status + | _ => fail("Expected InfoExp") + }; + }, + Statics.Map.error_ids(s), + ); + if (errors == []) { + fail("Expected errors"); + }; + print_endline( + "Errors: " ++ [%derive.show: list(Info.status_exp)](errors), + ); + }, + ); +}; let fully_consistent_typecheck = (name, serialized, expected, exp) => { test_case( name, @@ -370,6 +396,69 @@ let tests = ) |> Exp.fresh, ), + inconsistent_typecheck( + "Singleton Labled Tuple ascription in let with wrong type should fail", + "let x : (l=String) = 1 in x", + Some( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, + ]) + |> Typ.fresh, + ), + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Int(1) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + ), + fully_consistent_typecheck( + "Singleton Labled Tuple with specified label", + "let x : (l=String) = (l=\"a\") in x", + Some( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, + ]) + |> Typ.fresh, + ), + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Parens( + Tuple([ + TupLabel(Label("l") |> Exp.fresh, String("a") |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + ), fully_consistent_typecheck( "Labeled tuple with multiple labels", {|(l=32, l2="")|}, @@ -394,24 +483,23 @@ let tests = ), fully_consistent_typecheck( "Let statement that adds labels during elaboration", - {|let add : (street=String, city=String, state=String, zipcode=Int)= ("123 Maple St", "Ann Arbor", "MI", 48103) |}, + {|let x : (name=String, age=Int)= ("Bob", 20) |}, Some( Prod([ - TupLabel(Label("street") |> Typ.fresh, String |> Typ.fresh) - |> Typ.fresh, - TupLabel(Label("city") |> Typ.fresh, String |> Typ.fresh) + TupLabel(Label("name") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, + TupLabel(Label("age") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, ]) |> Typ.fresh, ), Let( Cast( - Var("add") |> Pat.fresh, + Var("x") |> Pat.fresh, Parens( Prod([ - TupLabel(Label("street") |> Typ.fresh, String |> Typ.fresh) + TupLabel(Label("name") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, - TupLabel(Label("city") |> Typ.fresh, String |> Typ.fresh) + TupLabel(Label("age") |> Typ.fresh, Int |> Typ.fresh) |> Typ.fresh, ]) |> Typ.fresh, @@ -421,14 +509,11 @@ let tests = ) |> Pat.fresh, Parens( - Tuple([ - String("123 Maple St") |> Exp.fresh, - String("Ann Arbor") |> Exp.fresh, - ]) + Tuple([String("Bob") |> Exp.fresh, Int(20) |> Exp.fresh]) |> Exp.fresh, ) |> Exp.fresh, - Var("add") |> Exp.fresh, + Var("x") |> Exp.fresh, ) |> Exp.fresh, ), From 1fa320c1e6b2b9bc85bc1c5a4966caa63242f899 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 14 Oct 2024 16:54:10 -0400 Subject: [PATCH 072/108] SIngleton labels kind of work --- src/haz3lcore/statics/Statics.re | 1132 ++++++++++++++++-------------- 1 file changed, 586 insertions(+), 546 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 9d90bdc49c..f65d7a30c9 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -185,9 +185,12 @@ and uexp_to_info_map = 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 add = (~self, ~co_ctx, m) => { + add'(~self=Common(self), ~co_ctx, m); + }; // add if uexp changed // let add_exp = (~self, ~co_ctx, ~uexp, m) => { // let info = @@ -222,581 +225,618 @@ and uexp_to_info_map = ([], m), ); let go_pat = upat_to_info_map(~ctx, ~ancestors); - let atomic = self => add(~self, ~co_ctx=CoCtx.empty, m); - - // This is to allow lifting single values into a singleton labeled tuple when the label is not present - // TODO Think about this real hard - let uexp = - switch (mode) { - | Ana(ty) => - let ty = Typ.weak_head_normalize(ctx, ty).term; - switch (ty) { - | Prod([{term: TupLabel({term: Label(l1), _}, ty), _}]) => - let (e, m) = go(~mode=Mode.Syn, uexp, m); + let atomic = self => { + add(~self, ~co_ctx=CoCtx.empty, m); + }; - switch (Typ.weak_head_normalize(e.ctx, e.ty).term) { - | Prod([{term: TupLabel({term: Label(l2), _}, ty), _}]) - when l1 == l2 => uexp - | _ => Tuple([uexp]) |> Exp.fresh - }; - | _ => uexp + let default_case = () => + switch (term) { + | Closure(_) => + failwith( + "TODO: implement closure type checking - see how dynamic type assignment does it", + ) + | MultiHole(tms) => + let (co_ctxs, m) = multi(~ctx, ~ancestors, m, tms); + add(~self=IsMulti, ~co_ctx=CoCtx.union(co_ctxs), m); + | Cast(e, t1, t2) + | FailedCast(e, t1, t2) => + let (e, m) = go(~mode=Ana(t1), e, m); + add(~self=Just(t2), ~co_ctx=e.co_ctx, m); + | Invalid(token) => atomic(BadToken(token)) + | EmptyHole => atomic(Just(Unknown(Internal) |> Typ.temp)) + | Deferral(position) => + add'(~self=IsDeferral(position), ~co_ctx=CoCtx.empty, m) + | Undefined => atomic(Just(Unknown(Hole(EmptyHole)) |> Typ.temp)) + | Bool(_) => atomic(Just(Bool |> Typ.temp)) + | Int(_) => atomic(Just(Int |> Typ.temp)) + | Float(_) => atomic(Just(Float |> Typ.temp)) + | String(_) => atomic(Just(String |> Typ.temp)) + | Label(name) => atomic(Just(Label(name) |> Typ.temp)) + | ListLit(es) => + 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.listlit(~empty=Unknown(Internal) |> Typ.temp, ctx, tys, ids), + ~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(hd.ty) |> Typ.temp), + ~co_ctx=CoCtx.union([hd.co_ctx, tl.co_ctx]), + m, + ); + | ListConcat(e1, e2) => + let mode = Mode.of_list_concat(ctx, mode); + let ids = List.map(UExp.rep_id, [e1, e2]); + let (e1, m) = go(~mode, e1, m); + let (e2, m) = go(~mode, e2, m); + add( + ~self=Self.list_concat(ctx, [e1.ty, e2.ty], ids), + ~co_ctx=CoCtx.union([e1.co_ctx, e2.co_ctx]), + m, + ); + | Var(name) => + add'( + ~self=Self.of_exp_var(ctx, name), + ~co_ctx=CoCtx.singleton(name, UExp.rep_id(uexp), Mode.ty_of(mode)), + m, + ) + | DynamicErrorHole(e, _) + | Parens(e) => + let (e, m) = go(~mode, e, m); + add(~self=Just(e.ty), ~co_ctx=e.co_ctx, m); + | UnOp(Meta(Unquote), e) when is_in_filter => + let e: UExp.t = { + ids: e.ids, + copied: false, + term: + switch (e.term) { + | Var("e") => UExp.Constructor("$e", Unknown(Internal) |> Typ.temp) + | Var("v") => UExp.Constructor("$v", Unknown(Internal) |> Typ.temp) + | _ => e.term + }, }; - | _ => uexp - }; - let term = uexp.term; - - switch (term) { - | Closure(_) => - failwith( - "TODO: implement closure type checking - see how dynamic type assignment does it", - ) - | MultiHole(tms) => - let (co_ctxs, m) = multi(~ctx, ~ancestors, m, tms); - add(~self=IsMulti, ~co_ctx=CoCtx.union(co_ctxs), m); - | Cast(e, t1, t2) - | FailedCast(e, t1, t2) => - let (e, m) = go(~mode=Ana(t1), e, m); - add(~self=Just(t2), ~co_ctx=e.co_ctx, m); - | Invalid(token) => atomic(BadToken(token)) - | EmptyHole => atomic(Just(Unknown(Internal) |> Typ.temp)) - | Deferral(position) => - add'(~self=IsDeferral(position), ~co_ctx=CoCtx.empty, m) - | Undefined => atomic(Just(Unknown(Hole(EmptyHole)) |> Typ.temp)) - | Bool(_) => atomic(Just(Bool |> Typ.temp)) - | Int(_) => atomic(Just(Int |> Typ.temp)) - | Float(_) => atomic(Just(Float |> Typ.temp)) - | String(_) => atomic(Just(String |> Typ.temp)) - | Label(name) => atomic(Just(Label(name) |> Typ.temp)) - | ListLit(es) => - 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.listlit(~empty=Unknown(Internal) |> Typ.temp, ctx, tys, ids), - ~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(hd.ty) |> Typ.temp), - ~co_ctx=CoCtx.union([hd.co_ctx, tl.co_ctx]), - m, - ); - | ListConcat(e1, e2) => - let mode = Mode.of_list_concat(ctx, mode); - let ids = List.map(UExp.rep_id, [e1, e2]); - let (e1, m) = go(~mode, e1, m); - let (e2, m) = go(~mode, e2, m); - add( - ~self=Self.list_concat(ctx, [e1.ty, e2.ty], ids), - ~co_ctx=CoCtx.union([e1.co_ctx, e2.co_ctx]), - m, - ); - | Var(name) => - add'( - ~self=Self.of_exp_var(ctx, name), - ~co_ctx=CoCtx.singleton(name, UExp.rep_id(uexp), Mode.ty_of(mode)), - m, - ) - | DynamicErrorHole(e, _) - | Parens(e) => - let (e, m) = go(~mode, e, m); - add(~self=Just(e.ty), ~co_ctx=e.co_ctx, m); - | UnOp(Meta(Unquote), e) when is_in_filter => - let e: UExp.t = { - ids: e.ids, - copied: false, - term: - switch (e.term) { - | Var("e") => UExp.Constructor("$e", Unknown(Internal) |> Typ.temp) - | Var("v") => UExp.Constructor("$v", Unknown(Internal) |> Typ.temp) - | _ => e.term - }, - }; - let ty_in = Typ.Var("$Meta") |> Typ.temp; - let ty_out = Typ.Unknown(Internal) |> Typ.temp; - let (e, m) = go(~mode=Ana(ty_in), e, m); - add(~self=Just(ty_out), ~co_ctx=e.co_ctx, m); - | UnOp(op, e) => - let (ty_in, ty_out) = typ_exp_unop(op); - 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 (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); - | TupLabel(label, e) => - let (labmode, mode) = Mode.of_label(ctx, mode); - let (lab, m) = go(~mode=labmode, label, m); - let (e, m) = go(~mode, e, m); - add( - ~self=Just(TupLabel(lab.ty, e.ty) |> Typ.temp), - ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), - m, - ); - | BuiltinFun(string) => - add'( - ~self=Self.of_exp_var(Builtins.ctx_init, string), - ~co_ctx=CoCtx.empty, - m, - ) - | Tuple(es) => - let (es, modes) = - Mode.of_prod(ctx, mode, es, UExp.get_label, (name, b) => - TupLabel(Label(name) |> Exp.fresh, b) |> Exp.fresh + let ty_in = Typ.Var("$Meta") |> Typ.temp; + let ty_out = Typ.Unknown(Internal) |> Typ.temp; + let (e, m) = go(~mode=Ana(ty_in), e, m); + add(~self=Just(ty_out), ~co_ctx=e.co_ctx, m); + | UnOp(op, e) => + let (ty_in, ty_out) = typ_exp_unop(op); + 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 (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, ); - let (es', m) = map_m_go(m, modes, es); - add( - ~self=Just(Prod(List.map(Info.exp_ty, es')) |> Typ.temp), - ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es')), - m, - ); - | Dot(e1, e2) => - let (info_e1, m) = go(~mode=Syn, e1, m); - let (ty, m) = { - switch (e2.term, info_e1.ty.term) { - | (Var(name), Unknown(_)) => - let ty = - Typ.Prod([ - TupLabel(Label(name) |> Typ.temp, Unknown(Internal) |> Typ.temp) - |> Typ.temp, - ]) - |> Typ.temp; - let (_, m) = go(~mode=Mode.Ana(ty), e1, m); - (ty, m); - | (_, Var(_)) => (Typ.weak_head_normalize(ctx, info_e1.ty), m) - | _ => (info_e1.ty, m) + | TupLabel(label, e) => + let (labmode, mode) = Mode.of_label(ctx, mode); + let (lab, m) = go(~mode=labmode, label, m); + let (e, m) = go(~mode, e, m); + add( + ~self=Just(TupLabel(lab.ty, e.ty) |> Typ.temp), + ~co_ctx=CoCtx.union([lab.co_ctx, e.co_ctx]), + m, + ); + | BuiltinFun(string) => + add'( + ~self=Self.of_exp_var(Builtins.ctx_init, string), + ~co_ctx=CoCtx.empty, + m, + ) + | Tuple(es) => + let (es, modes) = + Mode.of_prod(ctx, mode, es, UExp.get_label, (name, b) => + TupLabel(Label(name) |> Exp.fresh, b) |> Exp.fresh + ); + let (es', m) = map_m_go(m, modes, es); + add( + ~self=Just(Prod(List.map(Info.exp_ty, es')) |> Typ.temp), + ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es')), + m, + ); + | Dot(e1, e2) => + let (info_e1, m) = go(~mode=Syn, e1, m); + let (ty, m) = { + switch (e2.term, info_e1.ty.term) { + | (Var(name), Unknown(_)) => + let ty = + Typ.Prod([ + TupLabel( + Label(name) |> Typ.temp, + Unknown(Internal) |> Typ.temp, + ) + |> Typ.temp, + ]) + |> Typ.temp; + let (_, m) = go(~mode=Mode.Ana(ty), e1, m); + (ty, m); + | (_, Var(_)) => (Typ.weak_head_normalize(ctx, info_e1.ty), m) + | _ => (info_e1.ty, m) + }; }; - }; - switch (ty.term) { - | Prod(ts) => - switch (e2.term) { - | Var(name) => - let element: option(Typ.t) = - LabeledTuple.find_label(Typ.get_label, ts, name); - // let m = - // e2.ids - // |> List.fold_left( - // (m, id) => - // Id.Map.update( - // id, - // fun - // | Some(Info.InfoExp(exp)) => - // Some(Info.InfoExp({...exp, ctx})) - // | _ as info => info, - // m, - // ), - // m, - // ); - switch (element) { - | Some({term: TupLabel(_, typ), _}) - | Some(typ) => - let (body, m) = - go'( - ~ctx=[ - VarEntry({ - name, - id: List.nth(e2.ids, 0), - typ: Unknown(Internal) |> Typ.temp, - }), - ], - ~mode, - e2, - m, - ); - add(~self=Just(typ), ~co_ctx=body.co_ctx, m); - | None => + switch (ty.term) { + | Prod(ts) => + switch (e2.term) { + | Var(name) => + let element: option(Typ.t) = + LabeledTuple.find_label(Typ.get_label, ts, name); + // let m = + // e2.ids + // |> List.fold_left( + // (m, id) => + // Id.Map.update( + // id, + // fun + // | Some(Info.InfoExp(exp)) => + // Some(Info.InfoExp({...exp, ctx})) + // | _ as info => info, + // m, + // ), + // m, + // ); + switch (element) { + | Some({term: TupLabel(_, typ), _}) + | Some(typ) => + let (body, m) = + go'( + ~ctx=[ + VarEntry({ + name, + id: List.nth(e2.ids, 0), + typ: Unknown(Internal) |> Typ.temp, + }), + ], + ~mode, + e2, + m, + ); + add(~self=Just(typ), ~co_ctx=body.co_ctx, m); + | None => + let (body, m) = go'(~ctx=[], ~mode, e2, m); + add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); + }; + | _ => let (body, m) = go'(~ctx=[], ~mode, e2, m); add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); - }; + } | _ => let (body, m) = go'(~ctx=[], ~mode, e2, m); add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); - } - | _ => - let (body, m) = go'(~ctx=[], ~mode, e2, m); - add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); - }; - | Test(e) => - let (e, m) = go(~mode=Ana(Bool |> Typ.temp), e, m); - add(~self=Just(Prod([]) |> Typ.temp), ~co_ctx=e.co_ctx, m); - | Filter(Filter({pat: cond, _}), body) => - let (cond, m) = go(~mode=Syn, cond, m, ~is_in_filter=true); - let (body, m) = go(~mode, body, m); - add( - ~self=Just(body.ty), - ~co_ctx=CoCtx.union([cond.co_ctx, body.co_ctx]), - m, - ); - | Filter(Residue(_), body) => - let (body, m) = go(~mode, body, m); - add(~self=Just(body.ty), ~co_ctx=CoCtx.union([body.co_ctx]), m); - | Seq(e1, e2) => - 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) => - 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(ctx, fn.ty); - // In case of singleton tuple for fun ty_in, implicitly convert arg if necessary - // TODO: Is needed for TypAp or Deferred Ap? - let arg = - switch (arg.term, Typ.weak_head_normalize(ctx, ty_in).term) { - | (Tuple(es), Prod(ts)) => - let es' = - LabeledTuple.rearrange( - Typ.get_label, Exp.get_label, ts, es, (name, e) => - TupLabel(Label(name) |> Exp.fresh, e) |> Exp.fresh - ); - let arg: Exp.t = { - term: Exp.Tuple(es'), - ids: arg.ids, - copied: arg.copied, - }; - arg; - | (TupLabel(_), Prod([{term: TupLabel(_), _}])) => - Tuple([arg]) |> Exp.fresh - | (_, Prod([{term: TupLabel({term: Label(name), _}, _), _}])) => - Tuple([TupLabel(Label(name) |> Exp.fresh, arg) |> Exp.fresh]) - |> Exp.fresh - | (_, _) => arg }; - let (arg, m) = go(~mode=Ana(ty_in), arg, m); - let self: Self.t = - Id.is_nullary_ap_flag(arg.term.ids) - && !Typ.is_consistent(ctx, ty_in, Prod([]) |> Typ.temp) - ? BadTrivAp(ty_in) : Just(ty_out); - add(~self, ~co_ctx=CoCtx.union([fn.co_ctx, arg.co_ctx]), m); - | TypAp(fn, utyp) => - let typfn_mode = Mode.typap_mode; - let (fn, m) = go(~mode=typfn_mode, fn, m); - let (_, m) = utyp_to_info_map(~ctx, ~ancestors, utyp, m); - let (option_name, ty_body) = Typ.matched_forall(ctx, fn.ty); - switch (option_name) { - | Some(name) => - add(~self=Just(Typ.subst(utyp, name, ty_body)), ~co_ctx=fn.co_ctx, m) - | None => add(~self=Just(ty_body), ~co_ctx=fn.co_ctx, m) /* invalid name matches with no free type variables. */ - }; - | DeferredAp(fn, args) => - 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(ctx, fn.ty); - let num_args = List.length(args); - let ty_ins = Typ.matched_args(ctx, num_args, ty_in); - let self: Self.exp = Self.of_deferred_ap(args, ty_ins, ty_out); - let modes = Mode.of_deferred_ap_args(num_args, ty_ins); - let (args, m) = map_m_go(m, modes, args); - let arg_co_ctx = CoCtx.union(List.map(Info.exp_co_ctx, args)); - add'(~self, ~co_ctx=CoCtx.union([fn.co_ctx, arg_co_ctx]), m); - | Fun(p, e, _, _) => - let (mode_pat, mode_body) = Mode.of_arrow(ctx, mode); - let (p', _) = - go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, ~mode=mode_pat, p, m); - let (e, m) = go'(~ctx=p'.ctx, ~mode=mode_body, e, m); - /* add co_ctx to pattern */ - let (p'', m) = - go_pat(~is_synswitch=false, ~co_ctx=e.co_ctx, ~mode=mode_pat, p, m); - // TODO: factor out code - let unwrapped_self: Self.exp = - Common(Just(Arrow(p''.ty, e.ty) |> Typ.temp)); - 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); - | TypFun({term: Var(name), _} as utpat, body, _) - when !Ctx.shadows_typ(ctx, name) => - let mode_body = Mode.of_forall(ctx, Some(name), mode); - let m = utpat_to_info_map(~ctx, ~ancestors, utpat, m) |> snd; - let ctx_body = - Ctx.extend_tvar(ctx, {name, id: TPat.rep_id(utpat), kind: Abstract}); - let (body, m) = go'(~ctx=ctx_body, ~mode=mode_body, body, m); - add( - ~self=Just(Forall(utpat, body.ty) |> Typ.temp), - ~co_ctx=body.co_ctx, - m, - ); - | TypFun(utpat, body, _) => - let mode_body = Mode.of_forall(ctx, None, mode); - let m = utpat_to_info_map(~ctx, ~ancestors, utpat, m) |> snd; - let (body, m) = go(~mode=mode_body, body, m); - add( - ~self=Just(Forall(utpat, body.ty) |> Typ.temp), - ~co_ctx=body.co_ctx, - m, - ); - | Let(p, def, body) => - let (p_syn, _) = - go_pat(~is_synswitch=true, ~co_ctx=CoCtx.empty, ~mode=Syn, p, m); - let (def, p_ana_ctx, m, ty_p_ana) = - if (!is_recursive(ctx, p, def, p_syn.ty)) { - let (def, m) = go(~mode=Ana(p_syn.ty), def, m); - let ty_p_ana = def.ty; - let (p_ana', _) = - go_pat( - ~is_synswitch=false, - ~co_ctx=CoCtx.empty, - ~mode=Ana(ty_p_ana), - p, - m, - ); - (def, p_ana'.ctx, m, ty_p_ana); - } else { - let (def_base, _) = - go'(~ctx=p_syn.ctx, ~mode=Ana(p_syn.ty), def, m); - let ty_p_ana = def_base.ty; - /* Analyze pattern to incorporate def type into ctx */ - let (p_ana', _) = - go_pat( - ~is_synswitch=false, - ~co_ctx=CoCtx.empty, - ~mode=Ana(ty_p_ana), - p, - m, - ); - let def_ctx = p_ana'.ctx; - let (def_base2, _) = go'(~ctx=def_ctx, ~mode=Ana(p_syn.ty), def, m); - let ana_ty_fn = ((ty_fn1, ty_fn2), ty_p) => { - Typ.term_of(ty_p) == Typ.Unknown(SynSwitch) - && !Typ.eq(ty_fn1, ty_fn2) - ? ty_fn1 : ty_p; - }; - let ana = - switch ( - (def_base.ty |> Typ.term_of, def_base2.ty |> Typ.term_of), - p_syn.ty |> Typ.term_of, - ) { - | ((Prod(ty_fns1), Prod(ty_fns2)), Prod(ty_ps)) => - let tys = - List.map2(ana_ty_fn, List.combine(ty_fns1, ty_fns2), ty_ps); - Typ.Prod(tys) |> Typ.temp; - | ((_, _), _) => ana_ty_fn((def_base.ty, def_base2.ty), p_syn.ty) + | Test(e) => + let (e, m) = go(~mode=Ana(Bool |> Typ.temp), e, m); + add(~self=Just(Prod([]) |> Typ.temp), ~co_ctx=e.co_ctx, m); + | Filter(Filter({pat: cond, _}), body) => + let (cond, m) = go(~mode=Syn, cond, m, ~is_in_filter=true); + let (body, m) = go(~mode, body, m); + add( + ~self=Just(body.ty), + ~co_ctx=CoCtx.union([cond.co_ctx, body.co_ctx]), + m, + ); + | Filter(Residue(_), body) => + let (body, m) = go(~mode, body, m); + add(~self=Just(body.ty), ~co_ctx=CoCtx.union([body.co_ctx]), m); + | Seq(e1, e2) => + 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) => + 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(ctx, fn.ty); + // In case of singleton tuple for fun ty_in, implicitly convert arg if necessary + // TODO: Is needed for TypAp or Deferred Ap? + let arg = + switch (arg.term, Typ.weak_head_normalize(ctx, ty_in).term) { + | (Tuple(es), Prod(ts)) => + let es' = + LabeledTuple.rearrange( + Typ.get_label, Exp.get_label, ts, es, (name, e) => + TupLabel(Label(name) |> Exp.fresh, e) |> Exp.fresh + ); + let arg: Exp.t = { + term: Exp.Tuple(es'), + ids: arg.ids, + copied: arg.copied, }; - let (def, m) = go'(~ctx=def_ctx, ~mode=Ana(ana), def, m); - (def, def_ctx, m, ty_p_ana); + arg; + | (TupLabel(_), Prod([{term: TupLabel(_), _}])) => + Tuple([arg]) |> Exp.fresh + | (_, Prod([{term: TupLabel({term: Label(name), _}, _), _}])) => + Tuple([TupLabel(Label(name) |> Exp.fresh, arg) |> Exp.fresh]) + |> Exp.fresh + | (_, _) => arg + }; + let (arg, m) = go(~mode=Ana(ty_in), arg, m); + let self: Self.t = + Id.is_nullary_ap_flag(arg.term.ids) + && !Typ.is_consistent(ctx, ty_in, Prod([]) |> Typ.temp) + ? BadTrivAp(ty_in) : Just(ty_out); + add(~self, ~co_ctx=CoCtx.union([fn.co_ctx, arg.co_ctx]), m); + | TypAp(fn, utyp) => + let typfn_mode = Mode.typap_mode; + let (fn, m) = go(~mode=typfn_mode, fn, m); + let (_, m) = utyp_to_info_map(~ctx, ~ancestors, utyp, m); + let (option_name, ty_body) = Typ.matched_forall(ctx, fn.ty); + switch (option_name) { + | Some(name) => + add( + ~self=Just(Typ.subst(utyp, name, ty_body)), + ~co_ctx=fn.co_ctx, + m, + ) + | None => add(~self=Just(ty_body), ~co_ctx=fn.co_ctx, m) /* invalid name matches with no free type variables. */ }; - let (body, m) = go'(~ctx=p_ana_ctx, ~mode, body, m); - /* add co_ctx to pattern */ - let (p_ana, m) = - go_pat( - ~is_synswitch=false, + | DeferredAp(fn, args) => + 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(ctx, fn.ty); + let num_args = List.length(args); + let ty_ins = Typ.matched_args(ctx, num_args, ty_in); + let self: Self.exp = Self.of_deferred_ap(args, ty_ins, ty_out); + let modes = Mode.of_deferred_ap_args(num_args, ty_ins); + let (args, m) = map_m_go(m, modes, args); + let arg_co_ctx = CoCtx.union(List.map(Info.exp_co_ctx, args)); + add'(~self, ~co_ctx=CoCtx.union([fn.co_ctx, arg_co_ctx]), m); + | Fun(p, e, _, _) => + let (mode_pat, mode_body) = Mode.of_arrow(ctx, mode); + let (p', _) = + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=mode_pat, + p, + m, + ); + let (e, m) = go'(~ctx=p'.ctx, ~mode=mode_body, e, m); + /* add co_ctx to pattern */ + let (p'', m) = + go_pat(~is_synswitch=false, ~co_ctx=e.co_ctx, ~mode=mode_pat, p, m); + // TODO: factor out code + let unwrapped_self: Self.exp = + Common(Just(Arrow(p''.ty, e.ty) |> Typ.temp)); + 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); + | TypFun({term: Var(name), _} as utpat, body, _) + when !Ctx.shadows_typ(ctx, name) => + let mode_body = Mode.of_forall(ctx, Some(name), mode); + let m = utpat_to_info_map(~ctx, ~ancestors, utpat, m) |> snd; + let ctx_body = + Ctx.extend_tvar( + ctx, + {name, id: TPat.rep_id(utpat), kind: Abstract}, + ); + let (body, m) = go'(~ctx=ctx_body, ~mode=mode_body, body, m); + add( + ~self=Just(Forall(utpat, body.ty) |> Typ.temp), ~co_ctx=body.co_ctx, - ~mode=Ana(ty_p_ana), - p, m, ); - // 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, - ); - | FixF(p, e, _) => - let (p', _) = - go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, ~mode, p, m); - let (e', m) = go'(~ctx=p'.ctx, ~mode=Ana(p'.ty), e, m); - let (p'', m) = - go_pat(~is_synswitch=false, ~co_ctx=e'.co_ctx, ~mode, p, m); - add( - ~self=Just(p'.ty), - ~co_ctx=CoCtx.union([CoCtx.mk(ctx, p''.ctx, e'.co_ctx)]), - m, - ); - | If(e0, e1, e2) => - let branch_ids = List.map(UExp.rep_id, [e1, e2]); - let (cond, m) = go(~mode=Ana(Bool |> Typ.temp), e0, m); - let (cons, m) = go(~mode, e1, m); - let (alt, m) = go(~mode, e2, m); - add( - ~self=Self.match(ctx, [cons.ty, alt.ty], branch_ids), - ~co_ctx=CoCtx.union([cond.co_ctx, cons.co_ctx, alt.co_ctx]), - m, - ); - | 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 (ps', _) = - map_m( + | TypFun(utpat, body, _) => + let mode_body = Mode.of_forall(ctx, None, mode); + let m = utpat_to_info_map(~ctx, ~ancestors, utpat, m) |> snd; + let (body, m) = go(~mode=mode_body, body, m); + add( + ~self=Just(Forall(utpat, body.ty) |> Typ.temp), + ~co_ctx=body.co_ctx, + m, + ); + | Let(p, def, body) => + let (p_syn, _) = + go_pat(~is_synswitch=true, ~co_ctx=CoCtx.empty, ~mode=Syn, p, m); + let (def, p_ana_ctx, m, ty_p_ana) = + if (!is_recursive(ctx, p, def, p_syn.ty)) { + let (def, m) = go(~mode=Ana(p_syn.ty), def, m); + let ty_p_ana = def.ty; + let (p_ana', _) = + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=Ana(ty_p_ana), + p, + m, + ); + (def, p_ana'.ctx, m, ty_p_ana); + } else { + let (def_base, _) = + go'(~ctx=p_syn.ctx, ~mode=Ana(p_syn.ty), def, m); + let ty_p_ana = def_base.ty; + /* Analyze pattern to incorporate def type into ctx */ + let (p_ana', _) = + go_pat( + ~is_synswitch=false, + ~co_ctx=CoCtx.empty, + ~mode=Ana(ty_p_ana), + p, + m, + ); + let def_ctx = p_ana'.ctx; + let (def_base2, _) = + go'(~ctx=def_ctx, ~mode=Ana(p_syn.ty), def, m); + let ana_ty_fn = ((ty_fn1, ty_fn2), ty_p) => { + Typ.term_of(ty_p) == Typ.Unknown(SynSwitch) + && !Typ.eq(ty_fn1, ty_fn2) + ? ty_fn1 : ty_p; + }; + let ana = + switch ( + (def_base.ty |> Typ.term_of, def_base2.ty |> Typ.term_of), + p_syn.ty |> Typ.term_of, + ) { + | ((Prod(ty_fns1), Prod(ty_fns2)), Prod(ty_ps)) => + let tys = + List.map2(ana_ty_fn, List.combine(ty_fns1, ty_fns2), ty_ps); + Typ.Prod(tys) |> Typ.temp; + | ((_, _), _) => + ana_ty_fn((def_base.ty, def_base2.ty), p_syn.ty) + }; + let (def, m) = go'(~ctx=def_ctx, ~mode=Ana(ana), def, m); + (def, def_ctx, m, ty_p_ana); + }; + let (body, m) = go'(~ctx=p_ana_ctx, ~mode, body, m); + /* add co_ctx to pattern */ + let (p_ana, m) = go_pat( ~is_synswitch=false, - ~co_ctx=CoCtx.empty, - ~mode=Mode.Ana(scrut.ty), - ), - ps, + ~co_ctx=body.co_ctx, + ~mode=Ana(ty_p_ana), + p, + m, + ); + // 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, ); - 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, + | FixF(p, e, _) => + let (p', _) = + go_pat(~is_synswitch=false, ~co_ctx=CoCtx.empty, ~mode, p, m); + let (e', m) = go'(~ctx=p'.ctx, ~mode=Ana(p'.ty), e, m); + let (p'', m) = + go_pat(~is_synswitch=false, ~co_ctx=e'.co_ctx, ~mode, p, m); + add( + ~self=Just(p'.ty), + ~co_ctx=CoCtx.union([CoCtx.mk(ctx, p''.ctx, e'.co_ctx)]), + 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)); - let unwrapped_self: Self.exp = - Common(Self.match(ctx, e_tys, branch_ids)); - let constraint_ty = - switch (scrut.ty.term) { - | 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) |> Typ.temp, ctx) - | _ => Some(scrut.ty) - }; - let (self, m) = - switch (constraint_ty) { - | Some(constraint_ty) => - let pats_to_info_map = (ps: list(UPat.t), m) => { + | If(e0, e1, e2) => + let branch_ids = List.map(UExp.rep_id, [e1, e2]); + let (cond, m) = go(~mode=Ana(Bool |> Typ.temp), e0, m); + let (cons, m) = go(~mode, e1, m); + let (alt, m) = go(~mode, e2, m); + add( + ~self=Self.match(ctx, [cons.ty, alt.ty], branch_ids), + ~co_ctx=CoCtx.union([cond.co_ctx, cons.co_ctx, alt.co_ctx]), + m, + ); + | 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 (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)); + let unwrapped_self: Self.exp = + Common(Self.match(ctx, e_tys, branch_ids)); + let constraint_ty = + switch (scrut.ty.term) { + | 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) |> Typ.temp, ctx) + | _ => Some(scrut.ty) + }; + let (self, m) = + switch (constraint_ty) { + | Some(constraint_ty) => + let pats_to_info_map = (ps: list(UPat.t), m) => { + /* Add co-ctxs to patterns */ + 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, + ~prev_synswitch=None, + ~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 (m, final_constraint) = pats_to_info_map(ps, m); + let is_exhaustive = Incon.is_exhaustive(final_constraint); + let self = + is_exhaustive + ? unwrapped_self : InexhaustiveMatch(unwrapped_self); + (self, m); + | None => /* Add co-ctxs to patterns */ - 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) = + let (_, m) = + map_m( + ((p, co_ctx)) => 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, - ~prev_synswitch=None, - ~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), - ); + ), + List.combine(ps, e_co_ctxs), + m, + ); + (unwrapped_self, m); }; - let (m, final_constraint) = pats_to_info_map(ps, m); - let is_exhaustive = Incon.is_exhaustive(final_constraint); - let self = - is_exhaustive ? unwrapped_self : InexhaustiveMatch(unwrapped_self); - (self, m); - | None => - /* 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, - ); - (unwrapped_self, 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) { - | 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 would be obliterated. 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) = { - switch (utyp.term) { - | Sum(_) when List.mem(name, Typ.free_vars(utyp)) => - /* NOTE: When debugging type system issues it may be beneficial to - use a different name than the alias for the recursive parameter */ - //let ty_rec = Typ.Rec("α", Typ.subst(Var("α"), name, ty_pre)); - let ty_rec = - Typ.Rec(TPat.Var(name) |> IdTagged.fresh, utyp) |> Typ.temp; - let ctx_def = - Ctx.extend_alias(ctx, name, TPat.rep_id(typat), ty_rec); - (ty_rec, ctx_def, ctx_def); - | _ => ( - utyp, - ctx, - Ctx.extend_alias(ctx, name, TPat.rep_id(typat), utyp), - ) - /* NOTE(yuchen): Below is an alternative implementation that attempts to - add a rec whenever type alias is present. It may cause trouble to the - runtime, so precede with caution. */ - // Typ.lookup_surface(ty_pre) - // ? { - // let ty_rec = Typ.Rec({item: ty_pre, name}); - // let ctx_def = Ctx.add_alias(ctx, name, utpat_id(typat), ty_rec); - // (ty_rec, ctx_def, ctx_def); - // } - // : { - // let ty = Term.UTyp.to_typ(ctx, utyp); - // (ty, ctx, Ctx.add_alias(ctx, name, utpat_id(typat), ty)); - // }; + 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) { + | 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 would be obliterated. 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) = { + switch (utyp.term) { + | Sum(_) when List.mem(name, Typ.free_vars(utyp)) => + /* NOTE: When debugging type system issues it may be beneficial to + use a different name than the alias for the recursive parameter */ + //let ty_rec = Typ.Rec("α", Typ.subst(Var("α"), name, ty_pre)); + let ty_rec = + Typ.Rec(TPat.Var(name) |> IdTagged.fresh, utyp) |> Typ.temp; + let ctx_def = + Ctx.extend_alias(ctx, name, TPat.rep_id(typat), ty_rec); + (ty_rec, ctx_def, ctx_def); + | _ => ( + utyp, + ctx, + Ctx.extend_alias(ctx, name, TPat.rep_id(typat), utyp), + ) + /* NOTE(yuchen): Below is an alternative implementation that attempts to + add a rec whenever type alias is present. It may cause trouble to the + runtime, so precede with caution. */ + // Typ.lookup_surface(ty_pre) + // ? { + // let ty_rec = Typ.Rec({item: ty_pre, name}); + // let ctx_def = Ctx.add_alias(ctx, name, utpat_id(typat), ty_rec); + // (ty_rec, ctx_def, ctx_def); + // } + // : { + // let ty = Term.UTyp.to_typ(ctx, utyp); + // (ty, ctx, Ctx.add_alias(ctx, name, utpat_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 ({co_ctx, ty: ty_body, _}: Info.exp, m) = + go'(~ctx=ctx_body, ~mode, body, m); + /* Make sure types don't escape their scope */ + let ty_escape = Typ.subst(ty_def, typat, 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 ({co_ctx, ty: ty_body, _}: Info.exp, 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); }; - 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 ({co_ctx, ty: ty_body, _}: Info.exp, m) = - go'(~ctx=ctx_body, ~mode, body, m); - /* Make sure types don't escape their scope */ - let ty_escape = Typ.subst(ty_def, typat, 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 ({co_ctx, ty: ty_body, _}: Info.exp, 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); }; + + // This is to allow lifting single values into a singleton labeled tuple when the label is not present + // TODO Think about this real hard + + switch (mode) { + | Ana(ty) => + switch (Typ.weak_head_normalize(ctx, ty).term) { + | Prod([{term: TupLabel({term: Label(l1), _}, _), _}]) => + let (e, m) = go(~mode=Mode.Syn, uexp, m); + + switch (Typ.weak_head_normalize(e.ctx, e.ty).term) { + | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) when l1 == l2 => + default_case() + | _ => + uexp_to_info_map( + ~ctx, + ~mode=Mode.Ana(ty), + ~is_in_filter, + ~ancestors, + Tuple([TupLabel(Label(l1) |> Exp.fresh, uexp) |> Exp.fresh]) + |> Exp.fresh, + m, + ) + }; + | _ => default_case() + } + | _ => default_case() }; } and upat_to_info_map = From c87048d63afe87818c4cf070b0c0eb097671ad9d Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 14 Oct 2024 16:54:35 -0400 Subject: [PATCH 073/108] Remove singleton product from type view --- src/haz3lweb/view/Type.re | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/haz3lweb/view/Type.re b/src/haz3lweb/view/Type.re index 2ca7552a76..bc9075f701 100644 --- a/src/haz3lweb/view/Type.re +++ b/src/haz3lweb/view/Type.re @@ -59,8 +59,6 @@ let rec view_ty = (~strip_outer_parens=false, ty: Haz3lcore.Typ.t): Node.t => paren_view(t1) @ [text(" -> "), view_ty(t2)], ) | Prod([]) => div(~attrs=[clss(["typ-view", "Prod"])], [text("()")]) - | Prod([_]) => - div(~attrs=[clss(["typ-view", "Prod"])], [text("Singleton Product")]) | Prod([t0, ...ts]) => div( ~attrs=[clss(["typ-view", "atom", "Prod"])], From 01f84c5454505c1b3ab90a13fe9b1e8351595f1f Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Tue, 15 Oct 2024 10:29:09 -0400 Subject: [PATCH 074/108] Fix the duplicate singleton label statics --- src/haz3lcore/statics/Statics.re | 15 +++++-- test/Test_Statics.re | 67 ++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index f65d7a30c9..49c71059f1 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -817,10 +817,19 @@ and uexp_to_info_map = switch (mode) { | Ana(ty) => switch (Typ.weak_head_normalize(ctx, ty).term) { - | Prod([{term: TupLabel({term: Label(l1), _}, _), _}]) => + | Prod([{term: TupLabel({term: Label(l1), _}, ana_ty), _}]) => let (e, m) = go(~mode=Mode.Syn, uexp, m); - - switch (Typ.weak_head_normalize(e.ctx, e.ty).term) { + switch (Typ.weak_head_normalize(ctx, e.ty).term) { + | _ when Typ.is_consistent(ctx, ana_ty, e.ty) => + uexp_to_info_map( + ~ctx, + ~mode=Mode.Ana(ty), + ~is_in_filter, + ~ancestors, + Tuple([TupLabel(Label(l1) |> Exp.fresh, uexp) |> Exp.fresh]) + |> Exp.fresh, + m, + ) | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) when l1 == l2 => default_case() | _ => diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 79720aa6e5..88539779a8 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -517,4 +517,71 @@ let tests = ) |> Exp.fresh, ), + fully_consistent_typecheck( + "Duplicate singleton labels", + {|let x : (l=Int) = 1 in + let y : (l=(l=Int)) = x in y|}, + Some( + Prod([ + TupLabel( + Label("l") |> Typ.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ), + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Int(1) |> Exp.fresh, + Let( + Cast( + Var("y") |> Pat.fresh, + Parens( + Prod([ + TupLabel( + Label("l") |> Typ.fresh, + Parens( + Prod([ + TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + Var("x") |> Exp.fresh, + Var("y") |> Exp.fresh, + ) + |> Exp.fresh, + ) + |> Exp.fresh, + ), ]; From e0181262bda78da0ede044dd2412fcf55ff35ac3 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Tue, 15 Oct 2024 11:36:47 -0400 Subject: [PATCH 075/108] Fix stack overflow --- src/haz3lcore/statics/Statics.re | 62 +++++++++++++++++++++++--------- test/Test_Statics.re | 26 ++++++++++++++ 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 49c71059f1..778c573a3e 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -819,29 +819,59 @@ and uexp_to_info_map = switch (Typ.weak_head_normalize(ctx, ty).term) { | Prod([{term: TupLabel({term: Label(l1), _}, ana_ty), _}]) => let (e, m) = go(~mode=Mode.Syn, uexp, m); + switch (Typ.weak_head_normalize(ctx, e.ty).term) { | _ when Typ.is_consistent(ctx, ana_ty, e.ty) => - uexp_to_info_map( - ~ctx, - ~mode=Mode.Ana(ty), - ~is_in_filter, - ~ancestors, + let (e, m) = + uexp_to_info_map( + ~ctx, + ~mode=Mode.Ana(ana_ty), + ~is_in_filter, + ~ancestors, + uexp, + m, + ); + let fake_uexp = Tuple([TupLabel(Label(l1) |> Exp.fresh, uexp) |> Exp.fresh]) - |> Exp.fresh, - m, - ) + |> Exp.fresh; + let info = + Info.derived_exp( + ~uexp=fake_uexp, + ~ctx, + ~mode, + ~ancestors, + ~self=Common(Just(ty)), + ~co_ctx=e.co_ctx, + ); + + (info, add_info(fake_uexp.ids, InfoExp(info), m)); | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) when l1 == l2 => default_case() | _ => - uexp_to_info_map( - ~ctx, - ~mode=Mode.Ana(ty), - ~is_in_filter, - ~ancestors, + // TODO Deduplicate + let (e, m) = + uexp_to_info_map( + ~ctx, + ~mode=Mode.Ana(ana_ty), + ~is_in_filter, + ~ancestors, + uexp, + m, + ); + let fake_uexp = Tuple([TupLabel(Label(l1) |> Exp.fresh, uexp) |> Exp.fresh]) - |> Exp.fresh, - m, - ) + |> Exp.fresh; + let info = + Info.derived_exp( + ~uexp=fake_uexp, + ~ctx, + ~mode, + ~ancestors, + ~self=Common(Just(ty)), + ~co_ctx=e.co_ctx, + ); + + (info, add_info(fake_uexp.ids, InfoExp(info), m)); }; | _ => default_case() } diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 88539779a8..f1c40871a1 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -584,4 +584,30 @@ let tests = ) |> Exp.fresh, ), + fully_consistent_typecheck( + "Reconstructed labeled tuple without values", + {|let x : (l=|}, + Some(Unknown(Internal) |> Typ.fresh), + Let( + Cast( + Var("x") |> Pat.fresh, + Parens( + Prod([ + TupLabel( + Label("l") |> Typ.fresh, + Unknown(Hole(EmptyHole)) |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Pat.fresh, + EmptyHole |> Exp.fresh, + EmptyHole |> Exp.fresh, + ) + |> Exp.fresh, + ), ]; From 11804a2d1417e7a5d7390f33fd42bcb5512ffa1a Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Tue, 15 Oct 2024 13:02:08 -0400 Subject: [PATCH 076/108] Fix warning in test statics --- test/Test_Statics.re | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index f1c40871a1..83049d46c5 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -54,7 +54,7 @@ let type_of = (~statics_map=?, f) => { ); }; -let inconsistent_typecheck = (name, serialized, expected, exp) => { +let inconsistent_typecheck = (name, _serialized, exp) => { test_case( name, `Quick, @@ -399,12 +399,6 @@ let tests = inconsistent_typecheck( "Singleton Labled Tuple ascription in let with wrong type should fail", "let x : (l=String) = 1 in x", - Some( - Prod([ - TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) |> Typ.fresh, - ]) - |> Typ.fresh, - ), Let( Cast( Var("x") |> Pat.fresh, From 523177e44a3188f7dafa4c6a3782490793fa85a1 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Tue, 15 Oct 2024 13:02:23 -0400 Subject: [PATCH 077/108] First attempt singleton labeled tuple elaboration --- src/haz3lcore/dynamics/Elaborator.re | 45 +++++++++++++++++++++------- test/Test_Elaboration.re | 34 ++++++--------------- 2 files changed, 44 insertions(+), 35 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 50b3d535d0..1e36af36b1 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -18,18 +18,42 @@ module ElaborationResult = { | DoesNotElaborate; }; -let fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { - Typ.eq(t1, t2) - ? d - : { - let d' = - DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) +let rec fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { + switch (t2.term) { + | Prod([{term: TupLabel({term: Label(l), _}, t), _}]) => + switch (t1.term) { + | Prod([{term: TupLabel({term: Label(l'), _}, t'), _}]) when l == l' => + Typ.eq(t1, t2) + ? d + : { + let d' = + DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) + |> DHExp.fresh + |> Casts.transition_multiple; + DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) + |> DHExp.fresh + |> Casts.transition_multiple; + } + | _ => + Tuple([ + TupLabel(Label(l) |> DHExp.fresh, fresh_cast(d, t1, t)) + |> DHExp.fresh, + ]) + |> DHExp.fresh + } + | _ => + Typ.eq(t1, t2) + ? d + : { + let d' = + DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) + |> DHExp.fresh + |> Casts.transition_multiple; + DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) |> DHExp.fresh |> Casts.transition_multiple; - DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) - |> DHExp.fresh - |> Casts.transition_multiple; - }; + } + }; }; let fresh_pat_cast = (p: DHPat.t, t1: Typ.t, t2: Typ.t): DHPat.t => { @@ -271,6 +295,7 @@ let rec elaborate = elaborate(m, uexp, in_container); let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); let (term, rewrap) = UExp.unwrap(uexp); + print_endline("elaborating " ++ UExp.show(uexp)); let dhexp = switch (term) { | Invalid(_) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index e5defe3850..8df14a4e6c 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -10,6 +10,8 @@ let id_at = x => x |> List.nth(ids); let mk_map = Statics.mk(CoreSettings.on, Builtins.ctx_init); let dhexp_of_uexp = u => Elaborator.elaborate(mk_map(u), u, false) |> fst; let alco_check = dhexp_typ |> Alcotest.check; +let parse_exp = (s: string) => + MakeTerm.from_zip_for_sem(Option.get(Printer.zipper_of_string(s))).term; let u1: Exp.t = {ids: [id_at(0)], term: Int(8), copied: false}; let single_integer = () => @@ -312,26 +314,7 @@ let singleton_labeled_tuple_elaborates_labels = () => Var("x") |> Exp.fresh, ) |> Exp.fresh, - dhexp_of_uexp( - Let( - Cast( - Var("x") |> Pat.fresh, - Parens( - Prod([ - TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) - |> Typ.fresh, - ]) - |> Typ.fresh, - ) - |> Typ.fresh, - Unknown(Internal) |> Typ.fresh, - ) - |> Pat.fresh, - Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Should we require parens around singleton tables to ascribe labels - Var("x") |> Exp.fresh, - ) - |> Exp.fresh, - ), + dhexp_of_uexp(parse_exp("let x : (l=String) = \"a\" in x")), ); /* Labeled Tuple Rearranging @@ -413,11 +396,12 @@ let elaboration_tests = [ ), test_case("Labeled tuple elaboration", `Quick, elaborated_labeled_tuple), test_case("Rearranged labeled tuple", `Quick, rearranged_labeled_tuple), - // test_case( // TODO Not sure if we want this case - // "Singleton labeled tuple adds labels", - // `Quick, - // singleton_labeled_tuple_elaborates_labels, - // ), + test_case( + // TODO Not sure if we want this case + "Singleton labeled tuple adds labels", + `Quick, + singleton_labeled_tuple_elaborates_labels, + ), test_case("Singleton labeled tuple", `Quick, singleton_labeled_tuple), // TODO Make consistent with make term // TODO Add singleton labeled function application test_case("Singleton labeld tuple analysis adds label", `Quick, () => From c4db0d0c2eb7e2053f9b555e319b81eda19336ac Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 16 Oct 2024 09:15:32 -0400 Subject: [PATCH 078/108] Remove debug comment --- src/haz3lcore/dynamics/Elaborator.re | 1 - 1 file changed, 1 deletion(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 1e36af36b1..b64d171d27 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -295,7 +295,6 @@ let rec elaborate = elaborate(m, uexp, in_container); let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); let (term, rewrap) = UExp.unwrap(uexp); - print_endline("elaborating " ++ UExp.show(uexp)); let dhexp = switch (term) { | Invalid(_) From 03208ff7b50ab7378b4af097dee127c6b14b0e7f Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 16 Oct 2024 09:15:43 -0400 Subject: [PATCH 079/108] Fix test --- test/Test_Elaboration.re | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 8df14a4e6c..e4194e9d85 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -183,6 +183,7 @@ let deferral = () => alco_check( "string_sub(\"hello\", 1, _)", dhexp_of_uexp( + // This test seems broken DeferredAp( Var("string_sub") |> Exp.fresh, [ @@ -408,20 +409,12 @@ let elaboration_tests = [ alco_check( "Singleton labeld tuple analysis adds label", Let( - Cast( - Var("x") |> Pat.fresh, - Parens( - Prod([ - TupLabel(Label("l") |> Typ.fresh, String |> Typ.fresh) - |> Typ.fresh, - ]) - |> Typ.fresh, - ) - |> Typ.fresh, - Unknown(Internal) |> Typ.fresh, - ) - |> Pat.fresh, - Parens(Tuple([String("a") |> Exp.fresh]) |> Exp.fresh) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Var("x") |> Pat.fresh, + Tuple([ + TupLabel(Label("l") |> Exp.fresh, String("a") |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, Var("x") |> Exp.fresh, ) |> Exp.fresh, @@ -440,7 +433,7 @@ let elaboration_tests = [ Unknown(Internal) |> Typ.fresh, ) |> Pat.fresh, - Parens(String("a") |> Exp.fresh) |> Exp.fresh, // TODO Need to assert there's no inconsistency in this branch + Parens(String("a") |> Exp.fresh) |> Exp.fresh, Var("x") |> Exp.fresh, ) |> Exp.fresh, From 0f8521a6ddae2c2dbef5886cc2d90d21acadb714 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Wed, 16 Oct 2024 10:09:04 -0400 Subject: [PATCH 080/108] More singleton label elaborator fixes --- src/haz3lcore/dynamics/Elaborator.re | 25 +++++++++++++++--- test/Test_Elaboration.re | 39 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index b64d171d27..4a8f4359d9 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -22,7 +22,7 @@ let rec fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { switch (t2.term) { | Prod([{term: TupLabel({term: Label(l), _}, t), _}]) => switch (t1.term) { - | Prod([{term: TupLabel({term: Label(l'), _}, t'), _}]) when l == l' => + | Prod([{term: TupLabel({term: Label(l'), _}, _), _}]) when l == l' => Typ.eq(t1, t2) ? d : { @@ -42,6 +42,7 @@ let rec fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { |> DHExp.fresh } | _ => + // TODO Remove duplication in cases Typ.eq(t1, t2) ? d : { @@ -480,7 +481,15 @@ let rec elaborate = let def = add_name(Pat.get_var(p), def); let (def, ty2) = elaborate(m, def); let (body, ty) = elaborate(m, body); - Exp.Let(p, fresh_cast(def, ty2, ty1), body) + Exp.Let( + p, + fresh_cast( + def, + Typ.weak_head_normalize(ctx, ty2), + Typ.weak_head_normalize(ctx, ty1), + ), // TODO abanduk: Is it safe to normalize here? + body, + ) |> rewrap |> cast_from(ty); } else { @@ -489,7 +498,17 @@ let rec elaborate = let def = add_name(Option.map(s => s ++ "+", Pat.get_var(p)), def); let (def, ty2) = elaborate(m, def); let (body, ty) = elaborate(m, body); - let fixf = FixF(p, fresh_cast(def, ty2, ty1), None) |> DHExp.fresh; + let fixf = + FixF( + p, + fresh_cast( + def, + Typ.weak_head_normalize(ctx, ty2), + Typ.weak_head_normalize(ctx, ty1), + ), + None, + ) + |> DHExp.fresh; // TODO abanduk: Is it safe to normalize here? Exp.Let(p, fixf, body) |> rewrap |> cast_from(ty); }; | FixF(p, e, env) => diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index e4194e9d85..b492e8c15f 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -440,4 +440,43 @@ let elaboration_tests = [ ), ) ), + test_case( + "Singleton labeld tuple analysis adds label with type alias", `Quick, () => + alco_check( + {|type T = (a=String) in + let x : T = "hello" in x|}, + Let( + Var("x") |> Pat.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, String("hello") |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp( + parse_exp({|type T = (a=String) in let x : T = "hello" in x|}), + ), + ) + ), + test_case( + "Singleton labeld tuple analysis adds label with type alias", `Quick, () => + alco_check( + {|let zip_only : (zip=Int) = (zip=12345) in zip_only|}, + Let( + Var("zip_only") |> Pat.fresh, + Tuple([ + TupLabel(Label("zip") |> Exp.fresh, Int(12345) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("zip_only") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp( + parse_exp({|let zip_only : (zip=Int) = (zip=12345) in zip_only|}), + ), + ) + ), ]; From 1bee9bb63ff69d672f30de6101a63d109e048f48 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 18 Oct 2024 13:25:51 -0400 Subject: [PATCH 081/108] Update init --- src/haz3lweb/Init.ml | 485 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 460 insertions(+), 25 deletions(-) diff --git a/src/haz3lweb/Init.ml b/src/haz3lweb/Init.ml index e5e3defafe..5c3059642b 100644 --- a/src/haz3lweb/Init.ml +++ b/src/haz3lweb/Init.ml @@ -12189,26 +12189,26 @@ let startup : PersistentData.t = # Fold projectors cover terms with abstractions. #\n\ # 1. A simple fold roles up any term, replacing #\n\ # it with ... until it is expanded again. #\n\n\ - let fold = in\n\n\ + let fold = (((((((((((()))))))))))) in\n\n\ # 2. A semantic fold covers a term with a property: #\n\ # Click to toggle inferred & synthesized types #\n\n\ - let folds: = in\n\n\ + let folds: (Int -> Bool) = in\n\n\ # Projectors on literal data are called livelits. #\n\ # Three base types literals use inline views: #\n\n\ - let guard: Bool = in\n\ - let phase: Int = in\n\ - let float: Float = in\n\n\ + let guard: Bool = true in\n\ + let phase: Int = 44 in\n\ + let float: Float = 79.00 in\n\n\ # Inline error decorations (same as for tokens) #\n\n\ - let (a:Int, f: Float) = , in\n\n\ + let (a:Int, f: Float) = true, 28 in\n\n\ # The String base type get a multiline view: #\n\n\ - let _ = in\n\ - let __ = in\n\ - let ___ = in\n\ - let ____ = in\n\ - let _____ = in\n\ - let ______ = in\n\n\ + let _ = \"\" in\n\ + let __ = \"\\n\" in\n\ + let ___ = \"a\" in\n\ + let ____ = \"shift\\n\" in\n\ + let _____ = \"\\nmalicious\" in\n\ + let ______ = \"a\\n shift\\n malicious\" in\n\n\ # Multiline error decorations #\n\n\ - let box: Int = in\n\n\ + let box: Int = \"\\nmalicious\" in\n\n\ # ERRATA: #\n\ # The bottom toggle can also be used to remove #\n\ # projectors. Currently only bidelmited terms can #\n\ @@ -12217,7 +12217,7 @@ let startup : PersistentData.t = # currently are lost on cut/copy. Both these #\n\ # restrictions will be removed in a future update. #\n\n\ # Projectors playground #\n\n\ - if && < () \n\ + if true && 23 < int_of_float(51.00) \n\ then ______ else \"its: \" ++ box"; } ); ( "Types & static errors", @@ -17675,7 +17675,7 @@ let startup : PersistentData.t = ca0d2c33-96ef-44c6-ac6e-f8a4d7901280)(content(Whitespace\" \ \"))))(Secondary((id \ 98524bad-9684-472a-a0c8-b1204357df66)(content(Whitespace\"\\n\"))))(Secondary((id \ - 38404748-91f8-4ff9-bf3e-6079ab3a3add)(content(Whitespace\"\\n\")))))((Secondary((id \ + 38404748-91f8-4ff9-bf3e-6079ab3a3add)(content(Whitespace\"\\n\"))))(Secondary((id \ fbc19dd7-8fdb-4932-87af-5b52f6a093bb)(content(Comment\"# \ These can be encoded the types #\"))))(Secondary((id \ 312fb397-2960-419d-8012-b3844228b045)(content(Whitespace\"\\n\"))))(Tile((id \ @@ -17931,7 +17931,7 @@ let startup : PersistentData.t = Convex)(sort \ Typ))))))(shards(0))(children()))))))))(Secondary((id \ 0254047f-2d49-49da-a292-8ae1c8bd9315)(content(Whitespace\" \ - \")))))))))(Secondary((id \ + \"))))))))))((Secondary((id \ 30456699-1693-415d-a38e-b103a1d4f4ca)(content(Whitespace\"\\n\"))))(Secondary((id \ 4a35bd2e-ceac-4010-9b5e-b96baa3abef7)(content(Comment\"# \ These labels can be automatically applied based on the type \ @@ -18123,15 +18123,434 @@ let startup : PersistentData.t = 99c467af-0605-4a51-814b-6fe35edb5b59)(content(Whitespace\" \ \")))))))))(Secondary((id \ 1672c094-ce77-4a2c-a610-f352d9c00f7f)(content(Whitespace\"\\n\"))))(Secondary((id \ - 183b912f-dde9-4f06-8047-2b73d3e7ac89)(content(Whitespace\"\\n\"))))(Grout((id \ - 108cfcfd-2e17-407c-8380-ec1e63151450)(shape \ - Convex)))(Secondary((id \ - 867bbf01-916d-4d3e-9b99-1d4337659f57)(content(Whitespace\" \ + 183b912f-dde9-4f06-8047-2b73d3e7ac89)(content(Whitespace\"\\n\"))))(Secondary((id \ + 0bc5c1e3-46a7-4e8d-9cb6-6aadf34388ac)(content(Comment\"# As \ + Labeled Function Arguments#\"))))(Secondary((id \ + 5e62d069-586f-4b4a-bebd-1d85c911942e)(content(Whitespace\"\\n\"))))(Tile((id \ + 5fa063ff-949a-4aae-999a-41a6c69d6c56)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + fb4e903c-38ba-4ea6-8b32-317b1285f772)(content(Whitespace\" \ + \"))))(Tile((id \ + ec1af2af-1ed0-48ee-b453-7212541060db)(label(make_person))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + ccb12ba8-9f10-4b75-994e-5305f899a2f6)(content(Whitespace\" \ + \")))))((Secondary((id \ + cd12b638-f5e5-4404-9258-b52dcf650df7)(content(Whitespace\" \ + \"))))(Tile((id \ + 75548ddc-6a1b-40ba-9657-fd01f72ed587)(label(fun \ + ->))(mold((out Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 15))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id \ + b79f71ec-30f8-4195-9354-0438e6141369)(content(Whitespace\" \ + \"))))(Tile((id \ + 76c41ade-16f9-4118-8b93-19ee95712e29)(label(name))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 12499cf9-95f4-4b6c-b3e8-caeed4c8ac7f)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort \ + Pat))((shape(Concave 16))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 6a914505-51dc-4704-b3e6-c28c64ee2192)(label(name))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 2720ae7a-5bd6-4cce-b71d-d14996d9a6ae)(label(,))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 18))(sort \ + Pat))((shape(Concave 18))(sort \ + Pat))))))(shards(0))(children())))(Secondary((id \ + 592cf330-b2d5-4cab-876d-74ad562b281b)(content(Whitespace\" \ + \"))))(Tile((id \ + 9a3fa4ed-eb24-49e6-97b6-2060a725b792)(label(age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 83ea2c01-eaa9-41dc-b613-9f8b5f28bc2a)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort \ + Pat))((shape(Concave 16))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + 003dc40d-5777-4d85-826e-4bc2821ed79a)(label(age))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 20ddd665-117f-48fd-9d81-cfd0be30c3f6)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 468a44b1-08e5-4630-b83e-530908e27910)(content(Whitespace\" \ + \"))))(Tile((id \ + 87515d1a-6137-4329-adef-3447763bfeec)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 7e52e359-8f40-4fe8-a17e-5f3f7d2ac33e)(label(name))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 29619540-cc0d-4cc0-9981-c83c069dca20)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + c80ac6ac-d08a-4409-973e-5f3e18ba51b0)(content(Whitespace\" \ + \"))))(Tile((id \ + e02e1487-d3d4-4676-b336-162501ed79a6)(label(age))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 2039c996-dd01-4836-adeb-4e172e7a6fe9)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5e71d9fa-5efd-4e8e-9382-22a5ae2adfb4)(content(Whitespace\" \ + \"))))(Tile((id \ + a8d4584e-fbcb-43cf-b59f-48f6db174fd4)(label(favorite_color))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + a1fc6211-064f-456a-8db6-c8853f11f3a1)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 6ed737e9-6dfa-49f0-b3c0-0fb5e3586ca2)(label(\"\\\"red\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 3e83623e-f633-4186-a3b5-d8b9524a4a86)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + e8f3f82e-5611-4b88-863b-9a2ae9d1c21d)(content(Whitespace\"\\n\"))))(Tile((id \ + bf3c8af3-ae3a-48c6-93b4-04ac67772b08)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 619b044c-b0e4-4e02-b5db-d15570566791)(content(Whitespace\" \ + \"))))(Tile((id \ + f934d33c-4593-4026-8ec0-5ead64be5882)(label(inconsistent_function_arg))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 9e666317-40ce-4c94-91cc-ad967e7eb9c4)(content(Whitespace\" \ + \")))))((Secondary((id \ + 6e84d392-0a09-4e6b-b0c5-276e43ab0f4a)(content(Whitespace\" \ + \"))))(Tile((id \ + 6d4f698b-0886-4488-a1d9-559d1f453cd2)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + ab35f30b-6f45-48c8-839b-1ef89002c759)(label(\"\\\"Invalid\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 91e66749-d8b1-4e70-92d1-cd07b4bf0384)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 37c22349-8aa6-41c7-b125-c62afe63d0eb)(content(Whitespace\" \ + \"))))(Tile((id \ + 03cfd730-4fa8-4735-b189-b606425881af)(label(-))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape(Concave \ + 4))(sort Exp))))))(shards(0))(children())))(Tile((id \ + 12d2af65-b5c1-45f0-b3f9-6e4931addb73)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 0af9bc1c-fdfc-4a69-b7d6-27bd571dcfd8)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 71ab2007-0a3a-4c9e-a3ce-569eff4c9d0d)(content(Whitespace\"\\n\"))))(Tile((id \ + 6772cdf5-3409-4b9c-8637-a24516a5c967)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 9de2ec9f-c185-4c6d-a715-1a98df8558aa)(content(Whitespace\" \ + \"))))(Tile((id \ + 1bbb9c86-d902-4829-98d1-555dd346ef33)(label(consistent_function_arg))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + d400dbe1-4dc2-4df0-8996-86ae6b0f9c4c)(content(Whitespace\" \ + \")))))((Secondary((id \ + 16f13179-43e2-4bca-b532-62bb500c7855)(content(Whitespace\" \ + \"))))(Tile((id \ + 5142d9b7-f548-4acf-8901-2c6a902ab1eb)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 30f541b4-e181-44e2-887a-8db7636c3420)(label(name))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 622ecc74-32c1-4028-b39c-d8a61e1e204a)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 371d1add-d34b-4e00-b9ec-bda86d5c8009)(label(\"\\\"Valid\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 35d0418b-5000-42c5-8789-e69e0b8d602a)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + e04fa0dd-087b-439c-bbe3-0580927ee180)(content(Whitespace\" \ + \"))))(Tile((id \ + 27c6d19b-7e30-4502-823f-b766f0939ea4)(label(age))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 3311b98f-1230-4d42-a39c-2dd23582a839)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + cae073b2-d9e2-4e6e-bdb9-a6506415fe25)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + d12a2a58-1e0f-4924-b1c4-9260ab60fd8d)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + fae1053e-ed09-4559-ac80-c03838ddc7d8)(content(Whitespace\"\\n\"))))(Tile((id \ + 04747bb7-9e2f-4ebc-8ce0-7b198b5600ea)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + cf41c843-ee1e-462b-bf32-8d507355ca8f)(content(Whitespace\" \ + \"))))(Tile((id \ + 7c40a1e7-7010-494e-a909-8845d0c9326a)(label(more_people))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + fb482afa-0658-483f-9adf-70fd761b6290)(content(Whitespace\" \ + \"))))(Tile((id \ + 0c29ee28-0626-45b1-aac3-e4a78f11dcff)(label(:))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 13))(sort \ + Pat))((shape(Concave 13))(sort \ + Typ))))))(shards(0))(children())))(Secondary((id \ + 49e417e5-fe4b-453a-b01a-1d293bdb25ad)(content(Whitespace\" \ + \"))))(Tile((id 5a14afa0-4406-4d67-85d8-9cfa118caf38)(label([ \ + ]))(mold((out Typ)(in_(Typ))(nibs(((shape Convex)(sort \ + Typ))((shape Convex)(sort Typ))))))(shards(0 \ + 1))(children(((Tile((id \ + b93d434d-96ca-4604-847d-b0205aeb99ed)(label(Person))(mold((out \ + Typ)(in_())(nibs(((shape Convex)(sort Typ))((shape \ + Convex)(sort \ + Typ))))))(shards(0))(children()))))))))(Secondary((id \ + 5896c5a9-156b-46ca-8e72-30f57076188f)(content(Whitespace\" \ + \")))))((Secondary((id \ + 1ade8ad4-18e3-455c-9ec2-32d45710df5e)(content(Whitespace\" \ + \"))))(Tile((id 372c347d-d19d-4e90-a425-809765a77865)(label([ \ + ]))(mold((out Exp)(in_(Exp))(nibs(((shape Convex)(sort \ + Exp))((shape Convex)(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id \ + f383ce0c-2993-4d70-bd1e-071d4b8088a3)(content(Whitespace\"\\n\"))))(Tile((id \ + e2fc05f3-ccb2-4508-bb28-1df2197fcc07)(label(make_person))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + de83e03a-1b73-4386-9af3-b74e69527830)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 3))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + ca2fb28d-f718-4d00-a3a6-67f0b08fd3f4)(label(\"\\\"Bob\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + dbe464e2-a48d-421a-b32a-d555ecb3a6a3)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 5be01cd9-5138-4127-afad-6aa13115a9b0)(content(Whitespace\" \ + \"))))(Tile((id \ + 6cec742d-95b7-4cb2-9662-2761546bd130)(label(25))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children()))))))))(Tile((id \ + 86f01c66-3a10-4436-a265-ed32edc4110e)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 98be2652-07fc-4b72-8306-782c815b289e)(content(Whitespace\" \ + \"))))(Secondary((id \ + 3de82faf-6b7b-463c-996d-6c80e53ea84c)(content(Comment\"# \ + Labels Elided #\"))))(Secondary((id \ + f117280d-d441-4e2e-8838-9d60abeef621)(content(Whitespace\"\\n\"))))(Tile((id \ + 65e63a67-4573-4a72-8520-4f6c92520c85)(label(make_person))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 33c997e0-df65-4c1d-96cb-d80ef2677af5)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 3))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + b77a8e85-4ff3-413a-8a3e-a53b3724b247)(label(name))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 88107447-620c-4af0-a5ae-456a20ccc1c9)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + ab0c2887-7351-4627-b46d-a19631eed2bb)(label(\"\\\"Alice\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 3bfe6938-5e24-4b48-99a3-b9241d8801c5)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + 26d948f4-1b53-407f-82e7-ce22a2ef78ae)(label(age))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 614d4f6c-a75d-4a62-ac88-a1ea39d77474)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + b1f9b854-9e65-49c1-96e4-4d501e573920)(label(22))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children()))))))))(Tile((id \ + f7ea71cf-5d03-44ae-b4f7-efb79c1b0a80)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 23ccd115-dd96-415a-b141-18a2f9c2928c)(content(Whitespace\" \ + \"))))(Secondary((id \ + 4776654a-cdec-44cf-81c0-b8246aaba138)(content(Comment\"# \ + Labels Present #\"))))(Secondary((id \ + 0b72bd36-b3ed-4b5a-877d-39863dce9106)(content(Whitespace\"\\n\"))))(Tile((id \ + 1953b9bc-fe9d-4c1f-b000-a2bf7a9a53e4)(label(make_person))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 732bdb11-adfc-48bf-a140-1eb7cd7e6c9c)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 3))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1b0e2070-acec-473d-a277-c7672c903619)(label(age))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 01c9c18d-dbe1-4806-a8a6-65130c91a89a)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + b04bb7ea-7efd-453f-a197-4ab510dd0ecf)(label(23))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + df81e118-f9d0-4bc1-9019-be2b08b570bd)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + a0408131-c052-46c9-8416-c47aed162ded)(content(Whitespace\" \ + \"))))(Tile((id \ + a7730441-3dae-4dd8-9fbd-7b6f9a6041bf)(label(\"\\\"Mallory\\\"\"))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children()))))))))(Tile((id \ + f04e07bb-b99c-4d60-b21a-d14c84ea222b)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 82d777da-78dc-4090-8467-8fef0264b422)(content(Whitespace\" \ + \"))))(Secondary((id \ + 4468b1fa-3064-49f6-94ca-58e15e65db17)(content(Comment\"# \ + Labels Rearranging #\"))))(Secondary((id \ + 0a3e4609-541c-47ff-bf58-ee707e6fe045)(content(Whitespace\"\\n\"))))(Tile((id \ + 65153718-6c17-4581-9a16-00b9780bd520)(label(make_person))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 21b03f5b-15dc-49da-814b-0fce4ec86966)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 3))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + aa9bac65-bcdc-43b3-8afa-4c77a7981213)(label(inconsistent_function_arg))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children()))))))))(Tile((id \ + a8f6f87f-a708-401e-8151-bb9752e92503)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + 281dc9b8-8acf-4d09-b6c9-206958fd8761)(content(Whitespace\" \ + \"))))(Secondary((id \ + 6d84d30b-e4e5-49cc-ac1c-02ded4f46aba)(content(Comment\"# \ + Rearranging and label addition only happens for \ + literals#\"))))(Secondary((id \ + 7fd3a911-046b-4a06-a949-a753d4f06116)(content(Whitespace\"\\n\"))))(Tile((id \ + 61983531-9deb-4439-b41d-be9ec0ffce1a)(label(make_person))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 373f7dbf-5e4c-4f95-907a-d27240ba731b)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 3))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5cde39ac-556b-4891-9983-774d9c28bf97)(label(consistent_function_arg))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + 0efb970f-68ad-4381-81c3-9fc505b74e25)(content(Whitespace\" \ + \"))))(Secondary((id \ + 2c336ab6-7ae3-45ca-9878-92ae35539fd3)(content(Comment\"# \ + Unlabeled Tuple won't be allowed#\"))))(Secondary((id \ + 5213fdf4-7566-4b50-952b-69ed2727c40a)(content(Whitespace\"\\n\")))))))))(Secondary((id \ + fae77a96-5f1b-495d-9287-f067c380eb4c)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 63c5cf47-23a5-4ad2-b4fd-70ec5cbc26e2)(content(Whitespace\" \ \"))))(Secondary((id \ - 0342f646-322c-4f68-98cf-de94b4df6e3d)(content(Whitespace\"\\n\"))))(Secondary((id \ - fa4a94d2-5955-4f8a-a958-6d8c8ebeaefb)(content(Whitespace\"\\n\"))))(Secondary((id \ - d6e2d5c6-1ac7-42ca-9894-0f26ea900668)(content(Whitespace\"\\n\")))))))(ancestors())))(caret(Inner \ - 33 13)))"; + 16bbdb76-de5c-483d-ac2a-f6e9e3da33a4)(content(Whitespace\"\\n\"))))(Secondary((id \ + f0beefad-82fb-45a3-946c-981902b26ec5)(content(Whitespace\"\\n\"))))(Secondary((id \ + ecbf23ce-4a66-4b2b-b3d2-157af8872f02)(content(Whitespace\"\\n\"))))(Tile((id \ + aaced2aa-2d0a-461d-976f-9dec83c795cd)(label(let = \ + in))(mold((out Exp)(in_(Pat Exp))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 18))(sort Exp))))))(shards(0 1 \ + 2))(children(((Secondary((id \ + 7d1e8e23-dcd9-4b1e-b822-5f842cb6bd44)(content(Whitespace\" \ + \"))))(Tile((id \ + 774d1844-2b95-4fcf-8ee8-878cf7c84151)(label(singleton_function))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 1a9c907e-f571-4d67-81ef-4ecc4851f548)(content(Whitespace\" \ + \")))))((Secondary((id \ + f4534e76-0158-416a-b61d-c2db539c772c)(content(Whitespace\" \ + \"))))(Tile((id \ + edd442bd-46fd-4794-bb9c-5af613263d68)(label(fun \ + ->))(mold((out Exp)(in_(Pat))(nibs(((shape Convex)(sort \ + Exp))((shape(Concave 15))(sort Exp))))))(shards(0 \ + 1))(children(((Secondary((id \ + 4386d151-96f7-4f04-9f11-64c7e6b993ad)(content(Whitespace\" \ + \"))))(Tile((id \ + 9cdc3202-4783-4f18-a28a-170cf9dcb31b)(label(arg))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Tile((id \ + 560eb91c-1ae0-4403-95be-acad1d929786)(label(=))(mold((out \ + Pat)(in_())(nibs(((shape(Concave 16))(sort \ + Pat))((shape(Concave 16))(sort \ + Pat))))))(shards(0))(children())))(Tile((id \ + d747f9b6-5a31-403b-9d2e-d020d7eab3ec)(label(a))(mold((out \ + Pat)(in_())(nibs(((shape Convex)(sort Pat))((shape \ + Convex)(sort Pat))))))(shards(0))(children())))(Secondary((id \ + 4a40c3d1-4a54-44a4-ba42-0adaf192746c)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 1c961485-84a2-4344-b8ac-80e5dfb502cb)(content(Whitespace\" \ + \"))))(Tile((id \ + 205b25cf-a5e3-425c-9543-14fa3236c695)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 1c0b9b7b-a060-4823-ae2d-f550638e0152)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + e3b044ee-b11c-4853-804f-3aaf9ae93f05)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Secondary((id \ + f4118116-399b-4d85-98e8-803013328598)(content(Whitespace\" \ + \"))))(Tile((id \ + ead750da-7f4a-485a-a026-a7a4453e2f46)(label(a))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))(Secondary((id \ + db57dda3-640d-4413-852c-d3425de4192e)(content(Whitespace\" \ + \")))))))))(Secondary((id \ + 2065f441-6fa2-4bcf-ac9b-033463ad1d03)(content(Whitespace\"\\n\"))))(Tile((id \ + 75c4ccaf-dfa7-43b0-8715-707079b8ba58)(label([ ]))(mold((out \ + Exp)(in_(Exp))(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + bb9f8ac1-4fbd-46f6-8526-85d4dcb25dea)(label(singleton_function))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 48931dc4-c220-4d0f-808c-2bd7972ff57e)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 3))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 87bc964a-591e-4db8-9be5-0df341bc50fb)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children()))))))))(Tile((id \ + 70479ac6-4712-4591-b99e-d0cd8377f170)(label(,))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 18))(sort \ + Exp))((shape(Concave 18))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + cea4761f-b845-4944-85c4-af502a792bc7)(label(singleton_function))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 209793a6-3fbc-4b27-81bd-b2800716af95)(label(\"(\"\")\"))(mold((out \ + Exp)(in_(Exp))(nibs(((shape(Concave 3))(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0 1))(children(((Tile((id \ + 5d711ea8-0d2d-4afc-a3d3-f6e00203ff15)(label(arg))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort Exp))))))(shards(0))(children())))(Tile((id \ + 9ba1426c-958a-4cfe-b6b1-e14766cabcae)(label(=))(mold((out \ + Exp)(in_())(nibs(((shape(Concave 16))(sort \ + Exp))((shape(Concave 16))(sort \ + Exp))))))(shards(0))(children())))(Tile((id \ + cbe7def1-4267-4549-b8e6-f622fd80f3ec)(label(1))(mold((out \ + Exp)(in_())(nibs(((shape Convex)(sort Exp))((shape \ + Convex)(sort \ + Exp))))))(shards(0))(children()))))))))))))))))(ancestors())))(caret \ + Outer))"; backup_text = "# Labeled Tuples #\n\n\ # Tuples can have labels#\n\ @@ -18154,7 +18573,22 @@ let startup : PersistentData.t = # Destructuring #\n\ let (bobs_name, age=bobs_age, \ favorite_color=bobs_favorite_color) = bob in\n\n\ - \ \n\n\n"; + # As Labeled Function Arguments#\n\ + let make_person = fun name=name, age=age -> (name, age, \ + favorite_color=\"red\") in\n\ + let inconsistent_function_arg = (\"Invalid\", -1) in\n\ + let consistent_function_arg = (name=\"Valid\", age=1) in\n\ + let more_people : [Person] = [\n\ + make_person(\"Bob\", 25), # Labels Elided #\n\ + make_person(name=\"Alice\",age=22), # Labels Present #\n\ + make_person(age=23, \"Mallory\"), # Labels Rearranging #\n\ + make_person(inconsistent_function_arg), # Rearranging and \ + label addition only happens for literals#\n\ + make_person(consistent_function_arg) # Unlabeled Tuple won't \ + be allowed#\n\ + ] in \n\n\n\ + let singleton_function = fun arg=a -> (a, a) in\n\ + [singleton_function(1),singleton_function(arg=1)]"; } ); ( "Expressive Programming", { @@ -18258,6 +18692,7 @@ let startup : PersistentData.t = ("scratch_Computing Equationally", Evaluation); ("scratch_Conditional Expressions", Evaluation); ("scratch_Functions", Evaluation); + ("scratch_Labeled Tuples", Evaluation); ("scratch_Polymorphism", Evaluation); ("scratch_Programming Expressively", Evaluation); ("scratch_Projectors", Evaluation); From e66dd8011bb12f3d021ef3f1d42a7c4255453808 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 18 Oct 2024 19:46:53 -0400 Subject: [PATCH 082/108] Add tests for singleton labeled argument function application --- test/Test_Elaboration.re | 87 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index b492e8c15f..b4cc5b4796 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -479,4 +479,91 @@ let elaboration_tests = [ ), ) ), + test_case( + "Singleton labeled argument function application with known type", + `Quick, + () => + alco_check( + {|(fun a=x->x)(a=1)|}, + Ap( + Forward, + Fun( + Tuple([ + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + |> Pat.fresh, + ]) + |> Pat.fresh, + Var("x") |> Exp.fresh, + None, + None, + ) + |> Exp.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(parse_exp({|(fun a=(x:Int) -> x)(a=1)|})), + ) + ), + test_case( + "Singleton labeled argument function application with no label in ap", + `Quick, + () => + alco_check( + {|(fun a=x->x)(a=1)|}, + Ap( + Forward, + Fun( + Tuple([ + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + |> Pat.fresh, + ]) + |> Pat.fresh, + Var("x") |> Exp.fresh, + None, + None, + ) + |> Exp.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(parse_exp({|(fun a=(x:Int) -> x)(1)|})), + ) + ), + test_case( + "Singleton labeled argument function application with unknown type", + `Quick, + () => + alco_check( + {|(fun a=x->x)(a=1)|}, + Ap( + Forward, + Fun( + Tuple([ + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + |> Pat.fresh, + ]) + |> Pat.fresh, + Var("x") |> Exp.fresh, + None, + None, + ) + |> Exp.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(parse_exp({|(fun a=x->x)(a=1)|})), + ) + ), ]; From b42c6130f0479f32ee882af40732a11ebb49db6e Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 21 Oct 2024 16:00:25 -0400 Subject: [PATCH 083/108] Progress on elaborating singleton tuples with mismatched labels --- src/haz3lcore/dynamics/Elaborator.re | 94 ++++++++-------- src/haz3lcore/statics/Statics.re | 28 +---- src/haz3lcore/statics/Term.re | 9 +- src/haz3lcore/statics/TermBase.re | 4 +- test/Test_Elaboration.re | 73 +++++++++++- test/Test_Statics.re | 159 +++++++++++++++------------ 6 files changed, 223 insertions(+), 144 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 4a8f4359d9..68a6a6693e 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -19,29 +19,8 @@ module ElaborationResult = { }; let rec fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { - switch (t2.term) { - | Prod([{term: TupLabel({term: Label(l), _}, t), _}]) => - switch (t1.term) { - | Prod([{term: TupLabel({term: Label(l'), _}, _), _}]) when l == l' => - Typ.eq(t1, t2) - ? d - : { - let d' = - DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) - |> DHExp.fresh - |> Casts.transition_multiple; - DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) - |> DHExp.fresh - |> Casts.transition_multiple; - } - | _ => - Tuple([ - TupLabel(Label(l) |> DHExp.fresh, fresh_cast(d, t1, t)) - |> DHExp.fresh, - ]) - |> DHExp.fresh - } - | _ => + switch (t1.term) { + | Label(_) => // TODO Remove duplication in cases Typ.eq(t1, t2) ? d @@ -53,7 +32,44 @@ let rec fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) |> DHExp.fresh |> Casts.transition_multiple; + } // These should be a different sort. I don't think we should be casting them. + | _ => + switch (t2.term) { + | Prod([{term: TupLabel({term: Label(l), _}, t), _}]) => + switch (t1.term) { + | Prod([{term: TupLabel({term: Label(l'), _}, _), _}]) when l == l' => + Typ.eq(t1, t2) + ? d + : { + let d' = + DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) + |> DHExp.fresh + |> Casts.transition_multiple; + DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) + |> DHExp.fresh + |> Casts.transition_multiple; + } + | _ => + Tuple([ + TupLabel(Label(l) |> DHExp.fresh, fresh_cast(d, t1, t)) + |> DHExp.fresh, + ]) + |> DHExp.fresh } + | _ => + // TODO Remove duplication in cases + Typ.eq(t1, t2) + ? d + : { + let d' = + DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) + |> DHExp.fresh + |> Casts.transition_multiple; + DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) + |> DHExp.fresh + |> Casts.transition_multiple; + } + } }; }; @@ -288,12 +304,9 @@ let rec elaborate_pattern = [Matt] A lot of these fresh_cast calls are redundant, however if you want to remove one, I'd ask you instead comment it out and leave a comment explaining why it's redundant. */ -let rec elaborate = - (m: Statics.Map.t, uexp: UExp.t, in_container: bool) - : (DHExp.t, Typ.t) => { +let rec elaborate = (m: Statics.Map.t, uexp: UExp.t): (DHExp.t, Typ.t) => { let (elaborated_type, ctx, co_ctx) = elaborated_type(m, uexp); - let elaborate = (~in_container=false, m, uexp) => - elaborate(m, uexp, in_container); + let elaborate = (m, uexp) => elaborate(m, uexp); let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); let (term, rewrap) = UExp.unwrap(uexp); let dhexp = @@ -365,21 +378,11 @@ let rec elaborate = | TupLabel(label, e) => let (label', labty) = elaborate(m, label); let (e', ety) = elaborate(m, e); - if (in_container) { - Exp.TupLabel(label', e') - |> rewrap - |> cast_from(Typ.TupLabel(labty, ety) |> Typ.temp); - } else { - Tuple([Exp.TupLabel(label', e') |> rewrap]) - |> Exp.fresh - |> cast_from( - Typ.Prod([Typ.TupLabel(labty, ety) |> Typ.temp]) |> Typ.temp, - ); - }; - + Exp.TupLabel(label', e') + |> rewrap + |> cast_from(Typ.TupLabel(labty, ety) |> Typ.temp); | Tuple(es) => - let (ds, tys) = - List.map(elaborate(m, ~in_container=true), es) |> ListUtil.unzip; + let (ds, tys) = List.map(elaborate(m), es) |> ListUtil.unzip; let expected_labels: list(option(string)) = Typ.get_labels(ctx, elaborated_type); @@ -415,8 +418,9 @@ let rec elaborate = Typ.get_label, ds, tys, - (name, e) => - DHExp.TupLabel(Label(name) |> DHExp.fresh, e) |> DHExp.fresh, + (name, e) => { + DHExp.TupLabel(Label(name) |> DHExp.fresh, e) |> DHExp.fresh + }, (name, t) => Typ.TupLabel(Label(name) |> Typ.temp, t) |> Typ.temp, ); Exp.Tuple(ds) |> rewrap |> cast_from(Prod(tys) |> Typ.temp); @@ -766,7 +770,7 @@ let fix_typ_ids = Exp.map_term(~f_typ=(cont, e) => e |> IdTagged.new_ids |> cont); let uexp_elab = (m: Statics.Map.t, uexp: UExp.t): ElaborationResult.t => - switch (elaborate(m, uexp, false)) { + switch (elaborate(m, uexp)) { | exception MissingTypeInfo => DoesNotElaborate | (d, ty) => Elaborates(d, ty, Delta.empty) }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 778c573a3e..bfcca349d8 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -229,7 +229,7 @@ and uexp_to_info_map = add(~self, ~co_ctx=CoCtx.empty, m); }; - let default_case = () => + let default_case = () => { switch (term) { | Closure(_) => failwith( @@ -810,7 +810,7 @@ and uexp_to_info_map = add(~self=Just(ty_body), ~co_ctx, m); }; }; - + }; // This is to allow lifting single values into a singleton labeled tuple when the label is not present // TODO Think about this real hard @@ -821,30 +821,6 @@ and uexp_to_info_map = let (e, m) = go(~mode=Mode.Syn, uexp, m); switch (Typ.weak_head_normalize(ctx, e.ty).term) { - | _ when Typ.is_consistent(ctx, ana_ty, e.ty) => - let (e, m) = - uexp_to_info_map( - ~ctx, - ~mode=Mode.Ana(ana_ty), - ~is_in_filter, - ~ancestors, - uexp, - m, - ); - let fake_uexp = - Tuple([TupLabel(Label(l1) |> Exp.fresh, uexp) |> Exp.fresh]) - |> Exp.fresh; - let info = - Info.derived_exp( - ~uexp=fake_uexp, - ~ctx, - ~mode, - ~ancestors, - ~self=Common(Just(ty)), - ~co_ctx=e.co_ctx, - ); - - (info, add_info(fake_uexp.ids, InfoExp(info), m)); | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) when l1 == l2 => default_case() | _ => diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index 59c003e9a8..48a420d932 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -452,8 +452,8 @@ module Exp = { | Match => "Case expression" | Cast => "Cast expression"; - let rec get_label: t => option((LabeledTuple.label, t)) = - e => + let rec get_label: t => option((LabeledTuple.label, t)) = { + e => { switch (e.term) { | Parens(e) => get_label(e) | TupLabel(elab, e') => @@ -461,8 +461,13 @@ module Exp = { | Label(name) => Some((name, e')) | _ => None } + // | Cast(e2, _, {term: TupLabel({term: Label(l), _}, _), _}) => + // Some((l, e2)) // TODO I would like to remove this case and stop casting in the case that we have the same labels + | Cast(e, _, _) => get_label(e) // TODO I would like to remove this case and stop casting in the case that we have the same labels | _ => None }; + }; + }; // Typfun should be treated as a function here as this is only used to // determine when to allow for recursive definitions in a let binding. diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index a60c3f09f5..8bbdba094c 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -808,8 +808,8 @@ and Typ: { | (_, Parens(t2)) => eq_internal(n, t1, t2) | (TupLabel(label1, t1'), TupLabel(label2, t2')) => eq_internal(n, label1, label2) && eq_internal(n, t1', t2') - | (TupLabel(_, t1), _) => eq_internal(n, t1, t2) - | (_, TupLabel(_, t2)) => eq_internal(n, t1, t2) + | (TupLabel(_, t1), _) => false // TODO Verify this + | (_, TupLabel(_, t2)) => false | (Rec(x1, t1), Rec(x2, t2)) | (Forall(x1, t1), Forall(x2, t2)) => let alpha_subst = diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index b4cc5b4796..6bdb5cfea9 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -8,7 +8,7 @@ let dhexp_typ = testable(Fmt.using(Exp.show, Fmt.string), DHExp.fast_equal); let ids = List.init(12, _ => Id.mk()); let id_at = x => x |> List.nth(ids); let mk_map = Statics.mk(CoreSettings.on, Builtins.ctx_init); -let dhexp_of_uexp = u => Elaborator.elaborate(mk_map(u), u, false) |> fst; +let dhexp_of_uexp = u => Elaborator.elaborate(mk_map(u), u) |> fst; let alco_check = dhexp_typ |> Alcotest.check; let parse_exp = (s: string) => MakeTerm.from_zip_for_sem(Option.get(Printer.zipper_of_string(s))).term; @@ -537,6 +537,77 @@ let elaboration_tests = [ dhexp_of_uexp(parse_exp({|(fun a=(x:Int) -> x)(1)|})), ) ), + test_case("Failed cast inside labeled tuple", `Quick, () => + alco_check( + {|let x : (c=String) = c=1 in x|}, // TODO Things go wrong if this is unknown rather than String + Let( + Var("x") |> Pat.fresh, + Tuple([ + TupLabel( + Label("c") |> Exp.fresh, + FailedCast( + Int(1) |> Exp.fresh, + Int |> Typ.fresh, + String |> Typ.fresh, + ) + |> Exp.fresh, + ) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(parse_exp({|let x : (c=String) = c=1 in x|})), + ) + ), + test_case("nested different singleton labeled arguments", `Quick, () => + alco_check( + {|let x : (b=c=String) = b="" in x|}, + Let( + Var("x") |> Pat.fresh, + Tuple([ + TupLabel( + Label("b") |> Exp.fresh, + Tuple([ + TupLabel( + Label("c") |> Exp.fresh, + FailedCast( + Int(1) |> Exp.fresh, + Int |> Typ.fresh, + String |> Typ.fresh, + ) + |> Exp.fresh, + ) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(parse_exp({|let x : (b=c=String) = b="" in x|})), + ) + ), + test_case("Singleton labeled argument let with unknown type", `Quick, () => + alco_check( + {|let x : (a=?) = (a=1) in x|}, + Let( + Var("x") |> Pat.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(parse_exp({|let x : (a=?) = (a=1) in x|})), + ) + ), test_case( "Singleton labeled argument function application with unknown type", `Quick, diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 83049d46c5..928749f499 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -33,8 +33,13 @@ let ids = List.init(12, _ => Id.mk()); let id_at = x => x |> List.nth(ids); let statics = Statics.mk(CoreSettings.on, Builtins.ctx_init); let alco_check = Alcotest.option(testable_typ) |> Alcotest.check; +let parse_exp = (s: string) => + MakeTerm.from_zip_for_sem(Option.get(Printer.zipper_of_string(s))).term; let info_of_id = (~statics_map=?, f: UExp.t, id: Id.t) => { + // print_endline( + // "Map: " ++ [%derive.show: option(Statics.Map.t)](statics_map), + // ); let s = switch (statics_map) { | Some(s) => s @@ -305,27 +310,27 @@ let tests = ) |> Exp.fresh, ), - fully_consistent_typecheck( - "function application", - "float_of_int(1)", - Some(float), - Ap(Forward, Var("float_of_int") |> Exp.fresh, Int(1) |> Exp.fresh) - |> Exp.fresh, - ), - fully_consistent_typecheck( - "function deferral", - "string_sub(\"hello\", 1, _)", - Some(arrow(int, string)), - DeferredAp( - Var("string_sub") |> Exp.fresh, - [ - String("hello") |> Exp.fresh, - Int(1) |> Exp.fresh, - Deferral(InAp) |> Exp.fresh, - ], - ) - |> Exp.fresh, - ), + // fully_consistent_typecheck( + // "function application", + // "float_of_int(1)", + // Some(float), + // Ap(Forward, Var("float_of_int") |> Exp.fresh, Int(1) |> Exp.fresh) + // |> Exp.fresh, + // ), + // fully_consistent_typecheck( + // "function deferral", + // "string_sub(\"hello\", 1, _)", + // Some(arrow(int, string)), + // DeferredAp( + // Var("string_sub") |> Exp.fresh, + // [ + // String("hello") |> Exp.fresh, + // Int(1) |> Exp.fresh, + // Deferral(InAp) |> Exp.fresh, + // ], + // ) + // |> Exp.fresh, + // ), unlabeled_tuple_to_labeled_fails, simple_inconsistency, fully_consistent_typecheck( @@ -513,8 +518,7 @@ let tests = ), fully_consistent_typecheck( "Duplicate singleton labels", - {|let x : (l=Int) = 1 in - let y : (l=(l=Int)) = x in y|}, + {|let y : (l=(l=Int)) = (l=1) in y|}, Some( Prod([ TupLabel( @@ -532,51 +536,7 @@ let tests = ]) |> Typ.fresh, ), - Let( - Cast( - Var("x") |> Pat.fresh, - Parens( - Prod([ - TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) - |> Typ.fresh, - ]) - |> Typ.fresh, - ) - |> Typ.fresh, - Unknown(Internal) |> Typ.fresh, - ) - |> Pat.fresh, - Int(1) |> Exp.fresh, - Let( - Cast( - Var("y") |> Pat.fresh, - Parens( - Prod([ - TupLabel( - Label("l") |> Typ.fresh, - Parens( - Prod([ - TupLabel(Label("l") |> Typ.fresh, Int |> Typ.fresh) - |> Typ.fresh, - ]) - |> Typ.fresh, - ) - |> Typ.fresh, - ) - |> Typ.fresh, - ]) - |> Typ.fresh, - ) - |> Typ.fresh, - Unknown(Internal) |> Typ.fresh, - ) - |> Pat.fresh, - Var("x") |> Exp.fresh, - Var("y") |> Exp.fresh, - ) - |> Exp.fresh, - ) - |> Exp.fresh, + parse_exp({|let y : (l=(l=Int)) = (l=1) in y|}), ), fully_consistent_typecheck( "Reconstructed labeled tuple without values", @@ -604,4 +564,67 @@ let tests = ) |> Exp.fresh, ), + fully_consistent_typecheck( + "Singleton labeled argument let with unknown type", + {|let x : (a=?) = (a=1) in x|}, + Some( + Prod([ + TupLabel( + Label("a") |> Typ.fresh, + Unknown(Hole(EmptyHole)) |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ), + parse_exp({|let x : (a=?) = (a=1) in x|}), + ), + fully_consistent_typecheck( + "nested different singleton labeled arguments", + {|let x : (b=c=String) = b="" in x|}, + Some( + Prod([ + TupLabel( + Label("b") |> Typ.fresh, + Prod([ + TupLabel(Label("c") |> Typ.fresh, String |> Typ.fresh) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ), + parse_exp({|let x : (b=c=String) = b="" in x|}), + ), + fully_consistent_typecheck( + "nested different singleton labeled arguments", + {|let x : (a=b=c=?) = b=? in x|}, + Some( + Prod([ + TupLabel( + Label("a") |> Typ.fresh, + Prod([ + TupLabel( + Label("b") |> Typ.fresh, + Prod([ + TupLabel( + Label("c") |> Typ.fresh, + Unknown(Hole(EmptyHole)) |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ) + |> Typ.fresh, + ]) + |> Typ.fresh, + ), + parse_exp({|let x : (a=b=c=?) = b=? in x|}), + ), ]; From 9a918effcb59dcb63ac136f28241af6aa96d3603 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 21 Oct 2024 16:15:22 -0400 Subject: [PATCH 084/108] Fix warnings --- src/haz3lcore/statics/TermBase.re | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index 8bbdba094c..5bd1708bf6 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -808,8 +808,8 @@ and Typ: { | (_, Parens(t2)) => eq_internal(n, t1, t2) | (TupLabel(label1, t1'), TupLabel(label2, t2')) => eq_internal(n, label1, label2) && eq_internal(n, t1', t2') - | (TupLabel(_, t1), _) => false // TODO Verify this - | (_, TupLabel(_, t2)) => false + | (TupLabel(_, _), _) => false // TODO Verify this + | (_, TupLabel(_, _)) => false | (Rec(x1, t1), Rec(x2, t2)) | (Forall(x1, t1), Forall(x2, t2)) => let alpha_subst = From d88395e5a7da07edd02b949cfcdd8bd6553d90af Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Thu, 31 Oct 2024 16:07:48 -0400 Subject: [PATCH 085/108] Closer to getting singleton labeled tuples to work --- src/haz3lcore/dynamics/Elaborator.re | 20 +++++++++---- src/haz3lcore/statics/Statics.re | 19 +++++-------- test/Test_Elaboration.re | 42 +++++++++++----------------- 3 files changed, 38 insertions(+), 43 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 22e9fb5450..5904052bf8 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -88,14 +88,16 @@ let fresh_pat_cast = (p: DHPat.t, t1: Typ.t, t2: Typ.t): DHPat.t => { }; }; -let elaborated_type = (m: Statics.Map.t, uexp: UExp.t): (Typ.t, Ctx.t, 'a) => { - let (mode, self_ty, ctx, co_ctx) = +let elaborated_type = + (m: Statics.Map.t, uexp: UExp.t): (Typ.t, Ctx.t, 'a, UExp.t) => { + let (mode, self_ty, ctx, co_ctx, term) = switch (Id.Map.find_opt(Exp.rep_id(uexp), m)) { - | Some(Info.InfoExp({mode, ty, ctx, co_ctx, _})) => ( + | Some(Info.InfoExp({mode, ty, ctx, co_ctx, term, _})) => ( mode, ty, ctx, co_ctx, + term, ) | _ => raise(MissingTypeInfo) }; @@ -112,7 +114,7 @@ let elaborated_type = (m: Statics.Map.t, uexp: UExp.t): (Typ.t, Ctx.t, 'a) => { // We need to remove the synswitches from this type. | Ana(ana_ty) => Typ.match_synswitch(ana_ty, self_ty) }; - (elab_ty |> Typ.normalize(ctx), ctx, co_ctx); + (elab_ty |> Typ.normalize(ctx), ctx, co_ctx, term); }; let elaborated_pat_type = (m: Statics.Map.t, upat: UPat.t): (Typ.t, Ctx.t) => { @@ -305,10 +307,16 @@ let rec elaborate_pattern = want to remove one, I'd ask you instead comment it out and leave a comment explaining why it's redundant. */ let rec elaborate = (m: Statics.Map.t, uexp: UExp.t): (DHExp.t, Typ.t) => { - let (elaborated_type, ctx, co_ctx) = elaborated_type(m, uexp); - let elaborate = (m, uexp) => elaborate(m, uexp); + // In the case of singleton labeled tuples we update the syntax in Statics. + // We store this syntax with the same ID as the original expression and store it on the Info.exp in the Statics.map + // We are then pulling this out and using it in place of the actual expression. + let (elaborated_type, ctx, co_ctx, statics_pseudo_elaborated) = + elaborated_type(m, uexp); + let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); let (term, rewrap) = UExp.unwrap(uexp); + let uexp = rewrap(statics_pseudo_elaborated.term); + let term = statics_pseudo_elaborated.term; let dhexp = switch (term) { | Invalid(_) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index bfcca349d8..c46b835c64 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -825,29 +825,24 @@ and uexp_to_info_map = default_case() | _ => // TODO Deduplicate + + let (term, rewrap) = UExp.unwrap(uexp); + let og_exp = Exp.fresh(term); let (e, m) = uexp_to_info_map( ~ctx, ~mode=Mode.Ana(ana_ty), ~is_in_filter, ~ancestors, - uexp, + og_exp, // TODO Figure out how to manifest this with statics. We may need to add some ofther form of info_exp on the statics map. m, ); let fake_uexp = - Tuple([TupLabel(Label(l1) |> Exp.fresh, uexp) |> Exp.fresh]) - |> Exp.fresh; - let info = - Info.derived_exp( - ~uexp=fake_uexp, - ~ctx, - ~mode, - ~ancestors, - ~self=Common(Just(ty)), - ~co_ctx=e.co_ctx, + rewrap( + Tuple([TupLabel(Label(l1) |> Exp.fresh, og_exp) |> Exp.fresh]), ); - (info, add_info(fake_uexp.ids, InfoExp(info), m)); + uexp_to_info_map(~ctx, ~mode, ~ancestors, fake_uexp, m); }; | _ => default_case() } diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 4dc27f5f86..746886d180 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -685,15 +685,7 @@ let elaboration_tests = [ TupLabel( Label("b") |> Exp.fresh, Tuple([ - TupLabel( - Label("c") |> Exp.fresh, - FailedCast( - Int(1) |> Exp.fresh, - Int |> Typ.fresh, - String |> Typ.fresh, - ) - |> Exp.fresh, - ) + TupLabel(Label("c") |> Exp.fresh, String("") |> Exp.fresh) |> Exp.fresh, ]) |> Exp.fresh, @@ -707,22 +699,6 @@ let elaboration_tests = [ dhexp_of_uexp(parse_exp({|let x : (b=c=String) = b="" in x|})), ) ), - test_case("Singleton labeled argument let with unknown type", `Quick, () => - alco_check( - {|let x : (a=?) = (a=1) in x|}, - Let( - Var("x") |> Pat.fresh, - Tuple([ - TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) - |> Exp.fresh, - ]) - |> Exp.fresh, - Var("x") |> Exp.fresh, - ) - |> Exp.fresh, - dhexp_of_uexp(parse_exp({|let x : (a=?) = (a=1) in x|})), - ) - ), test_case( "Singleton labeled argument function application with unknown type", `Quick, @@ -752,6 +728,22 @@ let elaboration_tests = [ dhexp_of_uexp(parse_exp({|(fun a=x->x)(a=1)|})), ) ), + test_case("Singleton labeled argument let with unknown type", `Quick, () => + alco_check( + {|let x : (a=?) = (a=1) in x|}, + Let( + Var("x") |> Pat.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + Var("x") |> Exp.fresh, + ) + |> Exp.fresh, + dhexp_of_uexp(parse_exp({|let x : (a=?) = (a=1) in x|})), + ) + ), test_case( "Function application with a single remaining argument after deferral", `Quick, From 7c5abb5f18bb57dd7efbd9f049007ecb9503a0de Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 1 Nov 2024 09:34:05 -0400 Subject: [PATCH 086/108] Fix unused warnings --- src/haz3lcore/dynamics/Elaborator.re | 2 +- src/haz3lcore/statics/Statics.re | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 5904052bf8..1d27863ee2 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -314,7 +314,7 @@ let rec elaborate = (m: Statics.Map.t, uexp: UExp.t): (DHExp.t, Typ.t) => { elaborated_type(m, uexp); let cast_from = (ty, exp) => fresh_cast(exp, ty, elaborated_type); - let (term, rewrap) = UExp.unwrap(uexp); + let (_, rewrap) = UExp.unwrap(uexp); let uexp = rewrap(statics_pseudo_elaborated.term); let term = statics_pseudo_elaborated.term; let dhexp = diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index c46b835c64..d9c5e6c104 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -828,7 +828,7 @@ and uexp_to_info_map = let (term, rewrap) = UExp.unwrap(uexp); let og_exp = Exp.fresh(term); - let (e, m) = + let (_, m) = uexp_to_info_map( ~ctx, ~mode=Mode.Ana(ana_ty), From d163367bcdc6dbcb1b6a3b51dc9ac7d8d28177dd Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 1 Nov 2024 11:25:56 -0400 Subject: [PATCH 087/108] Errored statuses showed up right --- src/haz3lcore/statics/Info.re | 5 +++-- src/haz3lcore/statics/Statics.re | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 8406edcb66..bfa9e39781 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -533,8 +533,9 @@ let status_tpat = (ctx: Ctx.t, utpat: TPat.t): status_tpat => /* 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)) { + | InfoExp({status, _}) => + // TODO Confirm with disconcision that we can use the derived status + switch (status) { | InHole(_) => true | NotInHole(_) => false } diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index d9c5e6c104..71e081038a 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -828,7 +828,7 @@ and uexp_to_info_map = let (term, rewrap) = UExp.unwrap(uexp); let og_exp = Exp.fresh(term); - let (_, m) = + let (og_info, m) = uexp_to_info_map( ~ctx, ~mode=Mode.Ana(ana_ty), @@ -841,8 +841,12 @@ and uexp_to_info_map = rewrap( Tuple([TupLabel(Label(l1) |> Exp.fresh, og_exp) |> Exp.fresh]), ); + let (info, m) = + uexp_to_info_map(~ctx, ~mode, ~ancestors, fake_uexp, m); - uexp_to_info_map(~ctx, ~mode, ~ancestors, fake_uexp, m); + let info = {...info, status: og_info.status}; + + (info, add_info(fake_uexp.ids, InfoExp(info), m)); }; | _ => default_case() } From 0343f51f520ce0a14722371223c8eb74ecae65a9 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 1 Nov 2024 12:41:48 -0400 Subject: [PATCH 088/108] Extract functions to be slightly more legible --- src/haz3lcore/statics/Statics.re | 57 +++++++++++++++++--------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 71e081038a..94a53fffb6 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -225,6 +225,33 @@ and uexp_to_info_map = ([], m), ); let go_pat = upat_to_info_map(~ctx, ~ancestors); + let elaborate_singleton_tuple = (uexp: Exp.t, inner_ty, l, m) => { + let (term, rewrap) = UExp.unwrap(uexp); + let original_expression = Exp.fresh(term); + let (original_info, m) = + uexp_to_info_map( + ~ctx, + ~mode=Mode.Ana(inner_ty), + ~is_in_filter, + ~ancestors, + original_expression, + m, + ); + let elaborated_exp = + rewrap( + Tuple([ + TupLabel(Label(l) |> Exp.fresh, original_expression) |> Exp.fresh, + ]), + ); + // We need to reanalyze the elaborated expression to get the statics in the map for the label and tuple + let (info, m) = + uexp_to_info_map(~ctx, ~mode, ~ancestors, elaborated_exp, m); + + // We need to keep the original status of the expression to get error messages on the unelaborated expression + let info = {...info, status: original_info.status}; + + (info, add_info(elaborated_exp.ids, InfoExp(info), m)); + }; let atomic = self => { add(~self, ~co_ctx=CoCtx.empty, m); }; @@ -811,42 +838,20 @@ and uexp_to_info_map = }; }; }; - // This is to allow lifting single values into a singleton labeled tuple when the label is not present - // TODO Think about this real hard + // This is to allow lifting single values into a singleton labeled tuple when the label is not present switch (mode) { | Ana(ty) => switch (Typ.weak_head_normalize(ctx, ty).term) { | Prod([{term: TupLabel({term: Label(l1), _}, ana_ty), _}]) => + // We can flatten this by pulling it up on the case match but since OCaml is strict it'll be evaluated. + // So for performance reasons we'll just do it here. let (e, m) = go(~mode=Mode.Syn, uexp, m); switch (Typ.weak_head_normalize(ctx, e.ty).term) { | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) when l1 == l2 => default_case() - | _ => - // TODO Deduplicate - - let (term, rewrap) = UExp.unwrap(uexp); - let og_exp = Exp.fresh(term); - let (og_info, m) = - uexp_to_info_map( - ~ctx, - ~mode=Mode.Ana(ana_ty), - ~is_in_filter, - ~ancestors, - og_exp, // TODO Figure out how to manifest this with statics. We may need to add some ofther form of info_exp on the statics map. - m, - ); - let fake_uexp = - rewrap( - Tuple([TupLabel(Label(l1) |> Exp.fresh, og_exp) |> Exp.fresh]), - ); - let (info, m) = - uexp_to_info_map(~ctx, ~mode, ~ancestors, fake_uexp, m); - - let info = {...info, status: og_info.status}; - - (info, add_info(fake_uexp.ids, InfoExp(info), m)); + | _ => elaborate_singleton_tuple(uexp, ana_ty, l1, m) }; | _ => default_case() } From 12eef7012e9d6932a013248f0d02e2fce502e6a0 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 4 Nov 2024 13:54:54 -0500 Subject: [PATCH 089/108] Fixed singleton labeled tuple in function application --- src/haz3lcore/dynamics/Elaborator.re | 61 +++++----------------------- src/haz3lcore/statics/Statics.re | 12 +++--- test/Test_Statics.re | 50 +++++++++++++++++++++++ 3 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 1d27863ee2..fd97051a2d 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -18,59 +18,18 @@ module ElaborationResult = { | DoesNotElaborate; }; -let rec fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { - switch (t1.term) { - | Label(_) => - // TODO Remove duplication in cases - Typ.eq(t1, t2) - ? d - : { - let d' = - DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) - |> DHExp.fresh - |> Casts.transition_multiple; - DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) +let fresh_cast = (d: DHExp.t, t1: Typ.t, t2: Typ.t): DHExp.t => { + Typ.eq(t1, t2) + ? d + : { + let d' = + DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) |> DHExp.fresh |> Casts.transition_multiple; - } // These should be a different sort. I don't think we should be casting them. - | _ => - switch (t2.term) { - | Prod([{term: TupLabel({term: Label(l), _}, t), _}]) => - switch (t1.term) { - | Prod([{term: TupLabel({term: Label(l'), _}, _), _}]) when l == l' => - Typ.eq(t1, t2) - ? d - : { - let d' = - DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) - |> DHExp.fresh - |> Casts.transition_multiple; - DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) - |> DHExp.fresh - |> Casts.transition_multiple; - } - | _ => - Tuple([ - TupLabel(Label(l) |> DHExp.fresh, fresh_cast(d, t1, t)) - |> DHExp.fresh, - ]) - |> DHExp.fresh - } - | _ => - // TODO Remove duplication in cases - Typ.eq(t1, t2) - ? d - : { - let d' = - DHExp.Cast(d, t1, Typ.temp(Unknown(Internal))) - |> DHExp.fresh - |> Casts.transition_multiple; - DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) - |> DHExp.fresh - |> Casts.transition_multiple; - } - } - }; + DHExp.Cast(d', Typ.temp(Unknown(Internal)), t2) + |> DHExp.fresh + |> Casts.transition_multiple; + }; }; let fresh_pat_cast = (p: DHPat.t, t1: Typ.t, t2: Typ.t): DHPat.t => { diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 94a53fffb6..e7485ff376 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -226,6 +226,7 @@ and uexp_to_info_map = ); let go_pat = upat_to_info_map(~ctx, ~ancestors); let elaborate_singleton_tuple = (uexp: Exp.t, inner_ty, l, m) => { + print_endline("Elaborating singleton tuple"); let (term, rewrap) = UExp.unwrap(uexp); let original_expression = Exp.fresh(term); let (original_info, m) = @@ -484,11 +485,12 @@ and uexp_to_info_map = copied: arg.copied, }; arg; - | (TupLabel(_), Prod([{term: TupLabel(_), _}])) => - Tuple([arg]) |> Exp.fresh - | (_, Prod([{term: TupLabel({term: Label(name), _}, _), _}])) => - Tuple([TupLabel(Label(name) |> Exp.fresh, arg) |> Exp.fresh]) - |> Exp.fresh + // Now doing the singleton label elaboration below. I'll discuss with Anthony before removing these + // | (TupLabel(_), Prod([{term: TupLabel(_), _}])) => + // Tuple([arg]) |> Exp.fresh + // | (_, Prod([{term: TupLabel({term: Label(name), _}, _), _}])) => + // Tuple([TupLabel(Label(name) |> Exp.fresh, arg) |> Exp.fresh]) + // |> Exp.fresh | (_, _) => arg }; let (arg, m) = go(~mode=Ana(ty_in), arg, m); diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 928749f499..51a85a0b9d 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -627,4 +627,54 @@ let tests = ), parse_exp({|let x : (a=b=c=?) = b=? in x|}), ), + fully_consistent_typecheck( + "Singleton labeled argument function application with unknown type", + {|(fun a=x->x)(a=1)|}, + Some(unknown(Internal)), + Ap( + Forward, + Fun( + Tuple([ + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + |> Pat.fresh, + ]) + |> Pat.fresh, + Var("x") |> Exp.fresh, + None, + None, + ) + |> Exp.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + ), + fully_consistent_typecheck( + "Singleton labeled argument function application with no labeled param", + {|(fun a=x->x)(1)|}, + Some(int), + Ap( + Forward, + Fun( + Tuple([ + TupLabel(Label("a") |> Pat.fresh, Var("x") |> Pat.fresh) + |> Pat.fresh, + ]) + |> Pat.fresh, + Var("x") |> Exp.fresh, + None, + None, + ) + |> Exp.fresh, + Tuple([ + TupLabel(Label("a") |> Exp.fresh, Int(1) |> Exp.fresh) + |> Exp.fresh, + ]) + |> Exp.fresh, + ) + |> Exp.fresh, + ), ]; From 868ed9be5f85d1b433417e4a23a56d8efa7633b3 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 4 Nov 2024 14:22:46 -0500 Subject: [PATCH 090/108] Fix statics test --- test/Test_Statics.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Test_Statics.re b/test/Test_Statics.re index 51a85a0b9d..f1eedd487a 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -655,7 +655,7 @@ let tests = fully_consistent_typecheck( "Singleton labeled argument function application with no labeled param", {|(fun a=x->x)(1)|}, - Some(int), + Some(unknown(Internal)), Ap( Forward, Fun( From d1cd408a350087c83939015929767866f3ea8b59 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 8 Nov 2024 10:55:24 -0500 Subject: [PATCH 091/108] Add some information on the lifted type to the cursor inspector --- src/haz3lcore/statics/Info.re | 27 +++++++++++++++++--- src/haz3lcore/statics/Statics.re | 18 +++++++++++--- src/haz3lweb/view/CursorInspector.re | 37 +++++++++++++++++++++------- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index bfa9e39781..6202d262f0 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -202,7 +202,8 @@ type exp = { co_ctx: CoCtx.t, /* Locally free variables */ cls: Cls.t, /* DERIVED: Syntax class (i.e. form name) */ status: status_exp, /* DERIVED: Ok/Error statuses for display */ - ty: Typ.t /* DERIVED: Type after nonempty hole fixing */ + ty: Typ.t, /* DERIVED: Type after nonempty hole fixing */ + lifted_ty: option(Typ.t) /* Type static-level elaboration */ }; [@deriving (show({with_path: false}), sexp, yojson)] @@ -630,11 +631,31 @@ let fixed_typ_exp = (ctx, mode: Mode.t, self: Self.exp): Typ.t => /* Add derivable attributes for expression terms */ let derived_exp = - (~uexp: UExp.t, ~ctx, ~mode, ~ancestors, ~self, ~co_ctx): exp => { + ( + ~uexp: UExp.t, + ~ctx, + ~mode, + ~ancestors, + ~self, + ~co_ctx, + ~lifted_ty: option(Typ.t), + ) + : 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}; + { + cls, + self, + ty, + mode, + status, + ctx, + co_ctx, + ancestors, + lifted_ty, + term: uexp, + }; }; /* Add derivable attributes for pattern terms */ diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 3175df7bf0..dc7b8b809e 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -182,9 +182,17 @@ and uexp_to_info_map = | Ana({term: Unknown(SynSwitch), _}) => Mode.Syn | _ => mode }; - let add' = (~self, ~co_ctx, m) => { + let add' = (~lifted_ty=?, ~self, ~co_ctx, m) => { let info = - Info.derived_exp(~uexp, ~ctx, ~mode, ~ancestors, ~self, ~co_ctx); + Info.derived_exp( + ~uexp, + ~ctx, + ~mode, + ~ancestors, + ~self, + ~co_ctx, + ~lifted_ty, + ); (info, add_info(ids, InfoExp(info), m)); }; @@ -249,7 +257,11 @@ and uexp_to_info_map = uexp_to_info_map(~ctx, ~mode, ~ancestors, elaborated_exp, m); // We need to keep the original status of the expression to get error messages on the unelaborated expression - let info = {...info, status: original_info.status}; + let info = { + ...info, + status: original_info.status, + lifted_ty: Some(info.ty), + }; (info, add_info(elaborated_exp.ids, InfoExp(info), m)); }; diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index be3d3110e5..17e36c9480 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -66,7 +66,8 @@ let elements_noun: Cls.t => string = | Exp(ListConcat) => "Operands" | _ => failwith("elements_noun: Cls doesn't have elements"); -let common_err_view = (cls: Cls.t, err: Info.error_common) => +let common_err_view = + (~lifted_ty: option(Typ.t)=?, cls: Cls.t, err: Info.error_common) => switch (err) { | NoType(BadToken(token)) => switch (Form.bad_token_cls(token)) { @@ -85,19 +86,27 @@ let common_err_view = (cls: Cls.t, err: Info.error_common) => Type.view(typ), text("inconsistent with arrow type"), ] - | Inconsistent(Expectation({ana, syn})) => [ + | Inconsistent(Expectation({ana, syn})) => + [ text(":"), Type.view(syn), text("inconsistent with expected type"), Type.view(ana), ] + @ ( + switch (lifted_ty) { + | None => [] + | Some(lifted) => [text("lifted to"), Type.view(lifted)] + } + ) | Inconsistent(Internal(tys)) => [ text(elements_noun(cls) ++ " have inconsistent types:"), ...ListUtil.join(text(","), List.map(Type.view, tys)), ] }; -let common_ok_view = (cls: Cls.t, ok: Info.ok_pat) => { +let common_ok_view = + (~lifted_ty: option(Typ.t)=?, cls: Cls.t, ok: Info.ok_common) => { switch (cls, ok) { | (Exp(MultiHole) | Pat(MultiHole), _) => [ text("Expecting operator or delimiter"), @@ -122,12 +131,20 @@ let common_ok_view = (cls: Cls.t, ok: Info.ok_pat) => { Type.view(syn), text("equals expected type"), ] - | (_, Ana(Consistent({ana, syn, _}))) => [ + | (_, Ana(Consistent({ana, syn, _}))) => + // print_endline("Id: " ++) + [ text(":"), Type.view(syn), text("consistent with expected type"), Type.view(ana), ] + @ ( + switch (lifted_ty) { + | None => [] + | Some(lifted) => [text("lifted to"), Type.view(lifted)] + } + ) | (_, Ana(InternallyInconsistent({ana, nojoin: tys}))) => [ text(elements_noun(cls) ++ " have inconsistent types:"), @@ -177,7 +194,7 @@ let typ_err_view = (ok: Info.error_typ) => ] }; -let rec exp_view = (cls: Cls.t, status: Info.status_exp) => +let rec exp_view = (cls: Cls.t, status: Info.status_exp, info: Info.exp) => switch (status) { | InHole(FreeVariable(name)) => div_err([code_err(name), text("not found")]) @@ -188,7 +205,7 @@ let rec exp_view = (cls: Cls.t, status: Info.status_exp) => | Some(err) => let cls_str = String.uncapitalize_ascii(cls_str); div_err([ - exp_view(cls, InHole(Common(err))), + exp_view(cls, InHole(Common(err)), info), text("; " ++ cls_str ++ " is inexhaustive"), ]); }; @@ -208,10 +225,12 @@ let rec exp_view = (cls: Cls.t, status: Info.status_exp) => ++ " arguments", ), ]) - | InHole(Common(error)) => div_err(common_err_view(cls, error)) + | InHole(Common(error)) => + div_err(common_err_view(~lifted_ty=?info.lifted_ty, cls, error)) | NotInHole(AnaDeferralConsistent(ana)) => div_ok([text("Expecting type"), Type.view(ana)]) - | NotInHole(Common(ok)) => div_ok(common_ok_view(cls, ok)) + | NotInHole(Common(ok)) => + div_ok(common_ok_view(~lifted_ty=?info.lifted_ty, cls, ok)) }; let rec pat_view = (cls: Cls.t, status: Info.status_pat) => @@ -266,7 +285,7 @@ let view_of_info = (~inject, ~settings, ci): list(Node.t) => { ]; switch (ci) { | Secondary(_) => wrapper(div([])) - | InfoExp({cls, status, _}) => wrapper(exp_view(cls, status)) + | InfoExp({cls, status, _} as ie) => wrapper(exp_view(cls, status, ie)) | InfoPat({cls, status, _}) => wrapper(pat_view(cls, status)) | InfoTyp({cls, status, _}) => wrapper(typ_view(cls, status)) | InfoTPat({cls, status, _}) => wrapper(tpat_view(cls, status)) From ece70b411b897b1328ffdbd8e5f79beabd5249aa Mon Sep 17 00:00:00 2001 From: WondAli Date: Sun, 10 Nov 2024 14:23:08 -0500 Subject: [PATCH 092/108] label uniqueness checking --- src/haz3lcore/LabeledTuple.re | 99 ++++++++++++++---------- src/haz3lcore/statics/Info.re | 59 +++++++++++++-- src/haz3lcore/statics/Self.re | 10 ++- src/haz3lcore/statics/Statics.re | 109 +++++++++++++++++++-------- src/haz3lweb/view/CursorInspector.re | 5 ++ 5 files changed, 206 insertions(+), 76 deletions(-) diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index fbbfdee19c..a4ac9a667e 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -57,45 +57,6 @@ let separate_and_keep_labels: results; }; -// returns ordered list of (Some(string), TupLabel) -// and another of (None, not-TupLabel) -// TODO: Actually validate uniqueness in statics -// TODO: Make more efficient -// let validate_uniqueness: -// 'a. -// ('a => option((t, 'a)), list('a)) => -// (bool, list((option(t), 'a)), list('a)) -// = -// (get_label, es) => { -// let results = -// List.fold_left( -// ((b, ls, ns), e) => -// switch (get_label(e)) { -// | Some((s1, _)) -// when -// b -// && List.fold_left( -// (v, l) => -// switch (l) { -// | (Some(s2), _) when v => compare(s1, s2) != 0 -// | _ => false -// }, -// true, -// ls, -// ) => ( -// b, -// ls @ [(Some(s1), e)], -// ns, -// ) -// | None => (b, ls, ns @ [e]) -// | _ => (false, ls, ns) -// }, -// (true, [], []), -// es, -// ); -// results; -// }; - // TODO consider adding a t = (option(label), 'a) let separate_labeled = (xs: list((option(label), 'a))) => { @@ -114,6 +75,66 @@ let intersect = (xs, ys) => { List.filter_map(x => List.find_opt((==)(x), ys), xs); }; +// TODO: can just use get_duplicate_labels and check if empty. +// Takes a list of strings and returns true if there are no duplicates. +let rec is_uniquely_labeled_base: list(label) => bool = + labels => { + let contains_duplicates = + switch (labels) { + | [] => false + | [hd, ...tl] => + List.exists(l => hd == l, tl) || is_uniquely_labeled_base(tl) + }; + !contains_duplicates; + }; + +// TODO: Performance +// Takes a list of strings and returns a list of duplicates and list of uniques. +// Can also be modified to get unique labels. +let get_duplicate_and_unique_labels_base: + list(label) => (list(label), list(label)) = + labels => { + let (duplicates, uniques) = + List.fold_left( + (acc, label) => { + let (dupes, uniqs) = acc; + List.exists(l => label == l, uniqs) + ? List.exists(l => label == l, dupes) + ? (dupes, uniqs) : (dupes @ [label], uniqs) + : (dupes, uniqs @ [label]); + }, + ([], []), + labels, + ); + (duplicates, uniques); + }; + +// Takes in a get_label function and a list of elements and applys is_uniquely_labeled_base +let is_uniquely_labeled: 'a. ('a => option((label, 'a)), list('a)) => bool = + (get_label, es) => { + let labels = fst(separate_and_keep_labels(get_label, es)); + let labels = + labels + |> List.filter(x => Option.is_some(x)) + |> OptUtil.sequence + |> OptUtil.get(() => []); + is_uniquely_labeled_base(labels); + }; + +let get_duplicate_and_unique_labels: + 'a. + ('a => option((label, 'a)), list('a)) => (list(label), list(label)) + = + (get_label, es) => { + let labels = fst(separate_and_keep_labels(get_label, es)); + let labels = + labels + |> List.filter(x => Option.is_some(x)) + |> OptUtil.sequence + |> OptUtil.get(() => []); + get_duplicate_and_unique_labels_base(labels); + }; + // Assumes all labels are unique // Rearranges all the labels in l2 to match the order of the labels in l1. Labels are optional and should me reordered for all present labels first and then unlabled fields matched up pairwise. So labeled fields can be reordered and unlabeled ones can't. Also add labels to the unlabeled. // TODO Handle the unequal length case and extra labels case diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 6202d262f0..e9580b476f 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -59,7 +59,11 @@ type error_common = /* Underdetermined: No type can be assigned */ | NoType(error_no_type) /* Overdetermined: Conflicting type expectations */ - | Inconsistent(error_inconsistent); + | Inconsistent(error_inconsistent) + /* Duplicate labels in labeled tuple */ + | DuplicateLabels(Typ.t) + /* Duplicate item, used for duplicated labels*/ + | Duplicate(Typ.t); [@deriving (show({with_path: false}), sexp, yojson)] type error_exp = @@ -132,7 +136,8 @@ type status_variant = [@deriving (show({with_path: false}), sexp, yojson)] type typ_expects = | TypeExpected - | TupleExpected + | TupleExpected(status_variant) + | LabelExpected(status_variant, list(string)) // list of duplicate labels expected to NOT be | ConstructorExpected(status_variant, Typ.t) | VariantExpected(status_variant, Typ.t); @@ -145,8 +150,11 @@ type error_typ = | BadToken(Token.t) /* Invalid token, treated as type hole */ | FreeTypeVariable(string) /* Free type variable */ | DuplicateConstructor(Constructor.t) /* Duplicate ctr in same sum */ + | DuplicateLabels(Typ.t) + | Duplicate(Typ.t) | WantTypeFoundAp | WantTuple + | WantLabel | WantConstructorFoundType(Typ.t) | WantConstructorFoundAp; @@ -373,6 +381,11 @@ let rec status_common = } | (BadToken(name), _) => InHole(NoType(BadToken(name))) | (BadTrivAp(ty), _) => InHole(NoType(BadTrivAp(ty))) + | (Duplicate_Labels(Just(ty)), _) => InHole(DuplicateLabels(ty)) + | (Duplicate(Just(ty)), _) => InHole(Duplicate(ty)) + | (Duplicate_Labels(_), _) => + InHole(DuplicateLabels(Unknown(Internal) |> Typ.temp)) + | (Duplicate(_), _) => InHole(Duplicate(Unknown(Internal) |> Typ.temp)) | (IsMulti, _) => NotInHole(Syn(Unknown(Internal) |> Typ.temp)) | (NoJoin(wrap, tys), Ana(ana)) => let syn: Typ.t = Self.join_of(wrap, Unknown(Internal) |> Typ.temp); @@ -395,6 +408,8 @@ let rec status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => | InHole(Common(Inconsistent(Internal(_) | Expectation(_))) as err) | InHole(Common(NoType(_)) as err) => Some(err) | NotInHole(_) => None + | InHole(Common(DuplicateLabels(_))) // Is this right? + | InHole(Common(Duplicate(_))) | InHole(Common(Inconsistent(WithArrow(_)))) | InHole(ExpectedConstructor | Redundant(_)) => // ExpectedConstructor cannot be a reason to hole-wrap the entire pattern @@ -431,6 +446,8 @@ 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(Common(DuplicateLabels(_))) // Is this right? + | InHole(Common(Duplicate(_))) | InHole( FreeVariable(_) | InexhaustiveMatch(_) | UnusedDeferral | BadPartialAp(_), @@ -467,12 +484,18 @@ let status_typ = (ctx: Ctx.t, expects: typ_expects, ty: Typ.t): status_typ => | VariantExpected(Duplicate, _) | ConstructorExpected(Duplicate, _) => InHole(DuplicateConstructor(name)) - | TupleExpected => + | TupleExpected(_) => switch (Ctx.lookup_alias(ctx, name)) { | Some({term: Prod(_), _}) => NotInHole(TypeAlias(name, Typ.weak_head_normalize(ctx, ty))) | _ => InHole(WantTuple) } + | LabelExpected(_) => + switch (Ctx.lookup_alias(ctx, name)) { + | Some({term: Label(_), _}) => + NotInHole(TypeAlias(name, Typ.weak_head_normalize(ctx, ty))) + | _ => InHole(WantLabel) + } | TypeExpected => switch (Ctx.is_alias(ctx, name)) { | false => @@ -493,7 +516,8 @@ let status_typ = (ctx: Ctx.t, expects: typ_expects, ty: Typ.t): status_typ => NotInHole(VariantIncomplete(Arrow(ty_in, ty_variant) |> Typ.temp)) } | ConstructorExpected(_) => InHole(WantConstructorFoundAp) - | TupleExpected => InHole(WantTuple) + | TupleExpected(_) => InHole(WantTuple) + | LabelExpected(_) => InHole(WantLabel) | TypeExpected => InHole(WantTypeFoundAp) } // | Dot(t1, _) => @@ -505,10 +529,33 @@ let status_typ = (ctx: Ctx.t, expects: typ_expects, ty: Typ.t): status_typ => // } // | _ => NotInHole(Type(ty)) // } + | Label(name) => + switch (expects) { + | TypeExpected => NotInHole(Type(ty)) + | TupleExpected(_) => InHole(WantTuple) + | LabelExpected(_, dupes) => + List.exists(l => name == l, dupes) + ? InHole(Duplicate(ty)) : InHole(WantLabel) + | ConstructorExpected(_) + | VariantExpected(_) => InHole(WantConstructorFoundType(ty)) + } + | Prod(_) => + switch (expects) { + | TypeExpected => NotInHole(Type(ty)) + | TupleExpected(status) => + switch (status) { + | Duplicate => InHole(DuplicateLabels(ty)) + | _ => InHole(WantTuple) // shouldn't happen + } + | LabelExpected(_) => InHole(WantLabel) + | ConstructorExpected(_) + | VariantExpected(_) => InHole(WantConstructorFoundType(ty)) + } | _ => switch (expects) { | TypeExpected => NotInHole(Type(ty)) - | TupleExpected => InHole(WantTuple) + | TupleExpected(_) => InHole(WantTuple) + | LabelExpected(_) => InHole(WantLabel) | ConstructorExpected(_) | VariantExpected(_) => InHole(WantConstructorFoundType(ty)) } @@ -571,6 +618,8 @@ let fixed_typ_ok: ok_pat => Typ.t = let fixed_typ_err_common: error_common => Typ.t = fun | NoType(_) => Unknown(Internal) |> Typ.temp + | DuplicateLabels(typ) => typ + | Duplicate(typ) => typ | Inconsistent(Expectation({ana, _})) => ana | Inconsistent(Internal(_)) => Unknown(Internal) |> Typ.temp // Should this be some sort of meet? | Inconsistent(WithArrow(_)) => diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index cece7d2b0b..87d699e552 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -29,7 +29,9 @@ type join_type = type t = | Just(Typ.t) /* Just a regular type */ | NoJoin(join_type, list(Typ.source)) /* Inconsistent types for e.g match, listlits */ - | BadToken(Token.t) /* Invalid expression token, treated as hole */ + | Duplicate_Labels(t) /* Duplicate labels in a labeled tuple, treated as regular type (?) */ + | Duplicate(t) /* Duplicatee label, marked as duplicate */ + | BadToken(Token.t) /* Invalid expression token, continues with undefined behavior */ | BadTrivAp(Typ.t) /* Trivial (nullary) ap on function that doesn't take triv */ | IsMulti /* Multihole, treated as hole */ | IsConstructor({ @@ -71,11 +73,15 @@ let join_of = (j: join_type, ty: Typ.t): Typ.t => let typ_of: (Ctx.t, t) => option(Typ.t) = _ctx => fun - | Just(typ) => Some(typ) + | Just(typ) + | Duplicate_Labels(Just(typ)) + | Duplicate(Just(typ)) => Some(typ) | IsConstructor({syn_ty, _}) => syn_ty | BadToken(_) | BadTrivAp(_) | IsMulti + | Duplicate_Labels(_) + | Duplicate(_) | NoJoin(_) => None; let typ_of_exp: (Ctx.t, exp) => option(Typ.t) = diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index dc7b8b809e..fd13ac8923 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -131,7 +131,7 @@ let rec any_to_info_map = switch (any) { | Exp(e) => let ({co_ctx, _}: Info.exp, m) = - uexp_to_info_map(~ctx, ~ancestors, e, m); + uexp_to_info_map(~ctx, ~ancestors, ~duplicates=[], e, m); (co_ctx, m); | Pat(p) => let m = @@ -139,6 +139,7 @@ let rec any_to_info_map = ~is_synswitch=false, ~co_ctx=CoCtx.empty, ~ancestors, + ~duplicates=[], ~ctx, p, m, @@ -172,6 +173,7 @@ and uexp_to_info_map = ~mode=Mode.Syn, ~is_in_filter=false, ~ancestors, + ~duplicates: list(string), {ids, copied: _, term} as uexp: UExp.t, m: Map.t, ) @@ -219,20 +221,30 @@ and uexp_to_info_map = ~mode=Mode.Syn, ~is_in_filter=is_in_filter, ~ancestors=ancestors, + ~duplicates=[], uexp: UExp.t, m: Map.t, ) => { - uexp_to_info_map(~ctx, ~mode, ~is_in_filter, ~ancestors, uexp, m); + uexp_to_info_map( + ~ctx, + ~mode, + ~is_in_filter, + ~ancestors, + ~duplicates, + uexp, + m, + ); }; let go' = uexp_to_info_map(~ancestors); let go = go'(~ctx); - let map_m_go = m => + let map_m_go = (m, ~duplicates=[]) => List.fold_left2( ((es, m), mode, e) => - go(~mode, e, m) |> (((e, m)) => (es @ [e], m)), + go(~mode, ~duplicates, e, m) |> (((e, m)) => (es @ [e], m)), ([], m), ); - let go_pat = upat_to_info_map(~ctx, ~ancestors); + // TODO: Confirm if duplicates should or not be default [] + let go_pat = upat_to_info_map(~ctx, ~ancestors, ~duplicates); let elaborate_singleton_tuple = (uexp: Exp.t, inner_ty, l, m) => { print_endline("Elaborating singleton tuple"); let (term, rewrap) = UExp.unwrap(uexp); @@ -291,7 +303,10 @@ and uexp_to_info_map = | Int(_) => atomic(Just(Int |> Typ.temp)) | Float(_) => atomic(Just(Float |> Typ.temp)) | String(_) => atomic(Just(String |> Typ.temp)) - | Label(name) => atomic(Just(Label(name) |> Typ.temp)) + | Label(name) => + let self = Self.Just(Label(name) |> Typ.temp); + List.exists(l => name == l, duplicates) + ? atomic(Duplicate(self)) : atomic(self); | ListLit(es) => let ids = List.map(UExp.rep_id, es); let modes = Mode.of_list_lit(ctx, List.length(es), mode); @@ -361,7 +376,7 @@ and uexp_to_info_map = ); | TupLabel(label, e) => let (labmode, mode) = Mode.of_label(ctx, mode); - let (lab, m) = go(~mode=labmode, label, m); + let (lab, m) = go(~mode=labmode, ~duplicates, label, m); let (e, m) = go(~mode, e, m); add( ~self=Just(TupLabel(lab.ty, e.ty) |> Typ.temp), @@ -379,12 +394,14 @@ and uexp_to_info_map = Mode.of_prod(ctx, mode, es, UExp.get_label, (name, b) => TupLabel(Label(name) |> Exp.fresh, b) |> Exp.fresh ); - let (es', m) = map_m_go(m, modes, es); - add( - ~self=Just(Prod(List.map(Info.exp_ty, es')) |> Typ.temp), - ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es')), - m, - ); + let (duplicate_labels, _) = + LabeledTuple.get_duplicate_and_unique_labels(Exp.get_label, es); + let (es', m) = map_m_go(~duplicates=duplicate_labels, m, modes, es); + let ty_list = List.map(Info.exp_ty, es'); + let self = Self.Just(Prod(ty_list) |> Typ.temp); + let self = + List.is_empty(duplicate_labels) ? self : Self.Duplicate_Labels(self); + add(~self, ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es')), m); | Dot(e1, e2) => let (info_e1, m) = go(~mode=Syn, e1, m); let (ty, m) = { @@ -877,6 +894,7 @@ and upat_to_info_map = ~ctx, ~co_ctx, ~ancestors: Info.ancestors, + ~duplicates: list(string), ~mode: Mode.t=Mode.Syn, {ids, term, _} as upat: UPat.t, m: Map.t, @@ -909,6 +927,7 @@ and upat_to_info_map = ~ctx, ~co_ctx, ~ancestors, + ~duplicates=[], ~mode, upat: UPat.t, m: Map.t, @@ -918,6 +937,7 @@ and upat_to_info_map = ~ctx, ~co_ctx, ~ancestors, + ~duplicates, ~mode, upat, m: Map.t, @@ -927,10 +947,10 @@ and upat_to_info_map = let ancestors = [UPat.rep_id(upat)] @ ancestors; let go = upat_to_info_map(~is_synswitch, ~ancestors, ~co_ctx); let unknown = Unknown(is_synswitch ? SynSwitch : Internal) |> Typ.temp; - let ctx_fold = (ctx: Ctx.t, m) => + let ctx_fold = (ctx: Ctx.t, m, ~duplicates=[]) => List.fold_left2( ((ctx, tys, cons, m), e, mode) => - go(~ctx, ~mode, e, m) + go(~ctx, ~mode, ~duplicates, e, m) |> ( ((info, m)) => ( info.ctx, @@ -961,7 +981,12 @@ and upat_to_info_map = ) | String(string) => atomic(Just(String |> Typ.temp), Constraint.String(string)) - | Label(name) => atomic(Just(Label(name) |> Typ.temp), Constraint.Truth) + | Label(name) => + // TODO: Constraint? + let self = Self.Just(Label(name) |> Typ.temp); + List.exists(l => name == l, duplicates) + ? atomic(Duplicate(self), Constraint.Truth) + : atomic(self, Constraint.Truth); | ListLit(ps) => let ids = List.map(UPat.rep_id, ps); let modes = Mode.of_list_lit(ctx, List.length(ps), mode); @@ -1009,7 +1034,7 @@ and upat_to_info_map = ); | TupLabel(label, p) => let (labmode, mode) = Mode.of_label(ctx, mode); - let (lab, m) = go(~ctx, ~mode=labmode, label, m); + let (lab, m) = go(~ctx, ~mode=labmode, ~duplicates, label, m); let (p, m) = go(~ctx, ~mode, p, m); add( ~self=Just(TupLabel(lab.ty, p.ty) |> Typ.temp), @@ -1022,19 +1047,20 @@ and upat_to_info_map = Mode.of_prod(ctx, mode, ps, UPat.get_label, (name, b) => TupLabel(Label(name) |> UPat.fresh, b) |> UPat.fresh ); - 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) |> Typ.temp), - ~ctx, - ~constraint_=cons_fold_tuple(cons), - m, - ); + let (duplicate_labels, _) = + LabeledTuple.get_duplicate_and_unique_labels(Pat.get_label, ps); + let (ctx, tys, cons, m) = + ctx_fold(ctx, m, ~duplicates=duplicate_labels, ps, modes); + let self = Self.Just(Prod(tys) |> Typ.temp); + let self = + List.is_empty(duplicate_labels) ? self : Self.Duplicate_Labels(self); + add(~self, ~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); @@ -1069,10 +1095,11 @@ and utyp_to_info_map = m: Map.t, ) : (Info.typ, Map.t) => { - let add = (~utyp=utyp, m) => { + let add' = (~expects=expects, ~utyp=utyp, m) => { let info = Info.derived_typ(~utyp, ~ctx, ~ancestors, ~expects); (info, add_info(ids, InfoTyp(info), m)); }; + let add = (~utyp=utyp, m) => add'(~utyp, m); let ancestors = [UTyp.rep_id(utyp)] @ ancestors; let go' = utyp_to_info_map(~ctx, ~ancestors); let go = go'(~expects=TypeExpected); @@ -1096,12 +1123,33 @@ and utyp_to_info_map = let m = go(t2, m) |> snd; add(m); | TupLabel(label, t) => - let m = go(label, m) |> snd; + let expects = + switch (expects) { + | LabelExpected(_) => expects + | _ => TypeExpected + }; + let m = go'(~expects, label, m) |> snd; let m = go(t, m) |> snd; - add(m); + add'(~expects=TypeExpected, m); | Prod(ts) => - let m = map_m(go, ts, m) |> snd; - add(m); + // let m = map_m(go, ts, m) |> snd; + // add(m); + let (duplicate_labels, _) = + LabeledTuple.get_duplicate_and_unique_labels(Typ.get_label, ts); + let (expects, m) = + List.is_empty(duplicate_labels) + ? (expects, map_m(go, ts, m) |> snd) + : ( + TupleExpected(Duplicate), + map_m( + go'(~expects=LabelExpected(Duplicate, duplicate_labels)), + ts, + m, + ) + |> snd, + ); + let info = Info.derived_typ(~utyp, ~ctx, ~ancestors, ~expects); + (info, add_info(ids, InfoTyp(info), m)); | Ap(t1, t2) => let t1_mode: Info.typ_expects = switch (expects) { @@ -1224,7 +1272,8 @@ and variant_to_info_map = let mk = Core.Memo.general(~cache_size_bound=1000, (ctx, e) => { - uexp_to_info_map(~ctx, ~ancestors=[], e, Id.Map.empty) |> snd + uexp_to_info_map(~ctx, ~ancestors=[], ~duplicates=[], e, Id.Map.empty) + |> snd }); let mk = (core: CoreSettings.t, ctx, exp) => diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 17e36c9480..6e05fcd762 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -81,6 +81,8 @@ let common_err_view = Type.view(Prod([]) |> Typ.fresh), ] | NoType(FreeConstructor(name)) => [code_err(name), text("not found")] + | DuplicateLabels(_) => [text("Duplicate labels within a tuple")] + | Duplicate(_) => [text("Duplicated Label")] | Inconsistent(WithArrow(typ)) => [ text(":"), Type.view(typ), @@ -188,6 +190,9 @@ let typ_err_view = (ok: Info.error_typ) => | WantConstructorFoundType(_) => [text("Expected a constructor")] | WantTypeFoundAp => [text("Must be part of a sum type")] | WantTuple => [text("Expect a valid tuple")] + | WantLabel => [text("Expect a valid label")] + | DuplicateLabels(_) => [text("Duplicate labels within a tuple")] + | Duplicate(_) => [text("Duplicated Label")] | DuplicateConstructor(name) => [ Type.view(Var(name) |> Typ.fresh), text("already used in this sum"), From 3624020f026223664144f2482eeaec3aceed488b Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 8 Nov 2024 12:35:52 -0500 Subject: [PATCH 093/108] Start elaborating singleton labeled tuple patterns --- src/haz3lcore/statics/Info.re | 3 + src/haz3lcore/statics/Statics.re | 307 +++++++++++++++++++------------ test/Test_Evaluator.re | 26 ++- test/Test_Statics.re | 6 + test/haz3ltest.re | 4 +- 5 files changed, 222 insertions(+), 124 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index e9580b476f..0c0099fd96 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -227,6 +227,7 @@ type pat = { status: status_pat, ty: Typ.t, constraint_: Constraint.t, + lifted_ty: option(Typ.t) /* Type static-level elaboration */ }; [@deriving (show({with_path: false}), sexp, yojson)] @@ -718,6 +719,7 @@ let derived_pat = ~ancestors, ~self, ~constraint_, + ~lifted_ty: option(Typ.t), ) : pat => { let cls = Cls.Pat(UPat.cls_of_term(upat.term)); @@ -736,6 +738,7 @@ let derived_pat = ancestors, term: upat, constraint_, + lifted_ty, }; }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index fd13ac8923..7cad8c4fda 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -246,7 +246,6 @@ and uexp_to_info_map = // TODO: Confirm if duplicates should or not be default [] let go_pat = upat_to_info_map(~ctx, ~ancestors, ~duplicates); let elaborate_singleton_tuple = (uexp: Exp.t, inner_ty, l, m) => { - print_endline("Elaborating singleton tuple"); let (term, rewrap) = UExp.unwrap(uexp); let original_expression = Exp.fresh(term); let (original_info, m) = @@ -769,6 +768,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, + ~lifted_ty=None, ); ( // Override the info for the single upat @@ -900,7 +900,7 @@ and upat_to_info_map = m: Map.t, ) : (Info.pat, Map.t) => { - let add = (~self, ~ctx, ~constraint_, m) => { + let add = (~self, ~ctx, ~constraint_, ~lifted_ty=?, m) => { let prev_synswitch = switch (Id.Map.find_opt(Pat.rep_id(upat), m)) { | Some(Info.InfoPat({mode: Syn | SynFun, ty, _})) => Some(ty) @@ -918,6 +918,7 @@ and upat_to_info_map = ~ancestors, ~self=Common(self), ~constraint_, + ~lifted_ty, ); (info, add_info(ids, InfoPat(info), m)); }; @@ -962,128 +963,192 @@ and upat_to_info_map = (ctx, [], [], m), ); let hole = self => atomic(self, Constraint.Hole); - switch (term) { - | MultiHole(tms) => - let (_, m) = multi(~ctx, ~ancestors, m, tms); - add(~self=IsMulti, ~ctx, ~constraint_=Constraint.Hole, m); - | Invalid(token) => hole(BadToken(token)) - | EmptyHole => hole(Just(unknown)) - | Int(int) => atomic(Just(Int |> Typ.temp), Constraint.Int(int)) - | Float(float) => - atomic(Just(Float |> Typ.temp), Constraint.Float(float)) - | Tuple([]) => atomic(Just(Prod([]) |> Typ.temp), Constraint.Truth) - | Bool(bool) => - atomic( - Just(Bool |> Typ.temp), - bool - ? Constraint.InjL(Constraint.Truth) - : Constraint.InjR(Constraint.Truth), - ) - | String(string) => - atomic(Just(String |> Typ.temp), Constraint.String(string)) - | Label(name) => - // TODO: Constraint? - let self = Self.Just(Label(name) |> Typ.temp); - List.exists(l => name == l, duplicates) - ? atomic(Duplicate(self), Constraint.Truth) - : atomic(self, Constraint.Truth); - | ListLit(ps) => - let ids = List.map(UPat.rep_id, ps); - let modes = Mode.of_list_lit(ctx, List.length(ps), mode); - 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) |> Typ.temp), - ~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) - 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) |> Typ.temp)), + + let elaborate_singleton_tuple = (upat: Pat.t, inner_ty, l, m) => { + print_endline("elaborating singleton tuple: " ++ Pat.show(upat)); + let (term, rewrap) = UPat.unwrap(upat); + let original_expression = Pat.fresh(term); + let (original_info, m) = + upat_to_info_map( + ~ctx, + ~co_ctx, + ~is_synswitch, + ~ancestors, + ~mode=Mode.Ana(inner_ty), + original_expression, + m, ); - let entry = Ctx.VarEntry({name, id: UPat.rep_id(upat), typ: ctx_typ}); - add( - ~self=Just(unknown), - ~ctx=Ctx.extend(ctx, entry), - ~constraint_=Constraint.Truth, - m, - ); - | TupLabel(label, p) => - let (labmode, mode) = Mode.of_label(ctx, mode); - let (lab, m) = go(~ctx, ~mode=labmode, ~duplicates, label, m); - let (p, m) = go(~ctx, ~mode, p, m); - add( - ~self=Just(TupLabel(lab.ty, p.ty) |> Typ.temp), - ~ctx=p.ctx, - ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), - m, - ); - | Tuple(ps) => - let (ps, modes) = - Mode.of_prod(ctx, mode, ps, UPat.get_label, (name, b) => - TupLabel(Label(name) |> UPat.fresh, b) |> UPat.fresh + let elaborated_pat = + rewrap( + Tuple([ + TupLabel(Label(l) |> Pat.fresh, original_expression) |> Pat.fresh, + ]), + ); + let (info, m) = + upat_to_info_map( + ~ctx, + ~co_ctx, + ~is_synswitch, + ~ancestors, + ~mode, + elaborated_pat, + m, + ); + + // We need to keep the original status of the expression to get error messages on the unelaborated expression + let info = { + ...info, + status: original_info.status, + lifted_ty: Some(info.ty), + }; + + (info, add_info(elaborated_pat.ids, InfoPat(info), m)); + }; + + let default_case = () => + switch (term) { + | MultiHole(tms) => + let (_, m) = multi(~ctx, ~ancestors, m, tms); + add(~self=IsMulti, ~ctx, ~constraint_=Constraint.Hole, m); + | Invalid(token) => hole(BadToken(token)) + | EmptyHole => hole(Just(unknown)) + | Int(int) => atomic(Just(Int |> Typ.temp), Constraint.Int(int)) + | Float(float) => + atomic(Just(Float |> Typ.temp), Constraint.Float(float)) + | Tuple([]) => atomic(Just(Prod([]) |> Typ.temp), Constraint.Truth) + | Bool(bool) => + atomic( + Just(Bool |> Typ.temp), + bool + ? Constraint.InjL(Constraint.Truth) + : Constraint.InjR(Constraint.Truth), + ) + | String(string) => + atomic(Just(String |> Typ.temp), Constraint.String(string)) + | Label(name) => + // TODO: Constraint? + let self = Self.Just(Label(name) |> Typ.temp); + List.exists(l => name == l, duplicates) + ? atomic(Duplicate(self), Constraint.Truth) + : atomic(self, Constraint.Truth); + | ListLit(ps) => + let ids = List.map(UPat.rep_id, ps); + let modes = Mode.of_list_lit(ctx, List.length(ps), mode); + 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) |> Typ.temp), + ~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) + 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) |> Typ.temp)), + ); + let entry = Ctx.VarEntry({name, id: UPat.rep_id(upat), typ: ctx_typ}); + add( + ~self=Just(unknown), + ~ctx=Ctx.extend(ctx, entry), + ~constraint_=Constraint.Truth, + m, ); - let rec cons_fold_tuple = cs => - switch (cs) { - | [] => Constraint.Truth - | [elt] => elt - | [hd, ...tl] => Constraint.Pair(hd, cons_fold_tuple(tl)) + | TupLabel(label, p) => + let (labmode, mode) = Mode.of_label(ctx, mode); + let (lab, m) = go(~ctx, ~mode=labmode, ~duplicates, label, m); + let (p, m) = go(~ctx, ~mode, p, m); + add( + ~self=Just(TupLabel(lab.ty, p.ty) |> Typ.temp), + ~ctx=p.ctx, + ~constraint_=Constraint.TupLabel(lab.constraint_, p.constraint_), + m, + ); + | Tuple(ps) => + let (ps, modes) = + Mode.of_prod(ctx, mode, ps, UPat.get_label, (name, b) => + TupLabel(Label(name) |> UPat.fresh, b) |> UPat.fresh + ); + let rec cons_fold_tuple = cs => + switch (cs) { + | [] => Constraint.Truth + | [elt] => elt + | [hd, ...tl] => Constraint.Pair(hd, cons_fold_tuple(tl)) + }; + let (duplicate_labels, _) = + LabeledTuple.get_duplicate_and_unique_labels(Pat.get_label, ps); + let (ctx, tys, cons, m) = + ctx_fold(ctx, m, ~duplicates=duplicate_labels, ps, modes); + let self = Self.Just(Prod(tys) |> Typ.temp); + let self = + List.is_empty(duplicate_labels) ? self : Self.Duplicate_Labels(self); + add(~self, ~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, _) => + 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); + 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, + ); + | Cast(p, ann, _) => + let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); + let (p, m) = go(~ctx, ~mode=Ana(ann.term), p, m); + add(~self=Just(ann.term), ~ctx=p.ctx, ~constraint_=p.constraint_, m); + }; + // This is to allow lifting single values into a singleton labeled tuple when the label is not present + + print_endline("upat_to_info_map: " ++ UPat.show(upat)); + print_endline("mode: " ++ Mode.show(mode)); + switch (mode) { + | Ana(ty) => + switch (Typ.weak_head_normalize(ctx, ty).term) { + | Prod([{term: TupLabel({term: Label(l1), _}, ana_ty), _}]) => + // We can flatten this by pulling it up on the case match but since OCaml is strict it'll be evaluated. + // So for performance reasons we'll just do it here. + let (e, m) = go(~mode=Mode.Syn, ~ctx, upat, m); + + switch (Typ.weak_head_normalize(ctx, e.ty).term) { + | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) when l1 == l2 => + default_case() + | _ => elaborate_singleton_tuple(upat, ana_ty, l1, m) }; - let (duplicate_labels, _) = - LabeledTuple.get_duplicate_and_unique_labels(Pat.get_label, ps); - let (ctx, tys, cons, m) = - ctx_fold(ctx, m, ~duplicates=duplicate_labels, ps, modes); - let self = Self.Just(Prod(tys) |> Typ.temp); - let self = - List.is_empty(duplicate_labels) ? self : Self.Duplicate_Labels(self); - add(~self, ~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, _) => - 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); - 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, - ); - | Cast(p, ann, _) => - let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); - let (p, m) = go(~ctx, ~mode=Ana(ann.term), p, m); - add(~self=Just(ann.term), ~ctx=p.ctx, ~constraint_=p.constraint_, m); + | _ => default_case() + } + | _ => default_case() }; } and utyp_to_info_map = diff --git a/test/Test_Evaluator.re b/test/Test_Evaluator.re index 23aaf3cd77..58f4a46fec 100644 --- a/test/Test_Evaluator.re +++ b/test/Test_Evaluator.re @@ -11,7 +11,11 @@ let evaluation_test = (msg, expected, unevaluated) => snd(Evaluator.evaluate(Builtins.env_init, {d: unevaluated})), ), ); - +let parse_exp = (s: string) => + MakeTerm.from_zip_for_sem(Option.get(Printer.zipper_of_string(s))).term; +let dhexp_of_uexp = u => + Elaborator.elaborate(Statics.mk(CoreSettings.on, Builtins.ctx_init, u), u) + |> fst; let test_int = () => evaluation_test("8", Int(8) |> Exp.fresh, Int(8) |> Exp.fresh); @@ -196,4 +200,24 @@ let tests = [ test_case("Function application", `Quick, test_function_application), test_case("Function deferral", `Quick, test_function_deferral), test_case("Deferral applied to hole", `Quick, tet_ap_of_hole_deferral), + test_case("Elaborated Pattern for labeled tuple", `Quick, () => + check( + dhexp_typ, + {|let x : (a=Int) -> Int = fun a -> a in x(2)|}, + Int(2) |> Exp.fresh, + Evaluator.Result.unbox( + snd( + Evaluator.evaluate( + Builtins.env_init, + { + d: + dhexp_of_uexp( + parse_exp("let x : (a=Int) -> Int = fun a -> a in x(2)"), + ), + }, + ), + ), + ), + ) + ), ]; diff --git a/test/Test_Statics.re b/test/Test_Statics.re index f1eedd487a..59ba23283e 100644 --- a/test/Test_Statics.re +++ b/test/Test_Statics.re @@ -677,4 +677,10 @@ let tests = ) |> Exp.fresh, ), + fully_consistent_typecheck( + "Singleton labeled argument not labeled in pattern", + {|let x : (a=Int) -> Int = fun a -> a in x(2)|}, + Some(int), + parse_exp("let x : (a=Int) -> Int = fun a -> a in x(2)"), + ), ]; diff --git a/test/haz3ltest.re b/test/haz3ltest.re index 15c226f73d..b9cbea0c0a 100644 --- a/test/haz3ltest.re +++ b/test/haz3ltest.re @@ -5,12 +5,12 @@ let (suite, _) = ~and_exit=false, "HazelTests", [ - ("Elaboration", Test_Elaboration.elaboration_tests), + ("MakeTerm", Test_MakeTerm.tests), ("LabeledTuple", Test_LabeledTuple.tests), ("Statics", Test_Statics.tests), + ("Elaboration", Test_Elaboration.elaboration_tests), ("Evaluator", Test_Evaluator.tests), Test_ListUtil.tests, - ("MakeTerm", Test_MakeTerm.tests), ], ); Junit.to_file(Junit.make([suite]), "junit_tests.xml"); From ecbd7cef11f0ce9a526284d8f1e663a3d8bb4f22 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 15 Nov 2024 12:27:02 -0500 Subject: [PATCH 094/108] Singleton labeled tuple pattern elaboration disabled under ascription --- src/haz3lcore/dynamics/Elaborator.re | 13 +++++--- src/haz3lcore/statics/Statics.re | 48 +++++++++++++++++----------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 7f7f3c84ed..2a8a2cce91 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -76,14 +76,16 @@ let elaborated_type = (elab_ty |> Typ.normalize(ctx), ctx, co_ctx, term); }; -let elaborated_pat_type = (m: Statics.Map.t, upat: UPat.t): (Typ.t, Ctx.t) => { - let (mode, self_ty, ctx, prev_synswitch) = +let elaborated_pat_type = + (m: Statics.Map.t, upat: UPat.t): (Typ.t, Ctx.t, Pat.t) => { + let (mode, self_ty, ctx, prev_synswitch, term) = switch (Id.Map.find_opt(UPat.rep_id(upat), m)) { - | Some(Info.InfoPat({mode, ty, ctx, prev_synswitch, _})) => ( + | Some(Info.InfoPat({mode, ty, ctx, prev_synswitch, term, _})) => ( mode, ty, ctx, prev_synswitch, + term, ) | _ => raise(MissingTypeInfo) }; @@ -103,13 +105,14 @@ let elaborated_pat_type = (m: Statics.Map.t, upat: UPat.t): (Typ.t, Ctx.t) => { | Some(syn_ty) => Typ.match_synswitch(syn_ty, ana_ty) } }; - (elab_ty |> Typ.normalize(ctx), ctx); + (elab_ty |> Typ.normalize(ctx), ctx, term); }; let rec elaborate_pattern = (m: Statics.Map.t, upat: UPat.t, in_container: bool) : (DHPat.t, Typ.t) => { - let (elaborated_type, ctx) = elaborated_pat_type(m, upat); + // Pulling upat back out of the statics map for statics level elaboration + let (elaborated_type, ctx, upat) = elaborated_pat_type(m, upat); let elaborate_pattern = (~in_container=false, m, upat) => elaborate_pattern(m, upat, in_container); let cast_from = (ty, exp) => fresh_pat_cast(exp, ty, elaborated_type); diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 7cad8c4fda..4b8f883489 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -896,6 +896,7 @@ and upat_to_info_map = ~ancestors: Info.ancestors, ~duplicates: list(string), ~mode: Mode.t=Mode.Syn, + ~under_ascription: bool=false, {ids, term, _} as upat: UPat.t, m: Map.t, ) @@ -930,6 +931,7 @@ and upat_to_info_map = ~ancestors, ~duplicates=[], ~mode, + ~under_ascription=false, upat: UPat.t, m: Map.t, ) => { @@ -940,13 +942,15 @@ and upat_to_info_map = ~ancestors, ~duplicates, ~mode, + ~under_ascription, upat, m: Map.t, ); }; 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, ~co_ctx); + let go = (~under_ascription=false) => + upat_to_info_map(~under_ascription, ~is_synswitch, ~ancestors, ~co_ctx); let unknown = Unknown(is_synswitch ? SynSwitch : Internal) |> Typ.temp; let ctx_fold = (ctx: Ctx.t, m, ~duplicates=[]) => List.fold_left2( @@ -1126,29 +1130,37 @@ and upat_to_info_map = ); | Cast(p, ann, _) => let (ann, m) = utyp_to_info_map(~ctx, ~ancestors, ann, m); - let (p, m) = go(~ctx, ~mode=Ana(ann.term), p, m); + let (p, m) = + go(~ctx, ~under_ascription=true, ~mode=Ana(ann.term), p, m); add(~self=Just(ann.term), ~ctx=p.ctx, ~constraint_=p.constraint_, m); }; // This is to allow lifting single values into a singleton labeled tuple when the label is not present - print_endline("upat_to_info_map: " ++ UPat.show(upat)); - print_endline("mode: " ++ Mode.show(mode)); - switch (mode) { - | Ana(ty) => - switch (Typ.weak_head_normalize(ctx, ty).term) { - | Prod([{term: TupLabel({term: Label(l1), _}, ana_ty), _}]) => - // We can flatten this by pulling it up on the case match but since OCaml is strict it'll be evaluated. - // So for performance reasons we'll just do it here. - let (e, m) = go(~mode=Mode.Syn, ~ctx, upat, m); + // print_endline("upat_to_info_map: " ++ UPat.show(upat)); + // print_endline("mode: " ++ Mode.show(mode)); + print_endline("updat.term" ++ UPat.show(upat)); + print_endline("under ascription: " ++ string_of_bool(under_ascription)); + if (under_ascription) { + default_case(); + } else { + switch (mode) { + | Ana(ty) => + switch (Typ.weak_head_normalize(ctx, ty).term) { + | Prod([{term: TupLabel({term: Label(l1), _}, ana_ty), _}]) => + // We can flatten this by pulling it up on the case match but since OCaml is strict it'll be evaluated. + // So for performance reasons we'll just do it here. + let (e, m) = go(~mode=Mode.Syn, ~ctx, upat, m); - switch (Typ.weak_head_normalize(ctx, e.ty).term) { - | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) when l1 == l2 => - default_case() - | _ => elaborate_singleton_tuple(upat, ana_ty, l1, m) - }; + switch (Typ.weak_head_normalize(ctx, e.ty).term) { + | Prod([{term: TupLabel({term: Label(l2), _}, _), _}]) + when l1 == l2 => + default_case() + | _ => elaborate_singleton_tuple(upat, ana_ty, l1, m) + }; + | _ => default_case() + } | _ => default_case() - } - | _ => default_case() + }; }; } and utyp_to_info_map = From 24de2fad4d8b826f1cc99b0b53f82c1f056d4d39 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 15 Nov 2024 14:16:41 -0500 Subject: [PATCH 095/108] Fix assertions --- test/Test_Elaboration.re | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 746886d180..3b6b28e077 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -599,7 +599,7 @@ let elaboration_tests = [ `Quick, () => alco_check( - {|(fun a=x->x)(a=1)|}, + {|(fun a=(x:Int) -> x)(a=1)|}, Ap( Forward, Fun( @@ -620,7 +620,7 @@ let elaboration_tests = [ |> Exp.fresh, ) |> Exp.fresh, - dhexp_of_uexp(parse_exp({|(fun a=(x:Int) -> x)(a=1)|})), + dhexp_of_uexp(parse_exp({|(fun a=(x:Int) -> x)(a=1)|})) // Ignoring casts for now ) ), test_case( @@ -628,7 +628,7 @@ let elaboration_tests = [ `Quick, () => alco_check( - {|(fun a=x->x)(a=1)|}, + {|(fun a=(x:Int) -> x)(1)|}, Ap( Forward, Fun( From 58029ad04a8a601559bd2bec6eeacc94f1504434 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 15 Nov 2024 14:17:33 -0500 Subject: [PATCH 096/108] Stop debugging --- src/haz3lcore/statics/Statics.re | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 4b8f883489..9ef569e05f 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -1134,12 +1134,8 @@ and upat_to_info_map = go(~ctx, ~under_ascription=true, ~mode=Ana(ann.term), p, m); add(~self=Just(ann.term), ~ctx=p.ctx, ~constraint_=p.constraint_, m); }; - // This is to allow lifting single values into a singleton labeled tuple when the label is not present - // print_endline("upat_to_info_map: " ++ UPat.show(upat)); - // print_endline("mode: " ++ Mode.show(mode)); - print_endline("updat.term" ++ UPat.show(upat)); - print_endline("under ascription: " ++ string_of_bool(under_ascription)); + // This is to allow lifting single values into a singleton labeled tuple when the label is not present if (under_ascription) { default_case(); } else { From 69fb726f5aa569e8bf174c5ed5b5ae007b82becb Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 15 Nov 2024 14:18:24 -0500 Subject: [PATCH 097/108] Remove unnecessary module name --- src/haz3lcore/dynamics/EvalCtx.re | 216 +++++++++++++++--------------- 1 file changed, 107 insertions(+), 109 deletions(-) diff --git a/src/haz3lcore/dynamics/EvalCtx.re b/src/haz3lcore/dynamics/EvalCtx.re index 7ffe95e5e9..fb238fbcc8 100644 --- a/src/haz3lcore/dynamics/EvalCtx.re +++ b/src/haz3lcore/dynamics/EvalCtx.re @@ -54,114 +54,112 @@ let rec compose = (ctx: t, d: DHExp.t): DHExp.t => { | Mark => d | Term({term, ids}) => let wrap = DHExp.mk(ids); - DHExp.( - switch (term) { - | Closure(env, ctx) => - let d = compose(ctx, d); - Closure(env, d) |> wrap; - | Filter(flt, ctx) => - let d = compose(ctx, d); - Filter(flt, d) |> wrap; - | Seq1(ctx, d2) => - let d1 = compose(ctx, d); - Seq(d1, d2) |> wrap; - | Seq2(d1, ctx) => - let d2 = compose(ctx, d); - Seq(d1, d2) |> wrap; - | Ap1(dir, ctx, d2) => - let d1 = compose(ctx, d); - Ap(dir, d1, d2) |> wrap; - | Ap2(dir, d1, ctx) => - let d2 = compose(ctx, d); - Ap(dir, d1, d2) |> wrap; - | DeferredAp1(ctx, d2s) => - let d1 = compose(ctx, d); - DeferredAp(d1, d2s) |> wrap; - | DeferredAp2(d1, ctx, (ld, rd)) => - let d2 = compose(ctx, d); - DeferredAp(d1, ListUtil.rev_concat(ld, [d2, ...rd])) |> wrap; - | If1(ctx, d2, d3) => - let d' = compose(ctx, d); - If(d', d2, d3) |> wrap; - | If2(d1, ctx, d3) => - let d' = compose(ctx, d); - If(d1, d', d3) |> wrap; - | If3(d1, d2, ctx) => - let d' = compose(ctx, d); - If(d1, d2, d') |> wrap; - | Test(ctx) => - let d1 = compose(ctx, d); - Test(d1) |> wrap; - | UnOp(op, ctx) => - let d1 = compose(ctx, d); - UnOp(op, d1) |> wrap; - | BinOp1(op, ctx, d2) => - let d1 = compose(ctx, d); - BinOp(op, d1, d2) |> wrap; - | BinOp2(op, d1, ctx) => - let d2 = compose(ctx, d); - BinOp(op, d1, d2) |> wrap; - | Cons1(ctx, d2) => - let d1 = compose(ctx, d); - Cons(d1, d2) |> wrap; - | Cons2(d1, ctx) => - let d2 = compose(ctx, d); - Cons(d1, d2) |> wrap; - | ListConcat1(ctx, d2) => - let d1 = compose(ctx, d); - ListConcat(d1, d2) |> wrap; - | ListConcat2(d1, ctx) => - let d2 = compose(ctx, d); - ListConcat(d1, d2) |> wrap; - | TupLabel(label, ctx) => - let d = compose(ctx, d); - TupLabel(label, d) |> wrap; - | Dot1(ctx, d2) => - let d1 = compose(ctx, d); - Dot(d1, d2) |> wrap; - | Dot2(d1, ctx) => - let d2 = compose(ctx, d); - Dot(d1, d2) |> wrap; - | Tuple(ctx, (ld, rd)) => - let d = compose(ctx, d); - Tuple(ListUtil.rev_concat(ld, [d, ...rd])) |> wrap; - | ListLit(ctx, (ld, rd)) => - let d = compose(ctx, d); - ListLit(ListUtil.rev_concat(ld, [d, ...rd])) |> wrap; - | MultiHole(ctx, (ld, rd)) => - let d = compose(ctx, d); - MultiHole(ListUtil.rev_concat(ld, [Exp(d), ...rd])) |> wrap; - | Let1(dp, ctx, d2) => - let d = compose(ctx, d); - Let(dp, d, d2) |> wrap; - | Let2(dp, d1, ctx) => - let d = compose(ctx, d); - Let(dp, d1, d) |> wrap; - | Fun(dp, ctx, env, v) => - let d = compose(ctx, d); - Fun(dp, d, env, v) |> wrap; - | FixF(v, ctx, env) => - let d = compose(ctx, d); - FixF(v, d, env) |> wrap; - | Cast(ctx, ty1, ty2) => - let d = compose(ctx, d); - Cast(d, ty1, ty2) |> wrap; - | FailedCast(ctx, ty1, ty2) => - let d = compose(ctx, d); - FailedCast(d, ty1, ty2) |> wrap; - | DynamicErrorHole(ctx, err) => - let d = compose(ctx, d); - DynamicErrorHole(d, err) |> wrap; - | MatchScrut(ctx, rules) => - let d = compose(ctx, d); - Match(d, rules) |> wrap; - | MatchRule(scr, p, ctx, (lr, rr)) => - let d = compose(ctx, d); - Match(scr, ListUtil.rev_concat(lr, [(p, d), ...rr])) |> wrap; - | TypAp(ctx, ty) => - let d = compose(ctx, d); - TypAp(d, ty) |> wrap; - } - ); + switch (term) { + | Closure(env, ctx) => + let d = compose(ctx, d); + Closure(env, d) |> wrap; + | Filter(flt, ctx) => + let d = compose(ctx, d); + Filter(flt, d) |> wrap; + | Seq1(ctx, d2) => + let d1 = compose(ctx, d); + Seq(d1, d2) |> wrap; + | Seq2(d1, ctx) => + let d2 = compose(ctx, d); + Seq(d1, d2) |> wrap; + | Ap1(dir, ctx, d2) => + let d1 = compose(ctx, d); + Ap(dir, d1, d2) |> wrap; + | Ap2(dir, d1, ctx) => + let d2 = compose(ctx, d); + Ap(dir, d1, d2) |> wrap; + | DeferredAp1(ctx, d2s) => + let d1 = compose(ctx, d); + DeferredAp(d1, d2s) |> wrap; + | DeferredAp2(d1, ctx, (ld, rd)) => + let d2 = compose(ctx, d); + DeferredAp(d1, ListUtil.rev_concat(ld, [d2, ...rd])) |> wrap; + | If1(ctx, d2, d3) => + let d' = compose(ctx, d); + If(d', d2, d3) |> wrap; + | If2(d1, ctx, d3) => + let d' = compose(ctx, d); + If(d1, d', d3) |> wrap; + | If3(d1, d2, ctx) => + let d' = compose(ctx, d); + If(d1, d2, d') |> wrap; + | Test(ctx) => + let d1 = compose(ctx, d); + Test(d1) |> wrap; + | UnOp(op, ctx) => + let d1 = compose(ctx, d); + UnOp(op, d1) |> wrap; + | BinOp1(op, ctx, d2) => + let d1 = compose(ctx, d); + BinOp(op, d1, d2) |> wrap; + | BinOp2(op, d1, ctx) => + let d2 = compose(ctx, d); + BinOp(op, d1, d2) |> wrap; + | Cons1(ctx, d2) => + let d1 = compose(ctx, d); + Cons(d1, d2) |> wrap; + | Cons2(d1, ctx) => + let d2 = compose(ctx, d); + Cons(d1, d2) |> wrap; + | ListConcat1(ctx, d2) => + let d1 = compose(ctx, d); + ListConcat(d1, d2) |> wrap; + | ListConcat2(d1, ctx) => + let d2 = compose(ctx, d); + ListConcat(d1, d2) |> wrap; + | TupLabel(label, ctx) => + let d = compose(ctx, d); + TupLabel(label, d) |> wrap; + | Dot1(ctx, d2) => + let d1 = compose(ctx, d); + Dot(d1, d2) |> wrap; + | Dot2(d1, ctx) => + let d2 = compose(ctx, d); + Dot(d1, d2) |> wrap; + | Tuple(ctx, (ld, rd)) => + let d = compose(ctx, d); + Tuple(ListUtil.rev_concat(ld, [d, ...rd])) |> wrap; + | ListLit(ctx, (ld, rd)) => + let d = compose(ctx, d); + ListLit(ListUtil.rev_concat(ld, [d, ...rd])) |> wrap; + | MultiHole(ctx, (ld, rd)) => + let d = compose(ctx, d); + MultiHole(ListUtil.rev_concat(ld, [Exp(d), ...rd])) |> wrap; + | Let1(dp, ctx, d2) => + let d = compose(ctx, d); + Let(dp, d, d2) |> wrap; + | Let2(dp, d1, ctx) => + let d = compose(ctx, d); + Let(dp, d1, d) |> wrap; + | Fun(dp, ctx, env, v) => + let d = compose(ctx, d); + Fun(dp, d, env, v) |> wrap; + | FixF(v, ctx, env) => + let d = compose(ctx, d); + FixF(v, d, env) |> wrap; + | Cast(ctx, ty1, ty2) => + let d = compose(ctx, d); + Cast(d, ty1, ty2) |> wrap; + | FailedCast(ctx, ty1, ty2) => + let d = compose(ctx, d); + FailedCast(d, ty1, ty2) |> wrap; + | DynamicErrorHole(ctx, err) => + let d = compose(ctx, d); + DynamicErrorHole(d, err) |> wrap; + | MatchScrut(ctx, rules) => + let d = compose(ctx, d); + Match(d, rules) |> wrap; + | MatchRule(scr, p, ctx, (lr, rr)) => + let d = compose(ctx, d); + Match(scr, ListUtil.rev_concat(lr, [(p, d), ...rr])) |> wrap; + | TypAp(ctx, ty) => + let d = compose(ctx, d); + TypAp(d, ty) |> wrap; + }; }; }; From 4a78f89b6ce3c4da8638da9cfea8d76377ef3bf7 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Fri, 15 Nov 2024 15:17:12 -0500 Subject: [PATCH 098/108] Fix tests and strip casts out of some of the tests --- test/Test_Elaboration.re | 78 +++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/test/Test_Elaboration.re b/test/Test_Elaboration.re index 3b6b28e077..daf513d109 100644 --- a/test/Test_Elaboration.re +++ b/test/Test_Elaboration.re @@ -13,6 +13,42 @@ let alco_check = dhexp_typ |> Alcotest.check; let parse_exp = (s: string) => MakeTerm.from_zip_for_sem(Option.get(Printer.zipper_of_string(s))).term; +let rec strip_casts = (e: Exp.t): Exp.t => { + print_endline("Stripping casts: " ++ Exp.show(e)); + Exp.map_term( + ~f_pat= + (fn, t) => + switch (t.term) { + | Cast(e, _, _) => strip_casts_pat(e) + | _ => fn(t) + }, + ~f_exp= + (fn: Exp.t => Exp.t, t: Exp.t) => + switch (t.term) { + | Cast(e, _, _) => strip_casts(e) + | _ => fn(t) + }, + e, + ); +} +and strip_casts_pat = (p: Pat.t): Pat.t => { + print_endline("Stripping casts: " ++ Pat.show(p)); + Pat.map_term( + ~f_pat= + (fn, t) => + switch (t.term) { + | Cast(e, _, _) => fn(e) + | _ => fn(t) + }, + ~f_exp= + (fn: Exp.t => Exp.t, t: Exp.t) => + switch (t.term) { + | Cast(e, _, _) => strip_casts(e) + | _ => fn(t) + }, + p, + ); +}; let u1: Exp.t = {ids: [id_at(0)], term: Int(8), copied: false}; let single_integer = () => alco_check("Integer literal 8", u1, dhexp_of_uexp(u1)); @@ -286,20 +322,38 @@ let ap_of_deferral_of_hole = () => ], ) |> Exp.fresh, - Tuple([ + Cast( Cast( - Float(1.) |> Exp.fresh, - Float |> Typ.fresh, - Unknown(Internal) |> Typ.fresh, + Tuple([ + Cast( + Float(1.) |> Exp.fresh, + Float |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Exp.fresh, + Cast( + Bool(true) |> Exp.fresh, + Bool |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ) + |> Exp.fresh, + ]) + |> Exp.fresh, + Prod([ + Unknown(Internal) |> Typ.fresh, + Unknown(Internal) |> Typ.fresh, + ]) + |> Typ.fresh, + Prod([Float |> Typ.fresh, Bool |> Typ.fresh]) |> Typ.fresh, ) |> Exp.fresh, - Cast( - Bool(true) |> Exp.fresh, - Bool |> Typ.fresh, + Prod([Float |> Typ.fresh, Bool |> Typ.fresh]) |> Typ.fresh, + Prod([ Unknown(Internal) |> Typ.fresh, - ) - |> Exp.fresh, - ]) + Unknown(Internal) |> Typ.fresh, + ]) + |> Typ.fresh, + ) |> Exp.fresh, ) |> Exp.fresh, @@ -725,7 +779,7 @@ let elaboration_tests = [ |> Exp.fresh, ) |> Exp.fresh, - dhexp_of_uexp(parse_exp({|(fun a=x->x)(a=1)|})), + strip_casts(dhexp_of_uexp(parse_exp({|(fun a=x->x)(a=1)|}))), ) ), test_case("Singleton labeled argument let with unknown type", `Quick, () => @@ -741,7 +795,7 @@ let elaboration_tests = [ Var("x") |> Exp.fresh, ) |> Exp.fresh, - dhexp_of_uexp(parse_exp({|let x : (a=?) = (a=1) in x|})), + strip_casts(dhexp_of_uexp(parse_exp({|let x : (a=?) = (a=1) in x|}))) // Ignoring casts for now ) ), test_case( From 30e3b9c33aeaf31b2f29997a8eaf7c7738b522d3 Mon Sep 17 00:00:00 2001 From: WondAli Date: Sun, 17 Nov 2024 19:11:44 -0500 Subject: [PATCH 099/108] Bugfix: statics now check that the first argument in a TupLabel is a Label --- hazel.opam | 1 + src/haz3lcore/LabeledTuple.re | 11 +++++++++++ src/haz3lcore/dynamics/PatternMatch.re | 3 ++- src/haz3lcore/lang/term/Typ.re | 14 +++++++------- src/haz3lcore/statics/Info.re | 3 ++- src/haz3lcore/statics/MakeTerm.re | 6 ++++-- src/haz3lcore/statics/Mode.re | 3 ++- src/haz3lcore/statics/Self.re | 2 +- src/haz3lcore/statics/Statics.re | 6 +++--- src/haz3lcore/statics/TermBase.re | 3 ++- src/haz3lweb/view/Type.re | 2 +- 11 files changed, 36 insertions(+), 18 deletions(-) diff --git a/hazel.opam b/hazel.opam index 09ee887ab3..6f43cbbd17 100644 --- a/hazel.opam +++ b/hazel.opam @@ -14,6 +14,7 @@ depends: [ "reason" {>= "3.12.0"} "ppx_yojson_conv_lib" "ppx_yojson_conv" + "incr_dom" "bisect_ppx" "omd" {>= "2.0.0~alpha4"} "ezjs_idb" diff --git a/src/haz3lcore/LabeledTuple.re b/src/haz3lcore/LabeledTuple.re index a4ac9a667e..9c9b150b89 100644 --- a/src/haz3lcore/LabeledTuple.re +++ b/src/haz3lcore/LabeledTuple.re @@ -13,6 +13,17 @@ let equal: (option((label, 'a)), option((label, 'b))) => bool = }; }; +// This function should only be used for type checking labels +let match_labels: (label, label) => bool = + (label1, label2) => { + switch (label1, label2) { + // Empty label is a placeholder for checking any label + | ("", _) + | (_, "") => true + | (_, _) => label1 == label2 + }; + }; + let length = String.length; let compare = String.compare; diff --git a/src/haz3lcore/dynamics/PatternMatch.re b/src/haz3lcore/dynamics/PatternMatch.re index bf72b024fc..fd02b443af 100644 --- a/src/haz3lcore/dynamics/PatternMatch.re +++ b/src/haz3lcore/dynamics/PatternMatch.re @@ -32,7 +32,8 @@ let rec matches = (dp: Pat.t, d: DHExp.t): match_result => s == s' ? Matches(Environment.empty) : DoesNotMatch; | Label(name) => let* name' = Unboxing.unbox(Label, d); - name == name' ? Matches(Environment.empty) : DoesNotMatch; + LabeledTuple.match_labels(name, name') + ? Matches(Environment.empty) : DoesNotMatch; | TupLabel(_, x) => let* x' = Unboxing.unbox(TupLabel(dp), d); matches(x, x'); diff --git a/src/haz3lcore/lang/term/Typ.re b/src/haz3lcore/lang/term/Typ.re index 8c5f55096c..9528a611cd 100644 --- a/src/haz3lcore/lang/term/Typ.re +++ b/src/haz3lcore/lang/term/Typ.re @@ -289,7 +289,10 @@ let rec join = (~resolve=false, ~fix, ctx: Ctx.t, ty1: t, ty2: t): option(t) => | (Bool, _) => None | (String, String) => Some(ty1) | (String, _) => None - | (Label(name1), Label(name2)) when String.equal(name1, name2) => + | (Label(_), Label("")) => Some(ty1) + | (Label(""), Label(_)) => Some(ty2) + | (Label(name1), Label(name2)) + when LabeledTuple.match_labels(name1, name2) => Some(ty1) | (Label(_), _) => None | (Arrow(ty1, ty2), Arrow(ty1', ty2')) => @@ -457,13 +460,10 @@ let matched_label = (ctx, ty) => | Prod([ty]) => switch (term_of(weak_head_normalize(ctx, ty))) { | TupLabel(lab, ty) => (lab, ty) - | _ => (Unknown(Internal) |> temp, ty) + | _ => (Label("") |> temp, ty) // Empty label is a placeholder for checking any label } - | Unknown(SynSwitch) => ( - Unknown(SynSwitch) |> temp, - Unknown(SynSwitch) |> temp, - ) - | _ => (Unknown(Internal) |> temp, ty) + | Unknown(SynSwitch) => (Label("") |> temp, Unknown(SynSwitch) |> temp) + | _ => (Label("") |> temp, ty) }; let rec get_labels = (ctx, ty): list(option(string)) => { diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 0c0099fd96..0f31fc3e5b 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -534,7 +534,8 @@ let status_typ = (ctx: Ctx.t, expects: typ_expects, ty: Typ.t): status_typ => switch (expects) { | TypeExpected => NotInHole(Type(ty)) | TupleExpected(_) => InHole(WantTuple) - | LabelExpected(_, dupes) => + | LabelExpected(Unique, _) => NotInHole(Type(ty)) + | LabelExpected(Duplicate, dupes) => List.exists(l => name == l, dupes) ? InHole(Duplicate(ty)) : InHole(WantLabel) | ConstructorExpected(_) diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index b72a632ab3..ed62a19fd8 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -327,7 +327,8 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { | (["="], []) => // TODO (Anthony): Other cases to convert to string switch (l.term) { - | String(name) + // | String(name) + // Currently not allowing Strings to prevent empty Labels | Var(name) => Tuple([ TupLabel( @@ -422,7 +423,8 @@ and pat_term: unsorted => (UPat.term, list(Id.t)) = { | ([(_id, (["="], []))], []) => // TODO (Anthony): Other cases to convert to string switch (l.term) { - | String(name) + // | String(name) + // Currently not allowing Strings to prevent empty Labels | Var(name) => ret( Tuple([ diff --git a/src/haz3lcore/statics/Mode.re b/src/haz3lcore/statics/Mode.re index ee5573928e..d336a76c4a 100644 --- a/src/haz3lcore/statics/Mode.re +++ b/src/haz3lcore/statics/Mode.re @@ -60,11 +60,12 @@ let of_forall = (ctx: Ctx.t, name_opt: option(string), mode: t): t => }; }; +// Empty label is a placeholder for checking any label let of_label = (ctx: Ctx.t, mode: t): (t, t) => switch (mode) { | Syn | SynFun - | SynTypFun => (Syn, Syn) + | SynTypFun => (Ana(Label("") |> Typ.temp), Syn) | Ana(ty) => let (ty1, ty2) = Typ.matched_label(ctx, ty); (ana(ty1), ana(ty2)); diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index 87d699e552..824a0fc905 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -30,7 +30,7 @@ type t = | Just(Typ.t) /* Just a regular type */ | NoJoin(join_type, list(Typ.source)) /* Inconsistent types for e.g match, listlits */ | Duplicate_Labels(t) /* Duplicate labels in a labeled tuple, treated as regular type (?) */ - | Duplicate(t) /* Duplicatee label, marked as duplicate */ + | Duplicate(t) /* Duplicate label, marked as duplicate */ | BadToken(Token.t) /* Invalid expression token, continues with undefined behavior */ | BadTrivAp(Typ.t) /* Trivial (nullary) ap on function that doesn't take triv */ | IsMulti /* Multihole, treated as hole */ diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 9ef569e05f..e95840f387 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -1196,12 +1196,12 @@ and utyp_to_info_map = let m = go(t2, m) |> snd; add(m); | TupLabel(label, t) => - let expects = + let expects_label = switch (expects) { | LabelExpected(_) => expects - | _ => TypeExpected + | _ => LabelExpected(Unique, []) }; - let m = go'(~expects, label, m) |> snd; + let m = go'(~expects=expects_label, label, m) |> snd; let m = go(t, m) |> snd; add'(~expects=TypeExpected, m); | Prod(ts) => diff --git a/src/haz3lcore/statics/TermBase.re b/src/haz3lcore/statics/TermBase.re index 1b90948f9f..d3dcc199ac 100644 --- a/src/haz3lcore/statics/TermBase.re +++ b/src/haz3lcore/statics/TermBase.re @@ -752,7 +752,8 @@ and Typ: { | (Bool, _) => false | (String, String) => true | (String, _) => false - | (Label(name1), Label(name2)) => String.equal(name1, name2) + | (Label(name1), Label(name2)) => + LabeledTuple.match_labels(name1, name2) | (Label(_), _) => false | (Ap(t1, t2), Ap(t1', t2')) => eq_internal(n, t1, t1') && eq_internal(n, t2, t2') diff --git a/src/haz3lweb/view/Type.re b/src/haz3lweb/view/Type.re index 7563e68e55..0e30fbe673 100644 --- a/src/haz3lweb/view/Type.re +++ b/src/haz3lweb/view/Type.re @@ -29,7 +29,7 @@ let rec view_ty = (~strip_outer_parens=false, ty: Haz3lcore.Typ.t): Node.t => | Int => ty_view("Int", "Int") | Float => ty_view("Float", "Float") | String => ty_view("String", "String") - | Label(name) => ty_view("Label", name) + | Label(_) => ty_view("Label", "Label") | Bool => ty_view("Bool", "Bool") | Var(name) => ty_view("Var", name) | TupLabel({term: Label(l), _}, ty) => From 552938392fc780fe6df5c707a1e937887b7d20ef Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 18 Nov 2024 10:28:06 -0500 Subject: [PATCH 100/108] Progress on improving cursor inspector for automatic labelling --- src/haz3lcore/statics/Statics.re | 7 ++- src/haz3lweb/view/CursorInspector.re | 84 +++++++++++++++++++++------- 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index e95840f387..0bb12f77b1 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -184,7 +184,8 @@ and uexp_to_info_map = | Ana({term: Unknown(SynSwitch), _}) => Mode.Syn | _ => mode }; - let add' = (~lifted_ty=?, ~self, ~co_ctx, m) => { + let add' = + (~lifted_ty=?, ~unelaborated_info=?, ~sugar_info=?, ~self, ~co_ctx, m) => { let info = Info.derived_exp( ~uexp, @@ -194,6 +195,8 @@ and uexp_to_info_map = ~self, ~co_ctx, ~lifted_ty, + ~unelaborated_info, + ~sugar_info, ); (info, add_info(ids, InfoExp(info), m)); @@ -272,6 +275,8 @@ and uexp_to_info_map = ...info, status: original_info.status, lifted_ty: Some(info.ty), + unelaborated_info: Some(original_info), + sugar_info: Some(AutoLabel(l)), }; (info, add_info(elaborated_exp.ids, InfoExp(info), m)); diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 6e05fcd762..9c6898ae48 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -9,7 +9,7 @@ let okc = "ok"; let div_err = div(~attrs=[clss(["status", errc])]); let div_ok = div(~attrs=[clss(["status", okc])]); -let code_err = (code: string): Node.t => +let code = (code: string): Node.t => div(~attrs=[clss(["code"])], [text(code)]); let explain_this_toggle = (~inject, ~show_explain_this: bool): Node.t => { @@ -67,7 +67,12 @@ let elements_noun: Cls.t => string = | _ => failwith("elements_noun: Cls doesn't have elements"); let common_err_view = - (~lifted_ty: option(Typ.t)=?, cls: Cls.t, err: Info.error_common) => + ( + ~lifted_ty as _: option(Typ.t)=?, + ~sugar_info: option(Info.sugar)=?, + cls: Cls.t, + err: Info.error_common, + ) => switch (err) { | NoType(BadToken(token)) => switch (Form.bad_token_cls(token)) { @@ -80,7 +85,7 @@ let common_err_view = text("inconsistent with"), Type.view(Prod([]) |> Typ.fresh), ] - | NoType(FreeConstructor(name)) => [code_err(name), text("not found")] + | NoType(FreeConstructor(name)) => [code(name), text("not found")] | DuplicateLabels(_) => [text("Duplicate labels within a tuple")] | Duplicate(_) => [text("Duplicated Label")] | Inconsistent(WithArrow(typ)) => [ @@ -96,9 +101,12 @@ let common_err_view = Type.view(ana), ] @ ( - switch (lifted_ty) { + switch (sugar_info) { | None => [] - | Some(lifted) => [text("lifted to"), Type.view(lifted)] + | Some(AutoLabel(label)) => [ + text(" automatically added label "), + code(label), + ] // TODO Figure out styling as well as how to handle nested labels } ) | Inconsistent(Internal(tys)) => [ @@ -108,7 +116,12 @@ let common_err_view = }; let common_ok_view = - (~lifted_ty: option(Typ.t)=?, cls: Cls.t, ok: Info.ok_common) => { + ( + ~lifted_ty: option(Typ.t)=?, + ~sugar_info: option(Info.sugar)=?, + cls: Cls.t, + ok: Info.ok_common, + ) => { switch (cls, ok) { | (Exp(MultiHole) | Pat(MultiHole), _) => [ text("Expecting operator or delimiter"), @@ -128,11 +141,24 @@ let common_ok_view = text(":"), Type.view(ana), ] - | (_, Ana(Consistent({ana, syn, _}))) when ana == syn => [ - text(":"), - Type.view(syn), - text("equals expected type"), - ] + | (_, Ana(Consistent({ana, syn, _}))) when ana == syn => + [text(":"), Type.view(syn), text("equals expected type")] + @ ( + switch (lifted_ty) { + | None => [] + | Some(lifted) => [text(" lifted to"), Type.view(lifted)] + } + ) + @ ( + switch (sugar_info) { + | None => [] + | Some(AutoLabel(label)) => [ + text(" automatically added label "), + code(label), + ] // TODO Figure out styling as well as how to handle nested labels + } + ) + | (_, Ana(Consistent({ana, syn, _}))) => // print_endline("Id: " ++) [ @@ -147,6 +173,15 @@ let common_ok_view = | Some(lifted) => [text("lifted to"), Type.view(lifted)] } ) + @ ( + switch (sugar_info) { + | None => [] + | Some(AutoLabel(label)) => [ + text(" automatically added label "), + code(label), + ] // TODO Figure out styling as well as how to handle nested labels + } + ) | (_, Ana(InternallyInconsistent({ana, nojoin: tys}))) => [ text(elements_noun(cls) ++ " have inconsistent types:"), @@ -182,10 +217,7 @@ let typ_err_view = (ok: Info.error_typ) => Type.view(Var(name) |> Typ.fresh), text("not found"), ] - | BadToken(token) => [ - code_err(token), - text("not a type or type operator"), - ] + | BadToken(token) => [code(token), text("not a type or type operator")] | WantConstructorFoundAp | WantConstructorFoundType(_) => [text("Expected a constructor")] | WantTypeFoundAp => [text("Must be part of a sum type")] @@ -201,8 +233,7 @@ let typ_err_view = (ok: Info.error_typ) => let rec exp_view = (cls: Cls.t, status: Info.status_exp, info: Info.exp) => switch (status) { - | InHole(FreeVariable(name)) => - div_err([code_err(name), text("not found")]) + | InHole(FreeVariable(name)) => div_err([code(name), text("not found")]) | InHole(InexhaustiveMatch(additional_err)) => let cls_str = Cls.show(cls); switch (additional_err) { @@ -231,11 +262,25 @@ let rec exp_view = (cls: Cls.t, status: Info.status_exp, info: Info.exp) => ), ]) | InHole(Common(error)) => - div_err(common_err_view(~lifted_ty=?info.lifted_ty, cls, error)) + div_err( + common_err_view( + ~lifted_ty=?info.lifted_ty, + ~sugar_info=?info.sugar_info, + cls, + error, + ), + ) | NotInHole(AnaDeferralConsistent(ana)) => div_ok([text("Expecting type"), Type.view(ana)]) | NotInHole(Common(ok)) => - div_ok(common_ok_view(~lifted_ty=?info.lifted_ty, cls, ok)) + div_ok( + common_ok_view( + ~lifted_ty=?info.lifted_ty, + ~sugar_info=?info.sugar_info, + cls, + ok, + ), + ) }; let rec pat_view = (cls: Cls.t, status: Info.status_pat) => @@ -284,6 +329,7 @@ let tpat_view = (_: Cls.t, status: Info.status_tpat) => let secondary_view = (cls: Cls.t) => div_ok([text(cls |> Cls.show)]); let view_of_info = (~inject, ~settings, ci): list(Node.t) => { + print_endline("CI: " ++ Info.show(ci)); let wrapper = status_view => [ term_view(~inject, ~settings, ci), status_view, From 4a8776c63c908b6e112b096badf3d0f1b95c5abe Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 18 Nov 2024 10:30:29 -0500 Subject: [PATCH 101/108] Fix unused module open --- src/haz3lcore/zipper/EditorUtil.re | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/haz3lcore/zipper/EditorUtil.re b/src/haz3lcore/zipper/EditorUtil.re index 30104cf4a8..70944cf5bc 100644 --- a/src/haz3lcore/zipper/EditorUtil.re +++ b/src/haz3lcore/zipper/EditorUtil.re @@ -34,7 +34,7 @@ let rec append_exp = (e1: Exp.t, e2: Exp.t): Exp.t => { | BinOp(_) | BuiltinFun(_) | Cast(_) - | Match(_) => Exp.{ids: [Id.mk()], copied: false, term: Seq(e1, e2)} + | Match(_) => {ids: [Id.mk()], copied: false, term: Seq(e1, e2)} | Seq(e11, e12) => let e12' = append_exp(e12, e2); {ids: e1.ids, copied: false, term: Seq(e11, e12')}; From 7166f2827c16b4b24c809b744f7ae9a19827b9f3 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Mon, 18 Nov 2024 10:31:31 -0500 Subject: [PATCH 102/108] Add sugar to info --- src/haz3lcore/statics/Info.re | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 0f31fc3e5b..7141599e0b 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -200,6 +200,10 @@ type status_tpat = | NotInHole(ok_tpat) | InHole(error_tpat); +[@deriving (show({with_path: false}), sexp, yojson)] +type sugar = + | AutoLabel(LabeledTuple.label); + [@deriving (show({with_path: false}), sexp, yojson)] type exp = { term: UExp.t, /* The term under consideration */ @@ -211,7 +215,9 @@ type exp = { cls: Cls.t, /* DERIVED: Syntax class (i.e. form name) */ status: status_exp, /* DERIVED: Ok/Error statuses for display */ ty: Typ.t, /* DERIVED: Type after nonempty hole fixing */ - lifted_ty: option(Typ.t) /* Type static-level elaboration */ + lifted_ty: option(Typ.t), /* Type static-level elaboration */ + unelaborated_info: option(exp), /* The info of the pre-sugar term */ + sugar_info: option(sugar), }; [@deriving (show({with_path: false}), sexp, yojson)] @@ -690,6 +696,8 @@ let derived_exp = ~self, ~co_ctx, ~lifted_ty: option(Typ.t), + ~unelaborated_info: option(exp), + ~sugar_info: option(sugar), ) : exp => { let cls = Cls.Exp(UExp.cls_of_term(uexp.term)); @@ -706,6 +714,8 @@ let derived_exp = ancestors, lifted_ty, term: uexp, + unelaborated_info, + sugar_info, }; }; From 6e71d5268cf58b31ccc54322642e2cb2efbb1e5c Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Thu, 21 Nov 2024 10:57:00 -0500 Subject: [PATCH 103/108] Add more labeling information to cursor inspector --- src/haz3lweb/view/CursorInspector.re | 66 +++++++++++++++++++++------- 1 file changed, 49 insertions(+), 17 deletions(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index 9c6898ae48..af900496f0 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -117,6 +117,7 @@ let common_err_view = let common_ok_view = ( + ~auto_labels: list(string)=[], ~lifted_ty: option(Typ.t)=?, ~sugar_info: option(Info.sugar)=?, cls: Cls.t, @@ -174,12 +175,13 @@ let common_ok_view = } ) @ ( - switch (sugar_info) { - | None => [] - | Some(AutoLabel(label)) => [ - text(" automatically added label "), - code(label), - ] // TODO Figure out styling as well as how to handle nested labels + switch (auto_labels) { + | [] => [] + | [a] => [text("by automatically added label "), code(a)] + | _ => [ + text("by automatically added labels "), + ...ListUtil.join(text(","), List.map(code, auto_labels)), + ] } ) | (_, Ana(InternallyInconsistent({ana, nojoin: tys}))) => @@ -230,8 +232,22 @@ let typ_err_view = (ok: Info.error_typ) => text("already used in this sum"), ] }; +let rec automatic_inserted_labels = + (~statics, info: option(Info.exp)): list(string) => + switch (Option.bind(info, i => i.sugar_info)) { + | None => [] + | Some(AutoLabel(label)) => + [label] + @ automatic_inserted_labels( + ~statics, + Option.bind(info, i => i.unelaborated_info), + ) + }; + +let rec exp_view = + (~statics, cls: Cls.t, status: Info.status_exp, info: Info.exp) => { + let labels = automatic_inserted_labels(~statics, Some(info)); -let rec exp_view = (cls: Cls.t, status: Info.status_exp, info: Info.exp) => switch (status) { | InHole(FreeVariable(name)) => div_err([code(name), text("not found")]) | InHole(InexhaustiveMatch(additional_err)) => @@ -241,7 +257,7 @@ let rec exp_view = (cls: Cls.t, status: Info.status_exp, info: Info.exp) => | Some(err) => let cls_str = String.uncapitalize_ascii(cls_str); div_err([ - exp_view(cls, InHole(Common(err)), info), + exp_view(~statics, cls, InHole(Common(err)), info), text("; " ++ cls_str ++ " is inexhaustive"), ]); }; @@ -275,6 +291,7 @@ let rec exp_view = (cls: Cls.t, status: Info.status_exp, info: Info.exp) => | NotInHole(Common(ok)) => div_ok( common_ok_view( + ~auto_labels=labels, ~lifted_ty=?info.lifted_ty, ~sugar_info=?info.sugar_info, cls, @@ -282,15 +299,19 @@ let rec exp_view = (cls: Cls.t, status: Info.status_exp, info: Info.exp) => ), ) }; +}; -let rec pat_view = (cls: Cls.t, status: Info.status_pat) => +let rec pat_view = (~statics, cls: 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 redundant")]) | Some(err) => - div_err([pat_view(cls, InHole(err)), text("; pattern is redundant")]) + div_err([ + pat_view(~statics, 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)) @@ -328,7 +349,7 @@ let tpat_view = (_: Cls.t, status: Info.status_tpat) => let secondary_view = (cls: Cls.t) => div_ok([text(cls |> Cls.show)]); -let view_of_info = (~inject, ~settings, ci): list(Node.t) => { +let view_of_info = (~inject, ~settings, ~statics, ci): list(Node.t) => { print_endline("CI: " ++ Info.show(ci)); let wrapper = status_view => [ term_view(~inject, ~settings, ci), @@ -336,24 +357,30 @@ let view_of_info = (~inject, ~settings, ci): list(Node.t) => { ]; switch (ci) { | Secondary(_) => wrapper(div([])) - | InfoExp({cls, status, _} as ie) => wrapper(exp_view(cls, status, ie)) - | InfoPat({cls, status, _}) => wrapper(pat_view(cls, status)) + | InfoExp({cls, status, _} as ie) => + wrapper(exp_view(~statics, cls, status, ie)) + | InfoPat({cls, status, _}) => wrapper(pat_view(~statics, cls, status)) | InfoTyp({cls, status, _}) => wrapper(typ_view(cls, status)) | InfoTPat({cls, status, _}) => wrapper(tpat_view(cls, status)) }; }; -let inspector_view = (~inject, ~settings, ci): Node.t => +let inspector_view = (~inject, ~settings, ~statics, ci): Node.t => div( ~attrs=[ Attr.id("cursor-inspector"), clss([Info.is_error(ci) ? errc : okc]), ], - view_of_info(~inject, ~settings, ci), + view_of_info(~inject, ~settings, ~statics, ci), ); let view = - (~inject, ~settings: Settings.t, editor, cursor_info: option(Info.t)) => { + ( + ~inject, + ~settings: Settings.t, + editor: Editor.t, + cursor_info: option(Info.t), + ) => { let bar_view = div(~attrs=[Attr.id("bottom-bar")]); let err_view = err => bar_view([ @@ -367,7 +394,12 @@ let view = | None => err_view("Whitespace or Comment") | Some(ci) => bar_view([ - inspector_view(~inject, ~settings, ci), + inspector_view( + ~inject, + ~settings, + ~statics=editor.state.meta.statics, + ci, + ), ProjectorView.Panel.view( ~inject=a => inject(PerformAction(Project(a))), editor, From ddaaaa9e8110f2940dcf7b6c57d93b68bd61ce0a Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Tue, 26 Nov 2024 10:13:59 -0500 Subject: [PATCH 104/108] Add pattern labels to cursor inspector --- src/haz3lcore/statics/Info.re | 5 ++++- src/haz3lcore/statics/Statics.re | 6 +++++- src/haz3lweb/view/CursorInspector.re | 29 ++++++++++++++++++---------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 7141599e0b..96cd9c6c08 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -233,7 +233,8 @@ type pat = { status: status_pat, ty: Typ.t, constraint_: Constraint.t, - lifted_ty: option(Typ.t) /* Type static-level elaboration */ + lifted_ty: option(Typ.t), /* Type static-level elaboration */ + elaboration_provenance: option((pat, sugar)), }; [@deriving (show({with_path: false}), sexp, yojson)] @@ -731,6 +732,7 @@ let derived_pat = ~self, ~constraint_, ~lifted_ty: option(Typ.t), + ~elaboration_provenance: option((pat, sugar)), ) : pat => { let cls = Cls.Pat(UPat.cls_of_term(upat.term)); @@ -750,6 +752,7 @@ let derived_pat = term: upat, constraint_, lifted_ty, + elaboration_provenance, }; }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 0bb12f77b1..31467431c8 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -774,6 +774,7 @@ and uexp_to_info_map = // because redundancy doesn't make sense in a smaller context ~constraint_=p_constraint, ~lifted_ty=None, + ~elaboration_provenance=None, ); ( // Override the info for the single upat @@ -906,7 +907,8 @@ and upat_to_info_map = m: Map.t, ) : (Info.pat, Map.t) => { - let add = (~self, ~ctx, ~constraint_, ~lifted_ty=?, m) => { + let add = + (~self, ~ctx, ~constraint_, ~elaboration_provenance=?, ~lifted_ty=?, m) => { let prev_synswitch = switch (Id.Map.find_opt(Pat.rep_id(upat), m)) { | Some(Info.InfoPat({mode: Syn | SynFun, ty, _})) => Some(ty) @@ -925,6 +927,7 @@ and upat_to_info_map = ~self=Common(self), ~constraint_, ~lifted_ty, + ~elaboration_provenance, ); (info, add_info(ids, InfoPat(info), m)); }; @@ -1009,6 +1012,7 @@ and upat_to_info_map = ...info, status: original_info.status, lifted_ty: Some(info.ty), + elaboration_provenance: Some((original_info, AutoLabel(l))), }; (info, add_info(elaborated_pat.ids, InfoPat(info), m)); diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index af900496f0..e0048777a1 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -161,7 +161,6 @@ let common_ok_view = ) | (_, Ana(Consistent({ana, syn, _}))) => - // print_endline("Id: " ++) [ text(":"), Type.view(syn), @@ -232,21 +231,29 @@ let typ_err_view = (ok: Info.error_typ) => text("already used in this sum"), ] }; -let rec automatic_inserted_labels = +let rec automatic_inserted_labels_exp = (~statics, info: option(Info.exp)): list(string) => switch (Option.bind(info, i => i.sugar_info)) { | None => [] | Some(AutoLabel(label)) => [label] - @ automatic_inserted_labels( + @ automatic_inserted_labels_exp( ~statics, Option.bind(info, i => i.unelaborated_info), ) }; +let rec automatic_inserted_labels_pat = + (~statics, info: option(Info.pat)): list(string) => + switch (Option.bind(info, i => i.elaboration_provenance)) { + | None => [] + | Some((ui, AutoLabel(label))) => + [label] @ automatic_inserted_labels_pat(~statics, Some(ui)) + }; + let rec exp_view = (~statics, cls: Cls.t, status: Info.status_exp, info: Info.exp) => { - let labels = automatic_inserted_labels(~statics, Some(info)); + let labels = automatic_inserted_labels_exp(~statics, Some(info)); switch (status) { | InHole(FreeVariable(name)) => div_err([code(name), text("not found")]) @@ -301,7 +308,9 @@ let rec exp_view = }; }; -let rec pat_view = (~statics, cls: Cls.t, status: Info.status_pat) => +let rec pat_view = + (~statics, cls: Cls.t, status: Info.status_pat, info: Info.pat) => { + let labels = automatic_inserted_labels_pat(~statics, Some(info)); switch (status) { | InHole(ExpectedConstructor) => div_err([text("Expected a constructor")]) | InHole(Redundant(additional_err)) => @@ -309,14 +318,14 @@ let rec pat_view = (~statics, cls: Cls.t, status: Info.status_pat) => | None => div_err([text("Pattern is redundant")]) | Some(err) => div_err([ - pat_view(~statics, cls, InHole(err)), + pat_view(~statics, cls, InHole(err), info), text("; pattern is redundant"), ]) } | InHole(Common(error)) => div_err(common_err_view(cls, error)) - | NotInHole(ok) => div_ok(common_ok_view(cls, ok)) + | NotInHole(ok) => div_ok(common_ok_view(~auto_labels=labels, cls, ok)) }; - +}; let typ_view = (cls: Cls.t, status: Info.status_typ) => switch (status) { | NotInHole(ok) => div_ok(typ_ok_view(cls, ok)) @@ -350,7 +359,6 @@ let tpat_view = (_: Cls.t, status: Info.status_tpat) => let secondary_view = (cls: Cls.t) => div_ok([text(cls |> Cls.show)]); let view_of_info = (~inject, ~settings, ~statics, ci): list(Node.t) => { - print_endline("CI: " ++ Info.show(ci)); let wrapper = status_view => [ term_view(~inject, ~settings, ci), status_view, @@ -359,7 +367,8 @@ let view_of_info = (~inject, ~settings, ~statics, ci): list(Node.t) => { | Secondary(_) => wrapper(div([])) | InfoExp({cls, status, _} as ie) => wrapper(exp_view(~statics, cls, status, ie)) - | InfoPat({cls, status, _}) => wrapper(pat_view(~statics, cls, status)) + | InfoPat({cls, status, _} as info) => + wrapper(pat_view(~statics, cls, status, info)) | InfoTyp({cls, status, _}) => wrapper(typ_view(cls, status)) | InfoTPat({cls, status, _}) => wrapper(tpat_view(cls, status)) }; From 88931f42429851ce4b38bf7a7a70a31c8d2a0b76 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Tue, 26 Nov 2024 11:06:49 -0500 Subject: [PATCH 105/108] Remove lifted_ty from Info types --- src/haz3lcore/statics/Info.re | 6 ------ src/haz3lcore/statics/Statics.re | 11 ++--------- src/haz3lweb/view/CursorInspector.re | 4 ++-- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index 96cd9c6c08..f7316d300b 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -215,7 +215,6 @@ type exp = { cls: Cls.t, /* DERIVED: Syntax class (i.e. form name) */ status: status_exp, /* DERIVED: Ok/Error statuses for display */ ty: Typ.t, /* DERIVED: Type after nonempty hole fixing */ - lifted_ty: option(Typ.t), /* Type static-level elaboration */ unelaborated_info: option(exp), /* The info of the pre-sugar term */ sugar_info: option(sugar), }; @@ -233,7 +232,6 @@ type pat = { status: status_pat, ty: Typ.t, constraint_: Constraint.t, - lifted_ty: option(Typ.t), /* Type static-level elaboration */ elaboration_provenance: option((pat, sugar)), }; @@ -696,7 +694,6 @@ let derived_exp = ~ancestors, ~self, ~co_ctx, - ~lifted_ty: option(Typ.t), ~unelaborated_info: option(exp), ~sugar_info: option(sugar), ) @@ -713,7 +710,6 @@ let derived_exp = ctx, co_ctx, ancestors, - lifted_ty, term: uexp, unelaborated_info, sugar_info, @@ -731,7 +727,6 @@ let derived_pat = ~ancestors, ~self, ~constraint_, - ~lifted_ty: option(Typ.t), ~elaboration_provenance: option((pat, sugar)), ) : pat => { @@ -751,7 +746,6 @@ let derived_pat = ancestors, term: upat, constraint_, - lifted_ty, elaboration_provenance, }; }; diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 31467431c8..416749a606 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -184,8 +184,7 @@ and uexp_to_info_map = | Ana({term: Unknown(SynSwitch), _}) => Mode.Syn | _ => mode }; - let add' = - (~lifted_ty=?, ~unelaborated_info=?, ~sugar_info=?, ~self, ~co_ctx, m) => { + let add' = (~unelaborated_info=?, ~sugar_info=?, ~self, ~co_ctx, m) => { let info = Info.derived_exp( ~uexp, @@ -194,7 +193,6 @@ and uexp_to_info_map = ~ancestors, ~self, ~co_ctx, - ~lifted_ty, ~unelaborated_info, ~sugar_info, ); @@ -274,7 +272,6 @@ and uexp_to_info_map = let info = { ...info, status: original_info.status, - lifted_ty: Some(info.ty), unelaborated_info: Some(original_info), sugar_info: Some(AutoLabel(l)), }; @@ -773,7 +770,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, - ~lifted_ty=None, ~elaboration_provenance=None, ); ( @@ -907,8 +903,7 @@ and upat_to_info_map = m: Map.t, ) : (Info.pat, Map.t) => { - let add = - (~self, ~ctx, ~constraint_, ~elaboration_provenance=?, ~lifted_ty=?, m) => { + let add = (~self, ~ctx, ~constraint_, ~elaboration_provenance=?, m) => { let prev_synswitch = switch (Id.Map.find_opt(Pat.rep_id(upat), m)) { | Some(Info.InfoPat({mode: Syn | SynFun, ty, _})) => Some(ty) @@ -926,7 +921,6 @@ and upat_to_info_map = ~ancestors, ~self=Common(self), ~constraint_, - ~lifted_ty, ~elaboration_provenance, ); (info, add_info(ids, InfoPat(info), m)); @@ -1011,7 +1005,6 @@ and upat_to_info_map = let info = { ...info, status: original_info.status, - lifted_ty: Some(info.ty), elaboration_provenance: Some((original_info, AutoLabel(l))), }; diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index e0048777a1..a54fc0ba32 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -287,7 +287,7 @@ let rec exp_view = | InHole(Common(error)) => div_err( common_err_view( - ~lifted_ty=?info.lifted_ty, + ~lifted_ty=?Option.map(_ => info.ty, info.sugar_info), ~sugar_info=?info.sugar_info, cls, error, @@ -299,7 +299,7 @@ let rec exp_view = div_ok( common_ok_view( ~auto_labels=labels, - ~lifted_ty=?info.lifted_ty, + ~lifted_ty=?Option.map(_ => info.ty, info.sugar_info), ~sugar_info=?info.sugar_info, cls, ok, From 3a96a5a09f8447ab0a255b3bae7e5c99b7ba858f Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Thu, 5 Dec 2024 14:29:10 -0500 Subject: [PATCH 106/108] Cursor inspector changes --- src/haz3lweb/view/CursorInspector.re | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index a54fc0ba32..dee83684da 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -161,18 +161,13 @@ let common_ok_view = ) | (_, Ana(Consistent({ana, syn, _}))) => - [ - text(":"), - Type.view(syn), - text("consistent with expected type"), - Type.view(ana), - ] - @ ( + [text(":"), Type.view(syn), text("consistent with expected type")] + @ [ switch (lifted_ty) { - | None => [] - | Some(lifted) => [text("lifted to"), Type.view(lifted)] - } - ) + | None => Type.view(ana) + | Some(lifted) => Type.view(lifted) + }, + ] @ ( switch (auto_labels) { | [] => [] From 68f85ab1f3eeedc4ee433337feeaef40ffa273af Mon Sep 17 00:00:00 2001 From: WondAli Date: Fri, 6 Dec 2024 14:55:12 -0500 Subject: [PATCH 107/108] updated dot operator to use labels --- src/haz3lcore/dynamics/Elaborator.re | 12 ++-- src/haz3lcore/dynamics/Transition.re | 74 ++++++++++++++---------- src/haz3lcore/dynamics/TypeAssignment.re | 4 +- src/haz3lcore/statics/Info.re | 7 ++- src/haz3lcore/statics/MakeTerm.re | 10 +++- src/haz3lcore/statics/Self.re | 6 +- src/haz3lcore/statics/Statics.re | 52 ++++------------- src/haz3lcore/statics/Term.re | 4 +- src/haz3lweb/view/CursorInspector.re | 6 ++ test/Test_Evaluator.re | 2 +- 10 files changed, 90 insertions(+), 87 deletions(-) diff --git a/src/haz3lcore/dynamics/Elaborator.re b/src/haz3lcore/dynamics/Elaborator.re index 2a8a2cce91..49fc086959 100644 --- a/src/haz3lcore/dynamics/Elaborator.re +++ b/src/haz3lcore/dynamics/Elaborator.re @@ -391,20 +391,22 @@ let rec elaborate = (m: Statics.Map.t, uexp: UExp.t): (DHExp.t, Typ.t) => { | Dot(e1, e2) => let (e1, ty1) = elaborate(m, e1); - // I don't think we need to elaborate labels + // Don't elaborate labels // let (e2, ty2) = elaborate(m, e2); - let ty = - switch (Typ.weak_head_normalize(ctx, ty1).term, e2.term) { - | (Prod(tys), Var(name)) => + let rec elab_dot = (ty1: Typ.t, e2: DHExp.t) => + switch (ty1.term, e2.term) { + | (Parens(ty1), _) => elab_dot(ty1, e2) + | (Prod(tys), Label(name)) => let element = LabeledTuple.find_label(Typ.get_label, tys, name); switch (element) { | Some({term: TupLabel(_, ty), _}) => ty | _ => Unknown(Internal) |> Typ.temp }; - | (TupLabel(_, ty), Var(name)) + | (TupLabel(_, ty), Label(name)) when LabeledTuple.equal(Typ.get_label(ty1), Some((name, e2))) => ty | _ => Unknown(Internal) |> Typ.temp }; + let ty = elab_dot(ty1, e2); // Freshcast this, if necessary? Dot(e1, e2) |> rewrap |> cast_from(ty); diff --git a/src/haz3lcore/dynamics/Transition.re b/src/haz3lcore/dynamics/Transition.re index 339f951218..a9ab026182 100644 --- a/src/haz3lcore/dynamics/Transition.re +++ b/src/haz3lcore/dynamics/Transition.re @@ -709,8 +709,9 @@ module Transition = (EV: EV_MODE) => { and. d2' = req_final(req(state, env), d2 => Dot2(d1, d2) |> wrap_ctx, d2); // TODO: Holes and other cases handled? + // TODO: Get rid of all these casts switch (DHExp.term_of(d1'), DHExp.term_of(d2')) { - | (Tuple(ds), Var(name)) => + | (Tuple(ds), Label(name)) => Step({ expr: switch (LabeledTuple.find_label(DHExp.get_label, ds, name)) { @@ -721,41 +722,50 @@ module Transition = (EV: EV_MODE) => { kind: Dot, is_value: false, }) - | (_, Cast(d2', ty, ty')) => - // TODO: Probably not right + | (TupLabel(_, d), Label(name)) => Step({ - expr: Cast(Dot(d1, d2') |> fresh, ty, ty') |> fresh, + expr: + LabeledTuple.equal(Exp.get_label(d1'), Some((name, d))) + ? d : Undefined |> DHExp.fresh, state_update, - kind: CastAp, + kind: Dot, is_value: false, }) - | (Cast(d3', t2, t3), Var(name)) => - // TODO: doen't work because you get to a cast(1, Unknown, Int) which is Indet - let rec get_typs = (t2, t3) => - switch (Typ.term_of(t2), Typ.term_of(t3)) { - | (Prod(ts), Prod(ts')) => (ts, ts') - | (Parens(t2), _) => get_typs(t2, t3) - | (_, Parens(t3)) => get_typs(t2, t3) - | (_, _) => ([], []) - }; - let (ts, ts') = get_typs(t2, t3); - let ty = - switch (LabeledTuple.find_label(Typ.get_label, ts, name)) { - | Some({term: TupLabel(_, ty), _}) => ty - | _ => Unknown(Internal) |> Typ.temp - }; - let ty' = - switch (LabeledTuple.find_label(Typ.get_label, ts', name)) { - | Some({term: TupLabel(_, ty), _}) => ty - | _ => Unknown(Internal) |> Typ.temp - }; - Step({ - expr: Cast(Dot(d3', d2) |> fresh, ty, ty') |> fresh, - state_update, - kind: CastAp, - is_value: false, - }); - | _ => raise(EvaluatorError.Exception(BadPatternMatch)) + // | (_, Cast(d2', ty, ty')) => + // // TODO: Probably not right + // Step({ + // expr: Cast(Dot(d1, d2') |> fresh, ty, ty') |> fresh, + // state_update, + // kind: CastAp, + // is_value: false, + // }) + // | (Cast(d3', t2, t3), Label(name)) => + // // TODO: doen't work because you get to a cast(1, Unknown, Int) which is Indet + // let rec get_typs = (t2, t3) => + // switch (Typ.term_of(t2), Typ.term_of(t3)) { + // | (Prod(ts), Prod(ts')) => (ts, ts') + // | (Parens(t2), _) => get_typs(t2, t3) + // | (_, Parens(t3)) => get_typs(t2, t3) + // | (_, _) => ([], []) + // }; + // let (ts, ts') = get_typs(t2, t3); + // let ty = + // switch (LabeledTuple.find_label(Typ.get_label, ts, name)) { + // | Some({term: TupLabel(_, ty), _}) => ty + // | _ => Unknown(Internal) |> Typ.temp + // }; + // let ty' = + // switch (LabeledTuple.find_label(Typ.get_label, ts', name)) { + // | Some({term: TupLabel(_, ty), _}) => ty + // | _ => Unknown(Internal) |> Typ.temp + // }; + // Step({ + // expr: Cast(Dot(d3', d2) |> fresh, ty, ty') |> fresh, + // state_update, + // kind: CastAp, + // is_value: false, + // }); + | _ => Indet }; | TupLabel(label, d1) => // TODO (Anthony): Fix this if needed diff --git a/src/haz3lcore/dynamics/TypeAssignment.re b/src/haz3lcore/dynamics/TypeAssignment.re index 0e7931aa68..aeedf5634d 100644 --- a/src/haz3lcore/dynamics/TypeAssignment.re +++ b/src/haz3lcore/dynamics/TypeAssignment.re @@ -340,13 +340,13 @@ and typ_of_dhexp = (ctx: Ctx.t, m: Statics.Map.t, dh: DHExp.t): option(Typ.t) => Some(TupLabel(tlab, ty) |> Typ.temp); | Dot(d1, d2) => switch (d1.term, d2.term) { - | (Tuple(ds), Var(name)) => + | (Tuple(ds), Label(name)) => let element = LabeledTuple.find_label(DHExp.get_label, ds, name); switch (element) { | Some({term: TupLabel(_, exp), _}) => typ_of_dhexp(ctx, m, exp) | _ => None }; - | (TupLabel(_, de), Var(name)) + | (TupLabel(_, de), Label(name)) when LabeledTuple.equal(DHExp.get_label(d1), Some((name, d2))) => typ_of_dhexp(ctx, m, de) | _ => None diff --git a/src/haz3lcore/statics/Info.re b/src/haz3lcore/statics/Info.re index f7316d300b..593c1550f4 100644 --- a/src/haz3lcore/statics/Info.re +++ b/src/haz3lcore/statics/Info.re @@ -51,7 +51,10 @@ type error_no_type = /* Empty application of function with inconsistent type */ | BadTrivAp(Typ.t) /* Sum constructor neiter bound nor in ana type */ - | FreeConstructor(Constructor.t); + | FreeConstructor(Constructor.t) + /* Dot Operator is ill-formed */ + | WantTuple + | LabelNotFound; /* Errors which can apply to either expression or patterns */ [@deriving (show({with_path: false}), sexp, yojson)] @@ -404,6 +407,8 @@ let rec status_common = }; | (NoJoin(_, tys), Syn | SynFun | SynTypFun) => InHole(Inconsistent(Internal(Typ.of_source(tys)))) + | (WantTuple, _) => InHole(NoType(WantTuple)) + | (LabelNotFound, _) => InHole(NoType(LabelNotFound)) }; let rec status_pat = (ctx: Ctx.t, mode: Mode.t, self: Self.pat): status_pat => diff --git a/src/haz3lcore/statics/MakeTerm.re b/src/haz3lcore/statics/MakeTerm.re index ed62a19fd8..ed6b7dc842 100644 --- a/src/haz3lcore/statics/MakeTerm.re +++ b/src/haz3lcore/statics/MakeTerm.re @@ -339,7 +339,15 @@ and exp_term: unsorted => (UExp.term, list(Id.t)) = { ]) | _ => TupLabel(l, r) } - | (["."], []) => Dot(l, r) + | (["."], []) => + // TODO (Anthony): Other cases to convert to string + switch (r.term) { + // | String(name) + // Currently not allowing Strings to prevent empty Labels + | Var(name) => + Dot(l, {ids: r.ids, copied: r.copied, term: Label(name)}) + | _ => Dot(l, r) + } | (["|>"], []) => Ap(Reverse, r, l) | (["@"], []) => ListConcat(l, r) | _ => hole(tm) diff --git a/src/haz3lcore/statics/Self.re b/src/haz3lcore/statics/Self.re index 824a0fc905..5c278d8afa 100644 --- a/src/haz3lcore/statics/Self.re +++ b/src/haz3lcore/statics/Self.re @@ -37,7 +37,9 @@ type t = | IsConstructor({ name: Constructor.t, syn_ty: option(Typ.t), - }); /* Constructors have special ana logic */ + }) /* Constructors have special ana logic */ + | WantTuple /* Want a Tuple, found not-tuple */ + | LabelNotFound; /* Currently used by the dot operator for a label not found */ [@deriving (show({with_path: false}), sexp, yojson)] type error_partial_ap = @@ -82,6 +84,8 @@ let typ_of: (Ctx.t, t) => option(Typ.t) = | IsMulti | Duplicate_Labels(_) | Duplicate(_) + | WantTuple + | LabelNotFound | NoJoin(_) => None; let typ_of_exp: (Ctx.t, exp) => option(Typ.t) = diff --git a/src/haz3lcore/statics/Statics.re b/src/haz3lcore/statics/Statics.re index 416749a606..18aacc8b46 100644 --- a/src/haz3lcore/statics/Statics.re +++ b/src/haz3lcore/statics/Statics.re @@ -405,9 +405,11 @@ and uexp_to_info_map = add(~self, ~co_ctx=CoCtx.union(List.map(Info.exp_co_ctx, es')), m); | Dot(e1, e2) => let (info_e1, m) = go(~mode=Syn, e1, m); + let (info_e2, m) = go(~mode=Ana(Label("") |> Typ.temp), e2, m); let (ty, m) = { - switch (e2.term, info_e1.ty.term) { - | (Var(name), Unknown(_)) => + switch (info_e1.ty.term, info_e2.ty.term) { + | (Unknown(_), Label(name)) => + // This is so that the statics will result in Unknown(Internal) let ty = Prod([ TupLabel( @@ -419,58 +421,24 @@ and uexp_to_info_map = |> Typ.temp; let (_, m) = go(~mode=Mode.Ana(ty), e1, m); (ty, m); - | (_, Var(_)) => (Typ.weak_head_normalize(ctx, info_e1.ty), m) + | (Var(_), _) => (Typ.weak_head_normalize(ctx, info_e1.ty), m) | _ => (info_e1.ty, m) }; }; switch (ty.term) { | Prod(ts) => switch (e2.term) { - | Var(name) => + | Label(name) => let element: option(Typ.t) = LabeledTuple.find_label(Typ.get_label, ts, name); - // let m = - // e2.ids - // |> List.fold_left( - // (m, id) => - // Id.Map.update( - // id, - // fun - // | Some(Info.InfoExp(exp)) => - // Some(Info.InfoExp({...exp, ctx})) - // | _ as info => info, - // m, - // ), - // m, - // ); switch (element) { | Some({term: TupLabel(_, typ), _}) - | Some(typ) => - let (body, m) = - go'( - ~ctx=[ - VarEntry({ - name, - id: List.nth(e2.ids, 0), - typ: Unknown(Internal) |> Typ.temp, - }), - ], - ~mode, - e2, - m, - ); - add(~self=Just(typ), ~co_ctx=body.co_ctx, m); - | None => - let (body, m) = go'(~ctx=[], ~mode, e2, m); - add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); + | Some(typ) => add(~self=Just(typ), ~co_ctx=info_e2.co_ctx, m) + | None => add(~self=LabelNotFound, ~co_ctx=info_e2.co_ctx, m) }; - | _ => - let (body, m) = go'(~ctx=[], ~mode, e2, m); - add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); + | _ => add(~self=LabelNotFound, ~co_ctx=info_e2.co_ctx, m) } - | _ => - let (body, m) = go'(~ctx=[], ~mode, e2, m); - add(~self=Just(body.ty), ~co_ctx=body.co_ctx, m); + | _ => add(~self=WantTuple, ~co_ctx=info_e2.co_ctx, m) }; | Test(e) => let (e, m) = go(~mode=Ana(Bool |> Typ.temp), e, m); diff --git a/src/haz3lcore/statics/Term.re b/src/haz3lcore/statics/Term.re index 0da73b71e6..95f511473e 100644 --- a/src/haz3lcore/statics/Term.re +++ b/src/haz3lcore/statics/Term.re @@ -484,7 +484,7 @@ module Exp = { switch (e1.term) { | Tuple(ts) => switch (e2.term) { - | Var(name) => LabeledTuple.find_label(get_label, ts, name) + | Label(name) => LabeledTuple.find_label(get_label, ts, name) | _ => None } | _ => None // TODO (Anthony): other exps @@ -541,7 +541,7 @@ module Exp = { switch (e1.term) { | Tuple(ts) => switch (e2.term) { - | Var(name) => LabeledTuple.find_label(get_label, ts, name) + | Label(name) => LabeledTuple.find_label(get_label, ts, name) | _ => None } | _ => None // TODO (Anthony): other exps diff --git a/src/haz3lweb/view/CursorInspector.re b/src/haz3lweb/view/CursorInspector.re index dee83684da..bfb988116a 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -86,6 +86,12 @@ let common_err_view = Type.view(Prod([]) |> Typ.fresh), ] | NoType(FreeConstructor(name)) => [code(name), text("not found")] + | NoType(WantTuple) => [ + text("Invalid Dot Operation: requires tuple for first argument"), + ] + | NoType(LabelNotFound) => [ + text("Invalid Dot Operation: label not found in tuple"), + ] | DuplicateLabels(_) => [text("Duplicate labels within a tuple")] | Duplicate(_) => [text("Duplicated Label")] | Inconsistent(WithArrow(typ)) => [ diff --git a/test/Test_Evaluator.re b/test/Test_Evaluator.re index 58f4a46fec..8eb0180401 100644 --- a/test/Test_Evaluator.re +++ b/test/Test_Evaluator.re @@ -38,7 +38,7 @@ let test_labeled_tuple_projection = () => |> Exp.fresh, ]) |> Exp.fresh, - Var("a") |> Exp.fresh // This is a var now for parsing reasons + Label("a") |> Exp.fresh // This is a var now for parsing reasons ) |> Exp.fresh, ); From bd366734b6b51dbe5aae99f020c4cfa4409042f3 Mon Sep 17 00:00:00 2001 From: Alexander Bandukwala <7h3kk1d@gmail.com> Date: Tue, 10 Dec 2024 12:52:08 -0500 Subject: [PATCH 108/108] Fix cursor inspector message --- 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 bfb988116a..0cb0e1a1f2 100644 --- a/src/haz3lweb/view/CursorInspector.re +++ b/src/haz3lweb/view/CursorInspector.re @@ -110,7 +110,7 @@ let common_err_view = switch (sugar_info) { | None => [] | Some(AutoLabel(label)) => [ - text(" automatically added label "), + text(" after automatically added label "), code(label), ] // TODO Figure out styling as well as how to handle nested labels }