Refine type constructor

This commit is contained in:
Jeff 2024-06-17 10:50:06 -04:00
parent e448c9dd4c
commit 9e0c0b4db3
10 changed files with 136 additions and 131 deletions

View File

@ -9,18 +9,16 @@ use crate::{
Value,
};
use super::{
AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor, WithPosition,
};
use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct As {
expression: Expression,
constructor: WithPosition<TypeConstructor>,
constructor: TypeConstructor,
}
impl As {
pub fn new(expression: Expression, constructor: WithPosition<TypeConstructor>) -> Self {
pub fn new(expression: Expression, constructor: TypeConstructor) -> Self {
Self {
expression,
constructor,
@ -34,7 +32,7 @@ impl AbstractNode for As {
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
match self.constructor.node {
match self.constructor {
TypeConstructor::Type(_) => {}
_ => todo!("Create an error for this occurence."),
};
@ -61,7 +59,7 @@ impl AbstractNode for As {
ValidationError::InterpreterExpectedReturn(expression_position),
));
};
let r#type = self.constructor.node.construct(&context)?;
let r#type = self.constructor.construct(&context)?;
let (from_value, to_type): (&ValueInner, Type) = (value.inner().borrow(), r#type);
let converted = match (from_value, to_type) {
@ -76,6 +74,6 @@ impl AbstractNode for As {
impl ExpectedType for As {
fn expected_type(&self, context: &mut Context) -> Result<Type, ValidationError> {
self.constructor.node.clone().construct(&context)
self.constructor.clone().construct(&context)
}
}

View File

@ -12,7 +12,7 @@ use super::{AbstractNode, Evaluation, ExpectedType, Statement, TypeConstructor,
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct Assignment {
identifier: WithPosition<Identifier>,
constructor: Option<WithPosition<TypeConstructor>>,
constructor: Option<TypeConstructor>,
operator: AssignmentOperator,
statement: Box<Statement>,
}
@ -27,7 +27,7 @@ pub enum AssignmentOperator {
impl Assignment {
pub fn new(
identifier: WithPosition<Identifier>,
constructor: Option<WithPosition<TypeConstructor>>,
constructor: Option<TypeConstructor>,
operator: AssignmentOperator,
statement: Statement,
) -> Self {
@ -44,11 +44,7 @@ impl AbstractNode for Assignment {
fn validate(&self, context: &mut Context, manage_memory: bool) -> Result<(), ValidationError> {
let statement_type = self.statement.expected_type(context)?;
if let Some(WithPosition {
node: constructor,
position: expected_position,
}) = &self.constructor
{
if let Some(constructor) = &self.constructor {
let r#type = constructor.clone().construct(&context)?;
r#type
@ -56,7 +52,7 @@ impl AbstractNode for Assignment {
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: self.statement.position(),
expected_position: Some(expected_position.clone()),
expected_position: Some(constructor.position()),
})?;
context.set_type(self.identifier.node.clone(), r#type.clone())?;

View File

@ -6,21 +6,19 @@ use crate::{
value::ValueInner,
};
use super::{
AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor, WithPosition,
};
use super::{AbstractNode, Evaluation, ExpectedType, Expression, Type, TypeConstructor};
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionCall {
function: Box<Expression>,
type_arguments: Option<Vec<WithPosition<TypeConstructor>>>,
type_arguments: Option<Vec<TypeConstructor>>,
value_arguments: Vec<Expression>,
}
impl FunctionCall {
pub fn new(
function: Expression,
type_arguments: Option<Vec<WithPosition<TypeConstructor>>>,
type_arguments: Option<Vec<TypeConstructor>>,
value_arguments: Vec<Expression>,
) -> Self {
FunctionCall {
@ -115,7 +113,7 @@ impl AbstractNode for FunctionCall {
for (parameter, constructor) in
type_parameters.into_iter().zip(type_arguments.into_iter())
{
let r#type = constructor.node.construct(context)?;
let r#type = constructor.construct(context)?;
function_context.set_type(parameter.clone(), r#type)?;
}

View File

@ -104,7 +104,7 @@ impl ExpectedType for MapIndex {
for (property, constructor_option, expression) in properties {
if property == &index.node {
return if let Some(constructor) = constructor_option {
let r#type = constructor.node.clone().construct(&context)?;
let r#type = constructor.clone().construct(&context)?;
Ok(r#type)
} else {

View File

@ -42,7 +42,7 @@ pub use self::{
statement::Statement,
structure_definition::StructureDefinition,
type_alias::TypeAssignment,
type_constructor::TypeConstructor,
type_constructor::{FunctionTypeConstructor, ListTypeConstructor, TypeConstructor},
value_expression::Expression,
value_node::ValueNode,
};

View File

@ -6,16 +6,16 @@ use crate::{
identifier::Identifier,
};
use super::{AbstractNode, Evaluation, Type, TypeConstructor, WithPosition};
use super::{AbstractNode, Evaluation, Type, TypeConstructor};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct StructureDefinition {
name: Identifier,
fields: Vec<(Identifier, WithPosition<TypeConstructor>)>,
fields: Vec<(Identifier, TypeConstructor)>,
}
impl StructureDefinition {
pub fn new(name: Identifier, fields: Vec<(Identifier, WithPosition<TypeConstructor>)>) -> Self {
pub fn new(name: Identifier, fields: Vec<(Identifier, TypeConstructor)>) -> Self {
Self { name, fields }
}
}
@ -37,7 +37,7 @@ impl AbstractNode for StructureDefinition {
let mut fields = Vec::with_capacity(self.fields.len());
for (identifier, constructor) in self.fields {
let r#type = constructor.node.construct(&context)?;
let r#type = constructor.construct(&context)?;
fields.push((identifier, r#type));
}

View File

@ -11,14 +11,11 @@ use super::{AbstractNode, Evaluation, TypeConstructor, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TypeAssignment {
identifier: WithPosition<Identifier>,
constructor: WithPosition<TypeConstructor>,
constructor: TypeConstructor,
}
impl TypeAssignment {
pub fn new(
identifier: WithPosition<Identifier>,
constructor: WithPosition<TypeConstructor>,
) -> Self {
pub fn new(identifier: WithPosition<Identifier>, constructor: TypeConstructor) -> Self {
Self {
identifier,
constructor,
@ -40,7 +37,7 @@ impl AbstractNode for TypeAssignment {
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let r#type = self.constructor.node.construct(&context)?;
let r#type = self.constructor.construct(&context)?;
context.set_type(self.identifier.node, r#type)?;

View File

@ -4,25 +4,41 @@ use serde::{Deserialize, Serialize};
use crate::{context::Context, error::ValidationError, identifier::Identifier};
use super::{ExpectedType, Type, WithPosition};
use super::{ExpectedType, SourcePosition, Type, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum TypeConstructor {
Function {
type_parameters: Option<Vec<WithPosition<Identifier>>>,
value_parameters: Vec<(WithPosition<Identifier>, Box<WithPosition<TypeConstructor>>)>,
return_type: Box<WithPosition<TypeConstructor>>,
},
Function(WithPosition<FunctionTypeConstructor>),
Identifier(WithPosition<Identifier>),
List {
length: usize,
item_type: Box<WithPosition<TypeConstructor>>,
},
List(WithPosition<ListTypeConstructor>),
ListOf(WithPosition<Box<TypeConstructor>>),
Type(Type),
Type(WithPosition<Type>),
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct FunctionTypeConstructor {
pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
pub value_parameters: Vec<(WithPosition<Identifier>, Box<TypeConstructor>)>,
pub return_type: Box<TypeConstructor>,
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ListTypeConstructor {
pub length: usize,
pub item_type: Box<TypeConstructor>,
}
impl TypeConstructor {
pub fn position(&self) -> SourcePosition {
match self {
TypeConstructor::Function(WithPosition { position, .. }) => *position,
TypeConstructor::Identifier(WithPosition { position, .. }) => *position,
TypeConstructor::List(WithPosition { position, .. }) => *position,
TypeConstructor::ListOf(WithPosition { position, .. }) => *position,
TypeConstructor::Type(WithPosition { position, .. }) => *position,
}
}
pub fn validate(
&self,
_context: &mut Context,
@ -33,11 +49,7 @@ impl TypeConstructor {
pub fn construct(self, context: &Context) -> Result<Type, ValidationError> {
match self {
TypeConstructor::Function {
type_parameters: _,
value_parameters: _,
return_type: _,
} => todo!(),
TypeConstructor::Function(_) => todo!(),
TypeConstructor::Identifier(WithPosition {
node: identifier,
position,
@ -51,15 +63,16 @@ impl TypeConstructor {
})
}
}
TypeConstructor::List { length, item_type } => {
let constructed_type = item_type.node.construct(context)?;
TypeConstructor::List(positioned_constructor) => {
let ListTypeConstructor { length, item_type } = positioned_constructor.node;
let constructed_type = item_type.construct(context)?;
Ok(Type::List {
length,
item_type: Box::new(constructed_type),
})
}
TypeConstructor::Type(r#type) => Ok(r#type),
TypeConstructor::Type(r#type) => Ok(r#type.node),
TypeConstructor::ListOf(_) => todo!(),
}
}

View File

@ -19,13 +19,7 @@ pub enum ValueNode {
Float(f64),
Integer(i64),
List(Vec<Expression>),
Map(
Vec<(
Identifier,
Option<WithPosition<TypeConstructor>>,
Expression,
)>,
),
Map(Vec<(Identifier, Option<TypeConstructor>, Expression)>),
Range(Range<i64>),
String(String),
Structure {
@ -34,8 +28,8 @@ pub enum ValueNode {
},
ParsedFunction {
type_parameters: Option<Vec<WithPosition<Identifier>>>,
value_parameters: Vec<(Identifier, WithPosition<TypeConstructor>)>,
return_type: WithPosition<TypeConstructor>,
value_parameters: Vec<(Identifier, TypeConstructor)>,
return_type: TypeConstructor,
body: WithPosition<Block>,
},
}
@ -48,13 +42,13 @@ impl AbstractNode for ValueNode {
if let Some(constructor) = constructor_option {
let actual_type = expression.expected_type(context)?;
let exprected_type = constructor.node.clone().construct(&context)?;
let exprected_type = constructor.clone().construct(&context)?;
exprected_type.check(&actual_type).map_err(|conflict| {
ValidationError::TypeCheck {
conflict,
actual_position: expression.position(),
expected_position: Some(constructor.position),
expected_position: Some(constructor.position()),
}
})?;
}
@ -73,7 +67,7 @@ impl AbstractNode for ValueNode {
let mut function_context = Context::new(Some(&context));
for (identifier, type_constructor) in value_parameters {
let r#type = type_constructor.node.clone().construct(&function_context)?;
let r#type = type_constructor.clone().construct(&function_context)?;
function_context.set_type(identifier.clone(), r#type)?;
}
@ -83,14 +77,13 @@ impl AbstractNode for ValueNode {
let actual_return_type = body.node.expected_type(&mut function_context)?;
return_type
.node
.clone()
.construct(&function_context)?
.check(&actual_return_type)
.map_err(|conflict| ValidationError::TypeCheck {
conflict,
actual_position: body.position,
expected_position: Some(return_type.position),
expected_position: Some(return_type.position()),
})?;
return Ok(());
@ -197,12 +190,12 @@ impl AbstractNode for ValueNode {
let mut value_parameters = Vec::with_capacity(constructors.len());
for (identifier, constructor) in constructors {
let r#type = constructor.node.construct(&context)?;
let r#type = constructor.construct(&context)?;
value_parameters.push((identifier, r#type));
}
let return_type = return_type.node.construct(&context)?;
let return_type = return_type.construct(&context)?;
Value::function(type_parameters, value_parameters, return_type, body.node)
}
@ -353,7 +346,7 @@ impl ExpectedType for ValueNode {
let mut value_parameter_types = Vec::with_capacity(value_parameters.len());
for (identifier, type_constructor) in value_parameters {
let r#type = type_constructor.node.clone().construct(&context)?;
let r#type = type_constructor.clone().construct(&context)?;
value_parameter_types.push((identifier.clone(), r#type));
}
@ -364,7 +357,7 @@ impl ExpectedType for ValueNode {
.map(|identifier| identifier.node.clone())
.collect()
});
let return_type = return_type.node.clone().construct(&context)?;
let return_type = return_type.clone().construct(&context)?;
Type::Function {
type_parameters,

View File

@ -65,13 +65,6 @@ pub fn parser<'src>(
};
let type_constructor = recursive(|type_constructor| {
let positioned_type_constructor =
type_constructor
.clone()
.map_with(|constructor: TypeConstructor, state| {
constructor.with_position(state.span())
});
let primitive_type = choice((
just(Token::Keyword(Keyword::Any)).to(Type::Any),
just(Token::Keyword(Keyword::Bool)).to(Type::Boolean),
@ -81,7 +74,7 @@ pub fn parser<'src>(
just(Token::Keyword(Keyword::Range)).to(Type::Range),
just(Token::Keyword(Keyword::Str)).to(Type::String),
))
.map(|r#type| TypeConstructor::Type(r#type));
.map_with(|r#type, state| TypeConstructor::Type(r#type.with_position(state.span())));
let function_type = just(Token::Keyword(Keyword::Fn))
.ignore_then(
@ -99,9 +92,11 @@ pub fn parser<'src>(
positioned_identifier
.clone()
.then_ignore(just(Token::Control(Control::Colon)))
.then(type_constructor.clone().map_with(|constructor, state| {
Box::new(constructor.with_position(state.span()))
}))
.then(
type_constructor
.clone()
.map(|constructor| Box::new(constructor)),
)
.separated_by(just(Token::Control(Control::Comma)))
.collect()
.delimited_by(
@ -110,16 +105,21 @@ pub fn parser<'src>(
),
)
.then_ignore(just(Token::Control(Control::SkinnyArrow)))
.then(positioned_type_constructor.clone())
.map(
|((type_parameters, value_parameters), return_type)| TypeConstructor::Function {
type_parameters,
value_parameters,
return_type: Box::new(return_type),
.then(type_constructor.clone())
.map_with(
|((type_parameters, value_parameters), return_type), state| {
TypeConstructor::Function(
FunctionTypeConstructor {
type_parameters,
value_parameters,
return_type: Box::new(return_type),
}
.with_position(state.span()),
)
},
);
let list = positioned_type_constructor
let list = type_constructor
.clone()
.clone()
.then_ignore(just(Token::Control(Control::Semicolon)))
@ -128,9 +128,14 @@ pub fn parser<'src>(
just(Token::Control(Control::SquareOpen)),
just(Token::Control(Control::SquareClose)),
)
.map(|(item_type, length)| TypeConstructor::List {
length: length as usize,
item_type: Box::new(item_type),
.map_with(|(item_type, length), state| {
TypeConstructor::List(
ListTypeConstructor {
length: length as usize,
item_type: Box::new(item_type),
}
.with_position(state.span()),
)
});
let list_of = just(Token::Keyword(Keyword::List))
@ -145,12 +150,8 @@ pub fn parser<'src>(
choice((function_type, list, list_of, primitive_type))
});
let positioned_type_constructor = type_constructor
.clone()
.map_with(|constructor: TypeConstructor, state| constructor.with_position(state.span()));
let type_specification =
just(Token::Control(Control::Colon)).ignore_then(positioned_type_constructor.clone());
just(Token::Control(Control::Colon)).ignore_then(type_constructor.clone());
let statement = recursive(|statement| {
let allow_built_ins = allow_built_ins.clone();
@ -209,7 +210,7 @@ pub fn parser<'src>(
.then(
identifier
.then_ignore(just(Token::Control(Control::Colon)))
.then(positioned_type_constructor.clone())
.then(type_constructor.clone())
.separated_by(just(Token::Control(Control::Comma)))
.collect()
.delimited_by(
@ -218,7 +219,7 @@ pub fn parser<'src>(
),
)
.then_ignore(just(Token::Control(Control::SkinnyArrow)))
.then(positioned_type_constructor.clone())
.then(type_constructor.clone())
.then(block.clone())
.map_with(
|(((type_parameters, value_parameters), return_type), body), state| {
@ -293,7 +294,7 @@ pub fn parser<'src>(
}
});
let turbofish = positioned_type_constructor
let turbofish = type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.at_least(1)
@ -470,8 +471,7 @@ pub fn parser<'src>(
),
postfix(
2,
just(Token::Keyword(Keyword::As))
.ignore_then(positioned_type_constructor.clone()),
just(Token::Keyword(Keyword::As)).ignore_then(type_constructor.clone()),
|expression, constructor, span| {
Expression::As(
Box::new(As::new(expression, constructor)).with_position(span),
@ -576,7 +576,7 @@ pub fn parser<'src>(
let type_assignment = just(Token::Keyword(Keyword::Type))
.ignore_then(positioned_identifier.clone())
.then_ignore(just(Token::Operator(Operator::Assign)))
.then(positioned_type_constructor.clone())
.then(type_constructor.clone())
.map_with(|(identifier, constructor), state| {
Statement::TypeAssignment(
TypeAssignment::new(identifier, constructor).with_position(state.span()),
@ -619,7 +619,7 @@ mod tests {
Statement::TypeAssignment(
TypeAssignment::new(
Identifier::new("MyType").with_position((5, 11)),
TypeConstructor::Type(Type::String).with_position((14, 17))
TypeConstructor::Type(Type::String.with_position((14, 17)))
)
.with_position((0, 17))
)
@ -633,7 +633,7 @@ mod tests {
Statement::ValueExpression(Expression::As(
Box::new(As::new(
Expression::Value(ValueNode::Integer(1).with_position((0, 1))),
TypeConstructor::Type(Type::String).with_position((5, 8))
TypeConstructor::Type(Type::String.with_position((5, 8)))
))
.with_position((0, 8))
))
@ -768,11 +768,11 @@ mod tests {
vec![
(
Identifier::new("bar"),
TypeConstructor::Type(Type::Integer).with_position((64, 67))
TypeConstructor::Type(Type::Integer.with_position((64, 67)))
),
(
Identifier::new("baz"),
TypeConstructor::Type(Type::String).with_position((99, 102))
TypeConstructor::Type(Type::String.with_position((99, 102)))
),
]
)
@ -844,7 +844,7 @@ mod tests {
Statement::Assignment(
Assignment::new(
Identifier::new("foobar").with_position((0, 6)),
Some(TypeConstructor::Type(Type::Boolean).with_position((0, 0))),
Some(TypeConstructor::Type(Type::Boolean.with_position((0, 0)))),
AssignmentOperator::Assign,
Statement::ValueExpression(Expression::Value(
ValueNode::Boolean(true).with_position((16, 20))
@ -862,15 +862,15 @@ mod tests {
Statement::Assignment(
Assignment::new(
Identifier::new("foobar").with_position((0, 6)),
Some(
TypeConstructor::List {
Some(TypeConstructor::List(
ListTypeConstructor {
length: 2,
item_type: Box::new(
TypeConstructor::Type(Type::Integer).with_position((0, 0))
)
item_type: Box::new(TypeConstructor::Type(
Type::Integer.with_position((0, 0))
))
}
.with_position((8, 12))
),
)),
AssignmentOperator::Assign,
Statement::ValueExpression(Expression::Value(
ValueNode::List(vec![]).with_position((15, 17))
@ -888,7 +888,10 @@ mod tests {
Statement::Assignment(
Assignment::new(
Identifier::new("foobar").with_position((0, 6)),
Some(TypeConstructor::ListOf(Box::new(Type::Boolean)).with_position((9, 19))),
Some(TypeConstructor::ListOf(
Box::new(TypeConstructor::Type(Type::Boolean.with_position((9, 19))))
.with_position((0, 0))
)),
AssignmentOperator::Assign,
Statement::ValueExpression(Expression::Value(
ValueNode::List(vec![Expression::Value(
@ -909,14 +912,16 @@ mod tests {
Statement::Assignment(
Assignment::new(
Identifier::new("foobar").with_position((0, 6)),
Some(
TypeConstructor::Function {
Some(TypeConstructor::Function(
FunctionTypeConstructor {
type_parameters: None,
value_parameters: vec![],
return_type: Box::new(Type::Any),
return_type: Box::new(TypeConstructor::Type(
Type::Any.with_position((0, 0))
)),
}
.with_position((9, 20))
),
)),
AssignmentOperator::Assign,
Statement::ValueExpression(Expression::Identifier(
Identifier::new("some_function").with_position((23, 36))
@ -949,9 +954,9 @@ mod tests {
Statement::ValueExpression(Expression::FunctionCall(
FunctionCall::new(
Expression::Identifier(Identifier::new("foobar").with_position((0, 6))),
Some(vec![
TypeConstructor::Type(Type::String).with_position((9, 12))
]),
Some(vec![TypeConstructor::Type(
Type::String.with_position((9, 12))
)]),
vec![Expression::Value(
ValueNode::String("hi".to_string()).with_position((16, 20))
)],
@ -980,9 +985,9 @@ mod tests {
type_parameters: None,
value_parameters: vec![(
Identifier::new("x"),
TypeConstructor::Integer.with_position((7, 10))
TypeConstructor::Type(Type::Integer.with_position((7, 10)))
)],
return_type: TypeConstructor::Integer.with_position((12, 15)),
return_type: TypeConstructor::Type(Type::Integer.with_position((12, 15))),
body: Block::new(vec![Statement::ValueExpression(Expression::Identifier(
Identifier::new("x").with_position((18, 19))
))])
@ -1000,21 +1005,26 @@ mod tests {
Statement::ValueExpression(Expression::Value(
ValueNode::ParsedFunction {
type_parameters: Some(vec![
TypeConstructor::Argument(Identifier::new("T")).with_position((4, 5)),
TypeConstructor::Argument(Identifier::new("U")).with_position((7, 8)),
Identifier::new("T").with_position((4, 5)),
Identifier::new("U").with_position((7, 8)),
]),
value_parameters: vec![
(
Identifier::new("x"),
TypeConstructor::Argument(Identifier::new("T")).with_position((13, 14))
TypeConstructor::Identifier(
Identifier::new("T").with_position((13, 14))
)
),
(
Identifier::new("y"),
TypeConstructor::Argument(Identifier::new("U")).with_position((19, 20))
TypeConstructor::Identifier(
Identifier::new("U").with_position((19, 20))
)
)
],
return_type: TypeConstructor::Argument(Identifier::new("T"))
.with_position((22, 23)),
return_type: TypeConstructor::Identifier(
Identifier::new("T").with_position((22, 23))
),
body: Block::new(vec![Statement::ValueExpression(Expression::Identifier(
Identifier::new("x").with_position((26, 27))
))])
@ -1299,7 +1309,7 @@ mod tests {
Statement::Assignment(
Assignment::new(
Identifier::new("foobar").with_position((0, 6)),
Some(TypeConstructor::Integer.with_position((8, 11))),
Some(TypeConstructor::Type(Type::Integer.with_position((8, 11)))),
AssignmentOperator::Assign,
Statement::ValueExpression(Expression::Value(
ValueNode::Integer(1).with_position((14, 15))