summaryrefslogtreecommitdiff
path: root/src/spec_analysis.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/spec_analysis.ml')
-rw-r--r--src/spec_analysis.ml40
1 files changed, 31 insertions, 9 deletions
diff --git a/src/spec_analysis.ml b/src/spec_analysis.ml
index fd43de16..c858754e 100644
--- a/src/spec_analysis.ml
+++ b/src/spec_analysis.ml
@@ -447,15 +447,26 @@ let rec fv_of_scattered consider_var consider_scatter_as_one all_defs (SD_aux(sd
else init_env name in
init_env (name ^ "/end"), uses
-let fv_of_rd consider_var (DEC_aux (d,_)) = match d with
- | DEC_reg(t,id) ->
- init_env (string_of_id id), fv_of_typ consider_var mt mt t
- | DEC_config(id,t,exp) ->
- init_env (string_of_id id), fv_of_typ consider_var mt mt t
- | DEC_alias(id,alias) ->
- init_env (string_of_id id),mt
- | DEC_typ_alias(t,id,alias) ->
- init_env (string_of_id id), mt
+let fv_of_rd consider_var (DEC_aux (d, annot)) =
+ (* When we get the free variables of a register, we have to ensure
+ that we expand all synonyms so we can pick up dependencies with
+ undefined_type function, even when type is indirected through a
+ synonym. *)
+ let open Type_check in
+ let env = env_of_annot annot in
+ match d with
+ | DEC_reg(t, id) ->
+ let t' = Env.expand_synonyms env t in
+ init_env (string_of_id id),
+ Nameset.union (fv_of_typ consider_var mt mt t) (fv_of_typ consider_var mt mt t')
+ | DEC_config(id, t, exp) ->
+ let t' = Env.expand_synonyms env t in
+ init_env (string_of_id id),
+ Nameset.union (fv_of_typ consider_var mt mt t) (fv_of_typ consider_var mt mt t')
+ | DEC_alias(id, alias) ->
+ init_env (string_of_id id), mt
+ | DEC_typ_alias(t, id, alias) ->
+ init_env (string_of_id id), mt
let fv_of_def consider_var consider_scatter_as_one all_defs = function
| DEF_kind kdef -> fv_of_kind_def consider_var kdef
@@ -475,6 +486,8 @@ let fv_of_def consider_var consider_scatter_as_one all_defs = function
List.fold_left Nameset.union Nameset.empty (List.map snd fvs)
| DEF_scattered sdef -> fv_of_scattered consider_var consider_scatter_as_one all_defs sdef
| DEF_reg_dec rdec -> fv_of_rd consider_var rdec
+ | DEF_constraint (id, _, _) ->
+ raise (Reporting.err_unreachable (id_loc id) __POS__ "Constraint should be re-written")
let group_defs consider_scatter_as_one (Ast.Defs defs) =
List.map (fun d -> (fv_of_def false consider_scatter_as_one defs d,d)) defs
@@ -549,6 +562,15 @@ let scc ?(original_order : string list option) (g : graph) =
let add_def_to_graph (prelude, original_order, defset, graph) d =
let bound, used = fv_of_def false true [] d in
+ let used = match d with
+ | DEF_reg_dec _ ->
+ (* For a register, we need to ensure that any undefined_type
+ functions for types used by the register are placed before
+ the register declaration. *)
+ let undefineds = Nameset.map (fun name -> "undefined_" ^ name) used in
+ Nameset.union undefineds used
+ | _ -> used
+ in
try
(* A definition may bind multiple identifiers, e.g. "let (x, y) = ...".
We add all identifiers to the dependency graph as a cycle. The actual