Refactor function types
This commit is contained in:
parent
572d5a9d18
commit
af20dab0d2
@ -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,25 +41,50 @@ 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 {
|
||||||
|
for expression in value_arguments {
|
||||||
expression.validate(context, manage_memory)?;
|
expression.validate(context, manage_memory)?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let function_node_type =
|
let function_node_type =
|
||||||
if let Some(r#type) = self.function_expression.expected_type(context)? {
|
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) {
|
match (function.type_parameters(), self.type_arguments) {
|
||||||
(Some(type_parameters), Some(type_arguments)) => {
|
(Some(type_parameters), Some(type_arguments)) => {
|
||||||
@ -139,16 +156,17 @@ 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())
|
for ((identifier, _), expression) in
|
||||||
|
value_parameters.into_iter().zip(value_arguments.iter())
|
||||||
{
|
{
|
||||||
let expression_position = expression.position();
|
let expression_position = expression.position();
|
||||||
let evaluation = expression.clone().evaluate(context, clear_variables)?;
|
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> {
|
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 {
|
|
||||||
return_type,
|
|
||||||
type_parameters,
|
|
||||||
..
|
|
||||||
} = function_type
|
|
||||||
{
|
|
||||||
let return_type = return_type.map(|r#box| *r#box);
|
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)
|
Ok(return_type)
|
||||||
} else {
|
|
||||||
Err(ValidationError::ExpectedFunction {
|
|
||||||
actual: function_type,
|
|
||||||
position: self.function_expression.position(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
@ -135,14 +135,21 @@ 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)?))
|
||||||
} else {
|
} else {
|
||||||
@ -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>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,11 +95,13 @@ impl AbstractNode for ValueNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(value_parameters) = value_parameters {
|
||||||
for (identifier, type_constructor) in value_parameters {
|
for (identifier, type_constructor) in value_parameters {
|
||||||
let r#type = type_constructor.clone().construct(outer_context)?;
|
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,14 +409,20 @@ 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
|
||||||
.iter()
|
.iter()
|
||||||
@ -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)]
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,9 +187,11 @@ impl Display for Value {
|
|||||||
|
|
||||||
write!(f, "(")?;
|
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, "{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,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
|
self.context_template
|
||||||
.set_type(identifier.clone(), r#type.clone())?;
|
.set_type(identifier.clone(), r#type.clone())?;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
|
Loading…
Reference in New Issue
Block a user