import ast from type_def import * from inference import * from helper import * from parse_expr import * from top_level import * types = { 'int32': PrimitiveType('int32'), 'int64': PrimitiveType('int64'), 'str': PrimitiveType('str'), 'bool': PrimitiveType('bool') } i32 = types['int32'] i64 = types['int64'] s = types['str'] b = types['bool'] variables = { 'X': TypeVariable('X', []), 'Y': TypeVariable('Y', []), 'I': TypeVariable('I', [i32, i64]), 'A': TypeVariable('A', [i32, i64, s]), } X = variables['X'] Y = variables['Y'] I = variables['I'] A = variables['A'] i32.methods['__init__'] = ([SelfType(), I], None, set()) i32.methods['__add__'] = ([SelfType(), i32], i32, set()) i32.methods['__sub__'] = ([SelfType(), i32], i32, set()) i32.methods['__lt__'] = ([SelfType(), i32], b, set()) i32.methods['__gt__'] = ([SelfType(), i32], b, set()) i32.methods['__eq__'] = ([SelfType(), i32], b, set()) i32.methods['__ne__'] = ([SelfType(), i32], b, set()) i32.methods['__le__'] = ([SelfType(), i32], b, set()) i32.methods['__ge__'] = ([SelfType(), i32], b, set()) i64.methods['__init__'] = ([SelfType(), I], None, set()) i64.methods['__add__'] = ([SelfType(), i64], i64, set()) i64.methods['__sub__'] = ([SelfType(), i64], i64, set()) i64.methods['__lt__'] = ([SelfType(), i64], b, set()) i64.methods['__gt__'] = ([SelfType(), i64], b, set()) i64.methods['__eq__'] = ([SelfType(), i64], b, set()) i64.methods['__ne__'] = ([SelfType(), i64], b, set()) i64.methods['__le__'] = ([SelfType(), i64], b, set()) i64.methods['__ge__'] = ([SelfType(), i64], b, set()) ctx = Context(variables, types) def test_expr(expr, sym_table= {}): print(f'Testing {expr} w.r.t. {stringify_subst(sym_table)}') try: tree = ast.parse(expr, mode='eval') result = parse_expr(ctx, sym_table, tree) print(result) except CustomError as err: print(f'error: {err.msg}') test_expr('1 + 1') test_expr('1 - 1') test_expr('int64(1)') test_expr('int64(1) - 1') test_expr('a - a', {'a': I}) test_expr('a - a', {'a': A}) test_expr('[1, 2, 3][2]') test_expr('[[1], [2], [3]][2]') test_expr('[[1], [2], [3]][a]', {'a': i32}) test_expr('[][:]', {}) test_expr('[1,2,3][:]', {}) test_expr('[1,2,3][1:3]', {}) test_expr('[1,2,3][:a:2]', {'a': I}) test_expr('[1,2,3][:a:2]', {'a': i32}) test_expr('a == a == a', {'a': I}) test_expr('a == a and 1 == 2', {'a': I}) test_expr('1 if a == b else 0', {'a': I, 'b': I}) test_expr('a if a == b else 1', {'a': I, 'b': I}) test_expr('a if a == b else b', {'a': I, 'b': I}) test_expr('[x for x in [1, 2, 3]]', {}) test_expr('[1 for x in [1, 2, 3] if x > 2]', {}) test_expr('[a + a for x in [1, 2, 3] if x > 2]', {'a': I}) test_expr('[a for a, b in [(1, 2), (2, 3), (3, 4)] if b > 2]', {}) test_expr('[b for a, b in [(1, (2, 3)), (2, (3, 4)), (3, (4, 5))] if b > 2]', {}) test_expr('[b for a, b in [(1, (2, 3)), (2, (3, 4)), (3, (4, 5))]]', {}) test_expr('[b for a, (b, c) in [(1, (2, 3)), (2, (3, 4)), (3, (4, 5))] if b > 2]', {}) test_classes = """ class Foo: a: int32 def __init__(self, a: int32): self.a = a def __add__(self, other: Foo) -> Foo: return Foo(self.a + other.a) def __sub__(self, other: Foo) -> Foo: return Foo(self.a - other.a) def __lt__(self, other: Foo) -> bool: pass def __le__(self, other: Foo) -> bool: pass def __gt__(self, other: Foo) -> bool: pass def __ge__(self, other: Foo) -> bool: pass def find(ls: list[I], x: I) -> int32: pass """ ctx, _ = parse_top_level(ctx, ast.parse(test_classes)) test_expr('Foo(1) + Foo(1)', {}) test_expr('Foo(1) + Foo(1) < Foo(2) + Foo(3) < Foo(4)', {}) test_expr('find([1, 2, 3], 1)', {}) test_expr('find([], 1)', {})