// The parser's configuration: the dialect and the fuel budget, later the
// formatter and traversal settings. Values are immutable; a `Partial` is a
// layer with set and unset fields, merged HOCON style with
// `with_fallback`. `Config::load` is the only function here that touches
// the file system or the environment.
///|
/// The parser's configuration.
///
/// ```mbt check
/// test {
/// let c = @config.Config::default()
/// inspect(c.fuel.units(), content="100")
/// inspect(c.dialect.name, content="gleam-1.19")
/// }
/// ```
pub(all) struct Config {
dialect : @dialect.Dialect
fuel : @fuel.Budget
} derive(Eq, Debug)
///|
/// A layer of configuration: each field set or unset.
pub(all) struct Partial {
dialect : @dialect.Dialect?
fuel : @fuel.Budget?
} derive(Eq, Debug)
///|
/// Where a configuration value came from; an error names it.
pub(all) enum Source {
/// Reserved: the built-in defaults (no error comes from them).
Default
/// A key path in the TOML file (`parser.fuel`).
TomlKey(String)
/// The TOML text as a whole (a syntax error).
TomlSyntax
/// An environment variable (`GLEAM_PARSER_FUEL`).
EnvVar(String)
/// A file path that could not be read.
File(String)
/// Reserved: a value the caller passed (no error comes from it).
Caller
} derive(Eq, Debug)
///|
/// A configuration value that cannot be used. Nothing falls back silently.
pub(all) suberror ConfigError {
ConfigError(source~ : Source, message~ : String)
} derive(Eq, Debug)
///|
/// `Dialect::gleam_1_19()` and `@fuel.default_budget`.
pub fn Config::default() -> Config {
{ dialect: @dialect.Dialect::gleam_1_19(), fuel: @fuel.default_budget, }
}
///|
/// Every field set.
pub fn Config::to_partial(self : Config) -> Partial {
{ dialect: Some(self.dialect), fuel: Some(self.fuel), }
}
///|
/// `over`'s set fields replace this config's fields.
pub fn Config::with_fallback(self : Config, over : Partial) -> Config {
over.to_config(self)
}
///|
/// No field set.
pub fn Partial::empty() -> Partial {
{ dialect: None, fuel: None, }
}
///|
/// This layer's set fields win; unset fields come from `fallback`.
///
/// ```mbt check
/// test {
/// let file : @config.Partial = { dialect: None, fuel: @fuel.Budget::new(500), }
/// let env : @config.Partial = { dialect: None, fuel: @fuel.Budget::new(2000), }
/// let c = env.with_fallback(file).to_config(@config.Config::default())
/// inspect(c.fuel.units(), content="2000")
/// }
/// ```
pub fn Partial::with_fallback(self : Partial, fallback : Partial) -> Partial {
{
dialect: match self.dialect {
Some(d) => Some(d)
None => fallback.dialect
},
fuel: match self.fuel {
Some(b) => Some(b)
None => fallback.fuel
},
}
}
///|
/// A full config: unset fields come from `fallback`.
pub fn Partial::to_config(self : Partial, fallback : Config) -> Config {
{
dialect: self.dialect.unwrap_or(fallback.dialect),
fuel: self.fuel.unwrap_or(fallback.fuel),
}
}