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> {
|
take_turn = (fn cards <map>, opponent_card <str>, current_room <str>) <map> {
|
||||||
cards = (remove_card opponent_card cards)
|
cards = (remove_card cards opponent_card)
|
||||||
cards = (make_guess current_room cards)
|
cards = (make_guess cards current_room)
|
||||||
cards
|
cards
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ remove_card = (fn cards <map>, opponent_card <str>) <map> {
|
|||||||
cards
|
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) {
|
if (is_ready_to_solve cards) {
|
||||||
(output 'It was '
|
(output 'It was '
|
||||||
+ cards:suspects:0
|
+ cards:suspects:0
|
||||||
|
@ -102,7 +102,15 @@ impl AbstractTree for FunctionCall {
|
|||||||
Expression::Yield(r#yield) => r#yield.run(source, context)?,
|
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> {
|
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_node = child.child(child_count - 2).unwrap();
|
||||||
let return_type =
|
let return_type =
|
||||||
TypeDefinition::from_syntax_node(source, return_type_node, context)?;
|
TypeDefinition::from_syntax_node(source, return_type_node, context)?;
|
||||||
|
|
||||||
let body_node = child.child(child_count - 1).unwrap();
|
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 {
|
let r#type = Type::Function {
|
||||||
parameter_types,
|
parameter_types,
|
||||||
return_type: Box::new(return_type.take_inner()),
|
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()),
|
"integer" => ValueNode::Integer(source[child.byte_range()].to_string()),
|
||||||
"string" => {
|
"string" => {
|
||||||
|
@ -2,17 +2,23 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
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 {
|
pub struct Function {
|
||||||
parameters: Vec<Identifier>,
|
parameters: Vec<Identifier>,
|
||||||
body: Block,
|
body: Block,
|
||||||
r#type: Type,
|
r#type: Type,
|
||||||
|
context: Map,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
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 {
|
let r#type = r#type.unwrap_or(Type::Function {
|
||||||
parameter_types: vec![Type::Any; parameters.len()],
|
parameter_types: vec![Type::Any; parameters.len()],
|
||||||
return_type: Box::new(Type::Any),
|
return_type: Box::new(Type::Any),
|
||||||
@ -22,6 +28,7 @@ impl Function {
|
|||||||
parameters,
|
parameters,
|
||||||
body,
|
body,
|
||||||
r#type,
|
r#type,
|
||||||
|
context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +54,7 @@ impl Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call(&self, arguments: &[Expression], source: &str, context: &Map) -> Result<Value> {
|
pub fn call(&self, arguments: &[Value], source: &str, context: &Map) -> Result<Value> {
|
||||||
let function_context = Map::clone_from(context)?;
|
|
||||||
|
|
||||||
if self.parameters.len() != arguments.len() {
|
if self.parameters.len() != arguments.len() {
|
||||||
return Err(Error::ExpectedArgumentAmount {
|
return Err(Error::ExpectedArgumentAmount {
|
||||||
function_name: "",
|
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) {
|
||||||
for (identifier, expression) in parameter_argument_pairs {
|
continue;
|
||||||
let value = expression.run(source, context)?;
|
|
||||||
|
|
||||||
let key = identifier.inner().clone();
|
|
||||||
|
|
||||||
function_context.set(key, value, None)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let return_value = self.body.run(source, &function_context)?;
|
self.context
|
||||||
|
.set(key.clone(), value.clone(), Some(r#type.clone()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
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 {
|
impl Display for Function {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use serde::{ser::SerializeMap, Serialize};
|
use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
@ -120,3 +120,12 @@ impl Serialize for Map {
|
|||||||
map.end()
|
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