(* -*- mode: tuareg -*- *)
(* This package is automatically generated by xtree. Do not edit manually. *)

[@@@warning "-42"]

(* TODO Use appropriate OCaml integer type *)
type uint = Uint of string
type ureal = Ureal of { numerator : uint ; denominator : uint; base : int; negative : bool }

(* GNAT *)

type source_ptr =
  | No_location
  | Source_ptr of { filename: string; line: int }
type node_id = Node_id

(* GNATCOLL.Symbols *)
type symbol = No_symbol | Symbol of string
type symbol_set = symbol list
type string_sets_set = symbol list

type why_node_set = unit

(* Why.Sinfo *)

type odomain =
  | Expr
  | Term
  | Pterm
  | Pred
  | Prog

type domain =
  | Term
  | Pterm
  | Pred
  | Prog

type type_ =
  | Builtin
  | Split
  | Abstract

type literal =
  | True
  | False

type theory_type =
  | Theory
  | Module

type clone_type =
  | Import
  | Export
  | Clone_default

type subst_type =
  | Type_subst
  | Function
  | Predicate
  | Namepace
  | Lemma
  | Goal

type connector =
  | Or_else
  | And_then
  | Imply
  | Equivalent
  | Or
  | And

type assert_kind =
  | Assert
  | Check
  | Assume

type axiom_dep_kind =
  | Axdep_func
  | Axdep_pred

type 'a nonempty = { elt0: 'a; elts: 'a list }

let list_of_nonempty n = n.elt0 :: n.elts

(* Kind tags *)

type type_tag = [`Type]
type name_tag = [`Name]
type effects_tag = [`Effects]
type raise_effect_tag = [`Raise_effect]
type binder_tag = [`Binder]
type transparent_type_definition_tag = [`Transparent_type_definition]
type record_binder_tag = [`Record_binder]
type record_definition_tag = [`Record_definition]
type range_type_definition_tag = [`Range_type_definition]
type triggers_tag = [`Triggers]
type trigger_tag = [`Trigger]
type axiom_dep_tag = [`Axiom_dep]
type handler_tag = [`Handler]
type field_association_tag = [`Field_association]
type variant_tag = [`Variant]
type variants_tag = [`Variants]
type universal_quantif_tag = [`Universal_quantif]
type existential_quantif_tag = [`Existential_quantif]
type not_tag = [`Not]
type connection_tag = [`Connection]
type label_tag = [`Label]
type loc_label_tag = [`Loc_label]
type identifier_tag = [`Identifier]
type tagged_tag = [`Tagged]
type call_tag = [`Call]
type literal_tag = [`Literal]
type binding_tag = [`Binding]
type elsif_tag = [`Elsif]
type epsilon_tag = [`Epsilon]
type conditional_tag = [`Conditional]
type integer_constant_tag = [`Integer_constant]
type range_constant_tag = [`Range_constant]
type modular_constant_tag = [`Modular_constant]
type fixed_constant_tag = [`Fixed_constant]
type real_constant_tag = [`Real_constant]
type float_constant_tag = [`Float_constant]
type comment_tag = [`Comment]
type deref_tag = [`Deref]
type record_access_tag = [`Record_access]
type record_update_tag = [`Record_update]
type record_aggregate_tag = [`Record_aggregate]
type any_expr_tag = [`Any_expr]
type assignment_tag = [`Assignment]
type binding_ref_tag = [`Binding_ref]
type loop_tag = [`Loop]
type statement_sequence_tag = [`Statement_sequence]
type abstract_expr_tag = [`Abstract_expr]
type assert_tag = [`Assert]
type raise_tag = [`Raise]
type try_block_tag = [`Try_block]
type function_decl_tag = [`Function_decl]
type axiom_tag = [`Axiom]
type goal_tag = [`Goal]
type type_decl_tag = [`Type_decl]
type global_ref_declaration_tag = [`Global_ref_declaration]
type namespace_declaration_tag = [`Namespace_declaration]
type exception_declaration_tag = [`Exception_declaration]
type meta_declaration_tag = [`Meta_declaration]
type clone_declaration_tag = [`Clone_declaration]
type clone_substitution_tag = [`Clone_substitution]
type include_declaration_tag = [`Include_declaration]
type theory_declaration_tag = [`Theory_declaration]
type module_tag = [`Module]

(* Class tags *)

type expr_tag = [
 | `Universal_quantif
 | `Existential_quantif
 | `Not
 | `Connection
 | `Label
 | `Loc_label
 | `Identifier
 | `Tagged
 | `Call
 | `Literal
 | `Binding
 | `Elsif
 | `Epsilon
 | `Conditional
 | `Integer_constant
 | `Range_constant
 | `Modular_constant
 | `Fixed_constant
 | `Real_constant
 | `Float_constant
 | `Comment
 | `Deref
 | `Record_access
 | `Record_update
 | `Record_aggregate
 | `Any_expr
 | `Assignment
 | `Binding_ref
 | `Loop
 | `Statement_sequence
 | `Abstract_expr
 | `Assert
 | `Raise
 | `Try_block
]
type pred_tag = [
 | `Universal_quantif
 | `Existential_quantif
 | `Not
 | `Connection
 | `Label
 | `Loc_label
 | `Identifier
 | `Tagged
 | `Call
 | `Literal
 | `Binding
 | `Elsif
 | `Epsilon
 | `Conditional
]
type term_tag = [
 | `Label
 | `Loc_label
 | `Identifier
 | `Tagged
 | `Call
 | `Literal
 | `Binding
 | `Elsif
 | `Epsilon
 | `Conditional
 | `Integer_constant
 | `Range_constant
 | `Modular_constant
 | `Fixed_constant
 | `Real_constant
 | `Float_constant
 | `Comment
 | `Deref
 | `Record_access
 | `Record_update
 | `Record_aggregate
]
type prog_tag = [
 | `Not
 | `Connection
 | `Label
 | `Loc_label
 | `Identifier
 | `Tagged
 | `Call
 | `Literal
 | `Binding
 | `Elsif
 | `Epsilon
 | `Conditional
 | `Integer_constant
 | `Range_constant
 | `Modular_constant
 | `Fixed_constant
 | `Real_constant
 | `Float_constant
 | `Comment
 | `Deref
 | `Record_access
 | `Record_update
 | `Record_aggregate
 | `Any_expr
 | `Assignment
 | `Binding_ref
 | `Loop
 | `Statement_sequence
 | `Abstract_expr
 | `Assert
 | `Raise
 | `Try_block
]
type type_definition_tag = [
 | `Transparent_type_definition
 | `Record_binder
 | `Record_definition
 | `Range_type_definition
]
type declaration_tag = [
 | `Function_decl
 | `Axiom
 | `Goal
 | `Type_decl
 | `Global_ref_declaration
 | `Namespace_declaration
 | `Exception_declaration
 | `Meta_declaration
 | `Clone_declaration
]
type any_node_tag = [
 | `Type
 | `Name
 | `Effects
 | `Raise_effect
 | `Binder
 | `Transparent_type_definition
 | `Record_binder
 | `Record_definition
 | `Range_type_definition
 | `Triggers
 | `Trigger
 | `Axiom_dep
 | `Handler
 | `Field_association
 | `Variant
 | `Variants
 | `Universal_quantif
 | `Existential_quantif
 | `Not
 | `Connection
 | `Label
 | `Loc_label
 | `Identifier
 | `Tagged
 | `Call
 | `Literal
 | `Binding
 | `Elsif
 | `Epsilon
 | `Conditional
 | `Integer_constant
 | `Range_constant
 | `Modular_constant
 | `Fixed_constant
 | `Real_constant
 | `Float_constant
 | `Comment
 | `Deref
 | `Record_access
 | `Record_update
 | `Record_aggregate
 | `Any_expr
 | `Assignment
 | `Binding_ref
 | `Loop
 | `Statement_sequence
 | `Abstract_expr
 | `Assert
 | `Raise
 | `Try_block
 | `Function_decl
 | `Axiom
 | `Goal
 | `Type_decl
 | `Global_ref_declaration
 | `Namespace_declaration
 | `Exception_declaration
 | `Meta_declaration
 | `Clone_declaration
 | `Clone_substitution
 | `Include_declaration
 | `Theory_declaration
 | `Module
]

(* Why_Node *)

type 'a why_node = { info : why_node_info ; desc: 'a why_node_desc }

and why_node_info = {id: int; node: node_id; domain: domain; link: why_node_set; checked: bool}

and 'a why_node_desc =
  | Type : {type_kind: type_; name: name_id; is_mutable: bool; relaxed_init: bool} -> [> type_tag] why_node_desc
  | Name : {symb: symbol; namespace: symbol; module_: module_oid; infix: bool} -> [> name_tag] why_node_desc
  | Effects : {reads: identifier_olist; writes: identifier_olist; raises: raise_effect_olist} -> [> effects_tag] why_node_desc
  | Raise_effect : {name: name_id; arg_id: identifier_oid; post: pred_oid} -> [> raise_effect_tag] why_node_desc
  | Binder : {name: identifier_oid; arg_type: type_id} -> [> binder_tag] why_node_desc
  | Transparent_type_definition : {type_definition: type_id} -> [> transparent_type_definition_tag] why_node_desc
  | Record_binder : {name: identifier_oid; arg_type: type_id; labels: symbol_set; is_mutable: bool} -> [> record_binder_tag] why_node_desc
  | Record_definition : {fields: record_binder_list} -> [> record_definition_tag] why_node_desc
  | Range_type_definition : {first: uint; last: uint} -> [> range_type_definition_tag] why_node_desc
  | Triggers : {triggers: trigger_list} -> [> triggers_tag] why_node_desc
  | Trigger : {terms: expr_list} -> [> trigger_tag] why_node_desc
  | Axiom_dep : {name: identifier_id; kind: axiom_dep_kind} -> [> axiom_dep_tag] why_node_desc
  | Handler : {name: name_id; arg_id: identifier_oid; def: prog_id} -> [> handler_tag] why_node_desc
  | Field_association : {field: identifier_id; value: expr_id} -> [> field_association_tag] why_node_desc
  | Variant : {cmp_op: identifier_id; labels: symbol_set; expr: term_id} -> [> variant_tag] why_node_desc
  | Variants : {variants: variant_list} -> [> variants_tag] why_node_desc
  | Universal_quantif : {variables: identifier_list; labels: symbol_set; var_type: type_id; triggers: triggers_oid; pred: pred_id} -> [> universal_quantif_tag] why_node_desc
  | Existential_quantif : {variables: identifier_list; labels: symbol_set; var_type: type_id; pred: pred_id} -> [> existential_quantif_tag] why_node_desc
  | Not : {right: expr_id} -> [> not_tag] why_node_desc
  | Connection : {left: expr_id; op: connector; right: expr_id; more_right: expr_olist} -> [> connection_tag] why_node_desc
  | Label : {labels: symbol_set; def: expr_id; typ: type_oid} -> [> label_tag] why_node_desc
  | Loc_label : {sloc: source_ptr; def: expr_id; marker: symbol} -> [> loc_label_tag] why_node_desc
  | Identifier : {name: name_id; typ: type_oid; labels: string_sets_set} -> [> identifier_tag] why_node_desc
  | Tagged : {tag: symbol; def: expr_id; typ: type_oid} -> [> tagged_tag] why_node_desc
  | Call : {name: identifier_id; args: expr_olist; typ: type_oid} -> [> call_tag] why_node_desc
  | Literal : {value: literal; typ: type_oid} -> [> literal_tag] why_node_desc
  | Binding : {name: identifier_id; def: expr_id; context: expr_id; typ: type_oid} -> [> binding_tag] why_node_desc
  | Elsif : {condition: expr_id; then_part: expr_id; typ: type_oid} -> [> elsif_tag] why_node_desc
  | Epsilon : {name: identifier_id; typ: type_id; pred: pred_id} -> [> epsilon_tag] why_node_desc
  | Conditional : {condition: expr_id; then_part: expr_id; elsif_parts: expr_olist; else_part: expr_oid; typ: type_oid} -> [> conditional_tag] why_node_desc
  | Integer_constant : {value: uint} -> [> integer_constant_tag] why_node_desc
  | Range_constant : {value: uint; typ: type_id} -> [> range_constant_tag] why_node_desc
  | Modular_constant : {value: uint; typ: type_id} -> [> modular_constant_tag] why_node_desc
  | Fixed_constant : {value: uint; typ: type_id} -> [> fixed_constant_tag] why_node_desc
  | Real_constant : {value: ureal} -> [> real_constant_tag] why_node_desc
  | Float_constant : {value: ureal; typ: type_id} -> [> float_constant_tag] why_node_desc
  | Comment : {comment: symbol} -> [> comment_tag] why_node_desc
  | Deref : {right: identifier_id; typ: type_id} -> [> deref_tag] why_node_desc
  | Record_access : {name: expr_id; field: identifier_id; typ: type_oid} -> [> record_access_tag] why_node_desc
  | Record_update : {name: expr_id; updates: field_association_list; typ: type_oid} -> [> record_update_tag] why_node_desc
  | Record_aggregate : {associations: field_association_list; typ: type_oid} -> [> record_aggregate_tag] why_node_desc
  | Any_expr : {effects: effects_oid; pre: pred_oid; post: pred_oid; return_type: type_id; labels: symbol_set} -> [> any_expr_tag] why_node_desc
  | Assignment : {name: identifier_id; value: prog_id; typ: type_id; labels: symbol_set} -> [> assignment_tag] why_node_desc
  | Binding_ref : {name: identifier_id; def: prog_id; context: prog_id; typ: type_id} -> [> binding_ref_tag] why_node_desc
  | Loop : {code_before: prog_id; invariants: pred_olist; variants: variants_olist; code_after: prog_id} -> [> loop_tag] why_node_desc
  | Statement_sequence : {statements: prog_list} -> [> statement_sequence_tag] why_node_desc
  | Abstract_expr : {expr: prog_id; post: pred_id; typ: type_oid} -> [> abstract_expr_tag] why_node_desc
  | Assert : {pred: pred_id; assert_kind: assert_kind} -> [> assert_tag] why_node_desc
  | Raise : {name: name_id; arg: expr_oid; typ: type_oid} -> [> raise_tag] why_node_desc
  | Try_block : {prog: prog_id; handler: handler_list; typ: type_oid} -> [> try_block_tag] why_node_desc
  | Function_decl : {name: identifier_id; binders: binder_olist; effects: effects_oid; pre: pred_oid; post: pred_oid; return_type: type_oid; def: expr_oid; labels: symbol_set; location: source_ptr} -> [> function_decl_tag] why_node_desc
  | Axiom : {name: symbol; def: pred_id; dep: axiom_dep_oid} -> [> axiom_tag] why_node_desc
  | Goal : {name: symbol; def: pred_id} -> [> goal_tag] why_node_desc
  | Type_decl : {args: identifier_olist; name: name_id; labels: symbol_set; definition: type_definition_oid} -> [> type_decl_tag] why_node_desc
  | Global_ref_declaration : {name: identifier_id; ref_type: type_id; labels: symbol_set; location: source_ptr} -> [> global_ref_declaration_tag] why_node_desc
  | Namespace_declaration : {declarations: declaration_olist; name: symbol} -> [> namespace_declaration_tag] why_node_desc
  | Exception_declaration : {name: name_id; arg: type_oid} -> [> exception_declaration_tag] why_node_desc
  | Meta_declaration : {name: symbol; parameter: symbol} -> [> meta_declaration_tag] why_node_desc
  | Clone_declaration : {origin: module_id; as_name: symbol; clone_kind: clone_type; substitutions: clone_substitution_olist; theory_kind: theory_type} -> [> clone_declaration_tag] why_node_desc
  | Clone_substitution : {kind: subst_type; orig_name: name_id; image: name_id} -> [> clone_substitution_tag] why_node_desc
  | Include_declaration : {module_: module_id; kind: theory_type; use_kind: clone_type} -> [> include_declaration_tag] why_node_desc
  | Theory_declaration : {declarations: declaration_olist; name: symbol; kind: theory_type; includes: include_declaration_olist; comment: symbol} -> [> theory_declaration_tag] why_node_desc
  | Module : {file: symbol; name: symbol} -> [> module_tag] why_node_desc

