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::source_range::SourceRange;
|
||||||
use crate::symbol::FunctionSymbol;
|
use crate::symbol::FunctionSymbol;
|
||||||
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
pub struct ExternFunction {
|
pub struct ExternFunction {
|
||||||
declared_name: String,
|
declared_name: String,
|
||||||
@ -35,24 +33,24 @@ impl ExternFunction {
|
|||||||
let insert_result =
|
let insert_result =
|
||||||
symbol_table.insert_function_symbol(FunctionSymbol::new(&self.declared_name, true));
|
symbol_table.insert_function_symbol(FunctionSymbol::new(&self.declared_name, true));
|
||||||
|
|
||||||
let mut maybe_function_symbol: Option<Rc<RefCell<FunctionSymbol>>> = None;
|
let function_symbol = match insert_result {
|
||||||
match insert_result {
|
Ok(function_symbol) => function_symbol,
|
||||||
Ok(function_symbol) => {
|
Err(symbol_insert_error) => {
|
||||||
maybe_function_symbol = Some(function_symbol);
|
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));
|
symbol_table.push_scope(&format!("extern_function_scope({})", &self.declared_name));
|
||||||
|
|
||||||
@ -68,8 +66,7 @@ impl ExternFunction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maybe_function_symbol
|
function_symbol
|
||||||
.unwrap()
|
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.set_parameters(parameter_symbols);
|
.set_parameters(parameter_symbols);
|
||||||
|
|
||||||
@ -78,13 +75,21 @@ impl ExternFunction {
|
|||||||
diagnostics
|
diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_name_usages(&mut self, _symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||||
// no-op (for now)
|
self.parameters
|
||||||
vec![]
|
.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> {
|
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||||
// no-op (for now)
|
self.parameters
|
||||||
vec![]
|
.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::assemble_context::AssembleContext;
|
||||||
|
use crate::ast::parameter::Parameter;
|
||||||
use crate::ast::statement::Statement;
|
use crate::ast::statement::Statement;
|
||||||
use crate::constants_table::ConstantsTable;
|
use crate::constants_table::ConstantsTable;
|
||||||
use crate::diagnostic::Diagnostic;
|
use crate::diagnostic::Diagnostic;
|
||||||
@ -9,6 +10,7 @@ use crate::symbol_table::{SymbolInsertError, SymbolTable};
|
|||||||
pub struct Function {
|
pub struct Function {
|
||||||
declared_name: String,
|
declared_name: String,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
|
parameters: Vec<Parameter>,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -16,11 +18,13 @@ impl Function {
|
|||||||
pub fn new(
|
pub fn new(
|
||||||
declared_name: &str,
|
declared_name: &str,
|
||||||
declared_name_source_range: SourceRange,
|
declared_name_source_range: SourceRange,
|
||||||
|
parameters: Vec<Parameter>,
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
declared_name: declared_name.to_string(),
|
declared_name: declared_name.to_string(),
|
||||||
declared_name_source_range,
|
declared_name_source_range,
|
||||||
|
parameters,
|
||||||
statements,
|
statements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,36 +39,72 @@ impl Function {
|
|||||||
|
|
||||||
pub fn gather_declared_names(&mut self, symbol_table: &mut SymbolTable) -> Vec<Diagnostic> {
|
pub fn gather_declared_names(&mut self, symbol_table: &mut SymbolTable) -> Vec<Diagnostic> {
|
||||||
let mut diagnostics = vec![];
|
let mut diagnostics = vec![];
|
||||||
|
|
||||||
// insert function symbol
|
// insert function symbol
|
||||||
let insert_result =
|
let insert_result =
|
||||||
symbol_table.insert_function_symbol(FunctionSymbol::new(self.declared_name(), false));
|
symbol_table.insert_function_symbol(FunctionSymbol::new(self.declared_name(), false));
|
||||||
if let Err(symbol_insert_error) = insert_result {
|
|
||||||
match symbol_insert_error {
|
// get function symbol if successful
|
||||||
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
let function_symbol = match insert_result {
|
||||||
diagnostics.push(Diagnostic::new(
|
Ok(function_symbol) => function_symbol,
|
||||||
&format!(
|
Err(symbol_insert_error) => {
|
||||||
"Function {} already declared in current scope",
|
return match symbol_insert_error {
|
||||||
already_declared.name()
|
SymbolInsertError::AlreadyDeclared(already_declared) => {
|
||||||
),
|
diagnostics.push(Diagnostic::new(
|
||||||
self.declared_name_source_range.start(),
|
&format!(
|
||||||
self.declared_name_source_range.end(),
|
"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!("body_scope({})", self.declared_name));
|
||||||
|
|
||||||
symbol_table.push_scope(&format!("function_scope({})", self.declared_name()));
|
|
||||||
for statement in &mut self.statements {
|
for statement in &mut self.statements {
|
||||||
diagnostics.append(&mut statement.gather_declared_names(symbol_table));
|
diagnostics.append(&mut statement.gather_declared_names(symbol_table));
|
||||||
}
|
}
|
||||||
symbol_table.pop_scope();
|
symbol_table.pop_scope(); // body
|
||||||
|
symbol_table.pop_scope(); // params
|
||||||
diagnostics
|
diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||||
let mut diagnostics = vec![];
|
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 {
|
for statement in &mut self.statements {
|
||||||
diagnostics.append(&mut statement.check_name_usages(symbol_table));
|
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> {
|
pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Vec<Diagnostic> {
|
||||||
let mut diagnostics = vec![];
|
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 {
|
for statement in &mut self.statements {
|
||||||
diagnostics.append(&mut statement.type_check(symbol_table));
|
diagnostics.append(&mut statement.type_check(symbol_table));
|
||||||
}
|
}
|
||||||
|
|
||||||
diagnostics
|
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)?;
|
self.expect_advance(TokenKind::Fn)?;
|
||||||
let identifier_token = self.expect_advance(TokenKind::Identifier)?;
|
let identifier_token = self.expect_advance(TokenKind::Identifier)?;
|
||||||
self.expect_advance(TokenKind::LeftParentheses)?;
|
self.expect_advance(TokenKind::LeftParentheses)?;
|
||||||
// add params
|
|
||||||
|
let parameters = self.parameter_list()?;
|
||||||
|
|
||||||
self.expect_advance(TokenKind::RightParentheses)?;
|
self.expect_advance(TokenKind::RightParentheses)?;
|
||||||
let mut statements = vec![];
|
let mut statements = vec![];
|
||||||
let mut diagnostics = vec![];
|
let mut diagnostics = vec![];
|
||||||
@ -248,6 +250,7 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(Function::new(
|
Ok(Function::new(
|
||||||
self.token_text(&identifier_token),
|
self.token_text(&identifier_token),
|
||||||
SourceRange::new(identifier_token.start(), identifier_token.end()),
|
SourceRange::new(identifier_token.start(), identifier_token.end()),
|
||||||
|
parameters,
|
||||||
statements,
|
statements,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
@ -306,7 +309,7 @@ impl<'a> Parser<'a> {
|
|||||||
diagnostics.append(&mut parameter_diagnostics);
|
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();
|
self.advance();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +483,17 @@ mod smoke_tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn extern_fn_with_param() {
|
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