summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aarch64/prelude.sail4
-rw-r--r--language/l2.ott1
-rw-r--r--lib/option.sail28
-rw-r--r--riscv/main.sail8
-rw-r--r--riscv/prelude.sail8
-rw-r--r--riscv/riscv.sail74
-rw-r--r--riscv/riscv_sys.sail29
-rw-r--r--riscv/riscv_types.sail4
-rw-r--r--src/ast_util.ml7
-rw-r--r--src/ast_util.mli2
-rw-r--r--src/c_backend.ml31
-rw-r--r--src/initial_check.ml13
-rw-r--r--src/interpreter.ml4
-rw-r--r--src/monomorphise.ml23
-rw-r--r--src/ocaml_backend.ml14
-rw-r--r--src/parse_ast.ml3
-rw-r--r--src/parser.mly6
-rw-r--r--src/pattern_completeness.ml2
-rw-r--r--src/pretty_print_lem.ml65
-rw-r--r--src/pretty_print_lem_ast.ml8
-rw-r--r--src/pretty_print_sail.ml4
-rw-r--r--src/rewrites.ml6
-rw-r--r--src/spec_analysis.ml4
-rw-r--r--src/state.ml4
-rw-r--r--src/type_check.ml60
-rw-r--r--src/value.ml1
-rw-r--r--test/c/exception.sail6
-rw-r--r--test/ocaml/string_of_struct/sos.sail2
-rw-r--r--test/ocaml/trycatch/tc.sail2
-rw-r--r--test/ocaml/types/types.sail6
-rw-r--r--test/typecheck/pass/option_either.sail6
-rw-r--r--test/typecheck/pass/pat_completeness.sail8
-rw-r--r--test/typecheck/pass/union_infer.sail6
33 files changed, 189 insertions, 260 deletions
diff --git a/aarch64/prelude.sail b/aarch64/prelude.sail
index 4c6b7974..d9ba1cde 100644
--- a/aarch64/prelude.sail
+++ b/aarch64/prelude.sail
@@ -366,10 +366,10 @@ val break : unit -> unit
function break () = ()
union exception = {
- Error_Undefined,
+ Error_Undefined : unit,
Error_See : string,
Error_Implementation_Defined : string,
- Error_ReservedEncoding
+ Error_ReservedEncoding : unit
}
/*
diff --git a/language/l2.ott b/language/l2.ott
index e6b52482..c34dedb5 100644
--- a/language/l2.ott
+++ b/language/l2.ott
@@ -459,7 +459,6 @@ kind_def :: 'KD_' ::=
type_union :: 'Tu_' ::=
{{ com type union constructors }}
{{ aux _ l }}
- | id :: :: id
| typ id :: :: ty_id
index_range :: 'BF_' ::= {{ com index specification, for bitfields in register types}}
diff --git a/lib/option.sail b/lib/option.sail
new file mode 100644
index 00000000..3869167b
--- /dev/null
+++ b/lib/option.sail
@@ -0,0 +1,28 @@
+$ifndef _OPTION
+$define _OPTION
+
+// The option type is treated specially by the lem backend, so it maps
+// onto the lem maybe type. If the constructors are named differently,
+// this won't work - also no other type should be created with
+// constructors named Some or None.
+
+union option ('a : Type) = {
+ Some : 'a,
+ None : unit
+}
+
+val is_none : forall ('a : Type). option('a) -> bool
+
+function is_none opt = match opt {
+ Some(_) => false,
+ None() => true
+}
+
+val is_some : forall ('a : Type). option('a) -> bool
+
+function is_some opt = match opt {
+ Some(_) => true,
+ None() => false
+}
+
+$endif
diff --git a/riscv/main.sail b/riscv/main.sail
index 0cc34061..8e0b0440 100644
--- a/riscv/main.sail
+++ b/riscv/main.sail
@@ -27,7 +27,7 @@ function fetch_and_execute () =
nextPC = PC + instr_sz;
match instr_ast {
Some(ast) => execute(ast),
- None => {print("Decode failed"); exit (())}
+ None() => {print("Decode failed"); exit()}
}
};
let tohost_val = __RISCV_read(tohost, 4);
@@ -60,9 +60,9 @@ function main () = {
fetch_and_execute()
} catch {
Error_not_implemented(s) => print_string("Error: Not implemented: ", s),
- Error_misaligned_access => print("Error: misaligned_access"),
- Error_EBREAK => print("EBREAK"),
- Error_internal_error => print("Error: internal error")
+ Error_misaligned_access() => print("Error: misaligned_access"),
+ Error_EBREAK() => print("EBREAK"),
+ Error_internal_error() => print("Error: internal error")
};
dump_state ()
}
diff --git a/riscv/prelude.sail b/riscv/prelude.sail
index 89221596..b58ebc52 100644
--- a/riscv/prelude.sail
+++ b/riscv/prelude.sail
@@ -1,7 +1,7 @@
default Order dec
type bits ('n : Int) = vector('n, dec, bit)
-union option ('a : Type) = {None, Some : 'a}
+union option ('a : Type) = {None : unit, Some : 'a}
val eq_atom = {ocaml: "eq_int", lem: "eq"} : forall 'n 'm. (atom('n), atom('m)) -> bool
val lteq_atom = "lteq" : forall 'n 'm. (atom('n), atom('m)) -> bool
@@ -330,9 +330,9 @@ val print_string = "print_string" : (string, string) -> unit
union exception = {
Error_not_implemented : string,
- Error_misaligned_access,
- Error_EBREAK,
- Error_internal_error
+ Error_misaligned_access : unit,
+ Error_EBREAK : unit,
+ Error_internal_error : unit
}
val "sign_extend" : forall 'n 'm, 'm >= 'n. (bits('n), atom('m)) -> bits('m)
diff --git a/riscv/riscv.sail b/riscv/riscv.sail
index 004621c7..21c6fd64 100644
--- a/riscv/riscv.sail
+++ b/riscv/riscv.sail
@@ -353,40 +353,40 @@ function clause execute (FENCE(pred, succ)) = {
}
/* ****************************************************************** */
-union clause ast = FENCEI
+union clause ast = FENCEI : unit
-function clause decode 0b000000000000 @ 0b00000 @ 0b001 @ 0b00000 @ 0b0001111 = Some(FENCEI)
+function clause decode 0b000000000000 @ 0b00000 @ 0b001 @ 0b00000 @ 0b0001111 = Some(FENCEI())
-function clause execute FENCEI = MEM_fence_i()
+function clause execute FENCEI() = MEM_fence_i()
/* ****************************************************************** */
-union clause ast = ECALL
+union clause ast = ECALL : unit
-function clause decode 0b000000000000 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(ECALL)
+function clause decode 0b000000000000 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(ECALL())
-function clause execute ECALL =
+function clause execute ECALL() =
let t : sync_exception =
struct { trap = match (cur_privilege) {
USER => User_ECall,
MACHINE => Machine_ECall
},
- excinfo = (None : option(xlenbits)) } in
+ excinfo = (None() : option(xlenbits)) } in
nextPC = handle_exception_ctl(cur_privilege, CTL_TRAP(t), PC)
/* ****************************************************************** */
-union clause ast = MRET
+union clause ast = MRET : unit
-function clause decode 0b0011000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(MRET)
+function clause decode 0b0011000 @ 0b00010 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(MRET())
-function clause execute MRET =
- nextPC = handle_exception_ctl(cur_privilege, CTL_MRET, PC)
+function clause execute MRET() =
+ nextPC = handle_exception_ctl(cur_privilege, CTL_MRET(), PC)
/* ****************************************************************** */
-union clause ast = EBREAK
+union clause ast = EBREAK : unit
-function clause decode 0b000000000001 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(EBREAK)
+function clause decode 0b000000000001 @ 0b00000 @ 0b000 @ 0b00000 @ 0b1110011 = Some(EBREAK())
-function clause execute EBREAK = { throw(Error_EBREAK) }
+function clause execute EBREAK() = { throw Error_EBREAK() }
/* ****************************************************************** */
union clause ast = LOADRES : (bool, bool, regbits, word_width, regbits)
@@ -591,22 +591,22 @@ function clause execute CSR(csr, rs1, rd, is_imm, op) =
/* ****************************************************************** */
-union clause ast = NOP
+union clause ast = NOP : unit
function clause decodeCompressed (0b000 @ nzi1 : bits(1) @ 0b00000 @ (nzi0 : bits(5)) @ 0b01) : bits(16) = {
- if (nzi1 == 0b0) & (nzi0 == 0b00000) then Some(NOP)
- else None
+ if (nzi1 == 0b0) & (nzi0 == 0b00000) then Some(NOP())
+ else None()
}
-function clause execute (NOP) = ()
+function clause execute NOP() = ()
/* ****************************************************************** */
-union clause ast = ILLEGAL
+union clause ast = ILLEGAL : unit
-function clause decodeCompressed (0b0000 @ 0b00000 @ 0b00000 @ 0b00) : bits(16) = Some(ILLEGAL)
+function clause decodeCompressed (0b0000 @ 0b00000 @ 0b00000 @ 0b00) : bits(16) = Some(ILLEGAL())
-function clause execute (ILLEGAL) = {
+function clause execute ILLEGAL() = {
let t : sync_exception =
struct { trap = Illegal_Instr,
excinfo = Some (EXTZ(0b0)) } in
@@ -619,7 +619,7 @@ union clause ast = C_ADDI4SPN : (cregbits, bits(8))
function clause decodeCompressed (0b000 @ nz54 : bits(2) @ nz96 : bits(4) @ nz2 : bits(1) @ nz3 : bits(1) @ rd : cregbits @ 0b00) : bits(16) = {
let nzimm = (nz96 @ nz54 @ nz3 @ nz2) : bits(8) in
- if nzimm == 0b00000000 then None
+ if nzimm == 0b00000000 then None()
else Some(C_ADDI4SPN(rd, nzimm))
}
@@ -699,7 +699,7 @@ union clause ast = C_ADDI : (bits(6), regbits)
function clause decodeCompressed (0b000 @ nzi5 : bits(1) @ rsd : regbits @ nzi40 : bits(5) @ 0b01) : bits(16) = {
let nzi = (nzi5 @ nzi40) : bits(6) in
- if (nzi == 0b000000) | (rsd == zreg) then None
+ if (nzi == 0b000000) | (rsd == zreg) then None()
else Some(C_ADDI(nzi, rsd))
}
@@ -735,7 +735,7 @@ function clause execute (C_ADDIW(imm, rsd)) = {
union clause ast = C_LI : (bits(6), regbits)
function clause decodeCompressed (0b010 @ imm5 : bits(1) @ rd : regbits @ imm40 : bits(5) @ 0b01) = {
- if (rd == zreg) then None
+ if (rd == zreg) then None()
else Some(C_LI(imm5 @ imm40, rd))
}
@@ -750,7 +750,7 @@ union clause ast = C_ADDI16SP : (bits(6))
function clause decodeCompressed (0b011 @ nzi9 : bits(1) @ /* x2 */ 0b00010 @ nzi4 : bits(1) @ nzi6 : bits(1) @ nzi87 : bits(2) @ nzi5 : bits(1) @ 0b01) = {
let nzimm = nzi9 @ nzi87 @ nzi6 @ nzi5 @ nzi4 in
- if (nzimm == 0b000000) then None
+ if (nzimm == 0b000000) then None()
else Some(C_ADDI16SP(nzimm))
}
@@ -764,7 +764,7 @@ function clause execute (C_ADDI16SP(imm)) = {
union clause ast = C_LUI : (bits(6), regbits)
function clause decodeCompressed (0b011 @ imm17 : bits(1) @ rd : regbits @ imm1612 : bits(5) @ 0b01) = {
- if (rd == zreg) | (rd == sp) then None
+ if (rd == zreg) | (rd == sp) then None()
else Some(C_LUI(imm17 @ imm1612, rd))
}
@@ -780,7 +780,7 @@ union clause ast = C_SRLI : (bits(6), cregbits)
function clause decodeCompressed (0b100 @ nzui5 : bits(1) @ 0b00 @ rsd : cregbits @ nzui40 : bits(5) @ 0b01) = {
let shamt : bits(6) = nzui5 @ nzui40 in
if shamt == 0b000000 /* TODO: On RV32, also need shamt[5] == 0 */
- then None
+ then None()
else Some(C_SRLI(shamt, rsd))
}
@@ -796,7 +796,7 @@ union clause ast = C_SRAI : (bits(6), cregbits)
function clause decodeCompressed (0b100 @ nzui5 : bits(1) @ 0b01 @ rsd : cregbits @ nzui40 : bits(5) @ 0b01) = {
let shamt : bits(6) = nzui5 @ nzui40 in
if shamt == 0b000000 /* TODO: On RV32, also need shamt[5] == 0 */
- then None
+ then None()
else Some(C_SRAI(shamt, rsd))
}
@@ -927,7 +927,7 @@ union clause ast = C_SLLI : (bits(6), regbits)
function clause decodeCompressed (0b000 @ nzui5 : bits(1) @ rsd : regbits @ nzui40 : bits(5) @ 0b10) = {
let shamt : bits(6) = nzui5 @ nzui40 in
if shamt == 0b000000 | rsd == zreg /* TODO: On RV32, also need shamt[5] == 0 */
- then None
+ then None()
else Some(C_SLLI(shamt, rsd))
}
@@ -941,7 +941,7 @@ union clause ast = C_LWSP : (bits(6), regbits)
function clause decodeCompressed (0b010 @ ui5 : bits(1) @ rd : regbits @ ui42 : bits(3) @ ui76 : bits(2) @ 0b10) = {
let uimm : bits(6) = ui76 @ ui5 @ ui42 in
if rd == zreg
- then None
+ then None()
else Some(C_LWSP(uimm, rd))
}
@@ -957,7 +957,7 @@ union clause ast = C_LDSP : (bits(6), regbits)
function clause decodeCompressed (0b011 @ ui5 : bits(1) @ rd : regbits @ ui43 : bits(2) @ ui86 : bits(3) @ 0b10) = {
let uimm : bits(6) = ui86 @ ui5 @ ui43 in
if rd == zreg
- then None
+ then None()
else Some(C_LDSP(uimm, rd))
}
@@ -1000,7 +1000,7 @@ union clause ast = C_JR : (regbits)
function clause decodeCompressed (0b100 @ 0b0 @ rs1 : regbits @ 0b00000 @ 0b10) = {
if rs1 == zreg
- then None
+ then None()
else Some(C_JR(rs1))
}
@@ -1013,7 +1013,7 @@ union clause ast = C_JALR : (regbits)
function clause decodeCompressed (0b100 @ 0b1 @ rs1 : regbits @ 0b00000 @ 0b10) = {
if rs1 == zreg
- then None
+ then None()
else Some(C_JALR(rs1))
}
@@ -1026,7 +1026,7 @@ union clause ast = C_MV : (regbits, regbits)
function clause decodeCompressed (0b100 @ 0b0 @ rd : regbits @ rs2 : regbits @ 0b10) = {
if rs2 == zreg | rd == zreg
- then None
+ then None()
else Some(C_MV(rd, rs2))
}
@@ -1039,7 +1039,7 @@ union clause ast = C_ADD : (regbits, regbits)
function clause decodeCompressed (0b100 @ 0b1 @ rsd : regbits @ rs2 : regbits @ 0b10) = {
if rsd == zreg | rs2 == zreg
- then None
+ then None()
else Some(C_ADD(rsd, rs2))
}
@@ -1048,8 +1048,8 @@ function clause execute (C_ADD(rsd, rs2)) =
/* ****************************************************************** */
-function clause decode _ = None
-function clause decodeCompressed _ = None
+function clause decode _ = None()
+function clause decodeCompressed _ = None()
end ast
end decode
diff --git a/riscv/riscv_sys.sail b/riscv/riscv_sys.sail
index 2956caae..4a80bf3a 100644
--- a/riscv/riscv_sys.sail
+++ b/riscv/riscv_sys.sail
@@ -221,15 +221,16 @@ union ctl_result = {
CTL_URET,
CTL_SRET,
*/
- CTL_MRET
+ CTL_MRET : unit
}
/* privilege level */
-union privilege = {
+enum privilege = {
MACHINE,
USER
}
+
register cur_privilege : privilege
function priv_to_bits(p : privilege) -> bits(2) =
@@ -262,19 +263,19 @@ function handle_exception_ctl(cur_priv : privilege, ctl : ctl_result,
Misaligned_Fetch => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
Fetch_Access => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
Illegal_Instr => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
@@ -283,25 +284,25 @@ function handle_exception_ctl(cur_priv : privilege, ctl : ctl_result,
Misaligned_Load => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
Load_Access => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
Misaligned_Store => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
Store_Access => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
@@ -318,27 +319,27 @@ function handle_exception_ctl(cur_priv : privilege, ctl : ctl_result,
Fetch_PageFault => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
Load_PageFault => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
Store_PageFault => {
match (e.excinfo) {
Some(a) => mtval = a,
- None => throw(Error_internal_error)
+ None() => throw Error_internal_error()
}
},
- _ => throw(Error_internal_error) /* Don't expect ReservedExc0 etc. here */
+ _ => throw Error_internal_error() /* Don't expect ReservedExc0 etc. here */
};
/* TODO: make register read explicit */
mtvec
},
- (_, CTL_MRET) => {
+ (_, CTL_MRET()) => {
mstatus->MIE() = mstatus.MPIE();
mstatus->MPIE() = true;
cur_privilege = bits_to_priv(mstatus.MPP());
diff --git a/riscv/riscv_types.sail b/riscv/riscv_types.sail
index 944c7455..8799f580 100644
--- a/riscv/riscv_types.sail
+++ b/riscv/riscv_types.sail
@@ -5,7 +5,7 @@ function not_implemented message = throw(Error_not_implemented(message))
val internal_error : forall ('a : Type). string -> 'a effect {escape}
function internal_error(s) = {
assert (false, s);
- throw (Error_internal_error)
+ throw Error_internal_error()
}
let xlen = 64
@@ -51,7 +51,7 @@ function wX (r, v) =
overload X = {rX, wX}
function check_alignment (addr : xlenbits, width : atom('n)) -> forall 'n. unit =
- if unsigned(addr) % width != 0 then throw(Error_misaligned_access) else ()
+ if unsigned(addr) % width != 0 then throw Error_misaligned_access() else ()
val MEMr : forall 'n. (xlenbits, atom('n)) -> bits(8 * 'n) effect {rmem}
val MEMr_acquire : forall 'n. (xlenbits, atom('n)) -> bits(8 * 'n) effect {rmem}
diff --git a/src/ast_util.ml b/src/ast_util.ml
index 1c74381f..591e8df2 100644
--- a/src/ast_util.ml
+++ b/src/ast_util.ml
@@ -54,7 +54,7 @@ module Big_int = Nat_big_num
type mut = Immutable | Mutable
-type lvar = Register of typ | Enum of typ | Local of mut * typ | Union of typquant * typ | Unbound
+type lvar = Register of typ | Enum of typ | Local of mut * typ | Unbound
let no_annot = (Parse_ast.Unknown, ())
@@ -1009,10 +1009,7 @@ let split_defs f (Defs defs) =
let append_ast (Defs ast1) (Defs ast2) = Defs (ast1 @ ast2)
let concat_ast asts = List.fold_right append_ast asts (Defs [])
-let type_union_id (Tu_aux (aux, _)) = match aux with
- | Tu_id id -> id
- | Tu_ty_id (_, id) -> id
-
+let type_union_id (Tu_aux (Tu_ty_id (_, id), _)) = id
let rec subst id value (E_aux (e_aux, annot) as exp) =
let wrap e_aux = E_aux (e_aux, annot) in
diff --git a/src/ast_util.mli b/src/ast_util.mli
index d1827685..de925fc3 100644
--- a/src/ast_util.mli
+++ b/src/ast_util.mli
@@ -58,7 +58,7 @@ type mut = Immutable | Mutable
(** [lvar] is the type of variables - they can either be registers,
local mutable or immutable variables, nullary union constructors
(i.e. None in option), or unbound identifiers *)
-type lvar = Register of typ | Enum of typ | Local of mut * typ | Union of typquant * typ | Unbound
+type lvar = Register of typ | Enum of typ | Local of mut * typ | Unbound
val no_annot : unit annot
val gen_loc : Parse_ast.l -> Parse_ast.l
diff --git a/src/c_backend.ml b/src/c_backend.ml
index 33f6f127..2542dd42 100644
--- a/src/c_backend.ml
+++ b/src/c_backend.ml
@@ -80,7 +80,6 @@ let lvar_typ = function
| Local (_, typ) -> typ
| Register typ -> typ
| Enum typ -> typ
- (* | Union (_, typ) -> typ *)
| _ -> assert false
let string_of_value = function
@@ -348,8 +347,6 @@ let pp_lvar lvar doc =
string "[I/" ^^ string (string_of_typ typ |> Util.yellow |> Util.clear) ^^ string "]" ^^ doc
| Enum typ ->
string "[E/" ^^ string (string_of_typ typ |> Util.yellow |> Util.clear) ^^ string "]" ^^ doc
- | Union (typq, typ) ->
- string "[U/" ^^ string (string_of_typquant typq ^ "/" ^ string_of_typ typ |> Util.yellow |> Util.clear) ^^ string "]" ^^ doc
| Unbound -> string "[?]" ^^ doc
let pp_annot typ doc =
@@ -627,7 +624,6 @@ let rec anf (E_aux (e_aux, exp_annot) as exp) =
| E_id id ->
let lvar = Env.lookup_id id (env_of exp) in
begin match lvar with
- | Union (_, typ) -> AE_app (id, [AV_lit (mk_lit L_unit, unit_typ)], typ)
| _ -> AE_val (AV_id (id, lvar))
end
@@ -1123,16 +1119,7 @@ let cdef_ctyps ctx = function
| CDEF_reg_dec (_, ctyp) -> [ctyp]
| CDEF_spec (_, ctyps, ctyp) -> ctyp :: ctyps
| CDEF_fundef (id, _, _, instrs) ->
- (* TODO: Move this code to DEF_fundef -> CDEF_fundef translation, and modify bytecode.ott *)
- let _, Typ_aux (fn_typ, _) =
- try Env.get_val_spec id ctx.tc_env with
- | Type_error _ ->
- (* If we can't find the function type, then it must be a nullary union constructor. *)
- begin match Env.lookup_id id ctx.tc_env with
- | Union (typq, typ) -> typq, function_typ unit_typ typ no_effect
- | _ -> failwith ("Got function identifier " ^ string_of_id id ^ " which is neither a function nor a constructor.")
- end
- in
+ let _, Typ_aux (fn_typ, _) = Env.get_val_spec id ctx.tc_env in
let arg_typs, ret_typ = match fn_typ with
| Typ_fn (Typ_aux (Typ_tup arg_typs, _), ret_typ, _) -> arg_typs, ret_typ
| Typ_fn (arg_typ, ret_typ, _) -> [arg_typ], ret_typ
@@ -1455,15 +1442,7 @@ let compile_funcall ctx id args typ =
let setup = ref [] in
let cleanup = ref [] in
- let _, Typ_aux (fn_typ, _) =
- try Env.get_val_spec id ctx.tc_env with
- | Type_error _ ->
- (* If we can't find the function type, then it must be a nullary union constructor. *)
- begin match Env.lookup_id id ctx.tc_env with
- | Union (typq, typ) -> typq, function_typ unit_typ typ no_effect
- | _ -> failwith ("Got function identifier " ^ string_of_id id ^ " which is neither a function nor a constructor.")
- end
- in
+ let _, Typ_aux (fn_typ, _) = Env.get_val_spec id ctx.tc_env in
let arg_typs, ret_typ = match fn_typ with
| Typ_fn (Typ_aux (Typ_tup arg_typs, _), ret_typ, _) -> arg_typs, ret_typ
| Typ_fn (arg_typ, ret_typ, _) -> [arg_typ], ret_typ
@@ -1892,11 +1871,7 @@ let compile_type_def ctx (TD_aux (type_def, _)) =
{ ctx with records = Bindings.add id ctors ctx.records }
| TD_variant (id, _, _, tus, _) ->
- let compile_tu (Tu_aux (tu_aux, _)) =
- match tu_aux with
- | Tu_id id -> CT_unit, id
- | Tu_ty_id (typ, id) -> ctyp_of_typ ctx typ, id
- in
+ let compile_tu (Tu_aux (Tu_ty_id (typ, id), _)) = ctyp_of_typ ctx typ, id in
let ctus = List.fold_left (fun ctus (ctyp, id) -> Bindings.add id ctyp ctus) Bindings.empty (List.map compile_tu tus) in
CTD_variant (id, Bindings.bindings ctus),
{ ctx with variants = Bindings.add id ctus ctx.variants }
diff --git a/src/initial_check.ml b/src/initial_check.ml
index 9da200d9..0019f18f 100644
--- a/src/initial_check.ml
+++ b/src/initial_check.ml
@@ -648,15 +648,9 @@ let rec to_ast_range (Parse_ast.BF_aux(r,l)) = (* TODO add check that ranges are
| Parse_ast.BF_concat(ir1,ir2) -> BF_concat( to_ast_range ir1, to_ast_range ir2)),
l)
-let to_ast_type_union k_env default_order (Parse_ast.Tu_aux(tu,l)) =
- match tu with
- | Parse_ast.Tu_ty_id(atyp,id) ->
- let typ = to_ast_typ k_env default_order atyp in
- (match typ with
- | Typ_aux(Typ_id (Id_aux (Id "unit",_)),_) ->
- Tu_aux(Tu_id(to_ast_id id),l)
- | _ -> Tu_aux(Tu_ty_id(typ, to_ast_id id), l))
- | Parse_ast.Tu_id id -> (Tu_aux(Tu_id(to_ast_id id),l))
+let to_ast_type_union k_env default_order (Parse_ast.Tu_aux (Parse_ast.Tu_ty_id (atyp, id), l)) =
+ let typ = to_ast_typ k_env default_order atyp in
+ Tu_aux (Tu_ty_id (typ, to_ast_id id), l)
let to_ast_typedef (names,k_env,def_ord) (td:Parse_ast.type_def) : (unit type_def) envs_out =
match td with
@@ -1042,7 +1036,6 @@ let generate_undefineds vs_ids (Defs defs) =
end
in
let undefined_tu = function
- | Tu_aux (Tu_id id, _) -> mk_exp (E_id id)
| Tu_aux (Tu_ty_id (Typ_aux (Typ_tup typs, _), id), _) ->
mk_exp (E_app (id, List.map (fun _ -> mk_lit_exp L_undef) typs))
| Tu_aux (Tu_ty_id (typ, id), _) -> mk_exp (E_app (id, [mk_lit_exp L_undef]))
diff --git a/src/interpreter.ml b/src/interpreter.ml
index 55dcbed0..2b24d66c 100644
--- a/src/interpreter.ml
+++ b/src/interpreter.ml
@@ -415,7 +415,7 @@ let rec step (E_aux (e_aux, annot) as orig_exp) =
| Local (Immutable, _) ->
let chain = build_letchain id gstate.letbinds orig_exp in
return chain
- | Enum _ | Union _ ->
+ | Enum _ ->
return (exp_of_value (V_ctor (string_of_id id, [])))
| _ -> failwith ("id " ^ string_of_id id)
end
@@ -568,7 +568,7 @@ and pattern_match env (P_aux (p_aux, _) as pat) value =
let open Type_check in
begin
match Env.lookup_id id env with
- | Enum _ | Union _ ->
+ | Enum _ ->
if is_ctor value && string_of_id id = fst (coerce_ctor value)
then true, Bindings.empty
else false, Bindings.empty
diff --git a/src/monomorphise.ml b/src/monomorphise.ml
index 45541585..0d63a9c3 100644
--- a/src/monomorphise.ml
+++ b/src/monomorphise.ml
@@ -165,9 +165,7 @@ let pat_id_is_variable env id =
| Local _
| Register _
-> true
- | Enum _
- | Union _
- -> false
+ | Enum _ -> false
let rec is_value (E_aux (e,(l,annot))) =
let is_constructor id =
@@ -179,7 +177,7 @@ let rec is_value (E_aux (e,(l,annot))) =
| Some (env,_,_) ->
Env.is_union_constructor id env ||
(match Env.lookup_id id env with
- | Enum _ | Union _ -> true
+ | Enum _ -> true
| Unbound | Local _ | Register _ -> false)
in
match e with
@@ -1118,15 +1116,12 @@ let is_env_inconsistent env ksubsts =
let split_defs all_errors splits defs =
let no_errors_happened = ref true in
let split_constructors (Defs defs) =
- let sc_type_union q (Tu_aux (tu,l) as tua) =
- match tu with
- | Tu_id id -> [],[tua]
- | Tu_ty_id (ty,id) ->
- (match split_src_type id ty q with
- | None -> ([],[Tu_aux (Tu_ty_id (ty,id),l)])
- | Some variants ->
- ([(id,variants)],
- List.map (fun (insts, id', ty) -> Tu_aux (Tu_ty_id (ty,id'),Generated l)) variants))
+ let sc_type_union q (Tu_aux (Tu_ty_id (ty, id), l) as tua) =
+ match split_src_type id ty q with
+ | None -> ([],[Tu_aux (Tu_ty_id (ty,id),l)])
+ | Some variants ->
+ ([(id,variants)],
+ List.map (fun (insts, id', ty) -> Tu_aux (Tu_ty_id (ty,id'),Generated l)) variants)
in
let sc_type_def ((TD_aux (tda,annot)) as td) =
match tda with
@@ -2799,7 +2794,7 @@ let rec analyse_exp fn_id env assigns (E_aux (e,(l,annot)) as exp) =
| args -> (args,assigns,empty)
| exception Not_found ->
match Env.lookup_id id (Type_check.env_of_annot (l,annot)) with
- | Enum _ | Union _ -> dempty,assigns,empty
+ | Enum _ -> dempty,assigns,empty
| Register _ -> Unknown (l, string_of_id id ^ " is a register"),assigns,empty
| _ ->
Unknown (l, string_of_id id ^ " is not in the environment"),assigns,empty
diff --git a/src/ocaml_backend.ml b/src/ocaml_backend.ml
index 795b6300..c580b9fa 100644
--- a/src/ocaml_backend.ml
+++ b/src/ocaml_backend.ml
@@ -177,7 +177,6 @@ let rec ocaml_pat ctx (P_aux (pat_aux, _) as pat) =
match Env.lookup_id id (pat_env_of pat) with
| Local (Immutable, _) | Unbound -> zencode ctx id
| Enum _ -> zencode_upper ctx id
- | Union _ -> zencode_upper ctx id
| _ -> failwith ("Ocaml: Cannot pattern match on mutable variable or register:" ^ string_of_pat pat)
end
| P_lit lit -> ocaml_lit lit
@@ -315,7 +314,7 @@ and ocaml_atomic_exp ctx (E_aux (exp_aux, _) as exp) =
begin
match Env.lookup_id id (env_of exp) with
| Local (Immutable, _) | Unbound -> zencode ctx id
- | Enum _ | Union _ -> zencode_upper ctx id
+ | Enum _ -> zencode_upper ctx id
| Register _ when is_passed_by_name (typ_of exp) -> zencode ctx id
| Register typ ->
if !opt_trace_ocaml then
@@ -515,9 +514,8 @@ let rec ocaml_fields ctx =
| [] -> empty
let rec ocaml_cases ctx =
- let ocaml_case = function
- | Tu_aux (Tu_id id, _) -> separate space [bar; zencode_upper ctx id]
- | Tu_aux (Tu_ty_id (typ, id), _) -> separate space [bar; zencode_upper ctx id; string "of"; ocaml_typ ctx typ]
+ let ocaml_case (Tu_aux (Tu_ty_id (typ, id), _)) =
+ separate space [bar; zencode_upper ctx id; string "of"; ocaml_typ ctx typ]
in
function
| [tu] -> ocaml_case tu
@@ -525,10 +523,8 @@ let rec ocaml_cases ctx =
| [] -> empty
let rec ocaml_exceptions ctx =
- let ocaml_exception = function
- | Tu_aux (Tu_id id, _) -> separate space [string "exception"; zencode_upper ctx id]
- | Tu_aux (Tu_ty_id (typ, id), _) ->
- separate space [string "exception"; zencode_upper ctx id; string "of"; ocaml_typ ctx typ]
+ let ocaml_exception (Tu_aux (Tu_ty_id (typ, id), _)) =
+ separate space [string "exception"; zencode_upper ctx id; string "of"; ocaml_typ ctx typ]
in
function
| [tu] -> ocaml_exception tu
diff --git a/src/parse_ast.ml b/src/parse_ast.ml
index ba948040..635aa46e 100644
--- a/src/parse_ast.ml
+++ b/src/parse_ast.ml
@@ -361,8 +361,7 @@ funcl_aux = (* Function clause *)
type
type_union_aux = (* Type union constructors *)
- Tu_id of id
- | Tu_ty_id of atyp * id
+ Tu_ty_id of atyp * id
type
diff --git a/src/parser.mly b/src/parser.mly
index c8cc49a3..7e4874f8 100644
--- a/src/parser.mly
+++ b/src/parser.mly
@@ -677,6 +677,8 @@ atomic_pat:
| kid
{ mk_pat (P_var (mk_pat (P_id (id_of_kid $1)) $startpos $endpos,
mk_typ (ATyp_var $1) $startpos $endpos)) $startpos $endpos }
+ | id Unit
+ { mk_pat (P_app ($1, [mk_pat P_wild $startpos $endpos])) $startpos $endpos }
| id Lparen pat_list Rparen
{ mk_pat (P_app ($1, $3)) $startpos $endpos }
| atomic_pat Colon typ
@@ -999,6 +1001,8 @@ 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 }
+ | Exit Unit
+ { mk_exp (E_exit (mk_lit_exp L_unit $startpos $endpos)) $startpos $endpos }
| Exit Lparen exp Rparen
{ mk_exp (E_exit $3) $startpos $endpos }
| Sizeof Lparen typ Rparen
@@ -1155,8 +1159,6 @@ struct_fields:
type_union:
| id Colon typ
{ Tu_aux (Tu_ty_id ($3, $1), loc $startpos $endpos) }
- | id
- { Tu_aux (Tu_id $1, loc $startpos $endpos) }
type_unions:
| type_union
diff --git a/src/pattern_completeness.ml b/src/pattern_completeness.ml
index 94623e6f..c13452ff 100644
--- a/src/pattern_completeness.ml
+++ b/src/pattern_completeness.ml
@@ -97,7 +97,7 @@ let rec generalize ctx (P_aux (p_aux, _) as pat) =
| Unbound -> GP_wild
| Local (Immutable, _) -> GP_wild
| Register _ | Local (Mutable, _) -> Util.warn "Matching on register or mutable variable"; GP_wild
- | Enum _ | Union _ -> GP_app (Bindings.singleton id GP_wild)
+ | Enum _ -> GP_app (Bindings.singleton id GP_wild)
end
| P_var (pat, _) -> generalize ctx pat
| P_vector pats ->
diff --git a/src/pretty_print_lem.ml b/src/pretty_print_lem.ml
index a0390a94..f2136f07 100644
--- a/src/pretty_print_lem.ml
+++ b/src/pretty_print_lem.ml
@@ -445,24 +445,22 @@ let doc_typschm_lem quants (TypSchm_aux(TypSchm_ts(tq,t),_)) =
else pt
let is_ctor env id = match Env.lookup_id id env with
-| Enum _ | Union _ -> true
+| Enum _ -> true
| _ -> false
(*Note: vector concatenation, literal vectors, indexed vectors, and record should
be removed prior to pp. The latter two have never yet been seen
*)
let rec doc_pat_lem ctxt apat_needed (P_aux (p,(l,annot)) as pa) = match p with
+ | P_app(id, _) when string_of_id id = "None" -> string "Nothing"
| P_app(id, ((_ :: _) as pats)) ->
let ppp = doc_unop (doc_id_lem_ctor id)
(parens (separate_map comma (doc_pat_lem ctxt true) pats)) in
if apat_needed then parens ppp else ppp
- | P_app(id,[]) -> doc_id_lem_ctor id
+ | P_app(id, []) -> doc_id_lem_ctor id
| P_lit lit -> doc_lit_lem lit
| P_wild -> underscore
- | P_id id ->
- begin match id with
- | Id_aux (Id "None",_) -> string "Nothing" (* workaround temporary issue *)
- | _ -> doc_id_lem id end
+ | P_id id -> doc_id_lem id
| P_var(p,_) -> doc_pat_lem ctxt true p
| P_as(p,id) -> parens (separate space [doc_pat_lem ctxt true p; string "as"; doc_id_lem id])
| P_typ(Typ_aux (Typ_tup typs, _), P_aux (P_tup pats, _)) ->
@@ -614,6 +612,7 @@ let doc_exp_lem, doc_let_lem =
| E_app(f,args) ->
begin match f with
(* temporary hack to make the loop body a function of the temporary variables *)
+ | Id_aux (Id "None", _) as none -> doc_id_lem_ctor none
| Id_aux (Id "foreach", _) ->
begin
match args with
@@ -681,7 +680,7 @@ let doc_exp_lem, doc_let_lem =
end
| _ ->
begin match annot with
- | Some (env, _, _) when (is_ctor env f) ->
+ | Some (env, _, _) when Env.is_union_constructor f env ->
let epp =
match args with
| [] -> doc_id_lem_ctor f
@@ -899,10 +898,9 @@ let doc_exp_lem, doc_let_lem =
in top_exp, let_exp
(*TODO Upcase and downcase type and constructors as needed*)
-let doc_type_union_lem (Tu_aux(typ_u,_)) = match typ_u with
- | Tu_ty_id(typ,id) -> separate space [pipe; doc_id_lem_ctor id; string "of";
- parens (doc_typ_lem typ)]
- | Tu_id id -> separate space [pipe; doc_id_lem_ctor id]
+let doc_type_union_lem (Tu_aux(Tu_ty_id(typ,id),_)) =
+ separate space [pipe; doc_id_lem_ctor id; string "of";
+ parens (doc_typ_lem typ)]
let rec doc_range_lem (BF_aux(r,_)) = match r with
| BF_single i -> parens (doc_op comma (doc_int i) (doc_int i))
@@ -995,19 +993,12 @@ let doc_typdef_lem (TD_aux(td, (l, annot))) = match td with
(separate space [string "let rec";fromInterpValueF;string "v";equals;string "match v with"])
(
((separate_map (break 1))
- (fun (Tu_aux (tu,_)) ->
- match tu with
- | Tu_ty_id (ty,cid) ->
- (separate space)
- [pipe;string "SI.V_ctor";parens (make_id true cid);underscore;underscore;string "v";
- arrow;
- doc_id_lem_ctor cid;
- parens (string "fromInterpValue v")]
- | Tu_id cid ->
- (separate space)
- [pipe;string "SI.V_ctor";parens (make_id true cid);underscore;underscore;string "v";
- arrow;
- doc_id_lem_ctor cid])
+ (fun (Tu_aux (Tu_ty_id (ty,cid),_)) ->
+ (separate space)
+ [pipe;string "SI.V_ctor";parens (make_id true cid);underscore;underscore;string "v";
+ arrow;
+ doc_id_lem_ctor cid;
+ parens (string "fromInterpValue v")])
ar) ^/^
((separate space) [pipe;string "SI.V_tuple [v]";arrow;fromInterpValueF;string "v"]) ^/^
@@ -1024,24 +1015,14 @@ let doc_typdef_lem (TD_aux(td, (l, annot))) = match td with
(separate space [string "let";toInterpValueF;equals;string "function"])
(
((separate_map (break 1))
- (fun (Tu_aux (tu,_)) ->
- match tu with
- | Tu_ty_id (ty,cid) ->
- (separate space)
- [pipe;doc_id_lem_ctor cid;string "v";arrow;
- string "SI.V_ctor";
- parens (make_id false cid);
- parens (string "SIA.T_id " ^^ string_lit (doc_id id));
- string "SI.C_Union";
- parens (string "toInterpValue v")]
- | Tu_id cid ->
- (separate space)
- [pipe;doc_id_lem_ctor cid;arrow;
- string "SI.V_ctor";
- parens (make_id false cid);
- parens (string "SIA.T_id " ^^ string_lit (doc_id id));
- string "SI.C_Union";
- parens (string "toInterpValue ()")])
+ (fun (Tu_aux (Tu_ty_id (ty,cid),_)) ->
+ (separate space)
+ [pipe;doc_id_lem_ctor cid;string "v";arrow;
+ string "SI.V_ctor";
+ parens (make_id false cid);
+ parens (string "SIA.T_id " ^^ string_lit (doc_id id));
+ string "SI.C_Union";
+ parens (string "toInterpValue v")])
ar) ^/^
string "end") in
let fromToInterpValuePP =
diff --git a/src/pretty_print_lem_ast.ml b/src/pretty_print_lem_ast.ml
index 63661bb9..559c1116 100644
--- a/src/pretty_print_lem_ast.ml
+++ b/src/pretty_print_lem_ast.ml
@@ -517,11 +517,9 @@ let pp_lem_typdef ppf (TD_aux(td,(l,annot))) =
fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
kwd "TD_record" pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp f_pp f_pp) fs
| TD_variant(id,nm,typq,ar,_) ->
- let a_pp ppf (Tu_aux(typ_u,l)) =
- match typ_u with
- | Tu_ty_id(typ,id) -> fprintf ppf "@[<1>(Tu_aux (Tu_ty_id %a %a) %a);@]"
- pp_lem_typ typ pp_lem_id id pp_lem_l l
- | Tu_id(id) -> fprintf ppf "@[<1>(Tu_aux (Tu_id %a) %a);@]" pp_lem_id id pp_lem_l l
+ let a_pp ppf (Tu_aux(Tu_ty_id(typ,id),l)) =
+ fprintf ppf "@[<1>(Tu_aux (Tu_ty_id %a %a) %a);@]"
+ pp_lem_typ typ pp_lem_id id pp_lem_l l
in
fprintf ppf "@[<0>(%a %a %a %a [%a] false)@]"
kwd "TD_variant" pp_lem_id id pp_lem_namescm nm pp_lem_typquant typq (list_pp a_pp a_pp) ar
diff --git a/src/pretty_print_sail.ml b/src/pretty_print_sail.ml
index 7620ca50..29284262 100644
--- a/src/pretty_print_sail.ml
+++ b/src/pretty_print_sail.ml
@@ -456,9 +456,7 @@ let doc_dec (DEC_aux (reg,_)) =
let doc_field (typ, id) =
separate space [doc_id id; colon; doc_typ typ]
-let doc_union (Tu_aux (tu, l)) = match tu with
- | Tu_id id -> doc_id id
- | Tu_ty_id (typ, id) -> separate space [doc_id id; colon; doc_typ typ]
+let doc_union (Tu_aux (Tu_ty_id (typ, id), l)) = separate space [doc_id id; colon; doc_typ typ]
let doc_typdef (TD_aux(td,_)) = match td with
| TD_abbrev (id, _, typschm) ->
diff --git a/src/rewrites.ml b/src/rewrites.ml
index 50a8ae68..0b4a864c 100644
--- a/src/rewrites.ml
+++ b/src/rewrites.ml
@@ -1952,10 +1952,8 @@ let rewrite_constraint =
rewrite_defs_base { rewriters_base with rewrite_exp = (fun _ -> fold_exp rewrite_e_constraint) }
-let rewrite_type_union_typs rw_typ (Tu_aux (tu, annot)) =
- match tu with
- | Tu_id id -> Tu_aux (Tu_id id, annot)
- | Tu_ty_id (typ, id) -> Tu_aux (Tu_ty_id (rw_typ typ, id), annot)
+let rewrite_type_union_typs rw_typ (Tu_aux (Tu_ty_id (typ, id), annot)) =
+ Tu_aux (Tu_ty_id (rw_typ typ, id), annot)
let rewrite_type_def_typs rw_typ rw_typquant rw_typschm (TD_aux (td, annot)) =
match td with
diff --git a/src/spec_analysis.ml b/src/spec_analysis.ml
index 371acfdc..74312d9b 100644
--- a/src/spec_analysis.ml
+++ b/src/spec_analysis.ml
@@ -289,9 +289,7 @@ let init_env s = Nameset.singleton s
let typ_variants consider_var bound tunions =
List.fold_right
- (fun (Tu_aux(t,_)) (b,n) -> match t with
- | Tu_id id -> Nameset.add (string_of_id id) b,n
- | Tu_ty_id(t,id) -> Nameset.add (string_of_id id) b, fv_of_typ consider_var b n t)
+ (fun (Tu_aux(Tu_ty_id(t,id),_)) (b,n) -> Nameset.add (string_of_id id) b, fv_of_typ consider_var b n t)
tunions
(bound,mt)
diff --git a/src/state.ml b/src/state.ml
index 690c7948..8e024179 100644
--- a/src/state.ml
+++ b/src/state.ml
@@ -144,7 +144,7 @@ let add_regval_conv id typ defs =
let from_val = Printf.sprintf "val %s : register_value -> option(%s)" from_name typ_str in
let from_function = String.concat "\n" [
Printf.sprintf "function %s Regval_%s(v) = Some(v)" from_name id;
- Printf.sprintf "and %s _ = None" from_name
+ Printf.sprintf "and %s _ = None()" from_name
] in
let from_defs = if is_defined from_name then [] else [from_val; from_function] in
(* Create a function that converts from target type to regval. *)
@@ -316,7 +316,7 @@ let generate_regstate_defs mwords defs =
let regtyps = register_base_types mwords (List.map fst registers) in
let option_typ =
if has_def "option" then [] else
- ["union option ('a : Type) = {None, Some : 'a}"]
+ ["union option ('a : Type) = {None : unit, Some : 'a}"]
in
let regval_typ = if has_def "register_value" then [] else generate_regval_typ regtyps in
let regstate_typ = if has_def "regstate" then [] else generate_regstate registers in
diff --git a/src/type_check.ml b/src/type_check.ml
index 16e5bed2..ff4240aa 100644
--- a/src/type_check.ml
+++ b/src/type_check.ml
@@ -674,7 +674,6 @@ end = struct
let is_union_constructor id env =
let is_ctor id (Tu_aux (tu, _)) = match tu with
- | Tu_id ctor_id when Id.compare id ctor_id = 0 -> true
| Tu_ty_id (_, ctor_id) when Id.compare id ctor_id = 0 -> true
| _ -> false
in
@@ -835,14 +834,7 @@ end = struct
let (enum, _) = List.find (fun (enum, ctors) -> IdSet.mem id ctors) (Bindings.bindings env.enums) in
Enum (mk_typ (Typ_id enum))
with
- | Not_found ->
- begin
- try
- let (typq, typ) = freshen_bind env (Bindings.find id env.union_ids) in
- Union (typq, typ)
- with
- | Not_found -> Unbound
- end
+ | Not_found -> Unbound
end
end
@@ -2024,11 +2016,6 @@ let rec filter_casts env from_typ to_typ casts =
end
| [] -> []
-let is_union_id id env =
- match Env.lookup_id id env with
- | Union (_, _) -> true
- | _ -> false
-
let crule r env exp typ =
incr depth;
typ_print ("Check " ^ string_of_exp exp ^ " <= " ^ string_of_typ typ);
@@ -2246,14 +2233,6 @@ let rec check_exp env (E_aux (exp_aux, (l, ())) as exp : unit exp) (Typ_aux (typ
if is_typ_monomorphic typ || Env.polymorphic_undefineds env
then annot_exp_effect (E_lit lit) typ (mk_effect [BE_undef])
else typ_error l ("Type " ^ string_of_typ typ ^ " failed undefined monomorphism restriction")
- | E_id id, _ when is_union_id id env ->
- begin
- match Env.lookup_id id env with
- | Union (typq, ctor_typ) ->
- let inferred_exp = fst (infer_funapp' l env id (typq, mk_typ (Typ_fn (unit_typ, ctor_typ, no_effect))) [mk_lit_exp L_unit] (Some typ)) in
- annot_exp (E_id id) (typ_of inferred_exp)
- | _ -> assert false (* Unreachble due to guard *)
- end
| _, _ ->
let inferred_exp = irule infer_exp env exp in
type_coercion env inferred_exp typ
@@ -2381,19 +2360,18 @@ and bind_pat env (P_aux (pat_aux, (l, ())) as pat) (Typ_aux (typ_aux, _) as typ)
match pat_aux with
| P_id v ->
begin
+ (* If the identifier we're matching on is also a constructor of
+ a union, that's probably a mistake, so warn about it. *)
+ if Env.is_union_constructor v env then
+ Util.warn (Printf.sprintf "Identifier %s found in pattern is also a union constructor at %s\n"
+ (string_of_id v)
+ (Reporting_basic.loc_to_string l))
+ else ();
match Env.lookup_id v env with
| Local (Immutable, _) | Unbound -> annot_pat (P_id v) typ, Env.add_local v (Immutable, typ) env, []
| Local (Mutable, _) | Register _ ->
typ_error l ("Cannot shadow mutable local or register in switch statement pattern " ^ string_of_pat pat)
| Enum enum -> subtyp l env enum typ; annot_pat (P_id v) typ, env, []
- | Union (typq, ctor_typ) ->
- begin
- try
- let _ = unify l env ctor_typ typ in
- annot_pat (P_id v) typ, env, []
- with
- | Unification_error (l, m) -> typ_error l ("Unification error when pattern matching against union constructor: " ^ m)
- end
end
| P_var (pat, typ_pat) ->
let typ = Env.expand_synonyms env typ in
@@ -2523,7 +2501,7 @@ and infer_pat env (P_aux (pat_aux, (l, ())) as pat) =
| P_id v ->
begin
match Env.lookup_id v env with
- | Local (Immutable, _) | Unbound | Union _ ->
+ | Local (Immutable, _) | Unbound ->
typ_error l ("Cannot infer identifier in pattern " ^ string_of_pat pat ^ " - try adding a type annotation")
| Local (Mutable, _) | Register _ ->
typ_error l ("Cannot shadow mutable local or register in switch statement pattern " ^ string_of_pat pat)
@@ -2617,7 +2595,6 @@ and bind_assignment env (LEXP_aux (lexp_aux, _) as lexp) (E_aux (_, (l, ())) as
let is_immutable, vtyp, is_register = match Env.lookup_id v env with
| Unbound -> typ_error l "Cannot assign to element of unbound vector"
| Enum _ -> typ_error l "Cannot vector assign to enumeration element"
- | Union _ -> typ_error l "Cannot vector assign to union element"
| Local (Immutable, vtyp) -> true, vtyp, false
| Local (Mutable, vtyp) -> false, vtyp, false
| Register vtyp -> false, vtyp, true
@@ -2678,8 +2655,8 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ =
end
| LEXP_id v ->
begin match Env.lookup_id v env with
- | Local (Immutable, _) | Enum _ | Union _ ->
- typ_error l ("Cannot modify let-bound constant, union or enumeration constructor " ^ string_of_id v)
+ | Local (Immutable, _) | Enum _ ->
+ typ_error l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v)
| Local (Mutable, vtyp) -> subtyp l env typ vtyp; annot_lexp (LEXP_id v) typ, env
| Register vtyp -> subtyp l env typ vtyp; annot_lexp_effect (LEXP_id v) typ (mk_effect [BE_wreg]), env
| Unbound -> annot_lexp (LEXP_id v) typ, Env.add_local v (Mutable, typ) env
@@ -2687,8 +2664,8 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ =
| LEXP_cast (typ_annot, v) ->
begin
match Env.lookup_id v env with
- | Local (Immutable, _) | Enum _ | Union _ ->
- typ_error l ("Cannot modify let-bound constant, union or enumeration constructor " ^ string_of_id v)
+ | Local (Immutable, _) | Enum _ ->
+ typ_error l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v)
| Local (Mutable, vtyp) ->
begin
subtyp l env typ typ_annot;
@@ -2732,8 +2709,8 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ =
| LEXP_aux (LEXP_id v, _) ->
begin
match Env.lookup_id v env with
- | Local (Immutable, _) | Enum _ | Union _ ->
- typ_error l ("Cannot modify let-bound constant, union or enumeration constructor " ^ string_of_id v)
+ | Local (Immutable, _) | Enum _ ->
+ typ_error l ("Cannot modify let-bound constant or enumeration constructor " ^ string_of_id v)
| Unbound ->
typ_error l "Unbound variable in vector tuple assignment"
| Local (Mutable, vtyp) | Register vtyp ->
@@ -2773,7 +2750,6 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ =
let is_immutable, is_register, vtyp = match Env.lookup_id v env with
| Unbound -> typ_error l "Cannot assign to element of unbound vector"
| Enum _ -> typ_error l "Cannot vector assign to enumeration element"
- | Union _ -> typ_error l "Cannot vector assign to union element"
| Local (Immutable, vtyp) -> true, false, vtyp
| Local (Mutable, vtyp) -> false, false, vtyp
| Register vtyp -> false, true, vtyp
@@ -2798,7 +2774,6 @@ and bind_lexp env (LEXP_aux (lexp_aux, (l, ())) as lexp) typ =
let is_immutable, is_register, vtyp = match Env.lookup_id v env with
| Unbound -> typ_error l "Cannot assign to element of unbound vector"
| Enum _ -> typ_error l "Cannot vector assign to enumeration element"
- | Union _ -> typ_error l "Cannot vector assign to union element"
| Local (Immutable, vtyp) -> true, false, vtyp
| Local (Mutable, vtyp) -> false, false, vtyp
| Register vtyp -> false, true, vtyp
@@ -2840,10 +2815,6 @@ and infer_exp env (E_aux (exp_aux, (l, ())) as exp) =
| Local (_, typ) | Enum typ -> annot_exp (E_id v) typ
| Register typ -> annot_exp_effect (E_id v) typ (mk_effect [BE_rreg])
| Unbound -> typ_error l ("Identifier " ^ string_of_id v ^ " is unbound")
- | Union (typq, typ) ->
- if quant_items typq = []
- then annot_exp (E_id v) typ
- else typ_error l ("Cannot infer the type of polymorphic union indentifier " ^ string_of_id v)
end
| E_lit lit -> annot_exp (E_lit lit) (infer_lit env lit)
| E_sizeof nexp -> annot_exp (E_sizeof nexp) (mk_typ (Typ_app (mk_id "atom", [mk_typ_arg (Typ_arg_nexp nexp)])))
@@ -3610,7 +3581,6 @@ let fold_union_quant quants (QI_aux (qi, l)) =
let check_type_union env variant typq (Tu_aux (tu, l)) =
let ret_typ = app_typ variant (List.fold_left fold_union_quant [] (quant_items typq)) in
match tu with
- | Tu_id v -> Env.add_union_id v (typq, ret_typ) env
| Tu_ty_id (typ, v) ->
let typ' = mk_typ (Typ_fn (typ, ret_typ, no_effect)) in
env
diff --git a/src/value.ml b/src/value.ml
index 077ad883..f865fea1 100644
--- a/src/value.ml
+++ b/src/value.ml
@@ -434,6 +434,7 @@ let primops =
("sub_vec", value_sub_vec);
("read_ram", value_read_ram);
("write_ram", value_write_ram);
+ ("undefined_unit", fun _ -> V_unit);
("undefined_bit", fun _ -> V_bit Sail_lib.B0);
("undefined_int", fun _ -> V_int Big_int.zero);
("undefined_bool", fun _ -> V_bool false);
diff --git a/test/c/exception.sail b/test/c/exception.sail
index 27248021..4e74fcae 100644
--- a/test/c/exception.sail
+++ b/test/c/exception.sail
@@ -5,7 +5,7 @@ val print_int = "print_int" : (string, int) -> unit
union exception = {
Epair : (range(0, 255), range(0, 255)),
- Eunknown,
+ Eunknown : unit,
Estring : string
}
@@ -28,9 +28,9 @@ function main () = {
print(g());
f(); // will throw Estring
throw(Epair(42, 24));
- throw(Eunknown);
+ throw(Eunknown());
} catch {
- Eunknown => print("Caught Eunknown"),
+ Eunknown() => print("Caught Eunknown"),
Epair(x, y) => print("Caught Epair"),
Estring(str) => {
print("Caught Estring");
diff --git a/test/ocaml/string_of_struct/sos.sail b/test/ocaml/string_of_struct/sos.sail
index 6d14dfd7..69a17e6c 100644
--- a/test/ocaml/string_of_struct/sos.sail
+++ b/test/ocaml/string_of_struct/sos.sail
@@ -3,7 +3,7 @@ struct would cause the ocaml backend to generate a bad string_of
function for the struct */
union option ('a : Type) = {
- None,
+ None : unit,
Some : 'a
}
diff --git a/test/ocaml/trycatch/tc.sail b/test/ocaml/trycatch/tc.sail
index b805f3fa..f788305d 100644
--- a/test/ocaml/trycatch/tc.sail
+++ b/test/ocaml/trycatch/tc.sail
@@ -18,6 +18,6 @@ function main () = {
}
}
-union clause exception = Test_other
+union clause exception = Test_other : unit
end exception \ No newline at end of file
diff --git a/test/ocaml/types/types.sail b/test/ocaml/types/types.sail
index a710eb25..d13b527c 100644
--- a/test/ocaml/types/types.sail
+++ b/test/ocaml/types/types.sail
@@ -24,7 +24,7 @@ struct TestStruct = {
register SREG : TestStruct
-union option ('a : Type) = {None, Some : 'a}
+union option ('a : Type) = {None : unit, Some : 'a}
register OREG : option(byte)
@@ -37,8 +37,8 @@ function main () = {
SIGNALREG = High;
print(if SIGNALREG == High then "pass" else "fail");
SREG.field1 = 0b00;
- print(if SREG.field1 == 0b00 then "pass" else "faiL");
+ print(if SREG.field1 == 0b00 then "pass" else "fail");
SREG.field1 = 0b11;
- print(if SREG.field1 == 0b11 then "pass" else "faiL");
+ print(if SREG.field1 == 0b11 then "pass" else "fail");
print("pass")
}
diff --git a/test/typecheck/pass/option_either.sail b/test/typecheck/pass/option_either.sail
index 632b882d..de4458ed 100644
--- a/test/typecheck/pass/option_either.sail
+++ b/test/typecheck/pass/option_either.sail
@@ -1,13 +1,13 @@
default Order inc
-union option ('a : Type) = {None, Some : 'a}
+union option ('a : Type) = {None : unit, Some : 'a}
-function none () -> forall ('a : Type). option('a) = None
+function none () -> forall ('a : Type). option('a) = None()
function some x : 'a -> forall ('a : Type). option('a) = Some(x)
function test x : option('a) -> forall ('a : Type). range(0, 1) = match x {
- None => 0,
+ None() => 0,
Some(y) => 1
}
diff --git a/test/typecheck/pass/pat_completeness.sail b/test/typecheck/pass/pat_completeness.sail
index fd4a7757..6a4036c5 100644
--- a/test/typecheck/pass/pat_completeness.sail
+++ b/test/typecheck/pass/pat_completeness.sail
@@ -1,11 +1,11 @@
-union option ('a : Type) = {None, Some : 'a}
+union option ('a : Type) = {None : unit, Some : 'a}
union ast = {Foo : unit}
-let x : option(ast) = Some(Foo)
+let x : option(ast) = Some(Foo())
let y : unit = match(x) {
- Some(Foo) => (),
+ Some(Foo()) => (),
Some(a) => (),
- None => ()
+ None() => ()
} \ No newline at end of file
diff --git a/test/typecheck/pass/union_infer.sail b/test/typecheck/pass/union_infer.sail
index 15eb5c60..bb422b65 100644
--- a/test/typecheck/pass/union_infer.sail
+++ b/test/typecheck/pass/union_infer.sail
@@ -1,7 +1,7 @@
default Order inc
-union option ('a : Type) = {None, Some : 'a}
+union option ('a : Type) = {None : unit, Some : 'a}
-union Test = {A, B, C}
+union Test = {A : unit, B : unit, C : unit}
-function test () -> option(Test) = Some(C)
+function test () -> option(Test) = Some(C())