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 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
724pub 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 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}