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

View File

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

View File

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

View File

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

View File

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