Refactor function types
This commit is contained in:
parent
572d5a9d18
commit
af20dab0d2
@ -1,7 +1,4 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -17,23 +14,23 @@ use super::{AbstractNode, Evaluation, Expression, Type, TypeConstructor};
|
||||
pub struct FunctionCall {
|
||||
function_expression: Box<Expression>,
|
||||
type_arguments: Option<Vec<TypeConstructor>>,
|
||||
value_arguments: Vec<Expression>,
|
||||
value_arguments: Option<Vec<Expression>>,
|
||||
|
||||
#[serde(skip)]
|
||||
context: Arc<Mutex<Option<Context>>>,
|
||||
context: Context,
|
||||
}
|
||||
|
||||
impl FunctionCall {
|
||||
pub fn new(
|
||||
function_expression: Expression,
|
||||
type_arguments: Option<Vec<TypeConstructor>>,
|
||||
value_arguments: Vec<Expression>,
|
||||
value_arguments: Option<Vec<Expression>>,
|
||||
) -> Self {
|
||||
FunctionCall {
|
||||
function_expression: Box::new(function_expression),
|
||||
type_arguments,
|
||||
value_arguments,
|
||||
context: Arc::new(Mutex::new(None)),
|
||||
context: Context::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,25 +41,50 @@ impl FunctionCall {
|
||||
|
||||
impl AbstractNode for FunctionCall {
|
||||
fn define_types(&self, context: &Context) -> Result<(), ValidationError> {
|
||||
*self.context.lock()? = Some(context.create_child());
|
||||
|
||||
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 {
|
||||
previous = expression.define_types(context)?;
|
||||
if let (Some(type_parameters), Some(type_arguments)) =
|
||||
(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> {
|
||||
self.function_expression.validate(context, manage_memory)?;
|
||||
|
||||
for expression in &self.value_arguments {
|
||||
if let Some(value_arguments) = &self.value_arguments {
|
||||
for expression in value_arguments {
|
||||
expression.validate(context, manage_memory)?;
|
||||
}
|
||||
}
|
||||
|
||||
let function_node_type =
|
||||
if let Some(r#type) = self.function_expression.expected_type(context)? {
|
||||
@ -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) {
|
||||
(Some(type_parameters), Some(type_arguments)) => {
|
||||
@ -139,16 +156,17 @@ impl AbstractNode for FunctionCall {
|
||||
{
|
||||
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
|
||||
.value_parameters()
|
||||
.into_iter()
|
||||
.zip(self.value_arguments.iter())
|
||||
if let (Some(value_parameters), Some(value_arguments)) =
|
||||
(function.value_parameters(), self.value_arguments)
|
||||
{
|
||||
for ((identifier, _), expression) in
|
||||
value_parameters.into_iter().zip(value_arguments.iter())
|
||||
{
|
||||
let expression_position = expression.position();
|
||||
let evaluation = expression.clone().evaluate(context, clear_variables)?;
|
||||
@ -160,82 +178,37 @@ impl AbstractNode for FunctionCall {
|
||||
));
|
||||
};
|
||||
|
||||
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> {
|
||||
let function_type = if let Some(r#type) = self.function_expression.expected_type(context)? {
|
||||
r#type
|
||||
let return_type = if let Some(r#type) = self.function_expression.expected_type(context)? {
|
||||
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 {
|
||||
return Err(ValidationError::ExpectedExpression(
|
||||
self.function_expression.position(),
|
||||
));
|
||||
};
|
||||
|
||||
if let Type::Function {
|
||||
return_type,
|
||||
type_parameters,
|
||||
..
|
||||
} = function_type
|
||||
{
|
||||
let return_type = return_type.map(|r#box| *r#box);
|
||||
|
||||
if let Some(Type::Generic {
|
||||
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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub enum Type {
|
||||
Float,
|
||||
Function {
|
||||
type_parameters: Option<Vec<Identifier>>,
|
||||
value_parameters: Vec<Type>,
|
||||
value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||
return_type: Option<Box<Type>>,
|
||||
},
|
||||
Generic {
|
||||
@ -255,14 +255,16 @@ impl Display for Type {
|
||||
write!(f, ")(")?;
|
||||
}
|
||||
|
||||
for r#type in value_parameters {
|
||||
write!(f, "{type}")?;
|
||||
if let Some(value_parameters) = value_parameters {
|
||||
for (identifier, r#type) in value_parameters {
|
||||
write!(f, "{identifier}: {type}")?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, ")")?;
|
||||
|
||||
if let Some(r#type) = return_type {
|
||||
write!(f, " -> {}", r#type)
|
||||
write!(f, " -> {type}")
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -135,14 +135,21 @@ impl TypeConstructor {
|
||||
.map(|identifier| identifier.node.clone())
|
||||
.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 {
|
||||
let r#type = parameter.construct(&context)?;
|
||||
for (identifier, constructor) in declared_value_parameters {
|
||||
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 {
|
||||
Some(Box::new(constructor.construct(context)?))
|
||||
} else {
|
||||
@ -200,7 +207,7 @@ pub struct EnumTypeConstructor {
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct FunctionTypeConstructor {
|
||||
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>>,
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ pub enum ValueNode {
|
||||
impl ValueNode {
|
||||
pub fn function(
|
||||
type_parameters: Option<Vec<Identifier>>,
|
||||
value_parameters: Vec<(Identifier, TypeConstructor)>,
|
||||
value_parameters: Option<Vec<(Identifier, TypeConstructor)>>,
|
||||
return_type: Option<TypeConstructor>,
|
||||
body: WithPosition<Block>,
|
||||
) -> Self {
|
||||
@ -95,11 +95,13 @@ impl AbstractNode for ValueNode {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(value_parameters) = value_parameters {
|
||||
for (identifier, type_constructor) in value_parameters {
|
||||
let r#type = type_constructor.clone().construct(outer_context)?;
|
||||
|
||||
context_template.set_type(identifier.clone(), r#type)?;
|
||||
}
|
||||
}
|
||||
|
||||
body.node.define_types(context_template)?;
|
||||
}
|
||||
@ -310,20 +312,25 @@ impl AbstractNode for ValueNode {
|
||||
ValueNode::String(string) => Value::string(string),
|
||||
ValueNode::Function(FunctionNode {
|
||||
type_parameters,
|
||||
value_parameters: constructors,
|
||||
value_parameters,
|
||||
return_type,
|
||||
body,
|
||||
context_template,
|
||||
}) => {
|
||||
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)?;
|
||||
|
||||
value_parameters.push((identifier, r#type));
|
||||
parameters.push((identifier, r#type));
|
||||
}
|
||||
|
||||
Some(parameters)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let return_type = if let Some(constructor) = return_type {
|
||||
Some(constructor.construct(&outer_context)?)
|
||||
} else {
|
||||
@ -402,14 +409,20 @@ impl AbstractNode for ValueNode {
|
||||
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)?;
|
||||
|
||||
value_parameter_types.push(r#type);
|
||||
parameters.push((identifier.clone(), r#type));
|
||||
}
|
||||
|
||||
Some(parameters)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let type_parameters = type_parameters.clone().map(|parameters| {
|
||||
parameters
|
||||
.iter()
|
||||
@ -424,7 +437,7 @@ impl AbstractNode for ValueNode {
|
||||
|
||||
Type::Function {
|
||||
type_parameters,
|
||||
value_parameters: value_parameter_types,
|
||||
value_parameters,
|
||||
return_type,
|
||||
}
|
||||
}
|
||||
@ -586,7 +599,7 @@ impl Ord for ValueNode {
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct FunctionNode {
|
||||
type_parameters: Option<Vec<Identifier>>,
|
||||
value_parameters: Vec<(Identifier, TypeConstructor)>,
|
||||
value_parameters: Option<Vec<(Identifier, TypeConstructor)>>,
|
||||
return_type: Option<TypeConstructor>,
|
||||
body: WithPosition<Block>,
|
||||
#[serde(skip)]
|
||||
|
@ -104,8 +104,10 @@ pub fn parser<'src>(
|
||||
.or_not(),
|
||||
)
|
||||
.then(
|
||||
type_constructor
|
||||
positioned_identifier
|
||||
.clone()
|
||||
.then_ignore(just(Token::Symbol(Symbol::Colon)))
|
||||
.then(type_constructor.clone())
|
||||
.separated_by(just(Token::Symbol(Symbol::Comma)))
|
||||
.collect()
|
||||
.delimited_by(
|
||||
@ -119,7 +121,20 @@ pub fn parser<'src>(
|
||||
.or_not(),
|
||||
)
|
||||
.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(
|
||||
FunctionTypeConstructor {
|
||||
type_parameters,
|
||||
@ -290,7 +305,20 @@ pub fn parser<'src>(
|
||||
)
|
||||
.then(block.clone())
|
||||
.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(
|
||||
ValueNode::function(
|
||||
type_parameters,
|
||||
@ -561,7 +589,18 @@ pub fn parser<'src>(
|
||||
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(
|
||||
FunctionCall::new(
|
||||
function_expression,
|
||||
|
@ -344,9 +344,9 @@ fn r#while() {
|
||||
FunctionCall::new(
|
||||
Expression::Identifier(Identifier::new("output").with_position((13, 19))),
|
||||
None,
|
||||
vec![Expression::Value(
|
||||
Some(vec![Expression::Value(
|
||||
ValueNode::String("hi".to_string()).with_position((20, 24))
|
||||
)]
|
||||
)])
|
||||
)
|
||||
.with_position((13, 25))
|
||||
))]
|
||||
@ -431,22 +431,25 @@ fn list_of_type() {
|
||||
#[test]
|
||||
fn function_type() {
|
||||
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(
|
||||
TypeAlias::new(
|
||||
Identifier::new("Foo").with_position((5, 8)),
|
||||
TypeConstructor::Function(
|
||||
FunctionTypeConstructor {
|
||||
type_parameters: Some(vec![Identifier::new("T").with_position((15, 16))]),
|
||||
value_parameters: vec![TypeConstructor::Raw(
|
||||
RawTypeConstructor::Integer.with_position((19, 22))
|
||||
)],
|
||||
value_parameters: Some(vec![(
|
||||
Identifier::new("x").with_position((19, 20)),
|
||||
TypeConstructor::Raw(
|
||||
RawTypeConstructor::Integer.with_position((22, 25))
|
||||
)
|
||||
)]),
|
||||
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]
|
||||
fn function_type_with_return() {
|
||||
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(
|
||||
TypeAlias::new(
|
||||
Identifier::new("Foo").with_position((5, 8)),
|
||||
TypeConstructor::Function(
|
||||
FunctionTypeConstructor {
|
||||
type_parameters: Some(vec![Identifier::new("T").with_position((15, 16))]),
|
||||
value_parameters: vec![TypeConstructor::Raw(
|
||||
RawTypeConstructor::Integer.with_position((19, 22))
|
||||
)],
|
||||
value_parameters: Some(vec![(
|
||||
Identifier::new("x").with_position((19, 20)),
|
||||
TypeConstructor::Raw(
|
||||
RawTypeConstructor::Integer.with_position((22, 25))
|
||||
)
|
||||
)]),
|
||||
return_type: Some(Box::new(TypeConstructor::Invokation(
|
||||
TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T").with_position((27, 28)),
|
||||
identifier: Identifier::new("T").with_position((30, 31)),
|
||||
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(
|
||||
Expression::Identifier(Identifier::new("foobar").with_position((0, 6))),
|
||||
None,
|
||||
Vec::with_capacity(0),
|
||||
None,
|
||||
)
|
||||
.with_position((0, 8))
|
||||
))
|
||||
@ -504,9 +510,9 @@ fn function_call_with_type_arguments() {
|
||||
Some(vec![TypeConstructor::Raw(
|
||||
RawTypeConstructor::String.with_position((9, 12))
|
||||
)]),
|
||||
vec![Expression::Value(
|
||||
Some(vec![Expression::Value(
|
||||
ValueNode::String("hi".to_string()).with_position((16, 20))
|
||||
)],
|
||||
)]),
|
||||
)
|
||||
.with_position((0, 21))
|
||||
))
|
||||
@ -530,7 +536,7 @@ fn function() {
|
||||
Statement::Expression(Expression::Value(
|
||||
ValueNode::function(
|
||||
None,
|
||||
vec![],
|
||||
None,
|
||||
Some(TypeConstructor::Raw(
|
||||
RawTypeConstructor::Integer.with_position((9, 12))
|
||||
)),
|
||||
@ -548,10 +554,10 @@ fn function() {
|
||||
Statement::Expression(Expression::Value(
|
||||
ValueNode::function(
|
||||
None,
|
||||
vec![(
|
||||
Some(vec![(
|
||||
Identifier::new("x"),
|
||||
TypeConstructor::Raw(RawTypeConstructor::Integer.with_position((7, 10)))
|
||||
)],
|
||||
)]),
|
||||
Some(TypeConstructor::Raw(
|
||||
RawTypeConstructor::Integer.with_position((15, 18))
|
||||
)),
|
||||
@ -572,7 +578,7 @@ fn function_with_type_arguments() {
|
||||
Statement::Expression(Expression::Value(
|
||||
ValueNode::function(
|
||||
Some(vec![Identifier::new("T"), Identifier::new("U"),]),
|
||||
vec![
|
||||
Some(vec![
|
||||
(
|
||||
Identifier::new("x"),
|
||||
TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||
@ -587,7 +593,7 @@ fn function_with_type_arguments() {
|
||||
type_arguments: None,
|
||||
})
|
||||
)
|
||||
],
|
||||
]),
|
||||
Some(TypeConstructor::Invokation(TypeInvokationConstructor {
|
||||
identifier: Identifier::new("T").with_position((26, 27)),
|
||||
type_arguments: None,
|
||||
|
@ -70,7 +70,7 @@ impl Value {
|
||||
|
||||
pub fn function(
|
||||
type_parameters: Option<Vec<Identifier>>,
|
||||
value_parameters: Vec<(Identifier, Type)>,
|
||||
value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||
return_type: Option<Type>,
|
||||
body: Block,
|
||||
context_template: Context,
|
||||
@ -166,7 +166,7 @@ impl Display for Value {
|
||||
ValueInner::String(string) => write!(f, "{string}"),
|
||||
ValueInner::Function(Function {
|
||||
type_parameters,
|
||||
value_parameters: parameters,
|
||||
value_parameters,
|
||||
return_type,
|
||||
body,
|
||||
..
|
||||
@ -187,9 +187,11 @@ impl Display for Value {
|
||||
|
||||
write!(f, "(")?;
|
||||
|
||||
for (identifier, r#type) in parameters {
|
||||
if let Some(value_parameters) = value_parameters {
|
||||
for (identifier, r#type) in value_parameters {
|
||||
write!(f, "{identifier}: {}", r#type)?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, ")")?;
|
||||
|
||||
@ -594,17 +596,11 @@ impl ValueInner {
|
||||
ValueInner::Range(_) => Type::Range,
|
||||
ValueInner::String(_) => Type::String,
|
||||
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));
|
||||
|
||||
Type::Function {
|
||||
type_parameters: function.type_parameters().clone(),
|
||||
value_parameters,
|
||||
value_parameters: function.value_parameters().clone(),
|
||||
return_type,
|
||||
}
|
||||
}
|
||||
@ -714,7 +710,7 @@ impl Ord for ValueInner {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Function {
|
||||
type_parameters: Option<Vec<Identifier>>,
|
||||
value_parameters: Vec<(Identifier, Type)>,
|
||||
value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||
return_type: Option<Type>,
|
||||
body: Block,
|
||||
context_template: Context,
|
||||
@ -723,7 +719,7 @@ pub struct Function {
|
||||
impl Function {
|
||||
pub fn new(
|
||||
type_parameters: Option<Vec<Identifier>>,
|
||||
value_parameters: Vec<(Identifier, Type)>,
|
||||
value_parameters: Option<Vec<(Identifier, Type)>>,
|
||||
return_type: Option<Type>,
|
||||
body: Block,
|
||||
context_template: Context,
|
||||
@ -745,7 +741,7 @@ impl Function {
|
||||
&self.type_parameters
|
||||
}
|
||||
|
||||
pub fn value_parameters(&self) -> &Vec<(Identifier, Type)> {
|
||||
pub fn value_parameters(&self) -> &Option<Vec<(Identifier, Type)>> {
|
||||
&self.value_parameters
|
||||
}
|
||||
|
||||
@ -774,10 +770,12 @@ impl Function {
|
||||
}
|
||||
}
|
||||
|
||||
for (identifier, r#type) in &self.value_parameters {
|
||||
if let Some(value_parameters) = &self.value_parameters {
|
||||
for (identifier, r#type) in value_parameters {
|
||||
self.context_template
|
||||
.set_type(identifier.clone(), r#type.clone())?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ fn function_variable() {
|
||||
interpret("test", "foobar = fn (x: int) -> int { x }; foobar"),
|
||||
Ok(Some(Value::function(
|
||||
None,
|
||||
vec![(Identifier::new("x"), Type::Integer)],
|
||||
Some(vec![(Identifier::new("x"), Type::Integer)]),
|
||||
Some(Type::Integer),
|
||||
Block::new(vec![Statement::Expression(Expression::Identifier(
|
||||
Identifier::new("x").with_position((30, 31))
|
||||
|
Loading…
Reference in New Issue
Block a user