mod compile_ctx;
mod logic;
mod payload;
mod populate;
pub use logic::Logic;
pub(crate) use compile_ctx::{CompileCtx, NodeId, SYNTHETIC_ID};
pub(crate) use logic::node_is_static;
#[cfg(feature = "ext-control")]
pub(crate) use payload::CompiledExistsData;
#[cfg(feature = "error-handling")]
pub(crate) use payload::CompiledThrowData;
#[cfg(feature = "templating")]
pub(crate) use payload::StructuredObjectData;
pub(crate) use payload::{
CompiledMissingArg, CompiledMissingData, CompiledMissingMin, CompiledMissingPaths,
CompiledMissingSomeData, CustomOperatorData, MetadataHint, PathSegment, ReduceHint,
};
pub(crate) use populate::populate_lits;
use crate::arena::DataValue;
use crate::opcode::OpCode;
use datavalue::OwnedDataValue;
use populate::precompute_lit;
use std::num::NonZeroU32;
#[derive(Debug, Clone)]
pub(crate) enum CompiledNode {
Value {
id: NodeId,
value: OwnedDataValue,
lit: Option<Box<DataValue<'static>>>,
},
Array {
id: NodeId,
nodes: Box<[CompiledNode]>,
},
BuiltinOperator {
id: NodeId,
opcode: OpCode,
args: Box<[CompiledNode]>,
predicate_hint: Option<Box<crate::operators::array::FastPredicate>>,
iter_arg_kind: crate::operators::array::IterArgKind,
},
CustomOperator(Box<CustomOperatorData>),
#[cfg(feature = "templating")]
StructuredObject(Box<StructuredObjectData>),
Var {
id: NodeId,
scope_level: u32,
segments: Box<[PathSegment]>,
reduce_hint: ReduceHint,
metadata_hint: MetadataHint,
default_value: Option<Box<CompiledNode>>,
},
#[cfg(feature = "ext-control")]
Exists(Box<CompiledExistsData>),
#[cfg(feature = "error-handling")]
Throw(Box<CompiledThrowData>),
Missing(Box<CompiledMissingData>),
MissingSome(Box<CompiledMissingSomeData>),
InvalidArgs { id: NodeId, op_name: &'static str },
}
impl CompiledNode {
#[inline]
pub fn id(&self) -> u32 {
self.node_id().map(NonZeroU32::get).unwrap_or(0)
}
#[inline]
pub(crate) fn node_id(&self) -> NodeId {
match self {
CompiledNode::Value { id, .. } => *id,
CompiledNode::Array { id, .. } => *id,
CompiledNode::BuiltinOperator { id, .. } => *id,
CompiledNode::CustomOperator(data) => data.id,
#[cfg(feature = "templating")]
CompiledNode::StructuredObject(data) => data.id,
CompiledNode::Var { id, .. } => *id,
#[cfg(feature = "ext-control")]
CompiledNode::Exists(data) => data.id,
#[cfg(feature = "error-handling")]
CompiledNode::Throw(data) => data.id,
CompiledNode::Missing(data) => data.id,
CompiledNode::MissingSome(data) => data.id,
CompiledNode::InvalidArgs { id, .. } => *id,
}
}
pub(crate) fn visit_indexed_children<F: FnMut(u32, &CompiledNode)>(&self, f: &mut F) {
match self {
CompiledNode::Value { .. } => {}
CompiledNode::Array { nodes, .. } => {
for (i, n) in nodes.iter().enumerate() {
f(i as u32, n);
}
}
CompiledNode::BuiltinOperator { args, .. } => {
for (i, n) in args.iter().enumerate() {
f(i as u32, n);
}
}
CompiledNode::CustomOperator(data) => {
for (i, n) in data.args.iter().enumerate() {
f(i as u32, n);
}
}
#[cfg(feature = "templating")]
CompiledNode::StructuredObject(data) => {
for (i, (_, n)) in data.fields.iter().enumerate() {
f(i as u32, n);
}
}
CompiledNode::Var { default_value, .. } => {
if let Some(d) = default_value {
f(0, d);
}
}
#[cfg(feature = "ext-control")]
CompiledNode::Exists(_) => {}
#[cfg(feature = "error-handling")]
CompiledNode::Throw(_) => {}
CompiledNode::Missing(data) => {
for (i, arg) in data.args.iter().enumerate() {
if let CompiledMissingArg::Later(n) = arg {
f(i as u32, n);
}
}
}
CompiledNode::MissingSome(data) => {
if let CompiledMissingMin::Later(n) = &data.min_present {
f(0, n);
}
if let CompiledMissingPaths::Later(n) = &data.paths {
f(1, n);
}
}
CompiledNode::InvalidArgs { .. } => {}
}
}
#[inline]
pub(crate) fn visit_children<F: FnMut(&CompiledNode)>(&self, f: &mut F) {
self.visit_indexed_children(&mut |_, child| f(child));
}
pub(crate) fn visit_children_mut<F: FnMut(&mut CompiledNode)>(&mut self, f: &mut F) {
match self {
CompiledNode::Value { .. } => {}
CompiledNode::Array { nodes, .. } => {
for n in nodes.iter_mut() {
f(n);
}
}
CompiledNode::BuiltinOperator { args, .. } => {
for n in args.iter_mut() {
f(n);
}
}
CompiledNode::CustomOperator(data) => {
for n in data.args.iter_mut() {
f(n);
}
}
#[cfg(feature = "templating")]
CompiledNode::StructuredObject(data) => {
for (_, n) in data.fields.iter_mut() {
f(n);
}
}
CompiledNode::Var { default_value, .. } => {
if let Some(d) = default_value {
f(d);
}
}
#[cfg(feature = "ext-control")]
CompiledNode::Exists(_) => {}
#[cfg(feature = "error-handling")]
CompiledNode::Throw(_) => {}
CompiledNode::Missing(data) => {
for arg in data.args.iter_mut() {
if let CompiledMissingArg::Later(n) = arg {
f(n);
}
}
}
CompiledNode::MissingSome(data) => {
if let CompiledMissingMin::Later(n) = &mut data.min_present {
f(n);
}
if let CompiledMissingPaths::Later(n) = &mut data.paths {
f(n);
}
}
CompiledNode::InvalidArgs { .. } => {}
}
}
#[inline]
pub fn synthetic_value(value: OwnedDataValue) -> Self {
Self::value_with_id(SYNTHETIC_ID, value)
}
#[inline]
pub fn value_with_id(id: NodeId, value: OwnedDataValue) -> Self {
let lit = precompute_lit(&value);
CompiledNode::Value { id, value, lit }
}
pub fn operator_name(&self) -> Option<String> {
match self {
CompiledNode::BuiltinOperator { opcode, .. } => Some(opcode.as_str().to_string()),
CompiledNode::CustomOperator(data) => Some(data.name.clone()),
CompiledNode::Var { .. } => Some("var".to_string()),
#[cfg(feature = "ext-control")]
CompiledNode::Exists(_) => Some("exists".to_string()),
#[cfg(feature = "error-handling")]
CompiledNode::Throw(_) => Some("throw".to_string()),
CompiledNode::Missing(_) => Some("missing".to_string()),
CompiledNode::MissingSome(_) => Some("missing_some".to_string()),
_ => None,
}
}
}