Skip to content

Commit

Permalink
Began adding error system
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert-M-Lucas committed Jun 4, 2024
1 parent ad71b6d commit 1c03e3e
Show file tree
Hide file tree
Showing 12 changed files with 166 additions and 50 deletions.
5 changes: 5 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 7 additions & 32 deletions .idea/workspace.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions main.why
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

fn main() -> int {
return 12;
}
12 changes: 8 additions & 4 deletions src/root.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use name_resolver::resolve_names::resolve_names;
use crate::root::parser::parse::parse;
// use crate::root::assembler::assemble::generate_assembly;
// use crate::root::name_resolver::processor::process;
Expand All @@ -11,6 +10,7 @@ use std::path::PathBuf;
use crate::root::compiler::compile::compile;
use crate::root::name_resolver::resolve::resolve;
use shared::common::ByteSize;
use crate::root::errors::WError;
use crate::root::runner::{assemble, link_gcc, run};

// #[cfg(target_os = "windows")]
Expand All @@ -32,6 +32,7 @@ pub mod builtin;
pub mod shared;
pub mod compiler;
pub mod assembler;
pub mod errors;

pub const POINTER_SIZE: ByteSize = ByteSize(8);

Expand All @@ -52,10 +53,12 @@ pub struct Args {

pub fn main() {
let args = Args::parse();
let _ = main_args(args);
if let Err(e) = main_args(args) {
println!("\n{e}");
}
}

pub fn main_args(args: Args) {
pub fn main_args(args: Args) -> Result<(), WError> {
if let Some(path) = PathBuf::from(&args.output).parent() {
if let Err(e) = fs::create_dir_all(path) {
if !matches!(e.kind(), ErrorKind::AlreadyExists) {
Expand All @@ -72,7 +75,7 @@ pub fn main_args(args: Args) {

print!("Resolving Names... ");
time!(
let (global_table, unprocessed_functions) = resolve(parsed);
let (global_table, unprocessed_functions) = resolve(parsed)?;
);

print!("Compiling... ");
Expand Down Expand Up @@ -107,4 +110,5 @@ pub fn main_args(args: Args) {
}

cprintln!("<g,bold>Done!</>");
Ok(())
}
39 changes: 39 additions & 0 deletions src/root/errors/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use std::fmt::{Display, Formatter};
use color_print::cformat;
use crate::root::parser::parse::Location;

pub mod parser_errors;
pub mod name_resolver_errors;

pub struct WError {
error: String,
location: Option<Location> // ! Important, don't do file reads unless necessary (i.e. Display)
}

impl WError {
pub fn n(error: impl Display, location: Location) -> WError {
WError {
error: format!("{error}"),
location: Some(location)
}
}

pub fn locationless(error: impl Display) -> WError {
WError {
error: format!("{error}"),
location: None
}
}
}

impl Display for WError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let text = if let Some(location) = &self.location {
cformat!("<r,bold>Error:</>\n {}\n<c,bold>At:</>\n{}", self.error, location)
}
else {
cformat!("<r,bold>Error:</>\n {}", self.error)
};
f.write_str(&text)
}
}
9 changes: 9 additions & 0 deletions src/root/errors/name_resolver_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum NRErrors {
#[error("No top-level main function found")]
NoMain,
#[error("Cannot create 'impl' for an indirect type")]
IndirectImpl
}
7 changes: 7 additions & 0 deletions src/root/errors/parser_errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum ParseError {
// #[error("Names cannot contain character '{0}' (UTF-8 Code: {1:?})")]
// BadName(char, Vec<u8>),
}
11 changes: 6 additions & 5 deletions src/root/name_resolver/resolve.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
use std::collections::HashMap;
use crate::root::builtin::register_builtin;
use crate::root::errors::name_resolver_errors::NRErrors;
use crate::root::errors::WError;
use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
use crate::root::name_resolver::resolve_names::resolve_names;
use crate::root::parser::parse_function::FunctionToken;
use crate::root::parser::parse_toplevel::TopLevelTokens;
use crate::root::shared::common::FunctionID;

pub fn resolve(ast: Vec<TopLevelTokens>) -> (GlobalDefinitionTable, HashMap<FunctionID, FunctionToken>) {
pub fn resolve(ast: Vec<TopLevelTokens>) -> Result<(GlobalDefinitionTable, HashMap<FunctionID, FunctionToken>), WError> {
let mut global_table = GlobalDefinitionTable::new();
register_builtin(&mut global_table);
let unprocessed_functions = resolve_names(ast, &mut global_table);
let unprocessed_functions = resolve_names(ast, &mut global_table)?;

if !global_table.function_signatures().contains_key(&FunctionID(0)) {
// NO MAIN!
todo!()
return Err(WError::locationless(NRErrors::NoMain))
}

(global_table, unprocessed_functions)
Ok((global_table, unprocessed_functions))
}
9 changes: 5 additions & 4 deletions src/root/name_resolver/resolve_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use std::collections::HashMap;

use derive_getters::Getters;
use itertools::Itertools;
use crate::root::errors::name_resolver_errors::NRErrors;
use crate::root::errors::WError;

use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable, NameResultId};
use crate::root::name_resolver::resolve_function_signatures::resolve_function_signature;
Expand Down Expand Up @@ -84,7 +86,7 @@ impl Type for UserType {
}

// ! Unoptimised
pub fn resolve_names(ast: Vec<TopLevelTokens>, global_table: &mut GlobalDefinitionTable) -> HashMap<FunctionID, FunctionToken> {
pub fn resolve_names(ast: Vec<TopLevelTokens>, global_table: &mut GlobalDefinitionTable) -> Result<HashMap<FunctionID, FunctionToken>, WError> {
let mut ast = ast;

// ? User types > 1; Builtin Types < -1
Expand Down Expand Up @@ -118,8 +120,8 @@ pub fn resolve_names(ast: Vec<TopLevelTokens>, global_table: &mut GlobalDefiniti
.map(|(name, type_name)| {
// TODO
let type_ref = match global_table.resolve_global_name_to_id(&type_name).unwrap().unwrap() {
NameResultId::Function(_) => todo!(),
NameResultId::Type(type_ref) => type_ref,
NameResultId::Function(_) => todo!(),
NameResultId::NotFound => todo!(),
};

Expand All @@ -136,9 +138,8 @@ pub fn resolve_names(ast: Vec<TopLevelTokens>, global_table: &mut GlobalDefiniti
NameResultId::NotFound => todo!(),
};

// TODO
if type_ref.indirection().has_indirection() {
panic!()
return WError::n(NRErrors::IndirectImpl, it.location().clone());
}

for ft in it.dissolve().2 {
Expand Down
62 changes: 62 additions & 0 deletions src/root/parser/parse.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cmp::min;
use std::fmt::{Display, Formatter};
use crate::root::parser::parse_toplevel;
use nom::IResult;
use nom_locate::LocatedSpan;
Expand All @@ -21,7 +23,9 @@ pub type ErrorTree<'a> = GenericErrorTree<
#[derive(Debug, Clone, Getters, Hash)]
pub struct Location {
path: Rc<PathBuf>,
/// Offset in the line, counted from 0
offset: usize,
/// Line number, counted from 1
line: u32,
}

Expand All @@ -35,6 +39,64 @@ impl Location {
}
}

const CHAR_LIMIT: usize = 61;

impl Display for Location {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
fn fail(f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "Failed to fetch file reference (has the file changed?")
}

let Ok(file) = fs::read_to_string(self.path.as_path()) else { return fail(f); };

let mut line_iter = file.lines();

if self.line > 1 {
if self.line > 2 {
writeln!(f, "{} | ...", self.line - 2)?;
}

let Some(line) = line_iter.nth(self.line as usize - 2) else { return fail(f); };
let line = if line.chars().count() > CHAR_LIMIT { format!("{} ...", line.chars().take(CHAR_LIMIT - 4).collect::<String>()) } else { line.to_string() };
writeln!(f, "{} | {}", self.line - 1, line)?;
}

let Some(line) = line_iter.next() else { return fail(f); };
let (mut start, mut end) = (0usize, line.chars().count() - 1);

if end > CHAR_LIMIT {
let start_dist = self.offset - start;
let end_dist = end - self.offset;

if start_dist > end_dist {
let take_from_start = min(start_dist, CHAR_LIMIT / 2);
start += take_from_start;
end -= CHAR_LIMIT - 1 - take_from_start;
}
else {
let take_from_end = min(end_dist, CHAR_LIMIT / 2);
end -= take_from_end;
start = CHAR_LIMIT - 1 - take_from_end;
}
}

end += 1;

writeln!(f, "{} | {}", self.line, line.chars().skip(start).take(end - start).collect::<String>())?;
writeln!(f, "E | {}^Here", (0..(self.offset - start)).map(|_| ' ').collect::<String>())?;

if let Some(line) = line_iter.next() {
let line = if line.chars().count() > CHAR_LIMIT { format!("{} ...", line.chars().take(CHAR_LIMIT - 4).collect::<String>()) } else { line.to_string() };
writeln!(f, "{} | {}", self.line + 1, line)?;
if line_iter.next().is_some() {
writeln!(f, "{} | ...", self.line + 2)?;
}
}

Ok(())
}
}

pub fn parse(path: PathBuf) -> Result<Vec<TopLevelTokens>, ()> {
let text = fs::read_to_string(&path).unwrap();
let path = Rc::new(path);
Expand Down
9 changes: 4 additions & 5 deletions src/root/parser/parse_function.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use derive_getters::{Dissolve, Getters};
use nom::sequence::Tuple;
use nom::Parser;
use nom::{Offset, Parser};
use nom_supreme::tag::complete::tag;
use substring::Substring;

use crate::root::parser::parse::{ErrorTree, Location, ParseResult, Span};
use crate::root::parser::parse_blocks::default_section;
use crate::root::parser::parse_function::parse_line::{parse_lines, LineTokens};
use crate::root::parser::parse_function::parse_line::{LineTokens, parse_lines};
use crate::root::parser::parse_name::{parse_full_name, parse_simple_name, UnresolvedNameToken};
use crate::root::parser::parse_parameters::{parse_parameters, Parameters};
use crate::root::parser::parse_toplevel::{TopLevelTokens, ToplevelTestFn};
use crate::root::parser::parse_parameters::{Parameters, parse_parameters};
use crate::root::parser::parse_toplevel::{ToplevelTestFn, TopLevelTokens};
use crate::root::parser::parse_util::{discard_ignored, require_ignored};

pub mod parse_assigner;
Expand Down
13 changes: 13 additions & 0 deletions src/root/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ macro_rules! time {
};
}

// #[macro_export]
// macro_rules! try {
// ($($tts:tt)*) => {
// match $($tts)* {
// Err(e) => {
// println!("\n{}");
// return;
// }
// Ok(v) => v
// }
// };
// }

#[macro_export]
macro_rules! ret_time {
($out: expr, $($tts:tt)*) => {
Expand Down

0 comments on commit 1c03e3e

Please sign in to comment.