Refactor function types

This commit is contained in:
Jeff 2024-06-23 22:39:33 -04:00
parent 572d5a9d18
commit af20dab0d2
8 changed files with 209 additions and 171 deletions

View File

@ -1,7 +1,4 @@
use std::{ use std::cmp::Ordering;
cmp::Ordering,
sync::{Arc, Mutex},
};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -17,23 +14,23 @@ use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
pub struct FunctionCall { pub struct FunctionCall {
function_expression: Box<Expression>, function_expression: Box<Expression>,
type_arguments: Option<Vec<TypeConstructor>>, type_arguments: Option<Vec<TypeConstructor>>,
value_arguments: Vec<Expression>, value_arguments: Option<Vec<Expression>>,
#[serde(skip)] #[serde(skip)]
context: Arc<Mutex<Option<Context>>>, context: Context,
} }
impl FunctionCall { impl FunctionCall {
pub fn new( pub fn new(
function_expression: Expression, function_expression: Expression,
type_arguments: Option<Vec<TypeConstructor>>, type_arguments: Option<Vec<TypeConstructor>>,
value_arguments: Vec<Expression>, value_arguments: Option<Vec<Expression>>,
) -> Self { ) -> Self {
FunctionCall { FunctionCall {
function_expression: Box::new(function_expression), function_expression: Box::new(function_expression),
type_arguments, type_arguments,
value_arguments, value_arguments,
context: Arc::new(Mutex::new(None)), context: Context::new(None),
} }
} }
@ -44,24 +41,49 @@ impl FunctionCall {
impl AbstractNode for FunctionCall { impl AbstractNode for FunctionCall {
fn define_types(&self, context: &Context) -> Result<(), ValidationError> { fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
*self.context.lock()? = Some(context.create_child());
self.function_expression.define_types(context)?; self.function_expression.define_types(context)?;
let mut previous = (); let (type_parameters, value_parameters) =
if let Some(r#type) = self.function_expression.expected_type(context)? {
if let Type::Function {
type_parameters,
value_parameters,
..
} = r#type
{
(type_parameters, value_parameters)
} else {
return Err(ValidationError::ExpectedFunction {
actual: r#type,
position: self.function_expression.position(),
});
}
} else {
todo!("Create an error for this occurence");
};
for expression in &self.value_arguments { if let (Some(type_parameters), Some(type_arguments)) =
previous = expression.define_types(context)?; (type_parameters, &self.type_arguments)
{
for (identifier, constructor) in
type_parameters.into_iter().zip(type_arguments.into_iter())
{
let r#type = constructor.construct(context)?;
self.context.set_type(identifier, r#type)?;
}
} }
Ok(previous) Ok(())
} }
fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> { fn validate(&self, context: &Context, manage_memory: bool) -> Result<(), ValidationError> {
self.function_expression.validate(context, manage_memory)?; self.function_expression.validate(context, manage_memory)?;
for expression in &self.value_arguments { if let Some(value_arguments) = &self.value_arguments {
expression.validate(context, manage_memory)?; for expression in value_arguments {
expression.validate(context, manage_memory)?;
}
} }
let function_node_type = let function_node_type =
@ -126,11 +148,6 @@ impl AbstractNode for FunctionCall {
}, },
)); ));
}; };
let function_context = if let Some(context) = self.context.lock()?.clone() {
context
} else {
todo!("New error for out-of-order execution.")
};
match (function.type_parameters(), self.type_arguments) { match (function.type_parameters(), self.type_arguments) {
(Some(type_parameters), Some(type_arguments)) => { (Some(type_parameters), Some(type_arguments)) => {
@ -139,103 +156,59 @@ impl AbstractNode for FunctionCall {
{ {
let r#type = constructor.construct(context)?; let r#type = constructor.construct(context)?;
function_context.set_type(parameter.clone(), r#type)?; self.context.set_type(parameter.clone(), r#type)?;
} }
} }
_ => {} _ => {}
} }
for ((identifier, _), expression) in function if let (Some(value_parameters), Some(value_arguments)) =
.value_parameters() (function.value_parameters(), self.value_arguments)
.into_iter()
.zip(self.value_arguments.iter())
{ {
let expression_position = expression.position(); for ((identifier, _), expression) in
let evaluation = expression.clone().evaluate(context, clear_variables)?; value_parameters.into_iter().zip(value_arguments.iter())
let value = if let Some(Evaluation::Return(value)) = evaluation { {
value let expression_position = expression.position();
} else { let evaluation = expression.clone().evaluate(context, clear_variables)?;
return Err(RuntimeError::ValidationFailure( let value = if let Some(Evaluation::Return(value)) = evaluation {
ValidationError::ExpectedExpression(expression_position), value
)); } else {
}; return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedExpression(expression_position),
));
};
function_context.set_value(identifier.clone(), value)?; self.context.set_value(identifier.clone(), value)?;
}
} }
function.clone().call(&function_context, clear_variables) function.clone().call(&self.context, clear_variables)
} }
fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> { fn expected_type(&self, context: &Context) -> Result<Option<Type>, ValidationError> {
let function_type = if let Some(r#type) = self.function_expression.expected_type(context)? { let return_type = if let Some(r#type) = self.function_expression.expected_type(context)? {
r#type if let Type::Function {
type_parameters,
value_parameters,
return_type,
} = r#type
{
return_type
} else {
return Err(ValidationError::ExpectedFunction {
actual: r#type,
position: self.function_expression.position(),
});
}
} else { } else {
return Err(ValidationError::ExpectedExpression( return Err(ValidationError::ExpectedExpression(
self.function_expression.position(), self.function_expression.position(),
)); ));
}; };
if let Type::Function { let return_type = return_type.map(|r#box| *r#box);
return_type,
type_parameters,
..
} = function_type
{
let return_type = return_type.map(|r#box| *r#box);
if let Some(Type::Generic { Ok(return_type)
identifier: return_identifier,
..
}) = &return_type
{
if let (Some(type_arguments), Some(type_parameters)) =
(&self.type_arguments, &type_parameters)
{
for (constructor, identifier) in
type_arguments.into_iter().zip(type_parameters.into_iter())
{
if identifier == return_identifier {
let concrete_type = constructor.clone().construct(&context)?;
return Ok(Some(Type::Generic {
identifier: identifier.clone(),
concrete_type: Some(Box::new(concrete_type)),
}));
}
}
}
if let (None, Some(type_parameters)) = (&self.type_arguments, type_parameters) {
for (expression, identifier) in (&self.value_arguments)
.into_iter()
.zip(type_parameters.into_iter())
{
if &identifier == return_identifier {
let concrete_type =
if let Some(r#type) = expression.expected_type(context)? {
r#type
} else {
return Err(ValidationError::ExpectedExpression(
expression.position(),
));
};
return Ok(Some(Type::Generic {
identifier,
concrete_type: Some(Box::new(concrete_type)),
}));
}
}
}
}
Ok(return_type)
} else {
Err(ValidationError::ExpectedFunction {
actual: function_type,
position: self.function_expression.position(),
})
}
} }
} }

