Skip to content

Commit

Permalink
Merge pull request #32 from Ph0enixKM/A42
Browse files Browse the repository at this point in the history
A42 Feature: Create complex functions
  • Loading branch information
Ph0enixKM authored Sep 12, 2022
2 parents a5b8016 + bc75572 commit 7752629
Show file tree
Hide file tree
Showing 42 changed files with 194 additions and 71 deletions.
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

0 comments on commit 7752629

Please sign in to comment.