diff --git a/src/evaluator/enviroment.rs b/src/evaluator/enviroment.rs index acef164..fe84363 100644 --- a/src/evaluator/enviroment.rs +++ b/src/evaluator/enviroment.rs @@ -1,101 +1,48 @@ use std::collections::HashMap; -use super::object::Object; - -type OptionalEnvObj = Option>; - -#[derive(Debug, Clone)] -pub enum EnvObj { - OBJ(Obj), - SCOPE(Scope), -} +use crate::evaluator::object::Object; #[derive(Debug, Clone)] -pub struct Obj { - pub obj: Box, +pub struct EnvObj { pub is_const: bool, -} - -#[derive(Debug, Clone)] -pub struct Scope { - objs: HashMap, -} - -impl Scope { - pub fn set(&mut self, name: &String, obj: Obj) { - match self.objs.insert(format!("$var_{}", name), Some(Box::from(EnvObj::OBJ(obj)))) { - Some(_) => (), - None => (), - } - } - - pub fn get(&mut self, name: &String) -> Result { - match self.objs.get(&format!("$var_{}", name)) { - Some(obj) => match obj { - Some(val) => match &**val { - EnvObj::OBJ(val) => Ok(val.to_owned()), - EnvObj::SCOPE(_) => todo!(), - }, - None => todo!(), - }, - None => Err(()), - } - } + pub is_local: bool, + pub obj: Object, } #[derive(Debug, Clone)] pub struct Environment { - scope_id: i64, - objs: HashMap, + store: HashMap, } impl Environment { pub fn new() -> Self { - Self { - scope_id: 0, - objs: HashMap::new(), - } + let s = HashMap::new(); + Environment { store: s} } - pub fn set_global(&mut self, name: &String, obj: Obj) { - match self.objs.insert(format!("$var_{}", name), EnvObj::OBJ(obj)) { - Some(_) => (), - None => (), - } + pub fn get(&self, name: &String) -> Result { + let obj = match self.store.get(name) { + Some(val) => Ok(val.clone()), + None => { + Err(()) // Return an error if the key is not found + } + }; + obj } - pub fn get_global(&self, name: &String) -> Result { - match self.objs.get(&format!("$var_{}", name)) { - Some(obj) => match &obj { - EnvObj::OBJ(val) => Ok(val.to_owned()), - EnvObj::SCOPE(_) => todo!(), - }, - None => Err(()), - } + pub fn set(&mut self, name: &String, val: &Object, is_local: bool, is_const: bool) -> Object { + self.store.insert(name.to_string(), EnvObj { is_const, is_local, obj: val.to_owned() }); + val.clone() } - pub fn modify_global(&mut self, name: &String, new_val: Object) { - match self.objs.get_mut(&format!("$var_{}", name)) { - Some(val) => match val { - EnvObj::OBJ(obj) => if !obj.is_const { - obj.obj = Box::new(new_val) - } else { - todo!("Cannot modify a constant variable") - } - EnvObj::SCOPE(_) => todo!(), + pub fn modify(&mut self, name: &String, new_val: Object) { + match self.store.get_mut(name) { + Some(val) => if !val.is_const { + val.obj = new_val + } else { + todo!("Cannot modify a constant variable") }, None => todo!(), } } - - pub fn create_scope(&mut self) -> Scope { - self.scope_id += 1; - match self.objs.insert( - format!("#scope_{}", self.scope_id), - EnvObj::SCOPE(Scope { objs: HashMap::new() }), - ) { - Some(_) => Scope { objs: HashMap::new() }, - None => Scope { objs: HashMap::new() }, - } - } -} +} \ No newline at end of file diff --git a/src/evaluator/evaluator.rs b/src/evaluator/evaluator.rs index 71151cb..87bc14f 100644 --- a/src/evaluator/evaluator.rs +++ b/src/evaluator/evaluator.rs @@ -1,5 +1,3 @@ -use std::{borrow::BorrowMut, ops::DerefMut}; - use crate::{ builtin::builtins::{self, *}, parser::ast::*, @@ -7,22 +5,18 @@ use crate::{ }; use super::{ - enviroment::{EnvObj, Environment, Obj, Scope}, + enviroment::Environment, object::{self, *}, }; -#[derive(Debug, Clone)] pub struct Evaluator { env: Environment, - /// When scope is None we are in the global scope - cur_scope: Option, } impl Evaluator { pub fn new() -> Self { Self { env: Environment::new(), - cur_scope: None, } } @@ -44,36 +38,18 @@ impl Evaluator { fn eval_statement(&mut self, statement: &Statement, is_local: bool) -> Object { match statement { Statement::VAR(var) => { - let val: Object = self.eval_expression(&var.value); - match self.cur_scope { - Some(_) => todo!(), - None => self.env.set_global( - &var.name.value, - Obj { - obj: Box::from(val), - is_const: false, - }, - ), - } + let val = self.eval_expression(&var.value); + self.env.set(&var.name.value, &val, is_local, false); Object::Var(Var { - value: Box::from(self.eval_expression(&var.value)), + value: Box::from(val), is_local, }) } Statement::CONST(constant) => { let val = self.eval_expression(&constant.value); - match self.cur_scope { - Some(_) => todo!(), - None => self.env.set_global( - &constant.name.value, - Obj { - obj: Box::from(val), - is_const: true, - }, - ), - } + self.env.set(&constant.name.value, &val, is_local, true); Object::Var(Var { - value: Box::from(self.eval_expression(&constant.value)), + value: Box::from(val), is_local, }) } @@ -123,45 +99,23 @@ impl Evaluator { } fn eval_identifier(&mut self, ident: &Identifier) -> Object { - match &mut self.cur_scope { - Some(scope) => match scope.get(&ident.value) { - Ok(obj) => *obj.obj, - Err(_) => match &ident.value { - i if i == &BuiltinType::BOOLEAN.literal() => { - Object::Type(object::Type::BUILTIN(BuiltinType::BOOLEAN)) - } - i if i == &BuiltinType::NUMBER.literal() => { - Object::Type(object::Type::BUILTIN(BuiltinType::NUMBER)) - } - i if i == &BuiltinType::STRING.literal() => { - Object::Type(object::Type::BUILTIN(BuiltinType::STRING)) - } - _ => { - let err = Error::new(format!("Cannot find identifier: {}", ident.value)); - println!("scope: {:#?}", self.cur_scope); - throw_error(&err); - Object::Error(err) - } - }, - }, - None => match self.env.get_global(&ident.value) { - Ok(obj) => *obj.obj, - Err(_) => match &ident.value { - i if i == &BuiltinType::BOOLEAN.literal() => { - Object::Type(object::Type::BUILTIN(BuiltinType::BOOLEAN)) - } - i if i == &BuiltinType::NUMBER.literal() => { - Object::Type(object::Type::BUILTIN(BuiltinType::NUMBER)) - } - i if i == &BuiltinType::STRING.literal() => { - Object::Type(object::Type::BUILTIN(BuiltinType::STRING)) - } - _ => { - let err = Error::new(format!("Cannot find identifier: {}", ident.value)); - throw_error(&err); - Object::Error(err) - } - }, + match self.env.get(&ident.value) { + Ok(obj) => obj.obj, + Err(_) => match &ident.value { + i if i == &BuiltinType::BOOLEAN.literal() => { + Object::Type(object::Type::BUILTIN(BuiltinType::BOOLEAN)) + } + i if i == &BuiltinType::NUMBER.literal() => { + Object::Type(object::Type::BUILTIN(BuiltinType::NUMBER)) + } + i if i == &BuiltinType::STRING.literal() => { + Object::Type(object::Type::BUILTIN(BuiltinType::STRING)) + } + _ => { + let err = Error::new(format!("Cannot find identifier: {}", ident.value)); + throw_error(&err); + Object::Error(err) + } }, } } @@ -262,25 +216,20 @@ impl Evaluator { } fn eval_assign_infix_expression(&mut self, node: &InfixExpression, right: Object) -> Object { - match self.cur_scope { - Some(_) => todo!(), - None => { - match &*node.left { - Expression::IDENTIFIER(ident) => self.env.modify_global(&ident.value, right), - _ => todo!(), - } - match self.env.get_global( - &match &*node.left { - Expression::IDENTIFIER(ident) => ident, - _ => todo!(), - } - .value, - ) { - Ok(obj) => return *obj.obj, - Err(_) => todo!(), - }; - } + match &*node.left { + Expression::IDENTIFIER(ident) => self.env.modify(&ident.value, right), + _ => todo!(), } + match self.env.get( + &match &*node.left { + Expression::IDENTIFIER(ident) => ident, + _ => todo!(), + } + .value, + ) { + Ok(obj) => return obj.obj, + Err(_) => todo!(), + }; } fn eval_conversion_infix_expression(&mut self, node: &InfixExpression, left: Object) -> Object { @@ -496,11 +445,11 @@ impl Evaluator { Object::Num(num) => num.value as i32, _ => todo!(), }; - + for _ in left_val..right_val { self.eval_block_statement(&node.consequence); } - + return self.eval_block_statement(&node.consequence); } Object::List(list) => todo!(), @@ -585,37 +534,84 @@ impl Evaluator { Object::BuiltInFunction(func) } _ => { - let scope = self.env.create_scope(); - self.cur_scope = Some(scope); - let func = match self.env.get_global(&ident.value) { - Ok(obj) => *obj.obj, - Err(_) => todo!(), + let mut old_env = self.env.clone(); + let new_env = &self.env; + + self.env = new_env.clone(); + + let func = match self.env.get(&ident.value) { + Ok(obj) => obj, + Err(_) => { + let err = Error::new(format!( + "Cannot find identifier: {}", + ident.value.as_str() + )); + throw_error(&err); + return Object::Error(err); + } }; - let func_obj = match func { - Object::Function(func_obj) => func_obj, - _ => todo!(), + let empty_func = Function::empty(); + + let func_obj = if let Object::Function(ref func) = func.obj { + func + } else { + throw_error(&Error { + message: "Identifier is not a function".to_string(), + }); + &empty_func }; - match &mut self.cur_scope { - Some(scope) => { - for (index, arg) in func_obj.args.iter().enumerate() { - if index < node.args.len() { - self.eval_expression(&Expression::EMPTY); - scope.set(&String::new(), todo!()) - // cur_scope.set(&arg.arg.value, Obj { obj: Box::new(cur_arg), is_const: false }); - } else { - break; - } + for (index, arg) in func_obj.args.iter().enumerate() { + if index < node.args.len() { + let cur_arg = self.eval_expression(&node.args[index]); + self.env.set(&arg.arg.value, &cur_arg, false, false); + } else { + break; + } + } + + for stmt in &func_obj.body.statements { + let obj = self.eval(&stmt); + match obj { + Object::Return(ret) => { + return *ret.value; } + _ => continue, } - None => todo!(), } - todo!() + // Update all args cuz of mutability + for (index, arg) in node.args.iter().enumerate() { + let call_arg_name = match arg { + Expression::IDENTIFIER(ident) => Some(&ident.value), + _ => None, + }; + + let func_arg_name = &func_obj.args[index].arg.value; + + match call_arg_name { + Some(arg_name) => { + old_env.modify( + arg_name, + match self.env.get(func_arg_name) { + Ok(env_obj) => env_obj.obj, + Err(_) => todo!(), + }, + ); + } + None => (), + } + + // Take call args and update related vars with values from function + } + + self.env = old_env; + + func.obj } }, - _ => todo!(), + _ => todo!("{:?}", node.function), } } @@ -660,4 +656,4 @@ impl Evaluator { _ => right, } } -} +} \ No newline at end of file diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 206733c..132fd5e 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -494,7 +494,7 @@ impl<'a> Parser<'a> { let condition = Box::new(self.parse_expression(LOWEST)); - if *condition == Expression::EMPTY { + if &condition == &Box::new(Expression::EMPTY) { self.throw_error(empty_condition(&TokenType::LOOP, &condition), true); return Expression::EMPTY; } diff --git a/test/test.nx b/test/test.nx index ddd44e8..76e6451 100644 --- a/test/test.nx +++ b/test/test.nx @@ -1,5 +1,13 @@ +<<<<<<< HEAD foo :: func(x) { print(x) } -foo(0) \ No newline at end of file +foo(0) +======= +var x = [0, 0] + +loop i in 0..10 { + print(i) +} +>>>>>>> parent of 9811e27 (rewrite enviroments)