spl/
std_fns.rs

1use std::{
2    collections::{HashMap, VecDeque},
3    env::{self, args, vars},
4    fs,
5    io::{stdin, stdout, Write},
6    ops::{Add, Div, Mul, Rem, Sub},
7    process::{self, Stdio},
8    sync::Arc,
9    thread,
10    time::{Duration, SystemTime},
11};
12
13use readformat::readf;
14
15use crate::{dyn_fns, mutex::Mut, runtime::*, sasm::sasm_write, *};
16
17#[macro_export]
18macro_rules! type_err {
19    ($stack:expr, $a:expr, $b:expr) => {
20        $stack.err(ErrorKind::InvalidType($a.to_owned(), $b.to_owned()))?
21    };
22}
23
24macro_rules! array {
25    ($stack:expr, $i:expr) => {
26        || {
27            $stack.error(ErrorKind::PropertyNotFound(
28                "array".to_owned(),
29                $i.to_string(),
30            ))
31        }
32    };
33}
34
35pub fn print(stack: &mut Stack) -> OError {
36    let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
37        return stack.err(ErrorKind::InvalidCall("print".to_owned()));
38    };
39    print!("{s}");
40    stdout().lock().flush().unwrap();
41    Ok(())
42}
43
44pub fn clone(stack: &mut Stack) -> OError {
45    let o = stack.pop();
46    stack.push(Arc::new(Mut::new(o.lock_ro().clone())));
47    Ok(())
48}
49
50pub fn dup(stack: &mut Stack) -> OError {
51    let o = stack.peek();
52    stack.push(o);
53    Ok(())
54}
55
56pub fn dup2(stack: &mut Stack) -> OError {
57    let o = stack.peek();
58    stack.push(o.clone());
59    stack.push(o);
60    Ok(())
61}
62
63pub fn pop(stack: &mut Stack) -> OError {
64    stack.pop();
65    Ok(())
66}
67
68pub fn swap(stack: &mut Stack) -> OError {
69    let a = stack.pop();
70    let b = stack.pop();
71    stack.push(a);
72    stack.push(b);
73    Ok(())
74}
75
76pub fn mswap(stack: &mut Stack) -> OError {
77    let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
78        return stack.err(ErrorKind::InvalidCall("nswap".to_owned()));
79    };
80    let mut array = VecDeque::with_capacity(i as usize);
81    for _ in 0..i {
82        array.push_back(stack.pop());
83    }
84    for _ in 0..i {
85        // SAFETY: Items must exist because they are added in the previous loop
86        stack.push(array.pop_front().unwrap());
87    }
88    Ok(())
89}
90
91pub fn settype(stack: &mut Stack) -> OError {
92    let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
93        return stack.err(ErrorKind::InvalidCall("settype".to_owned()));
94    };
95    let o = stack.pop();
96    let kind = runtime(|rt| rt.get_type_by_name(&s))
97        .ok_or_else(|| stack.error(ErrorKind::TypeNotFound(s)))?;
98    set_type_internal(&o, kind);
99    stack.push(o);
100    Ok(())
101}
102
103pub fn settypeid(stack: &mut Stack) -> OError {
104    let Value::Int(i) = stack.pop().lock_ro().native.clone() else {
105        return stack.err(ErrorKind::InvalidCall("settype".to_owned()));
106    };
107    let o = stack.pop();
108    let kind = runtime(|rt| rt.get_type_by_id(i as u32))
109        .ok_or_else(|| stack.error(ErrorKind::TypeNotFound(format!(";{i}"))))?;
110    set_type_internal(&o, kind);
111    stack.push(o);
112    Ok(())
113}
114
115fn set_type_internal(o: &Arc<Mut<Object>>, kind: Arc<Mut<Type>>) {
116    let mut obj = o.lock();
117    kind.lock_ro().write_into(&mut obj);
118    obj.kind = kind;
119}
120
121pub fn gettype(stack: &mut Stack) -> OError {
122    let o = stack.pop();
123    stack.push(Value::Str(o.lock_ro().kind.lock_ro().get_name()).spl());
124    Ok(())
125}
126
127pub fn gettypeid(stack: &mut Stack) -> OError {
128    let o = stack.pop();
129    stack.push(Value::Int(o.lock_ro().kind.lock_ro().get_id() as i32).spl());
130    Ok(())
131}
132
133pub fn barray_new(stack: &mut Stack) -> OError {
134    let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
135        return stack.err(ErrorKind::InvalidCall("banew".to_owned()));
136    };
137    if i < 0 {
138        return stack.err(ErrorKind::InvalidCall("banew".to_owned()));
139    }
140    stack.push(Value::ByteArray(vec![0u8; i as usize]).spl());
141    Ok(())
142}
143
144pub fn array_new(stack: &mut Stack) -> OError {
145    let Value::Mega(i) = stack.pop().lock_ro().native.clone() else {
146        return stack.err(ErrorKind::InvalidCall("anew".to_owned()));
147    };
148    if i < 0 {
149        return stack.err(ErrorKind::InvalidCall("anew".to_owned()));
150    }
151    stack.push(Value::Array(vec![Value::Null.spl(); i as usize]).spl());
152    Ok(())
153}
154
155pub fn array_len(stack: &mut Stack) -> OError {
156    let binding = stack.pop();
157    let len = match binding.lock_ro().native {
158        Value::Array(ref a) => a.len(),
159        Value::ByteArray(ref a) => a.len(),
160        _ => return stack.err(ErrorKind::InvalidCall("array-len".to_owned())),
161    };
162    stack.push(Value::Mega(len as i128).spl());
163    Ok(())
164}
165
166pub fn array_get(stack: &mut Stack) -> OError {
167    let binding = stack.pop();
168    let Value::Mega(i) = stack.pop().lock_ro().native else {
169        return stack.err(ErrorKind::InvalidCall("array-get".to_owned()));
170    };
171    let o = match binding.lock_ro().native {
172        Value::Array(ref a) => a.get(i as usize).cloned(),
173        Value::ByteArray(ref a) => a.get(i as usize).map(|x| Value::Int(*x as i32).spl()),
174        _ => return stack.err(ErrorKind::InvalidCall("array-get".to_owned())),
175    };
176    stack.push(o.ok_or_else(array!(stack, i))?);
177    Ok(())
178}
179
180pub fn array_set(stack: &mut Stack) -> OError {
181    let binding = &stack.pop();
182    let binding = &mut binding.lock().native;
183    require_on_stack!(i, Mega, stack, "array-set");
184    let o = stack.pop();
185    if let Value::Array(ref mut a) = binding {
186        stack.push(a.get(i as usize).ok_or_else(array!(stack, i))?.clone());
187        *a.get_mut(i as usize).ok_or_else(array!(stack, i))? = o;
188    } else if let Value::ByteArray(ref mut a) = binding {
189        let Value::Int(o) = o.lock_ro().native else {
190            return stack.err(ErrorKind::InvalidCall("array-set".to_owned()));
191        };
192        stack.push(Value::Int(*a.get(i as usize).ok_or_else(array!(stack, i))? as i32).spl());
193        *a.get_mut(i as usize).ok_or_else(array!(stack, i))? = o as u8;
194    } else {
195        return stack.err(ErrorKind::InvalidCall("array-set".to_owned()));
196    };
197    Ok(())
198}
199
200pub fn eq(stack: &mut Stack) -> OError {
201    let b = stack.pop();
202    let a = stack.pop();
203    stack.push(Value::Int(if a == b { 1 } else { 0 }).spl());
204    Ok(())
205}
206
207pub fn lt(stack: &mut Stack) -> OError {
208    let b = stack.pop();
209    let a = stack.pop();
210    stack.push(Value::Int(if a < b { 1 } else { 0 }).spl());
211    Ok(())
212}
213
214pub fn gt(stack: &mut Stack) -> OError {
215    let b = stack.pop();
216    let a = stack.pop();
217    stack.push(Value::Int(if a > b { 1 } else { 0 }).spl());
218    Ok(())
219}
220
221pub fn not(stack: &mut Stack) -> OError {
222    let o = stack.pop();
223    stack.push(Value::Int(if o.lock_ro().is_truthy() { 0 } else { 1 }).spl());
224    Ok(())
225}
226
227pub fn and(stack: &mut Stack) -> OError {
228    let a = stack.pop();
229    let b = stack.pop();
230    stack.push(
231        Value::Int(if a.lock_ro().is_truthy() && b.lock_ro().is_truthy() {
232            1
233        } else {
234            0
235        })
236        .spl(),
237    );
238    Ok(())
239}
240
241pub fn or(stack: &mut Stack) -> OError {
242    let b = stack.pop();
243    let a = stack.pop();
244    stack.push(if a.lock_ro().is_truthy() { a } else { b });
245    Ok(())
246}
247
248macro_rules! impl_op {
249    ($a:expr, $b:expr, $op:tt, $err:expr, $($kind:tt,)*) => {
250        match ($a, $b) {
251            $(
252                (Value::$kind(a), Value::$kind(b)) => Value::$kind(a.$op(b)),
253            )*
254            _ => $err?,
255        }
256    };
257}
258
259pub fn plus(stack: &mut Stack) -> OError {
260    let b = stack.pop().lock_ro().native.clone();
261    let a = stack.pop().lock_ro().native.clone();
262    stack.push(
263        impl_op!(
264            a,
265            b,
266            add,
267            stack.err(ErrorKind::InvalidCall("plus".to_owned())),
268            Mega,
269            Long,
270            Int,
271            Float,
272            Double,
273        )
274        .spl(),
275    );
276    Ok(())
277}
278
279pub fn minus(stack: &mut Stack) -> OError {
280    let b = stack.pop().lock_ro().native.clone();
281    let a = stack.pop().lock_ro().native.clone();
282    stack.push(
283        impl_op!(
284            a,
285            b,
286            sub,
287            stack.err(ErrorKind::InvalidCall("minus".to_owned())),
288            Mega,
289            Long,
290            Int,
291            Float,
292            Double,
293        )
294        .spl(),
295    );
296    Ok(())
297}
298
299pub fn slash(stack: &mut Stack) -> OError {
300    let b = stack.pop().lock_ro().native.clone();
301    let a = stack.pop().lock_ro().native.clone();
302    stack.push(
303        impl_op!(
304            a,
305            b,
306            div,
307            stack.err(ErrorKind::InvalidCall("slash".to_owned())),
308            Mega,
309            Long,
310            Int,
311            Float,
312            Double,
313        )
314        .spl(),
315    );
316    Ok(())
317}
318
319pub fn star(stack: &mut Stack) -> OError {
320    let b = stack.pop().lock_ro().native.clone();
321    let a = stack.pop().lock_ro().native.clone();
322    stack.push(
323        impl_op!(
324            a,
325            b,
326            mul,
327            stack.err(ErrorKind::InvalidCall("star".to_owned())),
328            Mega,
329            Long,
330            Int,
331            Float,
332            Double,
333        )
334        .spl(),
335    );
336    Ok(())
337}
338
339pub fn pow(stack: &mut Stack) -> OError {
340    let b = stack.pop().lock_ro().native.clone();
341    let a = stack.pop().lock_ro().native.clone();
342    stack.push(
343        match (a, b) {
344            (Value::Mega(a), Value::Mega(b)) => Value::Mega(a.pow(b as u32)),
345            (Value::Long(a), Value::Long(b)) => Value::Long(a.pow(b as u32)),
346            (Value::Int(a), Value::Int(b)) => Value::Int(a.pow(b as u32)),
347            (Value::Float(a), Value::Float(b)) => Value::Float(a.powf(b)),
348            (Value::Double(a), Value::Double(b)) => Value::Double(a.powf(b)),
349            _ => (stack.err(ErrorKind::InvalidCall("pow".to_owned())))?,
350        }
351        .spl(),
352    );
353    Ok(())
354}
355
356pub fn percent(stack: &mut Stack) -> OError {
357    let b = stack.pop().lock_ro().native.clone();
358    let a = stack.pop().lock_ro().native.clone();
359    stack.push(
360        impl_op!(
361            a,
362            b,
363            rem,
364            stack.err(ErrorKind::InvalidCall("percent".to_owned())),
365            Mega,
366            Long,
367            Int,
368        )
369        .spl(),
370    );
371    Ok(())
372}
373
374pub fn to_int(stack: &mut Stack) -> OError {
375    let o = stack.pop().lock_ro().native.clone();
376    stack.push(
377        Value::Int(match o {
378            Value::Null => type_err!(stack, "null", "int"),
379            Value::Int(x) => x,
380            Value::Long(x) => x as i32,
381            Value::Mega(x) => x as i32,
382            Value::Float(x) => x as i32,
383            Value::Double(x) => x as i32,
384            Value::Func(_) => type_err!(stack, "func", "int"),
385            Value::Array(_) => type_err!(stack, "array", "int"),
386            Value::Str(x) => x
387                .parse()
388                .map_err(|_| stack.error(ErrorKind::Parse(x, "int".to_owned())))?,
389            Value::ByteArray(x) => x.len() as i32,
390        })
391        .spl(),
392    );
393    Ok(())
394}
395
396pub fn to_long(stack: &mut Stack) -> OError {
397    let o = stack.pop().lock_ro().native.clone();
398    stack.push(
399        Value::Long(match o {
400            Value::Null => type_err!(stack, "null", "long"),
401            Value::Int(x) => x as i64,
402            Value::Long(x) => x,
403            Value::Mega(x) => x as i64,
404            Value::Float(x) => x as i64,
405            Value::Double(x) => x as i64,
406            Value::Func(_) => type_err!(stack, "func", "long"),
407            Value::Array(_) => type_err!(stack, "array", "long"),
408            Value::Str(x) => x
409                .parse()
410                .map_err(|_| stack.error(ErrorKind::Parse(x, "long".to_owned())))?,
411            Value::ByteArray(x) => x.len() as i64,
412        })
413        .spl(),
414    );
415    Ok(())
416}
417
418pub fn to_mega(stack: &mut Stack) -> OError {
419    let o = stack.pop().lock_ro().native.clone();
420    stack.push(
421        Value::Mega(match o {
422            Value::Null => type_err!(stack, "null", "mega"),
423            Value::Int(x) => x as i128,
424            Value::Long(x) => x as i128,
425            Value::Mega(x) => x,
426            Value::Float(x) => x as i128,
427            Value::Double(x) => x as i128,
428            Value::Func(_) => type_err!(stack, "func", "mega"),
429            Value::Array(_) => type_err!(stack, "array", "mega"),
430            Value::Str(x) => x
431                .parse()
432                .map_err(|_| stack.error(ErrorKind::Parse(x, "mega".to_owned())))?,
433            Value::ByteArray(x) => x.len() as i128,
434        })
435        .spl(),
436    );
437    Ok(())
438}
439
440pub fn to_float(stack: &mut Stack) -> OError {
441    let o = stack.pop().lock_ro().native.clone();
442    stack.push(
443        Value::Float(match o {
444            Value::Null => type_err!(stack, "null", "float"),
445            Value::Int(x) => x as f32,
446            Value::Long(x) => x as f32,
447            Value::Mega(x) => x as f32,
448            Value::Float(x) => x,
449            Value::Double(x) => x as f32,
450            Value::Func(_) => type_err!(stack, "func", "float"),
451            Value::Array(_) => type_err!(stack, "array", "float"),
452            Value::Str(x) => x
453                .parse()
454                .map_err(|_| stack.error(ErrorKind::Parse(x, "float".to_owned())))?,
455            Value::ByteArray(_) => type_err!(stack, "bytearray", "float"),
456        })
457        .spl(),
458    );
459    Ok(())
460}
461
462pub fn to_double(stack: &mut Stack) -> OError {
463    let o = stack.pop().lock_ro().native.clone();
464    stack.push(
465        Value::Double(match o {
466            Value::Null => type_err!(stack, "null", "double"),
467            Value::Int(x) => x as f64,
468            Value::Long(x) => x as f64,
469            Value::Mega(x) => x as f64,
470            Value::Float(x) => x as f64,
471            Value::Double(x) => x,
472            Value::Func(_) => type_err!(stack, "func", "double"),
473            Value::Array(_) => type_err!(stack, "array", "double"),
474            Value::Str(x) => x
475                .parse()
476                .map_err(|_| stack.error(ErrorKind::Parse(x, "double".to_owned())))?,
477            Value::ByteArray(_) => type_err!(stack, "bytearray", "double"),
478        })
479        .spl(),
480    );
481    Ok(())
482}
483
484pub fn to_array(stack: &mut Stack) -> OError {
485    let o = stack.pop().lock_ro().native.clone();
486    stack.push(
487        Value::Array(match o {
488            Value::Null => type_err!(stack, "null", "array"),
489            Value::Int(_) => type_err!(stack, "int", "array"),
490            Value::Long(_) => type_err!(stack, "long", "array"),
491            Value::Mega(_) => type_err!(stack, "mega", "array"),
492            Value::Float(_) => type_err!(stack, "float", "array"),
493            Value::Double(_) => type_err!(stack, "double", "array"),
494            Value::Func(_) => type_err!(stack, "func", "array"),
495            Value::Array(x) => x,
496            Value::Str(x) => x
497                .chars()
498                .map(|x| Value::Int(x as u32 as i32).spl())
499                .collect(),
500            Value::ByteArray(x) => x
501                .iter()
502                .cloned()
503                .map(|x| Value::Int(x as i32).spl())
504                .collect(),
505        })
506        .spl(),
507    );
508    Ok(())
509}
510
511pub fn to_str(stack: &mut Stack) -> OError {
512    let o = stack.pop().lock_ro().native.clone();
513    stack.push(
514        Value::Str(match o {
515            Value::Null => type_err!(stack, "null", "str"),
516            Value::Int(x) => x.to_string(),
517            Value::Long(x) => x.to_string(),
518            Value::Mega(x) => x.to_string(),
519            Value::Float(x) => x.to_string(),
520            Value::Double(x) => x.to_string(),
521            Value::Func(_) => type_err!(stack, "func", "str"),
522            Value::Array(x) => {
523                let iter: Vec<_> = x
524                    .into_iter()
525                    .map(|x| match &x.lock_ro().native {
526                        Value::Int(x) => char::from_u32(*x as u32).ok_or_else(|| {
527                            stack.error(ErrorKind::InvalidType(
528                                format!("int-{x}"),
529                                "__str-element".to_owned(),
530                            ))
531                        }),
532                        _ => stack.err(ErrorKind::InvalidType(
533                            "?".to_owned(),
534                            "__str-element".to_owned(),
535                        )),
536                    })
537                    .collect();
538                let mut fixed = String::with_capacity(iter.len());
539                for item in iter {
540                    fixed.push(item?);
541                }
542                fixed
543            }
544            Value::Str(x) => x,
545            Value::ByteArray(x) => String::from_utf8(x).map_err(|_| {
546                stack.error(ErrorKind::InvalidType(
547                    "!utf8".to_owned(),
548                    "utf8".to_owned(),
549                ))
550            })?,
551        })
552        .spl(),
553    );
554    Ok(())
555}
556
557pub fn to_bytearray(stack: &mut Stack) -> OError {
558    let o = stack.pop().lock_ro().native.clone();
559    stack.push(
560        Value::ByteArray(match o {
561            Value::Null => type_err!(stack, "null", "array"),
562            Value::Int(_) => type_err!(stack, "int", "array"),
563            Value::Long(_) => type_err!(stack, "long", "array"),
564            Value::Mega(_) => type_err!(stack, "mega", "array"),
565            Value::Float(_) => type_err!(stack, "float", "array"),
566            Value::Double(_) => type_err!(stack, "double", "array"),
567            Value::Func(_) => type_err!(stack, "func", "array"),
568            Value::Array(x) => x
569                .iter()
570                .cloned()
571                .map(|x| {
572                    Ok(match &x.lock_ro().native {
573                        Value::Int(x) => *x as u8,
574                        Value::Long(x) => *x as u8,
575                        Value::Mega(x) => *x as u8,
576                        _ => stack.err(ErrorKind::InvalidType(
577                            x.lock_ro().kind.lock_ro().get_name(),
578                            "byte".to_owned(),
579                        ))?,
580                    })
581                })
582                .collect::<Result<Vec<_>, _>>()?,
583            Value::Str(x) => x.into_bytes(),
584            Value::ByteArray(x) => x,
585        })
586        .spl(),
587    );
588    Ok(())
589}
590
591pub fn call(stack: &mut Stack) -> OError {
592    let Value::Func(a) = stack.pop().lock_ro().native.clone() else {
593        return stack.err(ErrorKind::InvalidCall("call".to_owned()));
594    };
595    stack.call(&a)
596}
597
598pub fn callp(stack: &mut Stack) -> OError {
599    let Value::Func(a) = stack.pop().lock_ro().native.clone() else {
600        return stack.err(ErrorKind::InvalidCall("callp".to_owned()));
601    };
602    stack.call(&a)?;
603    for _ in 0..a.ret_count {
604        stack.pop();
605    }
606    Ok(())
607}
608
609pub fn trace(stack: &mut Stack) -> OError {
610    let trace = stack.trace();
611    stack.push(Value::Array(trace.into_iter().map(|x| Value::Str(x).spl()).collect()).spl());
612    Ok(())
613}
614
615pub fn mr_trace(stack: &mut Stack) -> OError {
616    let trace = stack.mr_trace();
617    stack.push(
618        Value::Array(
619            trace
620                .into_iter()
621                .map(|x| Value::Array(x.into_iter().map(|x| x.spl()).collect()).spl())
622                .collect(),
623        )
624        .spl(),
625    );
626    Ok(())
627}
628
629pub fn exit(stack: &mut Stack) -> OError {
630    let Value::Int(a) = stack.pop().lock_ro().native.clone().try_mega_to_int() else {
631        return stack.err(ErrorKind::InvalidCall("exit".to_owned()));
632    };
633    process::exit(a)
634}
635
636pub fn exec(stack: &mut Stack) -> OError {
637    let Value::Func(a) = stack.pop().lock_ro().native.clone() else {
638        return stack.err(ErrorKind::InvalidCall("exec".to_owned()));
639    };
640    unsafe {
641        let f = stack.pop_frame(0);
642        let r = a.to_call.call(stack);
643        stack.push_frame(f);
644        r
645    }
646}
647
648pub fn exec2(stack: &mut Stack) -> OError {
649    let Value::Func(a) = stack.pop().lock_ro().native.clone() else {
650        return stack.err(ErrorKind::InvalidCall("exec2".to_owned()));
651    };
652    unsafe {
653        let f = stack.pop_frame(0);
654        let f1 = stack.pop_frame(0);
655        let r = a.to_call.call(stack);
656        stack.push_frame(f1);
657        stack.push_frame(f);
658        r
659    }
660}
661
662pub fn exec3(stack: &mut Stack) -> OError {
663    let Value::Func(a) = stack.pop().lock_ro().native.clone() else {
664        return stack.err(ErrorKind::InvalidCall("exec3".to_owned()));
665    };
666    unsafe {
667        let f = stack.pop_frame(0);
668        let f1 = stack.pop_frame(0);
669        let f2 = stack.pop_frame(0);
670        let r = a.to_call.call(stack);
671        stack.push_frame(f2);
672        stack.push_frame(f1);
673        stack.push_frame(f);
674        r
675    }
676}
677
678pub fn stop(stack: &mut Stack) -> OError {
679    let Value::Int(i) = stack.pop().lock_ro().native.clone().try_mega_to_int() else {
680        return stack.err(ErrorKind::InvalidCall("stop".to_owned()));
681    };
682    stack.return_accumultor += i as u32;
683    Ok(())
684}
685
686pub fn argv(stack: &mut Stack) -> OError {
687    stack.push(Value::Array(args().into_iter().map(|x| Value::Str(x).spl()).collect()).spl());
688    Ok(())
689}
690
691pub fn get_env(stack: &mut Stack) -> OError {
692    stack.push(
693        Value::Array(
694            vars()
695                .into_iter()
696                .map(|x| Value::Array(vec![Value::Str(x.0).spl(), Value::Str(x.1).spl()]).spl())
697                .collect(),
698        )
699        .spl(),
700    );
701    Ok(())
702}
703
704pub fn read_file(stack: &mut Stack) -> OError {
705    let Value::Str(s) = stack.pop().lock_ro().native.clone() else {
706        return stack.err(ErrorKind::InvalidCall("read_file".to_owned()));
707    };
708    stack.push(
709        Value::Str(
710            fs::read_to_string(s).map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))?,
711        )
712        .spl(),
713    );
714    Ok(())
715}
716
717pub fn alit_end(stack: &mut Stack) -> OError {
718    let s = stack.pop();
719    let popped = stack.pop_until(s);
720    stack.push(Value::Array(popped).spl());
721    Ok(())
722}
723
724// TODO: rewrite
725pub fn import(stack: &mut Stack) -> OError {
726    let Value::Str(mut s) = stack.pop().lock_ro().native.clone() else {
727        return stack.err(ErrorKind::InvalidCall("import".to_owned()));
728    };
729    if let Some(x) = s.strip_prefix('#') {
730        s = find_in_splpath(x).unwrap_or(x.to_owned());
731    } else if let Some(x) = s.strip_prefix('@') {
732        s = x.to_owned();
733    } else {
734        s = stack
735            .peek_frame(1)
736            .origin
737            .file
738            .rsplit_once('/')
739            .map(|x| x.0)
740            .unwrap_or(".")
741            .to_owned()
742            + "/"
743            + &s;
744        s = s.trim_start_matches("./").to_owned();
745    }
746    let mut fallback = s
747        .as_str()
748        .rsplit_once(|x| x == '#')
749        .map(|(.., x)| x.to_owned())
750        .unwrap_or(s.clone());
751    while fallback.contains("/../") {
752        let mut fb = readf("{}/../{}", &fallback).unwrap();
753        if let Some(x) = fb[0].rsplit_once('/') {
754            fallback = x.0.to_owned() + &fb[1];
755        } else {
756            fallback = fb.swap_remove(1);
757        }
758    }
759    let fallback = runtime(|x| {
760        for (&p, &data) in &x.embedded_files {
761            if fallback == p {
762                return Some(data.to_owned());
763            }
764        }
765        None
766    });
767    if stack.include_file(
768        &(*fs::canonicalize(s.clone())
769            .unwrap_or_else(|_| s.clone().into())
770            .as_os_str()
771            .to_string_lossy())
772        .to_owned(),
773    ) {
774        stack.push(Value::Str(s.clone()).spl());
775        dup(stack)?;
776        read_file(stack).or_else(|x| {
777            if let Some(fallback) = fallback {
778                stack.push(Value::Str(fallback.to_owned()).spl());
779                Ok(())
780            } else {
781                Err(x)
782            }
783        })?;
784        dyn_fns::wrap(if s.ends_with(".sasm") {
785            dyn_fns::dyn_sasmf
786        } else {
787            dyn_fns::dyn_readf
788        })(stack)?;
789        call(stack)?;
790    }
791    Ok(())
792}
793
794pub fn readln(stack: &mut Stack) -> OError {
795    let mut s = String::new();
796    if stdin()
797        .read_line(&mut s)
798        .map_err(|x| stack.error(ErrorKind::IO(format!("{x:?}"))))?
799        == 0
800    {
801        stack.push(Value::Null.spl());
802        return Ok(());
803    }
804    let s = if let Some(s) = s.strip_suffix("\r\n") {
805        s.to_owned()
806    } else {
807        s
808    };
809    let s = if let Some(s) = s.strip_suffix('\n') {
810        s.to_owned()
811    } else {
812        s
813    };
814    stack.push(Value::Str(s).spl());
815    Ok(())
816}
817
818pub fn command(stack: &mut Stack) -> OError {
819    let binding = stack.pop();
820    let Value::Array(ref a) = binding.lock_ro().native else {
821        return stack.err(ErrorKind::InvalidCall("command".to_owned()));
822    };
823    let mut args = Vec::new();
824    for item in a.iter() {
825        if let Value::Str(ref s) = item.lock_ro().native {
826            args.push(s.to_owned());
827        }
828    }
829    if args.is_empty() {
830        return stack.err(ErrorKind::InvalidCall("command".to_owned()));
831    }
832    let child = process::Command::new(&args[0])
833        .args(&args[1..])
834        .stdin(Stdio::null())
835        .stdout(Stdio::null())
836        .stderr(Stdio::null())
837        .spawn()
838        .map_err(|x| stack.error(ErrorKind::IO(x.to_string())))?;
839    stack.push(Value::Long(child.id() as i64).spl());
840    runtime(|rt| rt.child(child));
841    Ok(())
842}
843
844pub fn command_wait(stack: &mut Stack) -> OError {
845    command_wait_impl(stack, Stdio::inherit)
846}
847
848pub fn command_wait_silent(stack: &mut Stack) -> OError {
849    command_wait_impl(stack, Stdio::null)
850}
851
852pub fn command_wait_impl(stack: &mut Stack, stdio: fn() -> Stdio) -> OError {
853    let binding = stack.pop();
854    let Value::Array(ref a) = binding.lock_ro().native else {
855        return stack.err(ErrorKind::InvalidCall("command".to_owned()));
856    };
857    let mut args = Vec::new();
858    for item in a.iter() {
859        if let Value::Str(ref s) = item.lock_ro().native {
860            args.push(s.to_owned());
861        } else {
862            return stack.err(ErrorKind::InvalidCall("command".to_owned()));
863        }
864    }
865    if args.is_empty() {
866        return stack.err(ErrorKind::InvalidCall("command".to_owned()));
867    }
868    stack.push(
869        Value::Int(
870            process::Command::new(&args[0])
871                .args(&args[1..])
872                .stdin(stdio())
873                .stdout(stdio())
874                .stderr(stdio())
875                .spawn()
876                .map_err(|x| stack.error(ErrorKind::IO(x.to_string())))?
877                .wait()
878                .map_err(|x| stack.error(ErrorKind::IO(x.to_string())))?
879                .code()
880                .unwrap_or(-1),
881        )
882        .spl(),
883    );
884    Ok(())
885}
886
887pub fn str_to_bytes(stack: &mut Stack) -> OError {
888    require_on_stack!(s, Str, stack, "str-to-bytes");
889    stack.push(Value::ByteArray(s.bytes().collect()).spl());
890    Ok(())
891}
892
893pub fn bytes_to_str(stack: &mut Stack) -> OError {
894    if stack.peek().lock_ro().kind.lock_ro().get_name() == "bytearray" {
895        require_on_stack!(a, ByteArray, stack, "bytes-to-str");
896        stack.push(Value::Str(String::from_utf8_lossy(&a[..]).into_owned()).spl());
897        return Ok(());
898    }
899    require_byte_array_on_stack!(a, stack, "bytes-to-str");
900    stack.push(Value::Str(String::from_utf8_lossy(&a).into_owned()).spl());
901    Ok(())
902}
903
904pub fn acopy(stack: &mut Stack) -> OError {
905    require_on_stack!(len, Mega, stack, "acopy");
906    require_on_stack!(idx_dest, Mega, stack, "acopy");
907    require_on_stack!(idx_src, Mega, stack, "acopy");
908    let dest_array = stack.pop();
909    let kind = dest_array.lock_ro().kind.lock_ro().get_name();
910    if kind == "array" {
911        require_mut_array!(dest, dest_array, stack, "acopy");
912        require_array_on_stack!(src, stack, "acopy");
913        if (src.len() as i128) < idx_src + len
914            || idx_src < 0
915            || (dest.len() as i128) < idx_dest + len
916            || idx_dest < 0
917        {
918            stack.err(ErrorKind::InvalidCall("acopy".to_owned()))?;
919        }
920        let len = len as usize;
921        let idx_src = idx_src as usize;
922        let idx_dest = idx_dest as usize;
923        (&mut dest[idx_dest..idx_dest + len]).clone_from_slice(&src[idx_src..idx_src + len]);
924    }
925    if kind == "bytearray" {
926        require_mut!(dest, ByteArray, dest_array, stack, "acopy");
927        require_byte_array_on_stack!(src, stack, "acopy");
928        if (src.len() as i128) < idx_src + len
929            || idx_src < 0
930            || (dest.len() as i128) < idx_dest + len
931            || idx_dest < 0
932        {
933            stack.err(ErrorKind::InvalidCall("acopy".to_owned()))?;
934        }
935        let len = len as usize;
936        let idx_src = idx_src as usize;
937        let idx_dest = idx_dest as usize;
938        (&mut dest[idx_dest..idx_dest + len]).copy_from_slice(&src[idx_src..idx_src + len]);
939    }
940    stack.push(dest_array);
941    Ok(())
942}
943
944pub fn throw(stack: &mut Stack) -> OError {
945    let obj = stack.pop();
946    if let Value::Str(ref s) = obj.lock_ro().native {
947        if obj.lock_ro().kind.lock_ro().get_id()
948            == get_type("str")
949                .expect("str type must exist")
950                .lock_ro()
951                .get_id()
952        {
953            stack.err(ErrorKind::Custom(s.to_owned()))?;
954        }
955    }
956    stack.err(ErrorKind::CustomObject(obj))
957}
958
959pub fn write_sasm(stack: &mut Stack) -> OError {
960    require_on_stack!(code, Str, stack, "write-sasm");
961    stack.push(
962        Value::Str(
963            lexer::lex(false, code)
964                .map(|x| sasm_write(x))
965                .map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
966        )
967        .spl(),
968    );
969    Ok(())
970}
971
972pub fn write_file_sasm(stack: &mut Stack) -> OError {
973    require_on_stack!(file, Str, stack, "write-file-sasm");
974    stack.push(
975        Value::Str(
976            lexer::lex(
977                file.ends_with(".isbpl"),
978                fs::read_to_string(file).map_err(|x| stack.error(ErrorKind::IO(x.to_string())))?,
979            )
980            .map(|x| sasm_write(x))
981            .map_err(|x| stack.error(ErrorKind::LexError(format!("{x:?}"))))?,
982        )
983        .spl(),
984    );
985    Ok(())
986}
987
988pub fn fork(stack: &mut Stack) -> OError {
989    require_on_stack!(callable, Func, stack, "fork");
990    let mut new_stack = stack.clone();
991    let rt = fork_runtime();
992    thread::spawn(move || {
993        rt.set();
994        if let Some(err) = new_stack.call(&callable).err() {
995            println!("{err:?}");
996        };
997    });
998    Ok(())
999}
1000
1001pub fn time(stack: &mut Stack) -> OError {
1002    require_on_stack!(sleep_ms, Mega, stack, "time");
1003    if sleep_ms != 0 {
1004        thread::sleep(Duration::from_millis(sleep_ms as u64));
1005    }
1006    stack.push(
1007        (SystemTime::now()
1008            .duration_since(SystemTime::UNIX_EPOCH)
1009            .unwrap()
1010            .as_millis() as i128)
1011            .spl(),
1012    );
1013    Ok(())
1014}
1015
1016pub fn str_readf(stack: &mut Stack) -> OError {
1017    require_on_stack!(string, Str, stack, "str-readf");
1018    require_on_stack!(pat, Str, stack, "str-readf");
1019    let Some(result) = readf(&pat, &string) else {
1020        stack.push(Value::Null.spl());
1021        return Ok(());
1022    };
1023    stack.push(Value::Array(result.into_iter().map(<String as SPL>::spl).collect()).spl());
1024    Ok(())
1025}
1026
1027pub fn str_to_mega_radix(stack: &mut Stack) -> OError {
1028    require_int_on_stack!(radix, stack, "str-to-mega-radix");
1029    require_on_stack!(str, Str, stack, "str-to-mega-radix");
1030    let Ok(result) = i128::from_str_radix(&str, radix as u32) else {
1031        stack.push(Value::Null.spl());
1032        return Ok(());
1033    };
1034    stack.push(Value::Mega(result).spl());
1035    return Ok(());
1036}
1037
1038pub fn mega_to_str_radix(stack: &mut Stack) -> OError {
1039    require_int_on_stack!(radix, stack, "mega-to-str-radix");
1040    require_on_stack!(mega, Mega, stack, "mega-to-str-radix");
1041    // capacity because O(n)
1042    let mut result = Vec::with_capacity((mega as f64).powf(1.0 / radix as f64) as usize + 2);
1043    let neg = mega < 0;
1044    let mut mega = mega;
1045    if neg {
1046        mega = -mega;
1047        result.push('-' as u32);
1048    }
1049    while mega != 0 {
1050        let i = (mega % radix as i128) as u32;
1051        result.push(if i < 10 { '0' as u32 } else { 'a' as u32 - 10 } + i);
1052        mega = mega / radix as i128;
1053    }
1054    result.reverse();
1055    stack.push(
1056        Value::Str(String::from_iter(
1057            result
1058                .into_iter()
1059                .map(|x| char::from_u32(x).expect("invalid radix")),
1060        ))
1061        .spl(),
1062    );
1063    return Ok(());
1064}
1065
1066pub fn properties(stack: &mut Stack) -> OError {
1067    let o = stack.pop();
1068    let o = o.lock_ro();
1069    let additional: Vec<AMObject> = vec![
1070        Value::Array(vec![
1071            ":".to_owned().spl(),
1072            o.kind.lock_ro().get_name().spl(),
1073        ])
1074        .spl(),
1075        Value::Array(vec![";".to_owned().spl(), o.native.clone().spl()]).spl(),
1076    ];
1077    stack.push(
1078        Value::Array(
1079            o.property_map
1080                .iter()
1081                .map(|(k, v)| Value::Array(vec![k.clone().spl(), v.clone()]).spl())
1082                .chain(additional.into_iter())
1083                .collect(),
1084        )
1085        .spl(),
1086    );
1087    Ok(())
1088}
1089
1090pub fn from_properties(stack: &mut Stack) -> OError {
1091    require_array_on_stack!(props, stack, "from-properties");
1092    let mut map = HashMap::with_capacity(props.len());
1093    for prop in props {
1094        require_array!(prop, prop, stack, "from-properties");
1095        if prop.len() != 2 {
1096            stack.err(ErrorKind::InvalidCall("from-properties".to_string()))?;
1097        }
1098        let Value::Str(ref s) = prop[0].lock_ro().native else {
1099            return Err(stack.error(ErrorKind::InvalidCall("from-properties".to_string())));
1100        };
1101        map.insert(s.to_owned(), prop[1].clone());
1102    }
1103    let Value::Str(kind) = map
1104        .get(":")
1105        .ok_or(stack.error(ErrorKind::InvalidCall("from-properties".to_string())))?
1106        .lock_ro()
1107        .native
1108        .clone()
1109    else {
1110        return Err(stack.error(ErrorKind::InvalidCall("from-properties".to_string())));
1111    };
1112    let kind = runtime(|rt| rt.get_type_by_name(&kind))
1113        .ok_or(stack.error(ErrorKind::TypeNotFound(kind.to_owned())))?;
1114    let native = map
1115        .get(";")
1116        .ok_or(stack.error(ErrorKind::InvalidCall("from-properties".to_owned())))?
1117        .lock_ro()
1118        .native
1119        .clone();
1120    map.remove(";");
1121    map.remove(":");
1122    stack.push(Arc::new(Mut::new(Object {
1123        kind,
1124        native,
1125        property_map: map,
1126    })));
1127    Ok(())
1128}
1129
1130pub fn list_files(stack: &mut Stack) -> OError {
1131    require_on_stack!(dir, Str, stack, "list-files");
1132    stack.push(
1133        match fs::read_dir(&dir)
1134            .map_err(|_| stack.error(ErrorKind::IO(format!("Not a directory: {}", &dir))))
1135        {
1136            Ok(it) => Value::Array(
1137                it.filter(|x| x.is_ok())
1138                    .map(|x| {
1139                        if let Ok(x) = x {
1140                            Value::Str(x.file_name().to_string_lossy().into_owned()).spl()
1141                        } else {
1142                            unreachable!()
1143                        }
1144                    })
1145                    .collect(),
1146            )
1147            .spl(),
1148            Err(_) => Value::Null.spl(),
1149        },
1150    );
1151    Ok(())
1152}
1153
1154pub fn delete_file(stack: &mut Stack) -> OError {
1155    require_on_stack!(file, Str, stack, "delete-file");
1156    stack.push(Value::Int(if fs::remove_file(file).is_ok() { 1 } else { 0 }).spl());
1157    Ok(())
1158}
1159
1160pub fn delete_dir(stack: &mut Stack) -> OError {
1161    require_on_stack!(dir, Str, stack, "delete-dir");
1162    stack.push(
1163        Value::Int(if fs::remove_dir_all(dir).is_ok() {
1164            1
1165        } else {
1166            0
1167        })
1168        .spl(),
1169    );
1170    Ok(())
1171}
1172
1173pub fn chdir(stack: &mut Stack) -> OError {
1174    require_on_stack!(dir, Str, stack, "chdir");
1175    env::set_current_dir(dir).map_err(|e| stack.error(ErrorKind::IO(e.to_string())))?;
1176    Ok(())
1177}
1178
1179pub fn register(r: &mut Stack, o: Arc<Frame>) {
1180    type Fn = fn(&mut Stack) -> OError;
1181    let fns: [(&str, Fn, u32); 71] = [
1182        ("pop", pop, 0),
1183        ("dup", dup, 2),
1184        ("dup2", dup2, 3),
1185        ("clone", clone, 1),
1186        ("swap", swap, 2),
1187        ("mswap", mswap, 2),
1188        ("print", print, 0),
1189        ("gettype", gettype, 1),
1190        ("gettypeid", gettypeid, 1),
1191        ("settype", settype, 1),
1192        ("settypeid", settypeid, 1),
1193        ("banew", barray_new, 1),
1194        ("anew", array_new, 1),
1195        ("array-len", array_len, 1),
1196        ("array-get", array_get, 1),
1197        ("array-set", array_set, 1),
1198        ("eq", eq, 1),
1199        ("lt", lt, 1),
1200        ("gt", gt, 1),
1201        ("not", not, 1),
1202        ("and", and, 1),
1203        ("or", or, 1),
1204        ("+", plus, 1),
1205        ("-", minus, 1),
1206        ("/", slash, 1),
1207        ("*", star, 1),
1208        ("%", percent, 1),
1209        ("pow", pow, 1),
1210        ("_int", to_int, 1),
1211        ("_long", to_long, 1),
1212        ("_mega", to_mega, 1),
1213        ("_float", to_float, 1),
1214        ("_double", to_double, 1),
1215        ("_array", to_array, 1),
1216        ("_str", to_str, 1),
1217        ("_barray", to_bytearray, 1),
1218        ("call", call, 0),
1219        ("callp", callp, 0),
1220        ("trace", trace, 1),
1221        ("mr-trace", mr_trace, 1),
1222        ("exit", exit, 0),
1223        ("exec", exec, 0),
1224        ("exec2", exec2, 0),
1225        ("exec3", exec3, 0),
1226        ("stop", stop, 0),
1227        ("argv", argv, 1),
1228        ("get-env", get_env, 1),
1229        ("read-file", read_file, 1),
1230        ("alit-end", alit_end, 1),
1231        ("import", import, 0),
1232        ("readln", readln, 1),
1233        ("command", command, 1),
1234        ("command-wait", command_wait, 1),
1235        ("command-wait-silent", command_wait_silent, 1),
1236        ("str-to-bytes", str_to_bytes, 1),
1237        ("bytes-to-str", bytes_to_str, 1),
1238        ("acopy", acopy, 1),
1239        ("throw", throw, 0),
1240        ("write-sasm", write_sasm, 1),
1241        ("write-file-sasm", write_file_sasm, 1),
1242        ("fork", fork, 0),
1243        ("sleeptime", time, 0),
1244        ("str-readf", str_readf, 1),
1245        ("str-to-mega-radix", str_to_mega_radix, 1),
1246        ("mega-to-str-radix", mega_to_str_radix, 1),
1247        ("properties", properties, 1),
1248        ("from-properties", from_properties, 1),
1249        ("list-files", list_files, 1),
1250        ("delete-file", delete_file, 1),
1251        ("delete-dir", delete_dir, 1),
1252        ("chdir", chdir, 0),
1253    ];
1254    for f in fns {
1255        r.define_func(
1256            f.0.to_owned(),
1257            AFunc::new(Func {
1258                ret_count: f.2,
1259                to_call: FuncImpl::Native(f.1),
1260                run_as_base: false,
1261                origin: o.clone(),
1262                fname: None,
1263                name: f.0.to_owned(),
1264            }),
1265        );
1266    }
1267}