B0_scope
Name scopes.
Scopes are used to track and scope the name of b0 definitions created by libraries and b0 files.
TODO.
val is_name_valid : name -> bool
is_name_valid name
is true
iff name
contains no sep
and is not empty.
val pp_name : string B0_std.Fmt.t
pp_name
formats scope or qualified scope names.
val file : t -> B0_std.Fpath.t option
file s
is the file in which the scope is opened.
val dir : t -> B0_std.Fpath.t option
dir s
is the directory of file s
(if any).
val is_root : t -> bool
is_root s
is true
if s
is the file root scope.
val path : t -> string list
path s
are the segments of the qualified name of s
. The segments of the root scope is []
. Library scopes have an initial ""
segment. String.concat sep (path s)
is the qualified name of s
.
val qualify_name : t -> kind:string -> string -> qualified_name
qualify_name s ~kind name
qualifies name name
for an entity of kind kind
(used for error reporting) in scope s
. Raises an error if is_name_valid
name
is false
. However if s
is a library scope then name
can be empty.
val make_unique_qualified_name :
t ->
defs:'a B0_std.String.Map.t ->
kind:string ->
string ->
qualified_name
make_unique_qualified_name
is like qualify_name
but it raises a duplicate definition error if the resulting qualified name is already defined in defs
.
val current : unit -> t option
current ()
is the current scope (if any).
val qualify_name_in_current : kind:string -> name -> qualified_name
qualify_name_in_current name
qualifies name
in the current scope. This is name
if there is no current scope.
val current_make_unique_qualified_name :
defs:'a B0_std.String.Map.t ->
kind:string ->
name ->
qualified_name * t
current_make_unique_qualified_name ~defs ~kind name
creates a unique qualified name for name
(as checked against def
's domain) in the current scope. This raises if there is no scope, if the scopes are sealed or if name
is already defined in the current scope or if name
is invalid.
val open_lib : module':string -> name -> unit
open_lib ~module':__MODULE__ l
opens a scope for library l
. Must be called before making any static definition in a library. Library scopes don't nest, no other scope can be opened before a close
. module'
is used to help users to identify the module to lookup for documentation. This is typically used at the top of your module and the end of your module has a close
.
let () = B0_scope.open_lib ~module':__MODULE__ "mydeflib"
…
let () = B0_scope.close ()
Note. This is used by the implementation of the driver API, if you are fiddling with this you are likely doing something wrong.
val name_list : unit -> (qualified_name * B0_std.Fpath.t) list
name_list ()
is the list of file scopes names tupled with the file that defines it. This function can only be called once definitions are seal
ed otherwise it raises Invalid_argument
.
val open_root : B0_std.Fpath.t -> unit
open_root file
initializes b0 file scoping and opens a root scope for the root b0 file at the absolute file path file
.
Only file scope can be opened from now on.
This installs a Printexc.set_uncaught_exception_handler
to handle uncaught and definition errors. If that happens the error is logged and the program Stdlib.exit
s with B0_driver.Exit.b0_file_error
.
val open_file : name -> B0_std.Fpath.t -> unit
open' name
opens a scope named name
(unqualified) to add the definitions of the absolute file path file
.
Warning. Scope unicity is not checked by the module this is expected to be handled by the client.
raise_error fmt …
can be used if an unrecoverable b0 file user error occurs in a scope (e.g. duplicate definition). The given error message is printed and the program exits with B0_driver.Exit.b0_file_error
.
raise_no_scope_error ~kind ~name
raises an error if an entity named name
of kind kind
is created without an open scope.
Note. This is borderline Invalid_argument
though.
raise_invalid_name_error ~kind ~name
raises an error for an invalid name name
(as per is_name_valid
) for an entity of kind kind
.
raise_duplicate_error ~kind ~name
raises an error for a dupliciate name name
for an entity of kind kind
.
Scope sealing allows to make sure no definitions are unscoped or happen dynamically.
Exception that can be used if definitions are made after seal
was invoked. The argument is an error message to print. The backtrace should point to the location of the illegal definition. See raise_after_seal
seal ()
prevents further scope definitions from being made. This function is called at the end of the root b0 file. Since it comes last during linking the library scopes have already been established.
raise_after_seal fmt …
can be used to bail out with an After_seal
exceptions if something happens after seal that should not have in a scope the given error message is printed and the program exits with B0_driver.Exit.b0_file_error
.
raise_create_after_seal ~kind ~name
raises an After_seal
error if a entity named name
of kind kind
was created after scope sealing.