and 'a why_node_oid = 'a why_node option
and 'a why_node_olist = 'a why_node list
and 'a why_node_id = 'a why_node
and 'a why_node_list = 'a why_node nonempty

(* Kind nodes *)

and type_oid = type_tag why_node_oid
and type_olist = type_tag why_node_olist
and type_id = type_tag why_node_id
and type_list = type_tag why_node_list

and name_oid = name_tag why_node_oid
and name_olist = name_tag why_node_olist
and name_id = name_tag why_node_id
and name_list = name_tag why_node_list

and effects_oid = effects_tag why_node_oid
and effects_olist = effects_tag why_node_olist
and effects_id = effects_tag why_node_id
and effects_list = effects_tag why_node_list

and raise_effect_oid = raise_effect_tag why_node_oid
and raise_effect_olist = raise_effect_tag why_node_olist
and raise_effect_id = raise_effect_tag why_node_id
and raise_effect_list = raise_effect_tag why_node_list

and binder_oid = binder_tag why_node_oid
and binder_olist = binder_tag why_node_olist
and binder_id = binder_tag why_node_id
and binder_list = binder_tag why_node_list

and transparent_type_definition_oid = transparent_type_definition_tag why_node_oid
and transparent_type_definition_olist = transparent_type_definition_tag why_node_olist
and transparent_type_definition_id = transparent_type_definition_tag why_node_id
and transparent_type_definition_list = transparent_type_definition_tag why_node_list

and record_binder_oid = record_binder_tag why_node_oid
and record_binder_olist = record_binder_tag why_node_olist
and record_binder_id = record_binder_tag why_node_id
and record_binder_list = record_binder_tag why_node_list

and record_definition_oid = record_definition_tag why_node_oid
and record_definition_olist = record_definition_tag why_node_olist
and record_definition_id = record_definition_tag why_node_id
and record_definition_list = record_definition_tag why_node_list

and range_type_definition_oid = range_type_definition_tag why_node_oid
and range_type_definition_olist = range_type_definition_tag why_node_olist
and range_type_definition_id = range_type_definition_tag why_node_id
and range_type_definition_list = range_type_definition_tag why_node_list

and triggers_oid = triggers_tag why_node_oid
and triggers_olist = triggers_tag why_node_olist
and triggers_id = triggers_tag why_node_id
and triggers_list = triggers_tag why_node_list

and trigger_oid = trigger_tag why_node_oid
and trigger_olist = trigger_tag why_node_olist
and trigger_id = trigger_tag why_node_id
and trigger_list = trigger_tag why_node_list

and axiom_dep_oid = axiom_dep_tag why_node_oid
and axiom_dep_olist = axiom_dep_tag why_node_olist
and axiom_dep_id = axiom_dep_tag why_node_id
and axiom_dep_list = axiom_dep_tag why_node_list

and handler_oid = handler_tag why_node_oid
and handler_olist = handler_tag why_node_olist
and handler_id = handler_tag why_node_id
and handler_list = handler_tag why_node_list

and field_association_oid = field_association_tag why_node_oid
and field_association_olist = field_association_tag why_node_olist
and field_association_id = field_association_tag why_node_id
and field_association_list = field_association_tag why_node_list

and variant_oid = variant_tag why_node_oid
and variant_olist = variant_tag why_node_olist
and variant_id = variant_tag why_node_id
and variant_list = variant_tag why_node_list

and variants_oid = variants_tag why_node_oid
and variants_olist = variants_tag why_node_olist
and variants_id = variants_tag why_node_id
and variants_list = variants_tag why_node_list

and universal_quantif_oid = universal_quantif_tag why_node_oid
and universal_quantif_olist = universal_quantif_tag why_node_olist
and universal_quantif_id = universal_quantif_tag why_node_id
and universal_quantif_list = universal_quantif_tag why_node_list

and existential_quantif_oid = existential_quantif_tag why_node_oid
and existential_quantif_olist = existential_quantif_tag why_node_olist
and existential_quantif_id = existential_quantif_tag why_node_id
and existential_quantif_list = existential_quantif_tag why_node_list

and not_oid = not_tag why_node_oid
and not_olist = not_tag why_node_olist
and not_id = not_tag why_node_id
and not_list = not_tag why_node_list

and connection_oid = connection_tag why_node_oid
and connection_olist = connection_tag why_node_olist
and connection_id = connection_tag why_node_id
and connection_list = connection_tag why_node_list

and label_oid = label_tag why_node_oid
and label_olist = label_tag why_node_olist
and label_id = label_tag why_node_id
and label_list = label_tag why_node_list

and loc_label_oid = loc_label_tag why_node_oid
and loc_label_olist = loc_label_tag why_node_olist
and loc_label_id = loc_label_tag why_node_id
and loc_label_list = loc_label_tag why_node_list

and identifier_oid = identifier_tag why_node_oid
and identifier_olist = identifier_tag why_node_olist
and identifier_id = identifier_tag why_node_id
and identifier_list = identifier_tag why_node_list

and tagged_oid = tagged_tag why_node_oid
and tagged_olist = tagged_tag why_node_olist
and tagged_id = tagged_tag why_node_id
and tagged_list = tagged_tag why_node_list

and call_oid = call_tag why_node_oid
and call_olist = call_tag why_node_olist
and call_id = call_tag why_node_id
and call_list = call_tag why_node_list

and literal_oid = literal_tag why_node_oid
and literal_olist = literal_tag why_node_olist
and literal_id = literal_tag why_node_id
and literal_list = literal_tag why_node_list

and binding_oid = binding_tag why_node_oid
and binding_olist = binding_tag why_node_olist
and binding_id = binding_tag why_node_id
and binding_list = binding_tag why_node_list

and elsif_oid = elsif_tag why_node_oid
and elsif_olist = elsif_tag why_node_olist
and elsif_id = elsif_tag why_node_id
and elsif_list = elsif_tag why_node_list

and epsilon_oid = epsilon_tag why_node_oid
and epsilon_olist = epsilon_tag why_node_olist
and epsilon_id = epsilon_tag why_node_id
and epsilon_list = epsilon_tag why_node_list

and conditional_oid = conditional_tag why_node_oid
and conditional_olist = conditional_tag why_node_olist
and conditional_id = conditional_tag why_node_id
and conditional_list = conditional_tag why_node_list

and integer_constant_oid = integer_constant_tag why_node_oid
and integer_constant_olist = integer_constant_tag why_node_olist
and integer_constant_id = integer_constant_tag why_node_id
and integer_constant_list = integer_constant_tag why_node_list

and range_constant_oid = range_constant_tag why_node_oid
and range_constant_olist = range_constant_tag why_node_olist
and range_constant_id = range_constant_tag why_node_id
and range_constant_list = range_constant_tag why_node_list

and modular_constant_oid = modular_constant_tag why_node_oid
and modular_constant_olist = modular_constant_tag why_node_olist
and modular_constant_id = modular_constant_tag why_node_id
and modular_constant_list = modular_constant_tag why_node_list

and fixed_constant_oid = fixed_constant_tag why_node_oid
and fixed_constant_olist = fixed_constant_tag why_node_olist
and fixed_constant_id = fixed_constant_tag why_node_id
and fixed_constant_list = fixed_constant_tag why_node_list

and real_constant_oid = real_constant_tag why_node_oid
and real_constant_olist = real_constant_tag why_node_olist
and real_constant_id = real_constant_tag why_node_id
and real_constant_list = real_constant_tag why_node_list

and float_constant_oid = float_constant_tag why_node_oid
and float_constant_olist = float_constant_tag why_node_olist
and float_constant_id = float_constant_tag why_node_id
and float_constant_list = float_constant_tag why_node_list

and comment_oid = comment_tag why_node_oid
and comment_olist = comment_tag why_node_olist
and comment_id = comment_tag why_node_id
and comment_list = comment_tag why_node_list

and deref_oid = deref_tag why_node_oid
and deref_olist = deref_tag why_node_olist
and deref_id = deref_tag why_node_id
and deref_list = deref_tag why_node_list

and record_access_oid = record_access_tag why_node_oid
and record_access_olist = record_access_tag why_node_olist
and record_access_id = record_access_tag why_node_id
and record_access_list = record_access_tag why_node_list

and record_update_oid = record_update_tag why_node_oid
and record_update_olist = record_update_tag why_node_olist
and record_update_id = record_update_tag why_node_id
and record_update_list = record_update_tag why_node_list

and record_aggregate_oid = record_aggregate_tag why_node_oid
and record_aggregate_olist = record_aggregate_tag why_node_olist
and record_aggregate_id = record_aggregate_tag why_node_id
and record_aggregate_list = record_aggregate_tag why_node_list

and any_expr_oid = any_expr_tag why_node_oid
and any_expr_olist = any_expr_tag why_node_olist
and any_expr_id = any_expr_tag why_node_id
and any_expr_list = any_expr_tag why_node_list

and assignment_oid = assignment_tag why_node_oid
and assignment_olist = assignment_tag why_node_olist
and assignment_id = assignment_tag why_node_id
and assignment_list = assignment_tag why_node_list

