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}