Skip to content

Instantly share code, notes, and snippets.

@nerodono
Created May 18, 2024 12:42
Show Gist options
  • Save nerodono/0562b0a03d2fb95236d35245511870a8 to your computer and use it in GitHub Desktop.
Save nerodono/0562b0a03d2fb95236d35245511870a8 to your computer and use it in GitHub Desktop.
Simplest typeck
import typing as t
from dataclasses import dataclass
Tp: t.TypeAlias = """
(
Struct
| Unknown
| Int
| Str
)
"""
@dataclass
class Int:
def __repr__(self) -> str:
return "int"
@dataclass
class Str:
def __repr__(self) -> str:
return "str"
@dataclass
class Struct:
fields: dict[str, Tp]
def __repr__(self) -> str:
return "{ %s }" % ", ".join(
f"{key}: {value!r}"
for key, value in self.fields.items()
)
@dataclass
class Unknown:
def __repr__(self) -> str:
return "?"
def typeck_struct(left: Struct, right: Struct) -> tuple[Struct, Struct]:
lhs_fields = {**left.fields}
rhs_fields = {**right.fields}
for lhs_name, lhs_tp in left.fields.items():
if lhs_name not in right.fields:
raise ValueError(f"struct {right!r} does not matches shape of struct {left} ({lhs_name!r} not found)")
rhs_tp = right.fields[lhs_name]
lhs_tp, rhs_tp = typeck(lhs_tp, rhs_tp)
lhs_fields[lhs_name] = lhs_tp
rhs_fields[lhs_name] = rhs_tp
return (Struct(lhs_fields), Struct(rhs_fields))
def typeck(type: Tp, with_: Tp) -> tuple[Tp, Tp]:
if isinstance(type, Unknown):
return (with_, with_)
elif isinstance(with_, Unknown):
return (type, type)
elif isinstance(type, Struct):
if not isinstance(with_, Struct):
raise ValueError(f"Typeck fail: {with_} is not a struct")
return typeck_struct(type, with_)
elif isinstance(type, Int):
if not isinstance(with_, Int):
raise ValueError(f"Typeck fail: {with_} is not a int")
return (type, with_)
elif isinstance(type, Str):
if not isinstance(with_, Str):
raise ValueError(f"Typeck fail: {with_} is not a string")
return (type, with_)
raise NotImplementedError
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment