spl/
dyn_fns.rs

1use std::sync::Arc;
2
3use crate::sasm::sasm_read;
4use crate::*;
5use crate::{lexer, runtime::*};
6
7pub fn dyn_dump(stack: &mut Stack) -> OError {
8    Words {
9        words: vec![Word::Key(Keyword::Dump)],
10    }
11    .exec(stack)
12}
13
14pub fn dyn_def(stack: &mut Stack) -> OError {
15    let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
16        return stack.err(ErrorKind::InvalidCall("dyn-def".to_owned()));
17    };
18    Words {
19        words: vec![Word::Key(Keyword::Def(s))],
20    }
21    .exec(stack)?;
22    Ok(())
23}
24
25pub fn dyn_func(stack: &mut Stack) -> OError {
26    let (Value::Str(s), Value::Func(f)) = (
27        stack.pop().lock_ro().native.clone(),
28        stack.pop().lock_ro().native.clone(),
29    ) else {
30        return stack.err(ErrorKind::InvalidCall("dyn-func".to_owned()));
31    };
32    stack.define_func(s, f);
33    Ok(())
34}
35
36pub fn dyn_construct(stack: &mut Stack) -> OError {
37    let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
38        return stack.err(ErrorKind::InvalidCall("dyn-construct".to_owned()));
39    };
40    Words {
41        words: vec![Word::Key(Keyword::Construct(
42            s,
43            Vec::new(),
44            Vec::new(),
45            ConstructKind::Thing,
46        ))],
47    }
48    .exec(stack)?;
49    Ok(())
50}
51
52pub fn dyn_namespace(stack: &mut Stack) -> OError {
53    let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
54        return stack.err(ErrorKind::InvalidCall("dyn-construct".to_owned()));
55    };
56    Words {
57        words: vec![Word::Key(Keyword::Construct(
58            s,
59            Vec::new(),
60            Vec::new(),
61            ConstructKind::Namespace,
62        ))],
63    }
64    .exec(stack)?;
65    Ok(())
66}
67
68pub fn dyn_def_field(stack: &mut Stack) -> OError {
69    let (Value::Str(s), Value::Str(name)) = (
70        stack.pop().lock_ro().native.clone(),
71        stack.pop().lock_ro().native.clone(),
72    ) else {
73        return stack.err(ErrorKind::InvalidCall("dyn-def-field".to_owned()));
74    };
75    runtime(|rt| rt.get_type_by_name(&s))
76        .ok_or_else(|| stack.error(ErrorKind::TypeNotFound(s)))?
77        .lock()
78        .add_property(name, stack.get_frame())?;
79    Ok(())
80}
81
82pub fn dyn_def_method(stack: &mut Stack) -> OError {
83    let (Value::Str(s), Value::Str(name), Value::Func(f)) = (
84        stack.pop().lock_ro().native.clone(),
85        stack.pop().lock_ro().native.clone(),
86        stack.pop().lock_ro().native.clone(),
87    ) else {
88        return stack.err(ErrorKind::InvalidCall("dyn-def-method".to_owned()));
89    };
90    runtime(|rt| rt.get_type_by_name(&s))
91        .ok_or_else(|| stack.error(ErrorKind::TypeNotFound(s)))?
92        .lock()
93        .functions
94        .insert(name, f);
95    Ok(())
96}
97
98pub fn dyn_include(stack: &mut Stack) -> OError {
99    let (Value::Str(b), Value::Str(a)) = (
100        stack.pop().lock_ro().native.clone(),
101        stack.pop().lock_ro().native.clone(),
102    ) else {
103        return stack.err(ErrorKind::InvalidCall("dyn-include".to_owned()));
104    };
105    Words {
106        words: vec![Word::Key(Keyword::Include(a, b))],
107    }
108    .exec(stack)?;
109    Ok(())
110}
111
112pub fn dyn_while(stack: &mut Stack) -> OError {
113    let (Value::Func(blk), Value::Func(cond)) = (
114        stack.pop().lock_ro().native.clone(),
115        stack.pop().lock_ro().native.clone(),
116    ) else {
117        return stack.err(ErrorKind::InvalidCall("dyn-while".to_owned()));
118    };
119    loop {
120        cond.to_call.call(stack)?;
121        if !stack.pop().lock_ro().is_truthy() {
122            break;
123        }
124        blk.to_call.call(stack)?;
125    }
126    Ok(())
127}
128
129pub fn dyn_if(stack: &mut Stack) -> OError {
130    let Value::Func(blk) = stack.pop().lock_ro().native.clone() else {
131        return stack.err(ErrorKind::InvalidCall("dyn-if".to_owned()));
132    };
133    if stack.pop().lock_ro().is_truthy() {
134        blk.to_call.call(stack)?;
135    }
136    Ok(())
137}
138
139pub fn dyn_call(stack: &mut Stack) -> OError {
140    let Value::Str(mut s) = stack.pop().lock_ro().native.clone() else {
141        return stack.err(ErrorKind::InvalidCall("dyn-call".to_owned()));
142    };
143    let mut words = Vec::new();
144    let mut ra = 0;
145    while s.starts_with('&') {
146        ra += 1;
147        s = s[1..].to_owned();
148    }
149    if s.ends_with(';') {
150        words.push(Word::Call(s[..s.len() - 1].to_owned(), true, ra));
151    } else {
152        words.push(Word::Call(s, false, ra));
153    }
154    Words { words }.exec(stack)?;
155    Ok(())
156}
157
158pub fn dyn_objcall(stack: &mut Stack) -> OError {
159    let Value::Str(mut s) = stack.pop().lock_ro().native.clone() else {
160        return stack.err(ErrorKind::InvalidCall("dyn-objcall".to_owned()));
161    };
162    let mut words = Vec::new();
163    let mut ra = 0;
164    while s.starts_with('&') {
165        ra += 1;
166        s = s[1..].to_owned();
167    }
168    if s.ends_with(';') {
169        words.push(Word::ObjCall(s[..s.len() - 1].to_owned(), true, ra));
170    } else {
171        words.push(Word::ObjCall(s, false, ra));
172    }
173    Words { words }.exec(stack)?;
174    Ok(())
175}
176
177pub fn dyn_all_types(stack: &mut Stack) -> OError {
178    stack.push(
179        Value::Array(
180            runtime(|rt| rt.get_types())
181                .into_iter()
182                .map(|x| Value::Str(x.lock_ro().get_name()).spl())
183                .collect(),
184        )
185        .spl(),
186    );
187    Ok(())
188}
189
190pub fn dyn_read(stack: &mut Stack) -> OError {
191    let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
192        return stack.err(ErrorKind::InvalidCall("dyn-read".to_owned()));
193    };
194    stack.push(
195        Value::Func(AFunc::new(Func {
196            ret_count: 0,
197            to_call: FuncImpl::SPL(
198                lexer::lex(false, s)
199                    .map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
200            ),
201            run_as_base: false,
202            origin: stack.get_frame(),
203            fname: None,
204            name: "(dyn-read)".to_owned(),
205        }))
206        .spl(),
207    );
208    Ok(())
209}
210
211pub fn dyn_readf(stack: &mut Stack) -> OError {
212    let (Value::Str(s), Value::Str(n)) = (
213        stack.pop().lock_ro().native.clone(),
214        stack.pop().lock_ro().native.clone(),
215    ) else {
216        return stack.err(ErrorKind::InvalidCall("dyn-readf".to_owned()));
217    };
218    stack.push(
219        Value::Func(AFunc::new(Func {
220            ret_count: 0,
221            to_call: FuncImpl::SPL(
222                lexer::lex(n.ends_with(".isbpl"), s)
223                    .map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
224            ),
225            run_as_base: true,
226            origin: stack.get_frame(),
227            fname: Some(n),
228            name: "root".to_owned(),
229        }))
230        .spl(),
231    );
232    Ok(())
233}
234
235pub fn dyn_sasm(stack: &mut Stack) -> OError {
236    require_on_stack!(sasm, Str, stack, "dyn-sasm");
237    stack.push(
238        Value::Func(AFunc::new(Func {
239            ret_count: 0,
240            to_call: FuncImpl::SPL(sasm_read(sasm)),
241            origin: stack.get_frame(),
242            fname: None,
243            name: "(dyn-read)".to_owned(),
244            run_as_base: false,
245        }))
246        .spl(),
247    );
248    Ok(())
249}
250
251pub fn dyn_sasmf(stack: &mut Stack) -> OError {
252    require_on_stack!(sasm, Str, stack, "dyn-sasmf");
253    require_on_stack!(n, Str, stack, "dyn-sasmf");
254    stack.push(
255        Value::Func(AFunc::new(Func {
256            ret_count: 0,
257            to_call: FuncImpl::SPL(sasm_read(sasm)),
258            origin: stack.get_frame(),
259            fname: Some(n),
260            name: "root".to_owned(),
261            run_as_base: true,
262        }))
263        .spl(),
264    );
265    Ok(())
266}
267
268pub fn dyn_catch(stack: &mut Stack) -> OError {
269    require_on_stack!(ctch, Func, stack, "dyn-catch");
270    require_on_stack!(blk, Func, stack, "dyn-catch");
271    require_on_stack!(types, Array, stack, "dyn-catch");
272    if let Err(e) = blk.to_call.call(stack) {
273        if types.is_empty() || types.contains(&e.kind.to_string().spl()) {
274            stack.push(e.spl());
275            ctch.to_call.call(stack)
276        } else {
277            Err(e)
278        }
279    } else {
280        Ok(())
281    }
282}
283
284pub fn dyn_use(stack: &mut Stack) -> OError {
285    require_on_stack!(item, Str, stack, "dyn-use");
286    Words::new(vec![Word::Key(Keyword::Use(item))]).exec(stack)
287}
288
289pub(crate) fn wrap(f: fn(&mut Stack) -> OError) -> impl Fn(&mut Stack) -> OError {
290    move |stack| unsafe {
291        let frame = stack.pop_frame(0);
292        let r = f(stack);
293        stack.push_frame(frame);
294        r
295    }
296}
297
298pub fn register(r: &mut Stack, o: Arc<Frame>) {
299    type Fn = fn(&mut Stack) -> OError;
300    let fns: [(&str, Fn, u32); 19] = [
301        ("dyn-__dump", dyn_dump, 0),
302        ("dyn-def", dyn_def, 0),
303        ("dyn-func", dyn_func, 0),
304        ("dyn-construct", dyn_construct, 0),
305        ("dyn-namespace", dyn_namespace, 0),
306        ("dyn-def-field", dyn_def_field, 0),
307        ("dyn-def-method", dyn_def_method, 0),
308        ("dyn-include", dyn_include, 0),
309        ("dyn-while", dyn_while, 0),
310        ("dyn-if", dyn_if, 0),
311        ("dyn-call", dyn_call, 0),
312        ("dyn-objcall", dyn_objcall, 0),
313        ("dyn-all-types", dyn_all_types, 1),
314        ("dyn-read", dyn_read, 1),
315        ("dyn-readf", dyn_readf, 1),
316        ("dyn-sasm", dyn_sasm, 1),
317        ("dyn-sasmf", dyn_sasmf, 1),
318        ("dyn-catch", dyn_catch, 0),
319        ("dyn-use", dyn_use, 0),
320    ];
321    for f in fns {
322        r.define_func(
323            f.0.to_owned(),
324            AFunc::new(Func {
325                ret_count: f.2,
326                to_call: FuncImpl::NativeDyn(Arc::new(Box::new(wrap(f.1)))),
327                run_as_base: false,
328                origin: o.clone(),
329                fname: None,
330                name: f.0.to_owned(),
331            }),
332        );
333    }
334}