#[macro_export]
macro_rules! raster {
($expr:expr) => {{
use $crate::dsl::ast::{Program, Statement};
use $crate::dsl::{parse_expression, CompiledProgram};
let expr_str = stringify!($expr);
let parsed = parse_expression(expr_str)?;
let program = Program {
statements: vec![Statement::Expr(Box::new(parsed))],
};
CompiledProgram::new(program)
}};
({ $($stmt:stmt);+ }) => {{
use $crate::dsl::{parse_program, CompiledProgram};
let program_str = stringify!({ $($stmt);+ });
let parsed = parse_program(program_str)?;
CompiledProgram::new(parsed)
}};
}
#[macro_export]
macro_rules! dsl_function {
(fn $name:ident ( $($param:ident),* $(,)? ) = $body:expr ;) => {
pub fn $name() -> ::std::string::String {
let params: &[&str] = &[ $( stringify!($param) ),* ];
let mut out = ::std::string::String::from("fn ");
out.push_str(stringify!($name));
out.push('(');
out.push_str(¶ms.join(", "));
out.push_str(") = ");
out.push_str(stringify!($body));
out.push(';');
out
}
};
}
#[cfg(test)]
mod tests {
dsl_function! {
fn ndvi(nir, red) = (nir - red) / (nir + red);
}
#[test]
fn test_dsl_function_emits_valid_source() {
let src = ndvi();
assert_eq!(src, "fn ndvi(nir, red) = (nir - red) / (nir + red);");
}
#[test]
fn test_dsl_function_source_is_usable_in_a_program() {
use crate::dsl::{CompiledProgram, parse_program};
use oxigeo_core::buffer::RasterBuffer;
use oxigeo_core::types::RasterDataType;
let def = ndvi();
parse_program(&def).expect("generated dsl_function source must parse");
let program_src = format!("{def}\nndvi(B1, B2);");
let program = parse_program(&program_src).expect("full program must parse");
let compiled = CompiledProgram::new(program);
let mut nir = RasterBuffer::zeros(2, 2, RasterDataType::Float32);
let mut red = RasterBuffer::zeros(2, 2, RasterDataType::Float32);
for y in 0..2 {
for x in 0..2 {
nir.set_pixel(x, y, 3.0).expect("set nir");
red.set_pixel(x, y, 1.0).expect("set red");
}
}
let result = compiled
.execute(&[nir, red])
.expect("dsl_function program should execute");
for y in 0..2 {
for x in 0..2 {
let v = result.get_pixel(x, y).expect("pixel readable");
assert!((v - 0.5).abs() < 1e-6, "unexpected NDVI value {v}");
}
}
}
}