Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
typing.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(**********************************************************************) (* *) (* 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. *) (* *) (**********************************************************************) exception Typing_error of string * string * string (** what, where, msg *) type env = (string * Types.typ_scheme) list let typing_error what where msg = raise (Typing_error (what, where, msg)) let unify_error what where t1 t2 = typing_error what where (Printf.sprintf "cannot unify types %s and %s" (Types.to_string t1) (Types.to_string t2)) let lookup_tenv what where env id = try List.assoc id env with Not_found -> raise (Typing_error (what, where, "undefined symbol \"" ^ id ^ "\"")) let try_unify what where ty ty' = try Types.unify ty ty'; with | Types.TypeConflict _ | Types.TypeCircularity _ -> unify_error what where ty ty' (* Typing expressions *) let rec type_expression tenv expr = let where = Expr.to_string expr in let type_expr expr = match expr.Expr.e_desc with Expr.EInt _ -> Types.type_int () | Expr.EBool _ -> Types.TyBool | Expr.EVar id -> Types.type_instance @@ lookup_tenv "expression" where tenv id | Expr.EBinop (op,e1,e2) -> let ty_fn = Types.type_instance @@ lookup_tenv "expression" where tenv op in type_application where tenv ty_fn [e1;e2] in let ty = type_expr expr in expr.e_typ <- ty; ty and type_application where tenv ty_fn args = let open Types in let ty_arg = TyProduct (List.map (type_expression tenv) args) in let ty_result = TyVar (Types.new_type_var ()) in try_unify "application" where ty_fn (TyArrow (ty_arg,ty_result)); ty_result (* and type_cast e t1 t2 = match t1, t2 with * | TyInt _, TyInt _ * | TyInt _, TyBool * | TyBool, TyBool * | TyBool, TyInt _ * | _, _ -> raise (Illegal_cast e) *) let type_check_output_valuation tenv oenv state_id (o,v) = (* Check that for output valuation [(o,v)], [o] is declared in [oenv] and [v] has a compliant type *) let ty = try List.assoc o oenv with Not_found -> raise (Typing_error ("symbol " ^ o, " assigned in state " ^ state_id, "not declared as output")) in let ty' = type_expression tenv v in try_unify "output" o ty ty' let type_check_fsm_state_decl f tenv (id,ovs) = List.iter (type_check_output_valuation tenv f.Fsm.outps id) ovs let type_check_fsm_action_ tenv act = match act with | Action.Assign (id, exp) -> let t = Types.type_instance @@ lookup_tenv "variable" id tenv id in let t' = type_expression tenv exp in try_unify "action" (Action.to_string act) t t' let type_check_fsm_guard_ tenv gexp = let t = type_expression tenv gexp in try_unify "guard" (Guard.to_string gexp) t Types.TyBool let type_check_fsm_state f s = if not (List.mem_assoc s f.Fsm.states) then typing_error "state" s "invalid state" let type_check_fsm_transition f tenv (src,guards,actions,dst) = (* For each transition [s -> s' when guards with acts] check that - [s] are [s'] are listed as states in [f] declaration - each [guardi] has type [bool] - for each [act]=[id:=exp] in [actions], [type(id)=type(exp)] *) type_check_fsm_state f src; type_check_fsm_state f dst; List.iter (type_check_fsm_guard_ tenv) guards; List.iter (type_check_fsm_action_ tenv) actions let type_check_fsm_itransition f tenv (s,acts) = (* For the initial transition [s with acts] check that - [s'] is listed as state if [n] declaration - for each [act]=[id:=exp] in [actions], [type(id)=type(exp)] *) type_check_fsm_state f s; List.iter (type_check_fsm_action_ tenv) acts (* Final type shortening and cleaning *) let type_clean_expression ~mono expr = let where = Expr.to_string expr in let actual_type t = try Types.mono_type t with Types.Polymorphic t -> if mono then typing_error "expression" where ("polymorphic type: " ^ Types.to_string t) else t in let open Expr in let rec clean e = match e.e_desc with | EInt _ | EBool _ | EVar _ -> e.e_typ <- actual_type e.e_typ | EBinop (_,e1,e2) -> clean e1; clean e2; e.e_typ <- actual_type e.e_typ in clean expr let type_clean_fsm_action act = match act with | Action.Assign (_, exp) -> type_clean_expression exp let type_clean_fsm_guard ~mono gexp = type_clean_expression ~mono gexp let type_clean_fsm_transition ~mono (_,guards,actions,_) = List.iter (type_clean_fsm_guard ~mono) guards; List.iter (type_clean_fsm_action ~mono) actions let type_clean_fsm_itransition ~mono (_,acts) = List.iter (type_clean_fsm_action ~mono) acts let type_clean_fsm ~mono f = List.iter (type_clean_fsm_transition ~mono) f.Fsm.trans; type_clean_fsm_itransition ~mono f.Fsm.itrans let fsm_tenv ?(with_clk=false) f = let open Fsm in List.map (fun (id, t) -> id, Types.trivial_scheme t) (f.vars @ f.inps @ f.outps) @ Builtins.typing_env @ (if with_clk then ["clk", Types.trivial_scheme (Types.type_int ())] else []) let type_check_fsm ?(mono=false) f = let tenv = fsm_tenv f in List.iter (type_check_fsm_state_decl f tenv) f.states; List.iter (type_check_fsm_transition f tenv) f.trans; type_check_fsm_itransition f tenv f.itrans; type_clean_fsm ~mono f; f let type_check_fsm_guard ?(mono=false) ?(with_clk=false) f e = type_check_fsm_guard_ (fsm_tenv ~with_clk f) e; type_clean_fsm_guard ~mono e; e let type_check_fsm_action ?(mono=false) f a = type_check_fsm_action_ (fsm_tenv f) a; type_clean_fsm_action ~mono a; a (* Type checking values *) let type_value v = match v with | Expr.Int _ -> Types.type_int () | Expr.Bool _ -> Types.TyBool | _ -> failwith "Typing.type_value" (* Type checking stimuli *) let type_check_event f ((id,v) as e) = let t = lookup_tenv "input" id f.Fsm.inps id in let t' = type_value v in try_unify "event" (Event.to_string e) t t' let type_check_events f (_,evs) = List.iter (type_check_event f) evs let type_check_stimuli f st = List.iter (type_check_events f) st; st