diff --git a/dust-lang/src/abstract_tree/mod.rs b/dust-lang/src/abstract_tree/mod.rs index 49818a0..3fdf33e 100644 --- a/dust-lang/src/abstract_tree/mod.rs +++ b/dust-lang/src/abstract_tree/mod.rs @@ -14,6 +14,7 @@ pub mod math; pub mod statement; pub mod structure_definition; pub mod r#type; +pub mod type_alias; pub mod value_node; pub mod r#while; @@ -40,6 +41,7 @@ pub use self::{ r#while::While, statement::Statement, structure_definition::StructureDefinition, + type_alias::TypeAlias, value_node::ValueNode, }; diff --git a/dust-lang/src/abstract_tree/statement.rs b/dust-lang/src/abstract_tree/statement.rs index 49a5b63..1355acb 100644 --- a/dust-lang/src/abstract_tree/statement.rs +++ b/dust-lang/src/abstract_tree/statement.rs @@ -7,7 +7,7 @@ use crate::{ use super::{ AbstractNode, Action, Assignment, AsyncBlock, Block, Expression, IfElse, Loop, SourcePosition, - StructureDefinition, Type, While, WithPosition, + StructureDefinition, Type, TypeAlias, While, WithPosition, }; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] @@ -20,6 +20,7 @@ pub enum Statement { IfElse(WithPosition), Loop(WithPosition), StructureDefinition(WithPosition), + TypeAlias(WithPosition), While(WithPosition), } @@ -34,6 +35,7 @@ impl Statement { Statement::IfElse(inner) => inner.position, Statement::Loop(inner) => inner.position, Statement::StructureDefinition(inner) => inner.position, + Statement::TypeAlias(inner) => inner.position, Statement::While(inner) => inner.position, } } @@ -50,6 +52,7 @@ impl AbstractNode for Statement { Statement::IfElse(if_else) => if_else.item.expected_type(_context), Statement::Loop(r#loop) => r#loop.item.expected_type(_context), Statement::While(r#while) => r#while.item.expected_type(_context), + Statement::TypeAlias(type_alias) => type_alias.item.expected_type(_context), Statement::StructureDefinition(structure_definition) => { structure_definition.item.expected_type(_context) } @@ -71,10 +74,11 @@ impl AbstractNode for Statement { Statement::Expression(expression) => expression.validate(_context, _manage_memory), Statement::IfElse(if_else) => if_else.item.validate(_context, _manage_memory), Statement::Loop(r#loop) => r#loop.item.validate(_context, _manage_memory), - Statement::While(r#while) => r#while.item.validate(_context, _manage_memory), Statement::StructureDefinition(structure_definition) => { structure_definition.item.validate(_context, _manage_memory) } + Statement::TypeAlias(type_alias) => type_alias.item.validate(_context, _manage_memory), + Statement::While(r#while) => r#while.item.validate(_context, _manage_memory), } } @@ -87,10 +91,11 @@ impl AbstractNode for Statement { Statement::Expression(expression) => expression.run(context, manage_memory), Statement::IfElse(if_else) => if_else.item.run(context, manage_memory), Statement::Loop(r#loop) => r#loop.item.run(context, manage_memory), - Statement::While(r#while) => r#while.item.run(context, manage_memory), Statement::StructureDefinition(structure_definition) => { structure_definition.item.run(context, manage_memory) } + Statement::TypeAlias(type_alias) => type_alias.item.run(context, manage_memory), + Statement::While(r#while) => r#while.item.run(context, manage_memory), }; if manage_memory { diff --git a/dust-lang/src/abstract_tree/type_alias.rs b/dust-lang/src/abstract_tree/type_alias.rs new file mode 100644 index 0000000..10874c6 --- /dev/null +++ b/dust-lang/src/abstract_tree/type_alias.rs @@ -0,0 +1,41 @@ +use serde::{Deserialize, Serialize}; + +use crate::{ + context::Context, + error::{RuntimeError, ValidationError}, + identifier::Identifier, +}; + +use super::{AbstractNode, Action, Type, WithPosition}; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct TypeAlias { + identifier: WithPosition, + r#type: WithPosition, +} + +impl TypeAlias { + pub fn new(identifier: WithPosition, r#type: WithPosition) -> Self { + Self { identifier, r#type } + } +} + +impl AbstractNode for TypeAlias { + fn expected_type(&self, _context: &mut Context) -> Result { + Ok(Type::None) + } + + fn validate( + &self, + _context: &mut Context, + _manage_memory: bool, + ) -> Result<(), ValidationError> { + Ok(()) + } + + fn run(self, context: &mut Context, _manage_memory: bool) -> Result { + context.set_type(self.identifier.item, self.r#type.item)?; + + Ok(Action::None) + } +} diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 70bc1f2..8635478 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -630,6 +630,14 @@ pub fn parser<'src>( }, ); + let type_alias = just(Token::Keyword(Keyword::Type)) + .ignore_then(positioned_identifier.clone()) + .then_ignore(just(Token::Operator(Operator::Assign))) + .then(r#type.clone()) + .map_with(|(identifier, r#type), state| { + Statement::TypeAlias(TypeAlias::new(identifier, r#type).with_position(state.span())) + }); + choice(( async_block, structure_definition, @@ -640,6 +648,7 @@ pub fn parser<'src>( block_statement, r#loop, r#while, + type_alias, )) .then_ignore(just(Token::Control(Control::Semicolon)).or_not()) }); @@ -659,6 +668,20 @@ mod tests { use super::*; + #[test] + fn type_alias() { + assert_eq!( + parse(&lex("type MyType = str").unwrap()).unwrap()[0], + Statement::TypeAlias( + TypeAlias::new( + Identifier::new("MyType").with_position((5, 11)), + Type::String.with_position((14, 17)) + ) + .with_position((0, 17)) + ) + ) + } + #[test] fn r#as() { assert_eq!(