diff --git a/examples/clue_solver.ds b/examples/clue_solver.ds index 1d18d85..dce0d5e 100644 --- a/examples/clue_solver.ds +++ b/examples/clue_solver.ds @@ -11,8 +11,8 @@ is_ready_to_solve = (fn cards ) { } take_turn = (fn cards , opponent_card , current_room ) { - cards = (remove_card opponent_card cards) - cards = (make_guess current_room cards) + cards = (remove_card cards opponent_card) + cards = (make_guess cards current_room) cards } @@ -23,7 +23,7 @@ remove_card = (fn cards , opponent_card ) { cards } -make_guess = (fn cards current_room ) { +make_guess = (fn cards , current_room ) { if (is_ready_to_solve cards) { (output 'It was ' + cards:suspects:0 diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 80a188c..388dbd3 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -102,7 +102,15 @@ impl AbstractTree for FunctionCall { Expression::Yield(r#yield) => r#yield.run(source, context)?, }; - value.as_function()?.call(&self.arguments, source, context) + let mut arguments = Vec::with_capacity(self.arguments.len()); + + for expression in &self.arguments { + let value = expression.run(source, context)?; + + arguments.push(value); + } + + value.as_function()?.call(&arguments, source, context) } fn expected_type(&self, context: &Map) -> Result { diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index ae02655..bc57c67 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -50,19 +50,36 @@ impl AbstractTree for ValueNode { } } + let function_context = Map::clone_from(context)?; + + for (parameter_name, parameter_type) in + parameters.iter().zip(parameter_types.iter()) + { + function_context.set( + parameter_name.inner().clone(), + Value::Empty, + Some(parameter_type.clone()), + )?; + } + let return_type_node = child.child(child_count - 2).unwrap(); let return_type = TypeDefinition::from_syntax_node(source, return_type_node, context)?; let body_node = child.child(child_count - 1).unwrap(); - let body = Block::from_syntax_node(source, body_node, context)?; + let body = Block::from_syntax_node(source, body_node, &function_context)?; let r#type = Type::Function { parameter_types, return_type: Box::new(return_type.take_inner()), }; - ValueNode::Function(Function::new(parameters, body, Some(r#type))) + ValueNode::Function(Function::new( + parameters, + body, + Some(r#type), + function_context, + )) } "integer" => ValueNode::Integer(source[child.byte_range()].to_string()), "string" => { diff --git a/src/value/function.rs b/src/value/function.rs index 498bda6..e7199b2 100644 --- a/src/value/function.rs +++ b/src/value/function.rs @@ -2,17 +2,23 @@ use std::fmt::{self, Display, Formatter}; use serde::{Deserialize, Serialize}; -use crate::{AbstractTree, Block, Error, Expression, Identifier, Map, Result, Type, Value}; +use crate::{AbstractTree, Block, Error, Identifier, Map, Result, Type, Value}; -#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialOrd, Ord)] pub struct Function { parameters: Vec, body: Block, r#type: Type, + context: Map, } impl Function { - pub fn new(parameters: Vec, body: Block, r#type: Option) -> Self { + pub fn new( + parameters: Vec, + body: Block, + r#type: Option, + context: Map, + ) -> Self { let r#type = r#type.unwrap_or(Type::Function { parameter_types: vec![Type::Any; parameters.len()], return_type: Box::new(Type::Any), @@ -22,6 +28,7 @@ impl Function { parameters, body, r#type, + context, } } @@ -47,9 +54,7 @@ impl Function { } } - pub fn call(&self, arguments: &[Expression], source: &str, context: &Map) -> Result { - let function_context = Map::clone_from(context)?; - + pub fn call(&self, arguments: &[Value], source: &str, context: &Map) -> Result { if self.parameters.len() != arguments.len() { return Err(Error::ExpectedArgumentAmount { function_name: "", @@ -58,22 +63,37 @@ impl Function { }); } - let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter()); + for (key, (value, r#type)) in context.variables()?.iter() { + if self.context.variables()?.contains_key(key) { + continue; + } - for (identifier, expression) in parameter_argument_pairs { - let value = expression.run(source, context)?; - - let key = identifier.inner().clone(); - - function_context.set(key, value, None)?; + self.context + .set(key.clone(), value.clone(), Some(r#type.clone()))?; } - let return_value = self.body.run(source, &function_context)?; + let parameter_argument_pairs = self.parameters.iter().zip(arguments.iter()); + + for (identifier, value) in parameter_argument_pairs { + let key = identifier.inner().clone(); + + self.context.set(key, value.clone(), None)?; + } + + let return_value = self.body.run(source, &self.context)?; Ok(return_value) } } +impl PartialEq for Function { + fn eq(&self, other: &Self) -> bool { + self.r#type.eq(&other.r#type) + && self.parameters.eq(&other.parameters) + && self.body.eq(&other.body) + } +} + impl Display for Function { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( diff --git a/src/value/map.rs b/src/value/map.rs index d7f3799..e56a2c3 100644 --- a/src/value/map.rs +++ b/src/value/map.rs @@ -1,4 +1,4 @@ -use serde::{ser::SerializeMap, Serialize}; +use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize}; use std::{ cmp::Ordering, collections::BTreeMap, @@ -120,3 +120,12 @@ impl Serialize for Map { map.end() } } + +impl<'de> Deserialize<'de> for Map { + fn deserialize(_deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + todo!() + } +}