Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A42 Feature: Create complex functions #32

Merged
merged 3 commits into from
Sep 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/cli/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,4 +426,40 @@ fn function_with_args_different_types() {
test(11, 42)
";
assert_eq!(cli.test_eval(code).trim(), "HelloWorld\n53");
}

#[test]
fn function_with_typed_args() {
let cli = CLI::new();
let code = "
fun test(a: Num, b: Num) {
$echo {a + b}$
}
test(11, 42)
";
assert_eq!(cli.test_eval(code).trim(), "53");
}
#[test]
fn function_with_typed_different_args() {
let cli = CLI::new();
let code = "
fun test(a: Num, b: Text) {
$echo {a}$
$echo {b}$
}
test(11, 'Hello')
";
assert_eq!(cli.test_eval(code).trim(), "11\nHello");
}

#[test]
fn function_with_typed_args_text() {
let cli = CLI::new();
let code = "
fun test(a: Text, b: Text) {
$echo {a + b}$
}
test('Hello', 'World')
";
assert_eq!(cli.test_eval(code).trim(), "HelloWorld");
}
2 changes: 1 addition & 1 deletion src/modules/command/expr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::{ParserMetadata, TranslateMetadata}, modules::{Type, Typed}};
use crate::{utils::{ParserMetadata, TranslateMetadata}, modules::types::{Type, Typed}};
use crate::modules::expression::expr::Expr;
use crate::translate::module::TranslateModule;

Expand Down
2 changes: 1 addition & 1 deletion src/modules/command/statement.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::{ParserMetadata, TranslateMetadata}, modules::{Type, Typed}};
use crate::{utils::{ParserMetadata, TranslateMetadata}, modules::types::{Type, Typed}};
use crate::modules::expression::expr::Expr;
use crate::translate::module::TranslateModule;

Expand Down
4 changes: 2 additions & 2 deletions src/modules/condition/ternary.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::modules::Typed;
use crate::modules::types::{Type, Typed};
use crate::modules::expression::binop::{parse_left_expr, expression_arms_of_same_type};
use crate::modules::expression::expr::Expr;
use crate::translate::module::TranslateModule;
Expand All @@ -14,7 +14,7 @@ pub struct Ternary {
}

