Skip to content

Commit

Permalink
feat(errors): add code snippet
Browse files Browse the repository at this point in the history
  • Loading branch information
Markos-Th09 committed Aug 7, 2023
1 parent 7dbb622 commit 1e92451
Show file tree
Hide file tree
Showing 235 changed files with 1,653,043 additions and 1,163,697 deletions.
4 changes: 2 additions & 2 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn compile_identifier(scope: usize, ident: ComplexToken) -> String {
use crate::parser::ComplexToken::*;

let mut result = String::new();
let Ident {expr, ..} = ident else {unreachable!()};
let Ident(expr) = ident else {unreachable!()};

for ctoken in expr {
match ctoken {
Expand Down Expand Up @@ -170,7 +170,7 @@ fn compile_expression(mut scope: usize, expr: Expression) -> String {
}
}
MultilineString(string) => result += &compile_multiline_string(&string),
Table { data, .. } => {
Table(data) => {
scope += 1;
let pre = indent(scope);
result.push('{');
Expand Down
83 changes: 63 additions & 20 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::{error::Error, fmt};
use std::{cell::OnceCell, collections::HashMap, error::Error, fmt};

use colored::Colorize;

use crate::lexer::Position;

#[derive(Debug)]
pub struct Diagnostic {
message: String,
Expand All @@ -14,12 +16,24 @@ pub struct Diagnostic {
enum DiagnosticKind {
Compiler {
path: Option<String>,
line: usize,
column: usize,
position: Position,
},
Other,
}

type Files = HashMap<String, String>;
static mut FILES: OnceCell<Files> = OnceCell::new();
pub fn get_files() -> &'static Files {
unsafe { FILES.get_or_init(HashMap::new) }
}

pub fn get_files_mut() -> &'static mut Files {
if unsafe { FILES.get().is_none() } {
unsafe { FILES.set(HashMap::new()).unwrap() };
}
unsafe { FILES.get_mut().unwrap() }
}

#[derive(Debug, Default)]
pub enum DiagnosticLevel {
#[default]
Expand All @@ -29,75 +43,72 @@ pub enum DiagnosticLevel {
}

impl Diagnostic {
pub fn new(message: String, path: Option<String>, line: usize, column: usize) -> Self {
pub fn new(message: String, path: Option<String>, position: Position) -> Self {
Self {
message,
hint: None,
level: Default::default(),
kind: DiagnosticKind::Compiler { path, line, column },
kind: DiagnosticKind::Compiler { path, position },
}
}

pub fn expected(expected: String, path: Option<String>, line: usize, column: usize) -> Self {
pub fn expected(expected: String, path: Option<String>, position: Position) -> Self {
Self {
message: format!("expected {}", expected),
hint: None,
level: Default::default(),
kind: DiagnosticKind::Compiler { path, line, column },
kind: DiagnosticKind::Compiler { path, position },
}
}

pub fn expected_found(
expected: String,
found: String,
path: Option<String>,
line: usize,
column: usize,
position: Position,
) -> Self {
Self {
message: format!("expected {}, found {}", expected, found),
hint: None,
level: Default::default(),
kind: DiagnosticKind::Compiler { path, line, column },
kind: DiagnosticKind::Compiler { path, position },
}
}

pub fn expected_before(
expected: String,
token: String,
path: Option<String>,
line: usize,
column: usize,
position: Position,
) -> Self {
Self {
message: format!("expected {} before {}", expected, token),
hint: None,
level: Default::default(),
kind: DiagnosticKind::Compiler { path, line, column },
kind: DiagnosticKind::Compiler { path, position },
}
}

pub fn expected_after(
expected: String,
token: String,
path: Option<String>,
line: usize,
column: usize,
position: Position,
) -> Self {
Self {
message: format!("expected {} after {}", expected, token),
hint: None,
level: Default::default(),
kind: DiagnosticKind::Compiler { path, line, column },
kind: DiagnosticKind::Compiler { path, position },
}
}

pub fn unexpected(found: String, path: Option<String>, line: usize, column: usize) -> Self {
pub fn unexpected(found: String, path: Option<String>, position: Position) -> Self {
Self {
message: format!("unexpected {}", found),
hint: None,
level: Default::default(),
kind: DiagnosticKind::Compiler { path, line, column },
kind: DiagnosticKind::Compiler { path, position },
}
}

Expand Down Expand Up @@ -133,12 +144,44 @@ impl fmt::Display for Diagnostic {

write!(f, "{}", self.message)?;
match &self.kind {
DiagnosticKind::Compiler { path, line, column } => {
DiagnosticKind::Compiler { path, position } => {
let Position { line, column, .. } = &position;
write!(f, "\n {} ", "-->".blue().bold())?;
if let Some(path) = path {
write!(f, "{}:", path)?;
}
write!(f, "{}:{}", line, column)?;
writeln!(f, "{}:{}", line, column)?;

if let Some(path) = path {
let source = get_files().get(path);
if let Some(source) = source {
let mut start = position.span.start;
while start > 0 && source.chars().nth(start - 1) != Some('\n') {
start -= 1;
}
let mut end = position.span.end;
while end < source.len() && source.chars().nth(end) != Some('\n') {
end += 1;
}

let source = source[start..end].to_owned();
let end = position.span.end - start;
let start = position.span.start - start;

for (i, line) in source.lines().enumerate() {
if i > 0 {
writeln!(f)?;
}
writeln!(f, "{:4} | {}", i + position.line, line)?;
write!(
f,
" | {}{}",
" ".repeat(start),
"^".repeat(end - start).bright_red()
)?;
}
}
}
}
DiagnosticKind::Other => {}
}
Expand Down
Loading

0 comments on commit 1e92451

Please sign in to comment.