use crate::capnp::jeff_capnp;
use crate::reader::value::{FunctionIOValue, ValueTable};
use super::metadata::sealed::HasMetadataSealed;
use super::string_table::StringTable;
use super::{ReadError, Region};
pub type FunctionId = u32;
#[derive(Clone, Copy, Debug)]
pub enum Function<'a> {
Definition(FunctionDefinition<'a>),
Declaration(FunctionDeclaration<'a>),
}
#[derive(Clone, Copy, Debug)]
pub struct FunctionDefinition<'a> {
function: jeff_capnp::function::Reader<'a>,
body: jeff_capnp::region::Reader<'a>,
values: ValueTable<'a>,
strings: StringTable<'a>,
}
#[derive(Clone, Copy, Debug)]
pub struct FunctionDeclaration<'a> {
function: jeff_capnp::function::Reader<'a>,
inputs: capnp::struct_list::Reader<'a, jeff_capnp::value::Owned>,
outputs: capnp::struct_list::Reader<'a, jeff_capnp::value::Owned>,
strings: StringTable<'a>,
}
impl<'a> Function<'a> {
pub(crate) fn read_capnp(
function: jeff_capnp::function::Reader<'a>,
strings: StringTable<'a>,
) -> Self {
match function.which().expect("Function should be valid") {
jeff_capnp::function::Which::Definition(def) => {
let body = def.get_body().expect("Body should be present");
let values = ValueTable::read_capnp(
def.get_values().expect("Values should be present"),
strings,
);
let def = FunctionDefinition {
function,
body,
values,
strings,
};
Self::Definition(def)
}
jeff_capnp::function::Which::Declaration(decl) => {
let inputs = decl.get_inputs().expect("Inputs should be present");
let outputs = decl.get_outputs().expect("Outputs should be present");
let decl = FunctionDeclaration {
function,
inputs,
outputs,
strings,
};
Self::Declaration(decl)
}
}
}
pub fn name(&self) -> &str {
match self {
Function::Declaration(decl) => decl.name(),
Function::Definition(def) => def.name(),
}
}
pub fn input_types(&self) -> impl Iterator<Item = Result<FunctionIOValue<'a>, ReadError>> + '_ {
match self {
Function::Declaration(decl) => itertools::Either::Left(decl.input_types()),
Function::Definition(def) => itertools::Either::Right(def.input_types()),
}
}
pub fn output_types(
&self,
) -> impl Iterator<Item = Result<FunctionIOValue<'a>, ReadError>> + '_ {
match self {
Function::Declaration(decl) => itertools::Either::Left(decl.output_types()),
Function::Definition(def) => itertools::Either::Right(def.output_types()),
}
}
}
impl<'a> FunctionDefinition<'a> {
pub fn name(&self) -> &str {
self.strings
.get(self.function.get_name(), "function name")
.expect("Invalid function name definition")
}
pub fn body(&self) -> Region<'a> {
Region::read_capnp(self.body, self.strings, self.values())
}
pub fn values(&self) -> ValueTable<'a> {
self.values
}
pub fn input_types(&self) -> impl Iterator<Item = Result<FunctionIOValue<'a>, ReadError>> + 'a {
self.body().sources().map(|v| Ok(v?.into()))
}
pub fn output_types(
&self,
) -> impl Iterator<Item = Result<FunctionIOValue<'a>, ReadError>> + 'a {
self.body().targets().map(|v| Ok(v?.into()))
}
}
impl<'a> FunctionDeclaration<'a> {
pub fn name(&self) -> &str {
self.strings
.get(self.function.get_name(), "function name")
.expect("Invalid function name definition")
}
pub fn input_types(&self) -> impl Iterator<Item = Result<FunctionIOValue<'a>, ReadError>> + '_ {
self.inputs
.iter()
.map(move |value| Ok(FunctionIOValue::read_capnp(value, self.strings)))
}
pub fn output_types(
&self,
) -> impl Iterator<Item = Result<FunctionIOValue<'a>, ReadError>> + '_ {
self.outputs
.iter()
.map(move |value| Ok(FunctionIOValue::read_capnp(value, self.strings)))
}
}
impl<'a> HasMetadataSealed for Function<'a> {
fn strings(&self) -> StringTable<'a> {
match self {
Function::Declaration(decl) => decl.strings,
Function::Definition(def) => def.strings,
}
}
fn metadata_reader(&self) -> capnp::struct_list::Reader<'_, jeff_capnp::meta::Owned> {
match self {
Function::Declaration(decl) => decl.metadata_reader(),
Function::Definition(def) => def.metadata_reader(),
}
}
}
impl<'a> HasMetadataSealed for FunctionDeclaration<'a> {
fn strings(&self) -> StringTable<'a> {
self.strings
}
fn metadata_reader(&self) -> capnp::struct_list::Reader<'_, jeff_capnp::meta::Owned> {
self.function
.get_metadata()
.expect("Metadata should be present")
}
}
impl<'a> HasMetadataSealed for FunctionDefinition<'a> {
fn strings(&self) -> StringTable<'a> {
self.strings
}
fn metadata_reader(&self) -> capnp::struct_list::Reader<'_, jeff_capnp::meta::Owned> {
self.function
.get_metadata()
.expect("Metadata should be present")
}
}