Shrink error Context and reduce cloning
This commit is contained in:
+56
-27
@@ -1,56 +1,85 @@
|
|||||||
use std::{cell::RefCell, error::Error, fmt::Display, ops::Range, rc::Rc};
|
use std::{cell::RefCell, error::Error, fmt::Display, ops::Range};
|
||||||
|
|
||||||
use crate::world::World;
|
use crate::world::World;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
pub enum Context<'a> {
|
||||||
pub struct Context {
|
Base(Box<RefCell<Vec<CompileMessage>>>),
|
||||||
messages: Rc<RefCell<Vec<CompileMessage>>>,
|
With(&'a Context<'a>, ContextInfo<'a>),
|
||||||
location: Location,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
pub enum ContextInfo<'a> {
|
||||||
pub fn with_file_path(&self, s: &str) -> Self {
|
FilePath(&'a str),
|
||||||
let mut result = self.clone();
|
Board(usize),
|
||||||
result.location.file_path = Some(s.into());
|
Stat(usize),
|
||||||
result
|
Span(Range<usize>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_board(&self, board: usize) -> Self {
|
impl<'a> Context<'a> {
|
||||||
let mut result = self.clone();
|
pub fn new() -> Self {
|
||||||
result.location.board = Some(board);
|
Self::Base(Box::new(RefCell::new(vec![])))
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_stat(&self, stat: usize) -> Self {
|
pub fn with_file_path(&'a self, s: &'a str) -> Self {
|
||||||
let mut result = self.clone();
|
Self::With(self, ContextInfo::FilePath(s))
|
||||||
result.location.stat = Some(stat);
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_span(&self, span: Range<usize>) -> Self {
|
pub fn with_board(&'a self, i: usize) -> Self {
|
||||||
let mut result = self.clone();
|
Self::With(self, ContextInfo::Board(i))
|
||||||
result.location.span = Some(span);
|
}
|
||||||
result
|
|
||||||
|
pub fn with_stat(&'a self, i: usize) -> Self {
|
||||||
|
Self::With(self, ContextInfo::Stat(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_span(&'a self, r: Range<usize>) -> Self {
|
||||||
|
Self::With(self, ContextInfo::Span(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store(&self, mut message: CompileMessage) {
|
||||||
|
match self {
|
||||||
|
Context::Base(refcell) => refcell.borrow_mut().push(message),
|
||||||
|
Context::With(parent, info) => {
|
||||||
|
let location = &mut message.location;
|
||||||
|
match info {
|
||||||
|
ContextInfo::FilePath(s) => {
|
||||||
|
location.file_path.get_or_insert((*s).into());
|
||||||
|
}
|
||||||
|
ContextInfo::Board(i) => {
|
||||||
|
location.board.get_or_insert(*i);
|
||||||
|
}
|
||||||
|
ContextInfo::Stat(i) => {
|
||||||
|
location.stat.get_or_insert(*i);
|
||||||
|
}
|
||||||
|
ContextInfo::Span(r) => {
|
||||||
|
location.span.get_or_insert(r.clone());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
parent.store(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(&self, message: &str) {
|
pub fn error(&self, message: &str) {
|
||||||
self.messages.borrow_mut().push(CompileMessage {
|
self.store(CompileMessage {
|
||||||
level: Level::Error,
|
level: Level::Error,
|
||||||
message: message.into(),
|
message: message.into(),
|
||||||
location: self.location.clone(),
|
location: Location::default(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn warning(&self, message: &str) {
|
pub fn warning(&self, message: &str) {
|
||||||
self.messages.borrow_mut().push(CompileMessage {
|
self.store(CompileMessage {
|
||||||
level: Level::Warning,
|
level: Level::Warning,
|
||||||
message: message.into(),
|
message: message.into(),
|
||||||
location: self.location.clone(),
|
location: Location::default(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_messages(self) -> Vec<CompileMessage> {
|
pub fn into_messages(self) -> Vec<CompileMessage> {
|
||||||
self.messages.take()
|
match self {
|
||||||
|
Context::Base(refcell) => refcell.into_inner(),
|
||||||
|
_ => panic!("into_messages() may only be called on the base context"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -259,28 +259,28 @@ mod test {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_label_sanitization() {
|
fn test_label_sanitization() {
|
||||||
let mut board = board_from_text("tests/labels/sanitize.txt");
|
let mut board = board_from_text("tests/labels/sanitize.txt");
|
||||||
let _ = process_labels(&mut board, &Context::default());
|
let _ = process_labels(&mut board, &Context::new());
|
||||||
assert_snapshot!(board_to_text(board));
|
assert_snapshot!(board_to_text(board));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_anonymous_labels() {
|
fn test_anonymous_labels() {
|
||||||
let mut board = board_from_text("tests/labels/anonymous.txt");
|
let mut board = board_from_text("tests/labels/anonymous.txt");
|
||||||
let _ = process_labels(&mut board, &Context::default());
|
let _ = process_labels(&mut board, &Context::new());
|
||||||
assert_snapshot!(board_to_text(board));
|
assert_snapshot!(board_to_text(board));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_local_labels() {
|
fn test_local_labels() {
|
||||||
let mut board = board_from_text("tests/labels/local.txt");
|
let mut board = board_from_text("tests/labels/local.txt");
|
||||||
let _ = process_labels(&mut board, &Context::default());
|
let _ = process_labels(&mut board, &Context::new());
|
||||||
assert_snapshot!(board_to_text(board));
|
assert_snapshot!(board_to_text(board));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_namespaces() {
|
fn test_namespaces() {
|
||||||
let mut board = board_from_text("tests/labels/namespaces.txt");
|
let mut board = board_from_text("tests/labels/namespaces.txt");
|
||||||
let _ = process_labels(&mut board, &Context::default());
|
let _ = process_labels(&mut board, &Context::new());
|
||||||
assert_snapshot!(board_to_text(board));
|
assert_snapshot!(board_to_text(board));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -38,14 +38,15 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resolve labels to proper ZZT-OOP
|
// Resolve labels to proper ZZT-OOP
|
||||||
let ctx = ErrContext::default().with_file_path(&world_filename);
|
let base_ctx = ErrContext::new();
|
||||||
|
let ctx = base_ctx.with_file_path(&world_filename);
|
||||||
for (i, mut board) in world.boards.iter_mut().enumerate() {
|
for (i, mut board) in world.boards.iter_mut().enumerate() {
|
||||||
let ctx = ctx.with_board(i);
|
let ctx = ctx.with_board(i);
|
||||||
process_labels(&mut board, &ctx);
|
process_labels(&mut board, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print diagnostics
|
// Print diagnostics
|
||||||
let messages = ctx.into_messages();
|
let messages = base_ctx.into_messages();
|
||||||
for (i, message) in messages.iter().enumerate() {
|
for (i, message) in messages.iter().enumerate() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
println!();
|
println!();
|
||||||
|
|||||||
Reference in New Issue
Block a user