Add parameter-list to regular fns.
This commit is contained in:
parent
61d7c66e17
commit
81ceeeadb8
@ -3,8 +3,6 @@ use crate::diagnostic::Diagnostic;
|
||||
use crate::source_range::SourceRange;
|
||||
use crate::symbol::FunctionSymbol;
|
||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct ExternFunction {
|
||||
declared_name: String,
|
||||
@ -35,24 +33,24 @@ impl ExternFunction {
|
||||
let insert_result =
|
||||
symbol_table.insert_function_symbol(FunctionSymbol::new(&self.declared_name, true));
|
||||
|
||||
let mut maybe_function_symbol: Option<Rc<RefCell<FunctionSymbol>>> = None;
|
||||
match insert_result {
|
||||
Ok(function_symbol) => {
|
||||
maybe_function_symbol = Some(function_symbol);
|
||||
let function_symbol = match insert_result {
|
||||
Ok(function_symbol) => function_symbol,
|
||||
Err(symbol_insert_error) => {
|
||||
return match symbol_insert_error {
|
||||
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
&format!(
|
||||
"Function {} already declared in current scope.",
|
||||
already_declared.name()
|
||||
),
|
||||
self.declared_name_source_range.start(),
|
||||
self.declared_name_source_range.end(),
|
||||
));
|
||||
diagnostics
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(symbol_insert_error) => match symbol_insert_error {
|
||||
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
&format!(
|
||||
"Function {} already declared in current scope.",
|
||||
already_declared.name()
|
||||
),
|
||||
self.declared_name_source_range.start(),
|
||||
self.declared_name_source_range.end(),
|
||||
));
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
symbol_table.push_scope(&format!("extern_function_scope({})", &self.declared_name));
|
||||
|
||||
@ -68,8 +66,7 @@ impl ExternFunction {
|
||||
}
|
||||
}
|
||||
}
|
||||
maybe_function_symbol
|
||||
.unwrap()
|
||||
function_symbol
|
||||
.borrow_mut()
|
||||
.set_parameters(parameter_symbols);
|
||||
|
||||
@ -78,13 +75,21 @@ impl ExternFunction {
|
||||
diagnostics
|
||||
}
|
||||
|
||||
pub fn check_name_usages(&mut self, _symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
// no-op (for now)
|
||||
vec![]
|
||||
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
self.parameters
|
||||
.iter_mut()
|
||||
.map(|parameter| parameter.check_name_usages(symbol_table))
|
||||
.filter_map(Result::err)
|
||||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn type_check(&mut self, _symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
// no-op (for now)
|
||||
vec![]
|
||||
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
self.parameters
|
||||
.iter_mut()
|
||||
.map(|parameter| parameter.type_check(symbol_table))
|
||||
.filter_map(Result::err)
|
||||
.flatten()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use crate::ast::assemble_context::AssembleContext;
|
||||
use crate::ast::parameter::Parameter;
|
||||
use crate::ast::statement::Statement;
|
||||
use crate::constants_table::ConstantsTable;
|
||||
use crate::diagnostic::Diagnostic;
|
||||
@ -9,6 +10,7 @@ use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||
pub struct Function {
|
||||
declared_name: String,
|
||||
declared_name_source_range: SourceRange,
|
||||
parameters: Vec<Parameter>,
|
||||
statements: Vec<Statement>,
|
||||
}
|
||||
|
||||
@ -16,11 +18,13 @@ impl Function {
|
||||
pub fn new(
|
||||
declared_name: &str,
|
||||
declared_name_source_range: SourceRange,
|
||||
parameters: Vec<Parameter>,
|
||||
statements: Vec<Statement>,
|
||||
) -> Self {
|
||||
Self {
|
||||
declared_name: declared_name.to_string(),
|
||||
declared_name_source_range,
|
||||
parameters,
|
||||
statements,
|
||||
}
|
||||
}
|
||||
@ -35,36 +39,72 @@ impl Function {
|
||||
|
||||
pub fn gather_declared_names(&mut self, symbol_table: &mut SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = vec![];
|
||||
|
||||
// insert function symbol
|
||||
let insert_result =
|
||||
symbol_table.insert_function_symbol(FunctionSymbol::new(self.declared_name(), false));
|
||||
if let Err(symbol_insert_error) = insert_result {
|
||||
match symbol_insert_error {
|
||||
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
&format!(
|
||||
"Function {} already declared in current scope",
|
||||
already_declared.name()
|
||||
),
|
||||
self.declared_name_source_range.start(),
|
||||
self.declared_name_source_range.end(),
|
||||
));
|
||||
|
||||
// get function symbol if successful
|
||||
let function_symbol = match insert_result {
|
||||
Ok(function_symbol) => function_symbol,
|
||||
Err(symbol_insert_error) => {
|
||||
return match symbol_insert_error {
|
||||
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
||||
diagnostics.push(Diagnostic::new(
|
||||
&format!(
|
||||
"Function {} already declared in current scope",
|
||||
already_declared.name()
|
||||
),
|
||||
self.declared_name_source_range.start(),
|
||||
self.declared_name_source_range.end(),
|
||||
));
|
||||
diagnostics
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// handle parameters
|
||||
symbol_table.push_scope(&format!("parameter_scope({})", self.declared_name));
|
||||
let mut parameter_symbols = vec![];
|
||||
for parameter in &mut self.parameters {
|
||||
match parameter.gather_declared_names(symbol_table) {
|
||||
Ok(parameter_symbol) => {
|
||||
parameter_symbols.push(parameter_symbol);
|
||||
}
|
||||
Err(mut parameter_diagnostics) => {
|
||||
diagnostics.append(&mut parameter_diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
function_symbol
|
||||
.borrow_mut()
|
||||
.set_parameters(parameter_symbols);
|
||||
|
||||
// todo: parameters
|
||||
|
||||
symbol_table.push_scope(&format!("function_scope({})", self.declared_name()));
|
||||
symbol_table.push_scope(&format!("body_scope({})", self.declared_name));
|
||||
for statement in &mut self.statements {
|
||||
diagnostics.append(&mut statement.gather_declared_names(symbol_table));
|
||||
}
|
||||
symbol_table.pop_scope();
|
||||
symbol_table.pop_scope(); // body
|
||||
symbol_table.pop_scope(); // params
|
||||
diagnostics
|
||||
}
|
||||
|
||||
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = vec![];
|
||||
|
||||
// parameters
|
||||
diagnostics.append(
|
||||
&mut self
|
||||
.parameters
|
||||
.iter_mut()
|
||||
.map(|parameter| parameter.check_name_usages(symbol_table))
|
||||
.filter_map(|result| result.err())
|
||||
.flatten()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
// statements
|
||||
for statement in &mut self.statements {
|
||||
diagnostics.append(&mut statement.check_name_usages(symbol_table));
|
||||
}
|
||||
@ -73,9 +113,23 @@ impl Function {
|
||||
|
||||
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||
let mut diagnostics = vec![];
|
||||
|
||||
// parameters
|
||||
diagnostics.append(
|
||||
&mut self
|
||||
.parameters
|
||||
.iter_mut()
|
||||
.map(|parameter| parameter.type_check(symbol_table))
|
||||
.filter_map(|result| result.err())
|
||||
.flatten()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
// statements
|
||||
for statement in &mut self.statements {
|
||||
diagnostics.append(&mut statement.type_check(symbol_table));
|
||||
}
|
||||
|
||||
diagnostics
|
||||
}
|
||||
|
||||
|
||||
@ -45,4 +45,12 @@ impl Parameter {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||
Ok(()) // no-op for now
|
||||
}
|
||||
|
||||
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Result<(), Vec<Diagnostic>> {
|
||||
Ok(()) // no-op for now
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,7 +219,9 @@ impl<'a> Parser<'a> {
|
||||
self.expect_advance(TokenKind::Fn)?;
|
||||
let identifier_token = self.expect_advance(TokenKind::Identifier)?;
|
||||
self.expect_advance(TokenKind::LeftParentheses)?;
|
||||
// add params
|
||||
|
||||
let parameters = self.parameter_list()?;
|
||||
|
||||
self.expect_advance(TokenKind::RightParentheses)?;
|
||||
let mut statements = vec![];
|
||||
let mut diagnostics = vec![];
|
||||
@ -248,6 +250,7 @@ impl<'a> Parser<'a> {
|
||||
Ok(Function::new(
|
||||
self.token_text(&identifier_token),
|
||||
SourceRange::new(identifier_token.start(), identifier_token.end()),
|
||||
parameters,
|
||||
statements,
|
||||
))
|
||||
} else {
|
||||
@ -306,7 +309,7 @@ impl<'a> Parser<'a> {
|
||||
diagnostics.append(&mut parameter_diagnostics);
|
||||
}
|
||||
}
|
||||
if self.lookahead.is_some() && self.peek_lookahead(TokenKind::Comma) {
|
||||
if self.current.is_some() && self.peek_current(TokenKind::Comma) {
|
||||
self.advance();
|
||||
}
|
||||
}
|
||||
@ -480,7 +483,17 @@ mod smoke_tests {
|
||||
|
||||
#[test]
|
||||
fn extern_fn_with_param() {
|
||||
smoke_test("extern fn println(message: Any)")
|
||||
smoke_test("extern fn println(message: Any)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fn_with_param() {
|
||||
smoke_test("fn foo(bar: Int) end");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fn_with_params() {
|
||||
smoke_test("fn foo(bar: Int, baz: Int) end");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user