Add more errors
This commit is contained in:
parent
799b5d838c
commit
4db3ae7cb8
@ -23,7 +23,11 @@ impl<'src> AbstractTree for Expression<'src> {
|
||||
}
|
||||
|
||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
todo!()
|
||||
match self {
|
||||
Expression::Identifier(identifier) => identifier.validate(_context),
|
||||
Expression::Logic(logic) => logic.validate(_context),
|
||||
Expression::Value(value_node) => value_node.validate(_context),
|
||||
}
|
||||
}
|
||||
|
||||
fn run(self, context: &Context) -> Result<Value, RuntimeError> {
|
||||
|
@ -1,4 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::{
|
||||
fmt::{self, Display, Formatter},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
context::Context,
|
||||
@ -22,18 +25,31 @@ impl Identifier {
|
||||
}
|
||||
|
||||
impl AbstractTree for Identifier {
|
||||
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
|
||||
todo!()
|
||||
fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
|
||||
if let Some(value) = context.get(self)? {
|
||||
Ok(value.r#type())
|
||||
} else {
|
||||
Err(ValidationError::VariableNotFound(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
todo!()
|
||||
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
|
||||
if let Some(_) = context.get(self)? {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ValidationError::VariableNotFound(self.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
todo!()
|
||||
// let value = context.get(&self)?.unwrap_or_else(Value::none).clone();
|
||||
fn run(self, context: &Context) -> Result<Value, RuntimeError> {
|
||||
let value = context.get(&self)?.unwrap_or_else(Value::none).clone();
|
||||
|
||||
// Ok(value)
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Identifier {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,12 @@ impl<'src> AbstractTree for Statement<'src> {
|
||||
}
|
||||
|
||||
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
|
||||
todo!()
|
||||
match self {
|
||||
Statement::Assignment(assignment) => assignment.validate(_context),
|
||||
Statement::Block(_) => todo!(),
|
||||
Statement::Expression(expression) => expression.validate(_context),
|
||||
Statement::Loop(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn run(self, _context: &Context) -> Result<Value, RuntimeError> {
|
||||
|
34
src/error.rs
34
src/error.rs
@ -3,14 +3,26 @@ use std::sync::PoisonError;
|
||||
use ariadne::{Label, Report, ReportKind};
|
||||
use chumsky::{prelude::Rich, span::SimpleSpan};
|
||||
|
||||
use crate::{abstract_tree::Type, lexer::Token};
|
||||
use crate::{
|
||||
abstract_tree::{Identifier, Type},
|
||||
lexer::Token,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
Parse { expected: String, span: SimpleSpan },
|
||||
Lex { expected: String, span: SimpleSpan },
|
||||
Parse {
|
||||
expected: String,
|
||||
span: SimpleSpan,
|
||||
},
|
||||
Lex {
|
||||
expected: String,
|
||||
span: SimpleSpan,
|
||||
},
|
||||
Runtime(RuntimeError),
|
||||
Validation(ValidationError),
|
||||
Validation {
|
||||
error: ValidationError,
|
||||
span: SimpleSpan,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<Rich<'_, char>> for Error {
|
||||
@ -60,6 +72,7 @@ pub enum ValidationError {
|
||||
ExpectedBoolean,
|
||||
RwLockPoison(RwLockPoisonError),
|
||||
TypeCheck(TypeCheckError),
|
||||
VariableNotFound(Identifier),
|
||||
}
|
||||
|
||||
impl From<RwLockPoisonError> for ValidationError {
|
||||
@ -110,7 +123,18 @@ pub fn create_report<'a>(errors: &'a [Error]) -> Report<'a> {
|
||||
);
|
||||
}
|
||||
Error::Runtime(_) => todo!(),
|
||||
Error::Validation(_) => todo!(),
|
||||
Error::Validation { error, span } => match error {
|
||||
ValidationError::ExpectedBoolean => todo!(),
|
||||
ValidationError::RwLockPoison(_) => todo!(),
|
||||
ValidationError::TypeCheck(_) => todo!(),
|
||||
ValidationError::VariableNotFound(identifier) => {
|
||||
report =
|
||||
report
|
||||
.with_label(Label::new(span.start..span.end).with_message(format!(
|
||||
"The variable {identifier} does not exist."
|
||||
)));
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
14
src/lib.rs
14
src/lib.rs
@ -26,12 +26,14 @@ impl Interpreter {
|
||||
let statements = parse(&tokens)?;
|
||||
let errors = statements
|
||||
.iter()
|
||||
.filter_map(|(statement, _span)| {
|
||||
if let Some(error) = statement.validate(&self.context).err() {
|
||||
Some(Error::Validation(error))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.filter_map(|(statement, span)| {
|
||||
statement
|
||||
.validate(&self.context)
|
||||
.map_err(|validation_error| Error::Validation {
|
||||
error: validation_error,
|
||||
span: span.clone(),
|
||||
})
|
||||
.err()
|
||||
})
|
||||
.collect::<Vec<Error>>();
|
||||
|
||||
|
26
src/value.rs
26
src/value.rs
@ -6,7 +6,10 @@ use std::{
|
||||
sync::{Arc, OnceLock},
|
||||
};
|
||||
|
||||
use crate::{abstract_tree::Identifier, error::ValidationError};
|
||||
use crate::{
|
||||
abstract_tree::{Identifier, Type},
|
||||
error::ValidationError,
|
||||
};
|
||||
|
||||
pub static NONE: OnceLock<Value> = OnceLock::new();
|
||||
|
||||
@ -63,6 +66,27 @@ impl Value {
|
||||
Value(Arc::new(ValueInner::Enum(name, variant)))
|
||||
}
|
||||
|
||||
pub fn r#type(&self) -> Type {
|
||||
match self.0.as_ref() {
|
||||
ValueInner::Boolean(_) => Type::Boolean,
|
||||
ValueInner::Float(_) => Type::Float,
|
||||
ValueInner::Integer(_) => Type::Integer,
|
||||
ValueInner::List(values) => {
|
||||
let mut types = Vec::with_capacity(values.len());
|
||||
|
||||
for value in values {
|
||||
types.push(value.r#type());
|
||||
}
|
||||
|
||||
Type::ListExact(types)
|
||||
}
|
||||
ValueInner::Map(_) => Type::Map,
|
||||
ValueInner::Range(_) => Type::Range,
|
||||
ValueInner::String(_) => Type::String,
|
||||
ValueInner::Enum(name, _) => Type::Custom(name.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_boolean(&self) -> Result<bool, ValidationError> {
|
||||
if let ValueInner::Boolean(boolean) = self.0.as_ref() {
|
||||
return Ok(*boolean);
|
||||
|
Loading…
Reference in New Issue
Block a user