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> {
|
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> {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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> {
|
||||||
|
34
src/error.rs
34
src/error.rs
@ -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."
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
src/lib.rs
14
src/lib.rs
@ -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>>();
|
||||||
|
|
||||||
|
26
src/value.rs
26
src/value.rs
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user