1
0

Refine type checking and function calling

This commit is contained in:
Jeff 2023-12-17 19:06:36 -05:00
parent 70f0c6b887
commit 3bfedec5d6
5 changed files with 75 additions and 21 deletions

View File

@ -11,8 +11,8 @@ is_ready_to_solve = (fn cards <map>) <bool> {
}
take_turn = (fn cards <map>, opponent_card <str>, current_room <str>) <map> {
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 <map>, opponent_card <str>) <map> {
cards
}
make_guess = (fn cards <map> current_room <str>) <map> {
make_guess = (fn cards <map>, current_room <str>) <map> {
if (is_ready_to_solve cards) {
(output 'It was '
+ cards:suspects:0

View File

@ -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<Type> {

View File

@ -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" => {

View File

@ -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<Identifier>,
body: Block,
r#type: Type,
context: Map,
}
impl Function {
pub fn new(parameters: Vec<Identifier>, body: Block, r#type: Option<Type>) -> Self {
pub fn new(
parameters: Vec<Identifier>,
body: Block,
r#type: Option<Type>,
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<Value> {
let function_context = Map::clone_from(context)?;
pub fn call(&self, arguments: &[Value], source: &str, context: &Map) -> Result<Value> {
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!(

View File

@ -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<D>(_deserializer: D) -> std::result::Result<Self, D::Error>
where
D: Deserializer<'de>,
{
todo!()
}
}