mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-12 09:30:40 +01:00
Fixed recursion not working
This commit is contained in:
parent
1b35a2ab42
commit
3009ad2ee1
@ -51,6 +51,7 @@ mod tests {
|
||||
#[test_case("matrices/operations")]
|
||||
#[test_case("matrices/transpose")]
|
||||
#[test_case("radix")]
|
||||
#[test_case("recursion")]
|
||||
#[test_case("redefining")]
|
||||
#[test_case("sum")]
|
||||
#[test_case("variables")]
|
||||
|
@ -156,7 +156,7 @@ fn equivalent_fraction(value: f64) -> Option<String> {
|
||||
numer = numer.trunc();
|
||||
denom = denom.trunc();
|
||||
|
||||
if denom <= 1f64 || denom >= 100f64 || denom == 10f64 {
|
||||
if denom <= 1f64 || denom >= 100f64 || denom as i64 == 10 {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#![allow(clippy::unused_unit)]
|
||||
#![allow(clippy::float_cmp)]
|
||||
mod analysis;
|
||||
pub mod ast;
|
||||
pub mod calculation_result;
|
||||
|
@ -212,16 +212,11 @@ pub fn parse(context: &mut Context, input: &str) -> Result<Vec<Stmt>, CalcError>
|
||||
}
|
||||
|
||||
fn parse_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
|
||||
if match_token(context, TokenKind::Identifier) {
|
||||
return Ok(match peek_next(context).kind {
|
||||
//TokenKind::Equals => parse_var_decl_stmt(context)?,
|
||||
_ => Stmt::Expr(Box::new(parse_expr(context)?)),
|
||||
});
|
||||
} else if match_token(context, TokenKind::UnitKeyword) {
|
||||
return parse_unit_decl_stmt(context);
|
||||
if match_token(context, TokenKind::UnitKeyword) {
|
||||
parse_unit_decl_stmt(context)
|
||||
} else {
|
||||
Ok(Stmt::Expr(Box::new(parse_expr(context)?)))
|
||||
}
|
||||
|
||||
Ok(Stmt::Expr(Box::new(parse_expr(context)?)))
|
||||
}
|
||||
|
||||
fn parse_piecewise(context: &mut Context) -> Result<Expr, CalcError> {
|
||||
@ -376,6 +371,57 @@ fn parse_comparison(context: &mut Context) -> Result<Expr, CalcError> {
|
||||
{
|
||||
let op = peek(context).kind;
|
||||
advance(context);
|
||||
|
||||
// If it's potentially a function declaration, run it through
|
||||
// the analysis phase to ensure it gets added to the symbol
|
||||
// table before parsing the right side. This is necessary for
|
||||
// recursion to work.
|
||||
if let (TokenKind::Equals, Expr::Binary(_, TokenKind::Star, _)) = (TokenKind::Equals, &left)
|
||||
{
|
||||
let analysed = analysis::analyse_stmt(
|
||||
context.symbol_table.get_mut(),
|
||||
Stmt::Expr(Box::new(Expr::Binary(
|
||||
Box::new(left),
|
||||
op,
|
||||
Box::new(Expr::Literal(0f64)),
|
||||
))),
|
||||
)?;
|
||||
|
||||
left = match analysed {
|
||||
// Reconstruct function declarations into what they were originally parsed as
|
||||
Stmt::FnDecl(identifier, parameters, _) => {
|
||||
let mut parameter_vars: Vec<Expr> = parameters
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
Expr::Var(Identifier::from_full_name(
|
||||
// Parameters will come back as eg. f-x,
|
||||
// therefore the function name needs to be removed
|
||||
&x[identifier.full_name.len() + 1..],
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
|
||||
Expr::Binary(
|
||||
Box::new(Expr::Var(identifier)),
|
||||
TokenKind::Star,
|
||||
Box::new(if parameter_vars.len() > 1 {
|
||||
Expr::Vector(parameter_vars)
|
||||
} else {
|
||||
Expr::Group(Box::new(parameter_vars.pop().unwrap()))
|
||||
}),
|
||||
)
|
||||
}
|
||||
Stmt::Expr(analysed_expr) => {
|
||||
if let Expr::Binary(analysed_left, TokenKind::Equals, _) = *analysed_expr {
|
||||
*analysed_left
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
|
||||
let right = if op == TokenKind::Equals && match_token(context, TokenKind::OpenBrace) {
|
||||
parse_piecewise(context)?
|
||||
} else {
|
||||
@ -385,7 +431,9 @@ fn parse_comparison(context: &mut Context) -> Result<Expr, CalcError> {
|
||||
left = match right {
|
||||
Expr::Binary(
|
||||
inner_left,
|
||||
inner_op @ (TokenKind::Equals
|
||||
inner_op
|
||||
@
|
||||
(TokenKind::Equals
|
||||
| TokenKind::NotEquals
|
||||
| TokenKind::GreaterThan
|
||||
| TokenKind::LessThan
|
||||
|
11
tests/recursion.kalker
Normal file
11
tests/recursion.kalker
Normal file
@ -0,0 +1,11 @@
|
||||
f(x) = {
|
||||
f(x - 1) if x >= 1
|
||||
x otherwise
|
||||
}
|
||||
|
||||
g(x, y) = {
|
||||
g(x - 1, y + 1) if x >= 1
|
||||
y otherwise
|
||||
}
|
||||
|
||||
f(5) = 0 and g(5, 0) = 5
|
Loading…
Reference in New Issue
Block a user