Errors refactoring - Code compiles.
This commit is contained in:
parent
743379c516
commit
c5f099340b
7 changed files with 34 additions and 42 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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: {:?}",
|
||||||
|
|
Loading…
Reference in a new issue