Skip to content

Commit

Permalink
Add support for multiple errors
Browse files Browse the repository at this point in the history
  • Loading branch information
didrikmunther committed Sep 20, 2024
1 parent b95ef12 commit 7dcd2ac
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 154 deletions.
4 changes: 3 additions & 1 deletion input.ro
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ fn add_two_numbers(a: int, b: int) {

let a = 1;
let b = 2;
add_two_numbers(a, b);
let u = add_two_number(a, b + c);

let q = u + 1;
5 changes: 4 additions & 1 deletion out.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,19 @@ def __user__add_two_numbers():

def __setup():
global __global_data
__global_data = list(range(1))
__global_data = list(range(2))
__global_data[0] = "%i + %i = %i\n"
__global_data[1] = "a"

def __main():
__intrinsic__stack_push(1)
_6_a = __intrinsic__stack_pop()
__intrinsic__stack_push(2)
_7_b = __intrinsic__stack_pop()
__intrinsic__stack_push(_6_a)
__intrinsic__stack_push(__global_data[1])
__intrinsic__stack_push(_7_b)
__intrinsic__stack_add()
__intrinsic__stack_push(2)
__user__add_two_numbers()
__intrinsic__stack_pop()
Expand Down
4 changes: 2 additions & 2 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use clap::Parser;
use rost::{run, shell, CompilationLevel, RunSettings, ShellSettings};
use rost::{run, CompilationLevel, RunSettings};
use std::{fs, process::exit};

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -31,7 +31,7 @@ fn main() -> std::io::Result<()> {
};

if args.shell {
shell(ShellSettings { level });
// shell(ShellSettings { level });
} else {
let generated = run(RunSettings {
file_name: args.file,
Expand Down
28 changes: 16 additions & 12 deletions src/compiler/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ use crate::error::{RostError, RostErrorElement};
pub enum CompilerErrorKind {
UndefinedVariable(String),
UndefinedFunction(String),
NotAFunction(String),
NotEnoughFunctionArguments {
missing: Vec<String>,
},
RedeclaredVariable(String, Range<usize>),
// DereferenceNonPointer(VariableType),
MissingMainFunction,
TooManyParametersInMainFunction,
NotSupported(String),

#[allow(dead_code)]
Expand Down Expand Up @@ -61,15 +62,6 @@ impl CompilerError {
)],
// todo: get_message should be a closure, accepting a document containing helper functions for getting lines.
// todo: perhaps a builder pattern to be able to show errors on multiple lines.
CompilerErrorKind::MissingMainFunction => vec![("Missing main function".into(), 0..0)],
CompilerErrorKind::TooManyParametersInMainFunction => vec![(
"Too many parameters for main function, expected maximum of 2".into(),
self.pos.clone(),
)],
// CompilerErrorKind::DereferenceNonPointer(typ) => vec![(
// format!("Cannot dereference non-pointer value of type {typ}"),
// self.pos.clone(),
// )],
CompilerErrorKind::RedeclaredVariable(identifier, pos) => vec![
(
format!("Redeclared variable: {identifier}"),
Expand All @@ -89,6 +81,18 @@ impl CompilerError {
self.pos.clone(),
)]
}
CompilerErrorKind::NotAFunction(identifier) => {
vec![(format!("Not a function: {identifier}"), self.pos.clone())]
}
CompilerErrorKind::NotEnoughFunctionArguments { missing } => {
vec![(
format!(
"Missing function arguments: {missing}",
missing = missing.join(", ")
),
self.pos.clone(),
)]
}
CompilerErrorKind::NotSupported(v) => {
vec![(format!("Not supported: {v}"), self.pos.clone())]
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ use self::{error::CompilerError, program::Program};
pub mod error;
pub mod program;

pub fn compile(parsed: Vec<Declaration>) -> Result<Program, CompilerError> {
pub fn compile(parsed: Vec<Declaration>) -> Result<Program, Vec<CompilerError>> {
Program::new().compile(parsed)
}
9 changes: 8 additions & 1 deletion src/compiler/program/assignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ impl Program {
&mut self,
declaration: &VariableDeclaration,
) -> Result<Builder, CompilerError> {
let value = self.handle_expression(&declaration.right)?;
let result = self.handle_expression(&declaration.right);
let value = self.get_or_add_error(result);
let assignment_has_error = value.is_none();

let variable_id = self.insert_variable(Variable {
identifier: declaration.identifier.clone(),
Expand All @@ -72,8 +74,13 @@ impl Program {
typ: PrimitiveType::Int,
}),
declaration_pos: declaration.identifier_pos.clone(),
assignment_has_error,
});

let Some(value) = value else {
return Ok(Builder::new());
};

let builder = Builder::new().append(value);

Ok(builder.push(Instruction {
Expand Down
66 changes: 45 additions & 21 deletions src/compiler/program/function_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ use crate::{
parser::definition::{Expression, FunctionCall},
};

use super::{builder::Builder, Program};

static BUILT_IN: &[&str] = &["printf"];
use super::{builder::Builder, ir::VariableKind, Program};

impl Program {
pub fn handle_function_call(
Expand All @@ -19,34 +17,60 @@ impl Program {
let mut builder = Builder::new();

for arg in &fcall.args {
let expr = self.handle_expression(arg)?;
builder = builder.append(expr);
let result = self.handle_expression(arg);
if let Some(expr) = self.get_or_add_error(result) {
builder = builder.append(expr);
}
}

let identifier = fcall.left.get_string().unwrap().to_string();

// if BUILT_IN.contains(&identifier.as_str()) {
// return Ok(builder
// .push(Instruction::new(
// expression.pos.clone(),
// InstructionKind::SystemCall(ProcedureCall {
// nargs: fcall.args.len(),
// identifier,
// }),
// ))
// .push(Instruction::new(
// expression.pos.clone(),
// InstructionKind::Pop,
// )));
// }

let Some(variable_id) = self.get_variable(&identifier) else {
let Some((variable_id, variable)) = self
.get_variable(&identifier)
.map(|variable_id| (variable_id, &self.variables[variable_id]))
else {
return Err(CompilerError::new(
fcall.left.pos.clone(),
CompilerErrorKind::UndefinedFunction(identifier),
));
};

let VariableKind::DeclaredFunction(function) = &variable.kind else {
return Err(CompilerError::new(
fcall.left.pos.clone(),
CompilerErrorKind::NotAFunction(identifier),
));
};

let parameters = function
.parameter_variable_ids
.iter()
.map(|&id| &self.variables[id])
.collect::<Vec<_>>();

let parameter_diff = parameters.len() as i32 - fcall.args.len() as i32;
if parameter_diff > 0 {
return Err(CompilerError::new(
fcall.left.pos.clone(),
CompilerErrorKind::NotEnoughFunctionArguments {
missing: parameters[parameters.len() - parameter_diff as usize..]
.iter()
.map(|v| v.identifier.clone())
.collect(),
},
));
}
// else if parameter_diff < 0 {
// return Err(CompilerError::new(
// fcall.left.pos.clone(),
// CompilerErrorKind::TooManyArguments {
// identifier,
// expected: parameters.len(),
// got: fcall.args.len(),
// },
// ));
// }

let builder = builder
.push(Instruction::new(
expression.pos.clone(),
Expand Down
25 changes: 15 additions & 10 deletions src/compiler/program/function_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,21 @@ impl Program {
) -> Result<(), CompilerError> {
let mut parameter_variable_ids = Vec::new();

let body = self.with_scope(|this| {
let result = self.with_scope(|this| {
// The first value on the stack on a function call is always amount of arguments.
// This is used for varargs functions, but we don't have those yet.
let mut body = Builder::new().push(Instruction::new(
fdec.identifier_pos.clone(),
InstructionKind::Pop,
));

let location = fdec
.content
.iter()
.fold(fdec.identifier_pos.clone(), |acc, decl| {
acc.start..decl.pos.end
});

for param in &fdec.parameters {
let variable_id = this.insert_variable(Variable {
identifier: param.identifier.clone(),
Expand All @@ -34,6 +41,7 @@ impl Program {
typ: PrimitiveType::Int, // TODO: Get the actual type
}),
declaration_pos: param.pos.clone(),
assignment_has_error: false,
});

parameter_variable_ids.push(variable_id);
Expand All @@ -46,24 +54,21 @@ impl Program {

let body = body.append(this.get_instructions(&fdec.content)?);

let location = fdec
.content
.iter()
.fold(fdec.identifier_pos.clone(), |acc, decl| {
acc.start..decl.pos.end
});

Ok((body, location))
})?;
});

let body = self.get_or_add_error(result);
let assignment_has_error = body.is_none();

self.insert_variable(Variable {
identifier: fdec.identifier.clone(),
scope: VariableScope::Global,
kind: VariableKind::DeclaredFunction(Function {
parameter_variable_ids,
body,
body: body.unwrap_or_default(),
}),
declaration_pos: fdec.identifier_pos.clone(),
assignment_has_error,
});

Ok(())
Expand Down
1 change: 1 addition & 0 deletions src/compiler/program/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub struct Variable {
pub scope: VariableScope,
pub kind: VariableKind,
pub declaration_pos: Range<usize>,
pub assignment_has_error: bool,
}

#[derive(Debug)]
Expand Down
46 changes: 38 additions & 8 deletions src/compiler/program/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub struct Program {
// We should use some kind of run-length encoding to make this more efficient.
scope_ranges: Vec<ScopeRange>,
pub scope_lookup: Lapper<Location, ScopeId>,

pub errors: Vec<CompilerError>,
}

impl Default for Program {
Expand All @@ -54,16 +56,21 @@ impl Program {
instructions: Builder::new(),
variables: vec![],
global_data: vec![],
errors: vec![],
}
}

pub fn compile(mut self, parsed: Vec<Declaration>) -> Result<Program, CompilerError> {
let location = parsed
.iter()
.fold(0..0, |acc, decl| acc.start..decl.pos.end);

self.scope_ranges.push((location, self.scope_id));
pub fn get_or_add_error(&mut self, result: Result<Builder, CompilerError>) -> Option<Builder> {
match result {
Ok(builder) => Some(builder),
Err(error) => {
self.errors.push(error);
None
}
}
}

fn add_builtin_functions(&mut self) -> Result<(), CompilerError> {
self.create_function_declaration(&FunctionDeclaration {
identifier: "printf".to_string(),
identifier_pos: 0..0,
Expand All @@ -80,10 +87,33 @@ impl Program {
return_type: None,
})?;

self.instructions = self.get_instructions(&parsed)?;
Ok(())
}

fn _compile(&mut self, parsed: Vec<Declaration>) -> Result<(), CompilerError> {
let location = parsed
.iter()
.fold(0..0, |acc, decl| acc.start..decl.pos.end);

self.scope_ranges.push((location, self.scope_id));
self.add_builtin_functions()?;
self.instructions = self.get_instructions(&parsed)?;
self.scope_lookup = self.get_scope_lookup();

Ok(self)
Ok(())
}

pub fn compile(mut self, parsed: Vec<Declaration>) -> Result<Program, Vec<CompilerError>> {
let result = self._compile(parsed);

if let Err(error) = result {
self.errors.push(error);
}

if self.errors.is_empty() {
Ok(self)
} else {
Err(self.errors)
}
}
}
21 changes: 16 additions & 5 deletions src/compiler/program/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,22 @@ use crate::{compiler::error::CompilerError, parser::definition::Declaration};

impl Program {
pub fn get_instructions(&mut self, content: &[Declaration]) -> Result<Builder, CompilerError> {
content
.iter()
.try_fold(Builder::default(), |builder, declaration| {
Ok(builder.append(self.handle_declaration(declaration)?))
})
// content
// .iter()
// .try_fold(Builder::default(), |builder, declaration| {
// Ok(builder.append(self.handle_declaration(declaration)?))
// })

let mut builder = Builder::default();

for declaration in content {
let result = self.handle_declaration(declaration);
if let Some(result) = self.get_or_add_error(result) {
builder = builder.append(result);
}
}

Ok(builder)
}

// pub fn get_variable(&self, identifier: &String) -> Option<&StoredVariable> {
Expand Down
Loading

0 comments on commit 7dcd2ac

Please sign in to comment.