impl Typed for Ternary {
fn get_type(&self) -> crate::modules::Type {
fn get_type(&self) -> Type {
self.true_expr.get_type()
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{translate_computation, ArithOp};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Add {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/and.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{translate_computation, ArithOp};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_same_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};


#[derive(Debug, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/div.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::{metadata::ParserMetadata, TranslateMetadata}, translate::compute::{translate_computation, ArithOp}};
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};
use crate::translate::module::TranslateModule;

#[derive(Debug, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/eq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::strip_text_quotes;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_same_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Eq {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/ge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Ge {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/gt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Gt {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/le.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Le {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/lt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{translate_computation, ArithOp};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Lt {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::{metadata::ParserMetadata, error::get_error_logger}, modules::{Type, Typed}};
use crate::{utils::{metadata::ParserMetadata, error::get_error_logger}, modules::types::{Type, Typed}};
use super::super::expression::expr::Expr;

pub mod add;
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/modulo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Modulo {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{translate_computation, ArithOp};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Mul {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/neq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::strip_text_quotes;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_same_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Neq {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/or.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{translate_computation, ArithOp};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_same_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Or {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/binop/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::translate::compute::{ArithOp, translate_computation};
use crate::utils::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use super::{super::expr::Expr, parse_left_expr, expression_arms_of_type};
use crate::modules::{Type, Typed};
use crate::modules::types::{Typed, Type};

#[derive(Debug, Clone)]
pub struct Sub {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/expr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::modules::{Typed, Type};
use crate::modules::types::{Typed, Type};
use crate::translate::module::TranslateModule;
use crate::utils::error::get_error_logger;
use crate::utils::{ParserMetadata, TranslateMetadata};
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/literal/bool.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::metadata::ParserMetadata, modules::{Type, Typed}};
use crate::{utils::metadata::ParserMetadata, modules::types::{Type, Typed}};
use crate::translate::module::TranslateModule;
use crate::utils::TranslateMetadata;

Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/literal/null.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::{ParserMetadata, TranslateMetadata}, modules::{Type, Typed}};
use crate::{utils::{ParserMetadata, TranslateMetadata}, modules::types::{Type, Typed}};
use crate::translate::module::TranslateModule;

#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/literal/number.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::metadata::{ParserMetadata, TranslateMetadata}, modules::{Typed, Type}};
use crate::{utils::metadata::{ParserMetadata, TranslateMetadata}, modules::types::{Type, Typed}};
use crate::translate::module::TranslateModule;

#[derive(Debug, Clone)]
Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/literal/text.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::{TranslateMetadata, ParserMetadata}, modules::{Type, Typed}};
use crate::{utils::{TranslateMetadata, ParserMetadata}, modules::types::{Type, Typed}};
use crate::translate::module::TranslateModule;
use crate::modules::expression::expr::Expr;

Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/parenthesis.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::metadata::ParserMetadata, modules::{Type, Typed}};
use crate::{utils::metadata::ParserMetadata, modules::types::{Type, Typed}};
use crate::translate::module::TranslateModule;
use super::expr::Expr;

Expand Down
2 changes: 1 addition & 1 deletion src/modules/expression/unop/not.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::{utils::{metadata::ParserMetadata, TranslateMetadata}, modules::{Type, Typed}, translate::{module::TranslateModule, compute::{translate_computation, ArithOp}}};
use crate::{utils::{metadata::ParserMetadata, TranslateMetadata}, modules::types::{Type, Typed}, translate::{module::TranslateModule, compute::{translate_computation, ArithOp}}};
use super::super::expr::Expr;

#[derive(Debug, Clone)]
Expand Down
14 changes: 12 additions & 2 deletions src/modules/function/declaration.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use heraclitus_compiler::prelude::*;
use crate::modules::Type;
use crate::modules::types::Type;
use crate::modules::variable::variable_name_extensions;
use crate::utils::error::get_error_logger;
use crate::utils::metadata::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use crate::modules::block::Block;
use crate::modules::types::parse_type;
use crate::context;

use super::declaration_utils::*;
Expand Down Expand Up @@ -58,12 +59,21 @@ impl SyntaxModule<ParserMetadata> for FunctionDeclaration {
break
}
let name = variable(meta, variable_name_extensions())?;
self.args.push((name, Type::Generic));
// Optionally parse the argument type
match token(meta, ":") {
Ok(_) => self.args.push((name.clone(), parse_type(meta)?)),
Err(_) => self.args.push((name, Type::Generic))
}
match token(meta, ")") {
Ok(_) => break,
Err(_) => token(meta, ",")?
};
}
// Optionally parse the return type
match token(meta, ":") {
Ok(_) => self.returns = parse_type(meta)?,
Err(_) => self.returns = Type::Text
}
// Parse the body
token(meta, "{")?;
let index_begin = meta.get_index();
Expand Down
2 changes: 1 addition & 1 deletion src/modules/function/declaration_utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use heraclitus_compiler::prelude::*;
use crate::modules::Type;
use crate::modules::types::Type;
use crate::utils::{ParserMetadata, error::get_error_logger};
use crate::modules::variable::{handle_identifier_name};

Expand Down
7 changes: 3 additions & 4 deletions src/modules/function/invocation.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use heraclitus_compiler::prelude::*;
use crate::modules::Type;
use crate::modules::types::{Type, Typed};
use crate::modules::variable::variable_name_extensions;
use crate::utils::metadata::{ParserMetadata, TranslateMetadata};
use crate::translate::module::TranslateModule;
use crate::modules::expression::expr::Expr;
use crate::modules::Typed;

use super::invocation_utils::*;

Expand Down Expand Up @@ -40,7 +39,7 @@ impl SyntaxModule<ParserMetadata> for FunctionInvocation {
self.name = variable(meta, variable_name_extensions())?;
// Get the arguments
token(meta, "(")?;
handle_function_reference(meta, tok, &self.name);
handle_function_reference(meta, tok.clone(), &self.name);
loop {
if token(meta, ")").is_ok() {
break
Expand All @@ -54,7 +53,7 @@ impl SyntaxModule<ParserMetadata> for FunctionInvocation {
};
}
let types = self.args.iter().map(|e| e.get_type()).collect::<Vec<Type>>();
(self.kind, self.id) = handle_function_parameters(meta, &self.name, &types);
(self.kind, self.id) = handle_function_parameters(meta, &self.name, &types, tok);
Ok(())
}
}
Expand Down
32 changes: 27 additions & 5 deletions src/modules/function/invocation_utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use heraclitus_compiler::prelude::*;
use similar_string::find_best_similarity;
use crate::modules::Type;
use crate::modules::types::Type;
use crate::utils::{ParserMetadata, error::get_error_logger};
use crate::modules::block::Block;

fn run_function_with_args(meta: &mut ParserMetadata, name: &str, args: &[Type]) -> usize {
fn run_function_with_args(meta: &mut ParserMetadata, name: &str, args: &[Type], tok: Option<Token>) -> usize {
let function = meta.mem.get_function(name).unwrap().clone();
let mut block = Block::new();
// Create a new parser metadata specific for the function parsing context
Expand All @@ -13,6 +13,28 @@ fn run_function_with_args(meta: &mut ParserMetadata, name: &str, args: &[Type])
new_meta.expr = function.body.clone();
new_meta.set_index(0);
new_meta.function_ctx = true;
// Check if the function can exist
if function.typed {
if function.args.len() != args.len() {
let err_details = ErrorDetails::from_token_option(tok.clone());
let were_was = if args.len() == 1 { "was" } else { "were" };
let error = format!("Function '{}' expects {} arguments, but {} {were_was} given", name, function.args.len(), args.len());
get_error_logger(meta, err_details)
.attach_message(error)
.show()
.exit();
}
for (index, (arg, kind)) in function.args.iter().enumerate() {
if kind != &args[index] {
let err_details = ErrorDetails::from_token_option(tok.clone());
let error = format!("Function '{}' expects argument '{}' to be of type '{}', but '{}' was given", name, arg, kind, args[index]);
get_error_logger(meta, err_details)
.attach_message(error)
.show()
.exit();
}
}
}
// Create a sub context for new variables
new_meta.mem.push_scope();
for (kind, (name, _generic)) in args.iter().zip(function.args.iter()) {
Expand All @@ -24,7 +46,7 @@ fn run_function_with_args(meta: &mut ParserMetadata, name: &str, args: &[Type])
new_meta.mem.pop_scope();
new_meta.function_ctx = function_ctx;
// Persist the new function instance
meta.mem.add_function_instance(function.id, args, Type::Text, block)
meta.mem.add_function_instance(function.id, args, function.returns, block)
} else { 0 }
}

Expand All @@ -41,10 +63,10 @@ pub fn handle_function_reference(meta: &mut ParserMetadata, tok: Option<Token>,
}
}

pub fn handle_function_parameters(meta: &mut ParserMetadata, name: &str, args: &[Type]) -> (Type, usize) {
pub fn handle_function_parameters(meta: &mut ParserMetadata, name: &str, args: &[Type], tok: Option<Token>) -> (Type, usize) {
let function_unit = meta.mem.get_function(name).unwrap().clone();
// TODO: Here is a good place to insert trace
(function_unit.returns, run_function_with_args(meta, name, args))
(function_unit.returns, run_function_with_args(meta, name, args, tok))
}

fn handle_similar_function(meta: &mut ParserMetadata, name: &str) -> Option<String> {
Expand Down
Loading