From e5c8167629f5443893198e504ad03e526469d5dc Mon Sep 17 00:00:00 2001 From: nulluser Date: Sun, 2 Jun 2024 02:31:22 +1000 Subject: [PATCH] basic function calling works, but parent relationshop for environments is broken --- src/backend/environment.rs | 2 +- src/backend/eval/expressions.rs | 33 +++++++++++++++++++++++++++------ src/backend/eval/statements.rs | 24 ++++++++++++++++++++++-- src/backend/interpreter.rs | 7 ++++--- src/backend/values.rs | 9 ++++++--- src/frontend/ast.rs | 12 ++++++------ 6 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/backend/environment.rs b/src/backend/environment.rs index 917b6de..c4f7954 100644 --- a/src/backend/environment.rs +++ b/src/backend/environment.rs @@ -8,7 +8,7 @@ use crate::{mk_bool, mk_native_fn, mk_null}; use super::native_fn::{native_println, native_time}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct Environment<'a> { values: HashMap, is_mutable: HashSet, diff --git a/src/backend/eval/expressions.rs b/src/backend/eval/expressions.rs index ee3feed..745f47a 100644 --- a/src/backend/eval/expressions.rs +++ b/src/backend/eval/expressions.rs @@ -3,10 +3,11 @@ use std::collections::HashMap; use crate::{ backend::{ environment::Environment, - values::{FloatVal, IntegerVal, ObjectVal, ToFloat, Val}, + interpreter::evaluate, + values::{FloatVal, IntegerVal, NullVal, ObjectVal, ToFloat, Val}, }, frontend::ast::{BinaryOp, Expr, Literal, Property}, - mk_float, mk_integer, + mk_float, mk_integer, mk_null, }; pub fn evaluate_expr(expr: Expr, env: &mut Environment) -> Val { @@ -61,11 +62,31 @@ pub fn evaluate_call_expr(args: Vec, caller: Expr, env: &mut Environment) .map(|expr| evaluate_expr(expr, env)) .collect(); let function = evaluate_expr(caller, env); - let callable = match function { - Val::NativeFunction(callable) => callable.call, - _ => panic!("Cannot call value that is not a function: {:?}", function), + match &function { + Val::NativeFunction(callable) => return (callable.call)(evaluated_args, env), + Val::Function(fn_value) => { + let mut scope = Environment::new_with_parent(env); + println!("{:#?}", scope); + for (i, _) in evaluated_args + .iter() + .enumerate() + .take(fn_value.parameters.len()) + { + // TODO: Check the bounds here. + // Verify arity of function. + let varname = &fn_value.parameters[i]; + let arg = &evaluated_args[i]; + scope.declare_var(varname, arg.clone(), false); + } + let mut result: Val = mk_null!(); + for stmt in &fn_value.body { + result = evaluate(stmt.clone(), &mut scope) + } + return result; + } + _ => {} }; - callable(evaluated_args, env) + panic!("Cannot call value that is not a function: {:?}", function); } pub fn evaluate_binary_op(op: BinaryOp, left: Expr, right: Expr, env: &mut Environment) -> Val { diff --git a/src/backend/eval/statements.rs b/src/backend/eval/statements.rs index 9c0fe94..6ddc569 100644 --- a/src/backend/eval/statements.rs +++ b/src/backend/eval/statements.rs @@ -1,6 +1,9 @@ use crate::{ - backend::{environment::Environment, values::NullVal, values::Val}, - frontend::ast::Expr, + backend::{ + environment::Environment, + values::{FunctionVal, NullVal, Val}, + }, + frontend::ast::{Expr, Stmt}, mk_null, }; @@ -20,3 +23,20 @@ pub fn evaluate_declare_var( env.declare_var(&name, value, is_mutable) } + +pub fn evaluate_declare_fn( + parameters: Vec, + name: String, + body: Vec, + is_async: bool, + env: &mut Environment, +) -> Val { + let function: Val = Val::Function(FunctionVal { + name: name.clone(), + parameters, + body, + is_async, + }); + + env.declare_var(&name, function, false) +} diff --git a/src/backend/interpreter.rs b/src/backend/interpreter.rs index c25a22e..59bde90 100644 --- a/src/backend/interpreter.rs +++ b/src/backend/interpreter.rs @@ -4,7 +4,7 @@ use crate::frontend::ast::Stmt; use super::environment::Environment; use super::eval::expressions::evaluate_expr; -use super::eval::statements::evaluate_declare_var; +use super::eval::statements::{evaluate_declare_fn, evaluate_declare_var}; use super::values::Val; pub fn evaluate(stmt: Stmt, env: &mut Environment) -> Val { @@ -15,7 +15,8 @@ pub fn evaluate(stmt: Stmt, env: &mut Environment) -> Val { } Stmt::ReturnStmt(_) => unimplemented!(), Stmt::IfStmt(_, _, _) => unimplemented!(), - Stmt::FunctionDeclaration(parameters, name, body, is_async) => todo!(), - // Handle other statement types... + Stmt::FunctionDeclaration(parameters, name, body, is_async) => { + evaluate_declare_fn(parameters, name, body, is_async, env) + } // Handle other statement types... } } diff --git a/src/backend/values.rs b/src/backend/values.rs index 7be9847..724efd1 100644 --- a/src/backend/values.rs +++ b/src/backend/values.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; +use crate::frontend::ast::Stmt; + use super::environment::Environment; #[derive(Debug, PartialEq)] @@ -95,9 +97,10 @@ impl RuntimeVal for NativeFunctionVal { #[derive(Debug, PartialEq, Clone)] pub struct FunctionVal { - name: String, - parameters: Vec, - declaration_env: &Environment, + pub name: String, + pub parameters: Vec, + pub body: Vec, + pub is_async: bool, } impl RuntimeVal for FunctionVal { diff --git a/src/frontend/ast.rs b/src/frontend/ast.rs index b87cef7..88e0852 100644 --- a/src/frontend/ast.rs +++ b/src/frontend/ast.rs @@ -14,7 +14,7 @@ impl Program { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub enum Expr { Literal(Literal), Identifier(String), @@ -38,7 +38,7 @@ impl std::fmt::Display for Expr { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub enum Stmt { ExprStmt(Expr), DeclareStmt(String, bool, Option), // Name, is_mutable, expr @@ -47,7 +47,7 @@ pub enum Stmt { IfStmt(Expr, Vec, Vec), } -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub enum Literal { Integer(i64), Float(f64), @@ -56,13 +56,13 @@ pub enum Literal { // Other literal types... } -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub struct Property { pub key: String, pub value: Option, } -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub enum BinaryOp { Add, Subtract, @@ -100,7 +100,7 @@ impl From for BinaryOp { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Clone)] pub enum UnaryOp { Negate, // Other unary operators...