Skip to content

Commit

Permalink
Improved error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert-M-Lucas committed Jun 4, 2024
1 parent 1c03e3e commit 53df4ec
Show file tree
Hide file tree
Showing 13 changed files with 151 additions and 86 deletions.
27 changes: 21 additions & 6 deletions .idea/workspace.xml

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

4 changes: 4 additions & 0 deletions main.why
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
struct A {
a: int,
b: int
}

fn main() -> int {
return 12;
Expand Down
2 changes: 1 addition & 1 deletion src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn main_args(args: Args) -> Result<(), WError> {

print!("Compiling... ");
time!(
let assembly = compile(global_table, unprocessed_functions);
let assembly = compile(global_table, unprocessed_functions)?;
);

print!("Writing Assembly... ");
Expand Down
7 changes: 4 additions & 3 deletions src/root/compiler/compile.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::collections::{HashMap, HashSet};
use crate::root::compiler::compile_function::compile_function;
use crate::root::errors::WError;
use crate::root::name_resolver::name_resolvers::GlobalDefinitionTable;
use crate::root::parser::parse_function::FunctionToken;
use crate::root::shared::common::FunctionID;

pub fn compile(global_table: GlobalDefinitionTable, unprocessed_functions: HashMap<FunctionID, FunctionToken>) -> String {
pub fn compile(global_table: GlobalDefinitionTable, unprocessed_functions: HashMap<FunctionID, FunctionToken>) -> Result<String, WError> {
let mut unprocessed_functions = unprocessed_functions;
let mut compiled_functions = HashMap::new();
let mut compiled_len = 0usize;
Expand All @@ -17,7 +18,7 @@ pub fn compile(global_table: GlobalDefinitionTable, unprocessed_functions: HashM

let current_function_token = unprocessed_functions.remove(&current_function).unwrap();

let (compiled, called_functions) = compile_function(current_function, current_function_token, &global_table);
let (compiled, called_functions) = compile_function(current_function, current_function_token, &global_table)?;
compiled_len += compiled.len() + 10;
compiled_functions.insert(current_function, compiled);

Expand All @@ -41,5 +42,5 @@ pub fn compile(global_table: GlobalDefinitionTable, unprocessed_functions: HashM
s += &f;
}

s
Ok(s)
}
19 changes: 12 additions & 7 deletions src/root/compiler/compile_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ use std::collections::HashSet;
use crate::root::compiler::assembly::utils::{align_16_bytes, align_16_bytes_plus_8, get_function_tag, get_qword_stack_pointer};
use crate::root::compiler::compile_evaluable::compile_evaluable;
use crate::root::compiler::local_variable_table::LocalVariableTable;
use crate::root::errors::WError;
use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable, NameResultId};
use crate::root::parser::parse_function::FunctionToken;
use crate::root::parser::parse_function::parse_line::LineTokens;
use crate::root::shared::common::{FunctionID, LocalAddress};
use crate::root::shared::common::AddressedTypeRef;

pub fn compile_function(fid: FunctionID, function: FunctionToken, global_table: &GlobalDefinitionTable) -> (String, HashSet<FunctionID>) {
pub fn compile_function(fid: FunctionID, function: FunctionToken, global_table: &GlobalDefinitionTable) -> Result<(String, HashSet<FunctionID>), WError> {
let mut local_variables = Box::new(LocalVariableTable::default());

let (_location, _name, return_type, parameters, lines) = function.dissolve();

let return_type = if fid.is_main() { None } else { return_type };

let return_type = return_type.and_then(
|t| Some(match global_table.resolve_global_name_to_id(&t).unwrap().unwrap() {
let return_type = if let Some((t, loc)) = return_type {
Some(match global_table.resolve_global_name_to_id(&t, &loc)? {
NameResultId::Function(_) => todo!(),
NameResultId::Type(type_ref) => {
if type_ref.indirection().has_indirection() {
Expand All @@ -25,12 +26,16 @@ pub fn compile_function(fid: FunctionID, function: FunctionToken, global_table:
type_ref
}
NameResultId::NotFound => todo!()
}));
})
}
else {
None
};

let mut param_address = LocalAddress(8);

for (param_name, param_type) in parameters {
let type_ref = match global_table.resolve_global_name_to_id(&param_type).unwrap().unwrap() {
for ((param_name, param_name_loc), (param_type, param_type_loc)) in parameters {
let type_ref = match global_table.resolve_global_name_to_id(&param_type, &param_type_loc)? {
NameResultId::Function(_) => todo!(),
NameResultId::Type(type_ref) => {
if type_ref.indirection().has_indirection() {
Expand Down Expand Up @@ -76,7 +81,7 @@ pub fn compile_function(fid: FunctionID, function: FunctionToken, global_table:
final_contents += "\n\tleave\n\tret"
}

(final_contents, function_calls)
Ok((final_contents, function_calls))
}

fn recursively_compile_lines(fid: FunctionID, lines: &[LineTokens], return_variable: &Option<AddressedTypeRef>, local_variables: Box<LocalVariableTable>, global_table: &GlobalDefinitionTable, function_calls: &mut HashSet<FunctionID>) -> (String, Box<LocalVariableTable>) {
Expand Down
2 changes: 1 addition & 1 deletion src/root/errors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl WError {
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)
cformat!("<r,bold>Error:</>\n {}\n{}\n", self.error, location)
}
else {
cformat!("<r,bold>Error:</>\n {}", self.error)
Expand Down
8 changes: 7 additions & 1 deletion src/root/errors/name_resolver_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,11 @@ pub enum NRErrors {
#[error("No top-level main function found")]
NoMain,
#[error("Cannot create 'impl' for an indirect type")]
IndirectImpl
IndirectImpl,
#[error("Cannot find the subname ({0}) of a function ({1})")]
FunctionSubname(String, String),
#[error("Cannot find method ({0}) of type ({1})")]
CannotFindMethod(String, String),
#[error("Two attributes found with the same name ({0})")]
SameAttributeName(String)
}
57 changes: 32 additions & 25 deletions src/root/name_resolver/name_resolvers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use std::path::PathBuf;
use std::rc::Rc;
use derive_getters::Getters;
use crate::root::compiler::local_variable_table::LocalVariableTable;
use crate::root::errors::name_resolver_errors::NRErrors;
use crate::root::errors::WError;
use crate::root::name_resolver::resolve_function_signatures::FunctionSignature;
use crate::root::parser::parse::Location;
use crate::root::shared::types::Type;
use crate::root::parser::parse_function::FunctionToken;
use crate::root::parser::parse_name::UnresolvedNameToken;
Expand Down Expand Up @@ -196,31 +199,33 @@ impl GlobalDefinitionTable {
todo!()
}

pub fn resolve_global_name_to_id(&self, name: &UnresolvedNameToken) -> Result<Option<NameResultId>, ()> {
pub fn resolve_global_name_to_id(&self, name: &UnresolvedNameToken, location: &Location) -> Result<NameResultId, WError> {
let path = name.location().path();

fn search_file_level_tree(tree: &Box<FileLevelTree>, name: &UnresolvedNameToken) -> Result<Option<NameResultId>, ()> {
fn search_file_level_tree(tree: &Box<FileLevelTree>, name: &UnresolvedNameToken, location: &Location) -> Result<Option<NameResultId>, WError> {
let base = name.base();

let Some(base) = tree.table.get(base) else { return Ok(None) };
let mut name_iter = name.names().iter();

match base {
FileLevelTreeNode::Function(fid) => {
if name_iter.next().is_some() || name.indirection().has_indirection() {
if let Some((_, next)) = name_iter.next() {
return Err(WError::n(NRErrors::FunctionSubname(next.clone(), name.base().clone()), location.clone()));
}
if name.indirection().has_indirection() {
// TODO
return Err(());
}
Ok(Some(NameResultId::Function(*fid)))
}
FileLevelTreeNode::Type(tid, imp) => {
Ok(Some(if let Some((connector, method_name)) = name_iter.next() {
// TODO
let Some(function) = imp.functions.get(method_name) else { return Err(()) };
let Some(function) = imp.functions.get(method_name) else {
return Err(WError::n(NRErrors::CannotFindMethod(method_name.clone(), name.base().clone()), location.clone()));
};

// TODO
if name_iter.next().is_some() {
return Err(());
if let Some((_, next)) = name_iter.next() {
return Err(WError::n(NRErrors::FunctionSubname(next.clone(), method_name.clone()), location.clone()));
}

// match connector {
Expand All @@ -246,8 +251,8 @@ impl GlobalDefinitionTable {

// * Search current file then others
if let Some(tree) = tree {
if let Some(found) = search_file_level_tree(tree, name)? {
return Ok(Some(found));
if let Some(found) = search_file_level_tree(tree, name, location)? {
return Ok(found);
}
}

Expand All @@ -256,20 +261,20 @@ impl GlobalDefinitionTable {
continue;
}

if let Some(found) = search_file_level_tree(tree, name)? {
return Ok(Some(found));
if let Some(found) = search_file_level_tree(tree, name, location)? {
return Ok(found);
}
}

if let Some((id, impl_node)) = self.builtin_type_name_table.get(name.base()) {
let mut name_iter = name.names().iter();
if let Some((connector, method_name)) = name_iter.next() {
// TODO
let Some(function) = impl_node.functions.get(method_name) else { return Err(()) };
let Some(function) = impl_node.functions.get(method_name) else {
return Err(WError::n(NRErrors::CannotFindMethod(method_name.clone(), name.base().clone()), location.clone()));
};

// TODO
if name_iter.next().is_some() {
return Err(());
if let Some((_, next)) = name_iter.next() {
return Err(WError::n(NRErrors::FunctionSubname(next.clone(), method_name.clone()), location.clone()));
}

// match connector {
Expand All @@ -282,22 +287,24 @@ impl GlobalDefinitionTable {
// NameConnectors::Static => {}
// }

return Ok(Some(NameResultId::Function(*function)));
return Ok(NameResultId::Function(*function));
}
else {
return Ok(Some(NameResultId::Type(TypeRef::new(*id, *name.indirection()))));
return Ok(NameResultId::Type(TypeRef::new(*id, *name.indirection())));
}
}

if let Some(id) = self.builtin_function_name_table.get(name.base()) {
// TODO
if !name.names().is_empty() || name.indirection().has_indirection() {
return Err(());
if let Some((_, next)) = name.names().iter().next() {
return Err(WError::n(NRErrors::FunctionSubname(next.clone(), name.base().clone()), location.clone()));
}
if name.indirection().has_indirection() {
// TODO
}

return Ok(Some(NameResultId::Function(*id)))
return Ok(NameResultId::Function(*id))
}

Ok(None)
todo!()
}
}
17 changes: 9 additions & 8 deletions src/root/name_resolver/resolve_function_signatures.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use derive_getters::Getters;
use crate::root::errors::WError;
use crate::root::name_resolver::name_resolvers::{GlobalDefinitionTable, NameResult, NameResultId};
use crate::root::shared::common::TypeRef;
use crate::root::parser::parse_function::FunctionToken;
Expand All @@ -9,12 +10,12 @@ pub struct FunctionSignature {
return_type: Option<TypeRef>
}

pub fn resolve_function_signature(function_token: &FunctionToken, global_table: &GlobalDefinitionTable) -> FunctionSignature {
pub fn resolve_function_signature(function_token: &FunctionToken, global_table: &GlobalDefinitionTable) -> Result<FunctionSignature, WError> {
let mut args = Vec::new();

let return_type = if let Some(type_name) = function_token.return_type() {
let return_type = if let Some((type_name, location)) = function_token.return_type() {
// TODO
Some(match global_table.resolve_global_name_to_id(type_name).unwrap().unwrap() {
Some(match global_table.resolve_global_name_to_id(type_name, location)? {
NameResultId::Function(_) => todo!(),
NameResultId::Type(type_id) => type_id,
NameResultId::NotFound => todo!()
Expand All @@ -23,20 +24,20 @@ pub fn resolve_function_signature(function_token: &FunctionToken, global_table:
None
};

for (arg_name, arg_type) in function_token.parameters() {
for (arg_name, (arg_type, arg_type_loc)) in function_token.parameters() {
args.push((
arg_name.clone(),
arg_name.0.clone(),
// TODO
match global_table.resolve_global_name_to_id(arg_type).unwrap().unwrap() {
match global_table.resolve_global_name_to_id(arg_type, arg_type_loc)? {
NameResultId::Function(_) => todo!(),
NameResultId::Type(type_ref) => type_ref,
NameResultId::NotFound => todo!()
}
))
}

FunctionSignature {
Ok(FunctionSignature {
args,
return_type
}
})
}
Loading

0 comments on commit 53df4ec

Please sign in to comment.