diff --git a/midas/checker/midas.py b/midas/checker/midas.py index 29846c6..5213785 100644 --- a/midas/checker/midas.py +++ b/midas/checker/midas.py @@ -28,7 +28,7 @@ from midas.checker.types import ( ) from midas.checker.variance import VarianceInferrer from midas.lexer.midas import MidasLexer -from midas.lexer.token import Token +from midas.lexer.token import Token, TokenType from midas.parser.midas import MidasParser @@ -297,6 +297,11 @@ class MidasTyper(m.Stmt.Visitor[None], m.Expr.Visitor[Type], m.Type.Visitor[Type return result.result def visit_unary_expr(self, expr: m.UnaryExpr) -> Type: + # Special case because there is no __not__ dunder method + match expr.operator: + case Token(type=TokenType.BANG): + return self.types.get_type("bool") + method: Optional[str] = MIDAS_UNARY_METHODS.get(expr.operator.type) if method is None: self.logger.warning(f"Unsupported operator {expr.operator.lexeme}") diff --git a/midas/checker/python.py b/midas/checker/python.py index b592ec1..8e5c617 100644 --- a/midas/checker/python.py +++ b/midas/checker/python.py @@ -686,6 +686,11 @@ class PythonTyper( return UnknownType() def visit_unary_expr(self, expr: p.UnaryExpr) -> Type: + # Special case because there is no __not__ dunder method + match expr.operator: + case ast.Not(): + return self.types.get_type("bool") + method: Optional[str] = PY_UNARY_METHODS.get(expr.operator.__class__) if method is None: self.logger.warning(f"Unsupported operator {expr.operator}") diff --git a/midas/lexer/midas.py b/midas/lexer/midas.py index e1f6758..f926310 100644 --- a/midas/lexer/midas.py +++ b/midas/lexer/midas.py @@ -32,6 +32,8 @@ class MidasLexer(Lexer): ) case "!" if self.match("="): self.add_token(TokenType.BANG_EQUAL) + case "!": + self.add_token(TokenType.BANG) case ":": self.add_token(TokenType.COLON) case ".": diff --git a/midas/lexer/token.py b/midas/lexer/token.py index d06052c..86ec518 100644 --- a/midas/lexer/token.py +++ b/midas/lexer/token.py @@ -36,6 +36,7 @@ class TokenType(Enum): EQUAL = auto() EQUAL_EQUAL = auto() BANG_EQUAL = auto() + BANG = auto() # Literals IDENTIFIER = auto() diff --git a/midas/parser/midas.py b/midas/parser/midas.py index 8b3282a..146ef54 100644 --- a/midas/parser/midas.py +++ b/midas/parser/midas.py @@ -487,12 +487,12 @@ class MidasParser(Parser[list[Stmt]]): """Parse a unary expression A unary consists of a call expression (see :func:`call`) optionally - preceded by zero or more unary operators (`+`, `-`) + preceded by zero or more unary operators (`+`, `-`, `!`) Returns: Expr: the parsed expression """ - if self.match(TokenType.PLUS, TokenType.MINUS): + if self.match(TokenType.PLUS, TokenType.MINUS, TokenType.BANG): operator: Token = self.previous() right: Expr = self.unary() location: Location = Location.span(operator.get_location(), right.location)