diff --git a/gen/midas.py b/gen/midas.py index 287fcc3..4c4ca32 100644 --- a/gen/midas.py +++ b/gen/midas.py @@ -44,6 +44,11 @@ class TypeStmt: type: Type +class AliasStmt: + name: Token + type: Type + + class MemberStmt: name: Token type: Type diff --git a/midas/ast/midas.py b/midas/ast/midas.py index 1ece261..a6e2ed9 100644 --- a/midas/ast/midas.py +++ b/midas/ast/midas.py @@ -51,6 +51,9 @@ class Stmt(ABC): @abstractmethod def visit_type_stmt(self, stmt: TypeStmt) -> T: ... + @abstractmethod + def visit_alias_stmt(self, stmt: AliasStmt) -> T: ... + @abstractmethod def visit_member_stmt(self, stmt: MemberStmt) -> T: ... @@ -71,6 +74,15 @@ class TypeStmt(Stmt): return visitor.visit_type_stmt(self) +@dataclass(frozen=True) +class AliasStmt(Stmt): + name: Token + type: Type + + def accept(self, visitor: Stmt.Visitor[T]) -> T: + return visitor.visit_alias_stmt(self) + + @dataclass(frozen=True) class MemberStmt(Stmt): name: Token diff --git a/midas/ast/printer.py b/midas/ast/printer.py index 680fd79..17f0dd0 100644 --- a/midas/ast/printer.py +++ b/midas/ast/printer.py @@ -105,6 +105,14 @@ class MidasAstPrinter( with self._child_level(single=True): stmt.type.accept(self) + def visit_alias_stmt(self, stmt: m.AliasStmt) -> None: + self._write_line("AliasStmt") + with self._child_level(): + self._write_line(f'name: "{stmt.name.lexeme}"') + self._write_line("type", last=True) + with self._child_level(single=True): + stmt.type.accept(self) + def _print_type_param(self, param: m.TypeParam) -> None: self._write_line("Param") with self._child_level(): @@ -371,6 +379,9 @@ class MidasPrinter(m.Expr.Visitor[str], m.Stmt.Visitor[str], m.Type.Visitor[str] res: str = f"type {stmt.name.lexeme}{template} = {stmt.type.accept(self)}" return self.indented(res) + def visit_alias_stmt(self, stmt: m.AliasStmt) -> str: + return self.indented(f"alias {stmt.name.lexeme} = {stmt.type.accept(self)}") + def _print_type_param(self, param: m.TypeParam) -> str: res: str = param.name.lexeme if param.bound is not None: diff --git a/midas/lexer/token.py b/midas/lexer/token.py index ce73aef..f1d4047 100644 --- a/midas/lexer/token.py +++ b/midas/lexer/token.py @@ -47,6 +47,7 @@ class TokenType(Enum): # Keywords TYPE = auto() + ALIAS = auto() PREDICATE = auto() EXTEND = auto() WHERE = auto() @@ -63,6 +64,7 @@ class TokenType(Enum): KEYWORDS: dict[str, TokenType] = { "type": TokenType.TYPE, + "alias": TokenType.ALIAS, "predicate": TokenType.PREDICATE, "extend": TokenType.EXTEND, "where": TokenType.WHERE, diff --git a/midas/parser/midas.py b/midas/parser/midas.py index fdb58c2..c5fced1 100644 --- a/midas/parser/midas.py +++ b/midas/parser/midas.py @@ -2,6 +2,7 @@ from typing import Optional from midas.ast.location import Location from midas.ast.midas import ( + AliasStmt, BinaryExpr, CallExpr, ComplexType, @@ -79,6 +80,8 @@ class MidasParser(Parser): try: if self.match(TokenType.TYPE): return self.type_declaration() + if self.match(TokenType.ALIAS): + return self.alias_declaration() if self.match(TokenType.EXTEND): return self.extend_declaration() if self.match(TokenType.PREDICATE): @@ -158,6 +161,25 @@ class MidasParser(Parser): self.consume(TokenType.RIGHT_BRACKET, "Missing ']' after type parameters") return params + def alias_declaration(self) -> AliasStmt: + """Parse an alias declaration + + Returns: + AliasStmt: the parsed alias declaration statement + """ + keyword: Token = self.previous() + name: Token = self.consume_identifier("Expected type name") + + self.consume(TokenType.EQUAL, "Expected '=' before alias definition") + + type: Type = self.type_expr() + + return AliasStmt( + location=keyword.location_to(self.previous()), + name=name, + type=type, + ) + def type_expr(self) -> Type: """Parse a type expression