Split Num into NatNum and IntNum
This is because Haskell defines negate, abs and signum for Num, but they don't work with our unsigned number types. (abs would be a noop.) Haskell has Word32 / Word64, but there negate doesn't make much sense to me. Implemented neg and abs. Implemented a type class inheritance check. Removed Integral from u8 and i8 since it wasn't implemented.
This commit is contained in:
parent
74ab3b47fd
commit
7544055a94
@ -97,3 +97,9 @@ References
|
||||
[4] https://www.w3.org/TR/wasm-core-1/
|
||||
[5] https://en.wikipedia.org/w/index.php?title=WebAssembly&oldid=1103639883
|
||||
[6] https://github.com/WebAssembly/wabt
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
- https://pengowray.github.io/wasm-ops/
|
||||
Shorthand overview for supported operations in WebAssembly.
|
||||
|
||||
1
TODO.md
1
TODO.md
@ -30,3 +30,4 @@
|
||||
- ourlang.BinaryOp should probably always be a Type3ClassMethod
|
||||
- Remove U32_OPERATOR_MAP / U64_OPERATOR_MAP
|
||||
- Make prelude more an actual thing
|
||||
- Implemented Bounded: https://hackage.haskell.org/package/base-4.21.0.0/docs/Prelude.html#t:Bounded
|
||||
|
||||
@ -53,29 +53,41 @@ INSTANCES = {
|
||||
'a=i32': stdlib_types.i32_integral_div,
|
||||
'a=i64': stdlib_types.i64_integral_div,
|
||||
},
|
||||
type3classes.Num.operators['+']: {
|
||||
'a=u32': stdlib_types.u32_num_add,
|
||||
'a=u64': stdlib_types.u64_num_add,
|
||||
'a=i32': stdlib_types.i32_num_add,
|
||||
'a=i64': stdlib_types.i64_num_add,
|
||||
'a=f32': stdlib_types.f32_num_add,
|
||||
'a=f64': stdlib_types.f64_num_add,
|
||||
type3classes.IntNum.methods['abs']: {
|
||||
'a=i32': stdlib_types.i32_intnum_abs,
|
||||
'a=i64': stdlib_types.i64_intnum_abs,
|
||||
'a=f32': stdlib_types.f32_intnum_abs,
|
||||
'a=f64': stdlib_types.f64_intnum_abs,
|
||||
},
|
||||
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.IntNum.methods['neg']: {
|
||||
'a=i32': stdlib_types.i32_intnum_neg,
|
||||
'a=i64': stdlib_types.i64_intnum_neg,
|
||||
'a=f32': stdlib_types.f32_intnum_neg,
|
||||
'a=f64': stdlib_types.f64_intnum_neg,
|
||||
},
|
||||
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,
|
||||
type3classes.NatNum.operators['+']: {
|
||||
'a=u32': stdlib_types.u32_natnum_add,
|
||||
'a=u64': stdlib_types.u64_natnum_add,
|
||||
'a=i32': stdlib_types.i32_natnum_add,
|
||||
'a=i64': stdlib_types.i64_natnum_add,
|
||||
'a=f32': stdlib_types.f32_natnum_add,
|
||||
'a=f64': stdlib_types.f64_natnum_add,
|
||||
},
|
||||
type3classes.NatNum.operators['-']: {
|
||||
'a=u32': stdlib_types.u32_natnum_sub,
|
||||
'a=u64': stdlib_types.u64_natnum_sub,
|
||||
'a=i32': stdlib_types.i32_natnum_sub,
|
||||
'a=i64': stdlib_types.i64_natnum_sub,
|
||||
'a=f32': stdlib_types.f32_natnum_sub,
|
||||
'a=f64': stdlib_types.f64_natnum_sub,
|
||||
},
|
||||
type3classes.NatNum.operators['*']: {
|
||||
'a=u32': stdlib_types.u32_natnum_mul,
|
||||
'a=u64': stdlib_types.u64_natnum_mul,
|
||||
'a=i32': stdlib_types.i32_natnum_mul,
|
||||
'a=i64': stdlib_types.i64_natnum_mul,
|
||||
'a=f32': stdlib_types.f32_natnum_mul,
|
||||
'a=f64': stdlib_types.f64_natnum_mul,
|
||||
},
|
||||
}
|
||||
|
||||
@ -894,6 +906,8 @@ def module(inp: ourlang.Module) -> wasm.Module:
|
||||
stdlib_alloc.__alloc__,
|
||||
stdlib_types.__alloc_bytes__,
|
||||
stdlib_types.__subscript_bytes__,
|
||||
stdlib_types.__i32_intnum_abs__,
|
||||
stdlib_types.__i64_intnum_abs__,
|
||||
] + [
|
||||
function(x)
|
||||
for x in inp.functions.values()
|
||||
|
||||
@ -39,7 +39,8 @@ PRELUDE_OPERATORS = {
|
||||
**type3typeclasses.Eq.operators,
|
||||
**type3typeclasses.Fractional.operators,
|
||||
**type3typeclasses.Integral.operators,
|
||||
**type3typeclasses.Num.operators,
|
||||
**type3typeclasses.IntNum.operators,
|
||||
**type3typeclasses.NatNum.operators,
|
||||
}
|
||||
|
||||
PRELUDE_METHODS = {
|
||||
@ -47,7 +48,8 @@ PRELUDE_METHODS = {
|
||||
**type3typeclasses.Floating.methods,
|
||||
**type3typeclasses.Fractional.methods,
|
||||
**type3typeclasses.Integral.methods,
|
||||
**type3typeclasses.Num.methods,
|
||||
**type3typeclasses.IntNum.methods,
|
||||
**type3typeclasses.NatNum.methods,
|
||||
}
|
||||
|
||||
def phasm_parse(source: str) -> Module:
|
||||
|
||||
@ -4,6 +4,7 @@ stdlib: Standard types that are not wasm primitives
|
||||
from phasm.stdlib import alloc
|
||||
from phasm.wasmgenerator import Generator, func_wrapper
|
||||
from phasm.wasmgenerator import VarType_i32 as i32
|
||||
from phasm.wasmgenerator import VarType_i64 as i64
|
||||
|
||||
|
||||
@func_wrapper()
|
||||
@ -66,6 +67,59 @@ def __subscript_bytes__(g: Generator, adr: i32, ofs: i32) -> i32:
|
||||
|
||||
return i32('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __i32_intnum_abs__(g: Generator, x: i32) -> i32:
|
||||
# https://stackoverflow.com/a/14194764
|
||||
y = i32('y')
|
||||
# z = i32('z')
|
||||
|
||||
# y = x >> 31
|
||||
g.local.get(x)
|
||||
g.i32.const(31)
|
||||
g.i32.shr_s() # Must be arithmetic shift
|
||||
g.local.set(y)
|
||||
|
||||
# abs(x) = (x XOR y) - y
|
||||
|
||||
# (x XOR y)
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i32.xor()
|
||||
|
||||
# - y
|
||||
g.local.get(y)
|
||||
g.i32.sub()
|
||||
g.return_()
|
||||
|
||||
return i32('return')
|
||||
|
||||
@func_wrapper()
|
||||
def __i64_intnum_abs__(g: Generator, x: i64) -> i64:
|
||||
# https://stackoverflow.com/a/14194764
|
||||
y = i64('y')
|
||||
# z = i64('z')
|
||||
|
||||
# y = x >> 31
|
||||
g.local.get(x)
|
||||
g.i64.const(31)
|
||||
g.i64.shr_s() # Must be arithmetic shift
|
||||
g.local.set(y)
|
||||
|
||||
# abs(x) = (x XOR y) - y
|
||||
|
||||
# (x XOR y)
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i64.xor()
|
||||
|
||||
# - y
|
||||
g.local.get(y)
|
||||
g.i64.sub()
|
||||
g.return_()
|
||||
|
||||
return i64('return')
|
||||
|
||||
|
||||
def u8_eq_equals(g: Generator) -> None:
|
||||
g.add_statement('i32.eq')
|
||||
|
||||
@ -114,56 +168,82 @@ def i32_integral_div(g: Generator) -> None:
|
||||
def i64_integral_div(g: Generator) -> None:
|
||||
g.add_statement('i64.div_s')
|
||||
|
||||
def u32_num_add(g: Generator) -> None:
|
||||
def u32_natnum_add(g: Generator) -> None:
|
||||
g.add_statement('i32.add')
|
||||
|
||||
def u64_num_add(g: Generator) -> None:
|
||||
def u64_natnum_add(g: Generator) -> None:
|
||||
g.add_statement('i64.add')
|
||||
|
||||
def i32_num_add(g: Generator) -> None:
|
||||
def i32_natnum_add(g: Generator) -> None:
|
||||
g.add_statement('i32.add')
|
||||
|
||||
def i64_num_add(g: Generator) -> None:
|
||||
def i64_natnum_add(g: Generator) -> None:
|
||||
g.add_statement('i64.add')
|
||||
|
||||
def f32_num_add(g: Generator) -> None:
|
||||
def f32_natnum_add(g: Generator) -> None:
|
||||
g.add_statement('f32.add')
|
||||
|
||||
def f64_num_add(g: Generator) -> None:
|
||||
def f64_natnum_add(g: Generator) -> None:
|
||||
g.add_statement('f64.add')
|
||||
|
||||
def u32_num_sub(g: Generator) -> None:
|
||||
def u32_natnum_sub(g: Generator) -> None:
|
||||
g.add_statement('i32.sub')
|
||||
|
||||
def u64_num_sub(g: Generator) -> None:
|
||||
def u64_natnum_sub(g: Generator) -> None:
|
||||
g.add_statement('i64.sub')
|
||||
|
||||
def i32_num_sub(g: Generator) -> None:
|
||||
def i32_natnum_sub(g: Generator) -> None:
|
||||
g.add_statement('i32.sub')
|
||||
|
||||
def i64_num_sub(g: Generator) -> None:
|
||||
def i64_natnum_sub(g: Generator) -> None:
|
||||
g.add_statement('i64.sub')
|
||||
|
||||
def f32_num_sub(g: Generator) -> None:
|
||||
def f32_natnum_sub(g: Generator) -> None:
|
||||
g.add_statement('f32.sub')
|
||||
|
||||
def f64_num_sub(g: Generator) -> None:
|
||||
def f64_natnum_sub(g: Generator) -> None:
|
||||
g.add_statement('f64.sub')
|
||||
|
||||
def u32_num_mul(g: Generator) -> None:
|
||||
def u32_natnum_mul(g: Generator) -> None:
|
||||
g.add_statement('i32.mul')
|
||||
|
||||
def u64_num_mul(g: Generator) -> None:
|
||||
def u64_natnum_mul(g: Generator) -> None:
|
||||
g.add_statement('i64.mul')
|
||||
|
||||
def i32_num_mul(g: Generator) -> None:
|
||||
def i32_natnum_mul(g: Generator) -> None:
|
||||
g.add_statement('i32.mul')
|
||||
|
||||
def i64_num_mul(g: Generator) -> None:
|
||||
def i64_natnum_mul(g: Generator) -> None:
|
||||
g.add_statement('i64.mul')
|
||||
|
||||
def f32_num_mul(g: Generator) -> None:
|
||||
def f32_natnum_mul(g: Generator) -> None:
|
||||
g.add_statement('f32.mul')
|
||||
|
||||
def f64_num_mul(g: Generator) -> None:
|
||||
def f64_natnum_mul(g: Generator) -> None:
|
||||
g.add_statement('f64.mul')
|
||||
|
||||
def i32_intnum_abs(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i32_intnum_abs__')
|
||||
|
||||
def i64_intnum_abs(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i64_intnum_abs__')
|
||||
|
||||
def f32_intnum_abs(g: Generator) -> None:
|
||||
g.f32.abs()
|
||||
|
||||
def f64_intnum_abs(g: Generator) -> None:
|
||||
g.f64.abs()
|
||||
|
||||
def i32_intnum_neg(g: Generator) -> None:
|
||||
g.i32.const(-1)
|
||||
g.i32.mul()
|
||||
|
||||
def i64_intnum_neg(g: Generator) -> None:
|
||||
g.i64.const(-1)
|
||||
g.i64.mul()
|
||||
|
||||
def f32_intnum_neg(g: Generator) -> None:
|
||||
g.f32.neg()
|
||||
|
||||
def f64_intnum_neg(g: Generator) -> None:
|
||||
g.f64.neg()
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict, Iterable, Optional, List, Mapping, Union
|
||||
from typing import Any, Dict, Iterable, List, Mapping, Optional, Union
|
||||
|
||||
|
||||
class TypeVariable:
|
||||
@ -62,12 +62,13 @@ class Type3ClassMethod:
|
||||
return f'Type3ClassMethod({repr(self.type3_class)}, {repr(self.name)}, {repr(self.signature)})'
|
||||
|
||||
class Type3Class:
|
||||
__slots__ = ('name', 'args', 'methods', 'operators', )
|
||||
__slots__ = ('name', 'args', 'methods', 'operators', 'inherited_classes', )
|
||||
|
||||
name: str
|
||||
args: List[TypeVariable]
|
||||
methods: Dict[str, Type3ClassMethod]
|
||||
operators: Dict[str, Type3ClassMethod]
|
||||
inherited_classes: List['Type3Class']
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -77,8 +78,6 @@ class Type3Class:
|
||||
operators: Mapping[str, str],
|
||||
inherited_classes: Optional[List['Type3Class']] = None,
|
||||
) -> None:
|
||||
del inherited_classes # Not implemented yet
|
||||
|
||||
self.name = name
|
||||
self.args = [TypeVariable(x) for x in args]
|
||||
self.methods = {
|
||||
@ -89,6 +88,7 @@ class Type3Class:
|
||||
k: Type3ClassMethod(self, k, v)
|
||||
for k, v in operators.items()
|
||||
}
|
||||
self.inherited_classes = inherited_classes or []
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return self.name
|
||||
@ -97,20 +97,25 @@ Eq = Type3Class('Eq', ['a'], methods={}, operators={
|
||||
'==': 'a -> a -> bool',
|
||||
})
|
||||
|
||||
Num = Type3Class('Num', ['a'], methods={}, operators={
|
||||
NatNum = Type3Class('NatNum', ['a'], methods={}, operators={
|
||||
'+': 'a -> a -> a',
|
||||
'-': 'a -> a -> a',
|
||||
'*': 'a -> a -> a',
|
||||
})
|
||||
|
||||
IntNum = Type3Class('IntNum', ['a'], methods={
|
||||
'abs': 'a -> a',
|
||||
'neg': 'a -> a',
|
||||
}, operators={}, inherited_classes=[NatNum])
|
||||
|
||||
Integral = Type3Class('Eq', ['a'], methods={
|
||||
'div': 'a -> a -> a',
|
||||
}, operators={}, inherited_classes=[NatNum])
|
||||
|
||||
Fractional = Type3Class('Fractional', ['a'], methods={}, operators={
|
||||
'/': 'a -> a -> a',
|
||||
}, inherited_classes=[Num])
|
||||
}, inherited_classes=[NatNum])
|
||||
|
||||
Floating = Type3Class('Floating', ['a'], methods={
|
||||
'sqrt': 'a -> a',
|
||||
}, operators={}, inherited_classes=[Fractional])
|
||||
|
||||
Integral = Type3Class('Eq', ['a'], methods={
|
||||
'div': 'a -> a -> a',
|
||||
}, operators={})
|
||||
|
||||
@ -4,9 +4,9 @@ Contains the final types for use in Phasm
|
||||
These are actual, instantiated types; not the abstract types that the
|
||||
constraint generator works with.
|
||||
"""
|
||||
from typing import Any, Dict, Iterable, List, Optional, Protocol, Union
|
||||
from typing import Any, Dict, Iterable, List, Optional, Protocol, Set, Union
|
||||
|
||||
from .typeclasses import Eq, Floating, Fractional, Integral, Num, Type3Class
|
||||
from .typeclasses import Eq, Floating, Fractional, Integral, IntNum, NatNum, Type3Class
|
||||
|
||||
TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before you can call any other method'
|
||||
|
||||
@ -31,14 +31,19 @@ class Type3:
|
||||
The name of the string, as parsed and outputted by codestyle.
|
||||
"""
|
||||
|
||||
classes: List[Type3Class]
|
||||
classes: Set[Type3Class]
|
||||
"""
|
||||
The type classes that this type implements
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, classes: Iterable[Type3Class]) -> None:
|
||||
self.name = name
|
||||
self.classes = [*classes]
|
||||
self.classes = set(classes)
|
||||
|
||||
for cls in self.classes:
|
||||
for inh_cls in cls.inherited_classes:
|
||||
if inh_cls not in self.classes:
|
||||
raise Exception(f'No instance for ({inh_cls} {self.name})')
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'Type3({repr(self.name)}, {repr(self.classes)})'
|
||||
@ -242,28 +247,28 @@ The bool type, either True or False
|
||||
Suffixes with an underscores, as it's a Python builtin
|
||||
"""
|
||||
|
||||
u8 = PrimitiveType3('u8', [Eq, Integral])
|
||||
u8 = PrimitiveType3('u8', [Eq])
|
||||
"""
|
||||
The unsigned 8-bit integer type.
|
||||
|
||||
Operations on variables employ modular arithmetic, with modulus 2^8.
|
||||
"""
|
||||
|
||||
u32 = PrimitiveType3('u32', [Eq, Integral, Num])
|
||||
u32 = PrimitiveType3('u32', [Eq, Integral, NatNum])
|
||||
"""
|
||||
The unsigned 32-bit integer type.
|
||||
|
||||
Operations on variables employ modular arithmetic, with modulus 2^32.
|
||||
"""
|
||||
|
||||
u64 = PrimitiveType3('u64', [Eq, Integral, Num])
|
||||
u64 = PrimitiveType3('u64', [Eq, Integral, NatNum])
|
||||
"""
|
||||
The unsigned 64-bit integer type.
|
||||
|
||||
Operations on variables employ modular arithmetic, with modulus 2^64.
|
||||
"""
|
||||
|
||||
i8 = PrimitiveType3('i8', [Eq, Integral])
|
||||
i8 = PrimitiveType3('i8', [Eq])
|
||||
"""
|
||||
The signed 8-bit integer type.
|
||||
|
||||
@ -271,7 +276,7 @@ Operations on variables employ modular arithmetic, with modulus 2^8, but
|
||||
with the middel point being 0.
|
||||
"""
|
||||
|
||||
i32 = PrimitiveType3('i32', [Eq, Integral, Num])
|
||||
i32 = PrimitiveType3('i32', [Eq, Integral, IntNum, NatNum])
|
||||
"""
|
||||
The unsigned 32-bit integer type.
|
||||
|
||||
@ -279,7 +284,7 @@ Operations on variables employ modular arithmetic, with modulus 2^32, but
|
||||
with the middel point being 0.
|
||||
"""
|
||||
|
||||
i64 = PrimitiveType3('i64', [Eq, Integral, Num])
|
||||
i64 = PrimitiveType3('i64', [Eq, Integral, IntNum, NatNum])
|
||||
"""
|
||||
The unsigned 64-bit integer type.
|
||||
|
||||
@ -287,12 +292,12 @@ Operations on variables employ modular arithmetic, with modulus 2^64, but
|
||||
with the middel point being 0.
|
||||
"""
|
||||
|
||||
f32 = PrimitiveType3('f32', [Eq, Floating, Fractional, Num])
|
||||
f32 = PrimitiveType3('f32', [Eq, Floating, Fractional, IntNum, NatNum])
|
||||
"""
|
||||
A 32-bits IEEE 754 float, of 32 bits width.
|
||||
"""
|
||||
|
||||
f64 = PrimitiveType3('f64', [Eq, Floating, Fractional, Num])
|
||||
f64 = PrimitiveType3('f64', [Eq, Floating, Fractional, IntNum, NatNum])
|
||||
"""
|
||||
A 32-bits IEEE 754 float, of 64 bits width.
|
||||
"""
|
||||
|
||||
@ -21,6 +21,9 @@ class VarType_u8(VarType_Base):
|
||||
class VarType_i32(VarType_Base):
|
||||
wasm_type = wasm.WasmTypeInt32
|
||||
|
||||
class VarType_i64(VarType_Base):
|
||||
wasm_type = wasm.WasmTypeInt64
|
||||
|
||||
class Generator_i32i64:
|
||||
def __init__(self, prefix: str, generator: 'Generator') -> None:
|
||||
self.prefix = prefix
|
||||
@ -31,6 +34,10 @@ class Generator_i32i64:
|
||||
self.add = functools.partial(self.generator.add_statement, f'{prefix}.add')
|
||||
self.sub = functools.partial(self.generator.add_statement, f'{prefix}.sub')
|
||||
self.mul = functools.partial(self.generator.add_statement, f'{prefix}.mul')
|
||||
self.shr_s = functools.partial(self.generator.add_statement, f'{prefix}.shr_s')
|
||||
self.shr_u = functools.partial(self.generator.add_statement, f'{prefix}.shr_u')
|
||||
self.rotr = functools.partial(self.generator.add_statement, f'{prefix}.rotr')
|
||||
self.xor = functools.partial(self.generator.add_statement, f'{prefix}.xor')
|
||||
|
||||
# irelop
|
||||
self.eq = functools.partial(self.generator.add_statement, f'{prefix}.eq')
|
||||
@ -60,8 +67,23 @@ class Generator_f32f64:
|
||||
self.generator = generator
|
||||
|
||||
# 2.4.1. Numeric Instructions
|
||||
# funop
|
||||
self.abs = functools.partial(self.generator.add_statement, f'{prefix}.abs')
|
||||
self.neg = functools.partial(self.generator.add_statement, f'{prefix}.neg')
|
||||
self.sqrt = functools.partial(self.generator.add_statement, f'{prefix}.sqrt')
|
||||
self.ceil = functools.partial(self.generator.add_statement, f'{prefix}.ceil')
|
||||
self.floor = functools.partial(self.generator.add_statement, f'{prefix}.floor')
|
||||
self.trunc = functools.partial(self.generator.add_statement, f'{prefix}.trunc')
|
||||
self.nearest = functools.partial(self.generator.add_statement, f'{prefix}.nearest')
|
||||
|
||||
# fbinop
|
||||
self.add = functools.partial(self.generator.add_statement, f'{prefix}.add')
|
||||
self.sub = functools.partial(self.generator.add_statement, f'{prefix}.sub')
|
||||
self.mul = functools.partial(self.generator.add_statement, f'{prefix}.mul')
|
||||
self.div = functools.partial(self.generator.add_statement, f'{prefix}.div')
|
||||
self.min = functools.partial(self.generator.add_statement, f'{prefix}.min')
|
||||
self.max = functools.partial(self.generator.add_statement, f'{prefix}.max')
|
||||
self.copysign = functools.partial(self.generator.add_statement, f'{prefix}.copysign')
|
||||
|
||||
# frelop
|
||||
self.eq = functools.partial(self.generator.add_statement, f'{prefix}.eq')
|
||||
|
||||
@ -26,10 +26,10 @@ class Foo:
|
||||
|
||||
@exported
|
||||
def testEntry(x: Foo, y: Foo) -> Foo:
|
||||
return x + y
|
||||
return x == y
|
||||
"""
|
||||
|
||||
with pytest.raises(Type3Exception, match='Foo does not implement the Num type class'):
|
||||
with pytest.raises(Type3Exception, match='Foo does not implement the Eq type class'):
|
||||
Suite(code_py).run_code()
|
||||
|
||||
@pytest.mark.integration_test
|
||||
|
||||
69
tests/integration/test_lang/test_intnum.py
Normal file
69
tests/integration/test_lang/test_intnum.py
Normal file
@ -0,0 +1,69 @@
|
||||
import pytest
|
||||
|
||||
from ..helpers import Suite
|
||||
|
||||
INT_TYPES = ['i32', 'i64']
|
||||
FLOAT_TYPES = ['f32', 'f64']
|
||||
|
||||
TYPE_MAP = {
|
||||
'i32': int,
|
||||
'i64': int,
|
||||
'f32': float,
|
||||
'f64': float,
|
||||
}
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', INT_TYPES)
|
||||
def test_abs_int(type_):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry() -> {type_}:
|
||||
return abs(-3)
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert 3 == result.returned_value
|
||||
assert TYPE_MAP[type_] is type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', FLOAT_TYPES)
|
||||
def test_abs_float(type_):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry() -> {type_}:
|
||||
return abs(-3.5)
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert 3.5 == result.returned_value
|
||||
assert TYPE_MAP[type_] is type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', INT_TYPES)
|
||||
def test_neg_int(type_):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry() -> {type_}:
|
||||
return neg(3)
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert -3 == result.returned_value
|
||||
assert TYPE_MAP[type_] is type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', FLOAT_TYPES)
|
||||
def test_neg_float(type_):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry() -> {type_}:
|
||||
return neg(3.5)
|
||||
"""
|
||||
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert -3.5 == result.returned_value
|
||||
assert TYPE_MAP[type_] is type(result.returned_value)
|
||||
@ -27,7 +27,7 @@ def testEntry(x: Foo, y: Foo) -> Foo:
|
||||
return x + y
|
||||
"""
|
||||
|
||||
with pytest.raises(Type3Exception, match='Foo does not implement the Num type class'):
|
||||
with pytest.raises(Type3Exception, match='Foo does not implement the NatNum type class'):
|
||||
Suite(code_py).run_code()
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@ -122,7 +122,7 @@ def testEntry() -> {type_}:
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert 30 == result.returned_value
|
||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||
assert TYPE_MAP[type_] is type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', FLOAT_TYPES)
|
||||
@ -136,7 +136,7 @@ def testEntry() -> {type_}:
|
||||
result = Suite(code_py).run_code()
|
||||
|
||||
assert 4.0 == result.returned_value
|
||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||
assert TYPE_MAP[type_] is type(result.returned_value)
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', INT_TYPES)
|
||||
Loading…
x
Reference in New Issue
Block a user