From d47adab0f85a2103d71fab7307b5638d620a1e44 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Mon, 2 Jan 2023 17:45:56 +0100
Subject: [PATCH] Interpreter - Call implementation

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

diff --git a/src/interpreter/interpretable.rs b/src/interpreter/interpretable.rs
index dd04150..fad7aca 100644
--- a/src/interpreter/interpretable.rs
+++ b/src/interpreter/interpretable.rs
@@ -122,6 +122,7 @@ impl ast::StmtNode {
             Value::Boolean(false) => String::from("false"),
             Value::Number(n) => n.to_string(),
             Value::String(s) => s,
+            Value::Callable(c) => c.borrow().to_string(),
         };
         println!("{}", output);
         Ok(InterpreterFlowControl::default())
@@ -243,6 +244,11 @@ impl Interpretable for ast::ExprNode {
             ast::ExprNode::Grouping { expression } => expression.interprete(environment),
             ast::ExprNode::Litteral { value } => self.on_litteral(value),
             ast::ExprNode::Variable { name } => Ok(environment.borrow().get(name)?.into()),
+            ast::ExprNode::Call {
+                callee,
+                right_paren,
+                arguments,
+            } => self.on_call(environment, callee, right_paren, arguments),
         }
     }
 }
@@ -375,4 +381,30 @@ impl ast::ExprNode {
         };
         Ok(out_value.into())
     }
+
+    /// Evaluate a function call.
+    fn on_call(
+        &self,
+        environment: &EnvironmentRef,
+        callee: &ast::ExprNode,
+        right_paren: &Token,
+        arguments: &Vec<ast::ExprNode>,
+    ) -> InterpreterResult {
+        let callee = callee.interprete(environment)?.result();
+        let arg_values = {
+            let mut v = Vec::with_capacity(arguments.len());
+            for argument in arguments.iter() {
+                v.push(argument.interprete(environment)?.result());
+            }
+            v
+        };
+        if let Value::Callable(callable) = &callee {
+            Ok(callable.borrow().call(environment, arg_values)?.into())
+        } else {
+            Err(InterpreterError::new(
+                right_paren,
+                "can only call functions and classes",
+            ))
+        }
+    }
 }