Skip to main content

nickel_lang_core/
stdlib.rs

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