use cel::common::ast::CallExpr;
use ferricel_types::functions::RuntimeFunction;
use walrus::InstrSeqBuilder;
use crate::compiler::{
context::{CompilerContext, CompilerEnv},
helpers::{compile_call_binary, compile_call_unary},
};
pub fn compile_k8s_quantity_function(
func_name: &str,
call_expr: &CallExpr,
body: &mut InstrSeqBuilder,
env: &CompilerEnv,
ctx: &CompilerContext,
module: &mut walrus::Module,
) -> Result<(), anyhow::Error> {
match func_name {
"quantity" => compile_call_unary(
call_expr,
func_name,
RuntimeFunction::K8sQuantityParse,
body,
env,
ctx,
module,
),
"isQuantity" => compile_call_unary(
call_expr,
func_name,
RuntimeFunction::K8sIsQuantity,
body,
env,
ctx,
module,
),
"sign" => compile_call_unary(
call_expr,
func_name,
RuntimeFunction::K8sQuantitySign,
body,
env,
ctx,
module,
),
"isInteger" => compile_call_unary(
call_expr,
func_name,
RuntimeFunction::K8sQuantityIsInteger,
body,
env,
ctx,
module,
),
"asInteger" => compile_call_unary(
call_expr,
func_name,
RuntimeFunction::K8sQuantityAsInteger,
body,
env,
ctx,
module,
),
"asApproximateFloat" => compile_call_unary(
call_expr,
func_name,
RuntimeFunction::K8sQuantityAsApproxFloat,
body,
env,
ctx,
module,
),
"add" => {
let second_arg = if let Some(_target) = &call_expr.target {
if call_expr.args.len() != 1 {
anyhow::bail!("add() method expects 1 argument");
}
&call_expr.args[0].expr
} else {
if call_expr.args.len() != 2 {
anyhow::bail!("add() function expects 2 arguments");
}
&call_expr.args[1].expr
};
if is_int_expr(second_arg) {
compile_call_binary(
call_expr,
func_name,
RuntimeFunction::K8sQuantityAddInt,
body,
env,
ctx,
module,
)
} else {
compile_call_binary(
call_expr,
func_name,
RuntimeFunction::K8sQuantityAdd,
body,
env,
ctx,
module,
)
}
}
"sub" => {
let second_arg = if let Some(_target) = &call_expr.target {
if call_expr.args.len() != 1 {
anyhow::bail!("sub() method expects 1 argument");
}
&call_expr.args[0].expr
} else {
if call_expr.args.len() != 2 {
anyhow::bail!("sub() function expects 2 arguments");
}
&call_expr.args[1].expr
};
if is_int_expr(second_arg) {
compile_call_binary(
call_expr,
func_name,
RuntimeFunction::K8sQuantitySubInt,
body,
env,
ctx,
module,
)
} else {
compile_call_binary(
call_expr,
func_name,
RuntimeFunction::K8sQuantitySub,
body,
env,
ctx,
module,
)
}
}
"isLessThan" => compile_call_binary(
call_expr,
func_name,
RuntimeFunction::K8sPolyIsLessThan,
body,
env,
ctx,
module,
),
"isGreaterThan" => compile_call_binary(
call_expr,
func_name,
RuntimeFunction::K8sPolyIsGreaterThan,
body,
env,
ctx,
module,
),
"compareTo" => compile_call_binary(
call_expr,
func_name,
RuntimeFunction::K8sPolyCompareTo,
body,
env,
ctx,
module,
),
_ => anyhow::bail!("Unknown Kubernetes quantity function: {}", func_name),
}
}
fn is_int_expr(expr: &cel::common::ast::Expr) -> bool {
use cel::common::ast::{Expr, LiteralValue};
match expr {
Expr::Literal(LiteralValue::Int(_)) => true,
Expr::Literal(LiteralValue::UInt(_)) => true,
Expr::Call(call) if call.func_name == "_-_" || call.func_name == "-_" => {
call.args.len() == 1 && {
matches!(&call.args[0].expr, Expr::Literal(LiteralValue::Int(_)))
}
}
_ => false,
}
}