12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455(** Registering and checking builtin symbols. *)openLplibopenBaseopenExtraopenTimedopenCommonopenErroropenPosopenTermopenSig_state(** [get ss pos name] returns the symbol mapped to the builtin [name]. If the
symbol cannot be found then [Fatal] is raised. *)letget:sig_state->popt->string->sym=funssposname->tryStrMap.findnamess.builtinswithNot_found->fatalpos"Builtin symbol \"%s\" undefined."name(** [get_opt ss name] returns [Some s] where [s] is the symbol mapped to
the builtin [name], and [None] otherwise. *)letget_opt:sig_state->string->symoption=funssname->trySome(StrMap.findnamess.builtins)withNot_found->None(** Hash-table used to record checking functions for builtins. *)lethtbl:(string,sig_state->popt->sym->unit)Hashtbl.t=Hashtbl.create17(** [check ss pos name sym] runs the registered check for builtin symbol
[name] on the symbol [sym] (if such a check has been registered). Note that
the [bmap] argument is expected to contain the builtin symbols in scope,
and the [pos] argument is used for error reporting. *)letcheck:sig_state->popt->string->sym->unit=funssposnamesym->tryHashtbl.findhtblnamesspossymwithNot_found->()(** [register name check] registers the checking function [check], for the
builtin symbols named [name]. When the check is run, [check] receives as
argument a position for error reporting as well as the map of every builtin
symbol in scope. It is expected to raise the [Fatal] exception to signal an
error. Note that this function should not be called using a [name] for
which a check has already been registered. *)letregister:string->(sig_state->popt->sym->unit)->unit=funnamecheck->ifHashtbl.memhtblnamethenassertfalse;Hashtbl.addhtblnamecheck(** [register_expected_type name build pp] registers a checking function that
checks the type of a symbol defining the builtin [name] against a type
constructed using the given [build] function. *)letregister_expected_type:termeq->termpp->string->(sig_state->popt->term)->unit=funeqppnamefn->letchecksspossym=letexpected=fnssposinifnot(eq!(sym.sym_type)expected)thenfatalpos"The type of %s is not of the form %a."sym.sym_nameppexpectedinregisternamecheck