summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrian Campbell2017-08-17 10:58:00 +0100
committerBrian Campbell2017-08-17 10:58:00 +0100
commitbc156a0c30ddc4e09586ec43e901ce94832bc8e3 (patch)
tree5fbb467a0c0f4882b8c1b4add4c730a308af3bab /src
parentf88cb793118d28d061fdee4d5bd8317f541136b8 (diff)
parent9f013687086937df8be81dd6a0ebd86fc750abf7 (diff)
Merge branch 'experiments' of bitbucket.org:Peter_Sewell/sail into mono-experiments
Diffstat (limited to 'src')
-rw-r--r--src/ast.ml4
-rw-r--r--src/ast_util.ml11
-rw-r--r--src/ast_util.mli2
-rw-r--r--src/initial_check.ml8
-rw-r--r--src/lexer.mll3
-rw-r--r--src/lexer2.mll80
-rw-r--r--src/monomorphise.ml3
-rw-r--r--src/parse_ast.ml3
-rw-r--r--src/parser.mly6
-rw-r--r--src/parser2.mly471
-rw-r--r--src/pretty_print_common.ml1
-rw-r--r--src/pretty_print_lem.ml1
-rw-r--r--src/pretty_print_lem_ast.ml3
-rw-r--r--src/pretty_print_ocaml.ml1
-rw-r--r--src/pretty_print_sail.ml6
-rw-r--r--src/type_check.ml108
-rw-r--r--src/type_check.mli29
17 files changed, 605 insertions, 135 deletions
diff --git a/src/ast.ml b/src/ast.ml
index 6a74d5b2..710e8067 100644
--- a/src/ast.ml
+++ b/src/ast.ml
@@ -238,7 +238,6 @@ and typ_arg_aux = (* Type constructor arguments of all kinds *)
Typ_arg_nexp of nexp
| Typ_arg_typ of typ
| Typ_arg_order of order
- | Typ_arg_effect of effect
and typ_arg =
Typ_arg_aux of typ_arg_aux * l
@@ -261,6 +260,7 @@ type
| P_as of 'a pat * id (* named pattern *)
| P_typ of typ * 'a pat (* typed pattern *)
| P_id of id (* identifier *)
+ | P_var of kid (* bind identifier and type variable *)
| P_app of id * ('a pat) list (* union constructor pattern *)
| P_record of ('a fpat) list * bool (* struct pattern *)
| P_vector of ('a pat) list (* vector pattern *)
@@ -320,6 +320,8 @@ type
| E_sizeof of nexp (* Expression to return the value of the nexp variable or expression at run time *)
| E_constraint of n_constraint (* Expression to evaluate the n_constraint at run time *)
| E_exit of 'a exp (* expression to halt all current execution, potentially calling a system, trap, or interrupt handler with exp *)
+ | E_throw of 'a exp
+ | E_try of 'a exp * ('a pexp) list
| E_return of 'a exp (* expression to end current function execution and return the value of exp from the function; this can be used to break out of for loops *)
| E_assert of 'a exp * 'a exp (* expression to halt with error, when the first expression is false, reporting the optional string as an error *)
| E_internal_cast of 'a annot * 'a exp (* This is an internal cast, generated during type checking that will resolve into a syntactic cast after *)
diff --git a/src/ast_util.ml b/src/ast_util.ml
index 67381c52..ddd83429 100644
--- a/src/ast_util.ml
+++ b/src/ast_util.ml
@@ -77,11 +77,13 @@ and map_exp_annot_aux f = function
| E_record_update (exp, fexps) -> E_record_update (map_exp_annot f exp, map_fexps_annot f fexps)
| E_field (exp, id) -> E_field (map_exp_annot f exp, id)
| E_case (exp, cases) -> E_case (map_exp_annot f exp, List.map (map_pexp_annot f) cases)
+ | E_try (exp, cases) -> E_try (map_exp_annot f exp, List.map (map_pexp_annot f) cases)
| E_let (letbind, exp) -> E_let (map_letbind_annot f letbind, map_exp_annot f exp)
| E_assign (lexp, exp) -> E_assign (map_lexp_annot f lexp, map_exp_annot f exp)
| E_sizeof nexp -> E_sizeof nexp
| E_constraint nc -> E_constraint nc
| E_exit exp -> E_exit (map_exp_annot f exp)
+ | E_throw exp -> E_throw (map_exp_annot f exp)
| E_return exp -> E_return (map_exp_annot f exp)
| E_assert (test, msg) -> E_assert (map_exp_annot f test, map_exp_annot f msg)
| E_internal_cast (annot, exp) -> E_internal_cast (f annot, map_exp_annot f exp)
@@ -110,6 +112,7 @@ and map_pat_annot_aux f = function
| P_as (pat, id) -> P_as (map_pat_annot f pat, id)
| P_typ (typ, pat) -> P_typ (typ, map_pat_annot f pat)
| P_id id -> P_id id
+ | P_var kid -> P_var kid
| P_app (id, pats) -> P_app (id, List.map (map_pat_annot f) pats)
| P_record (fpats, b) -> P_record (List.map (map_fpat_annot f) fpats, b)
| P_tup pats -> P_tup (List.map (map_pat_annot f) pats)
@@ -143,6 +146,9 @@ let string_of_id = function
| Id_aux (Id v, _) -> v
| Id_aux (DeIid v, _) -> "(deinfix " ^ v ^ ")"
+let id_of_kid = function
+ | Kid_aux (Var v, l) -> Id_aux (Id (String.sub v 1 (String.length v - 1)), l)
+
let string_of_kid = function
| Kid_aux (Var v, _) -> v
@@ -220,7 +226,6 @@ and string_of_typ_arg_aux = function
| Typ_arg_nexp n -> string_of_nexp n
| Typ_arg_typ typ -> string_of_typ typ
| Typ_arg_order o -> string_of_order o
- | Typ_arg_effect eff -> string_of_effect eff
and string_of_n_constraint = function
| NC_aux (NC_fixed (n1, n2), _) -> string_of_nexp n1 ^ " = " ^ string_of_nexp n2
| NC_aux (NC_not_equal (n1, n2), _) -> string_of_nexp n1 ^ " != " ^ string_of_nexp n2
@@ -279,6 +284,8 @@ let rec string_of_exp (E_aux (exp, _)) =
| E_tuple exps -> "(" ^ string_of_list ", " string_of_exp exps ^ ")"
| E_case (exp, cases) ->
"switch " ^ string_of_exp exp ^ " { case " ^ string_of_list " case " string_of_pexp cases ^ "}"
+ | E_try (exp, cases) ->
+ "try " ^ string_of_exp exp ^ " catch { case " ^ string_of_list " case " string_of_pexp cases ^ "}"
| E_let (letbind, exp) -> "let " ^ string_of_letbind letbind ^ " in " ^ string_of_exp exp
| E_assign (lexp, bind) -> string_of_lexp lexp ^ " := " ^ string_of_exp bind
| E_cast (typ, exp) -> "(" ^ string_of_typ typ ^ ") " ^ string_of_exp exp
@@ -297,6 +304,7 @@ let rec string_of_exp (E_aux (exp, _)) =
^ string_of_exp body
| E_assert (test, msg) -> "assert(" ^ string_of_exp test ^ ", " ^ string_of_exp msg ^ ")"
| E_exit exp -> "exit " ^ string_of_exp exp
+ | E_throw exp -> "throw " ^ string_of_exp exp
| E_cons (x, xs) -> string_of_exp x ^ " :: " ^ string_of_exp xs
| E_list xs -> "[||" ^ string_of_list ", " string_of_exp xs ^ "||]"
| _ -> "INTERNAL"
@@ -309,6 +317,7 @@ and string_of_pat (P_aux (pat, l)) =
| P_lit lit -> string_of_lit lit
| P_wild -> "_"
| P_id v -> string_of_id v
+ | P_var kid -> string_of_kid kid
| 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 ae340839..94f3f0cc 100644
--- a/src/ast_util.mli
+++ b/src/ast_util.mli
@@ -86,6 +86,8 @@ val string_of_index_range : index_range -> string
val id_of_fundef : 'a fundef -> id
+val id_of_kid : kid -> id
+
module Id : sig
type t = id
val compare : id -> id -> int
diff --git a/src/initial_check.ml b/src/initial_check.ml
index 9d295dda..e5717389 100644
--- a/src/initial_check.ml
+++ b/src/initial_check.ml
@@ -73,7 +73,7 @@ let rec kind_to_string kind = match kind.k with
| K_Lam (kinds,kind) -> "Lam [" ^ string_of_list ", " kind_to_string kinds ^ "] -> " ^ (kind_to_string kind)
(*Envs is a tuple of used names (currently unused), map from id to kind, default order for vector types and literal vectors *)
-type envs = Nameset.t * kind Envmap.t * order
+type envs = Nameset.t * kind Envmap.t * order
type 'a envs_out = 'a * envs
let id_to_string (Id_aux(id,l)) =
@@ -236,7 +236,7 @@ and to_ast_nexp (k_env : kind Envmap.t) (n: Parse_ast.atyp) : Ast.nexp =
let n1 = to_ast_nexp k_env t1 in
let n2 = to_ast_nexp k_env t2 in
Nexp_aux (Nexp_minus (n1, n2), l)
- | _ -> typ_error l "Requred an item of kind Nat, encountered an illegal form for this kind" None None None)
+ | _ -> typ_error l "Required an item of kind Nat, encountered an illegal form for this kind" None None None)
and to_ast_order (k_env : kind Envmap.t) (def_ord : order) (o: Parse_ast.atyp) : Ast.order =
match o with
@@ -301,7 +301,6 @@ and to_ast_typ_arg (k_env : kind Envmap.t) (def_ord : order) (kind : kind) (arg
| K_Typ -> Typ_arg_typ (to_ast_typ k_env def_ord arg)
| K_Nat -> Typ_arg_nexp (to_ast_nexp k_env arg)
| K_Ord -> Typ_arg_order (to_ast_order k_env def_ord arg)
- | K_Efct -> Typ_arg_effect (to_ast_effects k_env arg)
| _ -> raise (Reporting_basic.err_unreachable l ("To_ast_typ_arg received Lam kind or infer kind: " ^ kind_to_string kind))),
l)
@@ -416,6 +415,7 @@ let rec to_ast_pat (k_env : kind Envmap.t) (def_ord : order) (Parse_ast.P_aux(pa
| Parse_ast.P_as(pat,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 kid -> P_var (to_ast_var kid)
| Parse_ast.P_app(id,pats) ->
if pats = []
then P_id (to_ast_id id)
@@ -498,11 +498,13 @@ and to_ast_exp (k_env : kind Envmap.t) (def_ord : order) (Parse_ast.E_aux(exp,l)
| _ -> raise (Reporting_basic.err_unreachable l "to_ast_fexps with true returned none"))
| Parse_ast.E_field(exp,id) -> E_field(to_ast_exp k_env def_ord exp, to_ast_id id)
| Parse_ast.E_case(exp,pexps) -> E_case(to_ast_exp k_env def_ord exp, List.map (to_ast_case k_env def_ord) pexps)
+ | Parse_ast.E_try (exp, pexps) -> E_try (to_ast_exp k_env def_ord exp, List.map (to_ast_case k_env def_ord) pexps)
| Parse_ast.E_let(leb,exp) -> E_let(to_ast_letbind k_env def_ord leb, to_ast_exp k_env def_ord exp)
| Parse_ast.E_assign(lexp,exp) -> E_assign(to_ast_lexp k_env def_ord lexp, to_ast_exp k_env def_ord exp)
| Parse_ast.E_sizeof(nexp) -> E_sizeof(to_ast_nexp k_env nexp)
| Parse_ast.E_constraint nc -> E_constraint (to_ast_nexp_constraint k_env nc)
| Parse_ast.E_exit exp -> E_exit(to_ast_exp k_env def_ord exp)
+ | Parse_ast.E_throw exp -> E_throw (to_ast_exp k_env def_ord exp)
| Parse_ast.E_return exp -> E_return(to_ast_exp k_env def_ord exp)
| Parse_ast.E_assert(cond,msg) -> E_assert(to_ast_exp k_env def_ord cond, to_ast_exp k_env def_ord msg)
), (l,()))
diff --git a/src/lexer.mll b/src/lexer.mll
index 228ca38f..cf3c9baf 100644
--- a/src/lexer.mll
+++ b/src/lexer.mll
@@ -78,6 +78,9 @@ let kw_table =
("extern", (fun _ -> Extern));
("cast", (fun _ -> Cast));
("false", (fun _ -> False));
+ ("try", (fun _ -> Try));
+ ("catch", (fun _ -> Catch));
+ ("throw", (fun _ -> Throw));
("forall", (fun _ -> Forall));
("exist", (fun _ -> Exist));
("foreach", (fun _ -> Foreach));
diff --git a/src/lexer2.mll b/src/lexer2.mll
index a51067aa..f5350ea8 100644
--- a/src/lexer2.mll
+++ b/src/lexer2.mll
@@ -49,18 +49,41 @@ let r = fun s -> s (* Ulib.Text.of_latin1 *)
(* Available as Scanf.unescaped since OCaml 4.0 but 3.12 is still common *)
let unescaped s = Scanf.sscanf ("\"" ^ s ^ "\"") "%S%!" (fun x -> x)
-let mk_operator n op =
- match n with
- | 0 -> Op0 op
- | 1 -> Op1 op
- | 2 -> Op2 op
- | 3 -> Op3 op
- | 4 -> Op4 op
- | 5 -> Op5 op
- | 6 -> Op6 op
- | 7 -> Op7 op
- | 8 -> Op8 op
- | 9 -> Op9 op
+type prec = Infix | InfixL | InfixR
+
+let mk_operator prec n op =
+ match prec, n with
+ | Infix, 0 -> Op0 op
+ | Infix, 1 -> Op1 op
+ | Infix, 2 -> Op2 op
+ | Infix, 3 -> Op3 op
+ | Infix, 4 -> Op4 op
+ | Infix, 5 -> Op5 op
+ | Infix, 6 -> Op6 op
+ | Infix, 7 -> Op7 op
+ | Infix, 8 -> Op8 op
+ | Infix, 9 -> Op9 op
+ | InfixL, 0 -> Op0l op
+ | InfixL, 1 -> Op1l op
+ | InfixL, 2 -> Op2l op
+ | InfixL, 3 -> Op3l op
+ | InfixL, 4 -> Op4l op
+ | InfixL, 5 -> Op5l op
+ | InfixL, 6 -> Op6l op
+ | InfixL, 7 -> Op7l op
+ | InfixL, 8 -> Op8l op
+ | InfixL, 9 -> Op9l op
+ | InfixR, 0 -> Op0r op
+ | InfixR, 1 -> Op1r op
+ | InfixR, 2 -> Op2r op
+ | InfixR, 3 -> Op3r op
+ | InfixR, 4 -> Op4r op
+ | InfixR, 5 -> Op5r op
+ | InfixR, 6 -> Op6r op
+ | InfixR, 7 -> Op7r op
+ | InfixR, 8 -> Op8r op
+ | InfixR, 9 -> Op9r op
+ | _, _ -> assert false
let operators = ref M.empty
@@ -82,13 +105,11 @@ let kw_table =
("def", (fun _ -> Def));
("op", (fun _ -> Op));
("default", (fun _ -> Default));
- ("deinfix", (fun _ -> Deinfix));
("effect", (fun _ -> Effect));
("Effect", (fun _ -> EFFECT));
("end", (fun _ -> End));
("enum", (fun _ -> Enum));
("else", (fun _ -> Else));
- ("exit", (fun _ -> Exit));
("extern", (fun _ -> Extern));
("cast", (fun _ -> Cast));
("false", (fun _ -> False));
@@ -96,6 +117,9 @@ let kw_table =
("foreach", (fun _ -> Foreach));
("function", (fun x -> Function_));
("overload", (fun _ -> Overload));
+ ("throw", (fun _ -> Throw));
+ ("try", (fun _ -> Try));
+ ("catch", (fun _ -> Catch));
("if", (fun x -> If_));
("in", (fun x -> In));
("inc", (fun _ -> Inc));
@@ -112,7 +136,6 @@ let kw_table =
("sizeof", (fun x -> Sizeof));
("constraint", (fun x -> Constraint));
("struct", (fun x -> Struct));
- ("switch", (fun x -> Switch));
("then", (fun x -> Then));
("true", (fun x -> True));
("Type", (fun x -> TYPE));
@@ -120,7 +143,6 @@ let kw_table =
("undefined", (fun x -> Undefined));
("union", (fun x -> Union));
("with", (fun x -> With));
- ("when", (fun x -> When));
("val", (fun x -> Val));
("div", (fun x -> Div_));
@@ -145,12 +167,7 @@ let kw_table =
("unspec", (fun x -> Unspec));
("nondet", (fun x -> Nondet));
("escape", (fun x -> Escape));
-
-]
-
-let default_type_names = ["bool";"unit";"vector";"range";"list";"bit";"nat"; "int"; "real";
- "uint8";"uint16";"uint32";"uint64";"atom";"implicit";"string";"option"]
-let custom_type_names : string list ref = ref []
+ ]
}
@@ -164,6 +181,7 @@ let startident = letter|'_'
let ident = alphanum|['_''\'']
let tyvar_start = '\''
let oper_char = ['!''$''%''&''*''+''-''.''/'':''<''=''>''?''@''^''|''~']
+let operator = oper_char+ ('_' ident)?
let escape_sequence = ('\\' ['\\''\"''\'''n''t''b''r']) | ('\\' digit digit digit) | ('\\' 'x' hexdigit hexdigit)
rule token = parse
@@ -173,11 +191,12 @@ rule token = parse
{ Lexing.new_line lexbuf;
token lexbuf }
| "&" { (Amp(r"&")) }
- | "|" { Bar }
+ | "@" { (At "@") }
| "2" ws "^" { TwoCaret }
| "^" { (Caret(r"^")) }
| ":" { Colon(r ":") }
| "," { Comma }
+ | ".." { DotDot }
| "." { Dot }
| "=" { (Eq(r"=")) }
| ">" { (Gt(r">")) }
@@ -187,6 +206,9 @@ rule token = parse
| ";" { Semi }
| "*" { (Star(r"*")) }
| "_" { Under }
+ | "{|" { LcurlyBar }
+ | "|}" { RcurlyBar }
+ | "|" { Bar }
| "{" { Lcurly }
| "}" { Rcurly }
| "()" { Unit(r"()") }
@@ -199,10 +221,16 @@ rule token = parse
| "->" { MinusGt }
| "=>" { EqGt(r "=>") }
| "<=" { (LtEq(r"<=")) }
- | "infix" ws (digit as p) ws (oper_char+ as op)
- { operators := M.add op (mk_operator (int_of_string (Char.escaped p)) op) !operators;
+ | "infix" ws (digit as p) ws (operator as op)
+ { operators := M.add op (mk_operator Infix (int_of_string (Char.escaped p)) op) !operators;
+ token lexbuf }
+ | "infixl" ws (digit as p) ws (operator as op)
+ { operators := M.add op (mk_operator InfixL (int_of_string (Char.escaped p)) op) !operators;
+ token lexbuf }
+ | "infixr" ws (digit as p) ws (operator as op)
+ { operators := M.add op (mk_operator InfixR (int_of_string (Char.escaped p)) op) !operators;
token lexbuf }
- | oper_char+ as op
+ | operator as op
{ try M.find op !operators
with Not_found -> raise (LexError ("Operator fixity undeclared", Lexing.lexeme_start_p lexbuf)) }
| "(*" { comment (Lexing.lexeme_start_p lexbuf) 0 lexbuf; token lexbuf }
diff --git a/src/monomorphise.ml b/src/monomorphise.ml
index a9ddd1a7..d9ee73b8 100644
--- a/src/monomorphise.ml
+++ b/src/monomorphise.ml
@@ -56,8 +56,7 @@ let subst_src_typ substs t =
match ta with
| Typ_arg_nexp ne -> Typ_arg_aux (Typ_arg_nexp (s_snexp ne),l)
| Typ_arg_typ t -> Typ_arg_aux (Typ_arg_typ (s_styp t),l)
- | Typ_arg_order _
- | Typ_arg_effect _ -> targ
+ | Typ_arg_order _ -> targ
in s_styp t
let make_vector_lit sz i =
diff --git a/src/parse_ast.ml b/src/parse_ast.ml
index 8ce5e77d..3951ab51 100644
--- a/src/parse_ast.ml
+++ b/src/parse_ast.ml
@@ -234,6 +234,7 @@ pat_aux = (* Pattern *)
| P_as of pat * id (* named pattern *)
| P_typ of atyp * pat (* typed pattern *)
| P_id of id (* identifier *)
+ | P_var of kid
| P_app of id * (pat) list (* union constructor pattern *)
| P_record of (fpat) list * bool (* struct pattern *)
| P_vector of (pat) list (* vector pattern *)
@@ -283,6 +284,8 @@ exp_aux = (* Expression *)
| E_sizeof of atyp
| E_constraint of n_constraint
| E_exit of exp
+ | E_throw of exp
+ | E_try of exp * pexp list
| E_return of exp
| E_assert of exp * exp
diff --git a/src/parser.mly b/src/parser.mly
index d6da6e63..12e64141 100644
--- a/src/parser.mly
+++ b/src/parser.mly
@@ -131,7 +131,7 @@ let make_vector_sugar order_set is_inc typ typ1 =
%token And Alias As Assert Bitzero Bitone Bits By Case Clause Const Dec Def Default Deinfix Effect EFFECT End
%token Enumerate Else Exit Extern False Forall Exist Foreach Overload Function_ If_ In IN Inc Let_ Member Nat NatNum Order Cast
%token Pure Rec Register Return Scattered Sizeof Struct Switch Then True TwoStarStar Type TYPE Typedef
-%token Undefined Union With When Val Constraint
+%token Undefined Union With When Val Constraint Try Catch Throw
%token Barr Depend Rreg Wreg Rmem Rmemt Wmem Wmv Wmvt Eamem Exmem Undef Unspec Nondet Escape
@@ -609,10 +609,14 @@ atomic_exp:
{ eloc (E_list($2)) }
| Switch exp Lcurly case_exps Rcurly
{ eloc (E_case($2,$4)) }
+ | Try exp Catch Lcurly case_exps Rcurly
+ { eloc (E_try ($2, $5)) }
| Sizeof atomic_typ
{ eloc (E_sizeof($2)) }
| Constraint Lparen nexp_constraint Rparen
{ eloc (E_constraint $3) }
+ | Throw atomic_exp
+ { eloc (E_throw $2) }
| Exit atomic_exp
{ eloc (E_exit $2) }
| Return atomic_exp
diff --git a/src/parser2.mly b/src/parser2.mly
index c67fad59..bde542e0 100644
--- a/src/parser2.mly
+++ b/src/parser2.mly
@@ -53,6 +53,7 @@ let mk_kid str n m = Kid_aux (Var str, loc n m)
let deinfix (Id_aux (Id v, l)) = Id_aux (DeIid v, l)
+let mk_effect e n m = BE_aux (e, loc n m)
let mk_typ t n m = ATyp_aux (t, loc n m)
let mk_pat p n m = P_aux (p, loc n m)
let mk_pexp p n m = Pat_aux (p, loc n m)
@@ -61,12 +62,14 @@ let mk_lit l n m = L_aux (l, loc n m)
let mk_lit_exp l n m = mk_exp (E_lit (mk_lit l n m)) n m
let mk_typschm tq t n m = TypSchm_aux (TypSchm_ts (tq, t), loc n m)
let mk_nc nc n m = NC_aux (nc, loc n m)
+let mk_sd s n m = SD_aux (s, loc n m)
let mk_funcl f n m = FCL_aux (f, loc n m)
let mk_fun fn n m = FD_aux (fn, loc n m)
let mk_td t n m = TD_aux (t, loc n m)
let mk_vs v n m = VS_aux (v, loc n m)
let mk_reg_dec d n m = DEC_aux (d, loc n m)
+let mk_default d n m = DT_aux (d, loc n m)
let qi_id_of_kopt (KOpt_aux (kopt_aux, l) as kopt) = QI_aux (QI_id kopt, l)
@@ -118,10 +121,10 @@ let rec desugar_rchain chain s e =
/*Terminals with no content*/
-%token And As Assert Bitzero Bitone Bits By Match Clause Const Dec Def Default Deinfix Effect EFFECT End Op
-%token Enum Else Exit Extern False Forall Exist Foreach Overload Function_ If_ In IN Inc Let_ Member Int Order Cast
-%token Pure Rec Register Return Scattered Sizeof Struct Switch Then True TwoCaret Type TYPE Typedef
-%token Undefined Union With When Val Constraint
+%token And As Assert Bitzero Bitone Bits By Match Clause Const Dec Def Default Effect EFFECT End Op
+%token Enum Else Extern False Forall Exist Foreach Overload Function_ If_ In IN Inc Let_ Member Int Order Cast
+%token Pure Rec Register Return Scattered Sizeof Struct Then True TwoCaret Type TYPE Typedef
+%token Undefined Union With Val Constraint Throw Try Catch
%token Barr Depend Rreg Wreg Rmem Rmemt Wmem Wmv Wmvt Eamem Exmem Undef Unspec Nondet Escape
%nonassoc Then
@@ -129,10 +132,10 @@ let rec desugar_rchain chain s e =
%token Div_ Mod ModUnderS Quot Rem QuotUnderS
-%token Bar Comma Dot Eof Minus Semi Under
-%token Lcurly Rcurly Lparen Rparen Lsquare Rsquare
-%token BarBar BarSquare BarBarSquare ColonEq ColonGt ColonSquare DotDot
-%token MinusGt LtBar LtColon SquareBar SquareBarBar SquareColon
+%token Bar Comma Dot Eof Minus Semi Under DotDot
+%token Lcurly Rcurly Lparen Rparen Lsquare Rsquare LcurlyBar RcurlyBar
+%token BarBar BarSquare BarBarSquare ColonEq ColonGt ColonSquare
+%token MinusGt LtBar LtColon SquareBar SquareBarBar
/*Terminals with content*/
@@ -140,17 +143,14 @@ let rec desugar_rchain chain s e =
%token <int> Num
%token <string> String Bin Hex Real
-%token <string> Amp At Caret Div Eq Excl Gt Lt Plus Star Tilde EqGt Unit
+%token <string> Amp At Caret Div Eq Excl Gt Lt Plus Star EqGt Unit
%token <string> Colon ExclEq
%token <string> GtEq GtEqPlus GtGt GtGtGt GtPlus HashGtGt HashLtLt
%token <string> LtEq LtEqPlus LtGt LtLt LtLtLt LtPlus StarStar
-%token <string> GtEqUnderS GtEqUnderSi GtEqUnderU GtEqUnderUi GtGtUnderU GtUnderS
-%token <string> GtUnderSi GtUnderU GtUnderUi LtEqUnderS LtEqUnderSi LtEqUnderU
-%token <string> LtEqUnderUi LtUnderS LtUnderSi LtUnderU LtUnderUi StarStarUnderS StarStarUnderSi StarUnderS
-%token <string> StarUnderSi StarUnderU StarUnderUi PlusUnderS MinusUnderS
-
%token <string> Op0 Op1 Op2 Op3 Op4 Op5 Op6 Op7 Op8 Op9
+%token <string> Op0l Op1l Op2l Op3l Op4l Op5l Op6l Op7l Op8l Op9l
+%token <string> Op0r Op1r Op2r Op3r Op4r Op5r Op6r Op7r Op8r Op9r
%start file
%type <Parse_ast.defs> defs
@@ -159,32 +159,44 @@ let rec desugar_rchain chain s e =
%%
id:
- | Id
- { mk_id (Id $1) $startpos $endpos }
- | Op Op1
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op2
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op3
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op4
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op5
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op6
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op7
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op8
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Op9
- { mk_id (DeIid $2) $startpos $endpos }
- | Op Plus
- { mk_id (DeIid "+") $startpos $endpos }
- | Op Minus
- { mk_id (DeIid "-") $startpos $endpos }
- | Op Star
- { mk_id (DeIid "*") $startpos $endpos }
+ | Id { mk_id (Id $1) $startpos $endpos }
+
+ | Op Op0 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op1 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op2 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op3 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op4 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op5 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op6 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op7 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op8 { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op9 { mk_id (DeIid $2) $startpos $endpos }
+
+ | Op Op0l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op1l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op2l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op3l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op4l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op5l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op6l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op7l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op8l { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op9l { mk_id (DeIid $2) $startpos $endpos }
+
+ | Op Op0r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op1r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op2r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op3r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op4r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op5r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op6r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op7r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op8r { mk_id (DeIid $2) $startpos $endpos }
+ | Op Op9r { mk_id (DeIid $2) $startpos $endpos }
+
+ | Op Plus { mk_id (DeIid "+") $startpos $endpos }
+ | Op Minus { mk_id (DeIid "-") $startpos $endpos }
+ | Op Star { mk_id (DeIid "*") $startpos $endpos }
op0: Op0 { mk_id (Id $1) $startpos $endpos }
op1: Op1 { mk_id (Id $1) $startpos $endpos }
@@ -197,6 +209,28 @@ op7: Op7 { mk_id (Id $1) $startpos $endpos }
op8: Op8 { mk_id (Id $1) $startpos $endpos }
op9: Op9 { mk_id (Id $1) $startpos $endpos }
+op0l: Op0l { mk_id (Id $1) $startpos $endpos }
+op1l: Op1l { mk_id (Id $1) $startpos $endpos }
+op2l: Op2l { mk_id (Id $1) $startpos $endpos }
+op3l: Op3l { mk_id (Id $1) $startpos $endpos }
+op4l: Op4l { mk_id (Id $1) $startpos $endpos }
+op5l: Op5l { mk_id (Id $1) $startpos $endpos }
+op6l: Op6l { mk_id (Id $1) $startpos $endpos }
+op7l: Op7l { mk_id (Id $1) $startpos $endpos }
+op8l: Op8l { mk_id (Id $1) $startpos $endpos }
+op9l: Op9l { mk_id (Id $1) $startpos $endpos }
+
+op0r: Op0r { mk_id (Id $1) $startpos $endpos }
+op1r: Op1r { mk_id (Id $1) $startpos $endpos }
+op2r: Op2r { mk_id (Id $1) $startpos $endpos }
+op3r: Op3r { mk_id (Id $1) $startpos $endpos }
+op4r: Op4r { mk_id (Id $1) $startpos $endpos }
+op5r: Op5r { mk_id (Id $1) $startpos $endpos }
+op6r: Op6r { mk_id (Id $1) $startpos $endpos }
+op7r: Op7r { mk_id (Id $1) $startpos $endpos }
+op8r: Op8r { mk_id (Id $1) $startpos $endpos }
+op9r: Op9r { mk_id (Id $1) $startpos $endpos }
+
decl:
| Decl
{ mk_id (Id $1) $startpos $endpos }
@@ -281,48 +315,156 @@ typ:
| typ0
{ $1 }
+/* The following implements all nine levels of user-defined precedence for
+operators in types, with both left, right and non-associative operators */
+
typ0:
| typ1 op0 typ1 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ0l op0l typ1 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ1 op0r typ0r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ1 { $1 }
+typ0l:
+ | typ1 op0 typ1 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ0l op0l typ1 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ1 { $1 }
+typ0r:
+ | typ1 op0 typ1 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ1 op0r typ0r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ1 { $1 }
typ1:
| typ2 op1 typ2 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ1l op1l typ2 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ2 op1r typ1r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ2 { $1 }
+typ1l:
+ | typ2 op1 typ2 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ1l op1l typ2 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ2 { $1 }
+typ1r:
+ | typ2 op1 typ2 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ2 op1r typ1r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ2 { $1 }
typ2:
| typ3 op2 typ3 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ2l op2l typ3 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ3 op2r typ2r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ3 { $1 }
+typ2l:
+ | typ3 op2 typ3 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ2l op2l typ3 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ3 { $1 }
+typ2r:
+ | typ3 op2 typ3 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ3 op2r typ2r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ3 { $1 }
typ3:
| typ4 op3 typ4 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ3l op3l typ4 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ4 op3r typ3r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ4 { $1 }
+typ3l:
+ | typ4 op3 typ4 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ3l op3l typ4 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ4 { $1 }
+typ3r:
+ | typ4 op3 typ4 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ4 op3r typ3r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ4 { $1 }
typ4:
| typ5 op4 typ5 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ4l op4l typ5 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ5 op4r typ4r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ5 { $1 }
+typ4l:
+ | typ5 op4 typ5 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ4l op4l typ5 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ5 { $1 }
+typ4r:
+ | typ5 op4 typ5 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ5 op4r typ4r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ5 { $1 }
typ5:
| typ6 op5 typ6 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ5l op5l typ6 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ6 op5r typ5r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ6 { $1 }
+typ5l:
+ | typ6 op5 typ6 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ5l op5l typ6 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ6 { $1 }
+typ5r:
+ | typ6 op5 typ6 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ6 op5r typ5 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ6 { $1 }
typ6:
| typ7 op6 typ7 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
- | typ6 Plus typ7 { mk_typ (ATyp_sum ($1, $3)) $startpos $endpos }
- | typ6 Minus typ7 { mk_typ (ATyp_minus ($1, $3)) $startpos $endpos }
+ | typ6l op6l typ7 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ7 op6r typ6r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ6l Plus typ7 { mk_typ (ATyp_sum ($1, $3)) $startpos $endpos }
+ | typ6l Minus typ7 { mk_typ (ATyp_minus ($1, $3)) $startpos $endpos }
+ | typ7 { $1 }
+typ6l:
+ | typ7 op6 typ7 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ6l op6l typ7 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ6l Plus typ7 { mk_typ (ATyp_sum ($1, $3)) $startpos $endpos }
+ | typ6l Minus typ7 { mk_typ (ATyp_minus ($1, $3)) $startpos $endpos }
+ | typ7 { $1 }
+typ6r:
+ | typ7 op6 typ7 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ7 op6r typ6r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ7 { $1 }
typ7:
| typ8 op7 typ8 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
- | typ7 Star typ8 { mk_typ (ATyp_times ($1, $3)) $startpos $endpos }
+ | typ7l op7l typ8 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ8 op7r typ7r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ7l Star typ8 { mk_typ (ATyp_times ($1, $3)) $startpos $endpos }
+ | typ8 { $1 }
+typ7l:
+ | typ8 op7 typ8 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ7l op7l typ8 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ7l Star typ8 { mk_typ (ATyp_times ($1, $3)) $startpos $endpos }
+ | typ8 { $1 }
+typ7r:
+ | typ8 op7 typ8 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ8 op7r typ7r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| typ8 { $1 }
typ8:
| typ9 op8 typ9 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ8l op8l typ9 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ9 op8r typ8r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | TwoCaret typ9 { mk_typ (ATyp_exp $2) $startpos $endpos }
+ | typ9 { $1 }
+typ8l:
+ | typ9 op8 typ9 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ8l op8l typ9 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | TwoCaret typ9 { mk_typ (ATyp_exp $2) $startpos $endpos }
+ | typ9 { $1 }
+typ8r:
+ | typ9 op8 typ9 { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ9 op8r typ8r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| TwoCaret typ9 { mk_typ (ATyp_exp $2) $startpos $endpos }
| typ9 { $1 }
typ9:
| atomic_typ op9 atomic_typ { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ9l op9l atomic_typ { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | atomic_typ op9r typ9r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | atomic_typ { $1 }
+typ9l:
+ | atomic_typ op9 atomic_typ { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | typ9l op9l atomic_typ { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | atomic_typ { $1 }
+typ9r:
+ | atomic_typ op9 atomic_typ { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
+ | atomic_typ op9r typ9r { mk_typ (ATyp_app (deinfix $2, [$1; $3])) $startpos $endpos }
| atomic_typ { $1 }
atomic_typ:
@@ -342,6 +484,11 @@ atomic_typ:
{ $2 }
| Lparen typ Comma typ_list Rparen
{ mk_typ (ATyp_tup ($2 :: $4)) $startpos $endpos }
+ | LcurlyBar num_list RcurlyBar
+ { let v = mk_kid "n" $startpos $endpos in
+ let atom_id = mk_id (Id "atom") $startpos $endpos in
+ let atom_of_v = mk_typ (ATyp_app (atom_id, [mk_typ (ATyp_var v) $startpos $endpos])) $startpos $endpos in
+ mk_typ (ATyp_exist ([v], NC_aux (NC_nat_set_bounded (v, $2), loc $startpos($2) $endpos($2)), atom_of_v)) $startpos $endpos }
| Lcurly kid_list Dot typ Rcurly
{ mk_typ (ATyp_exist ($2, NC_aux (NC_true, loc $startpos $endpos), $4)) $startpos $endpos }
| Lcurly kid_list Comma nc Dot typ Rcurly
@@ -386,11 +533,59 @@ typquant:
| kopt_list
{ TypQ_aux (TypQ_tq (List.map qi_id_of_kopt $1), loc $startpos $endpos) }
+effect:
+ | Barr
+ { mk_effect BE_barr $startpos $endpos }
+ | Depend
+ { mk_effect BE_depend $startpos $endpos }
+ | Rreg
+ { mk_effect BE_rreg $startpos $endpos }
+ | Wreg
+ { mk_effect BE_wreg $startpos $endpos }
+ | Rmem
+ { mk_effect BE_rmem $startpos $endpos }
+ | Rmemt
+ { mk_effect BE_rmemt $startpos $endpos }
+ | Wmem
+ { mk_effect BE_wmem $startpos $endpos }
+ | Wmv
+ { mk_effect BE_wmv $startpos $endpos }
+ | Wmvt
+ { mk_effect BE_wmvt $startpos $endpos }
+ | Eamem
+ { mk_effect BE_eamem $startpos $endpos }
+ | Exmem
+ { mk_effect BE_exmem $startpos $endpos }
+ | Undef
+ { mk_effect BE_undef $startpos $endpos }
+ | Unspec
+ { mk_effect BE_unspec $startpos $endpos }
+ | Nondet
+ { mk_effect BE_nondet $startpos $endpos }
+ | Escape
+ { mk_effect BE_escape $startpos $endpos }
+
+effect_list:
+ | effect
+ { [$1] }
+ | effect Comma effect_list
+ { $1::$3 }
+
+effect_set:
+ | Lcurly effect_list Rcurly
+ { mk_typ (ATyp_set $2) $startpos $endpos }
+ | Pure
+ { mk_typ (ATyp_set []) $startpos $endpos }
+
typschm:
| typ MinusGt typ
{ (fun s e -> mk_typschm mk_typqn (mk_typ (ATyp_fn ($1, $3, mk_typ (ATyp_set []) s e)) s e) s e) $startpos $endpos }
| Forall typquant Dot typ MinusGt typ
{ (fun s e -> mk_typschm $2 (mk_typ (ATyp_fn ($4, $6, mk_typ (ATyp_set []) s e)) s e) s e) $startpos $endpos }
+ | typ MinusGt typ Effect effect_set
+ { (fun s e -> mk_typschm mk_typqn (mk_typ (ATyp_fn ($1, $3, $5)) s e) s e) $startpos $endpos }
+ | Forall typquant Dot typ MinusGt typ Effect effect_set
+ { (fun s e -> mk_typschm $2 (mk_typ (ATyp_fn ($4, $6, $8)) s e) s e) $startpos $endpos }
pat:
| atomic_pat
@@ -413,6 +608,12 @@ atomic_pat:
{ mk_pat (P_lit $1) $startpos $endpos }
| id
{ mk_pat (P_id $1) $startpos $endpos }
+ | kid
+ { mk_pat (P_var $1) $startpos $endpos }
+ | tydecl typ
+ { mk_pat (P_typ ($2, mk_pat (P_var $1) $startpos $endpos($1))) $startpos $endpos }
+ | id Lparen pat_list Rparen
+ { mk_pat (P_app ($1, $3)) $startpos $endpos }
| pat Colon typ
{ mk_pat (P_typ ($3, $1)) $startpos $endpos }
| decl typ
@@ -431,6 +632,16 @@ lit:
{ mk_lit (L_num $1) $startpos $endpos }
| Undefined
{ mk_lit L_undef $startpos $endpos }
+ | Bitzero
+ { mk_lit L_zero $startpos $endpos }
+ | Bitone
+ { mk_lit L_one $startpos $endpos }
+ | Bin
+ { mk_lit (L_bin $1) $startpos $endpos }
+ | Hex
+ { mk_lit (L_hex $1) $startpos $endpos }
+ | String
+ { mk_lit (L_string $1) $startpos $endpos }
exp:
| cast_exp Colon typ
@@ -449,55 +660,171 @@ cast_exp:
{ mk_exp (E_block $2) $startpos $endpos }
| Return cast_exp
{ mk_exp (E_return $2) $startpos $endpos }
+ | Throw cast_exp
+ { mk_exp (E_throw $2) $startpos $endpos }
| If_ exp Then cast_exp Else cast_exp
{ mk_exp (E_if ($2, $4, $6)) $startpos $endpos }
- | Match exp0 Lcurly case_list Rcurly
+ | If_ exp Then cast_exp
+ { mk_exp (E_if ($2, $4, mk_lit_exp L_unit $endpos($4) $endpos($4))) $startpos $endpos }
+ | Match exp Lcurly case_list Rcurly
{ mk_exp (E_case ($2, $4)) $startpos $endpos }
- | Lparen exp Comma exp_list Rparen
+ | Try exp Catch Lcurly case_list Rcurly
+ { mk_exp (E_try ($2, $5)) $startpos $endpos }
+ | Lparen exp0 Comma exp_list Rparen
{ mk_exp (E_tuple ($2 :: $4)) $startpos $endpos }
+/* The following implements all nine levels of user-defined precedence for
+operators in expressions, with both left, right and non-associative operators */
+
exp0:
| exp1 op0 exp1 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp0l op0l exp1 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp1 op0r exp0r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp1 { $1 }
+exp0l:
+ | exp1 op0 exp1 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp0l op0l exp1 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp1 { $1 }
+exp0r:
+ | exp1 op0 exp1 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp1 op0r exp0r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| exp1 { $1 }
exp1:
| exp2 op1 exp2 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp1l op1l exp2 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp2 op1r exp1r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp2 { $1 }
+exp1l:
+ | exp2 op1 exp2 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp1l op1l exp2 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp2 { $1 }
+exp1r:
+ | exp2 op1 exp2 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp2 op1r exp1r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| exp2 { $1 }
exp2:
| exp3 op2 exp3 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp2l op2l exp3 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp3 op2r exp2r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp3 { $1 }
+exp2l:
+ | exp3 op2 exp3 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp2l op2l exp3 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp3 { $1 }
+exp2r:
+ | exp3 op2 exp3 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp3 op2r exp2r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| exp3 { $1 }
exp3:
| exp4 op3 exp4 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp3l op3l exp4 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp4 op3r exp3r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp4 { $1 }
+exp3l:
+ | exp4 op3 exp4 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp3l op3l exp4 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp4 { $1 }
+exp3r:
+ | exp4 op3 exp4 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp4 op3r exp3r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| exp4 { $1 }
exp4:
| exp5 op4 exp5 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp4l op4l exp5 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp5 op4r exp4r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp5 { $1 }
+exp4l:
+ | exp5 op4 exp5 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp4l op4l exp5 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp5 { $1 }
+exp4r:
+ | exp5 op4 exp5 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp5 op4r exp4r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| exp5 { $1 }
exp5:
| exp6 op5 exp6 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp5l op5l exp6 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6 op5r exp5r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6 At exp5r { mk_exp (E_vector_append ($1, $3)) $startpos $endpos }
+ | exp6 { $1 }
+exp5l:
+ | exp6 op5 exp6 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp5l op5l exp6 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6 { $1 }
+exp5r:
+ | exp6 op5 exp6 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6 op5r exp5r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6 At exp5r { mk_exp (E_vector_append ($1, $3)) $startpos $endpos }
| exp6 { $1 }
exp6:
| exp7 op6 exp7 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
- | exp6 Plus exp7 { mk_exp (E_app_infix ($1, mk_id (Id "+") $startpos($2) $endpos($2), $3)) $startpos $endpos }
- | exp6 Minus exp7 { mk_exp (E_app_infix ($1, mk_id (Id "-") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp6l op6l exp7 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp7 op6r exp6r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6l Plus exp7 { mk_exp (E_app_infix ($1, mk_id (Id "+") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp6l Minus exp7 { mk_exp (E_app_infix ($1, mk_id (Id "-") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp7 { $1 }
+exp6l:
+ | exp7 op6 exp7 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6l op6l exp7 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp6l Plus exp7 { mk_exp (E_app_infix ($1, mk_id (Id "+") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp6l Minus exp7 { mk_exp (E_app_infix ($1, mk_id (Id "-") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp7 { $1 }
+exp6r:
+ | exp7 op6 exp7 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp7 op6r exp6r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| exp7 { $1 }
exp7:
| exp8 op7 exp8 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
- | exp7 Star exp8 { mk_exp (E_app_infix ($1, mk_id (Id "*") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp7l op7l exp8 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp8 op7r exp7r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp7l Star exp8 { mk_exp (E_app_infix ($1, mk_id (Id "*") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp8 { $1 }
+exp7l:
+ | exp8 op7 exp8 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp7l op7l exp8 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp7l Star exp8 { mk_exp (E_app_infix ($1, mk_id (Id "*") $startpos($2) $endpos($2), $3)) $startpos $endpos }
+ | exp8 { $1 }
+exp7r:
+ | exp8 op7 exp8 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp8 op7r exp7r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| exp8 { $1 }
exp8:
| exp9 op8 exp9 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp8l op8l exp9 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp9 op8r exp8r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | TwoCaret exp9 { mk_exp (E_app (mk_id (Id "pow2") $startpos($1) $endpos($1), [$2])) $startpos $endpos }
+ | exp9 { $1 }
+exp8l:
+ | exp9 op8 exp9 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp8l op8l exp9 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | TwoCaret exp9 { mk_exp (E_app (mk_id (Id "pow2") $startpos($1) $endpos($1), [$2])) $startpos $endpos }
+ | exp9 { $1 }
+exp8r:
+ | exp9 op8 exp9 { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp9 op8r exp8r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| TwoCaret exp9 { mk_exp (E_app (mk_id (Id "pow2") $startpos($1) $endpos($1), [$2])) $startpos $endpos }
| exp9 { $1 }
exp9:
| atomic_exp op9 atomic_exp { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp9l op9l atomic_exp { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | atomic_exp op9r exp9r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | atomic_exp { $1 }
+exp9l:
+ | atomic_exp op9 atomic_exp { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | exp9l op9l atomic_exp { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | atomic_exp { $1 }
+exp9r:
+ | atomic_exp op9 atomic_exp { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
+ | atomic_exp op9r exp9r { mk_exp (E_app_infix ($1, $2, $3)) $startpos $endpos }
| atomic_exp { $1 }
case:
@@ -515,8 +842,6 @@ case_list:
block:
| exp
{ [$1] }
- | If_ exp Then exp Semi block
- { mk_exp (E_if ($2, $4, mk_lit_exp L_unit $startpos($5) $endpos($5))) $startpos $endpos($5) :: $6 }
| Let_ letbind Semi block
{ [mk_exp (E_let ($2, mk_exp (E_block $4) $startpos($4) $endpos)) $startpos $endpos] }
| exp Semi /* Allow trailing semicolon in block */
@@ -539,6 +864,22 @@ atomic_exp:
{ mk_exp (E_app ($1, [mk_lit_exp L_unit $startpos($2) $endpos])) $startpos $endpos }
| id Lparen exp_list Rparen
{ mk_exp (E_app ($1, $3)) $startpos $endpos }
+ | Sizeof Lparen typ Rparen
+ { mk_exp (E_sizeof $3) $startpos $endpos }
+ | Constraint Lparen nc Rparen
+ { mk_exp (E_constraint $3) $startpos $endpos }
+ | Assert Lparen exp Comma exp Rparen
+ { mk_exp (E_assert ($3, $5)) $startpos $endpos }
+ | atomic_exp Lsquare exp Rsquare
+ { mk_exp (E_vector_access ($1, $3)) $startpos $endpos }
+ | atomic_exp Lsquare exp DotDot exp Rsquare
+ { mk_exp (E_vector_subrange ($1, $3, $5)) $startpos $endpos }
+ | Lsquare exp_list Rsquare
+ { mk_exp (E_vector $2) $startpos $endpos }
+ | Lsquare exp With atomic_exp Eq exp Rsquare
+ { mk_exp (E_vector_update ($2, $4, $6)) $startpos $endpos }
+ | Lsquare exp With atomic_exp DotDot atomic_exp Eq exp Rsquare
+ { mk_exp (E_vector_update_subrange ($2, $4, $6, $8)) $startpos $endpos }
| Lparen exp Rparen
{ $2 }
@@ -548,12 +889,6 @@ exp_list:
| exp Comma exp_list
{ $1 :: $3 }
-cast_exp_list:
- | cast_exp
- { [$1] }
- | cast_exp Comma exp_list
- { $1 :: $3 }
-
funcl:
| id pat Eq exp
{ mk_funcl (FCL_Funcl ($1, $2, $4)) $startpos $endpos }
@@ -634,6 +969,20 @@ register_def:
| Register id Colon typ
{ mk_reg_dec (DEC_reg ($4, $2)) $startpos $endpos }
+default_def:
+ | Default base_kind Inc
+ { mk_default (DT_order ($2, mk_typ ATyp_inc $startpos($3) $endpos)) $startpos $endpos }
+ | Default base_kind Dec
+ { mk_default (DT_order ($2, mk_typ ATyp_dec $startpos($3) $endpos)) $startpos $endpos }
+
+scattered_def:
+ | Union id typquant
+ { mk_sd (SD_scattered_variant($2, mk_namesectn, $3)) $startpos $endpos }
+ | Union id
+ { mk_sd (SD_scattered_variant($2, mk_namesectn, mk_typqn)) $startpos $endpos }
+ | Function_ id
+ { mk_sd (SD_scattered_function(mk_recn, mk_tannotn, mk_eannotn, $2)) $startpos $endpos }
+
def:
| fun_def
{ DEF_fundef $1 }
@@ -649,6 +998,16 @@ def:
{ DEF_overload ($2, $5) }
| Overload id Eq enum_bar
{ DEF_overload ($2, $4) }
+ | Scattered scattered_def
+ { DEF_scattered $2 }
+ | Function_ Clause funcl
+ { DEF_scattered (mk_sd (SD_scattered_funcl $3) $startpos $endpos) }
+ | Union Clause id Eq type_union
+ { DEF_scattered (mk_sd (SD_scattered_unioncl ($3, $5)) $startpos $endpos) }
+ | End id
+ { DEF_scattered (mk_sd (SD_scattered_end $2) $startpos $endpos) }
+ | default_def
+ { DEF_default $1 }
defs_list:
| def
diff --git a/src/pretty_print_common.ml b/src/pretty_print_common.ml
index bd43c1a7..70f5b749 100644
--- a/src/pretty_print_common.ml
+++ b/src/pretty_print_common.ml
@@ -189,7 +189,6 @@ let doc_typ, doc_atomic_typ, doc_nexp, doc_nexp_constraint =
| Typ_arg_typ t -> app_typ t
| Typ_arg_nexp n -> nexp n
| Typ_arg_order o -> doc_ord o
- | Typ_arg_effect e -> doc_effects e
(* same trick to handle precedence of nexp *)
and nexp ne = sum_typ ne
diff --git a/src/pretty_print_lem.ml b/src/pretty_print_lem.ml
index 586773ca..9b66331b 100644
--- a/src/pretty_print_lem.ml
+++ b/src/pretty_print_lem.ml
@@ -208,7 +208,6 @@ let doc_typ_lem, doc_atomic_typ_lem =
| Typ_arg_typ t -> app_typ regtypes true t
| Typ_arg_nexp n -> empty
| Typ_arg_order o -> empty
- | Typ_arg_effect e -> empty
in typ', atomic_typ
(* Check for variables in types that would be pretty-printed.
diff --git a/src/pretty_print_lem_ast.ml b/src/pretty_print_lem_ast.ml
index 018a93f5..adddcee6 100644
--- a/src/pretty_print_lem_ast.ml
+++ b/src/pretty_print_lem_ast.ml
@@ -210,8 +210,7 @@ and pp_format_typ_arg_lem (Typ_arg_aux(t,l)) =
(match t with
| Typ_arg_typ(t) -> "(Typ_arg_typ " ^ pp_format_typ_lem t ^ ")"
| Typ_arg_nexp(n) -> "(Typ_arg_nexp " ^ pp_format_nexp_lem n ^ ")"
- | Typ_arg_order(o) -> "(Typ_arg_order " ^ pp_format_ord_lem o ^ ")"
- | Typ_arg_effect(e) -> "(Typ_arg_effect " ^ pp_format_effects_lem e ^ ")") ^ " " ^
+ | Typ_arg_order(o) -> "(Typ_arg_order " ^ pp_format_ord_lem o ^ ")");
(pp_format_l_lem l) ^ ")"
and pp_format_nexp_constraint_lem (NC_aux(nc,l)) =
"(NC_aux " ^
diff --git a/src/pretty_print_ocaml.ml b/src/pretty_print_ocaml.ml
index fc02f568..b331a6cf 100644
--- a/src/pretty_print_ocaml.ml
+++ b/src/pretty_print_ocaml.ml
@@ -121,7 +121,6 @@ let doc_typ_ocaml, doc_atomic_typ_ocaml =
| Typ_arg_typ t -> app_typ t
| Typ_arg_nexp n -> empty
| Typ_arg_order o -> empty
- | Typ_arg_effect e -> empty
in typ, atomic_typ
let doc_lit_ocaml in_pat (L_aux(l,_)) =
diff --git a/src/pretty_print_sail.ml b/src/pretty_print_sail.ml
index a63df7ea..bb1d7357 100644
--- a/src/pretty_print_sail.ml
+++ b/src/pretty_print_sail.ml
@@ -277,6 +277,10 @@ let doc_exp, doc_let =
(doc_op equals (atomic_exp e1 ^^ colon ^^ atomic_exp e2) (exp e3)))
| E_list exps ->
squarebarbars (separate_map comma exp exps)
+ | E_try(e,pexps) ->
+ let opening = separate space [string "try"; exp e; string "catch"; lbrace] in
+ let cases = separate_map (break 1) doc_case pexps in
+ surround 2 1 opening cases rbrace
| E_case(e,pexps) ->
let opening = separate space [string "switch"; exp e; lbrace] in
let cases = separate_map (break 1) doc_case pexps in
@@ -287,6 +291,8 @@ let doc_exp, doc_let =
string "constraint" ^^ parens (doc_nexp_constraint nc)
| E_exit e ->
separate space [string "exit"; atomic_exp e;]
+ | E_throw e ->
+ separate space [string "throw"; atomic_exp e;]
| E_return e ->
separate space [string "return"; atomic_exp e;]
| E_assert(c,m) ->
diff --git a/src/type_check.ml b/src/type_check.ml
index a2481f3f..ec0b4a58 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -149,6 +149,8 @@ let vector_typ n m ord typ =
mk_typ_arg (Typ_arg_order ord);
mk_typ_arg (Typ_arg_typ typ)]))
+let exc_typ = mk_id_typ (mk_id "exception")
+
let is_range (Typ_aux (typ_aux, _)) =
match typ_aux with
| Typ_app (f, [Typ_arg_aux (Typ_arg_nexp n, _)])
@@ -194,7 +196,7 @@ let rec nc_negate (NC_aux (nc, _)) =
| NC_or (n1, n2) -> mk_nc (NC_and (nc_negate n1, nc_negate n2))
| NC_false -> mk_nc NC_true
| NC_true -> mk_nc NC_false
- | NC_nat_set_bounded (kid, []) -> typ_error Parse_ast.Unknown "Cannot negate empty nexp set"
+ | NC_nat_set_bounded (kid, []) -> nc_false
| NC_nat_set_bounded (kid, [int]) -> nc_neq (nvar kid) (nconstant int)
| NC_nat_set_bounded (kid, int :: ints) ->
mk_nc (NC_and (nc_neq (nvar kid) (nconstant int), nc_negate (mk_nc (NC_nat_set_bounded (kid, ints)))))
@@ -318,7 +320,6 @@ and typ_subst_arg_nexp_aux sv subst = function
| Typ_arg_nexp nexp -> Typ_arg_nexp (nexp_subst sv subst nexp)
| Typ_arg_typ typ -> Typ_arg_typ (typ_subst_nexp sv subst typ)
| Typ_arg_order ord -> Typ_arg_order ord
- | Typ_arg_effect eff -> Typ_arg_effect eff
let rec typ_subst_typ sv subst (Typ_aux (typ, l)) = Typ_aux (typ_subst_typ_aux sv subst typ, l)
and typ_subst_typ_aux sv subst = function
@@ -334,7 +335,6 @@ and typ_subst_arg_typ_aux sv subst = function
| Typ_arg_nexp nexp -> Typ_arg_nexp nexp
| Typ_arg_typ typ -> Typ_arg_typ (typ_subst_typ sv subst typ)
| Typ_arg_order ord -> Typ_arg_order ord
- | Typ_arg_effect eff -> Typ_arg_effect eff
let order_subst_aux sv subst = function
| Ord_var kid -> if Kid.compare kid sv = 0 then subst else Ord_var kid
@@ -357,7 +357,6 @@ and typ_subst_arg_order_aux sv subst = function
| Typ_arg_nexp nexp -> Typ_arg_nexp nexp
| Typ_arg_typ typ -> Typ_arg_typ (typ_subst_order sv subst typ)
| Typ_arg_order ord -> Typ_arg_order (order_subst sv subst ord)
- | Typ_arg_effect eff -> Typ_arg_effect eff
let rec typ_subst_kid sv subst (Typ_aux (typ, l)) = Typ_aux (typ_subst_kid_aux sv subst typ, l)
and typ_subst_kid_aux sv subst = function
@@ -374,7 +373,6 @@ and typ_subst_arg_kid_aux sv subst = function
| Typ_arg_nexp nexp -> Typ_arg_nexp (nexp_subst sv (Nexp_var subst) nexp)
| Typ_arg_typ typ -> Typ_arg_typ (typ_subst_kid sv subst typ)
| Typ_arg_order ord -> Typ_arg_order (order_subst sv (Ord_var subst) ord)
- | Typ_arg_effect eff -> Typ_arg_effect eff
let quant_item_subst_kid_aux sv subst = function
| QI_id (KOpt_aux (KOpt_none kid, l)) as qid ->
@@ -582,7 +580,6 @@ end = struct
| Typ_arg_nexp nexp -> wf_nexp ~exs:exs env nexp
| Typ_arg_typ typ -> wf_typ ~exs:exs env typ
| Typ_arg_order ord -> wf_order env ord
- | Typ_arg_effect _ -> () (* Check: is this ever used? *)
and wf_nexp ?exs:(exs=KidSet.empty) env (Nexp_aux (nexp_aux, l)) =
match nexp_aux with
| Nexp_id _ -> ()
@@ -814,7 +811,7 @@ end = struct
then typ_error (kid_loc kid) ("Kind identifier " ^ string_of_kid kid ^ " is already bound")
else
begin
- typ_debug ("Adding kind identifier binding " ^ string_of_kid kid ^ " :: " ^ string_of_base_kind_aux k);
+ typ_print ("Adding kind identifier " ^ string_of_kid kid ^ " :: " ^ string_of_base_kind_aux k);
{ env with typ_vars = KBindings.add kid k env.typ_vars }
end
@@ -964,7 +961,7 @@ let fresh_existential () =
let fresh = Kid_aux (Var ("'ex" ^ string_of_int !ex_counter), Parse_ast.Unknown) in
incr ex_counter; fresh
-let destructure_exist env typ =
+let destruct_exist env typ =
match Env.expand_synonyms env typ with
| Typ_aux (Typ_exist (kids, nc, typ), _) ->
let fresh_kids = List.map (fun kid -> (kid, fresh_existential ())) kids in
@@ -981,8 +978,8 @@ let exist_typ constr typ =
let fresh_kid = fresh_existential () in
mk_typ (Typ_exist ([fresh_kid], constr fresh_kid, typ fresh_kid))
-let destruct_vector_typ env typ =
- let destruct_vector_typ' = function
+let destruct_vector env typ =
+ let destruct_vector' = function
| Typ_aux (Typ_app (id, [Typ_arg_aux (Typ_arg_nexp n1, _);
Typ_arg_aux (Typ_arg_nexp n2, _);
Typ_arg_aux (Typ_arg_order o, _);
@@ -990,7 +987,7 @@ let destruct_vector_typ env typ =
), _) when string_of_id id = "vector" -> Some (n1, n2, o, vtyp)
| typ -> None
in
- destruct_vector_typ' (Env.expand_synonyms env typ)
+ destruct_vector' (Env.expand_synonyms env typ)
(**************************************************************************)
(* 3. Subtyping and constraint solving *)
@@ -1073,7 +1070,6 @@ and normalize_typ_arg env (Typ_arg_aux (typ_arg, _)) =
| Typ_arg_nexp n -> Tnf_arg_nexp n
| Typ_arg_typ typ -> Tnf_arg_typ (normalize_typ env typ)
| Typ_arg_order o -> Tnf_arg_order o
- | Typ_arg_effect e -> Tnf_arg_effect e
(* Here's how the constraint generation works for subtyping
@@ -1258,7 +1254,6 @@ and typ_arg_frees ?exs:(exs=KidSet.empty) (Typ_arg_aux (typ_arg_aux, l)) =
| Typ_arg_nexp n -> nexp_frees ~exs:exs n
| Typ_arg_typ typ -> typ_frees ~exs:exs typ
| Typ_arg_order ord -> order_frees ord
- | Typ_arg_effect _ -> assert false
let rec nexp_identical (Nexp_aux (nexp1, _)) (Nexp_aux (nexp2, _)) =
match nexp1, nexp2 with
@@ -1300,7 +1295,6 @@ and typ_arg_identical (Typ_arg_aux (arg1, _)) (Typ_arg_aux (arg2, _)) =
| Typ_arg_nexp n1, Typ_arg_nexp n2 -> nexp_identical n1 n2
| Typ_arg_typ typ1, Typ_arg_typ typ2 -> typ_identical typ1 typ2
| Typ_arg_order ord1, Typ_arg_order ord2 -> ord_identical ord1 ord2
- | Typ_arg_effect _, Typ_arg_effect _ -> assert false
type uvar =
| U_nexp of nexp
@@ -1475,10 +1469,9 @@ let rec unify l env typ1 typ2 =
end
| Typ_arg_typ typ1, Typ_arg_typ typ2 -> unify_typ l typ1 typ2
| Typ_arg_order ord1, Typ_arg_order ord2 -> unify_order l ord1 ord2
- | Typ_arg_effect _, Typ_arg_effect _ -> assert false
| _, _ -> unify_error l (string_of_typ_arg typ_arg1 ^ " cannot be unified with type argument " ^ string_of_typ_arg typ_arg2)
in
- match destructure_exist env typ2 with
+ match destruct_exist env typ2 with
| Some (kids, nc, typ2) ->
let typ1, typ2 = Env.expand_synonyms env typ1, Env.expand_synonyms env typ2 in
let (unifiers, _, _) = unify l env typ1 typ2 in
@@ -1508,7 +1501,7 @@ let uv_nexp_constraint env (kid, uvar) =
| _ -> env
let rec subtyp l env typ1 typ2 =
- match destructure_exist env typ1, destructure_exist env typ2 with
+ match destruct_exist env typ1, destruct_exist env typ2 with
| Some (kids, nc, typ1), _ ->
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
@@ -1626,8 +1619,8 @@ let rec instantiate_quants quants kid uvar = match quants with
| _ -> (QI_aux (QI_const nc, l)) :: instantiate_quants quants kid uvar
end
-let destructure_vec_typ l env typ =
- let destructure_vec_typ' l = function
+let destruct_vec_typ l env typ =
+ let destruct_vec_typ' l = function
| Typ_aux (Typ_app (id, [Typ_arg_aux (Typ_arg_nexp n1, _);
Typ_arg_aux (Typ_arg_nexp n2, _);
Typ_arg_aux (Typ_arg_order o, _);
@@ -1635,7 +1628,7 @@ let destructure_vec_typ l env typ =
), _) when string_of_id id = "vector" -> (n1, n2, o, vtyp)
| typ -> typ_error l ("Expected vector type, got " ^ string_of_typ typ)
in
- destructure_vec_typ' l (Env.expand_synonyms env typ)
+ destruct_vec_typ' l (Env.expand_synonyms env typ)
let env_of_annot (l, tannot) = match tannot with
@@ -1660,7 +1653,7 @@ let pat_typ_of (P_aux (_, (l, tannot))) = typ_of_annot (l, tannot)
(* Flow typing *)
-let destructure_atom (Typ_aux (typ_aux, _)) =
+let destruct_atom (Typ_aux (typ_aux, _)) =
match typ_aux with
| Typ_app (f, [Typ_arg_aux (Typ_arg_nexp (Nexp_aux (Nexp_constant c, _)), _)])
when string_of_id f = "atom" -> c
@@ -1668,7 +1661,7 @@ let destructure_atom (Typ_aux (typ_aux, _)) =
when string_of_id f = "range" && c1 = c2 -> c1
| _ -> assert false
-let destructure_atom_nexp (Typ_aux (typ_aux, _)) =
+let destruct_atom_nexp (Typ_aux (typ_aux, _)) =
match typ_aux with
| Typ_app (f, [Typ_arg_aux (Typ_arg_nexp n, _)])
when string_of_id f = "atom" -> n
@@ -1721,36 +1714,36 @@ let apply_flow_constraint = function
let rec infer_flow env (E_aux (exp_aux, (l, _))) =
match exp_aux with
| E_app (f, [x; y]) when string_of_id f = "lteq_atom_atom" ->
- let n1 = destructure_atom_nexp (typ_of x) in
- let n2 = destructure_atom_nexp (typ_of y) in
+ let n1 = destruct_atom_nexp (typ_of x) in
+ let n2 = destruct_atom_nexp (typ_of y) in
[], [nc_lteq n1 n2]
| E_app (f, [x; y]) when string_of_id f = "gteq_atom_atom" ->
- let n1 = destructure_atom_nexp (typ_of x) in
- let n2 = destructure_atom_nexp (typ_of y) in
+ let n1 = destruct_atom_nexp (typ_of x) in
+ let n2 = destruct_atom_nexp (typ_of y) in
[], [nc_gteq n1 n2]
| E_app (f, [x; y]) when string_of_id f = "lt_atom_atom" ->
- let n1 = destructure_atom_nexp (typ_of x) in
- let n2 = destructure_atom_nexp (typ_of y) in
+ let n1 = destruct_atom_nexp (typ_of x) in
+ let n2 = destruct_atom_nexp (typ_of y) in
[], [nc_lt n1 n2]
| E_app (f, [x; y]) when string_of_id f = "gt_atom_atom" ->
- let n1 = destructure_atom_nexp (typ_of x) in
- let n2 = destructure_atom_nexp (typ_of y) in
+ let n1 = destruct_atom_nexp (typ_of x) in
+ let n2 = destruct_atom_nexp (typ_of y) in
[], [nc_gt n1 n2]
| E_app (f, [E_aux (E_id v, _); y]) when string_of_id f = "lt_range_atom" ->
let kid = Env.fresh_kid env in
- let c = destructure_atom (typ_of y) in
+ let c = destruct_atom (typ_of y) in
[(v, Flow_lteq (c - 1))], []
| E_app (f, [E_aux (E_id v, _); y]) when string_of_id f = "lteq_range_atom" ->
let kid = Env.fresh_kid env in
- let c = destructure_atom (typ_of y) in
+ let c = destruct_atom (typ_of y) in
[(v, Flow_lteq c)], []
| E_app (f, [E_aux (E_id v, _); y]) when string_of_id f = "gt_range_atom" ->
let kid = Env.fresh_kid env in
- let c = destructure_atom (typ_of y) in
+ let c = destruct_atom (typ_of y) in
[(v, Flow_gteq (c + 1))], []
| E_app (f, [E_aux (E_id v, _); y]) when string_of_id f = "gteq_range_atom" ->
let kid = Env.fresh_kid env in
- let c = destructure_atom (typ_of y) in
+ let c = destruct_atom (typ_of y) in
[(v, Flow_gteq c)], []
| _ -> [], []
@@ -1877,6 +1870,18 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ
Pat_aux (Pat_when (tpat, checked_guard, crule check_exp env case typ), (l, None))
in
annot_exp (E_case (inferred_exp, List.map (fun case -> check_case case typ) cases)) typ
+ | E_try (exp, cases), _ ->
+ let checked_exp = crule check_exp env exp typ in
+ let check_case pat typ = match pat with
+ | Pat_aux (Pat_exp (pat, case), (l, _)) ->
+ let tpat, env = bind_pat env pat exc_typ in
+ Pat_aux (Pat_exp (tpat, crule check_exp env case typ), (l, None))
+ | Pat_aux (Pat_when (pat, guard, case), (l, _)) ->
+ let tpat, env = bind_pat env pat exc_typ in
+ let checked_guard = check_exp env guard bool_typ in
+ Pat_aux (Pat_when (tpat, checked_guard, crule check_exp env case typ), (l, None))
+ in
+ annot_exp (E_try (checked_exp, List.map (fun case -> check_case case typ) cases)) typ
| E_cons (x, xs), _ ->
begin
match is_list (Env.expand_synonyms env typ) with
@@ -1941,9 +1946,12 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ
| E_exit exp, _ ->
let checked_exp = crule check_exp env exp (mk_typ (Typ_id (mk_id "unit"))) in
annot_exp_effect (E_exit checked_exp) typ (mk_effect [BE_escape])
+ | E_throw exp, _ ->
+ let checked_exp = crule check_exp env exp exc_typ in
+ annot_exp_effect (E_throw checked_exp) typ (mk_effect [BE_escape])
| E_vector vec, _ ->
begin
- let (start, len, ord, vtyp) = destructure_vec_typ l env typ in
+ let (start, len, ord, vtyp) = destruct_vec_typ l env typ in
let checked_items = List.map (fun i -> crule check_exp env i vtyp) vec in
match nexp_simp len with
| Nexp_aux (Nexp_constant lenc, _) ->
@@ -2056,6 +2064,23 @@ 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 kid ->
+ begin
+ let v = id_of_kid kid in
+ match Env.lookup_id v env with
+ | Local (Immutable, _) | Unbound ->
+ begin
+ match destruct_exist env typ with
+ | Some ([kid'], nc, typ) ->
+ let env = Env.add_typ_var kid BK_nat env in
+ let env = Env.add_constraint (nc_subst_nexp kid' (Nexp_var kid) nc) env in
+ let env = Env.add_local v (Immutable, typ_subst_nexp kid' (Nexp_var kid) typ) env in
+ annot_pat (P_var kid) typ, env
+ | Some _ -> typ_error l ("Cannot bind type variable pattern against multiple argument existential")
+ | None _ -> typ_error l ("Cannot bind type variable against non existential type")
+ end
+ | _ -> typ_error l ("Bad type identifer pattern: " ^ string_of_pat pat)
+ end
| P_wild -> annot_pat P_wild typ, env
| P_cons (hd_pat, tl_pat) ->
begin
@@ -2171,9 +2196,9 @@ and infer_pat env (P_aux (pat_aux, (l, ())) as pat) =
pats @ [inferred_pat], env
in
let (inferred_pat :: inferred_pats), env = List.fold_left fold_pats ([], env) (pat :: pats) in
- let (_, len, _, vtyp) = destructure_vec_typ l env (pat_typ_of inferred_pat) in
+ let (_, len, _, vtyp) = destruct_vec_typ l env (pat_typ_of inferred_pat) in
let fold_len len pat =
- let (_, len', _, vtyp') = destructure_vec_typ l env (pat_typ_of pat) in
+ let (_, len', _, vtyp') = destruct_vec_typ l env (pat_typ_of pat) in
typ_equality l env vtyp vtyp';
nsum len len'
in
@@ -2729,6 +2754,11 @@ and propagate_exp_effect_aux = function
let p_cases = List.map propagate_pexp_effect cases in
let case_eff = List.fold_left union_effects no_effect (List.map snd p_cases) in
E_case (p_exp, List.map fst p_cases), union_effects (effect_of p_exp) case_eff
+ | E_try (exp, cases) ->
+ let p_exp = propagate_exp_effect exp in
+ let p_cases = List.map propagate_pexp_effect cases in
+ let case_eff = List.fold_left union_effects no_effect (List.map snd p_cases) in
+ E_try (p_exp, List.map fst p_cases), union_effects (effect_of p_exp) case_eff
| E_for (v, f, t, step, ord, body) ->
let p_f = propagate_exp_effect f in
let p_t = propagate_exp_effect t in
@@ -2756,6 +2786,9 @@ and propagate_exp_effect_aux = function
| E_exit exp ->
let p_exp = propagate_exp_effect exp in
E_exit p_exp, effect_of p_exp
+ | E_throw exp ->
+ let p_exp = propagate_exp_effect exp in
+ E_throw p_exp, effect_of p_exp
| E_return exp ->
let p_exp = propagate_exp_effect exp in
E_return p_exp, effect_of p_exp
@@ -2813,6 +2846,7 @@ and propagate_pat_effect_aux = function
let p_pat = propagate_pat_effect pat in
P_typ (typ, p_pat), effect_of_pat p_pat
| P_id id -> P_id id, no_effect
+ | P_var kid -> P_var kid, no_effect
| P_app (id, pats) ->
let p_pats = List.map propagate_pat_effect pats in
P_app (id, p_pats), collect_effects_pat p_pats
diff --git a/src/type_check.mli b/src/type_check.mli
index 0a85624c..d451e4d9 100644
--- a/src/type_check.mli
+++ b/src/type_check.mli
@@ -135,6 +135,7 @@ module Env : sig
end
+(* Push all the type variables and constraints from a typquant into an environment *)
val add_typquant : typquant -> Env.t -> Env.t
(* Some handy utility functions for constructing types. *)
@@ -155,9 +156,24 @@ val nsum : nexp -> nexp -> nexp
val ntimes : nexp -> nexp -> nexp
val npow2 : nexp -> nexp
val nvar : kid -> nexp
-val nid : id -> nexp
+val nid : id -> nexp (* NOTE: Nexp_id's don't do anything currently *)
+(* Numeric constraint builders *)
+val nc_eq : nexp -> nexp -> n_constraint
+val nc_neq : nexp -> nexp -> n_constraint
+val nc_lteq : nexp -> nexp -> n_constraint
val nc_gteq : nexp -> nexp -> n_constraint
+val nc_lt : nexp -> nexp -> n_constraint
+val nc_gt : nexp -> nexp -> n_constraint
+val nc_and : n_constraint -> n_constraint -> n_constraint
+val nc_or : n_constraint -> n_constraint -> n_constraint
+val nc_true : n_constraint
+val nc_false : n_constraint
+
+(* Negate a n_constraint. Note that there's no NC_not constructor, so
+ this flips all the inequalites a the n_constraint leaves and uses
+ de-morgans to switch and to or and vice versa. *)
+val nc_negate : n_constraint -> n_constraint
(* Sail builtin types. *)
val int_typ : typ
@@ -172,6 +188,7 @@ val real_typ : typ
val vector_typ : nexp -> nexp -> order -> typ -> typ
val list_typ : typ -> typ
val exist_typ : (kid -> n_constraint) -> (kid -> typ) -> typ
+val exc_typ : typ
val inc_ord : order
val dec_ord : order
@@ -217,9 +234,15 @@ val pat_typ_of : tannot pat -> typ
val effect_of : tannot exp -> effect
val effect_of_annot : tannot -> effect
-val destructure_atom_nexp : typ -> nexp
+(* TODO: make return option *)
+val destruct_atom_nexp : typ -> nexp
-val destruct_vector_typ : Env.t -> typ -> (nexp * nexp * order * typ) option
+(* Safely destructure an existential type. Returns None if the type is
+ not existential. This function will pick a fresh name for the
+ existential to ensure that no name-clashes occur. *)
+val destruct_exist : Env.t -> typ -> (kid list * n_constraint * typ) option
+
+val destruct_vector : Env.t -> typ -> (nexp * nexp * order * typ) option
type uvar =
| U_nexp of nexp