Skip to content
Snippets Groups Projects
Verified Commit 24a93bb4 authored by Louis's avatar Louis :fire:
Browse files

Support function declarations

parent fbb650cb
No related branches found
No related tags found
No related merge requests found
Pipeline #492 passed with stages
in 1 minute and 7 seconds
......@@ -168,6 +168,7 @@ pub enum ValueExpression {
ConditionalBlock(Conditional),
Identifier(Identifier),
FunctionCall(FunctionCall),
DeclareFunction(DeclareFunction),
}
#[derive(Clone)]
......@@ -344,6 +345,15 @@ pub enum DeclareIdent {
WithoutValue(Identifier),
}
#[derive(Clone)]
#[cfg_attr(feature = "debug-ast", derive(Debug))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DeclareFunction {
pub ident: Identifier,
pub params: Vec<DeclareIdent>,
pub body: ExpressionList,
}
#[derive(Clone)]
#[cfg_attr(feature = "debug-ast", derive(Debug))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
......
......@@ -33,6 +33,7 @@ peg::parser! {
= "(" ex:value_expression() ")" { ValueExpression::Grouped(GroupedExpression { inner: Box::new(ex) }) }
/ co:conditional() { ValueExpression::ConditionalBlock(co) }
/ decl:declare_variable() { ValueExpression::DeclareIdentifier(decl) }
/ decl:declare_function() { ValueExpression::DeclareFunction(decl) }
/ name:bare_identifier() "(" params:param_list()? ")"
{ ValueExpression::FunctionCall(FunctionCall { name, params: params.unwrap_or_default() }) }
/ left:value_expression() op:binary_operator() right:value_expression()
......@@ -46,8 +47,15 @@ peg::parser! {
= "print" ex:value_expression() { ex.into() }
rule declare_variable() -> DeclareIdent
= "let" assign:assignment() { DeclareIdent::WithValue(assign) }
/ "let" ident:bare_identifier() { DeclareIdent::WithoutValue(ident) }
= "let" ex:declare_identifier() { ex }
rule declare_identifier() -> DeclareIdent
= assign:assignment() { DeclareIdent::WithValue(assign) }
/ ident:bare_identifier() { DeclareIdent::WithoutValue(ident) }
rule declare_function() -> DeclareFunction
= "fn" ident:bare_identifier() "(" params:(declare_identifier() ** ",") ")" "{" block:expression_list()? "}"
{ DeclareFunction { ident, params, body: block.unwrap_or_default() } }
rule condition_loop() -> ConditionalLoop
= "while" guard:value_expression() "{" block:expression_list()? "}"
......
......@@ -58,3 +58,14 @@ fn function_calls() {
parse_program("some_func(250, if true { \"some val\" } else { \"123\" })")
.expect("Failed complex function params");
}
#[test]
fn declare_function() {
parse_program("fn some_func() {}").expect("Failed basic function");
parse_program("fn some_func(my_param) {}").expect("Failed basic function");
parse_program("fn some_func(my_param, second) {}").expect("Failed basic function");
parse_program("fn some_func(my_param, second = 1234) {}")
.expect("Failed basic function with defaults");
parse_program("fn add(first, second) { first + second }")
.expect("Failed basic function with body");
}
......@@ -161,6 +161,39 @@ impl Visitor for TreePrinter {
self.write(list.as_slice().join(", "));
self.write(")");
}
ValueExpression::DeclareFunction(declare) => {
self.write("fn ");
self.write(&declare.ident);
self.write("(");
let list = declare
.params
.iter()
.map(|param| {
let mut inner = TreePrinter {
indent: self.indent,
buffer: String::new(),
};
match param {
DeclareIdent::WithValue(assign) => {
inner.write(&assign.ident);
inner.write(" = ");
inner.evaluate_value_expression(assign.value.as_ref());
}
DeclareIdent::WithoutValue(identifier) => inner.write(identifier),
}
inner.take_value()
})
.collect::<Vec<String>>();
self.write(list.as_slice().join(", "));
self.writeln(") {");
self.increment();
self.writeln(self.format_expression_list(&declare.body));
self.decrement();
self.writeln("}");
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment