Begin converting type assingment to declarations

This commit is contained in:
Jeff 2024-06-20 16:28:33 -04:00
parent 0b8880ae55
commit e429693364
7 changed files with 244 additions and 172 deletions

View File

@ -0,0 +1,83 @@
use serde::{Deserialize, Serialize};
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
identifier::Identifier,
};
use super::{Evaluate, Evaluation, Type, TypeConstructor, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumDeclaration {
pub name: WithPosition<Identifier>,
pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
pub variants: Vec<EnumVariant>,
}
impl Evaluate for EnumDeclaration {
fn validate(
&self,
_context: &mut Context,
_manage_memory: bool,
) -> Result<(), ValidationError> {
Ok(())
}
fn evaluate(
self,
context: &mut Context,
_manage_memory: bool,
) -> Result<Evaluation, RuntimeError> {
let EnumDeclaration {
name,
type_parameters,
variants,
} = self;
let type_parameters = type_parameters.as_ref().map(|parameters| {
parameters
.iter()
.map(|identifier| Type::Generic {
identifier: identifier.node.clone(),
concrete_type: None,
})
.collect()
});
let mut type_variants = Vec::with_capacity(variants.len());
for EnumVariant { name, content } in variants {
let types = if let Some(content) = content {
let mut types = Vec::with_capacity(content.len());
for constructor in content {
let r#type = constructor.construct(&context)?;
types.push(r#type);
}
Some(types)
} else {
None
};
type_variants.push((name.node, types));
}
let r#type = Type::Enum {
name: name.node.clone(),
type_parameters,
variants: type_variants,
};
context.set_type(name.node, r#type)?;
Ok(Evaluation::None)
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumVariant {
pub name: WithPosition<Identifier>,
pub content: Option<Vec<TypeConstructor>>,
}

View File

@ -3,6 +3,7 @@ pub mod assignment;
pub mod async_block;
pub mod block;
pub mod built_in_function_call;
pub mod enum_declaration;
pub mod expression;
pub mod function_call;
pub mod if_else;
@ -14,7 +15,7 @@ pub mod math;
pub mod statement;
pub mod structure_definition;
pub mod r#type;
pub mod type_assignment;
pub mod type_alias;
pub mod type_constructor;
pub mod value_node;
pub mod r#while;
@ -29,6 +30,7 @@ pub use self::{
async_block::AsyncBlock,
block::Block,
built_in_function_call::BuiltInFunctionCall,
enum_declaration::{EnumDeclaration, EnumVariant},
expression::Expression,
function_call::FunctionCall,
if_else::IfElse,
@ -42,7 +44,7 @@ pub use self::{
r#while::While,
statement::Statement,
structure_definition::StructureDefinition,
type_assignment::TypeAssignment,
type_alias::TypeAlias,
type_constructor::{
EnumTypeConstructor, FunctionTypeConstructor, ListTypeConstructor, TypeConstructor,
},

View File

@ -6,8 +6,8 @@ use crate::{
};
use super::{
Assignment, AsyncBlock, Block, Evaluate, Evaluation, ExpectedType, Expression, IfElse, Loop,
SourcePosition, StructureDefinition, Type, TypeAssignment, While, WithPosition,
Assignment, AsyncBlock, Block, EnumDeclaration, Evaluate, Evaluation, ExpectedType, Expression,
IfElse, Loop, SourcePosition, StructureDefinition, Type, TypeAlias, While, WithPosition,
};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -19,7 +19,8 @@ pub enum Statement {
IfElse(WithPosition<IfElse>),
Loop(WithPosition<Loop>),
StructureDefinition(WithPosition<StructureDefinition>),
TypeAssignment(WithPosition<TypeAssignment>),
TypeAlias(WithPosition<TypeAlias>),
EnumDeclaration(WithPosition<EnumDeclaration>),
Expression(Expression),
While(WithPosition<While>),
}
@ -35,7 +36,8 @@ impl Statement {
Statement::IfElse(inner) => inner.position,
Statement::Loop(inner) => inner.position,
Statement::StructureDefinition(inner) => inner.position,
Statement::TypeAssignment(inner) => inner.position,
Statement::TypeAlias(inner) => inner.position,
Statement::EnumDeclaration(inner) => inner.position,
Statement::While(inner) => inner.position,
}
}
@ -68,8 +70,9 @@ impl Evaluate for Statement {
Statement::StructureDefinition(structure_definition) => {
structure_definition.node.validate(_context, _manage_memory)
}
Statement::TypeAssignment(type_alias) => {
type_alias.node.validate(_context, _manage_memory)
Statement::TypeAlias(type_alias) => type_alias.node.validate(_context, _manage_memory),
Statement::EnumDeclaration(type_declaration) => {
type_declaration.node.validate(_context, _manage_memory)
}
Statement::While(r#while) => r#while.node.validate(_context, _manage_memory),
}
@ -91,7 +94,8 @@ impl Evaluate for Statement {
Statement::StructureDefinition(structure_definition) => {
structure_definition.node.evaluate(context, manage_memory)
}
Statement::TypeAssignment(type_alias) => {
Statement::TypeAlias(type_alias) => type_alias.node.evaluate(context, manage_memory),
Statement::EnumDeclaration(type_alias) => {
type_alias.node.evaluate(context, manage_memory)
}
Statement::While(r#while) => r#while.node.evaluate(context, manage_memory),

View File

@ -16,6 +16,7 @@ pub enum Type {
Any,
Boolean,
Enum {
name: Identifier,
type_parameters: Option<Vec<Type>>,
variants: Vec<(Identifier, Option<Vec<Type>>)>,
},

View File

@ -9,12 +9,12 @@ use crate::{
use super::{Evaluate, Evaluation, TypeConstructor, WithPosition};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TypeAssignment {
pub struct TypeAlias {
identifier: WithPosition<Identifier>,
constructor: TypeConstructor,
}
impl TypeAssignment {
impl TypeAlias {
pub fn new(identifier: WithPosition<Identifier>, constructor: TypeConstructor) -> Self {
Self {
identifier,
@ -23,7 +23,7 @@ impl TypeAssignment {
}
}
impl Evaluate for TypeAssignment {
impl Evaluate for TypeAlias {
fn validate(&self, context: &mut Context, _manage_memory: bool) -> Result<(), ValidationError> {
let r#type = self.constructor.clone().construct(&context)?;

View File

@ -53,6 +53,7 @@ impl TypeConstructor {
};
if let Type::Enum {
name,
type_parameters,
variants,
} = invoked_type
@ -64,6 +65,7 @@ impl TypeConstructor {
}
Type::Enum {
name,
type_parameters: type_parameters.clone(),
variants: mapped_variants,
}
@ -73,6 +75,7 @@ impl TypeConstructor {
}
TypeConstructor::Enum(enum_type_constructor) => {
let EnumTypeConstructor {
name,
type_parameters,
variants,
} = enum_type_constructor.node;
@ -95,6 +98,7 @@ impl TypeConstructor {
}
Type::Enum {
name: name.node,
type_parameters: type_parameters.map(|identifiers| {
identifiers
.into_iter()
@ -165,6 +169,7 @@ impl Display for TypeConstructor {
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct EnumTypeConstructor {
pub name: WithPosition<Identifier>,
pub type_parameters: Option<Vec<WithPosition<Identifier>>>,
pub variants: Vec<(WithPosition<Identifier>, Option<Vec<TypeConstructor>>)>,
}

View File

@ -9,7 +9,7 @@ use crate::{
lexer::{Control, Keyword, Operator, Token},
};
use self::type_constructor::TypeInvokationConstructor;
use self::{enum_declaration::EnumVariant, type_constructor::TypeInvokationConstructor};
pub type ParserInput<'src> =
SpannedInput<Token<'src>, SimpleSpan, &'src [(Token<'src>, SimpleSpan)]>;
@ -149,51 +149,6 @@ pub fn parser<'src>(
TypeConstructor::ListOf(Box::new(item_type).with_position(state.span()))
});
let enum_variant = positioned_identifier.clone().then(
type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
)
.or_not(),
);
let enum_type = just(Token::Keyword(Keyword::Enum))
.ignore_then(
positioned_identifier
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::Pipe)),
just(Token::Control(Control::Pipe)),
)
.or_not(),
)
.then(
enum_variant
.separated_by(just(Token::Control(Control::Comma)))
.at_least(1)
.allow_trailing()
.collect()
.delimited_by(
just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)),
),
)
.map_with(|(type_parameters, variants), state| {
TypeConstructor::Enum(
EnumTypeConstructor {
type_parameters,
variants,
}
.with_position(state.span()),
)
});
let type_invokation = positioned_identifier
.clone()
.then(
@ -222,7 +177,6 @@ pub fn parser<'src>(
list_type,
list_of_type,
primitive_type,
enum_type,
))
});
@ -709,13 +663,64 @@ pub fn parser<'src>(
},
);
let type_assignment = just(Token::Keyword(Keyword::Type))
let type_alias = just(Token::Keyword(Keyword::Type))
.ignore_then(positioned_identifier.clone())
.then_ignore(just(Token::Operator(Operator::Assign)))
.then(type_constructor.clone())
.map_with(|(identifier, constructor), state| {
Statement::TypeAssignment(
TypeAssignment::new(identifier, constructor).with_position(state.span()),
Statement::TypeAlias(
TypeAlias::new(identifier, constructor).with_position(state.span()),
)
});
let enum_variant = positioned_identifier
.clone()
.then(
type_constructor
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::ParenOpen)),
just(Token::Control(Control::ParenClose)),
)
.or_not(),
)
.map(|(identifier, constructors)| EnumVariant {
name: identifier,
content: constructors,
});
let enum_declaration = just(Token::Keyword(Keyword::Enum))
.ignore_then(positioned_identifier.clone())
.then(
positioned_identifier
.clone()
.separated_by(just(Token::Control(Control::Comma)))
.collect()
.delimited_by(
just(Token::Operator(Operator::Less)),
just(Token::Operator(Operator::Greater)),
)
.or_not(),
)
.then(
enum_variant
.separated_by(just(Token::Control(Control::Comma)))
.collect()
.delimited_by(
just(Token::Control(Control::CurlyOpen)),
just(Token::Control(Control::CurlyClose)),
),
)
.map_with(|((name, type_parameters), variants), state| {
Statement::EnumDeclaration(
EnumDeclaration {
name,
type_parameters,
variants,
}
.with_position((0, 0)),
)
});
@ -731,7 +736,8 @@ pub fn parser<'src>(
block_statement,
r#loop,
r#while,
type_assignment,
type_alias,
enum_declaration,
)))
.then_ignore(just(Token::Control(Control::Semicolon)).or_not())
});
@ -741,6 +747,8 @@ pub fn parser<'src>(
#[cfg(test)]
mod tests {
use tests::enum_declaration::{EnumDeclaration, EnumVariant};
use crate::lexer::lex;
use super::*;
@ -793,103 +801,88 @@ mod tests {
}
#[test]
fn enum_type_empty() {
fn enum_declaration() {
assert_eq!(
parse(&lex("type MyEnum = enum { X, Y }").unwrap()).unwrap()[0],
Statement::TypeAssignment(
TypeAssignment::new(
Identifier::new("MyEnum").with_position((5, 11)),
TypeConstructor::Enum(
EnumTypeConstructor {
type_parameters: None,
variants: vec![
(Identifier::new("X").with_position((21, 22)), None),
(Identifier::new("Y").with_position((24, 25)), None)
],
parse(&lex("enum MyEnum { X, Y }").unwrap()).unwrap()[0],
Statement::EnumDeclaration(TypeDeclaration::Enum(
EnumDeclaration {
name: Identifier::new("MyEnum").with_position((0, 0)),
type_parameters: None,
variants: vec![
EnumVariant {
name: Identifier::new("X").with_position((0, 0)),
content: None
},
EnumVariant {
name: Identifier::new("Y").with_position((0, 0)),
content: None
}
.with_position((14, 27))
)
)
.with_position((0, 27))
)
],
}
.with_position((0, 0))
))
);
}
#[test]
fn enum_type_with_contents() {
fn enum_with_contents() {
assert_eq!(
parse(&lex("type MyEnum = enum { X(str, int), Y(int) }").unwrap()).unwrap()[0],
Statement::TypeAssignment(
TypeAssignment::new(
Identifier::new("MyEnum").with_position((5, 11)),
TypeConstructor::Enum(
EnumTypeConstructor {
type_parameters: None,
variants: vec![
(
Identifier::new("X").with_position((21, 22)),
Some(vec![
TypeConstructor::Raw(Type::String.with_position((23, 26))),
TypeConstructor::Raw(Type::Integer.with_position((28, 31)))
])
),
(
Identifier::new("Y").with_position((34, 35)),
Some(vec![TypeConstructor::Raw(
Type::Integer.with_position((36, 39))
)])
)
],
parse(&lex("enum MyEnum { X(str, int), Y(int) }").unwrap()).unwrap()[0],
Statement::EnumDeclaration(TypeDeclaration::Enum(
EnumDeclaration {
name: Identifier::new("MyEnum").with_position((0, 0)),
type_parameters: None,
variants: vec![
EnumVariant {
name: Identifier::new("X").with_position((0, 0)),
content: Some(vec![
TypeConstructor::Raw(Type::String.with_position((0, 0))),
TypeConstructor::Raw(Type::Integer.with_position((0, 0))),
])
},
EnumVariant {
name: Identifier::new("Y").with_position((0, 0)),
content: Some(vec![TypeConstructor::Raw(
Type::Integer.with_position((0, 0))
),])
}
.with_position((14, 42))
)
)
.with_position((0, 42))
)
]
}
.with_position((0, 0))
))
);
}
#[test]
fn enum_type_with_type_parameters() {
fn enum_with_type_parameters() {
assert_eq!(
parse(&lex("type MyEnum = enum |T, U| { X(T), Y(U) }").unwrap()).unwrap()[0],
Statement::TypeAssignment(
TypeAssignment::new(
Identifier::new("MyEnum").with_position((5, 11)),
TypeConstructor::Enum(
EnumTypeConstructor {
type_parameters: Some(vec![
Identifier::new("T").with_position((20, 21)),
Identifier::new("U").with_position((23, 24)),
]),
variants: vec![
(
Identifier::new("X").with_position((28, 29)),
Some(vec![TypeConstructor::Invokation(
TypeInvokationConstructor {
identifier: Identifier::new("T")
.with_position((30, 31)),
type_arguments: None,
}
)])
),
(
Identifier::new("Y").with_position((34, 35)),
Some(vec![TypeConstructor::Invokation(
TypeInvokationConstructor {
identifier: Identifier::new("U")
.with_position((36, 37)),
type_arguments: None,
}
)])
),
],
parse(&lex("enum MyEnum <T, U> { X(T), Y(U) }").unwrap()).unwrap()[0],
Statement::EnumDeclaration(TypeDeclaration::Enum(
EnumDeclaration {
name: Identifier::new("MyEnum").with_position((0, 0)),
type_parameters: Some(vec![
Identifier::new("T").with_position((0, 0)),
Identifier::new("U").with_position((0, 0))
]),
variants: vec![
EnumVariant {
name: Identifier::new("X").with_position((0, 0)),
content: Some(vec![TypeConstructor::Raw(
Type::Generic {
identifier: Identifier::new("T"),
concrete_type: None
}
.with_position((0, 0))
)])
},
EnumVariant {
name: todo!(),
content: todo!()
}
.with_position((14, 40))
)
)
.with_position((0, 40))
)
]
}
.with_position((0, 0))
))
);
}
@ -960,20 +953,6 @@ mod tests {
// )
// }
#[test]
fn type_alias() {
assert_eq!(
parse(&lex("type MyType = str").unwrap()).unwrap()[0],
Statement::TypeAssignment(
TypeAssignment::new(
Identifier::new("MyType").with_position((5, 11)),
TypeConstructor::Raw(Type::String.with_position((14, 17)))
)
.with_position((0, 17))
)
)
}
#[test]
fn r#as() {
assert_eq!(
@ -1191,28 +1170,26 @@ mod tests {
fn function_type() {
assert_eq!(
parse(&lex("type Foo = fn |T| (int) -> T").unwrap()).unwrap()[0],
Statement::TypeAssignment(
TypeAssignment::new(
Identifier::new("Foo").with_position((5, 8)),
Statement::TypeAlias(
TypeAlias::new(
Identifier::new("Foo").with_position((0, 0)),
TypeConstructor::Function(
FunctionTypeConstructor {
type_parameters: Some(vec![
Identifier::new("T").with_position((15, 16))
]),
type_parameters: Some(vec![Identifier::new("T").with_position((0, 0))]),
value_parameters: vec![TypeConstructor::Raw(
Type::Integer.with_position((19, 22))
Type::Integer.with_position((0, 0))
)],
return_type: Box::new(TypeConstructor::Invokation(
TypeInvokationConstructor {
identifier: Identifier::new("T").with_position((27, 28)),
type_arguments: None,
identifier: Identifier::new("T").with_position((0, 0)),
type_arguments: None
}
)),
))
}
.with_position((11, 28))
.with_position((0, 0))
)
)
.with_position((0, 28))
.with_position((0, 0))
)
);
}