Add more errors

This commit is contained in:
Jeff 2024-03-06 17:32:31 -05:00
parent 799b5d838c
commit 4db3ae7cb8
6 changed files with 98 additions and 23 deletions

View File

@ -23,7 +23,11 @@ impl<'src> AbstractTree for Expression<'src> {
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { 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> { fn run(self, context: &Context) -> Result<Value, RuntimeError> {

View File

@ -1,4 +1,7 @@
use std::sync::Arc; use std::{
fmt::{self, Display, Formatter},
sync::Arc,
};
use crate::{ use crate::{
context::Context, context::Context,
@ -22,18 +25,31 @@ impl Identifier {
} }
impl AbstractTree for Identifier { impl AbstractTree for Identifier {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> { fn expected_type(&self, context: &Context) -> Result<Type, ValidationError> {
todo!() if let Some(value) = context.get(self)? {
Ok(value.r#type())
} else {
Err(ValidationError::VariableNotFound(self.clone()))
}
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { fn validate(&self, context: &Context) -> Result<(), ValidationError> {
todo!() if let Some(_) = context.get(self)? {
Ok(())
} else {
Err(ValidationError::VariableNotFound(self.clone()))
}
} }
fn run(self, _context: &Context) -> Result<Value, RuntimeError> { fn run(self, context: &Context) -> Result<Value, RuntimeError> {
todo!() let value = context.get(&self)?.unwrap_or_else(Value::none).clone();
// 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)
} }
} }

View File

@ -24,7 +24,12 @@ impl<'src> AbstractTree for Statement<'src> {
} }
fn validate(&self, _context: &Context) -> Result<(), ValidationError> { 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> { fn run(self, _context: &Context) -> Result<Value, RuntimeError> {

View File

@ -3,14 +3,26 @@ use std::sync::PoisonError;
use ariadne::{Label, Report, ReportKind}; use ariadne::{Label, Report, ReportKind};
use chumsky::{prelude::Rich, span::SimpleSpan}; use chumsky::{prelude::Rich, span::SimpleSpan};
use crate::{abstract_tree::Type, lexer::Token}; use crate::{
abstract_tree::{Identifier, Type},
lexer::Token,
};
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum Error { pub enum Error {
Parse { expected: String, span: SimpleSpan }, Parse {
Lex { expected: String, span: SimpleSpan }, expected: String,
span: SimpleSpan,
},
Lex {
expected: String,
span: SimpleSpan,
},
Runtime(RuntimeError), Runtime(RuntimeError),
Validation(ValidationError), Validation {
error: ValidationError,
span: SimpleSpan,
},
} }
impl From<Rich<'_, char>> for Error { impl From<Rich<'_, char>> for Error {
@ -60,6 +72,7 @@ pub enum ValidationError {
ExpectedBoolean, ExpectedBoolean,
RwLockPoison(RwLockPoisonError), RwLockPoison(RwLockPoisonError),
TypeCheck(TypeCheckError), TypeCheck(TypeCheckError),
VariableNotFound(Identifier),
} }
impl From<RwLockPoisonError> for ValidationError { impl From<RwLockPoisonError> for ValidationError {
@ -110,7 +123,18 @@ pub fn create_report<'a>(errors: &'a [Error]) -> Report<'a> {
); );
} }
Error::Runtime(_) => todo!(), 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."
)));
}
},
} }
} }

View File

@ -26,12 +26,14 @@ impl Interpreter {
let statements = parse(&tokens)?; let statements = parse(&tokens)?;
let errors = statements let errors = statements
.iter() .iter()
.filter_map(|(statement, _span)| { .filter_map(|(statement, span)| {
if let Some(error) = statement.validate(&self.context).err() { statement
Some(Error::Validation(error)) .validate(&self.context)
} else { .map_err(|validation_error| Error::Validation {
None error: validation_error,
} span: span.clone(),
})
.err()
}) })
.collect::<Vec<Error>>(); .collect::<Vec<Error>>();

View File

@ -6,7 +6,10 @@ use std::{
sync::{Arc, OnceLock}, 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(); pub static NONE: OnceLock<Value> = OnceLock::new();
@ -63,6 +66,27 @@ impl Value {
Value(Arc::new(ValueInner::Enum(name, variant))) 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> { pub fn as_boolean(&self) -> Result<bool, ValidationError> {
if let ValueInner::Boolean(boolean) = self.0.as_ref() { if let ValueInner::Boolean(boolean) = self.0.as_ref() {
return Ok(*boolean); return Ok(*boolean);