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()
|
stmts: list[m.Stmt] = parser.parse()
|
||||||
self.ctx.resolve(stmts)
|
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:
|
def is_subtype(self, type1: Type, type2: Type) -> bool:
|
||||||
"""Check whether `type1` is a subtype of `type2`
|
"""Check whether `type1` is a subtype of `type2`
|
||||||
|
|
||||||
@@ -562,7 +569,24 @@ class Checker(
|
|||||||
)
|
)
|
||||||
return function.returns
|
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:
|
def visit_literal_expr(self, expr: p.LiteralExpr) -> Type:
|
||||||
match expr.value:
|
match expr.value:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from typing import Optional
|
|||||||
import midas.ast.midas as m
|
import midas.ast.midas as m
|
||||||
from midas.checker.types import (
|
from midas.checker.types import (
|
||||||
AliasType,
|
AliasType,
|
||||||
|
ComplexType,
|
||||||
Operation,
|
Operation,
|
||||||
Type,
|
Type,
|
||||||
UnknownType,
|
UnknownType,
|
||||||
@@ -178,7 +179,8 @@ class MidasResolver(m.Stmt.Visitor[None], m.Expr.Visitor[None], m.Type.Visitor[T
|
|||||||
return UnknownType()
|
return UnknownType()
|
||||||
|
|
||||||
def visit_complex_type(self, type: m.ComplexType) -> Type:
|
def visit_complex_type(self, type: m.ComplexType) -> Type:
|
||||||
for prop in type.properties:
|
return ComplexType(
|
||||||
prop.accept(self)
|
properties={
|
||||||
# TODO
|
prop.name.lexeme: prop.type.accept(self) for prop in type.properties
|
||||||
return UnknownType()
|
}
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user