diff --git a/phasm/compiler.py b/phasm/compiler.py index 4b0a9fa..3bb8d21 100644 --- a/phasm/compiler.py +++ b/phasm/compiler.py @@ -36,7 +36,23 @@ INSTANCES = { 'a=i64': stdlib_types.i64_num_add, 'a=f32': stdlib_types.f32_num_add, 'a=f64': stdlib_types.f64_num_add, - } + }, + type3classes.Num.operators['-']: { + 'a=u32': stdlib_types.u32_num_sub, + 'a=u64': stdlib_types.u64_num_sub, + 'a=i32': stdlib_types.i32_num_sub, + 'a=i64': stdlib_types.i64_num_sub, + 'a=f32': stdlib_types.f32_num_sub, + 'a=f64': stdlib_types.f64_num_sub, + }, + type3classes.Num.operators['*']: { + 'a=u32': stdlib_types.u32_num_mul, + 'a=u64': stdlib_types.u64_num_mul, + 'a=i32': stdlib_types.i32_num_mul, + 'a=i64': stdlib_types.i64_num_mul, + 'a=f32': stdlib_types.f32_num_mul, + 'a=f64': stdlib_types.f64_num_mul, + }, } def phasm_compile(inp: ourlang.Module) -> wasm.Module: @@ -108,8 +124,6 @@ def type3(inp: type3types.Type3OrPlaceholder) -> wasm.WasmType: # Operators that work for i32, i64, f32, f64 OPERATOR_MAP = { - '-': 'sub', - '*': 'mul', '==': 'eq', } diff --git a/phasm/stdlib/types.py b/phasm/stdlib/types.py index 72e5b43..7d64f54 100644 --- a/phasm/stdlib/types.py +++ b/phasm/stdlib/types.py @@ -83,3 +83,39 @@ def f32_num_add(g: Generator) -> None: def f64_num_add(g: Generator) -> None: g.add_statement('f64.add') + +def u32_num_sub(g: Generator) -> None: + g.add_statement('i32.sub') + +def u64_num_sub(g: Generator) -> None: + g.add_statement('i64.sub') + +def i32_num_sub(g: Generator) -> None: + g.add_statement('i32.sub') + +def i64_num_sub(g: Generator) -> None: + g.add_statement('i64.sub') + +def f32_num_sub(g: Generator) -> None: + g.add_statement('f32.sub') + +def f64_num_sub(g: Generator) -> None: + g.add_statement('f64.sub') + +def u32_num_mul(g: Generator) -> None: + g.add_statement('i32.mul') + +def u64_num_mul(g: Generator) -> None: + g.add_statement('i64.mul') + +def i32_num_mul(g: Generator) -> None: + g.add_statement('i32.mul') + +def i64_num_mul(g: Generator) -> None: + g.add_statement('i64.mul') + +def f32_num_mul(g: Generator) -> None: + g.add_statement('f32.mul') + +def f64_num_mul(g: Generator) -> None: + g.add_statement('f64.mul') diff --git a/phasm/type3/constraints.py b/phasm/type3/constraints.py index 65061e7..e0f9e43 100644 --- a/phasm/type3/constraints.py +++ b/phasm/type3/constraints.py @@ -292,14 +292,14 @@ class MustImplementTypeClassConstraint(ConstraintBase): type3: types.Type3OrPlaceholder DATA = { - 'u8': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'}, - 'u32': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'}, - 'u64': {'BitWiseOperation', 'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'}, - 'i32': {'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'}, - 'i64': {'BasicMathOperation', 'EqualComparison', 'StrictPartialOrder'}, + 'u8': {'BitWiseOperation', 'EqualComparison', 'StrictPartialOrder'}, + 'u32': {'BitWiseOperation', 'EqualComparison', 'StrictPartialOrder'}, + 'u64': {'BitWiseOperation', 'EqualComparison', 'StrictPartialOrder'}, + 'i32': {'EqualComparison', 'StrictPartialOrder'}, + 'i64': {'EqualComparison', 'StrictPartialOrder'}, 'bytes': {'Foldable', 'Sized'}, - 'f32': {'BasicMathOperation', 'FloatingPoint'}, - 'f64': {'BasicMathOperation', 'FloatingPoint'}, + 'f32': {'Fractional', 'FloatingPoint'}, + 'f64': {'Fractional', 'FloatingPoint'}, } def __init__(self, type_class3: Union[str, typeclasses.Type3Class], type3: types.Type3OrPlaceholder, comment: Optional[str] = None) -> None: diff --git a/phasm/type3/constraintsgenerator.py b/phasm/type3/constraintsgenerator.py index e21f504..724c735 100644 --- a/phasm/type3/constraintsgenerator.py +++ b/phasm/type3/constraintsgenerator.py @@ -113,11 +113,11 @@ def expression(ctx: Context, inp: ourlang.Expression) -> ConstraintGenerator: comment=f'({inp.operator}) :: a -> a -> a') return - if inp.operator in ('-', '*', '/', ): + if inp.operator in ('/', ): yield from expression(ctx, inp.left) yield from expression(ctx, inp.right) - yield MustImplementTypeClassConstraint('BasicMathOperation', inp.left.type3) + yield MustImplementTypeClassConstraint('Fractional', inp.left.type3) yield SameTypeConstraint(inp.left.type3, inp.right.type3, inp.type3, comment=f'({inp.operator}) :: a -> a -> a') return diff --git a/phasm/type3/typeclasses.py b/phasm/type3/typeclasses.py index 56f1d3d..e966521 100644 --- a/phasm/type3/typeclasses.py +++ b/phasm/type3/typeclasses.py @@ -54,4 +54,6 @@ class Type3Class: Num = Type3Class('Num', ['a'], methods={}, operators={ '+': 'a -> a -> a', + '-': 'a -> a -> a', + '*': 'a -> a -> a', }) diff --git a/tests/integration/test_lang/test_num.py b/tests/integration/test_lang/test_num.py index 70ec473..8f628e5 100644 --- a/tests/integration/test_lang/test_num.py +++ b/tests/integration/test_lang/test_num.py @@ -110,7 +110,33 @@ def testEntry() -> u32: assert 4294967295 == result.returned_value -# TODO: Multiplication +@pytest.mark.integration_test +@pytest.mark.parametrize('type_', INT_TYPES) +def test_multiplication_int(type_): + code_py = f""" +@exported +def testEntry() -> {type_}: + return 10 * 3 +""" + + result = Suite(code_py).run_code() + + assert 30 == result.returned_value + assert TYPE_MAP[type_] == type(result.returned_value) + +@pytest.mark.integration_test +@pytest.mark.parametrize('type_', FLOAT_TYPES) +def test_multiplication_float(type_): + code_py = f""" +@exported +def testEntry() -> {type_}: + return 32.0 * 0.125 +""" + + result = Suite(code_py).run_code() + + assert 4.0 == result.returned_value + assert TYPE_MAP[type_] == type(result.returned_value) @pytest.mark.integration_test @pytest.mark.parametrize('type_', INT_TYPES)