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::{
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,24 +41,49 @@ 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 {
expression.validate(context, manage_memory)?;
if let Some(value_arguments) = &self.value_arguments {
for expression in value_arguments {
expression.validate(context, manage_memory)?;
}
}
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) {
(Some(type_parameters), Some(type_arguments)) => {
@ -139,103 +156,59 @@ 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)
{
let expression_position = expression.position();
let evaluation = expression.clone().evaluate(context, clear_variables)?;
let value = if let Some(Evaluation::Return(value)) = evaluation {
value
} else {
return Err(RuntimeError::ValidationFailure(
ValidationError::ExpectedExpression(expression_position),
));
};
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)?;
let value = if let Some(Evaluation::Return(value)) = evaluation {
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> {
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);
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(),
})
}
Ok(return_type)
}
}

View File

@ -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(())
}

View File

@ -135,13 +135,20 @@ 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)?))
@ -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>>,
}

View File

@ -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,10 +95,12 @@ impl AbstractNode for ValueNode {
}
}
for (identifier, type_constructor) in value_parameters {
let r#type = type_constructor.clone().construct(outer_context)?;
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)?;
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 {
let r#type = constructor.construct(&outer_context)?;
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,13 +409,19 @@ 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 {
let r#type = type_constructor.clone().construct(&context)?;
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
@ -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)]

View File

@ -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,

View File

@ -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,

View File

@ -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,8 +187,10 @@ impl Display for Value {
write!(f, "(")?;
for (identifier, r#type) in parameters {
write!(f, "{identifier}: {}", r#type)?;
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,9 +770,11 @@ impl Function {
}
}
for (identifier, r#type) in &self.value_parameters {
self.context_template
.set_type(identifier.clone(), r#type.clone())?;
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(())

View File

@ -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))