feat: error handling
This commit is contained in:
@@ -14,7 +14,7 @@ use hashbrown::HashMap;
|
||||
use nixjit_error::{Error, Result};
|
||||
use nixjit_ir::{self as ir, ArgIdx, ExprId, PrimOpId};
|
||||
use nixjit_lir as lir;
|
||||
use nixjit_value::{Const, Symbol, format_symbol};
|
||||
use nixjit_value::{Const, format_symbol};
|
||||
|
||||
pub use crate::value::*;
|
||||
|
||||
@@ -39,6 +39,9 @@ pub trait EvalContext: Sized {
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> (Vec<Value>, T);
|
||||
|
||||
/// Looks up a stack slot on the current stack frame.
|
||||
fn lookup_stack<'a>(&'a self, idx: usize) -> &'a Value;
|
||||
|
||||
/// Looks up an identifier in the current `with` scope chain.
|
||||
fn lookup_with<'a>(&'a self, ident: &str) -> Option<&'a Value>;
|
||||
|
||||
@@ -107,7 +110,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::AttrSet {
|
||||
);
|
||||
for (k, v) in self.dyns.iter() {
|
||||
let mut k = k.eval(ctx)?;
|
||||
k.coerce_to_string();
|
||||
k.coerce_to_string()?;
|
||||
let v_eval_result = v.eval(ctx)?;
|
||||
attrs.push_attr(k.unwrap_string(), v_eval_result)?;
|
||||
}
|
||||
@@ -135,14 +138,10 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::HasAttr {
|
||||
use ir::Attr::*;
|
||||
let mut val = self.lhs.eval(ctx)?;
|
||||
val.has_attr(self.rhs.iter().map(|attr| {
|
||||
Ok(match attr {
|
||||
Str(ident) => ident.clone(),
|
||||
Dynamic(expr) => {
|
||||
let mut val = expr.eval(ctx)?;
|
||||
val.coerce_to_string();
|
||||
val.unwrap_string()
|
||||
}
|
||||
})
|
||||
match attr {
|
||||
Str(ident) => Ok(Value::String(ident.clone())),
|
||||
Dynamic(expr) => expr.eval(ctx)
|
||||
}
|
||||
}))?;
|
||||
Ok(val)
|
||||
}
|
||||
@@ -153,42 +152,47 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::BinOp {
|
||||
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
|
||||
use ir::BinOpKind::*;
|
||||
let mut lhs = self.lhs.eval(ctx)?;
|
||||
if matches!((&self.kind, &lhs), (And, Value::Bool(false))) {
|
||||
return Ok(Value::Bool(false));
|
||||
} else if matches!((&self.kind, &lhs), (Or, Value::Bool(true))) {
|
||||
return Ok(Value::Bool(true))
|
||||
}
|
||||
let mut rhs = self.rhs.eval(ctx)?;
|
||||
match self.kind {
|
||||
Add => lhs.add(rhs)?,
|
||||
Sub => {
|
||||
rhs.neg();
|
||||
rhs.neg()?;
|
||||
lhs.add(rhs)?;
|
||||
}
|
||||
Mul => lhs.mul(rhs),
|
||||
Mul => lhs.mul(rhs)?,
|
||||
Div => lhs.div(rhs)?,
|
||||
Eq => Value::eq(&mut lhs, &rhs),
|
||||
Eq => Value::eq(&mut lhs, rhs),
|
||||
Neq => {
|
||||
Value::eq(&mut lhs, &rhs);
|
||||
lhs.not();
|
||||
Value::eq(&mut lhs, rhs);
|
||||
let _ = lhs.not();
|
||||
}
|
||||
Lt => lhs.lt(rhs),
|
||||
Lt => lhs.lt(rhs)?,
|
||||
Gt => {
|
||||
rhs.lt(lhs);
|
||||
rhs.lt(lhs)?;
|
||||
lhs = rhs;
|
||||
}
|
||||
Leq => {
|
||||
rhs.lt(lhs);
|
||||
rhs.not();
|
||||
rhs.lt(lhs)?;
|
||||
let _ = rhs.not();
|
||||
lhs = rhs;
|
||||
}
|
||||
Geq => {
|
||||
lhs.lt(rhs);
|
||||
lhs.not();
|
||||
lhs.lt(rhs)?;
|
||||
let _ = lhs.not()?;
|
||||
}
|
||||
And => lhs.and(rhs),
|
||||
Or => lhs.or(rhs),
|
||||
And => lhs.and(rhs)?,
|
||||
Or => lhs.or(rhs)?,
|
||||
Impl => {
|
||||
lhs.not();
|
||||
lhs.or(rhs);
|
||||
let _ = lhs.not();
|
||||
lhs.or(rhs)?;
|
||||
}
|
||||
Con => lhs.concat(rhs),
|
||||
Upd => lhs.update(rhs),
|
||||
Con => lhs.concat(rhs)?,
|
||||
Upd => lhs.update(rhs)?,
|
||||
PipeL => lhs.call(core::iter::once(Ok(rhs)), ctx)?,
|
||||
PipeR => {
|
||||
rhs.call(core::iter::once(Ok(lhs)), ctx)?;
|
||||
@@ -206,10 +210,10 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::UnOp {
|
||||
let mut rhs = self.rhs.eval(ctx)?;
|
||||
match self.kind {
|
||||
Neg => {
|
||||
rhs.neg();
|
||||
rhs.neg()?;
|
||||
}
|
||||
Not => {
|
||||
rhs.not();
|
||||
rhs.not()?;
|
||||
}
|
||||
};
|
||||
Ok(rhs)
|
||||
@@ -230,7 +234,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Select {
|
||||
Str(ident) => ident.clone(),
|
||||
Dynamic(expr) => {
|
||||
let mut val = expr.eval(ctx)?;
|
||||
val.coerce_to_string();
|
||||
val.coerce_to_string()?;
|
||||
val.unwrap_string()
|
||||
}
|
||||
})
|
||||
@@ -243,7 +247,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Select {
|
||||
Str(ident) => ident.clone(),
|
||||
Dynamic(expr) => {
|
||||
let mut val = expr.eval(ctx)?;
|
||||
val.coerce_to_string();
|
||||
val.coerce_to_string()?;
|
||||
val.unwrap_string()
|
||||
}
|
||||
})
|
||||
@@ -314,7 +318,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Assert {
|
||||
if cond {
|
||||
self.expr.eval(ctx)
|
||||
} else {
|
||||
Ok(Value::Catchable("assertion failed".to_string()))
|
||||
Err(Error::Catchable("assertion failed".into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,22 +327,11 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::ConcatStrings {
|
||||
/// Evaluates a `ConcatStrings` by evaluating each part, coercing it to a string,
|
||||
/// and then concatenating the results.
|
||||
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
|
||||
let mut parts = self
|
||||
.parts
|
||||
.iter()
|
||||
.map(|part| {
|
||||
let mut part = part.eval(ctx)?;
|
||||
part.coerce_to_string();
|
||||
Ok(part)
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?
|
||||
.into_iter();
|
||||
let init = parts.next().unwrap();
|
||||
let result = parts.fold(init, |mut a, b| {
|
||||
a.concat_string(b);
|
||||
a
|
||||
});
|
||||
Ok(result)
|
||||
let mut buf = String::new();
|
||||
for part in self.parts.iter() {
|
||||
buf.push_str(part.eval(ctx)?.coerce_to_string()?.as_ref().unwrap_string());
|
||||
}
|
||||
Ok(Value::String(buf))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,7 +369,7 @@ impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Var {
|
||||
|
||||
impl<Ctx: EvalContext> Evaluate<Ctx> for ir::Path {
|
||||
/// Evaluates a `Path`. (Currently a TODO).
|
||||
fn eval(&self, ctx: &mut Ctx) -> Result<Value> {
|
||||
fn eval(&self, _ctx: &mut Ctx) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user