diff options
Diffstat (limited to 'tvix/eval/src')
-rw-r--r-- | tvix/eval/src/compiler.rs | 14 | ||||
-rw-r--r-- | tvix/eval/src/errors.rs | 16 | ||||
-rw-r--r-- | tvix/eval/src/eval.rs | 4 | ||||
-rw-r--r-- | tvix/eval/src/value/attrs.rs | 12 | ||||
-rw-r--r-- | tvix/eval/src/value/mod.rs | 27 | ||||
-rw-r--r-- | tvix/eval/src/vm.rs | 29 |
6 files changed, 62 insertions, 40 deletions
diff --git a/tvix/eval/src/compiler.rs b/tvix/eval/src/compiler.rs index 0718f45ba777..92f04c84dcbe 100644 --- a/tvix/eval/src/compiler.rs +++ b/tvix/eval/src/compiler.rs @@ -19,7 +19,7 @@ use rowan::ast::AstNode; use std::path::{Path, PathBuf}; use crate::chunk::Chunk; -use crate::errors::{Error, EvalResult}; +use crate::errors::{ErrorKind, EvalResult}; use crate::opcode::{CodeIdx, OpCode}; use crate::value::Value; use crate::warnings::{EvalWarning, WarningKind}; @@ -155,7 +155,7 @@ impl Compiler { Path::new(&raw_path).to_owned() } else if raw_path.starts_with('~') { let mut buf = dirs::home_dir().ok_or_else(|| { - Error::PathResolution("failed to determine home directory".into()) + ErrorKind::PathResolution("failed to determine home directory".into()) })?; buf.push(&raw_path); @@ -435,7 +435,7 @@ impl Compiler { match self.resolve_local(ident.ident_token().unwrap().text()) { Some(idx) => self.chunk.push_op(OpCode::OpGetLocal(idx)), - None => return Err(Error::UnknownStaticVariable(ident)), + None => return Err(ErrorKind::UnknownStaticVariable(ident).into()), }; } } @@ -663,7 +663,7 @@ impl Compiler { Some(idx) => self.chunk.push_op(OpCode::OpGetLocal(idx)), None => { if self.scope.with_stack.is_empty() { - return Err(Error::UnknownStaticVariable(node)); + return Err(ErrorKind::UnknownStaticVariable(node).into()); } // Variable needs to be dynamically resolved @@ -836,7 +836,7 @@ fn expr_str_to_string(expr: ast::Str) -> EvalResult<String> { } } - return Err(Error::DynamicKeyInLet(expr.syntax().clone())); + return Err(ErrorKind::DynamicKeyInLet(expr.syntax().clone()).into()); } /// Convert a single identifier path fragment to a string if possible, @@ -852,7 +852,7 @@ fn attr_to_string(node: ast::Attr) -> EvalResult<String> { // inside (i.e. `let ${"a"} = 1; in a` is valid). ast::Attr::Dynamic(ref dynamic) => match dynamic.expr().unwrap() { ast::Expr::Str(s) => expr_str_to_string(s), - _ => Err(Error::DynamicKeyInLet(node.syntax().clone())), + _ => Err(ErrorKind::DynamicKeyInLet(node.syntax().clone()).into()), }, } } @@ -868,7 +868,7 @@ pub fn compile(expr: ast::Expr, location: Option<PathBuf>) -> EvalResult<Compila let mut root_dir = match location { Some(dir) => Ok(dir), None => std::env::current_dir().map_err(|e| { - Error::PathResolution(format!("could not determine current directory: {}", e)) + ErrorKind::PathResolution(format!("could not determine current directory: {}", e)) }), }?; diff --git a/tvix/eval/src/errors.rs b/tvix/eval/src/errors.rs index 4aba877f4979..01a5e8144906 100644 --- a/tvix/eval/src/errors.rs +++ b/tvix/eval/src/errors.rs @@ -1,7 +1,7 @@ use std::fmt::Display; #[derive(Debug)] -pub enum Error { +pub enum ErrorKind { DuplicateAttrsKey { key: String, }, @@ -37,9 +37,21 @@ pub enum Error { AssertionFailed, } +#[derive(Debug)] +pub struct Error { + pub node: Option<rnix::SyntaxNode>, + pub kind: ErrorKind, +} + +impl From<ErrorKind> for Error { + fn from(kind: ErrorKind) -> Self { + Error { node: None, kind } + } +} + impl Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "{:?}", self) + writeln!(f, "{:?}", self.kind) } } diff --git a/tvix/eval/src/eval.rs b/tvix/eval/src/eval.rs index cd11d3289b12..8f2946e6cc84 100644 --- a/tvix/eval/src/eval.rs +++ b/tvix/eval/src/eval.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use rnix; use crate::{ - errors::{Error, EvalResult}, + errors::{ErrorKind, EvalResult}, value::Value, }; @@ -15,7 +15,7 @@ pub fn interpret(code: &str, location: Option<PathBuf>) -> EvalResult<Value> { for err in errors { eprintln!("parse error: {}", err); } - return Err(Error::ParseErrors(errors.to_vec())); + return Err(ErrorKind::ParseErrors(errors.to_vec()).into()); } // If we've reached this point, there are no errors. diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs index f614128550f3..319f6bdfa9bb 100644 --- a/tvix/eval/src/value/attrs.rs +++ b/tvix/eval/src/value/attrs.rs @@ -10,7 +10,7 @@ use std::collections::BTreeMap; use std::fmt::Display; use std::rc::Rc; -use crate::errors::{Error, EvalResult}; +use crate::errors::{ErrorKind, EvalResult}; use super::string::NixString; use super::Value; @@ -304,9 +304,10 @@ fn attempt_optimise_kv(slice: &mut [Value]) -> Option<NixAttrs> { // checking against duplicate keys. fn set_attr(attrs: &mut NixAttrs, key: NixString, value: Value) -> EvalResult<()> { match attrs.0.map_mut().entry(key) { - btree_map::Entry::Occupied(entry) => Err(Error::DuplicateAttrsKey { + btree_map::Entry::Occupied(entry) => Err(ErrorKind::DuplicateAttrsKey { key: entry.key().as_str().to_string(), - }), + } + .into()), btree_map::Entry::Vacant(entry) => { entry.insert(value); @@ -365,9 +366,10 @@ fn set_nested_attr( } _ => { - return Err(Error::DuplicateAttrsKey { + return Err(ErrorKind::DuplicateAttrsKey { key: entry.key().as_str().to_string(), - }) + } + .into()) } }, } diff --git a/tvix/eval/src/value/mod.rs b/tvix/eval/src/value/mod.rs index 6c0473fa6618..f054191f6716 100644 --- a/tvix/eval/src/value/mod.rs +++ b/tvix/eval/src/value/mod.rs @@ -7,7 +7,7 @@ mod attrs; mod list; mod string; -use crate::errors::{Error, EvalResult}; +use crate::errors::{ErrorKind, EvalResult}; pub use attrs::NixAttrs; pub use list::NixList; pub use string::NixString; @@ -55,50 +55,55 @@ impl Value { pub fn as_bool(&self) -> EvalResult<bool> { match self { Value::Bool(b) => Ok(*b), - other => Err(Error::TypeError { + other => Err(ErrorKind::TypeError { expected: "bool", actual: other.type_of(), - }), + } + .into()), } } pub fn as_attrs(&self) -> EvalResult<&NixAttrs> { match self { Value::Attrs(attrs) => Ok(attrs), - other => Err(Error::TypeError { + other => Err(ErrorKind::TypeError { expected: "set", actual: other.type_of(), - }), + } + .into()), } } pub fn to_string(self) -> EvalResult<NixString> { match self { Value::String(s) => Ok(s), - other => Err(Error::TypeError { + other => Err(ErrorKind::TypeError { expected: "string", actual: other.type_of(), - }), + } + .into()), } } pub fn to_attrs(self) -> EvalResult<Rc<NixAttrs>> { match self { Value::Attrs(s) => Ok(s), - other => Err(Error::TypeError { + other => Err(ErrorKind::TypeError { expected: "set", actual: other.type_of(), - }), + } + .into()), } } pub fn to_list(self) -> EvalResult<NixList> { match self { Value::List(l) => Ok(l), - other => Err(Error::TypeError { + other => Err(ErrorKind::TypeError { expected: "list", actual: other.type_of(), - }), + } + .into()), } } diff --git a/tvix/eval/src/vm.rs b/tvix/eval/src/vm.rs index cf70fda30747..7a6a6454eadc 100644 --- a/tvix/eval/src/vm.rs +++ b/tvix/eval/src/vm.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use crate::{ chunk::Chunk, - errors::{Error, EvalResult}, + errors::{ErrorKind, EvalResult}, opcode::OpCode, value::{NixAttrs, NixList, Value}, }; @@ -38,14 +38,14 @@ macro_rules! arithmetic_op { (Value::Integer(i1), Value::Float(f2)) => Value::Float(i1 as f64 $op f2), (Value::Float(f1), Value::Integer(i2)) => Value::Float(f1 $op i2 as f64), - (v1, v2) => return Err(Error::TypeError { + (v1, v2) => return Err(ErrorKind::TypeError { expected: "number (either int or float)", actual: if v1.is_number() { v2.type_of() } else { v1.type_of() }, - }), + }.into()), } }}; } @@ -65,10 +65,10 @@ macro_rules! cmp_op { (Value::Float(f1), Value::Integer(i2)) => f1 $op (i2 as f64), (Value::String(s1), Value::String(s2)) => s1 $op s2, - (lhs, rhs) => return Err(Error::Incomparable { + (lhs, rhs) => return Err(ErrorKind::Incomparable { lhs: lhs.type_of(), rhs: rhs.type_of(), - }), + }.into()), }; $self.push(Value::Bool(result)); @@ -136,10 +136,11 @@ impl VM { Value::Integer(i) => self.push(Value::Integer(-i)), Value::Float(f) => self.push(Value::Float(-f)), v => { - return Err(Error::TypeError { + return Err(ErrorKind::TypeError { expected: "number (either int or float)", actual: v.type_of(), - }) + } + .into()) } }, @@ -177,9 +178,10 @@ impl VM { Some(value) => self.push(value.clone()), None => { - return Err(Error::AttributeNotFound { + return Err(ErrorKind::AttributeNotFound { name: key.as_str().to_string(), - }) + } + .into()) } } } @@ -255,10 +257,11 @@ impl VM { OpCode::OpAssertBool => { let val = self.peek(0); if !val.is_bool() { - return Err(Error::TypeError { + return Err(ErrorKind::TypeError { expected: "bool", actual: val.type_of(), - }); + } + .into()); } } @@ -302,12 +305,12 @@ impl VM { } } - return Err(Error::UnknownDynamicVariable(ident.to_string())); + return Err(ErrorKind::UnknownDynamicVariable(ident.to_string()).into()); } OpCode::OpAssert => { if !self.pop().as_bool()? { - return Err(Error::AssertionFailed); + return Err(ErrorKind::AssertionFailed.into()); } } } |