diff --git a/grammar.ebnf b/grammar.ebnf index 0125e17..3f061d6 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -11,7 +11,7 @@ File = Item* EOI ; Item = Visibility ItemKind ; ItemKind = Const | Static | Module | Function | Struct | Enum - | Impl ; + | Alias | Impl ; (* item *) @@ -36,6 +36,8 @@ VarStruct = '{' (StructMember ',')* StructMember? '}' ; VarTuple = TyTuple ; VarCLike = '=' INTEGER ; +Alias = "type" Ty ('=' Ty)? ';' ; + Impl = "impl" Path '{' Item* '}' ; (* TODO: Impl Trait for Target*) diff --git a/libconlang/src/ast.rs b/libconlang/src/ast.rs index e983998..2e4029e 100644 --- a/libconlang/src/ast.rs +++ b/libconlang/src/ast.rs @@ -44,6 +44,10 @@ pub struct Item { /// Stores a concrete Item #[derive(Clone, Debug, PartialEq, Eq)] pub enum ItemKind { + // TODO: Import declaration ("use") item + // TODO: Trait declaration ("trait") item? + /// A [type alias](Alias) + Alias(Alias), /// A [constant](Const) Const(Const), /// A [static](Static) variable @@ -60,6 +64,12 @@ pub enum ItemKind { Impl(Impl), } +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Alias { + pub to: Box, + pub from: Option>, +} + /// Stores a `const` value #[derive(Clone, Debug, PartialEq, Eq)] pub struct Const { diff --git a/libconlang/src/ast/ast_impl.rs b/libconlang/src/ast/ast_impl.rs index b74db4f..ade5220 100644 --- a/libconlang/src/ast/ast_impl.rs +++ b/libconlang/src/ast/ast_impl.rs @@ -81,6 +81,7 @@ mod display { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.vis.fmt(f)?; match &self.kind { + ItemKind::Alias(v) => v.fmt(f), ItemKind::Const(v) => v.fmt(f), ItemKind::Static(v) => v.fmt(f), ItemKind::Module(v) => v.fmt(f), @@ -91,6 +92,15 @@ mod display { } } } + impl Display for Alias { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self { to, from } = self; + match from { + Some(from) => write!(f, "type {to} = {from};"), + None => write!(f, "type {to};"), + } + } + } impl Display for Const { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let Self { name, ty, init } = self; @@ -649,6 +659,7 @@ mod convert { impl_from! { impl From for ItemKind { + Alias => ItemKind::Alias, Const => ItemKind::Const, Static => ItemKind::Static, Module => ItemKind::Module, diff --git a/libconlang/src/interpreter.rs b/libconlang/src/interpreter.rs index 0f76329..6826229 100644 --- a/libconlang/src/interpreter.rs +++ b/libconlang/src/interpreter.rs @@ -330,6 +330,7 @@ pub mod interpret { impl Interpret for Item { fn interpret(&self, env: &mut Environment) -> IResult { match &self.kind { + ItemKind::Alias(item) => item.interpret(env), ItemKind::Const(item) => item.interpret(env), ItemKind::Static(item) => item.interpret(env), ItemKind::Module(item) => item.interpret(env), @@ -340,6 +341,11 @@ pub mod interpret { } } } + impl Interpret for Alias { + fn interpret(&self, env: &mut Environment) -> IResult { + todo!("Interpret type alias in {env}") + } + } impl Interpret for Const { fn interpret(&self, env: &mut Environment) -> IResult { todo!("interpret const in {env}") diff --git a/libconlang/src/parser.rs b/libconlang/src/parser.rs index a0e0b66..7b3f8fb 100644 --- a/libconlang/src/parser.rs +++ b/libconlang/src/parser.rs @@ -72,6 +72,7 @@ pub mod error { Visibility, Mutability, ItemKind, + Alias, Const, Static, Module, @@ -164,6 +165,7 @@ pub mod error { Parsing::Visibility => "a visibility qualifier", Parsing::Mutability => "a mutability qualifier", Parsing::ItemKind => "an item", + Parsing::Alias => "a type alias", Parsing::Const => "a const item", Parsing::Static => "a static variable", Parsing::Module => "a module", @@ -369,6 +371,7 @@ impl<'t> Parser<'t> { macro item_like() { Type::Keyword( Keyword::Pub + | Keyword::Type | Keyword::Const | Keyword::Static | Keyword::Mod @@ -466,6 +469,7 @@ impl<'t> Parser<'t> { /// See also: [Parser::item] pub fn itemkind(&mut self) -> PResult { Ok(match self.peek_type(Parsing::Item)? { + Type::Keyword(Keyword::Type) => self.parse_alias()?.into(), Type::Keyword(Keyword::Const) => self.parse_const()?.into(), Type::Keyword(Keyword::Static) => self.parse_static()?.into(), Type::Keyword(Keyword::Mod) => self.parse_module()?.into(), @@ -477,6 +481,21 @@ impl<'t> Parser<'t> { }) } + pub fn parse_alias(&mut self) -> PResult { + const PARSING: Parsing = Parsing::Alias; + self.match_kw(Keyword::Type, PARSING)?; + let out = Ok(Alias { + to: self.ty()?.into(), + from: if self.match_type(Type::Eq, PARSING).is_ok() { + Some(self.ty()?.into()) + } else { + None + }, + }); + self.match_type(Type::Semi, PARSING)?; + out + } + pub fn parse_const(&mut self) -> PResult { const PARSING: Parsing = Parsing::Const; self.match_kw(Keyword::Const, PARSING)?; diff --git a/libconlang/src/token/token_type.rs b/libconlang/src/token/token_type.rs index 150ada3..c43662a 100644 --- a/libconlang/src/token/token_type.rs +++ b/libconlang/src/token/token_type.rs @@ -99,6 +99,7 @@ pub enum Keyword { Struct, Super, True, + Type, While, } @@ -197,6 +198,7 @@ impl Display for Keyword { Self::Struct => "struct".fmt(f), Self::Super => "super".fmt(f), Self::True => "true".fmt(f), + Self::Type => "type".fmt(f), Self::While => "while".fmt(f), } } @@ -229,6 +231,7 @@ impl FromStr for Keyword { "struct" => Self::Struct, "super" => Self::Super, "true" => Self::True, + "type" => Self::Type, "while" => Self::While, _ => Err(())?, })