mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-14 18:40:50 +01:00
Made it possible for functions to call themselves
This commit is contained in:
parent
5b8ad2829c
commit
4da372aefe
@ -382,17 +382,45 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the arguments as their own variables.
|
// Initialise the arguments as their own variables.
|
||||||
|
let mut new_argument_values = Vec::new();
|
||||||
for (i, argument) in arguments.iter().enumerate() {
|
for (i, argument) in arguments.iter().enumerate() {
|
||||||
eval_stmt(
|
let identifier_parts: Vec<&str> = argument.split('-').collect();
|
||||||
context,
|
let var_decl = Stmt::VarDecl(
|
||||||
&Stmt::VarDecl(
|
Identifier::parameter_from_name(identifier_parts[1], identifier_parts[0]),
|
||||||
Identifier::from_full_name(argument),
|
Box::new(Expr::Literal(
|
||||||
Box::new(expressions[i].clone()),
|
eval_expr(context, &expressions[i], "")?.to_f64(),
|
||||||
),
|
)),
|
||||||
)?;
|
);
|
||||||
|
|
||||||
|
// Don't set these values just yet, since
|
||||||
|
// to avoid affecting the value of arguments
|
||||||
|
// during recursion.
|
||||||
|
new_argument_values.push((argument, var_decl));
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_expr(context, &fn_body, unit)
|
let mut old_argument_values = Vec::new();
|
||||||
|
for (name, value) in new_argument_values {
|
||||||
|
// Save the original argument values,
|
||||||
|
// so that they can be reverted to after
|
||||||
|
// the function call is evaluated.
|
||||||
|
// This is necessary since recursive
|
||||||
|
// function calls have the same argument names.
|
||||||
|
old_argument_values.push(context.symbol_table.get_and_remove_var(name));
|
||||||
|
|
||||||
|
// Now set the new variable value
|
||||||
|
eval_stmt(context, &value)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let fn_value = eval_expr(context, &fn_body, unit);
|
||||||
|
|
||||||
|
// Revert to original argument values
|
||||||
|
for old_argument_value in old_argument_values {
|
||||||
|
if let Some(old_argument_value) = old_argument_value {
|
||||||
|
context.symbol_table.insert(old_argument_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_value
|
||||||
}
|
}
|
||||||
_ => Err(CalcError::UndefinedFn(identifier.full_name.clone())),
|
_ => Err(CalcError::UndefinedFn(identifier.full_name.clone())),
|
||||||
}
|
}
|
||||||
|
@ -574,6 +574,8 @@ fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
|
|
||||||
fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
|
fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
|
||||||
let identifier = Identifier::from_full_name(&advance(context).value);
|
let identifier = Identifier::from_full_name(&advance(context).value);
|
||||||
|
let exists_as_fn = context.symbol_table.contains_fn(&identifier.pure_name)
|
||||||
|
|| context.current_function.as_ref() == Some(&identifier.pure_name);
|
||||||
|
|
||||||
// Eg. sqrt64
|
// Eg. sqrt64
|
||||||
if match_token(context, TokenKind::Literal)
|
if match_token(context, TokenKind::Literal)
|
||||||
@ -582,7 +584,7 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
|| peek(context).value == "ϕ"
|
|| peek(context).value == "ϕ"
|
||||||
{
|
{
|
||||||
// If there is a function with this name, parse it as a function, with the next token as the argument.
|
// If there is a function with this name, parse it as a function, with the next token as the argument.
|
||||||
if context.symbol_table.contains_fn(&identifier.pure_name) {
|
if exists_as_fn {
|
||||||
let parameter = if identifier.full_name == "√" {
|
let parameter = if identifier.full_name == "√" {
|
||||||
parse_exponent(context)?
|
parse_exponent(context)?
|
||||||
} else {
|
} else {
|
||||||
@ -594,7 +596,7 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
|
|||||||
|
|
||||||
let parse_as_var_instead = match_token(context, TokenKind::OpenParenthesis)
|
let parse_as_var_instead = match_token(context, TokenKind::OpenParenthesis)
|
||||||
&& !context.parsing_identifier_stmt
|
&& !context.parsing_identifier_stmt
|
||||||
&& !context.symbol_table.contains_fn(&identifier.pure_name);
|
&& !exists_as_fn;
|
||||||
|
|
||||||
// Eg. sqrt(64)
|
// Eg. sqrt(64)
|
||||||
// If the function doesn't exist, parse it as a variable and multiplication instead.
|
// If the function doesn't exist, parse it as a variable and multiplication instead.
|
||||||
|
Loading…
Reference in New Issue
Block a user