diff --git a/README.md b/README.md index 1499133..67a67c8 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,9 @@ Currently missing relevant features (TODOs) are: - Debug Information - Borrows+Pointers +Smaller features: +- Easier way to initialize arrays with a single value + ### Why "Reid" [áš± is an Elder Futhark rune](https://en.wikipedia.org/wiki/Raido) which means diff --git a/reid/lib/std.reid b/reid/lib/std.reid index 1b69685..d5be29b 100644 --- a/reid/lib/std.reid +++ b/reid/lib/std.reid @@ -1,10 +1,21 @@ extern fn puts(message: string) -> i32; +struct DivT { + quot: i32, + rem: i32, +} + +extern fn div(numerator: i32, denominator: i32) -> DivT; + pub fn print(message: string) { puts(message); } +pub fn intdiv(numerator: i32, denominator: i32) -> DivT { + return div(numerator, denominator); +} + fn main() -> u16 { return 0; } diff --git a/reid/src/lib.rs b/reid/src/lib.rs index f288dcd..0e2596a 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -121,7 +121,7 @@ pub fn perform_all_passes<'map>( #[cfg(debug_assertions)] println!("{}", &context); - let state = context.pass(&mut LinkerPass { module_map }); + let state = context.pass(&mut LinkerPass { module_map })?; #[cfg(debug_assertions)] println!("{}", &context); @@ -137,7 +137,7 @@ pub fn perform_all_passes<'map>( let refs = TypeRefs::default(); - let state = context.pass(&mut TypeInference { refs: &refs }); + let state = context.pass(&mut TypeInference { refs: &refs })?; #[cfg(debug_assertions)] dbg!(&refs); @@ -157,7 +157,7 @@ pub fn perform_all_passes<'map>( )); } - let state = context.pass(&mut TypeCheck { refs: &refs }); + let state = context.pass(&mut TypeCheck { refs: &refs })?; #[cfg(debug_assertions)] println!("{}", &context); @@ -189,13 +189,19 @@ pub fn compile_and_pass<'map>( let path = path.canonicalize().unwrap(); let name = path.file_name().unwrap().to_str().unwrap().to_owned(); - let (id, tokens) = parse_module(source, name, module_map).unwrap(); + let (id, tokens) = parse_module(source, name, module_map)?; let module = compile_module(id, &tokens, module_map, Some(path.clone()), true)?; let mut mir_context = mir::Context::from(vec![module], path.parent().unwrap().to_owned()); + dbg!(&mir_context); + println!("Context: {}", &mir_context); + perform_all_passes(&mut mir_context, module_map)?; + dbg!(&mir_context); + println!("Context: {}", &mir_context); + let mut context = Context::new(format!("Reid ({})", env!("CARGO_PKG_VERSION"))); let codegen_modules = mir_context.codegen(&mut context, &module_map); diff --git a/reid/src/mir/linker.rs b/reid/src/mir/linker.rs index cc81277..5b10905 100644 --- a/reid/src/mir/linker.rs +++ b/reid/src/mir/linker.rs @@ -7,10 +7,15 @@ use std::{ rc::Rc, }; -use crate::{compile_module, error_raporting::ModuleMap, lexer::FullToken, parse_module}; +use crate::{ + compile_module, + error_raporting::{ModuleMap, ReidError}, + lexer::FullToken, + parse_module, +}; use super::{ - pass::{Pass, PassState}, + pass::{Pass, PassResult, PassState}, r#impl::EqualsIssue, Context, FunctionDefinition, Import, Metadata, Module, }; @@ -41,14 +46,16 @@ pub enum ErrorKind { FunctionIsPrivate(String, String), } -pub fn compile_std(module_map: &mut ModuleMap) -> (super::Module, Vec) { - let (id, tokens) = parse_module(STD_SOURCE, "standard_library", module_map).unwrap(); - let module = compile_module(id, &tokens, module_map, None, false).unwrap(); +pub fn compile_std( + module_map: &mut ModuleMap, +) -> Result<(super::Module, Vec), ReidError> { + let (id, tokens) = parse_module(STD_SOURCE, "standard_library", module_map)?; + let module = compile_module(id, &tokens, module_map, None, false)?; let mut mir_context = super::Context::from(vec![module], Default::default()); let std_compiled = mir_context.modules.remove(0); - (std_compiled, tokens) + Ok((std_compiled, tokens)) } /// Struct used to implement a type-checking pass that can be performed on the @@ -62,7 +69,7 @@ type LinkerPassState<'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>; impl<'map> Pass for LinkerPass<'map> { type Data = (); type TError = ErrorKind; - fn context(&mut self, context: &mut Context, mut state: LinkerPassState) { + fn context(&mut self, context: &mut Context, mut state: LinkerPassState) -> PassResult { let mains = context .modules .iter() @@ -70,16 +77,16 @@ impl<'map> Pass for LinkerPass<'map> { .collect::>(); if mains.len() > 1 { state.note_errors(&vec![ErrorKind::MultipleMainsAtStart], Metadata::default()); - return; + return Ok(()); } let Some(main) = mains.first() else { state.note_errors(&vec![ErrorKind::NoMainDefined], Metadata::default()); - return; + return Ok(()); }; let Some(_) = main.functions.iter().find(|f| f.name == "main") else { state.note_errors(&vec![ErrorKind::NoMainFunction], Metadata::default()); - return; + return Ok(()); }; let mut modules = HashMap::>>::new(); @@ -95,10 +102,10 @@ impl<'map> Pass for LinkerPass<'map> { modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens)))); } - // modules.insert( - // "std".to_owned(), - // Rc::new(RefCell::new(compile_std(&mut self.module_map))), - // ); + modules.insert( + "std".to_owned(), + Rc::new(RefCell::new(compile_std(&mut self.module_map)?)), + ); let mut modules_to_process: Vec)>>> = modules.values().cloned().collect(); @@ -243,5 +250,7 @@ impl<'map> Pass for LinkerPass<'map> { .into_values() .map(|v| Rc::into_inner(v).unwrap().into_inner().0) .collect(); + + Ok(()) } } diff --git a/reid/src/mir/pass.rs b/reid/src/mir/pass.rs index 65a99d1..cddc1c5 100644 --- a/reid/src/mir/pass.rs +++ b/reid/src/mir/pass.rs @@ -5,6 +5,8 @@ use std::collections::HashMap; use std::convert::Infallible; use std::error::Error as STDError; +use crate::error_raporting::ReidError; + use super::*; #[derive(thiserror::Error, Debug, Clone)] @@ -205,33 +207,65 @@ impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, ' } } +pub type PassResult = Result<(), ReidError>; + pub trait Pass { type Data: Clone + Default; type TError: STDError + Clone; - fn context(&mut self, _context: &mut Context, mut _state: PassState) { + fn context( + &mut self, + _context: &mut Context, + mut _state: PassState, + ) -> PassResult { + Ok(()) + } + fn module( + &mut self, + _module: &mut Module, + mut _state: PassState, + ) -> PassResult { + Ok(()) } - fn module(&mut self, _module: &mut Module, mut _state: PassState) {} fn function( &mut self, _function: &mut FunctionDefinition, mut _state: PassState, - ) { + ) -> PassResult { + Ok(()) + } + fn block( + &mut self, + _block: &mut Block, + mut _state: PassState, + ) -> PassResult { + Ok(()) + } + fn stmt( + &mut self, + _stmt: &mut Statement, + mut _state: PassState, + ) -> PassResult { + Ok(()) + } + fn expr( + &mut self, + _expr: &mut Expression, + mut _state: PassState, + ) -> PassResult { + Ok(()) } - fn block(&mut self, _block: &mut Block, mut _state: PassState) {} - fn stmt(&mut self, _stmt: &mut Statement, mut _state: PassState) {} - fn expr(&mut self, _expr: &mut Expression, mut _state: PassState) {} } impl Context { - pub fn pass(&mut self, pass: &mut T) -> State { + pub fn pass(&mut self, pass: &mut T) -> Result, ReidError> { let mut state = State::new(); let mut scope = Scope::default(); - pass.context(self, PassState::from(&mut state, &mut scope)); + pass.context(self, PassState::from(&mut state, &mut scope))?; for module in &mut self.modules { - module.pass(pass, &mut state, &mut scope.inner()); + module.pass(pass, &mut state, &mut scope.inner())?; } - state + Ok(state) } } @@ -241,7 +275,7 @@ impl Module { pass: &mut T, state: &mut State, scope: &mut Scope, - ) { + ) -> PassResult { for typedef in &self.typedefs { let kind = match &typedef.kind { TypeDefinitionKind::Struct(fields) => TypeDefinitionKind::Struct(fields.clone()), @@ -262,11 +296,12 @@ impl Module { .ok(); } - pass.module(self, PassState::from(state, scope)); + pass.module(self, PassState::from(state, scope))?; for function in &mut self.functions { - function.pass(pass, state, &mut scope.inner()); + function.pass(pass, state, &mut scope.inner())?; } + Ok(()) } } @@ -276,7 +311,7 @@ impl FunctionDefinition { pass: &mut T, state: &mut State, scope: &mut Scope, - ) { + ) -> PassResult { for param in &self.parameters { scope .variables @@ -290,15 +325,16 @@ impl FunctionDefinition { .ok(); } - pass.function(self, PassState::from(state, scope)); + pass.function(self, PassState::from(state, scope))?; match &mut self.kind { FunctionDefinitionKind::Local(block, _) => { scope.return_type_hint = Some(self.return_type.clone()); - block.pass(pass, state, scope); + block.pass(pass, state, scope)?; } FunctionDefinitionKind::Extern(_) => {} }; + Ok(()) } } @@ -308,14 +344,14 @@ impl Block { pass: &mut T, state: &mut State, scope: &mut Scope, - ) { + ) -> PassResult { let mut scope = scope.inner(); for statement in &mut self.statements { - statement.pass(pass, state, &mut scope); + statement.pass(pass, state, &mut scope)?; } - pass.block(self, PassState::from(state, &mut scope)); + pass.block(self, PassState::from(state, &mut scope)) } } @@ -325,21 +361,21 @@ impl Statement { pass: &mut T, state: &mut State, scope: &mut Scope, - ) { + ) -> PassResult { match &mut self.0 { StmtKind::Let(_, _, expression) => { - expression.pass(pass, state, scope); + expression.pass(pass, state, scope)?; } StmtKind::Set(_, expression) => { - expression.pass(pass, state, scope); + expression.pass(pass, state, scope)?; } StmtKind::Import(_) => {} // Never exists at this stage StmtKind::Expression(expression) => { - expression.pass(pass, state, scope); + expression.pass(pass, state, scope)?; } } - pass.stmt(self, PassState::from(state, scope)); + pass.stmt(self, PassState::from(state, scope))?; match &mut self.0 { StmtKind::Let(variable_reference, mutable, _) => { @@ -358,6 +394,7 @@ impl Statement { StmtKind::Import(_) => {} // Never exists at this stage StmtKind::Expression(_) => {} }; + Ok(()) } } @@ -367,7 +404,8 @@ impl Expression { pass: &mut T, state: &mut State, scope: &mut Scope, - ) { - pass.expr(self, PassState::from(state, scope)); + ) -> PassResult { + pass.expr(self, PassState::from(state, scope))?; + Ok(()) } } diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 67cf397..a57a120 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -6,7 +6,7 @@ use crate::{mir::*, util::try_all}; use VagueType as Vague; use super::{ - pass::{Pass, PassState, ScopeFunction, ScopeVariable}, + pass::{Pass, PassResult, PassState, ScopeFunction, ScopeVariable}, typerefs::TypeRefs, }; @@ -70,7 +70,7 @@ impl<'t> Pass for TypeCheck<'t> { type Data = (); type TError = ErrorKind; - fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) { + fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) -> PassResult { let mut defmap = HashMap::new(); for typedef in &module.typedefs { let TypeDefinition { name, kind, meta } = &typedef; @@ -107,6 +107,7 @@ impl<'t> Pass for TypeCheck<'t> { let res = function.typecheck(&self.refs, &mut state.inner()); state.ok(res, function.block_meta()); } + Ok(()) } } diff --git a/reid/src/mir/typeinference.rs b/reid/src/mir/typeinference.rs index 1a86f2f..3d357f6 100644 --- a/reid/src/mir/typeinference.rs +++ b/reid/src/mir/typeinference.rs @@ -9,7 +9,7 @@ use std::{convert::Infallible, iter}; use crate::{mir::TypeKind, util::try_all}; use super::{ - pass::{Pass, PassState}, + pass::{Pass, PassResult, PassState}, r#impl::pick_return, typecheck::ErrorKind, typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, @@ -32,11 +32,12 @@ impl<'t> Pass for TypeInference<'t> { type Data = (); type TError = ErrorKind; - fn module(&mut self, module: &mut Module, mut state: TypeInferencePassState) { + fn module(&mut self, module: &mut Module, mut state: TypeInferencePassState) -> PassResult { for function in &mut module.functions { let res = function.infer_types(&self.refs, &mut state.inner()); state.ok(res, function.block_meta()); } + Ok(()) } } diff --git a/reid/tests/stdlib.rs b/reid/tests/stdlib.rs index dfbf54e..7206083 100644 --- a/reid/tests/stdlib.rs +++ b/reid/tests/stdlib.rs @@ -14,7 +14,9 @@ fn compiles() { #[test] fn passes_all_passes() { let mut map = Default::default(); - let (mut std, _) = compile_std(&mut map); + let Ok((mut std, _)) = compile_std(&mut map) else { + panic!() + }; // Needed to pass linker-pass std.is_main = true; diff --git a/reid_src/std_test.reid b/reid_src/std_test.reid new file mode 100644 index 0000000..4e8bcc0 --- /dev/null +++ b/reid_src/std_test.reid @@ -0,0 +1,12 @@ + +import std::print; +import std::intdiv; + +fn main() { + let hello = "hello world"; + + print(intdiv(10, 5).quot); + + print(hello); + +}