and binding_ref_oid = binding_ref_tag why_node_oid
and binding_ref_olist = binding_ref_tag why_node_olist
and binding_ref_id = binding_ref_tag why_node_id
and binding_ref_list = binding_ref_tag why_node_list

and loop_oid = loop_tag why_node_oid
and loop_olist = loop_tag why_node_olist
and loop_id = loop_tag why_node_id
and loop_list = loop_tag why_node_list

and statement_sequence_oid = statement_sequence_tag why_node_oid
and statement_sequence_olist = statement_sequence_tag why_node_olist
and statement_sequence_id = statement_sequence_tag why_node_id
and statement_sequence_list = statement_sequence_tag why_node_list

and abstract_expr_oid = abstract_expr_tag why_node_oid
and abstract_expr_olist = abstract_expr_tag why_node_olist
and abstract_expr_id = abstract_expr_tag why_node_id
and abstract_expr_list = abstract_expr_tag why_node_list

and assert_oid = assert_tag why_node_oid
and assert_olist = assert_tag why_node_olist
and assert_id = assert_tag why_node_id
and assert_list = assert_tag why_node_list

and raise_oid = raise_tag why_node_oid
and raise_olist = raise_tag why_node_olist
and raise_id = raise_tag why_node_id
and raise_list = raise_tag why_node_list

and try_block_oid = try_block_tag why_node_oid
and try_block_olist = try_block_tag why_node_olist
and try_block_id = try_block_tag why_node_id
and try_block_list = try_block_tag why_node_list

and function_decl_oid = function_decl_tag why_node_oid
and function_decl_olist = function_decl_tag why_node_olist
and function_decl_id = function_decl_tag why_node_id
and function_decl_list = function_decl_tag why_node_list

and axiom_oid = axiom_tag why_node_oid
and axiom_olist = axiom_tag why_node_olist
and axiom_id = axiom_tag why_node_id
and axiom_list = axiom_tag why_node_list

and goal_oid = goal_tag why_node_oid
and goal_olist = goal_tag why_node_olist
and goal_id = goal_tag why_node_id
and goal_list = goal_tag why_node_list

and type_decl_oid = type_decl_tag why_node_oid
and type_decl_olist = type_decl_tag why_node_olist
and type_decl_id = type_decl_tag why_node_id
and type_decl_list = type_decl_tag why_node_list

and global_ref_declaration_oid = global_ref_declaration_tag why_node_oid
and global_ref_declaration_olist = global_ref_declaration_tag why_node_olist
and global_ref_declaration_id = global_ref_declaration_tag why_node_id
and global_ref_declaration_list = global_ref_declaration_tag why_node_list

and namespace_declaration_oid = namespace_declaration_tag why_node_oid
and namespace_declaration_olist = namespace_declaration_tag why_node_olist
and namespace_declaration_id = namespace_declaration_tag why_node_id
and namespace_declaration_list = namespace_declaration_tag why_node_list

and exception_declaration_oid = exception_declaration_tag why_node_oid
and exception_declaration_olist = exception_declaration_tag why_node_olist
and exception_declaration_id = exception_declaration_tag why_node_id
and exception_declaration_list = exception_declaration_tag why_node_list

and meta_declaration_oid = meta_declaration_tag why_node_oid
and meta_declaration_olist = meta_declaration_tag why_node_olist
and meta_declaration_id = meta_declaration_tag why_node_id
and meta_declaration_list = meta_declaration_tag why_node_list

and clone_declaration_oid = clone_declaration_tag why_node_oid
and clone_declaration_olist = clone_declaration_tag why_node_olist
and clone_declaration_id = clone_declaration_tag why_node_id
and clone_declaration_list = clone_declaration_tag why_node_list

and clone_substitution_oid = clone_substitution_tag why_node_oid
and clone_substitution_olist = clone_substitution_tag why_node_olist
and clone_substitution_id = clone_substitution_tag why_node_id
and clone_substitution_list = clone_substitution_tag why_node_list

and include_declaration_oid = include_declaration_tag why_node_oid
and include_declaration_olist = include_declaration_tag why_node_olist
and include_declaration_id = include_declaration_tag why_node_id
and include_declaration_list = include_declaration_tag why_node_list

and theory_declaration_oid = theory_declaration_tag why_node_oid
and theory_declaration_olist = theory_declaration_tag why_node_olist
and theory_declaration_id = theory_declaration_tag why_node_id
and theory_declaration_list = theory_declaration_tag why_node_list

and module_oid = module_tag why_node_oid
and module_olist = module_tag why_node_olist
and module_id = module_tag why_node_id
and module_list = module_tag why_node_list

(* Class nodes *)

and expr_oid = expr_tag why_node_oid
and expr_olist = expr_tag why_node_olist
and expr_id = expr_tag why_node_id
and expr_list = expr_tag why_node_list

and pred_oid = pred_tag why_node_oid
and pred_olist = pred_tag why_node_olist
and pred_id = pred_tag why_node_id
and pred_list = pred_tag why_node_list

and term_oid = term_tag why_node_oid
and term_olist = term_tag why_node_olist
and term_id = term_tag why_node_id
and term_list = term_tag why_node_list

and prog_oid = prog_tag why_node_oid
and prog_olist = prog_tag why_node_olist
and prog_id = prog_tag why_node_id
and prog_list = prog_tag why_node_list

and type_definition_oid = type_definition_tag why_node_oid
and type_definition_olist = type_definition_tag why_node_olist
and type_definition_id = type_definition_tag why_node_id
and type_definition_list = type_definition_tag why_node_list

and declaration_oid = declaration_tag why_node_oid
and declaration_olist = declaration_tag why_node_olist
and declaration_id = declaration_tag why_node_id
and declaration_list = declaration_tag why_node_list

and any_node_oid = any_node_tag why_node_oid
and any_node_olist = any_node_tag why_node_olist
and any_node_id = any_node_tag why_node_id
and any_node_list = any_node_tag why_node_list

type file = { theory_declarations: theory_declaration_olist }

(* Tag coercions *)
let type_coercion (node : any_node_tag why_node) : type_tag why_node =
  match node.desc with
  | Type _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "type_coercion"

let name_coercion (node : any_node_tag why_node) : name_tag why_node =
  match node.desc with
  | Name _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "name_coercion"

let effects_coercion (node : any_node_tag why_node) : effects_tag why_node =
  match node.desc with
  | Effects _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "effects_coercion"

let raise_effect_coercion (node : any_node_tag why_node) : raise_effect_tag why_node =
  match node.desc with
  | Raise_effect _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "raise_effect_coercion"

let binder_coercion (node : any_node_tag why_node) : binder_tag why_node =
  match node.desc with
  | Binder _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "binder_coercion"

let transparent_type_definition_coercion (node : any_node_tag why_node) : transparent_type_definition_tag why_node =
  match node.desc with
  | Transparent_type_definition _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "transparent_type_definition_coercion"

let record_binder_coercion (node : any_node_tag why_node) : record_binder_tag why_node =
  match node.desc with
  | Record_binder _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "record_binder_coercion"

let record_definition_coercion (node : any_node_tag why_node) : record_definition_tag why_node =
  match node.desc with
  | Record_definition _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "record_definition_coercion"

let range_type_definition_coercion (node : any_node_tag why_node) : range_type_definition_tag why_node =
  match node.desc with
  | Range_type_definition _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "range_type_definition_coercion"

let triggers_coercion (node : any_node_tag why_node) : triggers_tag why_node =
  match node.desc with
  | Triggers _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "triggers_coercion"

let trigger_coercion (node : any_node_tag why_node) : trigger_tag why_node =
  match node.desc with
  | Trigger _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "trigger_coercion"

let axiom_dep_coercion (node : any_node_tag why_node) : axiom_dep_tag why_node =
  match node.desc with
  | Axiom_dep _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "axiom_dep_coercion"

let handler_coercion (node : any_node_tag why_node) : handler_tag why_node =
  match node.desc with
  | Handler _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "handler_coercion"

let field_association_coercion (node : any_node_tag why_node) : field_association_tag why_node =
  match node.desc with
  | Field_association _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "field_association_coercion"

let variant_coercion (node : any_node_tag why_node) : variant_tag why_node =
  match node.desc with
  | Variant _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "variant_coercion"

let variants_coercion (node : any_node_tag why_node) : variants_tag why_node =
  match node.desc with
  | Variants _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "variants_coercion"

let universal_quantif_coercion (node : any_node_tag why_node) : universal_quantif_tag why_node =
  match node.desc with
  | Universal_quantif _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "universal_quantif_coercion"

let existential_quantif_coercion (node : any_node_tag why_node) : existential_quantif_tag why_node =
  match node.desc with
  | Existential_quantif _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "existential_quantif_coercion"

let not_coercion (node : any_node_tag why_node) : not_tag why_node =
  match node.desc with
  | Not _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "not_coercion"

let connection_coercion (node : any_node_tag why_node) : connection_tag why_node =
  match node.desc with
  | Connection _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "connection_coercion"

let label_coercion (node : any_node_tag why_node) : label_tag why_node =
  match node.desc with
  | Label _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "label_coercion"

let loc_label_coercion (node : any_node_tag why_node) : loc_label_tag why_node =
  match node.desc with
  | Loc_label _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "loc_label_coercion"

let identifier_coercion (node : any_node_tag why_node) : identifier_tag why_node =
  match node.desc with
  | Identifier _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "identifier_coercion"

let tagged_coercion (node : any_node_tag why_node) : tagged_tag why_node =
  match node.desc with
  | Tagged _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "tagged_coercion"

let call_coercion (node : any_node_tag why_node) : call_tag why_node =
  match node.desc with
  | Call _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "call_coercion"

let literal_coercion (node : any_node_tag why_node) : literal_tag why_node =
  match node.desc with
  | Literal _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "literal_coercion"

let binding_coercion (node : any_node_tag why_node) : binding_tag why_node =
  match node.desc with
  | Binding _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "binding_coercion"

let elsif_coercion (node : any_node_tag why_node) : elsif_tag why_node =
  match node.desc with
  | Elsif _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "elsif_coercion"

let epsilon_coercion (node : any_node_tag why_node) : epsilon_tag why_node =
  match node.desc with
  | Epsilon _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "epsilon_coercion"

let conditional_coercion (node : any_node_tag why_node) : conditional_tag why_node =
  match node.desc with
  | Conditional _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "conditional_coercion"

let integer_constant_coercion (node : any_node_tag why_node) : integer_constant_tag why_node =
  match node.desc with
  | Integer_constant _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "integer_constant_coercion"

let range_constant_coercion (node : any_node_tag why_node) : range_constant_tag why_node =
  match node.desc with
  | Range_constant _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "range_constant_coercion"

let modular_constant_coercion (node : any_node_tag why_node) : modular_constant_tag why_node =
  match node.desc with
  | Modular_constant _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "modular_constant_coercion"

let fixed_constant_coercion (node : any_node_tag why_node) : fixed_constant_tag why_node =
  match node.desc with
  | Fixed_constant _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "fixed_constant_coercion"

let real_constant_coercion (node : any_node_tag why_node) : real_constant_tag why_node =
  match node.desc with
  | Real_constant _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "real_constant_coercion"

let float_constant_coercion (node : any_node_tag why_node) : float_constant_tag why_node =
  match node.desc with
  | Float_constant _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "float_constant_coercion"

let comment_coercion (node : any_node_tag why_node) : comment_tag why_node =
  match node.desc with
  | Comment _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "comment_coercion"

let deref_coercion (node : any_node_tag why_node) : deref_tag why_node =
  match node.desc with
  | Deref _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "deref_coercion"

let record_access_coercion (node : any_node_tag why_node) : record_access_tag why_node =
  match node.desc with
  | Record_access _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "record_access_coercion"

let record_update_coercion (node : any_node_tag why_node) : record_update_tag why_node =
  match node.desc with
  | Record_update _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "record_update_coercion"

let record_aggregate_coercion (node : any_node_tag why_node) : record_aggregate_tag why_node =
  match node.desc with
  | Record_aggregate _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "record_aggregate_coercion"

let any_expr_coercion (node : any_node_tag why_node) : any_expr_tag why_node =
  match node.desc with
  | Any_expr _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "any_expr_coercion"

let assignment_coercion (node : any_node_tag why_node) : assignment_tag why_node =
  match node.desc with
  | Assignment _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "assignment_coercion"

let binding_ref_coercion (node : any_node_tag why_node) : binding_ref_tag why_node =
  match node.desc with
  | Binding_ref _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "binding_ref_coercion"

