use crate::ir::{IrInterpreter, IrPat, IrValue};
use crate::query::Used;
use crate::{IrError, Spanned};
use runestick::Span;
mod ir;
mod ir_assign;
mod ir_binary;
mod ir_branches;
mod ir_break;
mod ir_call;
mod ir_condition;
mod ir_decl;
mod ir_loop;
mod ir_object;
mod ir_scope;
mod ir_set;
mod ir_template;
mod ir_tuple;
mod ir_vec;
mod prelude;
pub trait IrEval {
type Output;
fn eval(
&self,
interp: &mut IrInterpreter<'_>,
used: Used,
) -> Result<Self::Output, IrEvalOutcome>;
}
pub(crate) trait ConstAs {
fn as_bool(&self, interp: &mut IrInterpreter<'_>, used: Used) -> Result<bool, IrEvalOutcome>;
}
pub(crate) trait Matches {
fn matches<S>(
&self,
compiler: &mut IrInterpreter<'_>,
value: IrValue,
used: Used,
spanned: S,
) -> Result<bool, IrEvalOutcome>
where
S: Spanned;
}
impl<T> ConstAs for T
where
T: IrEval<Output = IrValue>,
T: Spanned,
{
fn as_bool(&self, interp: &mut IrInterpreter<'_>, used: Used) -> Result<bool, IrEvalOutcome> {
let span = self.span();
let value = self
.eval(interp, used)?
.into_bool()
.map_err(|actual| IrError::expected::<_, bool>(span, &actual))?;
Ok(value)
}
}
impl Matches for IrPat {
fn matches<S>(
&self,
interp: &mut IrInterpreter<'_>,
value: IrValue,
_used: Used,
spanned: S,
) -> Result<bool, IrEvalOutcome>
where
S: Spanned,
{
match self {
IrPat::Ignore => Ok(true),
IrPat::Binding(name) => {
interp.scopes.decl(name, value, spanned)?;
Ok(true)
}
}
}
}
pub enum IrEvalOutcome {
NotConst(Span),
Error(IrError),
Break(Span, IrEvalBreak),
}
impl IrEvalOutcome {
pub(crate) fn not_const<S>(spanned: S) -> Self
where
S: Spanned,
{
Self::NotConst(spanned.span())
}
}
impl<T> From<T> for IrEvalOutcome
where
IrError: From<T>,
{
fn from(error: T) -> Self {
Self::Error(IrError::from(error))
}
}
pub enum IrEvalBreak {
Inherent,
Value(IrValue),
Label(Box<str>),
}