use crate::error::set_runtime_error;
use crate::seqstring::global_string;
use crate::stack::{Stack, pop, push};
use crate::value::Value;
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_symbol_equal(stack: Stack) -> Stack {
assert!(!stack.is_null(), "symbol_equal: stack is empty");
let (stack, sym2_val) = unsafe { pop(stack) };
assert!(!stack.is_null(), "symbol_equal: need two symbols");
let (stack, sym1_val) = unsafe { pop(stack) };
match (sym1_val, sym2_val) {
(Value::Symbol(s1), Value::Symbol(s2)) => {
let equal = if s1.is_interned() && s2.is_interned() {
s1.as_ptr() == s2.as_ptr()
} else {
s1.as_str() == s2.as_str()
};
unsafe { push(stack, Value::Bool(equal)) }
}
_ => panic!("symbol_equal: expected two symbols on stack"),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_json_escape(stack: Stack) -> Stack {
assert!(!stack.is_null(), "json_escape: stack is empty");
let (stack, value) = unsafe { pop(stack) };
match value {
Value::String(s) => {
let input = s.as_str();
let mut result = String::with_capacity(input.len() + 16);
for ch in input.chars() {
match ch {
'"' => result.push_str("\\\""),
'\\' => result.push_str("\\\\"),
'\n' => result.push_str("\\n"),
'\r' => result.push_str("\\r"),
'\t' => result.push_str("\\t"),
'\x08' => result.push_str("\\b"), '\x0C' => result.push_str("\\f"), c if c.is_control() => {
result.push_str(&format!("\\u{:04X}", c as u32));
}
c => result.push(c),
}
}
unsafe { push(stack, Value::String(global_string(result))) }
}
_ => panic!("json_escape: expected String on stack"),
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn patch_seq_string_to_int(stack: Stack) -> Stack {
if stack.is_null() {
set_runtime_error("string->int: stack is empty");
return stack;
}
let (stack, val) = unsafe { pop(stack) };
match val {
Value::String(s) => match s.as_str().trim().parse::<i64>() {
Ok(i) => {
let stack = unsafe { push(stack, Value::Int(i)) };
unsafe { push(stack, Value::Bool(true)) }
}
Err(_) => {
let stack = unsafe { push(stack, Value::Int(0)) };
unsafe { push(stack, Value::Bool(false)) }
}
},
_ => {
set_runtime_error("string->int: expected String on stack");
let stack = unsafe { push(stack, Value::Int(0)) };
unsafe { push(stack, Value::Bool(false)) }
}
}
}