From 6acf492aa256657abfe04c700ca2742ffe00c267 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Mon, 2 Jan 2023 20:08:47 +0100
Subject: [PATCH] Interpreter - Handle function definitions

---
 src/interpreter/interpretable.rs | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/interpreter/interpretable.rs b/src/interpreter/interpretable.rs
index 43ef08b..1edb826 100644
--- a/src/interpreter/interpretable.rs
+++ b/src/interpreter/interpretable.rs
@@ -7,6 +7,8 @@ use crate::{
     tokens::{Token, TokenType},
 };
 
+use super::functions::Function;
+
 /// Evaluate an interpretable, returning its value.
 pub fn evaluate(err_hdl: &mut ErrorHandler, ast: &dyn Interpretable) -> Option<Value> {
     let env = Rc::new(RefCell::new(Environment::default()));
@@ -89,9 +91,12 @@ impl Interpretable for ast::ProgramNode {
 impl Interpretable for ast::StmtNode {
     fn interpret(&self, environment: &EnvironmentRef) -> InterpreterResult {
         match self {
+            ast::StmtNode::VarDecl(name, expr) => self.on_var_decl(environment, name, expr),
+            ast::StmtNode::FunDecl { name, params, body } => {
+                self.on_fun_decl(environment, name, params, body)
+            }
             ast::StmtNode::Expression(expr) => expr.interpret(environment),
             ast::StmtNode::Print(expr) => self.on_print(environment, expr),
-            ast::StmtNode::VarDecl(name, expr) => self.on_var_decl(environment, name, expr),
             ast::StmtNode::Block(statements) => self.on_block(environment, statements),
             ast::StmtNode::IfStmt {
                 condition,
@@ -143,6 +148,21 @@ impl ast::StmtNode {
         Ok(InterpreterFlowControl::default())
     }
 
+    /// Handle a function declaration.
+    fn on_fun_decl(
+        &self,
+        environment: &EnvironmentRef,
+        name: &Token,
+        params: &Vec<Token>,
+        body: &Vec<ast::StmtNode>,
+    ) -> InterpreterResult {
+        let fun = Function::new(name, params, body);
+        environment
+            .borrow_mut()
+            .define(name, Some(Value::Callable(fun)))?;
+        Ok(InterpreterFlowControl::default())
+    }
+
     /// Execute the contents of a block.
     fn on_block(&self, environment: &EnvironmentRef, stmts: &[ast::StmtNode]) -> InterpreterResult {
         let child = Environment::create_child(environment);