let loop_coercion (node : any_node_tag why_node) : loop_tag why_node =
  match node.desc with
  | Loop _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "loop_coercion"

let statement_sequence_coercion (node : any_node_tag why_node) : statement_sequence_tag why_node =
  match node.desc with
  | Statement_sequence _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "statement_sequence_coercion"

let abstract_expr_coercion (node : any_node_tag why_node) : abstract_expr_tag why_node =
  match node.desc with
  | Abstract_expr _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "abstract_expr_coercion"

let assert_coercion (node : any_node_tag why_node) : assert_tag why_node =
  match node.desc with
  | Assert _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "assert_coercion"

let raise_coercion (node : any_node_tag why_node) : raise_tag why_node =
  match node.desc with
  | Raise _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "raise_coercion"

let try_block_coercion (node : any_node_tag why_node) : try_block_tag why_node =
  match node.desc with
  | Try_block _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "try_block_coercion"

let function_decl_coercion (node : any_node_tag why_node) : function_decl_tag why_node =
  match node.desc with
  | Function_decl _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "function_decl_coercion"

let axiom_coercion (node : any_node_tag why_node) : axiom_tag why_node =
  match node.desc with
  | Axiom _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "axiom_coercion"

let goal_coercion (node : any_node_tag why_node) : goal_tag why_node =
  match node.desc with
  | Goal _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "goal_coercion"

let type_decl_coercion (node : any_node_tag why_node) : type_decl_tag why_node =
  match node.desc with
  | Type_decl _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "type_decl_coercion"

let global_ref_declaration_coercion (node : any_node_tag why_node) : global_ref_declaration_tag why_node =
  match node.desc with
  | Global_ref_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "global_ref_declaration_coercion"

let namespace_declaration_coercion (node : any_node_tag why_node) : namespace_declaration_tag why_node =
  match node.desc with
  | Namespace_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "namespace_declaration_coercion"

let exception_declaration_coercion (node : any_node_tag why_node) : exception_declaration_tag why_node =
  match node.desc with
  | Exception_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "exception_declaration_coercion"

let meta_declaration_coercion (node : any_node_tag why_node) : meta_declaration_tag why_node =
  match node.desc with
  | Meta_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "meta_declaration_coercion"

let clone_declaration_coercion (node : any_node_tag why_node) : clone_declaration_tag why_node =
  match node.desc with
  | Clone_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "clone_declaration_coercion"

let clone_substitution_coercion (node : any_node_tag why_node) : clone_substitution_tag why_node =
  match node.desc with
  | Clone_substitution _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "clone_substitution_coercion"

let include_declaration_coercion (node : any_node_tag why_node) : include_declaration_tag why_node =
  match node.desc with
  | Include_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "include_declaration_coercion"

let theory_declaration_coercion (node : any_node_tag why_node) : theory_declaration_tag why_node =
  match node.desc with
  | Theory_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "theory_declaration_coercion"

let module_coercion (node : any_node_tag why_node) : module_tag why_node =
  match node.desc with
  | Module _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "module_coercion"


(* Class coercions *)
let expr_coercion (node : any_node_tag why_node) : expr_tag why_node =
  match node.desc with
  | Universal_quantif _ as desc -> {info=node.info; desc}
  | Existential_quantif _ as desc -> {info=node.info; desc}
  | Not _ as desc -> {info=node.info; desc}
  | Connection _ as desc -> {info=node.info; desc}
  | Label _ as desc -> {info=node.info; desc}
  | Loc_label _ as desc -> {info=node.info; desc}
  | Identifier _ as desc -> {info=node.info; desc}
  | Tagged _ as desc -> {info=node.info; desc}
  | Call _ as desc -> {info=node.info; desc}
  | Literal _ as desc -> {info=node.info; desc}
  | Binding _ as desc -> {info=node.info; desc}
  | Elsif _ as desc -> {info=node.info; desc}
  | Epsilon _ as desc -> {info=node.info; desc}
  | Conditional _ as desc -> {info=node.info; desc}
  | Integer_constant _ as desc -> {info=node.info; desc}
  | Range_constant _ as desc -> {info=node.info; desc}
  | Modular_constant _ as desc -> {info=node.info; desc}
  | Fixed_constant _ as desc -> {info=node.info; desc}
  | Real_constant _ as desc -> {info=node.info; desc}
  | Float_constant _ as desc -> {info=node.info; desc}
  | Comment _ as desc -> {info=node.info; desc}
  | Deref _ as desc -> {info=node.info; desc}
  | Record_access _ as desc -> {info=node.info; desc}
  | Record_update _ as desc -> {info=node.info; desc}
  | Record_aggregate _ as desc -> {info=node.info; desc}
  | Any_expr _ as desc -> {info=node.info; desc}
  | Assignment _ as desc -> {info=node.info; desc}
  | Binding_ref _ as desc -> {info=node.info; desc}
  | Loop _ as desc -> {info=node.info; desc}
  | Statement_sequence _ as desc -> {info=node.info; desc}
  | Abstract_expr _ as desc -> {info=node.info; desc}
  | Assert _ as desc -> {info=node.info; desc}
  | Raise _ as desc -> {info=node.info; desc}
  | Try_block _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "expr_coercion"
  [@@warning "-11"]

let pred_coercion (node : any_node_tag why_node) : pred_tag why_node =
  match node.desc with
  | Universal_quantif _ as desc -> {info=node.info; desc}
  | Existential_quantif _ as desc -> {info=node.info; desc}
  | Not _ as desc -> {info=node.info; desc}
  | Connection _ as desc -> {info=node.info; desc}
  | Label _ as desc -> {info=node.info; desc}
  | Loc_label _ as desc -> {info=node.info; desc}
  | Identifier _ as desc -> {info=node.info; desc}
  | Tagged _ as desc -> {info=node.info; desc}
  | Call _ as desc -> {info=node.info; desc}
  | Literal _ as desc -> {info=node.info; desc}
  | Binding _ as desc -> {info=node.info; desc}
  | Elsif _ as desc -> {info=node.info; desc}
  | Epsilon _ as desc -> {info=node.info; desc}
  | Conditional _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "pred_coercion"
  [@@warning "-11"]

let term_coercion (node : any_node_tag why_node) : term_tag why_node =
  match node.desc with
  | Label _ as desc -> {info=node.info; desc}
  | Loc_label _ as desc -> {info=node.info; desc}
  | Identifier _ as desc -> {info=node.info; desc}
  | Tagged _ as desc -> {info=node.info; desc}
  | Call _ as desc -> {info=node.info; desc}
  | Literal _ as desc -> {info=node.info; desc}
  | Binding _ as desc -> {info=node.info; desc}
  | Elsif _ as desc -> {info=node.info; desc}
  | Epsilon _ as desc -> {info=node.info; desc}
  | Conditional _ as desc -> {info=node.info; desc}
  | Integer_constant _ as desc -> {info=node.info; desc}
  | Range_constant _ as desc -> {info=node.info; desc}
  | Modular_constant _ as desc -> {info=node.info; desc}
  | Fixed_constant _ as desc -> {info=node.info; desc}
  | Real_constant _ as desc -> {info=node.info; desc}
  | Float_constant _ as desc -> {info=node.info; desc}
  | Comment _ as desc -> {info=node.info; desc}
  | Deref _ as desc -> {info=node.info; desc}
  | Record_access _ as desc -> {info=node.info; desc}
  | Record_update _ as desc -> {info=node.info; desc}
  | Record_aggregate _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "term_coercion"
  [@@warning "-11"]

let prog_coercion (node : any_node_tag why_node) : prog_tag why_node =
  match node.desc with
  | Not _ as desc -> {info=node.info; desc}
  | Connection _ as desc -> {info=node.info; desc}
  | Label _ as desc -> {info=node.info; desc}
  | Loc_label _ as desc -> {info=node.info; desc}
  | Identifier _ as desc -> {info=node.info; desc}
  | Tagged _ as desc -> {info=node.info; desc}
  | Call _ as desc -> {info=node.info; desc}
  | Literal _ as desc -> {info=node.info; desc}
  | Binding _ as desc -> {info=node.info; desc}
  | Elsif _ as desc -> {info=node.info; desc}
  | Epsilon _ as desc -> {info=node.info; desc}
  | Conditional _ as desc -> {info=node.info; desc}
  | Integer_constant _ as desc -> {info=node.info; desc}
  | Range_constant _ as desc -> {info=node.info; desc}
  | Modular_constant _ as desc -> {info=node.info; desc}
  | Fixed_constant _ as desc -> {info=node.info; desc}
  | Real_constant _ as desc -> {info=node.info; desc}
  | Float_constant _ as desc -> {info=node.info; desc}
  | Comment _ as desc -> {info=node.info; desc}
  | Deref _ as desc -> {info=node.info; desc}
  | Record_access _ as desc -> {info=node.info; desc}
  | Record_update _ as desc -> {info=node.info; desc}
  | Record_aggregate _ as desc -> {info=node.info; desc}
  | Any_expr _ as desc -> {info=node.info; desc}
  | Assignment _ as desc -> {info=node.info; desc}
  | Binding_ref _ as desc -> {info=node.info; desc}
  | Loop _ as desc -> {info=node.info; desc}
  | Statement_sequence _ as desc -> {info=node.info; desc}
  | Abstract_expr _ as desc -> {info=node.info; desc}
  | Assert _ as desc -> {info=node.info; desc}
  | Raise _ as desc -> {info=node.info; desc}
  | Try_block _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "prog_coercion"
  [@@warning "-11"]

let type_definition_coercion (node : any_node_tag why_node) : type_definition_tag why_node =
  match node.desc with
  | Transparent_type_definition _ as desc -> {info=node.info; desc}
  | Record_binder _ as desc -> {info=node.info; desc}
  | Record_definition _ as desc -> {info=node.info; desc}
  | Range_type_definition _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "type_definition_coercion"
  [@@warning "-11"]

let declaration_coercion (node : any_node_tag why_node) : declaration_tag why_node =
  match node.desc with
  | Function_decl _ as desc -> {info=node.info; desc}
  | Axiom _ as desc -> {info=node.info; desc}
  | Goal _ as desc -> {info=node.info; desc}
  | Type_decl _ as desc -> {info=node.info; desc}
  | Global_ref_declaration _ as desc -> {info=node.info; desc}
  | Namespace_declaration _ as desc -> {info=node.info; desc}
  | Exception_declaration _ as desc -> {info=node.info; desc}
  | Meta_declaration _ as desc -> {info=node.info; desc}
  | Clone_declaration _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "declaration_coercion"
  [@@warning "-11"]

let any_node_coercion (node : any_node_tag why_node) : any_node_tag why_node =
  match node.desc with
  | Type _ as desc -> {info=node.info; desc}
  | Name _ as desc -> {info=node.info; desc}
  | Effects _ as desc -> {info=node.info; desc}
  | Raise_effect _ as desc -> {info=node.info; desc}
  | Binder _ as desc -> {info=node.info; desc}
  | Transparent_type_definition _ as desc -> {info=node.info; desc}
  | Record_binder _ as desc -> {info=node.info; desc}
  | Record_definition _ as desc -> {info=node.info; desc}
  | Range_type_definition _ as desc -> {info=node.info; desc}
  | Triggers _ as desc -> {info=node.info; desc}
  | Trigger _ as desc -> {info=node.info; desc}
  | Axiom_dep _ as desc -> {info=node.info; desc}
  | Handler _ as desc -> {info=node.info; desc}
  | Field_association _ as desc -> {info=node.info; desc}
  | Variant _ as desc -> {info=node.info; desc}
  | Variants _ as desc -> {info=node.info; desc}
  | Universal_quantif _ as desc -> {info=node.info; desc}
  | Existential_quantif _ as desc -> {info=node.info; desc}
  | Not _ as desc -> {info=node.info; desc}
  | Connection _ as desc -> {info=node.info; desc}
  | Label _ as desc -> {info=node.info; desc}
  | Loc_label _ as desc -> {info=node.info; desc}
  | Identifier _ as desc -> {info=node.info; desc}
  | Tagged _ as desc -> {info=node.info; desc}
  | Call _ as desc -> {info=node.info; desc}
  | Literal _ as desc -> {info=node.info; desc}
  | Binding _ as desc -> {info=node.info; desc}
  | Elsif _ as desc -> {info=node.info; desc}
  | Epsilon _ as desc -> {info=node.info; desc}
  | Conditional _ as desc -> {info=node.info; desc}
  | Integer_constant _ as desc -> {info=node.info; desc}
  | Range_constant _ as desc -> {info=node.info; desc}
  | Modular_constant _ as desc -> {info=node.info; desc}
  | Fixed_constant _ as desc -> {info=node.info; desc}
  | Real_constant _ as desc -> {info=node.info; desc}
  | Float_constant _ as desc -> {info=node.info; desc}
  | Comment _ as desc -> {info=node.info; desc}
  | Deref _ as desc -> {info=node.info; desc}
  | Record_access _ as desc -> {info=node.info; desc}
  | Record_update _ as desc -> {info=node.info; desc}
  | Record_aggregate _ as desc -> {info=node.info; desc}
  | Any_expr _ as desc -> {info=node.info; desc}
  | Assignment _ as desc -> {info=node.info; desc}
  | Binding_ref _ as desc -> {info=node.info; desc}
  | Loop _ as desc -> {info=node.info; desc}
  | Statement_sequence _ as desc -> {info=node.info; desc}
  | Abstract_expr _ as desc -> {info=node.info; desc}
  | Assert _ as desc -> {info=node.info; desc}
  | Raise _ as desc -> {info=node.info; desc}
  | Try_block _ as desc -> {info=node.info; desc}
  | Function_decl _ as desc -> {info=node.info; desc}
  | Axiom _ as desc -> {info=node.info; desc}
  | Goal _ as desc -> {info=node.info; desc}
  | Type_decl _ as desc -> {info=node.info; desc}
  | Global_ref_declaration _ as desc -> {info=node.info; desc}
  | Namespace_declaration _ as desc -> {info=node.info; desc}
  | Exception_declaration _ as desc -> {info=node.info; desc}
  | Meta_declaration _ as desc -> {info=node.info; desc}
  | Clone_declaration _ as desc -> {info=node.info; desc}
  | Clone_substitution _ as desc -> {info=node.info; desc}
  | Include_declaration _ as desc -> {info=node.info; desc}
  | Theory_declaration _ as desc -> {info=node.info; desc}
  | Module _ as desc -> {info=node.info; desc}
  | _ -> invalid_arg "any_node_coercion"
  [@@warning "-11"]


