Skip to content

Commit

Permalink
Merge branch 'dev' into param_types_update
Browse files Browse the repository at this point in the history
  • Loading branch information
isdiemer committed Feb 22, 2025
2 parents 6325229 + 38f9222 commit 6b6cd28
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 40 deletions.
11 changes: 3 additions & 8 deletions src/haz3lcore/dynamics/PatternMatch.re
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,10 @@ let rec matches = (dp: Pat.t, d: DHExp.t): match_result =>
| String(s) =>
let* s' = Unboxing.unbox(String, d);
s == s' ? Matches(Environment.empty) : DoesNotMatch;
| Cast({term: ListLit([] as xs), _}, _, _) // Shortcut for empty list pattern match perf
| ListLit(xs) =>
let* s' = Unboxing.unbox(List, d);
if (List.length(xs) == List.length(s')) {
List.map2(matches, xs, s')
|> List.fold_left(combine_result, Matches(Environment.empty));
} else {
DoesNotMatch;
};
let* s' = Unboxing.unbox(ListLit(List.length(xs)), d);
List.map2(matches, xs, s')
|> List.fold_left(combine_result, Matches(Environment.empty));
| Cons(x, xs) =>
let* (x', xs') = Unboxing.unbox(Cons, d);
let* m_x = matches(x, x');
Expand Down
12 changes: 12 additions & 0 deletions src/haz3lcore/dynamics/Unboxing.re
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type unbox_request('a) =
| Tuple(int): unbox_request(list(DHExp.t))
| TupLabel(DHPat.t): unbox_request(DHExp.t)
| List: unbox_request(list(DHExp.t))
| ListLit(int): unbox_request(list(DHExp.t)) // This request is used for performance reasons to prevent casting lists of the wrong length
| Cons: unbox_request((DHExp.t, DHExp.t))
| SumNoArg(string): unbox_request(unit)
| SumWithArg(string): unbox_request(DHExp.t)
Expand Down Expand Up @@ -104,14 +105,22 @@ let rec unbox: type a. (unbox_request(a), DHExp.t) => unboxed(a) =

/* Lists can be either lists or list casts */
| (List, ListLit(l)) => Matches(l)
| (ListLit(n), ListLit(l)) when ListUtil.is_length(n, l) => Matches(l)
| (ListLit(_), ListLit(_)) => DoesNotMatch
| (Cons, ListLit([x, ...xs])) =>
Matches((x, ListLit(xs) |> DHExp.fresh))
| (Cons, ListLit([])) => DoesNotMatch

| (List, Cast(l, {term: List(t1), _}, {term: List(t2), _})) =>
let* l = unbox(List, l);
let l = List.map(d => Cast(d, t1, t2) |> DHExp.fresh, l);
let l = List.map(fixup_cast, l);
Matches(l);
| (ListLit(n), Cast(l, {term: List(t1), _}, {term: List(t2), _})) =>
let* l = unbox(ListLit(n), l);
let l = List.map(d => Cast(d, t1, t2) |> DHExp.fresh, l);
let l = List.map(fixup_cast, l);
Matches(l);
| (
Cons,
Cast(l, {term: List(t1), _} as ct1, {term: List(t2), _} as ct2),
Expand Down Expand Up @@ -195,6 +204,8 @@ let rec unbox: type a. (unbox_request(a), DHExp.t) => unboxed(a) =
| (Fun, DeferredAp(d1, ds)) => Matches(DeferredAp(d1, ds))

/* TypFun-like things can look like the following when values */
| (TypFun, Closure(env', {term: TypFun(utpat, tfbody, name), _})) =>
Matches(TypFun(utpat, Closure(env', tfbody) |> Exp.fresh, name))
| (TypFun, TypFun(utpat, tfbody, name)) =>
Matches(TypFun(utpat, tfbody, name))
// Note: We might be able to handle this cast like other casts
Expand Down Expand Up @@ -241,6 +252,7 @@ let rec unbox: type a. (unbox_request(a), DHExp.t) => unboxed(a) =
| Label => raise(EvaluatorError.Exception(InvalidBoxedLabel(expr)))
| Tuple(_) => raise(EvaluatorError.Exception(InvalidBoxedTuple(expr)))
| List
| ListLit(_)
| Cons => raise(EvaluatorError.Exception(InvalidBoxedListLit(expr)))
| SumNoArg(_)
| SumWithArg(_) =>
Expand Down
28 changes: 13 additions & 15 deletions src/haz3lcore/pretty/ExpToSegment.re
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Settings = {
fold_fn_bodies: !settings.evaluation.show_fn_bodies,
hide_fixpoints: !settings.evaluation.show_fixpoints,
fold_cast_types: !settings.evaluation.show_casts,
show_filters: false,
show_filters: settings.evaluation.show_stepper_filters,
};
};

Expand Down Expand Up @@ -308,12 +308,6 @@ let rec parenthesize =
)
|> rewrap
| Test(e) => Test(parenthesize(e) |> paren_at(Precedence.min)) |> rewrap
// | Filter(f, e) =>
// Filter(
// f, // TODO: Filters
// parenthesize(e) |> paren_at(Precedence.min),
// )
// |> rewrap
| Parens(e) =>
Parens(parenthesize(~already_paren=true, e) |> paren_at(Precedence.min))
|> rewrap
Expand Down Expand Up @@ -707,14 +701,18 @@ let rec exp_to_pretty = (~settings: Settings.t, exp: Exp.t): pretty => {
let id = exp |> Exp.rep_id;
let* p = go(pat);
let+ e = go(e);
let form =
switch (act) {
| (Step, One) => Form.FilterPause
| (Step, All) => Form.FilterDebug
| (Eval, One) => Form.FilterHide
| (Eval, All) => Form.FilterEval
};
[mk_form(form, id, [p])] @ e;
settings.show_filters
? {
let form =
switch (act) {
| (Step, One) => Form.FilterPause
| (Step, All) => Form.FilterDebug
| (Eval, One) => Form.FilterHide
| (Eval, All) => Form.FilterEval
};
[mk_form(form, id, [p])] @ e;
}
: e;
// Forms which should be removed by substitute_closures
| Closure(_) => failwith("closure not removed before printing")
// Other cases
Expand Down
18 changes: 14 additions & 4 deletions src/haz3lcore/statics/Elaborator.re
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,12 @@ let rec elaborate_pattern =
switch (Mode.ctr_ana_typ(ctx, mode, c), Ctx.lookup_ctr(ctx, c)) {
| (Some(ana_ty), _) => ana_ty
| (_, Some({typ: syn_ty, _})) => syn_ty
| _ => Unknown(Internal) |> Typ.temp
| _ =>
Sum([
ConstructorMap.Variant(c, [Id.invalid], None),
ConstructorMap.BadEntry(Unknown(Internal) |> Typ.temp),
])
|> Typ.temp
};
let t = t |> Typ.normalize(ctx);
Constructor(c, t) |> rewrap |> cast_from(t);
Expand Down Expand Up @@ -333,7 +338,12 @@ let rec elaborate = (m: Statics.Map.t, uexp: Exp.t): (DHExp.t, Typ.t) => {
switch (Mode.ctr_ana_typ(ctx, mode, c), Ctx.lookup_ctr(ctx, c)) {
| (Some(ana_ty), _) => ana_ty
| (_, Some({typ: syn_ty, _})) => syn_ty
| _ => Unknown(Internal) |> Typ.temp
| _ =>
Sum([
ConstructorMap.Variant(c, [Id.invalid], None),
ConstructorMap.BadEntry(Unknown(Internal) |> Typ.temp),
])
|> Typ.temp
};
let t = t |> Typ.normalize(ctx) |> Typ.all_ids_temp;
Constructor(c, t) |> rewrap |> cast_from(t);
Expand Down Expand Up @@ -444,14 +454,14 @@ let rec elaborate = (m: Statics.Map.t, uexp: Exp.t): (DHExp.t, Typ.t) => {
|> Option.get
|> List.exists(f => VarMap.lookup(co_ctx, f) != None);
if (!is_recursive) {
let def = add_name(Pat.get_var(p), def);
let (def, ty2) = elaborate(m, def);
let def = add_name(Pat.get_var(p), def);
let (body, ty) = elaborate(m, body);
Let(p, fresh_cast(def, ty2, ty1), body) |> rewrap |> cast_from(ty);
} else {
// TODO: Add names to mutually recursive functions
let def = add_name(Option.map(s => s ++ "+", Pat.get_var(p)), def);
let (def, ty2) = elaborate(m, def);
let def = add_name(Option.map(s => s ++ "+", Pat.get_var(p)), def);
let (body, ty) = elaborate(m, body);
let fixf =
(FixF(p, fresh_cast(def, ty2, ty1), None): Exp.term)
Expand Down
13 changes: 12 additions & 1 deletion src/haz3lcore/statics/Info.re
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,18 @@ let fixed_typ_ok: ok_pat => Typ.t =

let fixed_typ_err_common: error_common => Typ.t =
fun
| NoType(_) => Unknown(Internal) |> Typ.temp
| NoType(FreeConstructor(c)) =>
Sum([
ConstructorMap.Variant(c, [Id.invalid], None),
ConstructorMap.BadEntry(Unknown(Internal) |> Typ.temp),
])
|> Typ.temp
| NoType(BadToken(_))
| NoType(BadTrivAp(_))
| NoType(WantTuple)
| NoType(LabelNotFound(_))
| NoType(BadLabel(_))
| NoType(InvalidLabel(_)) => Unknown(Internal) |> Typ.temp
| TupleLabelError({typ, _})
| DuplicateLabel(_, typ) => typ
| Inconsistent(Expectation({ana, _})) => ana
Expand Down
7 changes: 6 additions & 1 deletion src/haz3lweb/view/NutMenu.re
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,12 @@ let stepper_group = (~globals: Globals.t) => {
s.show_hidden_steps,
Evaluation(ShowHiddenSteps),
),
("⏯️", "Filters", s.show_stepper_filters, Evaluation(ShowFilters)),
(
"⏯️",
"Show filters",
s.show_stepper_filters,
Evaluation(ShowFilters),
),
],
);
};
Expand Down
9 changes: 9 additions & 0 deletions src/util/ListUtil.re
Original file line number Diff line number Diff line change
Expand Up @@ -591,3 +591,12 @@ let minimum = (f: 'a => int, xs: list('a)): option('a) =>
};
loop(x, f(x), xs);
};

// for performance, doesn't check the whole list if already above length
let rec is_length = (n: int, xs: list('a)): bool =>
switch (xs) {
| [] when n == 0 => true
| _ when n <= 0 => false
| [] => false
| [_, ...xs] => is_length(n - 1, xs)
};
11 changes: 0 additions & 11 deletions test/Test_Elaboration.re
Original file line number Diff line number Diff line change
Expand Up @@ -995,16 +995,6 @@ module MenhirElaborationTests = {
failed_cast_uexp,
);

let constructor_str = "X";
let constructor_uexp: Exp.t =
Constructor("X", Unknown(Internal) |> Typ.fresh) |> Exp.fresh;
let constructor_menhir = () =>
alco_check_menhir(
"Constructor test (menhir)",
constructor_str,
constructor_uexp,
);

/*
<<1 / 2 ? `a`>>
*/
Expand Down Expand Up @@ -1172,7 +1162,6 @@ x
`Quick,
dynamic_error_hole_menhir,
),
test_case("Constructor test (menhir)", `Quick, constructor_menhir),
test_case("Failed cast test (menhir)", `Quick, failed_cast_menhir),
test_case("Type ap test (menhir)", `Quick, typ_ap_menhir),
test_case("Let expression for a tuple (menhir)", `Quick, let_exp_menhir),
Expand Down
44 changes: 44 additions & 0 deletions test/Test_Evaluator.re
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,44 @@ let test_unevaluated_if = () =>
|> Exp.fresh,
);

let test_invalid_constructor_match = () => {
let invalid_constructor_match =
Let(
Constructor("T", Unknown(Internal) |> Typ.fresh) |> Pat.fresh,
Int(1) |> Exp.fresh,
EmptyHole |> Exp.fresh,
)
|> Exp.fresh
|> elaborate;
evaluation_test(
"let T = 1 in ?",
invalid_constructor_match,
invalid_constructor_match,
);
};

let test_typfun_application = () =>
evaluation_test(
"(typfun T -> fun x -> 1)@<Int>(2)",
Int(1) |> Exp.fresh,
Ap(
Forward,
TypAp(
TypFun(
Var("T") |> TPat.fresh,
Fun(Var("x") |> Pat.fresh, Int(1) |> Exp.fresh, None, None)
|> Exp.fresh,
None,
)
|> Exp.fresh,
Int |> Typ.fresh,
)
|> Exp.fresh,
Int(2) |> Exp.fresh,
)
|> Exp.fresh,
);

let tests = (
"Evaluator",
[
Expand Down Expand Up @@ -340,6 +378,12 @@ in fn("hello")|},
test_case("Variable capture", `Quick, test_variable_capture),
test_case("Unbound lookup", `Quick, test_unbound_lookup),
test_case("Unevaluated if closure", `Quick, test_unevaluated_if),
test_case(
"Invalid constructor match",
`Quick,
test_invalid_constructor_match,
),
test_case("Typfun application", `Quick, test_typfun_application),
test_case("Negative integer literal", `Quick, () =>
evaluation_test(
"-8",
Expand Down

0 comments on commit 6b6cd28

Please sign in to comment.