use crate::ArcisType;
use arcis_compiler::{compile::read_ir, ArcisInstruction, DomainKind, EvalValue};
pub struct ArcisInstructionWithInfo {
instruction: ArcisInstruction,
output_domains: Vec<DomainKind>,
}
trait ArcisTypeOrRaw {
fn to_raw_inputs(self) -> Vec<EvalValue>;
fn from_raw_outputs(outputs: Vec<EvalValue>) -> Self;
}
impl ArcisTypeOrRaw for Vec<EvalValue> {
fn to_raw_inputs(self) -> Vec<EvalValue> {
self
}
fn from_raw_outputs(outputs: Vec<EvalValue>) -> Self {
outputs
}
}
impl<T: ArcisType> ArcisTypeOrRaw for T {
fn to_raw_inputs(self) -> Vec<EvalValue> {
let mut input_vals = Vec::new();
self.handle_outputs(&mut input_vals);
input_vals
}
fn from_raw_outputs(outputs: Vec<EvalValue>) -> Self {
T::from_values(outputs.as_slice())
}
}
impl ArcisInstructionWithInfo {
fn eval_raw(&self, inputs: Vec<EvalValue>) -> Vec<EvalValue> {
let mut rng = rand::thread_rng();
self.instruction
.mock_eval_vec(inputs, self.output_domains.as_slice(), &[], &mut rng)
}
#[allow(private_bounds)]
pub fn eval<R: ArcisTypeOrRaw>(&self, inputs: impl ArcisTypeOrRaw) -> R {
let inputs = inputs.to_raw_inputs();
let output_vals = self.eval_raw(inputs);
R::from_raw_outputs(output_vals)
}
}
pub fn get_instruction(name: &str) -> ArcisInstructionWithInfo {
let workspace_root = match find_workspace_root() {
Ok(path) => path,
Err(error) => panic!("Unable to find workspace root: {}", error),
};
let path = workspace_root.join(format!("build/{}.arcis.ir", name));
let ir =
read_ir(path.to_str().expect("Cannot convert path to string.")).expect("Cannot read IR.");
let output_domains = ir.get_output_domains();
let instruction = ir.optimize_into_circuitable().to_async_mpc_circuit();
ArcisInstructionWithInfo {
instruction,
output_domains,
}
}
fn find_workspace_root() -> Result<std::path::PathBuf, &'static str> {
let start_dir = std::path::PathBuf::from(
std::env::var("CARGO_MANIFEST_DIR").map_err(|_| "CARGO_MANIFEST_DIR not set")?,
);
let mut dir = start_dir.clone();
loop {
let manifest = dir.join("Cargo.toml");
if manifest.exists() {
let content = std::fs::read_to_string(&manifest).map_err(|_| "cannot read manifest")?;
if content.contains("[workspace]") {
return Ok(dir);
}
}
if !dir.pop() {
return Ok(start_dir);
}
}
}