View File

@ -17,7 +17,7 @@ pub enum Type {
Float, Float,
Function { Function {
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<Type>, value_parameters: Option<Vec<(Identifier, Type)>>,
return_type: Option<Box<Type>>, return_type: Option<Box<Type>>,
}, },
Generic { Generic {
@ -255,14 +255,16 @@ impl Display for Type {
write!(f, ")(")?; write!(f, ")(")?;
} }
for r#type in value_parameters { if let Some(value_parameters) = value_parameters {
write!(f, "{type}")?; for (identifier, r#type) in value_parameters {
write!(f, "{identifier}: {type}")?;
}
} }
write!(f, ")")?; write!(f, ")")?;
if let Some(r#type) = return_type { if let Some(r#type) = return_type {
write!(f, " -> {}", r#type) write!(f, " -> {type}")
} else { } else {
Ok(()) Ok(())
} }

View File

@ -135,13 +135,20 @@ impl TypeConstructor {
.map(|identifier| identifier.node.clone()) .map(|identifier| identifier.node.clone())
.collect() .collect()
}); });
let mut value_parameters = Vec::with_capacity(declared_value_parameters.len()); let value_parameters =
if let Some(declared_value_parameters) = declared_value_parameters {
let mut parameters = Vec::with_capacity(declared_value_parameters.len());
for parameter in declared_value_parameters { for (identifier, constructor) in declared_value_parameters {
let r#type = parameter.construct(&context)?; let r#type = constructor.construct(&context)?;
value_parameters.push(r#type); parameters.push((identifier.node.clone(), r#type));
} }
Some(parameters)
} else {
None
};
let return_type = if let Some(constructor) = return_type { let return_type = if let Some(constructor) = return_type {
Some(Box::new(constructor.construct(context)?)) Some(Box::new(constructor.construct(context)?))
@ -200,7 +207,7 @@ pub struct EnumTypeConstructor {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionTypeConstructor { pub struct FunctionTypeConstructor {
pub type_parameters: Option<Vec<WithPosition<Identifier>>>, pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
pub value_parameters: Vec<TypeConstructor>, pub value_parameters: Option<Vec<(WithPosition<Identifier>, TypeConstructor)>>,
pub return_type: Option<Box<TypeConstructor>>, pub return_type: Option<Box<TypeConstructor>>,
} }

View File

@ -37,7 +37,7 @@ pub enum ValueNode {
impl ValueNode { impl ValueNode {
pub fn function( pub fn function(
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, TypeConstructor)>, value_parameters: Option<Vec<(Identifier, TypeConstructor)>>,
return_type: Option<TypeConstructor>, return_type: Option<TypeConstructor>,
body: WithPosition<Block>, body: WithPosition<Block>,
) -> Self { ) -> Self {
@ -95,10 +95,12 @@ impl AbstractNode for ValueNode {
} }
} }
for (identifier, type_constructor) in value_parameters { if let Some(value_parameters) = value_parameters {
let r#type = type_constructor.clone().construct(outer_context)?; for (identifier, type_constructor) in value_parameters {
let r#type = type_constructor.clone().construct(outer_context)?;
context_template.set_type(identifier.clone(), r#type)?; context_template.set_type(identifier.clone(), r#type)?;
}
} }
body.node.define_types(context_template)?; body.node.define_types(context_template)?;
@ -310,20 +312,25 @@ impl AbstractNode for ValueNode {
ValueNode::String(string) => Value::string(string), ValueNode::String(string) => Value::string(string),
ValueNode::Function(FunctionNode { ValueNode::Function(FunctionNode {
type_parameters, type_parameters,
value_parameters: constructors, value_parameters,
return_type, return_type,
body, body,
context_template, context_template,
}) => { }) => {
let outer_context = context; let outer_context = context;
let mut value_parameters = Vec::with_capacity(constructors.len()); let value_parameters = if let Some(value_parameters) = value_parameters {
let mut parameters = Vec::with_capacity(value_parameters.len());
for (identifier, constructor) in constructors { for (identifier, constructor) in value_parameters {
let r#type = constructor.construct(&outer_context)?; let r#type = constructor.construct(&outer_context)?;
value_parameters.push((identifier, r#type)); parameters.push((identifier, r#type));
} }
Some(parameters)
} else {
None
};
let return_type = if let Some(constructor) = return_type { let return_type = if let Some(constructor) = return_type {
Some(constructor.construct(&outer_context)?) Some(constructor.construct(&outer_context)?)
} else { } else {
@ -402,13 +409,19 @@ impl AbstractNode for ValueNode {
return_type, return_type,
.. ..
}) => { }) => {
let mut value_parameter_types = Vec::with_capacity(value_parameters.len()); let value_parameters = if let Some(value_parameters) = value_parameters {
let mut parameters = Vec::with_capacity(value_parameters.len());
for (_, type_constructor) in value_parameters { for (identifier, type_constructor) in value_parameters {
let r#type = type_constructor.clone().construct(&context)?; let r#type = type_constructor.clone().construct(&context)?;
value_parameter_types.push(r#type); parameters.push((identifier.clone(), r#type));
} }
Some(parameters)
} else {
None
};
let type_parameters = type_parameters.clone().map(|parameters| { let type_parameters = type_parameters.clone().map(|parameters| {
parameters parameters
@ -424,7 +437,7 @@ impl AbstractNode for ValueNode {
Type::Function { Type::Function {
type_parameters, type_parameters,
value_parameters: value_parameter_types, value_parameters,
return_type, return_type,
} }
} }
@ -586,7 +599,7 @@ impl Ord for ValueNode {
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FunctionNode { pub struct FunctionNode {
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, TypeConstructor)>, value_parameters: Option<Vec<(Identifier, TypeConstructor)>>,
return_type: Option<TypeConstructor>, return_type: Option<TypeConstructor>,
body: WithPosition<Block>, body: WithPosition<Block>,
#[serde(skip)] #[serde(skip)]

View File

@ -104,8 +104,10 @@ pub fn parser<'src>(
.or_not(), .or_not(),
) )
.then( .then(
type_constructor positioned_identifier
.clone() .clone()
.then_ignore(just(Token::Symbol(Symbol::Colon)))
.then(type_constructor.clone())
.separated_by(just(Token::Symbol(Symbol::Comma))) .separated_by(just(Token::Symbol(Symbol::Comma)))
.collect() .collect()
.delimited_by( .delimited_by(
@ -119,7 +121,20 @@ pub fn parser<'src>(
.or_not(), .or_not(),
) )
.map_with( .map_with(
|((type_parameters, value_parameters), return_type), state| { |((type_parameters, value_parameters), return_type): (
(
Option<Vec<WithPosition<Identifier>>>,
Vec<(WithPosition<Identifier>, TypeConstructor)>,
),
Option<TypeConstructor>,
),
state| {
let value_parameters = if value_parameters.is_empty() {
None
} else {
Some(value_parameters)
};
TypeConstructor::Function( TypeConstructor::Function(
FunctionTypeConstructor { FunctionTypeConstructor {
type_parameters, type_parameters,
@ -290,7 +305,20 @@ pub fn parser<'src>(
) )
.then(block.clone()) .then(block.clone())
.map_with( .map_with(
|(((type_parameters, value_parameters), return_type), body), state| { |(((type_parameters, value_parameters), return_type), body): (
(
(Option<Vec<Identifier>>, Vec<(Identifier, TypeConstructor)>),
Option<TypeConstructor>,
),
WithPosition<Block>,
),
state| {
let value_parameters = if value_parameters.is_empty() {
None
} else {
Some(value_parameters)
};
Expression::Value( Expression::Value(
ValueNode::function( ValueNode::function(
type_parameters, type_parameters,
@ -561,7 +589,18 @@ pub fn parser<'src>(
just(Token::Symbol(Symbol::ParenClose)), just(Token::Symbol(Symbol::ParenClose)),
), ),
), ),
|function_expression, (type_parameters, value_parameters), span| { |function_expression,
(type_parameters, value_parameters): (
Option<Vec<TypeConstructor>>,
Vec<Expression>,
),
span| {
let value_parameters = if value_parameters.is_empty() {
None
} else {
Some(value_parameters)
};
Expression::FunctionCall( Expression::FunctionCall(
FunctionCall::new( FunctionCall::new(
function_expression, function_expression,

View File

@ -344,9 +344,9 @@ fn r#while() {
FunctionCall::new( FunctionCall::new(
Expression::Identifier(Identifier::new("output").with_position((13, 19))), Expression::Identifier(Identifier::new("output").with_position((13, 19))),
None, None,
vec![Expression::Value( Some(vec![Expression::Value(
ValueNode::String("hi".to_string()).with_position((20, 24)) ValueNode::String("hi".to_string()).with_position((20, 24))
)] )])
) )
.with_position((13, 25)) .with_position((13, 25))
))] ))]
@ -431,22 +431,25 @@ fn list_of_type() {
#[test] #[test]
fn function_type() { fn function_type() {
assert_eq!( assert_eq!(
parse(&lex("type Foo = fn |T| (int)").unwrap()).unwrap()[0], parse(&lex("type Foo = fn |T| (x: int)").unwrap()).unwrap()[0],
Statement::TypeAlias( Statement::TypeAlias(
TypeAlias::new( TypeAlias::new(
Identifier::new("Foo").with_position((5, 8)), Identifier::new("Foo").with_position((5, 8)),
TypeConstructor::Function( TypeConstructor::Function(
FunctionTypeConstructor { FunctionTypeConstructor {
type_parameters: Some(vec![Identifier::new("T").with_position((15, 16))]), type_parameters: Some(vec![Identifier::new("T").with_position((15, 16))]),
value_parameters: vec![TypeConstructor::Raw( value_parameters: Some(vec![(
RawTypeConstructor::Integer.with_position((19, 22)) Identifier::new("x").with_position((19, 20)),
)], TypeConstructor::Raw(
RawTypeConstructor::Integer.with_position((22, 25))
)
)]),
return_type: None return_type: None
} }
.with_position((11, 23)) .with_position((11, 26))
) )
) )
.with_position((0, 23)) .with_position((0, 26))
) )
); );
} }
@ -454,27 +457,30 @@ fn function_type() {
#[test] #[test]
fn function_type_with_return() { fn function_type_with_return() {
assert_eq!( assert_eq!(
parse(&lex("type Foo = fn |T| (int) -> T").unwrap()).unwrap()[0], parse(&lex("type Foo = fn |T| (x: int) -> T").unwrap()).unwrap()[0],
Statement::TypeAlias( Statement::TypeAlias(
TypeAlias::new( TypeAlias::new(
Identifier::new("Foo").with_position((5, 8)), Identifier::new("Foo").with_position((5, 8)),
TypeConstructor::Function( TypeConstructor::Function(
FunctionTypeConstructor { FunctionTypeConstructor {
type_parameters: Some(vec![Identifier::new("T").with_position((15, 16))]), type_parameters: Some(vec![Identifier::new("T").with_position((15, 16))]),
value_parameters: vec![TypeConstructor::Raw( value_parameters: Some(vec![(
RawTypeConstructor::Integer.with_position((19, 22)) Identifier::new("x").with_position((19, 20)),
)], TypeConstructor::Raw(
RawTypeConstructor::Integer.with_position((22, 25))
)
)]),
return_type: Some(Box::new(TypeConstructor::Invokation( return_type: Some(Box::new(TypeConstructor::Invokation(
TypeInvokationConstructor { TypeInvokationConstructor {
identifier: Identifier::new("T").with_position((27, 28)), identifier: Identifier::new("T").with_position((30, 31)),
type_arguments: None type_arguments: None
} }
))) )))
} }
.with_position((11, 28)) .with_position((11, 31))
) )
) )
.with_position((0, 28)) .with_position((0, 31))
) )
); );
} }
@ -487,7 +493,7 @@ fn function_call() {
FunctionCall::new( FunctionCall::new(
Expression::Identifier(Identifier::new("foobar").with_position((0, 6))), Expression::Identifier(Identifier::new("foobar").with_position((0, 6))),
None, None,
Vec::with_capacity(0), None,
) )
.with_position((0, 8)) .with_position((0, 8))
)) ))
@ -504,9 +510,9 @@ fn function_call_with_type_arguments() {
Some(vec![TypeConstructor::Raw( Some(vec![TypeConstructor::Raw(
RawTypeConstructor::String.with_position((9, 12)) RawTypeConstructor::String.with_position((9, 12))
)]), )]),
vec![Expression::Value( Some(vec![Expression::Value(
ValueNode::String("hi".to_string()).with_position((16, 20)) ValueNode::String("hi".to_string()).with_position((16, 20))
)], )]),
) )
.with_position((0, 21)) .with_position((0, 21))
)) ))
@ -530,7 +536,7 @@ fn function() {
Statement::Expression(Expression::Value( Statement::Expression(Expression::Value(
ValueNode::function( ValueNode::function(
None, None,
vec![], None,
Some(TypeConstructor::Raw( Some(TypeConstructor::Raw(
RawTypeConstructor::Integer.with_position((9, 12)) RawTypeConstructor::Integer.with_position((9, 12))
)), )),
@ -548,10 +554,10 @@ fn function() {
Statement::Expression(Expression::Value( Statement::Expression(Expression::Value(
ValueNode::function( ValueNode::function(
None, None,
vec![( Some(vec![(
Identifier::new("x"), Identifier::new("x"),
TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10))) TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10)))
)], )]),
Some(TypeConstructor::Raw( Some(TypeConstructor::Raw(
RawTypeConstructor::Integer.with_position((15, 18)) RawTypeConstructor::Integer.with_position((15, 18))
)), )),
@ -572,7 +578,7 @@ fn function_with_type_arguments() {
Statement::Expression(Expression::Value( Statement::Expression(Expression::Value(
ValueNode::function( ValueNode::function(
Some(vec![Identifier::new("T"), Identifier::new("U"),]), Some(vec![Identifier::new("T"), Identifier::new("U"),]),
vec![ Some(vec![
( (
Identifier::new("x"), Identifier::new("x"),
TypeConstructor::Invokation(TypeInvokationConstructor { TypeConstructor::Invokation(TypeInvokationConstructor {
@ -587,7 +593,7 @@ fn function_with_type_arguments() {
type_arguments: None, type_arguments: None,
}) })
) )
], ]),
Some(TypeConstructor::Invokation(TypeInvokationConstructor { Some(TypeConstructor::Invokation(TypeInvokationConstructor {
identifier: Identifier::new("T").with_position((26, 27)), identifier: Identifier::new("T").with_position((26, 27)),
type_arguments: None, type_arguments: None,

View File

@ -70,7 +70,7 @@ impl Value {
pub fn function( pub fn function(
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, Type)>, value_parameters: Option<Vec<(Identifier, Type)>>,
return_type: Option<Type>, return_type: Option<Type>,
body: Block, body: Block,
context_template: Context, context_template: Context,
@ -166,7 +166,7 @@ impl Display for Value {
ValueInner::String(string) => write!(f, "{string}"), ValueInner::String(string) => write!(f, "{string}"),
ValueInner::Function(Function { ValueInner::Function(Function {
type_parameters, type_parameters,
value_parameters: parameters, value_parameters,
return_type, return_type,
body, body,
.. ..
@ -187,8 +187,10 @@ impl Display for Value {
write!(f, "(")?; write!(f, "(")?;
for (identifier, r#type) in parameters { if let Some(value_parameters) = value_parameters {
write!(f, "{identifier}: {}", r#type)?; for (identifier, r#type) in value_parameters {
write!(f, "{identifier}: {}", r#type)?;
}
} }
write!(f, ")")?; write!(f, ")")?;
@ -594,17 +596,11 @@ impl ValueInner {
ValueInner::Range(_) => Type::Range, ValueInner::Range(_) => Type::Range,
ValueInner::String(_) => Type::String, ValueInner::String(_) => Type::String,
ValueInner::Function(function) => { ValueInner::Function(function) => {
let value_parameters = function
.value_parameters()
.into_iter()
.map(|(_, r#type)| r#type)
.cloned()
.collect();
let return_type = function.return_type.clone().map(|r#type| Box::new(r#type)); let return_type = function.return_type.clone().map(|r#type| Box::new(r#type));
Type::Function { Type::Function {
type_parameters: function.type_parameters().clone(), type_parameters: function.type_parameters().clone(),
value_parameters, value_parameters: function.value_parameters().clone(),
return_type, return_type,
} }
} }
@ -714,7 +710,7 @@ impl Ord for ValueInner {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Function { pub struct Function {
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, Type)>, value_parameters: Option<Vec<(Identifier, Type)>>,
return_type: Option<Type>, return_type: Option<Type>,
body: Block, body: Block,
context_template: Context, context_template: Context,
@ -723,7 +719,7 @@ pub struct Function {
impl Function { impl Function {
pub fn new( pub fn new(
type_parameters: Option<Vec<Identifier>>, type_parameters: Option<Vec<Identifier>>,
value_parameters: Vec<(Identifier, Type)>, value_parameters: Option<Vec<(Identifier, Type)>>,
return_type: Option<Type>, return_type: Option<Type>,
body: Block, body: Block,
context_template: Context, context_template: Context,
@ -745,7 +741,7 @@ impl Function {
&self.type_parameters &self.type_parameters
} }
pub fn value_parameters(&self) -> &Vec<(Identifier, Type)> { pub fn value_parameters(&self) -> &Option<Vec<(Identifier, Type)>> {
&self.value_parameters &self.value_parameters
} }
@ -774,9 +770,11 @@ impl Function {
} }
} }
for (identifier, r#type) in &self.value_parameters { if let Some(value_parameters) = &self.value_parameters {
self.context_template for (identifier, r#type) in value_parameters {
.set_type(identifier.clone(), r#type.clone())?; self.context_template
.set_type(identifier.clone(), r#type.clone())?;
}
} }
Ok(()) Ok(())

View File

@ -48,7 +48,7 @@ fn function_variable() {
interpret("test", "foobar = fn (x: int) -> int { x }; foobar"), interpret("test", "foobar = fn (x: int) -> int { x }; foobar"),
Ok(Some(Value::function( Ok(Some(Value::function(
None, None,
vec![(Identifier::new("x"), Type::Integer)], Some(vec![(Identifier::new("x"), Type::Integer)]),
Some(Type::Integer), Some(Type::Integer),
Block::new(vec![Statement::Expression(Expression::Identifier( Block::new(vec![Statement::Expression(Expression::Identifier(
Identifier::new("x").with_position((30, 31)) Identifier::new("x").with_position((30, 31))