1
//! Built-in registrations: operators, special forms, native fns,
2
//! entity-type/context constants, typed-entity accessors, and the
3
//! MAP-family macros (MAPCAR / MAPC).
4

            
5
use crate::ast::{Expr, Fraction, LambdaParams};
6

            
7
use super::entry::{Symbol, SymbolKind};
8
use super::table::SymbolTable;
9

            
10
impl SymbolTable {
11
79072
    pub fn register_builtins(&mut self) {
12
        // Name lists tangle from doc/scripting/builtin_reference.org
13
        // into builtins_generated.rs — the org registry tables are
14
        // the single source of truth. Adding a builtin = one org row.
15
869792
        for op in super::builtins_generated::OPERATORS {
16
869792
            self.define(Symbol::new(*op, SymbolKind::Operator));
17
869792
        }
18
3479168
        for form in super::builtins_generated::SPECIAL_FORMS {
19
3479168
            self.define(Symbol::new(*form, SymbolKind::SpecialForm));
20
3479168
        }
21
2530304
        for native in super::builtins_generated::NATIVES {
22
2530304
            self.define(Symbol::new(*native, SymbolKind::Native));
23
2530304
        }
24

            
25
79072
        self.register_entity_constants();
26
79072
        self.register_entity_accessors();
27

            
28
79072
        self.add_map_family_macros();
29
79072
    }
30

            
31
79072
    fn register_entity_constants(&mut self) {
32
        use scripting_format::{ContextType, EntityType};
33

            
34
79072
        let entity_types: &[(&str, EntityType)] = &[
35
79072
            ("+ENTITY-TRANSACTION+", EntityType::Transaction),
36
79072
            ("+ENTITY-SPLIT+", EntityType::Split),
37
79072
            ("+ENTITY-TAG+", EntityType::Tag),
38
79072
            ("+ENTITY-ACCOUNT+", EntityType::Account),
39
79072
            ("+ENTITY-COMMODITY+", EntityType::Commodity),
40
79072
        ];
41
395360
        for (name, ty) in entity_types {
42
395360
            self.define(
43
395360
                Symbol::new(*name, SymbolKind::Variable)
44
395360
                    .with_value(Expr::Number(Fraction::from_integer(i64::from(*ty as u8)))),
45
395360
            );
46
395360
        }
47

            
48
79072
        let context_types: &[(&str, ContextType)] = &[
49
79072
            ("+CONTEXT-CREATE+", ContextType::EntityCreate),
50
79072
            ("+CONTEXT-UPDATE+", ContextType::EntityUpdate),
51
79072
            ("+CONTEXT-DELETE+", ContextType::EntityDelete),
52
79072
            ("+CONTEXT-BATCH+", ContextType::BatchProcess),
53
79072
        ];
54
316288
        for (name, ct) in context_types {
55
316288
            self.define(
56
316288
                Symbol::new(*name, SymbolKind::Variable)
57
316288
                    .with_value(Expr::Number(Fraction::from_integer(i64::from(*ct as u8)))),
58
316288
            );
59
316288
        }
60
79072
    }
61

            
62
158144
    pub(super) fn register_entity_accessors(&mut self) {
63
158144
        let accessors = [
64
158144
            "ENTITY-COUNT",
65
158144
            "CONTEXT-TYPE",
66
158144
            "PRIMARY-ENTITY-TYPE",
67
158144
            "PRIMARY-ENTITY-IDX",
68
158144
            "ENTITY-TYPE",
69
158144
            "ENTITY-PARENT-IDX",
70
158144
            "TRANSACTION-SPLIT-COUNT",
71
158144
            "TRANSACTION-TAG-COUNT",
72
158144
            "TRANSACTION-IS-MULTI-CURRENCY",
73
158144
            "TRANSACTION-POST-DATE",
74
158144
            "TRANSACTION-ENTER-DATE",
75
158144
            "SPLIT-VALUE-NUM",
76
158144
            "SPLIT-VALUE-DENOM",
77
158144
            "SPLIT-VALUE",
78
158144
            "SPLIT-RECONCILE-STATE",
79
158144
            "SPLIT-RECONCILE-DATE",
80
158144
            "SPLIT-ACCOUNT-NAME",
81
158144
            "CREATE-TAG",
82
158144
            "TAG-NAME",
83
158144
            "TAG-VALUE",
84
158144
            "STRING=",
85
158144
            "DELETE-ENTITY",
86
158144
            // Typed-entity accessors (mirror `compiler::native::typed_entity`).
87
158144
            "ACCOUNT-ID",
88
158144
            "ACCOUNT-NAME",
89
158144
            "ACCOUNT-PARENT",
90
158144
            "COMMODITY-ID",
91
158144
            "COMMODITY-SYMBOL",
92
158144
            "COMMODITY-NAME",
93
158144
            "TRANSACTION-ID",
94
158144
            "TRANSACTION-NOTE",
95
158144
            "SPLIT-ID",
96
158144
            "SPLIT-ACCOUNT-ID",
97
158144
            "SPLIT-COMMODITY-ID",
98
158144
            "SPLIT-AMOUNT",
99
158144
            "TAG-ENTITY-ID",
100
158144
            "TAG-ENTITY-NAME",
101
158144
            "TAG-ENTITY-VALUE",
102
158144
            "PRICE-ID",
103
158144
            "PRICE-COMMODITY-ID",
104
158144
            "PRICE-CURRENCY-ID",
105
158144
            "PRICE-VALUE",
106
158144
            "PRICE-DATE",
107
158144
            "SSH-KEY-ID",
108
158144
            "SSH-KEY-FINGERPRINT",
109
158144
            "SSH-KEY-NAME",
110
158144
            "NODE-ID",
111
158144
            "NODE-LABEL",
112
158144
            "NODE-DEPTH",
113
158144
            "NODE-AMOUNT",
114
158144
            "NODE-CHILDREN",
115
158144
        ];
116
7907200
        for name in accessors {
117
7907200
            self.define(Symbol::new(name, SymbolKind::Native));
118
7907200
        }
119
158144
    }
120

            
121
79072
    fn add_map_family_macros(&mut self) {
122
79072
        let mapcar_params = LambdaParams {
123
79072
            required: vec!["func".to_string(), "list".to_string()],
124
79072
            optional: Vec::new(),
125
79072
            rest: Some("lists".to_string()),
126
79072
            key: Vec::new(),
127
79072
            aux: Vec::new(),
128
79072
        };
129
79072
        let mapcar_body = Expr::List(vec![
130
79072
            Expr::Symbol("APPLY".to_string()),
131
79072
            Expr::Quote(Box::new(Expr::Symbol("LIST".to_string()))),
132
79072
            Expr::Quote(Box::new(Expr::Symbol("MAP".to_string()))),
133
79072
            Expr::Symbol("func".to_string()),
134
79072
            Expr::Symbol("list".to_string()),
135
79072
            Expr::Symbol("lists".to_string()),
136
79072
        ]);
137
79072
        let mapcar_lambda = Expr::Lambda(mapcar_params, Box::new(mapcar_body));
138
79072
        self.define(Symbol::new("MAPCAR", SymbolKind::Macro).with_function(mapcar_lambda));
139

            
140
79072
        let mapc_params = LambdaParams::simple(vec!["func".to_string(), "list".to_string()]);
141
79072
        let mapc_body = Expr::List(vec![
142
79072
            Expr::Symbol("LIST".to_string()),
143
79072
            Expr::Quote(Box::new(Expr::Symbol("MAP".to_string()))),
144
79072
            Expr::Symbol("func".to_string()),
145
79072
            Expr::Symbol("list".to_string()),
146
79072
        ]);
147
79072
        let mapc_lambda = Expr::Lambda(mapc_params, Box::new(mapc_body));
148
79072
        self.define(Symbol::new("MAPC", SymbolKind::Macro).with_function(mapc_lambda));
149
79072
    }
150
}