nickel_lang_core/
stdlib.rs

1//! Load the Nickel standard library in strings at compile-time.
2use crate::term::make as mk_term;
3use crate::term::RichTerm;
4
5/// This is an array containing all the Nickel standard library modules. Currently, this is one
6/// monolithic `std` module, and the definitions of `internals` living at the toplevel.
7///
8/// Using a dedicated enum tpe, handling arrays, etc. for two modules can seem a bit overkill, but
9/// we'll probably extend `StdlibModule` when we'll split the `std` module into several files.
10pub fn modules() -> [StdlibModule; 2] {
11    [StdlibModule::Std, StdlibModule::Internals]
12}
13
14/// Represents a particular Nickel standard library module.
15#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
16pub enum StdlibModule {
17    Std,
18    Internals,
19}
20
21impl StdlibModule {
22    pub fn file_name(&self) -> &'static str {
23        match self {
24            StdlibModule::Std => "<stdlib/std.ncl>",
25            StdlibModule::Internals => "<stdlib/internals.ncl>",
26        }
27    }
28
29    /// The name of the module. Used to determine its namespace in the initial environment (the
30    /// module named `std` will be put under the `std` identifier). `StdlibModule::Internals` is an
31    /// exception, because although it has a name, it's not put under any namespace but directly at
32    /// top-level in the environment.
33    pub fn name(&self) -> &'static str {
34        match self {
35            StdlibModule::Std => "std",
36            StdlibModule::Internals => "internals",
37        }
38    }
39
40    pub fn content(&self) -> &'static str {
41        match self {
42            StdlibModule::Std => include_str!("../stdlib/std.ncl"),
43            StdlibModule::Internals => include_str!("../stdlib/internals.ncl"),
44        }
45    }
46}
47
48pub struct UnknownStdlibModule;
49
50macro_rules! generate_accessor {
51    ($value:ident) => {
52        pub fn $value() -> RichTerm {
53            mk_term::var(format!("${}", stringify!($value)))
54        }
55    };
56}
57
58/// Accessors to the builtin contracts and other internals that aren't accessible from user code.
59pub mod internals {
60    use super::*;
61
62    // `dyn` is a reserved keyword in rust
63    pub fn dynamic() -> RichTerm {
64        mk_term::var("$dyn")
65    }
66
67    // `enum` is a reserved keyword in rust
68    pub fn enumeration() -> RichTerm {
69        mk_term::var("$enum")
70    }
71
72    generate_accessor!(num);
73    generate_accessor!(bool);
74    generate_accessor!(foreign_id);
75    generate_accessor!(string);
76
77    generate_accessor!(array);
78    generate_accessor!(array_dyn);
79
80    generate_accessor!(func);
81    generate_accessor!(func_dom);
82    generate_accessor!(func_codom);
83    generate_accessor!(func_dyn);
84
85    generate_accessor!(forall_var);
86    generate_accessor!(forall);
87
88    generate_accessor!(enum_fail);
89    generate_accessor!(enum_variant);
90    generate_accessor!(forall_enum_tail);
91
92    generate_accessor!(record_contract);
93    generate_accessor!(record_type);
94    generate_accessor!(forall_record_tail);
95    generate_accessor!(forall_record_tail_excluded_only);
96    generate_accessor!(dyn_tail);
97    generate_accessor!(empty_tail);
98
99    generate_accessor!(dict_type);
100    generate_accessor!(dict_contract);
101    generate_accessor!(dict_dyn);
102
103    generate_accessor!(stdlib_contract_equal);
104
105    generate_accessor!(naked_to_custom);
106    generate_accessor!(add_default_check_label);
107
108    generate_accessor!(rec_default);
109    generate_accessor!(rec_force);
110}