use super::{
BoolExpr, CallArg, CustomFieldAccess, FloatExpr, IntExpr, PanicExpr, StringExpr, TupleExpr,
UtfCodepointFunctionExpr, UtfCodepointListExpr,
};
use crate::plan::{FunctionInstantiation, HostCallSite, Step, UtfCodepointLocalId};
use ecow::EcoString;
use num_bigint::BigInt;
#[derive(Debug, Clone, PartialEq)]
pub struct UtfCodepointExpr {
kind: UtfCodepointExprKind,
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum UtfCodepointExprKind {
LocalGet {
local: UtfCodepointLocalId,
name: EcoString,
},
Call {
function: FunctionInstantiation,
args: Vec<CallArg>,
site: HostCallSite,
},
FunctionCall {
function: Box<UtfCodepointFunctionExpr>,
args: Vec<CallArg>,
site: HostCallSite,
},
TupleIndex {
tuple: Box<TupleExpr>,
index: usize,
},
CustomField(CustomFieldAccess),
ListIndex {
list: Box<UtfCodepointListExpr>,
index: usize,
},
Panic(PanicExpr),
BoolCase {
subject: Box<BoolExpr>,
true_: Box<UtfCodepointExpr>,
false_: Box<UtfCodepointExpr>,
},
IntCase {
subject: Box<IntExpr>,
clauses: Vec<(BigInt, UtfCodepointExpr)>,
fallback: Box<UtfCodepointExpr>,
},
StringCase {
subject: Box<StringExpr>,
clauses: Vec<(EcoString, UtfCodepointExpr)>,
fallback: Box<UtfCodepointExpr>,
},
FloatCase {
subject: Box<FloatExpr>,
clauses: Vec<(f64, UtfCodepointExpr)>,
fallback: Box<UtfCodepointExpr>,
},
Block {
steps: Vec<Step>,
return_: Box<UtfCodepointExpr>,
},
}
impl UtfCodepointExpr {
pub(crate) fn local_get(local: UtfCodepointLocalId, name: EcoString) -> Self {
Self::new(UtfCodepointExprKind::LocalGet { local, name })
}
#[cfg(test)]
pub(crate) fn call(function: FunctionInstantiation, args: Vec<CallArg>) -> Self {
Self::call_at(function, args, HostCallSite::unknown())
}
pub(crate) fn call_at(
function: FunctionInstantiation,
args: Vec<CallArg>,
site: HostCallSite,
) -> Self {
Self::new(UtfCodepointExprKind::Call {
function,
args,
site,
})
}
#[cfg(test)]
pub(crate) fn function_call(function: UtfCodepointFunctionExpr, args: Vec<CallArg>) -> Self {
Self::function_call_at(function, args, HostCallSite::unknown())
}
pub(crate) fn function_call_at(
function: UtfCodepointFunctionExpr,
args: Vec<CallArg>,
site: HostCallSite,
) -> Self {
Self::new(UtfCodepointExprKind::FunctionCall {
function: Box::new(function),
args,
site,
})
}
pub(crate) fn tuple_index(tuple: TupleExpr, index: usize) -> Self {
Self::new(UtfCodepointExprKind::TupleIndex {
tuple: Box::new(tuple),
index,
})
}
pub(crate) fn custom_field(access: CustomFieldAccess) -> Self {
Self::new(UtfCodepointExprKind::CustomField(access))
}
pub(crate) fn list_index(list: UtfCodepointListExpr, index: usize) -> Self {
Self::new(UtfCodepointExprKind::ListIndex {
list: Box::new(list),
index,
})
}
pub(crate) fn panic(panic: PanicExpr) -> Self {
Self::new(UtfCodepointExprKind::Panic(panic))
}
pub(crate) fn bool_case(subject: BoolExpr, true_: Self, false_: Self) -> Self {
Self::new(UtfCodepointExprKind::BoolCase {
subject: Box::new(subject),
true_: Box::new(true_),
false_: Box::new(false_),
})
}
pub(crate) fn int_case(subject: IntExpr, clauses: Vec<(BigInt, Self)>, fallback: Self) -> Self {
Self::new(UtfCodepointExprKind::IntCase {
subject: Box::new(subject),
clauses,
fallback: Box::new(fallback),
})
}
pub(crate) fn string_case(
subject: StringExpr,
clauses: Vec<(EcoString, Self)>,
fallback: Self,
) -> Self {
Self::new(UtfCodepointExprKind::StringCase {
subject: Box::new(subject),
clauses,
fallback: Box::new(fallback),
})
}
pub(crate) fn float_case(
subject: FloatExpr,
clauses: Vec<(f64, Self)>,
fallback: Self,
) -> Self {
Self::new(UtfCodepointExprKind::FloatCase {
subject: Box::new(subject),
clauses,
fallback: Box::new(fallback),
})
}
pub(crate) fn block(steps: Vec<Step>, return_: Self) -> Self {
Self::new(UtfCodepointExprKind::Block {
steps,
return_: Box::new(return_),
})
}
pub(crate) fn kind(&self) -> &UtfCodepointExprKind {
&self.kind
}
fn new(kind: UtfCodepointExprKind) -> Self {
Self { kind }
}
}
#[cfg(test)]
mod tests {
use super::{UtfCodepointExpr, UtfCodepointExprKind};
use crate::plan::{
BoolExpr, Expr, FunctionInstantiation, FunctionShape, IntExpr, PanicExpr, PanicSite, Step,
StringExpr, TupleExpr, TupleLocalId, UtfCodepointFunctionExpr,
UtfCodepointFunctionReference, UtfCodepointListExpr, UtfCodepointListItem,
UtfCodepointListLocalId, UtfCodepointLocalId, ValueShape, ValueType,
monomorphic_function_instantiation,
};
#[test]
fn utf_codepoint_expr_kind_accessors() {
assert_eq!(
value().kind(),
&UtfCodepointExprKind::LocalGet {
local: UtfCodepointLocalId(0),
name: "value".into(),
},
);
assert_eq!(
UtfCodepointExpr::call(function_instantiation(), Vec::new()).kind(),
&UtfCodepointExprKind::Call {
function: function_instantiation(),
args: Vec::new(),
site: crate::plan::HostCallSite::unknown(),
},
);
assert_eq!(
UtfCodepointExpr::function_call(function(), Vec::new()).kind(),
&UtfCodepointExprKind::FunctionCall {
function: Box::new(function()),
args: Vec::new(),
site: crate::plan::HostCallSite::unknown(),
},
);
assert_eq!(
UtfCodepointExpr::tuple_index(tuple(), 0).kind(),
&UtfCodepointExprKind::TupleIndex {
tuple: Box::new(tuple()),
index: 0,
},
);
assert_eq!(
UtfCodepointExpr::list_index(list(), 0).kind(),
&UtfCodepointExprKind::ListIndex {
list: Box::new(list()),
index: 0,
},
);
let panic = PanicExpr::panic_at(None, PanicSite::unknown());
assert_eq!(
UtfCodepointExpr::panic(panic.clone()).kind(),
&UtfCodepointExprKind::Panic(panic),
);
assert_eq!(
UtfCodepointExpr::bool_case(BoolExpr::value(true), value(), value()).kind(),
&UtfCodepointExprKind::BoolCase {
subject: Box::new(BoolExpr::value(true)),
true_: Box::new(value()),
false_: Box::new(value()),
},
);
assert_eq!(
UtfCodepointExpr::int_case(
IntExpr::value(1.into()),
vec![(1.into(), value())],
value(),
)
.kind(),
&UtfCodepointExprKind::IntCase {
subject: Box::new(IntExpr::value(1.into())),
clauses: vec![(1.into(), value())],
fallback: Box::new(value()),
},
);
assert_eq!(
UtfCodepointExpr::string_case(
StringExpr::value("one".into()),
vec![("one".into(), value())],
value(),
)
.kind(),
&UtfCodepointExprKind::StringCase {
subject: Box::new(StringExpr::value("one".into())),
clauses: vec![("one".into(), value())],
fallback: Box::new(value()),
},
);
assert_eq!(
UtfCodepointExpr::float_case(
crate::plan::FloatExpr::value(1.0),
vec![(1.0, value())],
value(),
)
.kind(),
&UtfCodepointExprKind::FloatCase {
subject: Box::new(crate::plan::FloatExpr::value(1.0)),
clauses: vec![(1.0, value())],
fallback: Box::new(value()),
},
);
assert_eq!(
UtfCodepointExpr::block(
vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
value(),
)
.kind(),
&UtfCodepointExprKind::Block {
steps: vec![Step::evaluate(Expr::int(IntExpr::value(1.into())))],
return_: Box::new(value()),
},
);
}
fn value() -> UtfCodepointExpr {
UtfCodepointExpr::local_get(UtfCodepointLocalId(0), "value".into())
}
fn function() -> UtfCodepointFunctionExpr {
UtfCodepointFunctionExpr::reference(UtfCodepointFunctionReference::new(
function_instantiation(),
))
}
fn function_instantiation() -> FunctionInstantiation {
monomorphic_function_instantiation(
0,
FunctionShape::new(vec![ValueShape::UtfCodepoint], ValueShape::UtfCodepoint),
)
}
fn tuple() -> TupleExpr {
TupleExpr::local_get(
TupleLocalId(0),
"pair".into(),
vec![ValueType::UtfCodepoint],
)
}
fn list() -> UtfCodepointListExpr {
UtfCodepointListExpr::local_get(
UtfCodepointListItem,
UtfCodepointListLocalId(0),
"values".into(),
)
}
}