Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
types.ml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230(**********************************************************************) (* *) (* This file is part of the FSML library *) (* github.com/jserot/fsml *) (* *) (* Copyright (c) 2020-present, Jocelyn SEROT. All rights reserved. *) (* *) (* This source code is licensed under the license found in the *) (* LICENSE file in the root directory of this source tree. *) (* *) (**********************************************************************) type t = | TyInt of sign attr * size attr * range attr | TyBool | TyArrow of t * t (** Internal use only *) | TyProduct of t list (** Internal use only *) | TyVar of t var (** Internal use only *) [@@deriving show {with_path=false}, yojson] and 'a attr = | Const of 'a | Var of ('a attr) var [@@deriving show {with_path=false}, yojson] and 'a var = { stamp: string; mutable value: 'a value } [@@deriving show {with_path=false}, yojson] and 'a value = | Unknown | Known of 'a [@@deriving show {with_path=false}, yojson] and sign = Signed | Unsigned [@@deriving show {with_path=false}, yojson] and size = int [@@deriving show {with_path=false}, yojson] and range = { lo: int; hi: int } [@@deriving show {with_path=false}, yojson] type typ_scheme = { ts_params: ts_params; ts_body: t } [@@deriving show {with_path=false}, yojson] and ts_params = { tp_typ: (t var) list; tp_sign: ((sign attr) var) list; tp_size: ((size attr) var) list; tp_range: ((range attr) var) list; } (* Builders *) let new_stamp = let var_cnt = ref 0 in function () -> incr var_cnt; "_" ^ string_of_int !var_cnt let make_var () = { value = Unknown; stamp=new_stamp () } let new_type_var () = make_var () let new_attr_var () = make_var () let type_int () = TyInt (Var (make_var ()), Var (make_var ()), Var (make_var())) let empty_params = { tp_typ=[]; tp_sign=[]; tp_size=[]; tp_range=[] } let trivial_scheme t = { ts_params=empty_params; ts_body=t } (* Path compression *) let rec type_repr = function | TyVar ({value = Known ty1; _} as var) -> let ty = type_repr ty1 in var.value <- Known ty; ty | ty -> ty (* TODO: find a way to share type_xxx and attr_xxx fns .. *) let rec attr_repr = function | Var ({value = Known r1; _} as var) -> let r = attr_repr r1 in var.value <- Known r; r | r -> r let real_attr a = match attr_repr a with | Var { value=Known v'; _} -> v' | r -> r let real_type ty = match type_repr ty with | TyInt (sg, sz, rg) -> TyInt (real_attr sg, real_attr sz, real_attr rg) | TyVar { value=Known ty'; _} -> ty' | ty -> ty exception Polymorphic of t (* let rec mono_attr t = function * | Var ({value = Known v1; _}) -> mono_attr t v1 * | Var ({value = Unknown; _}) -> raise (Polymorphic t) * | r -> r *) let rec mono_type = function (* | TyInt (sg, sz, rg) as t -> TyInt (mono_attr t sg, mono_attr t sz, mono_attr t rg) *) | TyArrow (t1, t2) -> TyArrow (mono_type t1, mono_type t2) | TyProduct ts -> TyProduct (List.map mono_type ts) | TyVar ({value = Known ty1; _}) -> mono_type ty1 | TyVar ({value = Unknown; _}) as t -> raise (Polymorphic t) | ty -> ty (* Unification *) exception TypeConflict of t * t exception TypeCircularity of t * t let unify_attr (ty1,ty2) a1 a2 = let val1 = real_attr a1 and val2 = real_attr a2 in if val1 == val2 then () else match (val1, val2) with | Const s1, Const s2 when s1 = s2 -> () | Var var1, Var var2 when var1 == var2 -> () (* This is hack *) | Var var, v -> var.value <- Known v | v, Var var -> var.value <- Known v | _, _ -> raise (TypeConflict(ty1, ty2)) let rec unify ty1 ty2 = let val1 = real_type ty1 and val2 = real_type ty2 in if val1 == val2 then () else match (val1, val2) with | TyVar v1, TyVar v2 when v1==v2 -> () | TyVar var, ty -> occur_check var ty; var.value <- Known ty | ty, TyVar var -> occur_check var ty; var.value <- Known ty | TyBool, TyBool -> () | TyInt (sg1,sz1,rg1), TyInt (sg2,sz2,rg2) -> unify_attr (val1,val2) sg1 sg2; unify_attr (val1,val2) sz1 sz2; unify_attr (val1,val2) rg1 rg2 | TyArrow(ty1, ty2), TyArrow(ty1', ty2') -> unify ty1 ty1'; unify ty2 ty2' | TyProduct ts1, TyProduct ts2 when List.length ts1 = List.length ts2 -> List.iter2 unify ts1 ts2 | _, _ -> raise (TypeConflict(val1, val2)) and occur_check var ty = let test s = match type_repr s with | TyVar var' -> if var == var' then raise(TypeCircularity(TyVar var,ty)) | _ -> () in test ty let copy_attr bs a = match attr_repr a with | Var var as v -> begin try List.assq var bs with Not_found -> v end | r -> r type bindings = { tb_typ: (t var * t) list; tb_sign: ((sign attr) var * sign attr) list; tb_size: ((size attr) var * size attr) list; tb_range: ((range attr) var * range attr) list; } let copy_type bs ty = let rec copy ty = match type_repr ty with | TyVar var as ty -> begin try List.assq var bs.tb_typ with Not_found -> ty end | TyInt (sg, sz, rg) -> TyInt (copy_attr bs.tb_sign sg, copy_attr bs.tb_size sz, copy_attr bs.tb_range rg) | TyArrow (ty1, ty2) -> TyArrow (copy ty1, copy ty2) | TyProduct ts -> TyProduct (List.map copy ts) | ty -> ty in copy ty let type_instance ts = match ts.ts_params with | { tp_typ=[]; tp_sign=[]; tp_size=[]; tp_range=[] } -> ts.ts_body (* Monotype *) | _ -> copy_type { tb_typ = List.map (fun var -> (var, TyVar (make_var()))) ts.ts_params.tp_typ; tb_sign = List.map (fun var -> (var, Var (make_var()))) ts.ts_params.tp_sign; tb_size = List.map (fun var -> (var, Var (make_var()))) ts.ts_params.tp_size; tb_range = List.map (fun var -> (var, Var (make_var()))) ts.ts_params.tp_range } ts.ts_body (* Printing *) let string_of_sign, string_of_size, string_of_range = let string_of_attr sf a = match a with | Const c -> sf c | Var v -> v.stamp in (string_of_attr (function Unsigned -> "unsigned" | Signed -> "signed"), string_of_attr string_of_int, string_of_attr (function r -> string_of_int r.lo ^ ".." ^ string_of_int r.hi)) let rec to_string t = match t with | TyBool -> "bool" (* | TyInt (Const Signed, _, _) -> "signed" * | TyInt (Const Unsigned, _, _) -> "unsigned" *) | TyInt (_, _, Const r) -> "int<" ^ string_of_int r.lo ^ ".." ^ string_of_int r.hi ^ ">" (* Special case *) | TyInt (sg, sz, rg) -> "int<" ^ string_of_sign sg ^ "," ^ string_of_size sz ^ "," ^ string_of_range rg ^ ">" | TyArrow (t1, t2) -> to_string t1 ^ "->" ^ to_string t2 | TyProduct ts -> Misc.string_of_list ~f:to_string ~sep:"*" ts | TyVar v -> v.stamp