diff --git a/src/ast/data/function.rs b/src/ast/data/function.rs index 15aa645..900e144 100644 --- a/src/ast/data/function.rs +++ b/src/ast/data/function.rs @@ -15,7 +15,7 @@ impl Function { // where: struct ExpressionsMut<'r>(&'r mut Function); impl<'r> InternalIterator for ExpressionsMut<'r> { - internal_iterator_guts! {} + internal_iterator_mut_guts! {} } impl<'r> InternalIteratorMut for ExpressionsMut<'r> { @@ -33,6 +33,53 @@ impl Function { } } + #[cfg(target_os = "none")] + pub fn calls_ref( + &self, + ) -> impl '_ + InternalIterator> { + return CallsRef(self); + // where: + struct CallsRef<'r>(&'r Function); + impl<'r> InternalIterator for CallsRef<'r> { + type Item = &'r FileSpanned; + + fn try_for_each(self, mut f: F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + for stmt in self.0.statements.iter() { + stmt.calls_ref().try_for_each(&mut f)?; + } + ControlFlow::Continue(()) + } + } + } + + pub fn calls_mut( + &mut self, + ) -> impl '_ + InternalIteratorMut> { + return CallsMut(self); + // where: + struct CallsMut<'r>(&'r mut Function); + impl<'r> InternalIterator for CallsMut<'r> { + internal_iterator_mut_guts! {} + } + + impl<'r> InternalIteratorMut for CallsMut<'r> { + type ItemMut = &'r mut FileSpanned; + + fn try_for_each_mut(self, f: &mut F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + for stmt in self.0.statements.iter_mut() { + stmt.calls_mut().try_for_each_mut(&mut *f)?; + } + ControlFlow::Continue(()) + } + } + } + pub fn generate_code(&self) -> Vec { let mut out = Vec::new(); let mut loop_stack = Vec::new(); diff --git a/src/ast/data/if_else.rs b/src/ast/data/if_else.rs index a6a8d6d..21fa913 100644 --- a/src/ast/data/if_else.rs +++ b/src/ast/data/if_else.rs @@ -34,7 +34,7 @@ impl IfElse { // where: struct ExpressionsMut<'r>(&'r mut IfElse); impl<'r> InternalIterator for ExpressionsMut<'r> { - internal_iterator_guts! {} + internal_iterator_mut_guts! {} } impl<'r> InternalIteratorMut for ExpressionsMut<'r> { @@ -56,6 +56,58 @@ impl IfElse { } } + pub fn calls_ref( + &self, + ) -> impl '_ + InternalIterator> { + return CallsRef(self); + // where: + struct CallsRef<'r>(&'r IfElse); + impl<'r> InternalIterator for CallsRef<'r> { + type Item = &'r FileSpanned; + + fn try_for_each(self, mut f: F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + for stmt in self.0.if_body.iter() { + stmt.calls_ref().try_for_each(&mut f)?; + } + for stmt in self.0.else_body.iter() { + stmt.calls_ref().try_for_each(&mut f)?; + } + ControlFlow::Continue(()) + } + } + } + + pub fn calls_mut( + &mut self, + ) -> impl '_ + InternalIteratorMut> { + return CallsMut(self); + // where: + struct CallsMut<'r>(&'r mut IfElse); + impl<'r> InternalIterator for CallsMut<'r> { + internal_iterator_mut_guts! {} + } + + impl<'r> InternalIteratorMut for CallsMut<'r> { + type ItemMut = &'r mut FileSpanned; + + fn try_for_each_mut(self, f: &mut F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + for stmt in self.0.if_body.iter_mut() { + stmt.calls_mut().try_for_each_mut(&mut *f)?; + } + for stmt in self.0.else_body.iter_mut() { + stmt.calls_mut().try_for_each_mut(&mut *f)?; + } + ControlFlow::Continue(()) + } + } + } + pub fn write_code( &self, loop_stack: &mut Vec<(Option, StrID)>, out: &mut impl Extend, diff --git a/src/ast/data/loop_.rs b/src/ast/data/loop_.rs index 84c646a..d7ec09f 100644 --- a/src/ast/data/loop_.rs +++ b/src/ast/data/loop_.rs @@ -46,7 +46,7 @@ impl Loop { // where: struct ExpressionsMut<'r>(&'r mut Loop); impl<'r> InternalIterator for ExpressionsMut<'r> { - internal_iterator_guts! {} + internal_iterator_mut_guts! {} } impl<'r> InternalIteratorMut for ExpressionsMut<'r> { @@ -64,6 +64,52 @@ impl Loop { } } + pub fn calls_ref( + &self, + ) -> impl '_ + InternalIterator> { + return CallsRef(self); + // where: + struct CallsRef<'r>(&'r Loop); + impl<'r> InternalIterator for CallsRef<'r> { + type Item = &'r FileSpanned; + + fn try_for_each(self, mut f: F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + for stmt in self.0.statements.iter() { + stmt.calls_ref().try_for_each(&mut f)?; + } + ControlFlow::Continue(()) + } + } + } + + pub fn calls_mut( + &mut self, + ) -> impl '_ + InternalIteratorMut> { + return CallsMut(self); + // where: + struct CallsMut<'r>(&'r mut Loop); + impl<'r> InternalIterator for CallsMut<'r> { + internal_iterator_mut_guts! {} + } + + impl<'r> InternalIteratorMut for CallsMut<'r> { + type ItemMut = &'r mut FileSpanned; + + fn try_for_each_mut(self, f: &mut F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + for stmt in self.0.statements.iter_mut() { + stmt.calls_mut().try_for_each_mut(&mut *f)?; + } + ControlFlow::Continue(()) + } + } + } + pub fn write_code( &self, loop_stack: &mut Vec<(Option, StrID)>, out: &mut impl Extend, diff --git a/src/ast/data/statement.rs b/src/ast/data/statement.rs index ba6f5e5..67a4556 100644 --- a/src/ast/data/statement.rs +++ b/src/ast/data/statement.rs @@ -20,7 +20,7 @@ impl Statement { // where: struct ExpressionsMut<'r>(&'r mut Statement); impl<'r> InternalIterator for ExpressionsMut<'r> { - internal_iterator_guts! {} + internal_iterator_mut_guts! {} } impl<'r> InternalIteratorMut for ExpressionsMut<'r> { @@ -49,6 +49,68 @@ impl Statement { } } + pub fn calls_ref( + &self, + ) -> impl '_ + InternalIterator> { + return CallsRef(self); + // where: + struct CallsRef<'r>(&'r Statement); + impl<'r> InternalIterator for CallsRef<'r> { + type Item = &'r FileSpanned; + + fn try_for_each(self, mut f: F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + match self.0 { + Statement::Call(c) => f(c)?, + Statement::IfElse(if_else) => if_else.calls_ref().try_for_each(f)?, + Statement::Loop(loop_) => loop_.calls_ref().try_for_each(f)?, + Statement::Break(_) + | Statement::Continue(_) + | Statement::Expression(_) + | Statement::Return + | Statement::StatementError => {} + } + ControlFlow::Continue(()) + } + } + } + + pub fn calls_mut( + &mut self, + ) -> impl '_ + InternalIteratorMut> { + return CallsMut(self); + // where: + struct CallsMut<'r>(&'r mut Statement); + impl<'r> InternalIterator for CallsMut<'r> { + internal_iterator_mut_guts! {} + } + + impl<'r> InternalIteratorMut for CallsMut<'r> { + type ItemMut = &'r mut FileSpanned; + + fn try_for_each_mut(self, f: &mut F) -> ControlFlow + where + F: FnMut(Self::Item) -> ControlFlow, + { + match self.0 { + Statement::Call(c) => f(c)?, + Statement::IfElse(if_else) => { + if_else.calls_mut().try_for_each_mut(f)? + } + Statement::Loop(loop_) => loop_.calls_mut().try_for_each_mut(f)?, + Statement::Break(_) + | Statement::Continue(_) + | Statement::Expression(_) + | Statement::Return + | Statement::StatementError => {} + } + ControlFlow::Continue(()) + } + } + } + pub fn write_code( &self, loop_stack: &mut Vec<(Option, StrID)>, out: &mut impl Extend, diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 9769b66..5590bd8 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -95,6 +95,21 @@ impl Ast { } } + #[cfg(target_os = "none")] + pub fn check_all_calls_valid(&mut self) { + for function in self.functions.values() { + function.calls_ref().for_each(|c| { + if !self.functions.contains_key(&c.target) { + if self.statics.contains_key(&c.target) { + self.err_bucket.push(YagError::CalledAStatic(c.clone())) + } else { + self.err_bucket.push(YagError::CalledAMissingFunction(c.clone())) + } + } + }); + } + } + pub fn resolve_size_of_static(&mut self) { for func in self.functions.values_mut() { func.expressions_mut().for_each(|xpr| { diff --git a/src/bin/yagbas.rs b/src/bin/yagbas.rs index 5de3eff..dc8e7f0 100644 --- a/src/bin/yagbas.rs +++ b/src/bin/yagbas.rs @@ -205,6 +205,7 @@ pub fn do_ast(args: AstArgs) { every_item.extend(items); } let mut ast = Ast::from_items(every_item); + //ast.check_all_calls_valid(); ast.run_const_eval(); ast.run_static_eval(); ast.resolve_size_of_static(); @@ -228,6 +229,7 @@ pub fn do_codegen(args: CodegenArgs) { every_item.extend(items); } let mut ast = Ast::from_items(every_item); + //ast.check_all_calls_valid(); ast.run_const_eval(); ast.run_static_eval(); ast.resolve_size_of_static(); @@ -235,29 +237,32 @@ pub fn do_codegen(args: CodegenArgs) { ast.resolve_identifiers(); ast.resolve_ref(); ast.simplify_constant_values(); - let assembly_items = ast.generate_assembly_items(); - let mut buffer = String::new(); - for (i, (name, assembly)) in assembly_items.iter().enumerate() { - if i > 0 { - println!(); - } - for asm in assembly.iter() { - use core::fmt::Write; - write!(buffer, "{asm}").ok(); - if buffer.ends_with(":") { - // a label - if buffer.starts_with('.') { - // local label - println!(" {buffer}") + err_bucket.append(&mut ast.err_bucket); + if err_bucket.is_empty() { + let assembly_items = ast.generate_assembly_items(); + let mut buffer = String::new(); + for (i, (name, assembly)) in assembly_items.iter().enumerate() { + if i > 0 { + println!(); + } + for asm in assembly.iter() { + use core::fmt::Write; + write!(buffer, "{asm}").ok(); + if buffer.ends_with(":") { + // a label + if buffer.starts_with('.') { + // local label + println!(" {buffer}") + } else { + println!("{buffer}"); + } } else { - println!("{buffer}"); + println!(" {buffer}"); } - } else { - println!(" {buffer}"); + buffer.clear(); } - buffer.clear(); } + } else { + report_all_the_errors(src_files, err_bucket, args.message_size); } - err_bucket.append(&mut ast.err_bucket); - report_all_the_errors(src_files, err_bucket, args.message_size); } diff --git a/src/errors/mod.rs b/src/errors/mod.rs index 44ac684..d665b25 100644 --- a/src/errors/mod.rs +++ b/src/errors/mod.rs @@ -16,6 +16,8 @@ pub enum YagError { Item(Rich<'static, TokenTree, FileSpan, &'static str>), MultipleDefinitions(Vec>), ConstIdentifierUndefined(FileSpanned), + CalledAStatic(FileSpanned), + CalledAMissingFunction(FileSpanned), } impl YagError { pub fn one_line(&self) -> String { @@ -47,6 +49,16 @@ impl YagError { let span = i._span; format!("Error: Constant Identifier Undefined: `{payload}` {span}") } + YagError::CalledAStatic(call) => { + let payload = call._payload.target; + let span = call._span; + format!("Error: Called A Static: `{payload}` {span}") + } + YagError::CalledAMissingFunction(call) => { + let payload = call._payload.target; + let span = call._span; + format!("Error: Called A Missing Function: `{payload}` {span}") + } } } @@ -130,6 +142,23 @@ impl YagError { .with_label(Label::new(i._span)) .finish() } + YagError::CalledAStatic(call) => { + Report::build(ReportKind::Error, call._span) + .with_config(config) + .with_message(format!("Called A Static: `{}`", call._payload.target)) + .with_label(Label::new(call._span)) + .finish() + } + YagError::CalledAMissingFunction(call) => { + Report::build(ReportKind::Error, call._span) + .with_config(config) + .with_message(format!( + "Called A Missing Function: `{}`", + call._payload.target + )) + .with_label(Label::new(call._span)) + .finish() + } } } } diff --git a/src/internal_iterator_mut.rs b/src/internal_iterator_mut.rs index d11f5e2..4a30413 100644 --- a/src/internal_iterator_mut.rs +++ b/src/internal_iterator_mut.rs @@ -8,7 +8,7 @@ pub trait InternalIteratorMut: InternalIterator { } #[macro_export] -macro_rules! internal_iterator_guts { +macro_rules! internal_iterator_mut_guts { () => { type Item = ::ItemMut;