Implements division

Division by zero is a trap on most runtimes, following
the Let it Crash philosophy
This commit is contained in:
Johan B.W. de Vries 2022-09-22 11:50:38 +02:00
parent 977c449c3f
commit bce3ed7ba1
4 changed files with 49 additions and 2 deletions

View File

@ -101,6 +101,7 @@ U32_OPERATOR_MAP = {
'^': 'xor', '^': 'xor',
'|': 'or', '|': 'or',
'&': 'and', '&': 'and',
'/': 'div_u' # Division by zero is a trap and the program will panic
} }
U64_OPERATOR_MAP = { U64_OPERATOR_MAP = {
@ -113,6 +114,7 @@ U64_OPERATOR_MAP = {
'^': 'xor', '^': 'xor',
'|': 'or', '|': 'or',
'&': 'and', '&': 'and',
'/': 'div_u' # Division by zero is a trap and the program will panic
} }
I32_OPERATOR_MAP = { I32_OPERATOR_MAP = {
@ -120,6 +122,7 @@ I32_OPERATOR_MAP = {
'>': 'gt_s', '>': 'gt_s',
'<=': 'le_s', '<=': 'le_s',
'>=': 'ge_s', '>=': 'ge_s',
'/': 'div_s' # Division by zero is a trap and the program will panic
} }
I64_OPERATOR_MAP = { I64_OPERATOR_MAP = {
@ -127,6 +130,15 @@ I64_OPERATOR_MAP = {
'>': 'gt_s', '>': 'gt_s',
'<=': 'le_s', '<=': 'le_s',
'>=': 'ge_s', '>=': 'ge_s',
'/': 'div_s' # Division by zero is a trap and the program will panic
}
F32_OPERATOR_MAP = {
'/': 'div' # Division by zero is a trap and the program will panic
}
F64_OPERATOR_MAP = {
'/': 'div' # Division by zero is a trap and the program will panic
} }
def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None: def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
@ -251,10 +263,16 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
if operator := OPERATOR_MAP.get(inp.operator, None): if operator := OPERATOR_MAP.get(inp.operator, None):
wgn.add_statement(f'f32.{operator}') wgn.add_statement(f'f32.{operator}')
return return
if operator := F32_OPERATOR_MAP.get(inp.operator, None):
wgn.add_statement(f'f32.{operator}')
return
if mtyp == 'f64': if mtyp == 'f64':
if operator := OPERATOR_MAP.get(inp.operator, None): if operator := OPERATOR_MAP.get(inp.operator, None):
wgn.add_statement(f'f64.{operator}') wgn.add_statement(f'f64.{operator}')
return return
if operator := F64_OPERATOR_MAP.get(inp.operator, None):
wgn.add_statement(f'f64.{operator}')
return
raise NotImplementedError(expression, inp.type_var, inp.operator) raise NotImplementedError(expression, inp.type_var, inp.operator)

View File

@ -351,6 +351,8 @@ class OurVisitor:
operator = '-' operator = '-'
elif isinstance(node.op, ast.Mult): elif isinstance(node.op, ast.Mult):
operator = '*' operator = '*'
elif isinstance(node.op, ast.Div):
operator = '/'
elif isinstance(node.op, ast.LShift): elif isinstance(node.op, ast.LShift):
operator = '<<' operator = '<<'
elif isinstance(node.op, ast.RShift): elif isinstance(node.op, ast.RShift):

View File

@ -98,7 +98,7 @@ def expression(ctx: Context, inp: ourlang.Expression) -> 'TypeVar':
return right return right
if isinstance(inp, ourlang.BinaryOp): if isinstance(inp, ourlang.BinaryOp):
if inp.operator in ('+', '-', '*', '|', '&', '^'): if inp.operator in ('+', '-', '*', '/', '|', '&', '^'):
left = expression(ctx, inp.left) left = expression(ctx, inp.left)
right = expression(ctx, inp.right) right = expression(ctx, inp.right)
ctx.unify(left, right) ctx.unify(left, right)

View File

@ -226,7 +226,34 @@ def testEntry() -> {type_}:
assert TYPE_MAP[type_] == type(result.returned_value) assert TYPE_MAP[type_] == type(result.returned_value)
# TODO: Multiplication # TODO: Multiplication
# TODO: Division
@pytest.mark.integration_test
@pytest.mark.parametrize('type_', COMPLETE_INT_TYPES)
def test_division_int(type_):
code_py = f"""
@exported
def testEntry() -> {type_}:
return 10 / 3
"""
result = Suite(code_py).run_code()
assert 3 == result.returned_value
assert TYPE_MAP[type_] == type(result.returned_value)
@pytest.mark.integration_test
@pytest.mark.parametrize('type_', ALL_FLOAT_TYPES)
def test_division_float(type_):
code_py = f"""
@exported
def testEntry() -> {type_}:
return 10.0 / 8.0
"""
result = Suite(code_py).run_code()
assert 1.25 == result.returned_value
assert TYPE_MAP[type_] == type(result.returned_value)
@pytest.mark.integration_test @pytest.mark.integration_test
@pytest.mark.parametrize('type_', ['f32', 'f64']) @pytest.mark.parametrize('type_', ['f32', 'f64'])