use cel::common::ast::LiteralValue;
use ferricel_types::functions::RuntimeFunction;
use walrus::{InstrSeqBuilder, LocalId, ValType};
use crate::compiler::{context::CompilerEnv, helpers::get_memory_id};
pub fn compile_literal(
literal: &LiteralValue,
body: &mut InstrSeqBuilder,
env: &CompilerEnv,
module: &mut walrus::Module,
) -> Result<(), anyhow::Error> {
match literal {
LiteralValue::Int(value) => {
body.i64_const(**value);
body.call(env.get(RuntimeFunction::CreateInt));
}
LiteralValue::UInt(value) => {
body.i64_const(**value as i64);
body.call(env.get(RuntimeFunction::CreateUint));
}
LiteralValue::Boolean(b) => {
body.i64_const(if **b { 1 } else { 0 });
body.call(env.get(RuntimeFunction::CreateBool));
}
LiteralValue::Double(d) => {
body.f64_const(**d);
body.call(env.get(RuntimeFunction::CreateDouble));
}
LiteralValue::String(s) => {
let cel_val_local = compile_string_literal(s.inner(), body, env, module)?;
body.local_get(cel_val_local);
}
LiteralValue::Bytes(bytes) => {
let cel_val_local = compile_bytes_literal(bytes.inner(), body, env, module)?;
body.local_get(cel_val_local);
}
LiteralValue::Null => {
body.call(env.get(RuntimeFunction::CreateNull));
}
}
Ok(())
}
fn compile_string_literal(
s: &str,
body: &mut InstrSeqBuilder,
env: &CompilerEnv,
module: &mut walrus::Module,
) -> Result<LocalId, anyhow::Error> {
let string_bytes = s.as_bytes();
let string_len = string_bytes.len() as i32;
let data_ptr_local = module.locals.add(ValType::I32);
body.i32_const(string_len)
.call(env.get(RuntimeFunction::Malloc)) .local_set(data_ptr_local);
let memory_id = get_memory_id(module)?;
for (offset, &byte) in string_bytes.iter().enumerate() {
body.local_get(data_ptr_local);
body.i32_const(byte as i32);
body.store(
memory_id,
walrus::ir::StoreKind::I32_8 { atomic: false },
walrus::ir::MemArg {
align: 1,
offset: offset as u64,
},
);
}
body.local_get(data_ptr_local); body.i32_const(string_len); body.call(env.get(RuntimeFunction::CreateString));
let cel_val_local = module.locals.add(ValType::I32);
body.local_set(cel_val_local);
Ok(cel_val_local)
}
fn compile_bytes_literal(
bytes: &[u8],
body: &mut InstrSeqBuilder,
env: &CompilerEnv,
module: &mut walrus::Module,
) -> Result<LocalId, anyhow::Error> {
let bytes_len = bytes.len() as i32;
let data_ptr_local = module.locals.add(ValType::I32);
body.i32_const(bytes_len)
.call(env.get(RuntimeFunction::Malloc)) .local_set(data_ptr_local);
let memory_id = get_memory_id(module)?;
for (offset, &byte) in bytes.iter().enumerate() {
body.local_get(data_ptr_local);
body.i32_const(byte as i32);
body.store(
memory_id,
walrus::ir::StoreKind::I32_8 { atomic: false },
walrus::ir::MemArg {
align: 1,
offset: offset as u64,
},
);
}
body.local_get(data_ptr_local); body.i32_const(bytes_len); body.call(env.get(RuntimeFunction::CreateBytes));
let cel_val_local = module.locals.add(ValType::I32);
body.local_set(cel_val_local);
Ok(cel_val_local)
}