Syntax.TermThis module provides functionality for the notion of terms.
val fn_list : unit -> fn listfn_list returns the list of all function symbols names
val get_fn : string -> fnfn_from_string name is f if f is registered with name name.
val get_fn_opt : string -> fn optionget_fn_opt name is Some f if f is registered with name name, None otherwise.
val fn_register : string -> fnfn_register f returns a fn with name f.
Side Effect: f is kept in a stack internally.
val fn_to_string : fn -> stringfn_to_string f is the string (name) associated with f.
fn_compare x y returns 0 if x is equal to y, a negative integer if x is less than y, and a positive integer if x is greater than y.
val fn_register_ty : fn -> Ty.SType.ty -> unitfn_register_ty f t adds the pair (f, t) to the stack.
Side effect: the list of such pairs (f,t) is kept as state in the terms module.
val arity : fn -> Ty.SType.tyarity f returns the registered type of f.
val var_list : unit -> var listvar_list () returns the list of all variables registered up to the time this function is called.
val get_var : string -> varget_var name is the variable v that is registered with the key name name.
val get_var_opt : string -> var optionget_var_opt name is Some v if v is a variable registered with name key name, and None otherwise.
val var_register : string -> varvar_register name registers a variable v using the key name name. If such variable is already registered, then no name is registered and the previously recorded name is returned.
val var_to_string : var -> stringvar_to_string x is the written representation of the key value used to register x.
Finally, given that we have types and functionalities for function symbols and variables, we can construct our type for terms.
Two notions of terms is defined: the type term is for named terms, i.e., variables have names. The second type bruijn is an abstract type used to represent terms in de bruijn notation. We instantiate bruijn to a concrete implementation nameless, where function symbols are fn and indeces are integers.
val tm_to_string : term -> stringtm_to_string t is the written representation of t. It uses standard rules to generate the strings, so unecessary parenthesis are removed:
term_equal t t' is whether t and t' are equal module alpha-equivalence.
In de Bruijn notation, variables are nameless, i.e., they are represented by numbers.
In a closed term, the indexes represent the distance of a variable to its binding abstractor. If the original term t has free variables, then we need a naming context to represent t as a nameless term.
terms_to_bruijn t returns the nameless representation of t, it uses the set of free-variables of t as the name context to determine the index of free variables.
terms_to_bruijn_ctx ctx t returns the nameless representation of t; but contrary to terms_to_bruijn, it uses the context ctx to determine the position of the free variables in t.
val nameless_to_string : nameless -> stringnameless_to_string n returns the string representation of the nameless term n.
nameless_equal n n' is whether n and n' are syntactically equal.
Note: syntactical equality of two nameless terms imply in alpha-equality. Therefore, if t,t' are values of type term, then t is alpha-equivalent to t' iff
nameless_equal (terms_to_bruijn t) (terms_to_bruijn t')
evaluates to true.