feat(checker): handle attribute getter
This commit is contained in:
11
examples/01_simple_type_checking/04_complex_types.midas
Normal file
11
examples/01_simple_type_checking/04_complex_types.midas
Normal file
@@ -0,0 +1,11 @@
|
||||
type Meter = float
|
||||
|
||||
extend Meter {
|
||||
op __add__(Meter) -> Meter
|
||||
op __sub__(Meter) -> Meter
|
||||
}
|
||||
|
||||
type Coordinate = {
|
||||
x: Meter
|
||||
y: Meter
|
||||
}
|
||||
9
examples/01_simple_type_checking/04_complex_types.py
Normal file
9
examples/01_simple_type_checking/04_complex_types.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# type: ignore
|
||||
# ruff: disable [F821]
|
||||
p1: Coordinate
|
||||
p2: Coordinate
|
||||
|
||||
diff_x = p2.x - p1.x
|
||||
diff_y = p2.y - p1.y
|
||||
|
||||
dist = diff_x + diff_y
|
||||
@@ -178,6 +178,13 @@ class Checker(
|
||||
stmts: list[m.Stmt] = parser.parse()
|
||||
self.ctx.resolve(stmts)
|
||||
|
||||
def unfold_type(self, type: Type) -> Type:
|
||||
match type:
|
||||
case AliasType(type=ref_type):
|
||||
return self.unfold_type(ref_type)
|
||||
case _:
|
||||
return type
|
||||
|
||||
def is_subtype(self, type1: Type, type2: Type) -> bool:
|
||||
"""Check whether `type1` is a subtype of `type2`
|
||||
|
||||
@@ -562,7 +569,24 @@ class Checker(
|
||||
)
|
||||
return function.returns
|
||||
|
||||
def visit_get_expr(self, expr: p.GetExpr) -> Type: ...
|
||||
def visit_get_expr(self, expr: p.GetExpr) -> Type:
|
||||
object: Type = self.type_of(expr.object)
|
||||
base_object: Type = self.unfold_type(object)
|
||||
match base_object:
|
||||
case ComplexType(properties=properties):
|
||||
if expr.name not in properties:
|
||||
self.error(
|
||||
expr.location, f"Unknown property '{expr.name} on {object}"
|
||||
)
|
||||
return UnknownType()
|
||||
return properties[expr.name]
|
||||
case UnknownType():
|
||||
return UnknownType()
|
||||
case _:
|
||||
self.error(
|
||||
expr.location, f"Cannot get property '{expr.name}' on {object}"
|
||||
)
|
||||
return UnknownType()
|
||||
|
||||
def visit_literal_expr(self, expr: p.LiteralExpr) -> Type:
|
||||
match expr.value:
|
||||
|
||||
@@ -3,6 +3,7 @@ from typing import Optional
|
||||
import midas.ast.midas as m
|
||||
from midas.checker.types import (
|
||||
AliasType,
|
||||
ComplexType,
|
||||
Operation,
|
||||
Type,
|
||||
UnknownType,
|
||||
@@ -178,7 +179,8 @@ class MidasResolver(m.Stmt.Visitor[None], m.Expr.Visitor[None], m.Type.Visitor[T
|
||||
return UnknownType()
|
||||
|
||||
def visit_complex_type(self, type: m.ComplexType) -> Type:
|
||||
for prop in type.properties:
|
||||
prop.accept(self)
|
||||
# TODO
|
||||
return UnknownType()
|
||||
return ComplexType(
|
||||
properties={
|
||||
prop.name.lexeme: prop.type.accept(self) for prop in type.properties
|
||||
}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user