summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast_util.ml6
-rw-r--r--src/ast_util.mli1
-rw-r--r--src/initial_check.ml17
-rw-r--r--src/parse_ast.ml4
-rw-r--r--src/parser.mly9
-rw-r--r--src/type_check.ml86
6 files changed, 85 insertions, 38 deletions
diff --git a/src/ast_util.ml b/src/ast_util.ml
index 546faf14..2fb90b02 100644
--- a/src/ast_util.ml
+++ b/src/ast_util.ml
@@ -669,16 +669,16 @@ and string_of_pexp (Pat_aux (pexp, _)) =
match pexp with
| Pat_exp (pat, exp) -> string_of_pat pat ^ " -> " ^ string_of_exp exp
| Pat_when (pat, guard, exp) -> string_of_pat pat ^ " when " ^ string_of_exp guard ^ " -> " ^ string_of_exp exp
-and string_of_tpat = function
+and string_of_typ_pat = function
| TP_wild -> "_"
| TP_var kid -> string_of_kid kid
- | TP_app (f, tpats) -> string_of_id f ^ "(" ^ string_of_list ", " string_of_tpat tpats ^ ")"
+ | TP_app (f, tpats) -> string_of_id f ^ "(" ^ string_of_list ", " string_of_typ_pat tpats ^ ")"
and string_of_pat (P_aux (pat, l)) =
match pat with
| P_lit lit -> string_of_lit lit
| P_wild -> "_"
| P_id v -> string_of_id v
- | P_var (pat, tpat) -> string_of_pat pat ^ " as " ^ string_of_tpat tpat
+ | P_var (pat, tpat) -> string_of_pat pat ^ " as " ^ string_of_typ_pat tpat
| P_typ (typ, pat) -> "(" ^ string_of_typ typ ^ ") " ^ string_of_pat pat
| P_tup pats -> "(" ^ string_of_list ", " string_of_pat pats ^ ")"
| P_app (f, pats) -> string_of_id f ^ "(" ^ string_of_list ", " string_of_pat pats ^ ")"
diff --git a/src/ast_util.mli b/src/ast_util.mli
index 5ceb29f8..5d2b01b8 100644
--- a/src/ast_util.mli
+++ b/src/ast_util.mli
@@ -194,6 +194,7 @@ val string_of_order : order -> string
val string_of_nexp : nexp -> string
val string_of_typ : typ -> string
val string_of_typ_arg : typ_arg -> string
+val string_of_typ_pat : typ_pat -> string
val string_of_annot : ('a * typ * effect) option -> string
val string_of_n_constraint : n_constraint -> string
val string_of_quant_item : quant_item -> string
diff --git a/src/initial_check.ml b/src/initial_check.ml
index 812bfaad..9516f53e 100644
--- a/src/initial_check.ml
+++ b/src/initial_check.ml
@@ -430,17 +430,26 @@ let to_ast_lit (Parse_ast.L_aux(lit,l)) : lit =
| Parse_ast.L_bin(b) -> L_bin(b)
| Parse_ast.L_real r -> L_real r
| Parse_ast.L_string(s) -> L_string(s))
- ,l)
-
+ ,l)
+
+let rec to_ast_typ_pat (Parse_ast.ATyp_aux (typ_aux, l)) =
+ match typ_aux with
+ | Parse_ast.ATyp_wild -> TP_wild
+ | Parse_ast.ATyp_var kid -> TP_var (to_ast_var kid)
+ | Parse_ast.ATyp_app (f, typs) ->
+ TP_app (to_ast_id f, List.map to_ast_typ_pat typs)
+ | _ -> typ_error l "Unexpected type in type pattern" None None None
+
let rec to_ast_pat (k_env : kind Envmap.t) (def_ord : order) (Parse_ast.P_aux(pat,l) : Parse_ast.pat) : unit pat =
P_aux(
(match pat with
| Parse_ast.P_lit(lit) -> P_lit(to_ast_lit lit)
| Parse_ast.P_wild -> P_wild
- | Parse_ast.P_as(pat,id) -> P_as(to_ast_pat k_env def_ord pat,to_ast_id id)
+ | Parse_ast.P_var (pat, Parse_ast.ATyp_aux (Parse_ast.ATyp_id id, _)) ->
+ P_as (to_ast_pat k_env def_ord pat, to_ast_id id)
| Parse_ast.P_typ(typ,pat) -> P_typ(to_ast_typ k_env def_ord typ,to_ast_pat k_env def_ord pat)
| Parse_ast.P_id(id) -> P_id(to_ast_id id)
- | Parse_ast.P_var (pat,kid) -> P_var (to_ast_pat k_env def_ord pat, TP_var (to_ast_var kid))
+ | Parse_ast.P_var (pat, typ) -> P_var (to_ast_pat k_env def_ord pat, to_ast_typ_pat typ)
| Parse_ast.P_app(id,pats) ->
if pats = []
then P_id (to_ast_id id)
diff --git a/src/parse_ast.ml b/src/parse_ast.ml
index 5eb8038a..ba948040 100644
--- a/src/parse_ast.ml
+++ b/src/parse_ast.ml
@@ -150,6 +150,7 @@ atyp_aux = (* expressions of all kinds, to be translated to types, nats, orders
| ATyp_default_ord (* default order for increasing or decreasing signficant bits *)
| ATyp_set of (base_effect) list (* effect set *)
| ATyp_fn of atyp * atyp * atyp (* Function type (first-order only in user code), last atyp is an effect *)
+ | ATyp_wild
| ATyp_tup of (atyp) list (* Tuple type *)
| ATyp_app of id * (atyp) list (* type constructor application *)
| ATyp_exist of kid list * n_constraint * atyp
@@ -239,10 +240,9 @@ type
pat_aux = (* Pattern *)
P_lit of lit (* literal constant pattern *)
| P_wild (* wildcard *)
- | P_as of pat * id (* named pattern *)
| P_typ of atyp * pat (* typed pattern *)
| P_id of id (* identifier *)
- | P_var of pat * kid (* bind pat to type variable *)
+ | P_var of pat * atyp (* bind pat to type variable *)
| P_app of id * (pat) list (* union constructor pattern *)
| P_record of (fpat) list * bool (* struct pattern *)
| P_vector of (pat) list (* vector pattern *)
diff --git a/src/parser.mly b/src/parser.mly
index 32ee3368..b781ea1f 100644
--- a/src/parser.mly
+++ b/src/parser.mly
@@ -512,6 +512,8 @@ typ9r:
atomic_typ:
| id
{ mk_typ (ATyp_id $1) $startpos $endpos }
+ | Under
+ { mk_typ ATyp_wild $startpos $endpos }
| kid
{ mk_typ (ATyp_var $1) $startpos $endpos }
| Num
@@ -654,9 +656,7 @@ pat_concat:
pat:
| pat1
{ $1 }
- | pat1 As id
- { mk_pat (P_as ($1, $3)) $startpos $endpos }
- | pat1 As kid
+ | pat1 As typ
{ mk_pat (P_var ($1, $3)) $startpos $endpos }
pat_list:
@@ -673,7 +673,8 @@ atomic_pat:
| id
{ mk_pat (P_id $1) $startpos $endpos }
| kid
- { mk_pat (P_var (mk_pat (P_id (id_of_kid $1)) $startpos $endpos, $1)) $startpos $endpos }
+ { mk_pat (P_var (mk_pat (P_id (id_of_kid $1)) $startpos $endpos,
+ mk_typ (ATyp_var $1) $startpos $endpos)) $startpos $endpos }
| id Lparen pat_list Rparen
{ mk_pat (P_app ($1, $3)) $startpos $endpos }
| atomic_pat Colon typ
diff --git a/src/type_check.ml b/src/type_check.ml
index 2fcfb309..4d599125 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -1261,6 +1261,21 @@ let order_frees (Ord_aux (ord_aux, l)) =
| Ord_var kid -> KidSet.singleton kid
| _ -> KidSet.empty
+let rec typ_nexps (Typ_aux (typ_aux, l)) =
+ match typ_aux with
+ | Typ_id v -> []
+ | Typ_var kid -> []
+ | Typ_tup typs -> List.concat (List.map typ_nexps typs)
+ | Typ_app (f, args) -> List.concat (List.map typ_arg_nexps args)
+ | Typ_exist (kids, nc, typ) -> typ_nexps typ
+ | Typ_fn (typ1, typ2, _) ->
+ typ_nexps typ1 @ typ_nexps typ2
+and typ_arg_nexps (Typ_arg_aux (typ_arg_aux, l)) =
+ match typ_arg_aux with
+ | Typ_arg_nexp n -> [n]
+ | Typ_arg_typ typ -> typ_nexps typ
+ | Typ_arg_order ord -> []
+
let rec typ_frees ?exs:(exs=KidSet.empty) (Typ_aux (typ_aux, l)) =
match typ_aux with
| Typ_id v -> KidSet.empty
@@ -2372,40 +2387,36 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ)
| Unification_error (l, m) -> typ_error l ("Unification error when pattern matching against union constructor: " ^ m)
end
end
- | P_var (pat, TP_var kid) ->
+ | P_var (pat, typ_pat) ->
let typ = Env.expand_synonyms env typ in
- begin
- match destruct_exist env typ, typ with
- | Some ([kid'], nc, ex_typ), _ ->
- let env = Env.add_typ_var kid BK_nat env in
- let ex_typ = typ_subst_nexp kid' (Nexp_var kid) ex_typ in
- let env = Env.add_constraint (nc_subst_nexp kid' (Nexp_var kid) nc) env in
- let typed_pat, env, guards = bind_pat env pat ex_typ in
- annot_pat (P_var (typed_pat, TP_var kid)) typ, env, guards
- | Some _, _ -> typ_error l ("Cannot bind type variable pattern against multiple argument existential")
- | None, Typ_aux (Typ_id id, _) when Id.compare id (mk_id "int") == 0 ->
- let env = Env.add_typ_var kid BK_nat env in
- let typed_pat, env, guards = bind_pat env pat (atom_typ (nvar kid)) in
- annot_pat (P_var (typed_pat, TP_var kid)) typ, env, guards
- | None, Typ_aux (Typ_id id, _) when Id.compare id (mk_id "nat") == 0 ->
+ let kid = Env.fresh_kid env in
+ let env, ex_typ = match destruct_exist env typ, typ with
+ | Some (kids, nc, ex_typ), _ ->
+ let env = List.fold_left (fun env kid -> Env.add_typ_var kid BK_nat env) env kids in
+ let env = Env.add_constraint nc env in
+ env, ex_typ
+ | None, Typ_aux (Typ_id id, _) when string_of_id id = "int" ->
+ Env.add_typ_var kid BK_nat env, atom_typ (nvar kid)
+ | None, Typ_aux (Typ_id id, _) when string_of_id id = "nat" ->
let env = Env.add_typ_var kid BK_nat env in
let env = Env.add_constraint (nc_gt (nvar kid) (nint 0)) env in
- let typed_pat, env, guards = bind_pat env pat (atom_typ (nvar kid)) in
- annot_pat (P_var (typed_pat, TP_var kid)) typ, env, guards
+ env, atom_typ (nvar kid)
| None, Typ_aux (Typ_app (id, [Typ_arg_aux (Typ_arg_nexp lo, _); Typ_arg_aux (Typ_arg_nexp hi, _)]), _)
- when Id.compare id (mk_id "range") == 0 ->
+ when string_of_id id = "range" ->
let env = Env.add_typ_var kid BK_nat env in
- let env = Env.add_constraint (nc_and (nc_lteq lo (nvar kid)) (nc_lteq (nvar kid) hi)) env in
- let typed_pat, env, guards = bind_pat env pat (atom_typ (nvar kid)) in
- annot_pat (P_var (typed_pat, TP_var kid)) typ, env, guards
+ let env = Env.add_constraint (nc_lteq lo (nvar kid)) env in
+ let env = Env.add_constraint (nc_lteq (nvar kid) hi) env in
+ env, atom_typ (nvar kid)
| None, Typ_aux (Typ_app (id, [Typ_arg_aux (Typ_arg_nexp n, _)]), _)
- when Id.compare id (mk_id "atom") == 0 ->
+ when string_of_id id = "atom" ->
let env = Env.add_typ_var kid BK_nat env in
let env = Env.add_constraint (nc_eq (nvar kid) n) env in
- let typed_pat, env, guards = bind_pat env pat (atom_typ (nvar kid)) in
- annot_pat (P_var (typed_pat, TP_var kid)) typ, env, guards
+ env, atom_typ (nvar kid)
| None, _ -> typ_error l ("Cannot bind type variable against non existential or numeric type")
- end
+ in
+ let env = bind_typ_pat l env typ_pat ex_typ in
+ let typed_pat, env, guards = bind_pat env pat ex_typ in
+ annot_pat (P_var (typed_pat, typ_pat)) typ, env, guards
| P_wild -> annot_pat P_wild typ, env, []
| P_cons (hd_pat, tl_pat) ->
begin
@@ -2548,6 +2559,31 @@ and infer_pat env (P_aux (pat_aux, (l, ())) as pat) =
guards
| _ -> typ_error l ("Couldn't infer type of pattern " ^ string_of_pat pat)
+and bind_typ_pat l env typ_pat (Typ_aux (typ_aux, _) as typ) =
+ match typ_pat, typ_aux with
+ | TP_wild, _ -> env
+ | TP_var kid, _ ->
+ begin
+ match typ_nexps typ with
+ | [nexp] ->
+ Env.add_constraint (nc_eq (nvar kid) nexp) (Env.add_typ_var kid BK_nat env)
+ | [] ->
+ typ_error l ("No numeric expressions in " ^ string_of_typ typ ^ " to bind " ^ string_of_kid kid ^ " to")
+ | nexps ->
+ typ_error l ("Type " ^ string_of_typ typ ^ " has multiple numeric expressions. Cannot bind " ^ string_of_kid kid)
+ end
+ | TP_app (f1, tpats), Typ_app (f2, typs) when Id.compare f1 f2 = 0->
+ List.fold_left2 (bind_typ_pat_arg l) env tpats typs
+ | _, _ -> typ_error l ("Couldn't bind type " ^ string_of_typ typ ^ " with " ^ string_of_typ_pat typ_pat)
+and bind_typ_pat_arg l env typ_pat (Typ_arg_aux (typ_arg_aux, _) as typ_arg) =
+ match typ_pat, typ_arg_aux with
+ | TP_wild, _ -> env
+ | TP_var kid, Typ_arg_nexp nexp ->
+ Env.add_constraint (nc_eq (nvar kid) nexp) (Env.add_typ_var kid BK_nat env)
+ | _, Typ_arg_typ typ -> bind_typ_pat l env typ_pat typ
+ | _, Typ_arg_order _ -> typ_error l "Cannot bind type pattern against order"
+ | _, _ -> typ_error l ("Couldn't bind type argument " ^ string_of_typ_arg typ_arg ^ " with " ^ string_of_typ_pat typ_pat)
+
and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as exp) =
let annot_assign lexp exp = E_aux (E_assign (lexp, exp), (l, Some (env, mk_typ (Typ_id (mk_id "unit")), no_effect))) in
let annot_lexp_effect lexp typ eff = LEXP_aux (lexp, (l, Some (env, typ, eff))) in