Refine type checking and function calling
This commit is contained in:
parent
70f0c6b887
commit
3bfedec5d6
@ -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
|
||||
|
@ -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> {
|
||||
|
@ -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" => {
|
||||
|
@ -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!(
|
||||
|
@ -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!()
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user