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/
|
[4] https://www.w3.org/TR/wasm-core-1/
|
||||||
[5] https://en.wikipedia.org/w/index.php?title=WebAssembly&oldid=1103639883
|
[5] https://en.wikipedia.org/w/index.php?title=WebAssembly&oldid=1103639883
|
||||||
[6] https://github.com/WebAssembly/wabt
|
[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
|
- ourlang.BinaryOp should probably always be a Type3ClassMethod
|
||||||
- Remove U32_OPERATOR_MAP / U64_OPERATOR_MAP
|
- Remove U32_OPERATOR_MAP / U64_OPERATOR_MAP
|
||||||
- Make prelude more an actual thing
|
- 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=i32': stdlib_types.i32_integral_div,
|
||||||
'a=i64': stdlib_types.i64_integral_div,
|
'a=i64': stdlib_types.i64_integral_div,
|
||||||
},
|
},
|
||||||
type3classes.Num.operators['+']: {
|
type3classes.IntNum.methods['abs']: {
|
||||||
'a=u32': stdlib_types.u32_num_add,
|
'a=i32': stdlib_types.i32_intnum_abs,
|
||||||
'a=u64': stdlib_types.u64_num_add,
|
'a=i64': stdlib_types.i64_intnum_abs,
|
||||||
'a=i32': stdlib_types.i32_num_add,
|
'a=f32': stdlib_types.f32_intnum_abs,
|
||||||
'a=i64': stdlib_types.i64_num_add,
|
'a=f64': stdlib_types.f64_intnum_abs,
|
||||||
'a=f32': stdlib_types.f32_num_add,
|
|
||||||
'a=f64': stdlib_types.f64_num_add,
|
|
||||||
},
|
},
|
||||||
type3classes.Num.operators['-']: {
|
type3classes.IntNum.methods['neg']: {
|
||||||
'a=u32': stdlib_types.u32_num_sub,
|
'a=i32': stdlib_types.i32_intnum_neg,
|
||||||
'a=u64': stdlib_types.u64_num_sub,
|
'a=i64': stdlib_types.i64_intnum_neg,
|
||||||
'a=i32': stdlib_types.i32_num_sub,
|
'a=f32': stdlib_types.f32_intnum_neg,
|
||||||
'a=i64': stdlib_types.i64_num_sub,
|
'a=f64': stdlib_types.f64_intnum_neg,
|
||||||
'a=f32': stdlib_types.f32_num_sub,
|
|
||||||
'a=f64': stdlib_types.f64_num_sub,
|
|
||||||
},
|
},
|
||||||
type3classes.Num.operators['*']: {
|
type3classes.NatNum.operators['+']: {
|
||||||
'a=u32': stdlib_types.u32_num_mul,
|
'a=u32': stdlib_types.u32_natnum_add,
|
||||||
'a=u64': stdlib_types.u64_num_mul,
|
'a=u64': stdlib_types.u64_natnum_add,
|
||||||
'a=i32': stdlib_types.i32_num_mul,
|
'a=i32': stdlib_types.i32_natnum_add,
|
||||||
'a=i64': stdlib_types.i64_num_mul,
|
'a=i64': stdlib_types.i64_natnum_add,
|
||||||
'a=f32': stdlib_types.f32_num_mul,
|
'a=f32': stdlib_types.f32_natnum_add,
|
||||||
'a=f64': stdlib_types.f64_num_mul,
|
'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_alloc.__alloc__,
|
||||||
stdlib_types.__alloc_bytes__,
|
stdlib_types.__alloc_bytes__,
|
||||||
stdlib_types.__subscript_bytes__,
|
stdlib_types.__subscript_bytes__,
|
||||||
|
stdlib_types.__i32_intnum_abs__,
|
||||||
|
stdlib_types.__i64_intnum_abs__,
|
||||||
] + [
|
] + [
|
||||||
function(x)
|
function(x)
|
||||||
for x in inp.functions.values()
|
for x in inp.functions.values()
|
||||||
|
|||||||
@ -39,7 +39,8 @@ PRELUDE_OPERATORS = {
|
|||||||
**type3typeclasses.Eq.operators,
|
**type3typeclasses.Eq.operators,
|
||||||
**type3typeclasses.Fractional.operators,
|
**type3typeclasses.Fractional.operators,
|
||||||
**type3typeclasses.Integral.operators,
|
**type3typeclasses.Integral.operators,
|
||||||
**type3typeclasses.Num.operators,
|
**type3typeclasses.IntNum.operators,
|
||||||
|
**type3typeclasses.NatNum.operators,
|
||||||
}
|
}
|
||||||
|
|
||||||
PRELUDE_METHODS = {
|
PRELUDE_METHODS = {
|
||||||
@ -47,7 +48,8 @@ PRELUDE_METHODS = {
|
|||||||
**type3typeclasses.Floating.methods,
|
**type3typeclasses.Floating.methods,
|
||||||
**type3typeclasses.Fractional.methods,
|
**type3typeclasses.Fractional.methods,
|
||||||
**type3typeclasses.Integral.methods,
|
**type3typeclasses.Integral.methods,
|
||||||
**type3typeclasses.Num.methods,
|
**type3typeclasses.IntNum.methods,
|
||||||
|
**type3typeclasses.NatNum.methods,
|
||||||
}
|
}
|
||||||
|
|
||||||
def phasm_parse(source: str) -> Module:
|
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.stdlib import alloc
|
||||||
from phasm.wasmgenerator import Generator, func_wrapper
|
from phasm.wasmgenerator import Generator, func_wrapper
|
||||||
from phasm.wasmgenerator import VarType_i32 as i32
|
from phasm.wasmgenerator import VarType_i32 as i32
|
||||||
|
from phasm.wasmgenerator import VarType_i64 as i64
|
||||||
|
|
||||||
|
|
||||||
@func_wrapper()
|
@func_wrapper()
|
||||||
@ -66,6 +67,59 @@ def __subscript_bytes__(g: Generator, adr: i32, ofs: i32) -> i32:
|
|||||||
|
|
||||||
return i32('return') # To satisfy mypy
|
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:
|
def u8_eq_equals(g: Generator) -> None:
|
||||||
g.add_statement('i32.eq')
|
g.add_statement('i32.eq')
|
||||||
|
|
||||||
@ -114,56 +168,82 @@ def i32_integral_div(g: Generator) -> None:
|
|||||||
def i64_integral_div(g: Generator) -> None:
|
def i64_integral_div(g: Generator) -> None:
|
||||||
g.add_statement('i64.div_s')
|
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')
|
g.add_statement('i32.add')
|
||||||
|
|
||||||
def u64_num_add(g: Generator) -> None:
|
def u64_natnum_add(g: Generator) -> None:
|
||||||
g.add_statement('i64.add')
|
g.add_statement('i64.add')
|
||||||
|
|
||||||
def i32_num_add(g: Generator) -> None:
|
def i32_natnum_add(g: Generator) -> None:
|
||||||
g.add_statement('i32.add')
|
g.add_statement('i32.add')
|
||||||
|
|
||||||
def i64_num_add(g: Generator) -> None:
|
def i64_natnum_add(g: Generator) -> None:
|
||||||
g.add_statement('i64.add')
|
g.add_statement('i64.add')
|
||||||
|
|
||||||
def f32_num_add(g: Generator) -> None:
|
def f32_natnum_add(g: Generator) -> None:
|
||||||
g.add_statement('f32.add')
|
g.add_statement('f32.add')
|
||||||
|
|
||||||
def f64_num_add(g: Generator) -> None:
|
def f64_natnum_add(g: Generator) -> None:
|
||||||
g.add_statement('f64.add')
|
g.add_statement('f64.add')
|
||||||
|
|
||||||
def u32_num_sub(g: Generator) -> None:
|
def u32_natnum_sub(g: Generator) -> None:
|
||||||
g.add_statement('i32.sub')
|
g.add_statement('i32.sub')
|
||||||
|
|
||||||
def u64_num_sub(g: Generator) -> None:
|
def u64_natnum_sub(g: Generator) -> None:
|
||||||
g.add_statement('i64.sub')
|
g.add_statement('i64.sub')
|
||||||
|
|
||||||
def i32_num_sub(g: Generator) -> None:
|
def i32_natnum_sub(g: Generator) -> None:
|
||||||
g.add_statement('i32.sub')
|
g.add_statement('i32.sub')
|
||||||
|
|
||||||
def i64_num_sub(g: Generator) -> None:
|
def i64_natnum_sub(g: Generator) -> None:
|
||||||
g.add_statement('i64.sub')
|
g.add_statement('i64.sub')
|
||||||
|
|
||||||
def f32_num_sub(g: Generator) -> None:
|
def f32_natnum_sub(g: Generator) -> None:
|
||||||
g.add_statement('f32.sub')
|
g.add_statement('f32.sub')
|
||||||
|
|
||||||
def f64_num_sub(g: Generator) -> None:
|
def f64_natnum_sub(g: Generator) -> None:
|
||||||
g.add_statement('f64.sub')
|
g.add_statement('f64.sub')
|
||||||
|
|
||||||
def u32_num_mul(g: Generator) -> None:
|
def u32_natnum_mul(g: Generator) -> None:
|
||||||
g.add_statement('i32.mul')
|
g.add_statement('i32.mul')
|
||||||
|
|
||||||
def u64_num_mul(g: Generator) -> None:
|
def u64_natnum_mul(g: Generator) -> None:
|
||||||
g.add_statement('i64.mul')
|
g.add_statement('i64.mul')
|
||||||
|
|
||||||
def i32_num_mul(g: Generator) -> None:
|
def i32_natnum_mul(g: Generator) -> None:
|
||||||
g.add_statement('i32.mul')
|
g.add_statement('i32.mul')
|
||||||
|
|
||||||
def i64_num_mul(g: Generator) -> None:
|
def i64_natnum_mul(g: Generator) -> None:
|
||||||
g.add_statement('i64.mul')
|
g.add_statement('i64.mul')
|
||||||
|
|
||||||
def f32_num_mul(g: Generator) -> None:
|
def f32_natnum_mul(g: Generator) -> None:
|
||||||
g.add_statement('f32.mul')
|
g.add_statement('f32.mul')
|
||||||
|
|
||||||
def f64_num_mul(g: Generator) -> None:
|
def f64_natnum_mul(g: Generator) -> None:
|
||||||
g.add_statement('f64.mul')
|
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:
|
class TypeVariable:
|
||||||
@ -62,12 +62,13 @@ class Type3ClassMethod:
|
|||||||
return f'Type3ClassMethod({repr(self.type3_class)}, {repr(self.name)}, {repr(self.signature)})'
|
return f'Type3ClassMethod({repr(self.type3_class)}, {repr(self.name)}, {repr(self.signature)})'
|
||||||
|
|
||||||
class Type3Class:
|
class Type3Class:
|
||||||
__slots__ = ('name', 'args', 'methods', 'operators', )
|
__slots__ = ('name', 'args', 'methods', 'operators', 'inherited_classes', )
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
args: List[TypeVariable]
|
args: List[TypeVariable]
|
||||||
methods: Dict[str, Type3ClassMethod]
|
methods: Dict[str, Type3ClassMethod]
|
||||||
operators: Dict[str, Type3ClassMethod]
|
operators: Dict[str, Type3ClassMethod]
|
||||||
|
inherited_classes: List['Type3Class']
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -77,8 +78,6 @@ class Type3Class:
|
|||||||
operators: Mapping[str, str],
|
operators: Mapping[str, str],
|
||||||
inherited_classes: Optional[List['Type3Class']] = None,
|
inherited_classes: Optional[List['Type3Class']] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
del inherited_classes # Not implemented yet
|
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.args = [TypeVariable(x) for x in args]
|
self.args = [TypeVariable(x) for x in args]
|
||||||
self.methods = {
|
self.methods = {
|
||||||
@ -89,6 +88,7 @@ class Type3Class:
|
|||||||
k: Type3ClassMethod(self, k, v)
|
k: Type3ClassMethod(self, k, v)
|
||||||
for k, v in operators.items()
|
for k, v in operators.items()
|
||||||
}
|
}
|
||||||
|
self.inherited_classes = inherited_classes or []
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return self.name
|
return self.name
|
||||||
@ -97,20 +97,25 @@ Eq = Type3Class('Eq', ['a'], methods={}, operators={
|
|||||||
'==': 'a -> a -> bool',
|
'==': 'a -> a -> bool',
|
||||||
})
|
})
|
||||||
|
|
||||||
Num = Type3Class('Num', ['a'], methods={}, operators={
|
NatNum = Type3Class('NatNum', ['a'], methods={}, operators={
|
||||||
'+': 'a -> a -> a',
|
'+': 'a -> a -> a',
|
||||||
'-': 'a -> a -> a',
|
'-': '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={
|
Fractional = Type3Class('Fractional', ['a'], methods={}, operators={
|
||||||
'/': 'a -> a -> a',
|
'/': 'a -> a -> a',
|
||||||
}, inherited_classes=[Num])
|
}, inherited_classes=[NatNum])
|
||||||
|
|
||||||
Floating = Type3Class('Floating', ['a'], methods={
|
Floating = Type3Class('Floating', ['a'], methods={
|
||||||
'sqrt': 'a -> a',
|
'sqrt': 'a -> a',
|
||||||
}, operators={}, inherited_classes=[Fractional])
|
}, 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
|
These are actual, instantiated types; not the abstract types that the
|
||||||
constraint generator works with.
|
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'
|
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.
|
The name of the string, as parsed and outputted by codestyle.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
classes: List[Type3Class]
|
classes: Set[Type3Class]
|
||||||
"""
|
"""
|
||||||
The type classes that this type implements
|
The type classes that this type implements
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name: str, classes: Iterable[Type3Class]) -> None:
|
def __init__(self, name: str, classes: Iterable[Type3Class]) -> None:
|
||||||
self.name = name
|
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:
|
def __repr__(self) -> str:
|
||||||
return f'Type3({repr(self.name)}, {repr(self.classes)})'
|
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
|
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.
|
The unsigned 8-bit integer type.
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^8.
|
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.
|
The unsigned 32-bit integer type.
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^32.
|
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.
|
The unsigned 64-bit integer type.
|
||||||
|
|
||||||
Operations on variables employ modular arithmetic, with modulus 2^64.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
A 32-bits IEEE 754 float, of 64 bits width.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -21,6 +21,9 @@ class VarType_u8(VarType_Base):
|
|||||||
class VarType_i32(VarType_Base):
|
class VarType_i32(VarType_Base):
|
||||||
wasm_type = wasm.WasmTypeInt32
|
wasm_type = wasm.WasmTypeInt32
|
||||||
|
|
||||||
|
class VarType_i64(VarType_Base):
|
||||||
|
wasm_type = wasm.WasmTypeInt64
|
||||||
|
|
||||||
class Generator_i32i64:
|
class Generator_i32i64:
|
||||||
def __init__(self, prefix: str, generator: 'Generator') -> None:
|
def __init__(self, prefix: str, generator: 'Generator') -> None:
|
||||||
self.prefix = prefix
|
self.prefix = prefix
|
||||||
@ -31,6 +34,10 @@ class Generator_i32i64:
|
|||||||
self.add = functools.partial(self.generator.add_statement, f'{prefix}.add')
|
self.add = functools.partial(self.generator.add_statement, f'{prefix}.add')
|
||||||
self.sub = functools.partial(self.generator.add_statement, f'{prefix}.sub')
|
self.sub = functools.partial(self.generator.add_statement, f'{prefix}.sub')
|
||||||
self.mul = functools.partial(self.generator.add_statement, f'{prefix}.mul')
|
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
|
# irelop
|
||||||
self.eq = functools.partial(self.generator.add_statement, f'{prefix}.eq')
|
self.eq = functools.partial(self.generator.add_statement, f'{prefix}.eq')
|
||||||
@ -60,8 +67,23 @@ class Generator_f32f64:
|
|||||||
self.generator = generator
|
self.generator = generator
|
||||||
|
|
||||||
# 2.4.1. Numeric Instructions
|
# 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
|
# fbinop
|
||||||
self.add = functools.partial(self.generator.add_statement, f'{prefix}.add')
|
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
|
# frelop
|
||||||
self.eq = functools.partial(self.generator.add_statement, f'{prefix}.eq')
|
self.eq = functools.partial(self.generator.add_statement, f'{prefix}.eq')
|
||||||
|
|||||||
@ -26,10 +26,10 @@ class Foo:
|
|||||||
|
|
||||||
@exported
|
@exported
|
||||||
def testEntry(x: Foo, y: Foo) -> Foo:
|
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()
|
Suite(code_py).run_code()
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@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
|
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()
|
Suite(code_py).run_code()
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
@pytest.mark.integration_test
|
||||||
@ -122,7 +122,7 @@ def testEntry() -> {type_}:
|
|||||||
result = Suite(code_py).run_code()
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
assert 30 == result.returned_value
|
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.integration_test
|
||||||
@pytest.mark.parametrize('type_', FLOAT_TYPES)
|
@pytest.mark.parametrize('type_', FLOAT_TYPES)
|
||||||
@ -136,7 +136,7 @@ def testEntry() -> {type_}:
|
|||||||
result = Suite(code_py).run_code()
|
result = Suite(code_py).run_code()
|
||||||
|
|
||||||
assert 4.0 == result.returned_value
|
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.integration_test
|
||||||
@pytest.mark.parametrize('type_', INT_TYPES)
|
@pytest.mark.parametrize('type_', INT_TYPES)
|
||||||
Loading…
x
Reference in New Issue
Block a user