Remove module_level_declaration ast node.
This commit is contained in:
parent
80b6b96aeb
commit
9790ec6ca6
@ -1,6 +1,8 @@
|
|||||||
use crate::ast::field::Field;
|
use crate::ast::field::Field;
|
||||||
use crate::ast::function::Function;
|
use crate::ast::function::Function;
|
||||||
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::source_range::SourceRange;
|
use crate::source_range::SourceRange;
|
||||||
|
use crate::symbol_table::SymbolTable;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Class {
|
pub struct Class {
|
||||||
@ -24,4 +26,19 @@ impl Class {
|
|||||||
functions,
|
functions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn gather_declared_names(
|
||||||
|
&mut self,
|
||||||
|
symbol_table: &mut SymbolTable,
|
||||||
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,39 @@
|
|||||||
use crate::ast::module_level_declaration::ModuleLevelDeclaration;
|
use crate::ast::class::Class;
|
||||||
|
use crate::ast::extern_function::ExternFunction;
|
||||||
|
use crate::ast::function::Function;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
use crate::ir::ir_function::IrFunction;
|
use crate::ir::ir_function::IrFunction;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
|
|
||||||
pub struct CompilationUnit {
|
pub struct CompilationUnit {
|
||||||
declarations: Vec<ModuleLevelDeclaration>,
|
functions: Vec<Function>,
|
||||||
|
extern_functions: Vec<ExternFunction>,
|
||||||
|
classes: Vec<Class>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompilationUnit {
|
impl CompilationUnit {
|
||||||
pub fn new(declarations: Vec<ModuleLevelDeclaration>) -> Self {
|
pub fn new(
|
||||||
Self { declarations }
|
functions: Vec<Function>,
|
||||||
|
extern_functions: Vec<ExternFunction>,
|
||||||
|
classes: Vec<Class>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
functions,
|
||||||
|
extern_functions,
|
||||||
|
classes,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn declarations(&self) -> &[ModuleLevelDeclaration] {
|
pub fn functions(&self) -> &[Function] {
|
||||||
&self.declarations
|
&self.functions
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extern_functions(&self) -> &[ExternFunction] {
|
||||||
|
&self.extern_functions
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn classes(&self) -> &[Class] {
|
||||||
|
&self.classes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gather_declared_names(
|
pub fn gather_declared_names(
|
||||||
@ -22,13 +42,27 @@ impl CompilationUnit {
|
|||||||
) -> Result<(), Vec<Diagnostic>> {
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
symbol_table.push_scope("compilation_unit_scope");
|
symbol_table.push_scope("compilation_unit_scope");
|
||||||
|
|
||||||
let diagnostics: Vec<Diagnostic> = self
|
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||||
.declarations
|
self.functions
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|declaration| declaration.gather_declared_names(symbol_table))
|
.map(|f| f.gather_declared_names(symbol_table))
|
||||||
.filter_map(Result::err)
|
.filter_map(Result::err)
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
|
self.extern_functions
|
||||||
|
.iter_mut()
|
||||||
|
.map(|f| f.gather_declared_names(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
|
self.classes
|
||||||
|
.iter_mut()
|
||||||
|
.map(|c| c.gather_declared_names(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
symbol_table.pop_scope();
|
symbol_table.pop_scope();
|
||||||
|
|
||||||
@ -40,13 +74,29 @@ impl CompilationUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
let diagnostics: Vec<Diagnostic> = self
|
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||||
.declarations
|
|
||||||
|
self.functions
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|declaration| declaration.check_name_usages(symbol_table))
|
.map(|f| f.check_name_usages(symbol_table))
|
||||||
.filter_map(Result::err)
|
.filter_map(Result::err)
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
|
self.extern_functions
|
||||||
|
.iter_mut()
|
||||||
|
.map(|f| f.check_name_usages(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
|
self.classes
|
||||||
|
.iter_mut()
|
||||||
|
.map(|c| c.check_name_usages(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
if diagnostics.is_empty() {
|
if diagnostics.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -55,13 +105,29 @@ impl CompilationUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||||
let diagnostics: Vec<Diagnostic> = self
|
let mut diagnostics: Vec<Diagnostic> = vec![];
|
||||||
.declarations
|
|
||||||
|
self.functions
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.map(|declaration| declaration.type_check(symbol_table))
|
.map(|f| f.type_check(symbol_table))
|
||||||
.filter_map(Result::err)
|
.filter_map(Result::err)
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect();
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
|
self.extern_functions
|
||||||
|
.iter_mut()
|
||||||
|
.map(|f| f.type_check(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
|
self.classes
|
||||||
|
.iter_mut()
|
||||||
|
.map(|c| c.type_check(symbol_table))
|
||||||
|
.filter_map(Result::err)
|
||||||
|
.flatten()
|
||||||
|
.for_each(|diagnostic| diagnostics.push(diagnostic));
|
||||||
|
|
||||||
if diagnostics.is_empty() {
|
if diagnostics.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -70,12 +136,9 @@ impl CompilationUnit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_ir(&self, symbol_table: &SymbolTable) -> Vec<IrFunction> {
|
pub fn to_ir(&self, symbol_table: &SymbolTable) -> Vec<IrFunction> {
|
||||||
let mut ir_functions = vec![];
|
self.functions
|
||||||
for declaration in &self.declarations {
|
.iter()
|
||||||
if let ModuleLevelDeclaration::Function(function) = declaration {
|
.map(|f| f.to_ir(symbol_table))
|
||||||
ir_functions.push(function.to_ir(symbol_table));
|
.collect()
|
||||||
}
|
|
||||||
}
|
|
||||||
ir_functions
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,6 @@ pub mod identifier;
|
|||||||
pub mod integer_literal;
|
pub mod integer_literal;
|
||||||
pub mod ir_builder;
|
pub mod ir_builder;
|
||||||
pub mod let_statement;
|
pub mod let_statement;
|
||||||
pub mod module_level_declaration;
|
|
||||||
pub mod negative_expression;
|
pub mod negative_expression;
|
||||||
pub mod parameter;
|
pub mod parameter;
|
||||||
pub mod statement;
|
pub mod statement;
|
||||||
|
|||||||
@ -1,54 +0,0 @@
|
|||||||
use crate::ast::class::Class;
|
|
||||||
use crate::ast::extern_function::ExternFunction;
|
|
||||||
use crate::ast::function::Function;
|
|
||||||
use crate::diagnostic::Diagnostic;
|
|
||||||
use crate::symbol_table::SymbolTable;
|
|
||||||
|
|
||||||
pub enum ModuleLevelDeclaration {
|
|
||||||
Function(Function),
|
|
||||||
ExternFunction(ExternFunction),
|
|
||||||
Class(Class),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleLevelDeclaration {
|
|
||||||
pub fn gather_declared_names(
|
|
||||||
&mut self,
|
|
||||||
symbol_table: &mut SymbolTable,
|
|
||||||
) -> Result<(), Vec<Diagnostic>> {
|
|
||||||
match self {
|
|
||||||
ModuleLevelDeclaration::Function(function) => {
|
|
||||||
function.gather_declared_names(symbol_table)
|
|
||||||
}
|
|
||||||
ModuleLevelDeclaration::ExternFunction(extern_function) => {
|
|
||||||
extern_function.gather_declared_names(symbol_table)
|
|
||||||
}
|
|
||||||
ModuleLevelDeclaration::Class(class) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
|
||||||
match self {
|
|
||||||
ModuleLevelDeclaration::Function(function) => function.check_name_usages(symbol_table),
|
|
||||||
ModuleLevelDeclaration::ExternFunction(extern_function) => {
|
|
||||||
extern_function.check_name_usages(symbol_table)
|
|
||||||
}
|
|
||||||
ModuleLevelDeclaration::Class(class) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
|
||||||
match self {
|
|
||||||
ModuleLevelDeclaration::Function(function) => function.type_check(symbol_table),
|
|
||||||
ModuleLevelDeclaration::ExternFunction(extern_function) => {
|
|
||||||
extern_function.type_check(symbol_table)
|
|
||||||
}
|
|
||||||
ModuleLevelDeclaration::Class(class) => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -121,7 +121,6 @@ impl Display for IrBlock {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::ast::module_level_declaration::ModuleLevelDeclaration;
|
|
||||||
use crate::parser::parse_compilation_unit;
|
use crate::parser::parse_compilation_unit;
|
||||||
use crate::symbol_table::SymbolTable;
|
use crate::symbol_table::SymbolTable;
|
||||||
|
|
||||||
@ -139,22 +138,24 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut symbol_table = SymbolTable::new();
|
let mut symbol_table = SymbolTable::new();
|
||||||
compilation_unit.gather_declared_names(&mut symbol_table);
|
compilation_unit
|
||||||
compilation_unit.check_name_usages(&mut symbol_table);
|
.gather_declared_names(&mut symbol_table)
|
||||||
compilation_unit.type_check(&mut symbol_table);
|
.expect("gather failed");
|
||||||
|
compilation_unit
|
||||||
|
.check_name_usages(&mut symbol_table)
|
||||||
|
.expect("name check failed");
|
||||||
|
compilation_unit
|
||||||
|
.type_check(&mut symbol_table)
|
||||||
|
.expect("type check failed");
|
||||||
|
|
||||||
let main = compilation_unit
|
let main = compilation_unit
|
||||||
.declarations()
|
.functions()
|
||||||
.iter()
|
.iter()
|
||||||
.find(|d| matches!(d, ModuleLevelDeclaration::Function(_)))
|
.find(|f| f.declared_name() == "main")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if let ModuleLevelDeclaration::Function(main) = main {
|
let mut main_ir = main.to_ir(&symbol_table);
|
||||||
let mut main_ir = main.to_ir(&symbol_table);
|
let (register_assignments, _) = main_ir.assign_registers(2);
|
||||||
let (register_assignments, _) = main_ir.assign_registers(2);
|
assert_eq!(register_assignments.len(), 4);
|
||||||
assert_eq!(register_assignments.len(), 4);
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,6 @@ use crate::ast::function::Function;
|
|||||||
use crate::ast::identifier::Identifier;
|
use crate::ast::identifier::Identifier;
|
||||||
use crate::ast::integer_literal::IntegerLiteral;
|
use crate::ast::integer_literal::IntegerLiteral;
|
||||||
use crate::ast::let_statement::LetStatement;
|
use crate::ast::let_statement::LetStatement;
|
||||||
use crate::ast::module_level_declaration::ModuleLevelDeclaration;
|
|
||||||
use crate::ast::negative_expression::NegativeExpression;
|
use crate::ast::negative_expression::NegativeExpression;
|
||||||
use crate::ast::parameter::Parameter;
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
@ -189,16 +188,24 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn compilation_unit(&mut self) -> Result<CompilationUnit, Vec<Diagnostic>> {
|
pub fn compilation_unit(&mut self) -> Result<CompilationUnit, Vec<Diagnostic>> {
|
||||||
let mut declarations = vec![];
|
let mut functions: Vec<Function> = vec![];
|
||||||
|
let mut extern_functions: Vec<ExternFunction> = vec![];
|
||||||
|
let mut classes: Vec<Class> = vec![];
|
||||||
|
|
||||||
let mut diagnostics = vec![];
|
let mut diagnostics = vec![];
|
||||||
|
|
||||||
self.advance(); // get started
|
self.advance(); // get started
|
||||||
|
|
||||||
while self.current.is_some() {
|
while self.current.is_some() {
|
||||||
let current = self.get_current();
|
let current = self.get_current();
|
||||||
match current.kind() {
|
match current.kind() {
|
||||||
TokenKind::Fn | TokenKind::Extern | TokenKind::Class => {
|
TokenKind::Fn | TokenKind::Extern | TokenKind::Class => {
|
||||||
let declaration_result = self.module_level_declaration();
|
match self.module_level_declaration(
|
||||||
match declaration_result {
|
&mut functions,
|
||||||
Ok(declaration) => declarations.push(declaration),
|
&mut extern_functions,
|
||||||
|
&mut classes,
|
||||||
|
) {
|
||||||
|
Ok(_) => {}
|
||||||
Err(mut declaration_diagnostics) => {
|
Err(mut declaration_diagnostics) => {
|
||||||
diagnostics.append(&mut declaration_diagnostics)
|
diagnostics.append(&mut declaration_diagnostics)
|
||||||
}
|
}
|
||||||
@ -219,19 +226,27 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if diagnostics.is_empty() {
|
if diagnostics.is_empty() {
|
||||||
Ok(CompilationUnit::new(declarations))
|
Ok(CompilationUnit::new(functions, extern_functions, classes))
|
||||||
} else {
|
} else {
|
||||||
Err(diagnostics)
|
Err(diagnostics)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn module_level_declaration(&mut self) -> Result<ModuleLevelDeclaration, Vec<Diagnostic>> {
|
fn module_level_declaration(
|
||||||
|
&mut self,
|
||||||
|
functions: &mut Vec<Function>,
|
||||||
|
extern_functions: &mut Vec<ExternFunction>,
|
||||||
|
classes: &mut Vec<Class>,
|
||||||
|
) -> Result<(), Vec<Diagnostic>> {
|
||||||
let current = self.get_current();
|
let current = self.get_current();
|
||||||
match current.kind() {
|
match current.kind() {
|
||||||
TokenKind::Fn => {
|
TokenKind::Fn => {
|
||||||
let function_result = self.function();
|
let function_result = self.function();
|
||||||
match function_result {
|
match function_result {
|
||||||
Ok(function) => Ok(ModuleLevelDeclaration::Function(function)),
|
Ok(function) => {
|
||||||
|
functions.push(function);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Err(function_diagnostics) => Err(function_diagnostics),
|
Err(function_diagnostics) => Err(function_diagnostics),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,13 +254,17 @@ impl<'a> Parser<'a> {
|
|||||||
let extern_function_result = self.extern_function();
|
let extern_function_result = self.extern_function();
|
||||||
match extern_function_result {
|
match extern_function_result {
|
||||||
Ok(extern_function) => {
|
Ok(extern_function) => {
|
||||||
Ok(ModuleLevelDeclaration::ExternFunction(extern_function))
|
extern_functions.push(extern_function);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(extern_function_diagnostics) => Err(extern_function_diagnostics),
|
Err(extern_function_diagnostics) => Err(extern_function_diagnostics),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TokenKind::Class => match self.class() {
|
TokenKind::Class => match self.class() {
|
||||||
Ok(class) => Ok(ModuleLevelDeclaration::Class(class)),
|
Ok(class) => {
|
||||||
|
classes.push(class);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Err(class_diagnostics) => Err(class_diagnostics),
|
Err(class_diagnostics) => Err(class_diagnostics),
|
||||||
},
|
},
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
@ -865,29 +884,19 @@ mod concrete_tests {
|
|||||||
compilation_unit: &'a CompilationUnit,
|
compilation_unit: &'a CompilationUnit,
|
||||||
function_name: &str,
|
function_name: &str,
|
||||||
) -> &'a Function {
|
) -> &'a Function {
|
||||||
let declarations = compilation_unit.declarations();
|
compilation_unit
|
||||||
for declaration in declarations {
|
.functions()
|
||||||
match declaration {
|
.iter()
|
||||||
ModuleLevelDeclaration::Function(function) => {
|
.find(|f| f.declared_name() == function_name)
|
||||||
if function.declared_name() == function_name {
|
.unwrap()
|
||||||
return function;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic!("Function {} not found", function_name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parses_extern_fn() {
|
fn parses_extern_fn() {
|
||||||
let compilation_unit = assert_compilation_unit("extern fn println() -> Void");
|
let compilation_unit = assert_compilation_unit("extern fn println() -> Void");
|
||||||
let declarations = compilation_unit.declarations();
|
let extern_functions = compilation_unit.extern_functions();
|
||||||
assert_eq!(declarations.len(), 1);
|
assert_eq!(extern_functions.len(), 1);
|
||||||
let extern_function = match &declarations[0] {
|
let extern_function = &extern_functions[0];
|
||||||
ModuleLevelDeclaration::ExternFunction(extern_function) => extern_function,
|
|
||||||
_ => panic!(),
|
|
||||||
};
|
|
||||||
assert_eq!(extern_function.declared_name(), "println");
|
assert_eq!(extern_function.declared_name(), "println");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user