module From_json = struct

  type t = [
    | `Null
    | `Bool of bool
    | `Int of int
    | `Intlit of string
    | `Float of float
    | `String of string
    | `Assoc of (string * t) list
    | `List of t list
    | `Tuple of t list
    | `Variant of string * t option
  ]

  type 'a from_json = t -> 'a

  exception Unexpected_Json of string * t

  let unexpected_json type_str json =
    raise (Unexpected_Json (type_str, json))

  let boolean_from_json : bool from_json = function
    | `Bool b -> b
    | json -> unexpected_json "bool" json

  let int_from_json : int from_json = function
    | `Int i -> i
    | json -> unexpected_json "int" json

  let uint_from_json : uint from_json = function
    | `String s -> Uint s
    | json -> unexpected_json "uint" json

  let ureal_from_json : ureal from_json = function
    | `List [numerator; denominator; base; negative] ->
      Ureal {
        numerator = uint_from_json numerator;
        denominator = uint_from_json denominator;
        base = int_from_json base;
        negative = boolean_from_json negative;
      }
    | json ->
      unexpected_json "ureal" json

  let source_ptr_from_json : source_ptr from_json = function
    | `Null -> No_location
    | `List [`String filename; `Int line] ->
      Source_ptr {filename; line}
    | json -> unexpected_json "source_ptr" json

  let node_id_from_json : node_id from_json = function
    | `String "<Node_Id>" -> Node_id
    | json -> unexpected_json "node_id" json

  let why_node_set_from_json : why_node_set from_json = function
    | `String "<Why_Node_Set>" -> ()
    | json -> unexpected_json "why_node_set" json

  let symbol_from_json : symbol from_json = function
    | `String "" -> No_symbol
    | `String s -> Symbol s
    | json -> unexpected_json "symbol" json

  let symbol_set_from_json : symbol_set from_json = function
    | `List l -> List.map symbol_from_json l
    | json -> unexpected_json "symbol_set" json

  let string_sets_set_from_json : string_sets_set from_json = function
    | `List l -> List.map symbol_from_json l
    | json -> unexpected_json "string_sets_set" json

  (* Why.Sinfo *)

  let domain_from_json : domain from_json = function
    | `Int 1 -> Term
    | `Int 2 -> Pterm
    | `Int 3 -> Pred
    | `Int 4 -> Prog
    | json -> unexpected_json "domain" json

  let type_from_json : type_ from_json = function
    | `Int 0 -> Builtin
    | `Int 1 -> Split
    | `Int 2 -> Abstract
    | json -> unexpected_json "type_" json

  let literal_from_json : literal from_json = function
    | `Int 0 -> True
    | `Int 1 -> False
    | json -> unexpected_json "literal" json

  let theory_type_from_json : theory_type from_json = function
    | `Int 0 -> Theory
    | `Int 1 -> Module
    | json -> unexpected_json "theory_type" json

  let clone_type_from_json : clone_type from_json = function
    | `Int 0 -> Import
    | `Int 1 -> Export
    | `Int 2 -> Clone_default
    | json -> unexpected_json "clone_type" json

  let subst_type_from_json : subst_type from_json = function
    | `Int 0 -> Type_subst
    | `Int 1 -> Function
    | `Int 2 -> Predicate
    | `Int 3 -> Namepace
    | `Int 4 -> Lemma
    | `Int 5 -> Goal
    | json -> unexpected_json "subst_type" json

  let connector_from_json : connector from_json = function
    | `Int 0 -> Or_else
    | `Int 1 -> And_then
    | `Int 2 -> Imply
    | `Int 3 -> Equivalent
    | `Int 4 -> Or
    | `Int 5 -> And
    | json -> unexpected_json "connector" json

  let assert_kind_from_json : assert_kind from_json = function
    | `Int 0 -> Assert
    | `Int 1 -> Check
    | `Int 2 -> Assume
    | json -> unexpected_json "assert_kind" json

  let axiom_dep_kind_from_json : axiom_dep_kind from_json = function
    | `Int 0 -> Axdep_func
    | `Int 1 -> Axdep_pred
    | json -> unexpected_json "axiom_dep_kind" json

  let rec why_node_from_json : 'a why_node from_json = function
    | `List [`String "W_TYPE"; id; node; domain; link; checked; type_kind; name; is_mutable; relaxed_init] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Type {
        type_kind = type_from_json type_kind;
        name = name_opaque_id_from_json name;
        is_mutable = boolean_from_json is_mutable;
        relaxed_init = boolean_from_json relaxed_init;
      } in
      {info; desc}
    | `List [`String "W_NAME"; id; node; domain; link; checked; symb; namespace; module_; infix] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Name {
        symb = symbol_from_json symb;
        namespace = symbol_from_json namespace;
        module_ = module_opaque_oid_from_json module_;
        infix = boolean_from_json infix;
      } in
      {info; desc}
    | `List [`String "W_EFFECTS"; id; node; domain; link; checked; reads; writes; raises] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Effects {
        reads = identifier_opaque_olist_from_json reads;
        writes = identifier_opaque_olist_from_json writes;
        raises = raise_effect_opaque_olist_from_json raises;
      } in
      {info; desc}
    | `List [`String "W_RAISE_EFFECT"; id; node; domain; link; checked; name; arg_id; post] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Raise_effect {
        name = name_opaque_id_from_json name;
        arg_id = identifier_opaque_oid_from_json arg_id;
        post = pred_opaque_oid_from_json post;
      } in
      {info; desc}
    | `List [`String "W_BINDER"; id; node; domain; link; checked; name; arg_type] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Binder {
        name = identifier_opaque_oid_from_json name;
        arg_type = type_opaque_id_from_json arg_type;
      } in
      {info; desc}
    | `List [`String "W_TRANSPARENT_TYPE_DEFINITION"; id; node; domain; link; checked; type_definition] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Transparent_type_definition {
        type_definition = type_opaque_id_from_json type_definition;
      } in
      {info; desc}
    | `List [`String "W_RECORD_BINDER"; id; node; domain; link; checked; name; arg_type; labels; is_mutable] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Record_binder {
        name = identifier_opaque_oid_from_json name;
        arg_type = type_opaque_id_from_json arg_type;
        labels = symbol_set_from_json labels;
        is_mutable = boolean_from_json is_mutable;
      } in
      {info; desc}
    | `List [`String "W_RECORD_DEFINITION"; id; node; domain; link; checked; fields] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Record_definition {
        fields = record_binder_opaque_list_from_json fields;
      } in
      {info; desc}
    | `List [`String "W_RANGE_TYPE_DEFINITION"; id; node; domain; link; checked; first; last] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Range_type_definition {
        first = uint_from_json first;
        last = uint_from_json last;
      } in
      {info; desc}
    | `List [`String "W_TRIGGERS"; id; node; domain; link; checked; triggers] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Triggers {
        triggers = trigger_opaque_list_from_json triggers;
      } in
      {info; desc}
    | `List [`String "W_TRIGGER"; id; node; domain; link; checked; terms] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Trigger {
        terms = expr_opaque_list_from_json terms;
      } in
      {info; desc}
    | `List [`String "W_AXIOM_DEP"; id; node; domain; link; checked; name; kind] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Axiom_dep {
        name = identifier_opaque_id_from_json name;
        kind = axiom_dep_kind_from_json kind;
      } in
      {info; desc}
    | `List [`String "W_HANDLER"; id; node; domain; link; checked; name; arg_id; def] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Handler {
        name = name_opaque_id_from_json name;
        arg_id = identifier_opaque_oid_from_json arg_id;
        def = prog_opaque_id_from_json def;
      } in
      {info; desc}
    | `List [`String "W_FIELD_ASSOCIATION"; id; node; domain; link; checked; field; value] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Field_association {
        field = identifier_opaque_id_from_json field;
        value = expr_opaque_id_from_json value;
      } in
      {info; desc}
    | `List [`String "W_VARIANT"; id; node; domain; link; checked; cmp_op; labels; expr] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Variant {
        cmp_op = identifier_opaque_id_from_json cmp_op;
        labels = symbol_set_from_json labels;
        expr = term_opaque_id_from_json expr;
      } in
      {info; desc}
    | `List [`String "W_VARIANTS"; id; node; domain; link; checked; variants] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Variants {
        variants = variant_opaque_list_from_json variants;
      } in
      {info; desc}
    | `List [`String "W_UNIVERSAL_QUANTIF"; id; node; domain; link; checked; variables; labels; var_type; triggers; pred] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Universal_quantif {
        variables = identifier_opaque_list_from_json variables;
        labels = symbol_set_from_json labels;
        var_type = type_opaque_id_from_json var_type;
        triggers = triggers_opaque_oid_from_json triggers;
        pred = pred_opaque_id_from_json pred;
      } in
      {info; desc}
    | `List [`String "W_EXISTENTIAL_QUANTIF"; id; node; domain; link; checked; variables; labels; var_type; pred] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Existential_quantif {
        variables = identifier_opaque_list_from_json variables;
        labels = symbol_set_from_json labels;
        var_type = type_opaque_id_from_json var_type;
        pred = pred_opaque_id_from_json pred;
      } in
      {info; desc}
    | `List [`String "W_NOT"; id; node; domain; link; checked; right] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Not {
        right = expr_opaque_id_from_json right;
      } in
      {info; desc}
    | `List [`String "W_CONNECTION"; id; node; domain; link; checked; left; op; right; more_right] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Connection {
        left = expr_opaque_id_from_json left;
        op = connector_from_json op;
        right = expr_opaque_id_from_json right;
        more_right = expr_opaque_olist_from_json more_right;
      } in
      {info; desc}
    | `List [`String "W_LABEL"; id; node; domain; link; checked; labels; def; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Label {
        labels = symbol_set_from_json labels;
        def = expr_opaque_id_from_json def;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_LOC_LABEL"; id; node; domain; link; checked; sloc; def; marker] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Loc_label {
        sloc = source_ptr_from_json sloc;
        def = expr_opaque_id_from_json def;
        marker = symbol_from_json marker;
      } in
      {info; desc}
    | `List [`String "W_IDENTIFIER"; id; node; domain; link; checked; name; typ; labels] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Identifier {
        name = name_opaque_id_from_json name;
        typ = type_opaque_oid_from_json typ;
        labels = string_sets_set_from_json labels;
      } in
      {info; desc}
    | `List [`String "W_TAGGED"; id; node; domain; link; checked; tag; def; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Tagged {
        tag = symbol_from_json tag;
        def = expr_opaque_id_from_json def;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_CALL"; id; node; domain; link; checked; name; args; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Call {
        name = identifier_opaque_id_from_json name;
        args = expr_opaque_olist_from_json args;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_LITERAL"; id; node; domain; link; checked; value; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Literal {
        value = literal_from_json value;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_BINDING"; id; node; domain; link; checked; name; def; context; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Binding {
        name = identifier_opaque_id_from_json name;
        def = expr_opaque_id_from_json def;
        context = expr_opaque_id_from_json context;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_ELSIF"; id; node; domain; link; checked; condition; then_part; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Elsif {
        condition = expr_opaque_id_from_json condition;
        then_part = expr_opaque_id_from_json then_part;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_EPSILON"; id; node; domain; link; checked; name; typ; pred] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Epsilon {
        name = identifier_opaque_id_from_json name;
        typ = type_opaque_id_from_json typ;
        pred = pred_opaque_id_from_json pred;
      } in
      {info; desc}
    | `List [`String "W_CONDITIONAL"; id; node; domain; link; checked; condition; then_part; elsif_parts; else_part; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Conditional {
        condition = expr_opaque_id_from_json condition;
        then_part = expr_opaque_id_from_json then_part;
        elsif_parts = expr_opaque_olist_from_json elsif_parts;
        else_part = expr_opaque_oid_from_json else_part;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_INTEGER_CONSTANT"; id; node; domain; link; checked; value] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Integer_constant {
        value = uint_from_json value;
      } in
      {info; desc}
    | `List [`String "W_RANGE_CONSTANT"; id; node; domain; link; checked; value; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Range_constant {
        value = uint_from_json value;
        typ = type_opaque_id_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_MODULAR_CONSTANT"; id; node; domain; link; checked; value; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Modular_constant {
        value = uint_from_json value;
        typ = type_opaque_id_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_FIXED_CONSTANT"; id; node; domain; link; checked; value; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Fixed_constant {
        value = uint_from_json value;
        typ = type_opaque_id_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_REAL_CONSTANT"; id; node; domain; link; checked; value] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Real_constant {
        value = ureal_from_json value;
      } in
      {info; desc}
    | `List [`String "W_FLOAT_CONSTANT"; id; node; domain; link; checked; value; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Float_constant {
        value = ureal_from_json value;
        typ = type_opaque_id_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_COMMENT"; id; node; domain; link; checked; comment] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Comment {
        comment = symbol_from_json comment;
      } in
      {info; desc}
    | `List [`String "W_DEREF"; id; node; domain; link; checked; right; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Deref {
        right = identifier_opaque_id_from_json right;
        typ = type_opaque_id_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_RECORD_ACCESS"; id; node; domain; link; checked; name; field; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Record_access {
        name = expr_opaque_id_from_json name;
        field = identifier_opaque_id_from_json field;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_RECORD_UPDATE"; id; node; domain; link; checked; name; updates; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Record_update {
        name = expr_opaque_id_from_json name;
        updates = field_association_opaque_list_from_json updates;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_RECORD_AGGREGATE"; id; node; domain; link; checked; associations; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Record_aggregate {
        associations = field_association_opaque_list_from_json associations;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_ANY_EXPR"; id; node; domain; link; checked; effects; pre; post; return_type; labels] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Any_expr {
        effects = effects_opaque_oid_from_json effects;
        pre = pred_opaque_oid_from_json pre;
        post = pred_opaque_oid_from_json post;
        return_type = type_opaque_id_from_json return_type;
        labels = symbol_set_from_json labels;
      } in
      {info; desc}
    | `List [`String "W_ASSIGNMENT"; id; node; domain; link; checked; name; value; typ; labels] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Assignment {
        name = identifier_opaque_id_from_json name;
        value = prog_opaque_id_from_json value;
        typ = type_opaque_id_from_json typ;
        labels = symbol_set_from_json labels;
      } in
      {info; desc}
    | `List [`String "W_BINDING_REF"; id; node; domain; link; checked; name; def; context; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Binding_ref {
        name = identifier_opaque_id_from_json name;
        def = prog_opaque_id_from_json def;
        context = prog_opaque_id_from_json context;
        typ = type_opaque_id_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_LOOP"; id; node; domain; link; checked; code_before; invariants; variants; code_after] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Loop {
        code_before = prog_opaque_id_from_json code_before;
        invariants = pred_opaque_olist_from_json invariants;
        variants = variants_opaque_olist_from_json variants;
        code_after = prog_opaque_id_from_json code_after;
      } in
      {info; desc}
    | `List [`String "W_STATEMENT_SEQUENCE"; id; node; domain; link; checked; statements] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Statement_sequence {
        statements = prog_opaque_list_from_json statements;
      } in
      {info; desc}
    | `List [`String "W_ABSTRACT_EXPR"; id; node; domain; link; checked; expr; post; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Abstract_expr {
        expr = prog_opaque_id_from_json expr;
        post = pred_opaque_id_from_json post;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_ASSERT"; id; node; domain; link; checked; pred; assert_kind] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Assert {
        pred = pred_opaque_id_from_json pred;
        assert_kind = assert_kind_from_json assert_kind;
      } in
      {info; desc}
    | `List [`String "W_RAISE"; id; node; domain; link; checked; name; arg; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Raise {
        name = name_opaque_id_from_json name;
        arg = expr_opaque_oid_from_json arg;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_TRY_BLOCK"; id; node; domain; link; checked; prog; handler; typ] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Try_block {
        prog = prog_opaque_id_from_json prog;
        handler = handler_opaque_list_from_json handler;
        typ = type_opaque_oid_from_json typ;
      } in
      {info; desc}
    | `List [`String "W_FUNCTION_DECL"; id; node; domain; link; checked; name; binders; effects; pre; post; return_type; def; labels; location] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Function_decl {
        name = identifier_opaque_id_from_json name;
        binders = binder_opaque_olist_from_json binders;
        effects = effects_opaque_oid_from_json effects;
        pre = pred_opaque_oid_from_json pre;
        post = pred_opaque_oid_from_json post;
        return_type = type_opaque_oid_from_json return_type;
        def = expr_opaque_oid_from_json def;
        labels = symbol_set_from_json labels;
        location = source_ptr_from_json location;
      } in
      {info; desc}
    | `List [`String "W_AXIOM"; id; node; domain; link; checked; name; def; dep] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Axiom {
        name = symbol_from_json name;
        def = pred_opaque_id_from_json def;
        dep = axiom_dep_opaque_oid_from_json dep;
      } in
      {info; desc}
    | `List [`String "W_GOAL"; id; node; domain; link; checked; name; def] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Goal {
        name = symbol_from_json name;
        def = pred_opaque_id_from_json def;
      } in
      {info; desc}
    | `List [`String "W_TYPE_DECL"; id; node; domain; link; checked; args; name; labels; definition] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Type_decl {
        args = identifier_opaque_olist_from_json args;
        name = name_opaque_id_from_json name;
        labels = symbol_set_from_json labels;
        definition = type_definition_opaque_oid_from_json definition;
      } in
      {info; desc}
    | `List [`String "W_GLOBAL_REF_DECLARATION"; id; node; domain; link; checked; name; ref_type; labels; location] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Global_ref_declaration {
        name = identifier_opaque_id_from_json name;
        ref_type = type_opaque_id_from_json ref_type;
        labels = symbol_set_from_json labels;
        location = source_ptr_from_json location;
      } in
      {info; desc}
    | `List [`String "W_NAMESPACE_DECLARATION"; id; node; domain; link; checked; declarations; name] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Namespace_declaration {
        declarations = declaration_opaque_olist_from_json declarations;
        name = symbol_from_json name;
      } in
      {info; desc}
    | `List [`String "W_EXCEPTION_DECLARATION"; id; node; domain; link; checked; name; arg] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Exception_declaration {
        name = name_opaque_id_from_json name;
        arg = type_opaque_oid_from_json arg;
      } in
      {info; desc}
    | `List [`String "W_META_DECLARATION"; id; node; domain; link; checked; name; parameter] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Meta_declaration {
        name = symbol_from_json name;
        parameter = symbol_from_json parameter;
      } in
      {info; desc}
    | `List [`String "W_CLONE_DECLARATION"; id; node; domain; link; checked; origin; as_name; clone_kind; substitutions; theory_kind] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Clone_declaration {
        origin = module_opaque_id_from_json origin;
        as_name = symbol_from_json as_name;
        clone_kind = clone_type_from_json clone_kind;
        substitutions = clone_substitution_opaque_olist_from_json substitutions;
        theory_kind = theory_type_from_json theory_kind;
      } in
      {info; desc}
    | `List [`String "W_CLONE_SUBSTITUTION"; id; node; domain; link; checked; kind; orig_name; image] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Clone_substitution {
        kind = subst_type_from_json kind;
        orig_name = name_opaque_id_from_json orig_name;
        image = name_opaque_id_from_json image;
      } in
      {info; desc}
    | `List [`String "W_INCLUDE_DECLARATION"; id; node; domain; link; checked; module_; kind; use_kind] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Include_declaration {
        module_ = module_opaque_id_from_json module_;
        kind = theory_type_from_json kind;
        use_kind = clone_type_from_json use_kind;
      } in
      {info; desc}
    | `List [`String "W_THEORY_DECLARATION"; id; node; domain; link; checked; declarations; name; kind; includes; comment] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Theory_declaration {
        declarations = declaration_opaque_olist_from_json declarations;
        name = symbol_from_json name;
        kind = theory_type_from_json kind;
        includes = include_declaration_opaque_olist_from_json includes;
        comment = symbol_from_json comment;
      } in
      {info; desc}
    | `List [`String "W_MODULE"; id; node; domain; link; checked; file; name] ->
      let info = {
        id = int_from_json id;
        node = node_id_from_json node;
        domain = domain_from_json domain;
        link = why_node_set_from_json link;
        checked = boolean_from_json checked;
      } in
      let desc = Module {
        file = symbol_from_json file;
        name = symbol_from_json name;
      } in
      {info; desc}
    | json ->
      unexpected_json "why_node" json

  and why_node_id_from_json : 'a . (any_node_tag why_node -> 'a why_node) -> 'a why_node_id from_json =
    fun coerce json ->
    coerce (why_node_from_json json)

  and why_node_oid_from_json : 'a . (any_node_tag why_node -> 'a why_node) -> 'a why_node_oid from_json =
    fun coerce json ->
    match json with
    | `Null ->
      None
    | json ->
      Some (coerce (why_node_from_json json))

  and why_node_list_from_json : 'a . (any_node_tag why_node -> 'a why_node) -> 'a why_node_list from_json =
    fun coerce json ->
    match json with
    | `List (elt0 :: elts) ->
      let elt0 = coerce (why_node_from_json elt0) in
      let elts =
        List.map coerce
          (List.map why_node_from_json elts) in
      {elt0; elts}
    | json ->
      unexpected_json "why_node_list" json

  and why_node_olist_from_json : 'a . (any_node_tag why_node -> 'a why_node) -> 'a why_node_olist from_json =
    fun coerce json ->
    match json with
    | `Null ->
      []
    | `List l ->
      List.map coerce
        (List.map why_node_from_json l)
    | json ->
      unexpected_json "why_node_olist_from_json" json

  (* Opaque tags from json *)

  and type_opaque_oid_from_json json =  why_node_oid_from_json type_coercion json
  and type_opaque_olist_from_json json =  why_node_olist_from_json type_coercion json
  and type_opaque_id_from_json json =  why_node_id_from_json type_coercion json
  and type_opaque_list_from_json json =  why_node_list_from_json type_coercion json

  and name_opaque_oid_from_json json =  why_node_oid_from_json name_coercion json
  and name_opaque_olist_from_json json =  why_node_olist_from_json name_coercion json
  and name_opaque_id_from_json json =  why_node_id_from_json name_coercion json
  and name_opaque_list_from_json json =  why_node_list_from_json name_coercion json

  and effects_opaque_oid_from_json json =  why_node_oid_from_json effects_coercion json
  and effects_opaque_olist_from_json json =  why_node_olist_from_json effects_coercion json
  and effects_opaque_id_from_json json =  why_node_id_from_json effects_coercion json
  and effects_opaque_list_from_json json =  why_node_list_from_json effects_coercion json

  and raise_effect_opaque_oid_from_json json =  why_node_oid_from_json raise_effect_coercion json
  and raise_effect_opaque_olist_from_json json =  why_node_olist_from_json raise_effect_coercion json
  and raise_effect_opaque_id_from_json json =  why_node_id_from_json raise_effect_coercion json
  and raise_effect_opaque_list_from_json json =  why_node_list_from_json raise_effect_coercion json

  and binder_opaque_oid_from_json json =  why_node_oid_from_json binder_coercion json
  and binder_opaque_olist_from_json json =  why_node_olist_from_json binder_coercion json
  and binder_opaque_id_from_json json =  why_node_id_from_json binder_coercion json
  and binder_opaque_list_from_json json =  why_node_list_from_json binder_coercion json

  and transparent_type_definition_opaque_oid_from_json json =  why_node_oid_from_json transparent_type_definition_coercion json
  and transparent_type_definition_opaque_olist_from_json json =  why_node_olist_from_json transparent_type_definition_coercion json
  and transparent_type_definition_opaque_id_from_json json =  why_node_id_from_json transparent_type_definition_coercion json
  and transparent_type_definition_opaque_list_from_json json =  why_node_list_from_json transparent_type_definition_coercion json

  and record_binder_opaque_oid_from_json json =  why_node_oid_from_json record_binder_coercion json
  and record_binder_opaque_olist_from_json json =  why_node_olist_from_json record_binder_coercion json
  and record_binder_opaque_id_from_json json =  why_node_id_from_json record_binder_coercion json
  and record_binder_opaque_list_from_json json =  why_node_list_from_json record_binder_coercion json

  and record_definition_opaque_oid_from_json json =  why_node_oid_from_json record_definition_coercion json
  and record_definition_opaque_olist_from_json json =  why_node_olist_from_json record_definition_coercion json
  and record_definition_opaque_id_from_json json =  why_node_id_from_json record_definition_coercion json
  and record_definition_opaque_list_from_json json =  why_node_list_from_json record_definition_coercion json

  and range_type_definition_opaque_oid_from_json json =  why_node_oid_from_json range_type_definition_coercion json
  and range_type_definition_opaque_olist_from_json json =  why_node_olist_from_json range_type_definition_coercion json
  and range_type_definition_opaque_id_from_json json =  why_node_id_from_json range_type_definition_coercion json
  and range_type_definition_opaque_list_from_json json =  why_node_list_from_json range_type_definition_coercion json

  and triggers_opaque_oid_from_json json =  why_node_oid_from_json triggers_coercion json
  and triggers_opaque_olist_from_json json =  why_node_olist_from_json triggers_coercion json
  and triggers_opaque_id_from_json json =  why_node_id_from_json triggers_coercion json
  and triggers_opaque_list_from_json json =  why_node_list_from_json triggers_coercion json

  and trigger_opaque_oid_from_json json =  why_node_oid_from_json trigger_coercion json
  and trigger_opaque_olist_from_json json =  why_node_olist_from_json trigger_coercion json
  and trigger_opaque_id_from_json json =  why_node_id_from_json trigger_coercion json
  and trigger_opaque_list_from_json json =  why_node_list_from_json trigger_coercion json

  and axiom_dep_opaque_oid_from_json json =  why_node_oid_from_json axiom_dep_coercion json
  and axiom_dep_opaque_olist_from_json json =  why_node_olist_from_json axiom_dep_coercion json
  and axiom_dep_opaque_id_from_json json =  why_node_id_from_json axiom_dep_coercion json
  and axiom_dep_opaque_list_from_json json =  why_node_list_from_json axiom_dep_coercion json

  and handler_opaque_oid_from_json json =  why_node_oid_from_json handler_coercion json
  and handler_opaque_olist_from_json json =  why_node_olist_from_json handler_coercion json
  and handler_opaque_id_from_json json =  why_node_id_from_json handler_coercion json
  and handler_opaque_list_from_json json =  why_node_list_from_json handler_coercion json

  and field_association_opaque_oid_from_json json =  why_node_oid_from_json field_association_coercion json
  and field_association_opaque_olist_from_json json =  why_node_olist_from_json field_association_coercion json
  and field_association_opaque_id_from_json json =  why_node_id_from_json field_association_coercion json
  and field_association_opaque_list_from_json json =  why_node_list_from_json field_association_coercion json

  and variant_opaque_oid_from_json json =  why_node_oid_from_json variant_coercion json
  and variant_opaque_olist_from_json json =  why_node_olist_from_json variant_coercion json
  and variant_opaque_id_from_json json =  why_node_id_from_json variant_coercion json
  and variant_opaque_list_from_json json =  why_node_list_from_json variant_coercion json

  and variants_opaque_oid_from_json json =  why_node_oid_from_json variants_coercion json
  and variants_opaque_olist_from_json json =  why_node_olist_from_json variants_coercion json
  and variants_opaque_id_from_json json =  why_node_id_from_json variants_coercion json
  and variants_opaque_list_from_json json =  why_node_list_from_json variants_coercion json

  and universal_quantif_opaque_oid_from_json json =  why_node_oid_from_json universal_quantif_coercion json
  and universal_quantif_opaque_olist_from_json json =  why_node_olist_from_json universal_quantif_coercion json
  and universal_quantif_opaque_id_from_json json =  why_node_id_from_json universal_quantif_coercion json
  and universal_quantif_opaque_list_from_json json =  why_node_list_from_json universal_quantif_coercion json

  and existential_quantif_opaque_oid_from_json json =  why_node_oid_from_json existential_quantif_coercion json
  and existential_quantif_opaque_olist_from_json json =  why_node_olist_from_json existential_quantif_coercion json
  and existential_quantif_opaque_id_from_json json =  why_node_id_from_json existential_quantif_coercion json
  and existential_quantif_opaque_list_from_json json =  why_node_list_from_json existential_quantif_coercion json

  and not_opaque_oid_from_json json =  why_node_oid_from_json not_coercion json
  and not_opaque_olist_from_json json =  why_node_olist_from_json not_coercion json
  and not_opaque_id_from_json json =  why_node_id_from_json not_coercion json
  and not_opaque_list_from_json json =  why_node_list_from_json not_coercion json

  and connection_opaque_oid_from_json json =  why_node_oid_from_json connection_coercion json
  and connection_opaque_olist_from_json json =  why_node_olist_from_json connection_coercion json
  and connection_opaque_id_from_json json =  why_node_id_from_json connection_coercion json
  and connection_opaque_list_from_json json =  why_node_list_from_json connection_coercion json

  and label_opaque_oid_from_json json =  why_node_oid_from_json label_coercion json
  and label_opaque_olist_from_json json =  why_node_olist_from_json label_coercion json
  and label_opaque_id_from_json json =  why_node_id_from_json label_coercion json
  and label_opaque_list_from_json json =  why_node_list_from_json label_coercion json

  and loc_label_opaque_oid_from_json json =  why_node_oid_from_json loc_label_coercion json
  and loc_label_opaque_olist_from_json json =  why_node_olist_from_json loc_label_coercion json
  and loc_label_opaque_id_from_json json =  why_node_id_from_json loc_label_coercion json
  and loc_label_opaque_list_from_json json =  why_node_list_from_json loc_label_coercion json

  and identifier_opaque_oid_from_json json =  why_node_oid_from_json identifier_coercion json
  and identifier_opaque_olist_from_json json =  why_node_olist_from_json identifier_coercion json
  and identifier_opaque_id_from_json json =  why_node_id_from_json identifier_coercion json
  and identifier_opaque_list_from_json json =  why_node_list_from_json identifier_coercion json

  and tagged_opaque_oid_from_json json =  why_node_oid_from_json tagged_coercion json
  and tagged_opaque_olist_from_json json =  why_node_olist_from_json tagged_coercion json
  and tagged_opaque_id_from_json json =  why_node_id_from_json tagged_coercion json
  and tagged_opaque_list_from_json json =  why_node_list_from_json tagged_coercion json

  and call_opaque_oid_from_json json =  why_node_oid_from_json call_coercion json
  and call_opaque_olist_from_json json =  why_node_olist_from_json call_coercion json
  and call_opaque_id_from_json json =  why_node_id_from_json call_coercion json
  and call_opaque_list_from_json json =  why_node_list_from_json call_coercion json

  and literal_opaque_oid_from_json json =  why_node_oid_from_json literal_coercion json
  and literal_opaque_olist_from_json json =  why_node_olist_from_json literal_coercion json
  and literal_opaque_id_from_json json =  why_node_id_from_json literal_coercion json
  and literal_opaque_list_from_json json =  why_node_list_from_json literal_coercion json

  and binding_opaque_oid_from_json json =  why_node_oid_from_json binding_coercion json
  and binding_opaque_olist_from_json json =  why_node_olist_from_json binding_coercion json
  and binding_opaque_id_from_json json =  why_node_id_from_json binding_coercion json
  and binding_opaque_list_from_json json =  why_node_list_from_json binding_coercion json

  and elsif_opaque_oid_from_json json =  why_node_oid_from_json elsif_coercion json
  and elsif_opaque_olist_from_json json =  why_node_olist_from_json elsif_coercion json
  and elsif_opaque_id_from_json json =  why_node_id_from_json elsif_coercion json
  and elsif_opaque_list_from_json json =  why_node_list_from_json elsif_coercion json

  and epsilon_opaque_oid_from_json json =  why_node_oid_from_json epsilon_coercion json
  and epsilon_opaque_olist_from_json json =  why_node_olist_from_json epsilon_coercion json
  and epsilon_opaque_id_from_json json =  why_node_id_from_json epsilon_coercion json
  and epsilon_opaque_list_from_json json =  why_node_list_from_json epsilon_coercion json

  and conditional_opaque_oid_from_json json =  why_node_oid_from_json conditional_coercion json
  and conditional_opaque_olist_from_json json =  why_node_olist_from_json conditional_coercion json
  and conditional_opaque_id_from_json json =  why_node_id_from_json conditional_coercion json
  and conditional_opaque_list_from_json json =  why_node_list_from_json conditional_coercion json

  and integer_constant_opaque_oid_from_json json =  why_node_oid_from_json integer_constant_coercion json
  and integer_constant_opaque_olist_from_json json =  why_node_olist_from_json integer_constant_coercion json
  and integer_constant_opaque_id_from_json json =  why_node_id_from_json integer_constant_coercion json
  and integer_constant_opaque_list_from_json json =  why_node_list_from_json integer_constant_coercion json

  and range_constant_opaque_oid_from_json json =  why_node_oid_from_json range_constant_coercion json
  and range_constant_opaque_olist_from_json json =  why_node_olist_from_json range_constant_coercion json
  and range_constant_opaque_id_from_json json =  why_node_id_from_json range_constant_coercion json
  and range_constant_opaque_list_from_json json =  why_node_list_from_json range_constant_coercion json

  and modular_constant_opaque_oid_from_json json =  why_node_oid_from_json modular_constant_coercion json
  and modular_constant_opaque_olist_from_json json =  why_node_olist_from_json modular_constant_coercion json
  and modular_constant_opaque_id_from_json json =  why_node_id_from_json modular_constant_coercion json
  and modular_constant_opaque_list_from_json json =  why_node_list_from_json modular_constant_coercion json

  and fixed_constant_opaque_oid_from_json json =  why_node_oid_from_json fixed_constant_coercion json
  and fixed_constant_opaque_olist_from_json json =  why_node_olist_from_json fixed_constant_coercion json
  and fixed_constant_opaque_id_from_json json =  why_node_id_from_json fixed_constant_coercion json
  and fixed_constant_opaque_list_from_json json =  why_node_list_from_json fixed_constant_coercion json

  and real_constant_opaque_oid_from_json json =  why_node_oid_from_json real_constant_coercion json
  and real_constant_opaque_olist_from_json json =  why_node_olist_from_json real_constant_coercion json
  and real_constant_opaque_id_from_json json =  why_node_id_from_json real_constant_coercion json
  and real_constant_opaque_list_from_json json =  why_node_list_from_json real_constant_coercion json

  and float_constant_opaque_oid_from_json json =  why_node_oid_from_json float_constant_coercion json
  and float_constant_opaque_olist_from_json json =  why_node_olist_from_json float_constant_coercion json
  and float_constant_opaque_id_from_json json =  why_node_id_from_json float_constant_coercion json
  and float_constant_opaque_list_from_json json =  why_node_list_from_json float_constant_coercion json

  and comment_opaque_oid_from_json json =  why_node_oid_from_json comment_coercion json
  and comment_opaque_olist_from_json json =  why_node_olist_from_json comment_coercion json
  and comment_opaque_id_from_json json =  why_node_id_from_json comment_coercion json
  and comment_opaque_list_from_json json =  why_node_list_from_json comment_coercion json

  and deref_opaque_oid_from_json json =  why_node_oid_from_json deref_coercion json
  and deref_opaque_olist_from_json json =  why_node_olist_from_json deref_coercion json
  and deref_opaque_id_from_json json =  why_node_id_from_json deref_coercion json
  and deref_opaque_list_from_json json =  why_node_list_from_json deref_coercion json

  and record_access_opaque_oid_from_json json =  why_node_oid_from_json record_access_coercion json
  and record_access_opaque_olist_from_json json =  why_node_olist_from_json record_access_coercion json
  and record_access_opaque_id_from_json json =  why_node_id_from_json record_access_coercion json
  and record_access_opaque_list_from_json json =  why_node_list_from_json record_access_coercion json

  and record_update_opaque_oid_from_json json =  why_node_oid_from_json record_update_coercion json
  and record_update_opaque_olist_from_json json =  why_node_olist_from_json record_update_coercion json
  and record_update_opaque_id_from_json json =  why_node_id_from_json record_update_coercion json
  and record_update_opaque_list_from_json json =  why_node_list_from_json record_update_coercion json

  and record_aggregate_opaque_oid_from_json json =  why_node_oid_from_json record_aggregate_coercion json
  and record_aggregate_opaque_olist_from_json json =  why_node_olist_from_json record_aggregate_coercion json
  and record_aggregate_opaque_id_from_json json =  why_node_id_from_json record_aggregate_coercion json
  and record_aggregate_opaque_list_from_json json =  why_node_list_from_json record_aggregate_coercion json

  and any_expr_opaque_oid_from_json json =  why_node_oid_from_json any_expr_coercion json
  and any_expr_opaque_olist_from_json json =  why_node_olist_from_json any_expr_coercion json
  and any_expr_opaque_id_from_json json =  why_node_id_from_json any_expr_coercion json
  and any_expr_opaque_list_from_json json =  why_node_list_from_json any_expr_coercion json

  and assignment_opaque_oid_from_json json =  why_node_oid_from_json assignment_coercion json
  and assignment_opaque_olist_from_json json =  why_node_olist_from_json assignment_coercion json
  and assignment_opaque_id_from_json json =  why_node_id_from_json assignment_coercion json
  and assignment_opaque_list_from_json json =  why_node_list_from_json assignment_coercion json

  and binding_ref_opaque_oid_from_json json =  why_node_oid_from_json binding_ref_coercion json
  and binding_ref_opaque_olist_from_json json =  why_node_olist_from_json binding_ref_coercion json
  and binding_ref_opaque_id_from_json json =  why_node_id_from_json binding_ref_coercion json
  and binding_ref_opaque_list_from_json json =  why_node_list_from_json binding_ref_coercion json

  and loop_opaque_oid_from_json json =  why_node_oid_from_json loop_coercion json
  and loop_opaque_olist_from_json json =  why_node_olist_from_json loop_coercion json
  and loop_opaque_id_from_json json =  why_node_id_from_json loop_coercion json
  and loop_opaque_list_from_json json =  why_node_list_from_json loop_coercion json

  and statement_sequence_opaque_oid_from_json json =  why_node_oid_from_json statement_sequence_coercion json
  and statement_sequence_opaque_olist_from_json json =  why_node_olist_from_json statement_sequence_coercion json
  and statement_sequence_opaque_id_from_json json =  why_node_id_from_json statement_sequence_coercion json
  and statement_sequence_opaque_list_from_json json =  why_node_list_from_json statement_sequence_coercion json

  and abstract_expr_opaque_oid_from_json json =  why_node_oid_from_json abstract_expr_coercion json
  and abstract_expr_opaque_olist_from_json json =  why_node_olist_from_json abstract_expr_coercion json
  and abstract_expr_opaque_id_from_json json =  why_node_id_from_json abstract_expr_coercion json
  and abstract_expr_opaque_list_from_json json =  why_node_list_from_json abstract_expr_coercion json

  and assert_opaque_oid_from_json json =  why_node_oid_from_json assert_coercion json
  and assert_opaque_olist_from_json json =  why_node_olist_from_json assert_coercion json
  and assert_opaque_id_from_json json =  why_node_id_from_json assert_coercion json
  and assert_opaque_list_from_json json =  why_node_list_from_json assert_coercion json

  and raise_opaque_oid_from_json json =  why_node_oid_from_json raise_coercion json
  and raise_opaque_olist_from_json json =  why_node_olist_from_json raise_coercion json
  and raise_opaque_id_from_json json =  why_node_id_from_json raise_coercion json
  and raise_opaque_list_from_json json =  why_node_list_from_json raise_coercion json

  and try_block_opaque_oid_from_json json =  why_node_oid_from_json try_block_coercion json
  and try_block_opaque_olist_from_json json =  why_node_olist_from_json try_block_coercion json
  and try_block_opaque_id_from_json json =  why_node_id_from_json try_block_coercion json
  and try_block_opaque_list_from_json json =  why_node_list_from_json try_block_coercion json

  and function_decl_opaque_oid_from_json json =  why_node_oid_from_json function_decl_coercion json
  and function_decl_opaque_olist_from_json json =  why_node_olist_from_json function_decl_coercion json
  and function_decl_opaque_id_from_json json =  why_node_id_from_json function_decl_coercion json
  and function_decl_opaque_list_from_json json =  why_node_list_from_json function_decl_coercion json

  and axiom_opaque_oid_from_json json =  why_node_oid_from_json axiom_coercion json
  and axiom_opaque_olist_from_json json =  why_node_olist_from_json axiom_coercion json
  and axiom_opaque_id_from_json json =  why_node_id_from_json axiom_coercion json
  and axiom_opaque_list_from_json json =  why_node_list_from_json axiom_coercion json

  and goal_opaque_oid_from_json json =  why_node_oid_from_json goal_coercion json
  and goal_opaque_olist_from_json json =  why_node_olist_from_json goal_coercion json
  and goal_opaque_id_from_json json =  why_node_id_from_json goal_coercion json
  and goal_opaque_list_from_json json =  why_node_list_from_json goal_coercion json

  and type_decl_opaque_oid_from_json json =  why_node_oid_from_json type_decl_coercion json
  and type_decl_opaque_olist_from_json json =  why_node_olist_from_json type_decl_coercion json
  and type_decl_opaque_id_from_json json =  why_node_id_from_json type_decl_coercion json
  and type_decl_opaque_list_from_json json =  why_node_list_from_json type_decl_coercion json

  and global_ref_declaration_opaque_oid_from_json json =  why_node_oid_from_json global_ref_declaration_coercion json
  and global_ref_declaration_opaque_olist_from_json json =  why_node_olist_from_json global_ref_declaration_coercion json
  and global_ref_declaration_opaque_id_from_json json =  why_node_id_from_json global_ref_declaration_coercion json
  and global_ref_declaration_opaque_list_from_json json =  why_node_list_from_json global_ref_declaration_coercion json

  and namespace_declaration_opaque_oid_from_json json =  why_node_oid_from_json namespace_declaration_coercion json
  and namespace_declaration_opaque_olist_from_json json =  why_node_olist_from_json namespace_declaration_coercion json
  and namespace_declaration_opaque_id_from_json json =  why_node_id_from_json namespace_declaration_coercion json
  and namespace_declaration_opaque_list_from_json json =  why_node_list_from_json namespace_declaration_coercion json

  and exception_declaration_opaque_oid_from_json json =  why_node_oid_from_json exception_declaration_coercion json
  and exception_declaration_opaque_olist_from_json json =  why_node_olist_from_json exception_declaration_coercion json
  and exception_declaration_opaque_id_from_json json =  why_node_id_from_json exception_declaration_coercion json
  and exception_declaration_opaque_list_from_json json =  why_node_list_from_json exception_declaration_coercion json

  and meta_declaration_opaque_oid_from_json json =  why_node_oid_from_json meta_declaration_coercion json
  and meta_declaration_opaque_olist_from_json json =  why_node_olist_from_json meta_declaration_coercion json
  and meta_declaration_opaque_id_from_json json =  why_node_id_from_json meta_declaration_coercion json
  and meta_declaration_opaque_list_from_json json =  why_node_list_from_json meta_declaration_coercion json

  and clone_declaration_opaque_oid_from_json json =  why_node_oid_from_json clone_declaration_coercion json
  and clone_declaration_opaque_olist_from_json json =  why_node_olist_from_json clone_declaration_coercion json
  and clone_declaration_opaque_id_from_json json =  why_node_id_from_json clone_declaration_coercion json
  and clone_declaration_opaque_list_from_json json =  why_node_list_from_json clone_declaration_coercion json

  and clone_substitution_opaque_oid_from_json json =  why_node_oid_from_json clone_substitution_coercion json
  and clone_substitution_opaque_olist_from_json json =  why_node_olist_from_json clone_substitution_coercion json
  and clone_substitution_opaque_id_from_json json =  why_node_id_from_json clone_substitution_coercion json
  and clone_substitution_opaque_list_from_json json =  why_node_list_from_json clone_substitution_coercion json

  and include_declaration_opaque_oid_from_json json =  why_node_oid_from_json include_declaration_coercion json
  and include_declaration_opaque_olist_from_json json =  why_node_olist_from_json include_declaration_coercion json
  and include_declaration_opaque_id_from_json json =  why_node_id_from_json include_declaration_coercion json
  and include_declaration_opaque_list_from_json json =  why_node_list_from_json include_declaration_coercion json

  and theory_declaration_opaque_oid_from_json json =  why_node_oid_from_json theory_declaration_coercion json
  and theory_declaration_opaque_olist_from_json json =  why_node_olist_from_json theory_declaration_coercion json
  and theory_declaration_opaque_id_from_json json =  why_node_id_from_json theory_declaration_coercion json
  and theory_declaration_opaque_list_from_json json =  why_node_list_from_json theory_declaration_coercion json

  and module_opaque_oid_from_json json =  why_node_oid_from_json module_coercion json
  and module_opaque_olist_from_json json =  why_node_olist_from_json module_coercion json
  and module_opaque_id_from_json json =  why_node_id_from_json module_coercion json
  and module_opaque_list_from_json json =  why_node_list_from_json module_coercion json

  (* Opaque classes from json *)

  and expr_opaque_oid_from_json json =  why_node_oid_from_json expr_coercion json
  and expr_opaque_olist_from_json json =  why_node_olist_from_json expr_coercion json
  and expr_opaque_id_from_json json =  why_node_id_from_json expr_coercion json
  and expr_opaque_list_from_json json =  why_node_list_from_json expr_coercion json

  and pred_opaque_oid_from_json json =  why_node_oid_from_json pred_coercion json
  and pred_opaque_olist_from_json json =  why_node_olist_from_json pred_coercion json
  and pred_opaque_id_from_json json =  why_node_id_from_json pred_coercion json
  and pred_opaque_list_from_json json =  why_node_list_from_json pred_coercion json

  and term_opaque_oid_from_json json =  why_node_oid_from_json term_coercion json
  and term_opaque_olist_from_json json =  why_node_olist_from_json term_coercion json
  and term_opaque_id_from_json json =  why_node_id_from_json term_coercion json
  and term_opaque_list_from_json json =  why_node_list_from_json term_coercion json

  and prog_opaque_oid_from_json json =  why_node_oid_from_json prog_coercion json
  and prog_opaque_olist_from_json json =  why_node_olist_from_json prog_coercion json
  and prog_opaque_id_from_json json =  why_node_id_from_json prog_coercion json
  and prog_opaque_list_from_json json =  why_node_list_from_json prog_coercion json

  and type_definition_opaque_oid_from_json json =  why_node_oid_from_json type_definition_coercion json
  and type_definition_opaque_olist_from_json json =  why_node_olist_from_json type_definition_coercion json
  and type_definition_opaque_id_from_json json =  why_node_id_from_json type_definition_coercion json
  and type_definition_opaque_list_from_json json =  why_node_list_from_json type_definition_coercion json

  and declaration_opaque_oid_from_json json =  why_node_oid_from_json declaration_coercion json
  and declaration_opaque_olist_from_json json =  why_node_olist_from_json declaration_coercion json
  and declaration_opaque_id_from_json json =  why_node_id_from_json declaration_coercion json
  and declaration_opaque_list_from_json json =  why_node_list_from_json declaration_coercion json

  and any_node_opaque_oid_from_json json =  why_node_oid_from_json any_node_coercion json
  and any_node_opaque_olist_from_json json =  why_node_olist_from_json any_node_coercion json
  and any_node_opaque_id_from_json json =  why_node_id_from_json any_node_coercion json
  and any_node_opaque_list_from_json json =  why_node_list_from_json any_node_coercion json

  let file_from_json : file from_json = function
    | `Assoc fields when
        List.length fields = 1 && List.mem_assoc "theory_declarations" fields  ->
      let ast_json = List.assoc "theory_declarations" fields in
      let theory_declarations = theory_declaration_opaque_olist_from_json ast_json in
      { theory_declarations }
    | json -> unexpected_json "file_from_json" json
end