use cel::common::ast::CallExpr;
use ferricel_types::functions::RuntimeFunction;
use walrus::InstrSeqBuilder;
use crate::compiler::{
context::{CompilerContext, CompilerEnv},
expr::compile_expr,
};
pub fn compile_ext_regex_function(
func_name: &str,
call_expr: &CallExpr,
body: &mut InstrSeqBuilder,
env: &CompilerEnv,
ctx: &CompilerContext,
module: &mut walrus::Module,
) -> Result<(), anyhow::Error> {
match func_name {
"replace" => compile_regex_replace(call_expr, body, env, ctx, module),
"extract" => compile_regex_binary(
call_expr,
"regex.extract",
RuntimeFunction::RegexExtract,
body,
env,
ctx,
module,
),
"extractAll" => compile_regex_binary(
call_expr,
"regex.extractAll",
RuntimeFunction::RegexExtractAll,
body,
env,
ctx,
module,
),
_ => anyhow::bail!("Unknown regex extension function: {}", func_name),
}
}
fn compile_regex_binary(
call_expr: &CallExpr,
func_name: &str,
runtime_fn: RuntimeFunction,
body: &mut InstrSeqBuilder,
env: &CompilerEnv,
ctx: &CompilerContext,
module: &mut walrus::Module,
) -> Result<(), anyhow::Error> {
if call_expr.args.len() != 2 {
anyhow::bail!(
"{}() expects 2 arguments, got {}",
func_name,
call_expr.args.len()
);
}
compile_expr(&call_expr.args[0].expr, body, env, ctx, module)?;
compile_expr(&call_expr.args[1].expr, body, env, ctx, module)?;
body.call(env.get(runtime_fn));
Ok(())
}
fn compile_regex_replace(
call_expr: &CallExpr,
body: &mut InstrSeqBuilder,
env: &CompilerEnv,
ctx: &CompilerContext,
module: &mut walrus::Module,
) -> Result<(), anyhow::Error> {
match call_expr.args.len() {
3 => {
compile_expr(&call_expr.args[0].expr, body, env, ctx, module)?;
compile_expr(&call_expr.args[1].expr, body, env, ctx, module)?;
compile_expr(&call_expr.args[2].expr, body, env, ctx, module)?;
body.call(env.get(RuntimeFunction::RegexReplace));
Ok(())
}
4 => {
compile_expr(&call_expr.args[0].expr, body, env, ctx, module)?;
compile_expr(&call_expr.args[1].expr, body, env, ctx, module)?;
compile_expr(&call_expr.args[2].expr, body, env, ctx, module)?;
compile_expr(&call_expr.args[3].expr, body, env, ctx, module)?;
body.call(env.get(RuntimeFunction::RegexReplaceN));
Ok(())
}
n => anyhow::bail!("regex.replace() expects 3 or 4 arguments, got {}", n),
}
}