change syntax for callable

anything that can be applied is now callable, this is the first step for
closure, partial application, and call-by-value
This commit is contained in:
nganhkhoa 2024-03-29 14:45:17 +07:00
parent 6a27f8fdf8
commit 6ad5cbb586
3 changed files with 28 additions and 8 deletions

View File

@ -107,11 +107,11 @@ if_expr = {
"if" ~ if_cond ~ "then" ~ if_branch ~ "else" ~ else_branch
}
call_function = _{ identifier }
call_param_list = _{ expr ~ ("," ~ expr)* }
call_param = { call_param_list? }
call_expr = {
call_function ~ "(" ~ call_param ~ ")"
call_function = _{ identifier
| "(" ~ (if_expr | function) ~ ")" }
call_param = { expr ~ ("," ~ expr)* }
call_expr = {
call_function ~ ( "(" ~ call_param? ~ ")" )+
}
binop = _{

View File

@ -90,7 +90,7 @@ impl Into<BinaryOp> for &str {
#[derive(Clone, Debug)]
pub enum Expression {
IfClause(Box<Expression>, Box<Expression>, Box<Expression>),
Application(/*function name*/Identifier, /*params*/Vec<Box<Expression>>), // function call
Application(/*function name*/Box<Expression>, /*params*/Vec<Box<Expression>>), // function call
Identifier(Identifier),
Number(u64),
String(String),
@ -163,10 +163,18 @@ fn parse_if_expr(parsed: Pair<Rule>) -> Option<Box<Expression>> {
fn parse_call_expr(parsed: Pair<Rule>) -> Option<Box<Expression>> {
let mut p = parsed.into_inner();
let identifier = parse_identifier(p.next()?);
let callable = {
let caller = p.next()?;
match caller.as_rule() {
Rule::identifier => Box::new(Expression::Identifier(parse_identifier(caller))),
Rule::if_expr => parse_if_expr(caller)?,
Rule::function => parse_function_expr(caller)?,
_ => unreachable!(),
}
};
let parsed_params = p.next()?;
let params = parsed_params.into_inner().map(parse_expr).collect();
Some(Box::new(Expression::Application(identifier, params)))
Some(Box::new(Expression::Application(callable, params)))
}
fn parse_single_expr(parsed: Pair<Rule>) -> Box<Expression> {

View File

@ -41,4 +41,16 @@ increment : fn number => number = function x is
is_even : fn number => bool = function x is
if x % 2 then true else false
; invoke a function by name
bruh : number = increment(one)
; invoke a lambda function
bruh1 : number = (function x is x)(1)
; invoke a calculation returns a function
bruh2 : fn bool => number = function cond is
(if cond then
function x is x + 1
else
function x is x + 2
)(0)