Errors refactoring - Code compiles.

This commit is contained in:
Emmanuel BENOîT 2023-01-04 07:58:44 +01:00
parent 743379c516
commit c5f099340b
7 changed files with 34 additions and 42 deletions

View file

@ -114,11 +114,6 @@ pub struct ErrorHandler {
} }
impl ErrorHandler { impl ErrorHandler {
/// Check whether this handler reported an error.
pub fn had_error(&self) -> Option<ErrorKind> {
self.had_error
}
/// Report an error. /// Report an error.
pub fn report(&mut self, error: SloxError) { pub fn report(&mut self, error: SloxError) {
self.had_error = Some(error.kind); self.had_error = Some(error.kind);
@ -131,8 +126,8 @@ impl ErrorHandler {
match result { match result {
Ok(v) => Ok(v), Ok(v) => Ok(v),
Err(e) => { Err(e) => {
self.report(e);
let fe = SloxError::stage_failed(e.kind); let fe = SloxError::stage_failed(e.kind);
self.report(e);
println!("{fe}"); println!("{fe}");
Err(fe) Err(fe)
} }

View file

@ -1,6 +1,6 @@
use std::{cell::RefCell, fmt::Debug, rc::Rc}; use std::{cell::RefCell, fmt::Debug, rc::Rc};
use crate::errors::InterpreterError; use crate::errors::SloxResult;
use super::{EnvironmentRef, Value}; use super::{EnvironmentRef, Value};
@ -11,11 +11,7 @@ pub trait Callable: Debug + ToString {
/// Run the callable in the execution environment with the specified /// Run the callable in the execution environment with the specified
/// arguments. /// arguments.
fn call( fn call(&self, environment: &EnvironmentRef, arguments: Vec<Value>) -> SloxResult<Value>;
&self,
environment: &EnvironmentRef,
arguments: Vec<Value>,
) -> Result<Value, InterpreterError>;
} }
/// A reference to a callable. /// A reference to a callable.

View file

@ -1,6 +1,9 @@
use std::{cell::RefCell, collections::HashMap, rc::Rc}; use std::{cell::RefCell, collections::HashMap, rc::Rc};
use crate::{errors::InterpreterError, tokens::Token}; use crate::{
errors::{ErrorKind, SloxError, SloxResult},
tokens::Token,
};
use super::{native_fn, CallableRef, Value}; use super::{native_fn, CallableRef, Value};
@ -45,11 +48,12 @@ impl Environment {
} }
/// Define a new variable. /// Define a new variable.
pub fn define(&mut self, name: &Token, value: Variable) -> Result<(), InterpreterError> { pub fn define(&mut self, name: &Token, value: Variable) -> SloxResult<()> {
if self.values.contains_key(&name.lexeme as &str) { if self.values.contains_key(&name.lexeme as &str) {
Err(InterpreterError::new( Err(SloxError::with_token(
ErrorKind::Runtime,
name, name,
&format!("variable '{}' already defined in scope", name.lexeme), format!("variable '{}' already defined in scope", name.lexeme),
)) ))
} else { } else {
self.values.insert(name.lexeme.clone(), value); self.values.insert(name.lexeme.clone(), value);
@ -58,33 +62,36 @@ impl Environment {
} }
/// Get the value of a variable. /// Get the value of a variable.
pub fn get(&self, name: &Token) -> Result<Value, InterpreterError> { pub fn get(&self, name: &Token) -> SloxResult<Value> {
match self.values.get(&name.lexeme as &str) { match self.values.get(&name.lexeme as &str) {
None => match &self.enclosing { None => match &self.enclosing {
None => Err(InterpreterError::new( None => Err(SloxError::with_token(
ErrorKind::Runtime,
name, name,
&format!("undefined variable '{}'", name.lexeme), format!("undefined variable '{}'", name.lexeme),
)), )),
Some(parent) => parent.borrow().get(name), Some(parent) => parent.borrow().get(name),
}, },
Some(None) => Err(InterpreterError::new( Some(None) => Err(SloxError::with_token(
ErrorKind::Runtime,
name, name,
&format!("variable '{}' has not been initialized", name.lexeme), format!("variable '{}' has not been initialized", name.lexeme),
)), )),
Some(Some(value)) => Ok(value.clone()), Some(Some(value)) => Ok(value.clone()),
} }
} }
/// Assign a value to an existing variable. /// Assign a value to an existing variable.
pub fn assign(&mut self, name: &Token, value: Value) -> Result<(), InterpreterError> { pub fn assign(&mut self, name: &Token, value: Value) -> SloxResult<()> {
if self.values.contains_key(&name.lexeme as &str) { if self.values.contains_key(&name.lexeme as &str) {
self.values.insert(name.lexeme.clone(), Some(value)); self.values.insert(name.lexeme.clone(), Some(value));
Ok(()) Ok(())
} else { } else {
match &mut self.enclosing { match &mut self.enclosing {
None => Err(InterpreterError::new( None => Err(SloxError::with_token(
ErrorKind::Runtime,
name, name,
&format!("undefined variable '{}'", name.lexeme), format!("undefined variable '{}'", name.lexeme),
)), )),
Some(parent) => parent.borrow_mut().assign(name, value), Some(parent) => parent.borrow_mut().assign(name, value),
} }

View file

@ -4,7 +4,7 @@ use itertools::izip;
use crate::{ use crate::{
ast, ast,
errors::InterpreterError, errors::SloxResult,
interpreter::{Environment, Interpretable, InterpreterFlowControl}, interpreter::{Environment, Interpretable, InterpreterFlowControl},
tokens::Token, tokens::Token,
}; };
@ -39,11 +39,7 @@ impl Callable for Function {
self.params.len() self.params.len()
} }
fn call( fn call(&self, environment: &EnvironmentRef, arguments: Vec<Value>) -> SloxResult<Value> {
&self,
environment: &EnvironmentRef,
arguments: Vec<Value>,
) -> Result<Value, InterpreterError> {
assert_eq!(arguments.len(), self.arity()); assert_eq!(arguments.len(), self.arity());
let param_env = Environment::create_child(environment); let param_env = Environment::create_child(environment);
for (arg, value) in izip!(self.params.iter(), arguments.into_iter()) { for (arg, value) in izip!(self.params.iter(), arguments.into_iter()) {

View file

@ -4,7 +4,7 @@ use std::{
time::{SystemTime, UNIX_EPOCH}, time::{SystemTime, UNIX_EPOCH},
}; };
use crate::errors::InterpreterError; use crate::errors::SloxResult;
use super::{Callable, CallableRef, EnvironmentRef, Value}; use super::{Callable, CallableRef, EnvironmentRef, Value};
@ -20,11 +20,7 @@ impl Callable for Clock {
0 0
} }
fn call( fn call(&self, _environment: &EnvironmentRef, _arguments: Vec<Value>) -> SloxResult<Value> {
&self,
_environment: &EnvironmentRef,
_arguments: Vec<Value>,
) -> Result<Value, InterpreterError> {
let now = SystemTime::now(); let now = SystemTime::now();
let since_epoch = now let since_epoch = now
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)

View file

@ -517,7 +517,11 @@ impl Parser {
value: Box::new(value), value: Box::new(value),
}) })
} else { } else {
self.error("invalid assignment target") Err(SloxError::with_token(
ErrorKind::Parse,
&equals,
"invalid assignment target".to_owned(),
))
} }
} else { } else {
Ok(expr) Ok(expr)

View file

@ -145,7 +145,7 @@ impl Scanner {
// Identifiers // Identifiers
ch if ch.is_ascii_alphabetic() => self.identifier(), ch if ch.is_ascii_alphabetic() => self.identifier(),
// Anything else is an error // Anything else is an error
ch => return self.error("unexpected character".to_owned()), _ => return self.error("unexpected character".to_owned()),
} }
} }
@ -167,8 +167,7 @@ impl Scanner {
} else { } else {
self.current += 1; // Last '"' self.current += 1; // Last '"'
let value = self.get_substring(self.start + 1, self.current - 1); let value = self.get_substring(self.start + 1, self.current - 1);
self.add_token(TokenType::String(value)); self.add_token(TokenType::String(value))
Ok(())
} }
} }
@ -187,8 +186,7 @@ impl Scanner {
let tok_string = self.get_substring(self.start, self.current); let tok_string = self.get_substring(self.start, self.current);
match tok_string.parse::<f64>() { match tok_string.parse::<f64>() {
Ok(value) => { Ok(value) => {
self.add_token(TokenType::Number(value)); self.add_token(TokenType::Number(value))
Ok(())
} }
Err(e) => self.error(format!( Err(e) => self.error(format!(
"Could not parse {} as a floating point number: {:?}", "Could not parse {} as a floating point number: {:?}",