Implements the Ord type class
This commit is contained in:
parent
46dbc90475
commit
94c8f9388c
@ -49,6 +49,66 @@ INSTANCES = {
|
||||
'a=f32': stdlib_types.f32_eq_not_equals,
|
||||
'a=f64': stdlib_types.f64_eq_not_equals,
|
||||
},
|
||||
type3classes.Ord.methods['min']: {
|
||||
'a=u8': stdlib_types.u8_ord_min,
|
||||
'a=u32': stdlib_types.u32_ord_min,
|
||||
'a=u64': stdlib_types.u64_ord_min,
|
||||
'a=i8': stdlib_types.i8_ord_min,
|
||||
'a=i32': stdlib_types.i32_ord_min,
|
||||
'a=i64': stdlib_types.i64_ord_min,
|
||||
'a=f32': stdlib_types.f32_ord_min,
|
||||
'a=f64': stdlib_types.f64_ord_min,
|
||||
},
|
||||
type3classes.Ord.methods['max']: {
|
||||
'a=u8': stdlib_types.u8_ord_max,
|
||||
'a=u32': stdlib_types.u32_ord_max,
|
||||
'a=u64': stdlib_types.u64_ord_max,
|
||||
'a=i8': stdlib_types.i8_ord_max,
|
||||
'a=i32': stdlib_types.i32_ord_max,
|
||||
'a=i64': stdlib_types.i64_ord_max,
|
||||
'a=f32': stdlib_types.f32_ord_max,
|
||||
'a=f64': stdlib_types.f64_ord_max,
|
||||
},
|
||||
type3classes.Ord.operators['<']: {
|
||||
'a=u8': stdlib_types.u8_ord_less_than,
|
||||
'a=u32': stdlib_types.u32_ord_less_than,
|
||||
'a=u64': stdlib_types.u64_ord_less_than,
|
||||
'a=i8': stdlib_types.i8_ord_less_than,
|
||||
'a=i32': stdlib_types.i32_ord_less_than,
|
||||
'a=i64': stdlib_types.i64_ord_less_than,
|
||||
'a=f32': stdlib_types.f32_ord_less_than,
|
||||
'a=f64': stdlib_types.f64_ord_less_than,
|
||||
},
|
||||
type3classes.Ord.operators['<=']: {
|
||||
'a=u8': stdlib_types.u8_ord_less_than_or_equal,
|
||||
'a=u32': stdlib_types.u32_ord_less_than_or_equal,
|
||||
'a=u64': stdlib_types.u64_ord_less_than_or_equal,
|
||||
'a=i8': stdlib_types.i8_ord_less_than_or_equal,
|
||||
'a=i32': stdlib_types.i32_ord_less_than_or_equal,
|
||||
'a=i64': stdlib_types.i64_ord_less_than_or_equal,
|
||||
'a=f32': stdlib_types.f32_ord_less_than_or_equal,
|
||||
'a=f64': stdlib_types.f64_ord_less_than_or_equal,
|
||||
},
|
||||
type3classes.Ord.operators['>']: {
|
||||
'a=u8': stdlib_types.u8_ord_greater_than,
|
||||
'a=u32': stdlib_types.u32_ord_greater_than,
|
||||
'a=u64': stdlib_types.u64_ord_greater_than,
|
||||
'a=i8': stdlib_types.i8_ord_greater_than,
|
||||
'a=i32': stdlib_types.i32_ord_greater_than,
|
||||
'a=i64': stdlib_types.i64_ord_greater_than,
|
||||
'a=f32': stdlib_types.f32_ord_greater_than,
|
||||
'a=f64': stdlib_types.f64_ord_greater_than,
|
||||
},
|
||||
type3classes.Ord.operators['>=']: {
|
||||
'a=u8': stdlib_types.u8_ord_greater_than_or_equal,
|
||||
'a=u32': stdlib_types.u32_ord_greater_than_or_equal,
|
||||
'a=u64': stdlib_types.u64_ord_greater_than_or_equal,
|
||||
'a=i8': stdlib_types.i8_ord_greater_than_or_equal,
|
||||
'a=i32': stdlib_types.i32_ord_greater_than_or_equal,
|
||||
'a=i64': stdlib_types.i64_ord_greater_than_or_equal,
|
||||
'a=f32': stdlib_types.f32_ord_greater_than_or_equal,
|
||||
'a=f64': stdlib_types.f64_ord_greater_than_or_equal,
|
||||
},
|
||||
type3classes.Floating.methods['sqrt']: {
|
||||
'a=f32': stdlib_types.f32_floating_sqrt,
|
||||
'a=f64': stdlib_types.f64_floating_sqrt,
|
||||
@ -200,10 +260,6 @@ U8_OPERATOR_MAP = {
|
||||
}
|
||||
|
||||
U32_OPERATOR_MAP = {
|
||||
'<': 'lt_u',
|
||||
'>': 'gt_u',
|
||||
'<=': 'le_u',
|
||||
'>=': 'ge_u',
|
||||
'<<': 'shl',
|
||||
'>>': 'shr_u',
|
||||
'^': 'xor',
|
||||
@ -212,10 +268,6 @@ U32_OPERATOR_MAP = {
|
||||
}
|
||||
|
||||
U64_OPERATOR_MAP = {
|
||||
'<': 'lt_u',
|
||||
'>': 'gt_u',
|
||||
'<=': 'le_u',
|
||||
'>=': 'ge_u',
|
||||
'<<': 'shl',
|
||||
'>>': 'shr_u',
|
||||
'^': 'xor',
|
||||
@ -223,18 +275,10 @@ U64_OPERATOR_MAP = {
|
||||
'&': 'and',
|
||||
}
|
||||
|
||||
I32_OPERATOR_MAP = {
|
||||
'<': 'lt_s',
|
||||
'>': 'gt_s',
|
||||
'<=': 'le_s',
|
||||
'>=': 'ge_s',
|
||||
I32_OPERATOR_MAP: dict[str, str] = {
|
||||
}
|
||||
|
||||
I64_OPERATOR_MAP = {
|
||||
'<': 'lt_s',
|
||||
'>': 'gt_s',
|
||||
'<=': 'le_s',
|
||||
'>=': 'ge_s',
|
||||
I64_OPERATOR_MAP: dict[str, str] = {
|
||||
}
|
||||
|
||||
def tuple_instantiation(wgn: WasmGenerator, inp: ourlang.TupleInstantiation) -> None:
|
||||
@ -923,6 +967,14 @@ def module(inp: ourlang.Module) -> wasm.Module:
|
||||
stdlib_alloc.__alloc__,
|
||||
stdlib_types.__alloc_bytes__,
|
||||
stdlib_types.__subscript_bytes__,
|
||||
stdlib_types.__u32_ord_min__,
|
||||
stdlib_types.__u64_ord_min__,
|
||||
stdlib_types.__i32_ord_min__,
|
||||
stdlib_types.__i64_ord_min__,
|
||||
stdlib_types.__u32_ord_max__,
|
||||
stdlib_types.__u64_ord_max__,
|
||||
stdlib_types.__i32_ord_max__,
|
||||
stdlib_types.__i64_ord_max__,
|
||||
stdlib_types.__i32_intnum_abs__,
|
||||
stdlib_types.__i64_intnum_abs__,
|
||||
] + [
|
||||
|
||||
@ -36,6 +36,7 @@ from .type3 import types as type3types
|
||||
|
||||
PRELUDE_OPERATORS = {
|
||||
**type3typeclasses.Eq.operators,
|
||||
**type3typeclasses.Ord.operators,
|
||||
**type3typeclasses.Fractional.operators,
|
||||
**type3typeclasses.Integral.operators,
|
||||
**type3typeclasses.IntNum.operators,
|
||||
@ -44,6 +45,7 @@ PRELUDE_OPERATORS = {
|
||||
|
||||
PRELUDE_METHODS = {
|
||||
**type3typeclasses.Eq.methods,
|
||||
**type3typeclasses.Ord.methods,
|
||||
**type3typeclasses.Floating.methods,
|
||||
**type3typeclasses.Fractional.methods,
|
||||
**type3typeclasses.Integral.methods,
|
||||
@ -405,12 +407,16 @@ class OurVisitor:
|
||||
|
||||
if isinstance(node.ops[0], ast.Gt):
|
||||
operator = '>'
|
||||
elif isinstance(node.ops[0], ast.GtE):
|
||||
operator = '>='
|
||||
elif isinstance(node.ops[0], ast.Eq):
|
||||
operator = '=='
|
||||
elif isinstance(node.ops[0], ast.NotEq):
|
||||
operator = '!='
|
||||
elif isinstance(node.ops[0], ast.Lt):
|
||||
operator = '<'
|
||||
elif isinstance(node.ops[0], ast.LtE):
|
||||
operator = '<='
|
||||
else:
|
||||
raise NotImplementedError(f'Operator {node.ops}')
|
||||
|
||||
|
||||
@ -67,6 +67,126 @@ def __subscript_bytes__(g: Generator, adr: i32, ofs: i32) -> i32:
|
||||
|
||||
return i32('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __u32_ord_min__(g: Generator, x: i32, y: i32) -> i32:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i32.lt_u()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i32('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __u64_ord_min__(g: Generator, x: i64, y: i64) -> i64:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i64.lt_u()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i64('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __i32_ord_min__(g: Generator, x: i32, y: i32) -> i32:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i32.lt_s()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i32('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __i64_ord_min__(g: Generator, x: i64, y: i64) -> i64:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i64.lt_s()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i64('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __u32_ord_max__(g: Generator, x: i32, y: i32) -> i32:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i32.gt_u()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i32('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __u64_ord_max__(g: Generator, x: i64, y: i64) -> i64:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i64.gt_u()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i64('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __i32_ord_max__(g: Generator, x: i32, y: i32) -> i32:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i32.gt_s()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i32('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __i64_ord_max__(g: Generator, x: i64, y: i64) -> i64:
|
||||
g.local.get(x)
|
||||
g.local.get(y)
|
||||
g.i64.gt_s()
|
||||
|
||||
with g.if_():
|
||||
g.local.get(x)
|
||||
g.return_()
|
||||
|
||||
g.local.get(y)
|
||||
g.return_()
|
||||
|
||||
return i64('return') # To satisfy mypy
|
||||
|
||||
@func_wrapper()
|
||||
def __i32_intnum_abs__(g: Generator, x: i32) -> i32:
|
||||
# https://stackoverflow.com/a/14194764
|
||||
@ -170,6 +290,153 @@ def f32_eq_not_equals(g: Generator) -> None:
|
||||
def f64_eq_not_equals(g: Generator) -> None:
|
||||
g.f64.ne()
|
||||
|
||||
## ###
|
||||
## class Ord
|
||||
|
||||
def u8_ord_min(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__u32_ord_min__')
|
||||
|
||||
def u32_ord_min(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__u32_ord_min__')
|
||||
|
||||
def u64_ord_min(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__u64_ord_min__')
|
||||
|
||||
def i8_ord_min(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i32_ord_min__')
|
||||
|
||||
def i32_ord_min(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i32_ord_min__')
|
||||
|
||||
def i64_ord_min(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i64_ord_min__')
|
||||
|
||||
def f32_ord_min(g: Generator) -> None:
|
||||
g.f32.min()
|
||||
|
||||
def f64_ord_min(g: Generator) -> None:
|
||||
g.f64.min()
|
||||
|
||||
def u8_ord_max(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__u32_ord_max__')
|
||||
|
||||
def u32_ord_max(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__u32_ord_max__')
|
||||
|
||||
def u64_ord_max(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__u64_ord_max__')
|
||||
|
||||
def i8_ord_max(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i32_ord_max__')
|
||||
|
||||
def i32_ord_max(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i32_ord_max__')
|
||||
|
||||
def i64_ord_max(g: Generator) -> None:
|
||||
g.add_statement('call $stdlib.types.__i64_ord_max__')
|
||||
|
||||
def f32_ord_max(g: Generator) -> None:
|
||||
g.f32.max()
|
||||
|
||||
def f64_ord_max(g: Generator) -> None:
|
||||
g.f64.max()
|
||||
|
||||
|
||||
def u8_ord_less_than(g: Generator) -> None:
|
||||
g.i32.lt_u()
|
||||
|
||||
def u32_ord_less_than(g: Generator) -> None:
|
||||
g.i32.lt_u()
|
||||
|
||||
def u64_ord_less_than(g: Generator) -> None:
|
||||
g.i64.lt_u()
|
||||
|
||||
def i8_ord_less_than(g: Generator) -> None:
|
||||
g.i32.lt_s()
|
||||
|
||||
def i32_ord_less_than(g: Generator) -> None:
|
||||
g.i32.lt_s()
|
||||
|
||||
def i64_ord_less_than(g: Generator) -> None:
|
||||
g.i64.lt_s()
|
||||
|
||||
def f32_ord_less_than(g: Generator) -> None:
|
||||
g.f32.lt()
|
||||
|
||||
def f64_ord_less_than(g: Generator) -> None:
|
||||
g.f64.lt()
|
||||
|
||||
def u8_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.i32.le_u()
|
||||
|
||||
def u32_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.i32.le_u()
|
||||
|
||||
def u64_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.i64.le_u()
|
||||
|
||||
def i8_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.i32.le_s()
|
||||
|
||||
def i32_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.i32.le_s()
|
||||
|
||||
def i64_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.i64.le_s()
|
||||
|
||||
def f32_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.f32.le()
|
||||
|
||||
def f64_ord_less_than_or_equal(g: Generator) -> None:
|
||||
g.f64.le()
|
||||
|
||||
def u8_ord_greater_than(g: Generator) -> None:
|
||||
g.i32.gt_u()
|
||||
|
||||
def u32_ord_greater_than(g: Generator) -> None:
|
||||
g.i32.gt_u()
|
||||
|
||||
def u64_ord_greater_than(g: Generator) -> None:
|
||||
g.i64.gt_u()
|
||||
|
||||
def i8_ord_greater_than(g: Generator) -> None:
|
||||
g.i32.gt_s()
|
||||
|
||||
def i32_ord_greater_than(g: Generator) -> None:
|
||||
g.i32.gt_s()
|
||||
|
||||
def i64_ord_greater_than(g: Generator) -> None:
|
||||
g.i64.gt_s()
|
||||
|
||||
def f32_ord_greater_than(g: Generator) -> None:
|
||||
g.f32.gt()
|
||||
|
||||
def f64_ord_greater_than(g: Generator) -> None:
|
||||
g.f64.gt()
|
||||
|
||||
def u8_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.i32.ge_u()
|
||||
|
||||
def u32_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.i32.ge_u()
|
||||
|
||||
def u64_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.i64.ge_u()
|
||||
|
||||
def i8_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.i32.ge_s()
|
||||
|
||||
def i32_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.i32.ge_s()
|
||||
|
||||
def i64_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.i64.ge_s()
|
||||
|
||||
def f32_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.f32.ge()
|
||||
|
||||
def f64_ord_greater_than_or_equal(g: Generator) -> None:
|
||||
g.f64.ge()
|
||||
|
||||
## ###
|
||||
## class Fractional
|
||||
|
||||
@ -98,6 +98,16 @@ Eq = Type3Class('Eq', ['a'], methods={}, operators={
|
||||
'!=': 'a -> a -> bool',
|
||||
})
|
||||
|
||||
Ord = Type3Class('Ord', ['a'], methods={
|
||||
'min': 'a -> a -> a',
|
||||
'max': 'a -> a -> a',
|
||||
}, operators={
|
||||
'<': 'a -> a -> bool',
|
||||
'<=': 'a -> a -> bool',
|
||||
'>': 'a -> a -> bool',
|
||||
'>=': 'a -> a -> bool',
|
||||
}, inherited_classes=[Eq])
|
||||
|
||||
NatNum = Type3Class('NatNum', ['a'], methods={}, operators={
|
||||
'+': 'a -> a -> a',
|
||||
'-': 'a -> a -> a',
|
||||
|
||||
@ -6,7 +6,16 @@ constraint generator works with.
|
||||
"""
|
||||
from typing import Any, Dict, Iterable, List, Optional, Protocol, Set, Union
|
||||
|
||||
from .typeclasses import Eq, Floating, Fractional, Integral, IntNum, NatNum, Type3Class
|
||||
from .typeclasses import (
|
||||
Eq,
|
||||
Floating,
|
||||
Fractional,
|
||||
Integral,
|
||||
IntNum,
|
||||
NatNum,
|
||||
Ord,
|
||||
Type3Class,
|
||||
)
|
||||
|
||||
TYPE3_ASSERTION_ERROR = 'You must call phasm_type3 after calling phasm_parse before you can call any other method'
|
||||
|
||||
@ -43,7 +52,10 @@ class Type3:
|
||||
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})')
|
||||
raise Exception(
|
||||
f'No instance for ({inh_cls} {self.name})'
|
||||
f'; required for ({cls} {self.name})'
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f'Type3({repr(self.name)}, {repr(self.classes)})'
|
||||
@ -247,28 +259,28 @@ The bool type, either True or False
|
||||
Suffixes with an underscores, as it's a Python builtin
|
||||
"""
|
||||
|
||||
u8 = PrimitiveType3('u8', [Eq])
|
||||
u8 = PrimitiveType3('u8', [Eq, Ord])
|
||||
"""
|
||||
The unsigned 8-bit integer type.
|
||||
|
||||
Operations on variables employ modular arithmetic, with modulus 2^8.
|
||||
"""
|
||||
|
||||
u32 = PrimitiveType3('u32', [Eq, Integral, NatNum])
|
||||
u32 = PrimitiveType3('u32', [Eq, Integral, NatNum, Ord])
|
||||
"""
|
||||
The unsigned 32-bit integer type.
|
||||
|
||||
Operations on variables employ modular arithmetic, with modulus 2^32.
|
||||
"""
|
||||
|
||||
u64 = PrimitiveType3('u64', [Eq, Integral, NatNum])
|
||||
u64 = PrimitiveType3('u64', [Eq, Integral, NatNum, Ord])
|
||||
"""
|
||||
The unsigned 64-bit integer type.
|
||||
|
||||
Operations on variables employ modular arithmetic, with modulus 2^64.
|
||||
"""
|
||||
|
||||
i8 = PrimitiveType3('i8', [Eq])
|
||||
i8 = PrimitiveType3('i8', [Eq, Ord])
|
||||
"""
|
||||
The signed 8-bit integer type.
|
||||
|
||||
@ -276,7 +288,7 @@ Operations on variables employ modular arithmetic, with modulus 2^8, but
|
||||
with the middel point being 0.
|
||||
"""
|
||||
|
||||
i32 = PrimitiveType3('i32', [Eq, Integral, IntNum, NatNum])
|
||||
i32 = PrimitiveType3('i32', [Eq, Integral, IntNum, NatNum, Ord])
|
||||
"""
|
||||
The unsigned 32-bit integer type.
|
||||
|
||||
@ -284,7 +296,7 @@ Operations on variables employ modular arithmetic, with modulus 2^32, but
|
||||
with the middel point being 0.
|
||||
"""
|
||||
|
||||
i64 = PrimitiveType3('i64', [Eq, Integral, IntNum, NatNum])
|
||||
i64 = PrimitiveType3('i64', [Eq, Integral, IntNum, NatNum, Ord])
|
||||
"""
|
||||
The unsigned 64-bit integer type.
|
||||
|
||||
@ -292,12 +304,12 @@ Operations on variables employ modular arithmetic, with modulus 2^64, but
|
||||
with the middel point being 0.
|
||||
"""
|
||||
|
||||
f32 = PrimitiveType3('f32', [Eq, Floating, Fractional, IntNum, NatNum])
|
||||
f32 = PrimitiveType3('f32', [Eq, Floating, Fractional, IntNum, NatNum, Ord])
|
||||
"""
|
||||
A 32-bits IEEE 754 float, of 32 bits width.
|
||||
"""
|
||||
|
||||
f64 = PrimitiveType3('f64', [Eq, Floating, Fractional, IntNum, NatNum])
|
||||
f64 = PrimitiveType3('f64', [Eq, Floating, Fractional, IntNum, NatNum, Ord])
|
||||
"""
|
||||
A 32-bits IEEE 754 float, of 64 bits width.
|
||||
"""
|
||||
|
||||
@ -34,15 +34,29 @@ 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.div_s = functools.partial(self.generator.add_statement, f'{prefix}.div_s')
|
||||
self.div_u = functools.partial(self.generator.add_statement, f'{prefix}.div_u')
|
||||
self.rem_s = functools.partial(self.generator.add_statement, f'{prefix}.rem_s')
|
||||
self.rem_u = functools.partial(self.generator.add_statement, f'{prefix}.rem_u')
|
||||
self.and_ = functools.partial(self.generator.add_statement, f'{prefix}.and')
|
||||
self.or_ = functools.partial(self.generator.add_statement, f'{prefix}.or')
|
||||
self.xor = functools.partial(self.generator.add_statement, f'{prefix}.xor')
|
||||
self.shl = functools.partial(self.generator.add_statement, f'{prefix}.shl')
|
||||
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.rotl = functools.partial(self.generator.add_statement, f'{prefix}.rotl')
|
||||
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')
|
||||
self.ne = functools.partial(self.generator.add_statement, f'{prefix}.ne')
|
||||
self.lt_s = functools.partial(self.generator.add_statement, f'{prefix}.lt_s')
|
||||
self.lt_u = functools.partial(self.generator.add_statement, f'{prefix}.lt_u')
|
||||
self.gt_s = functools.partial(self.generator.add_statement, f'{prefix}.gt_s')
|
||||
self.gt_u = functools.partial(self.generator.add_statement, f'{prefix}.gt_u')
|
||||
self.le_s = functools.partial(self.generator.add_statement, f'{prefix}.le_s')
|
||||
self.le_u = functools.partial(self.generator.add_statement, f'{prefix}.le_u')
|
||||
self.ge_s = functools.partial(self.generator.add_statement, f'{prefix}.ge_s')
|
||||
self.ge_u = functools.partial(self.generator.add_statement, f'{prefix}.ge_u')
|
||||
|
||||
# 2.4.4. Memory Instructions
|
||||
@ -88,6 +102,10 @@ class Generator_f32f64:
|
||||
# frelop
|
||||
self.eq = functools.partial(self.generator.add_statement, f'{prefix}.eq')
|
||||
self.ne = functools.partial(self.generator.add_statement, f'{prefix}.ne')
|
||||
self.lt = functools.partial(self.generator.add_statement, f'{prefix}.lt')
|
||||
self.gt = functools.partial(self.generator.add_statement, f'{prefix}.gt')
|
||||
self.le = functools.partial(self.generator.add_statement, f'{prefix}.le')
|
||||
self.ge = functools.partial(self.generator.add_statement, f'{prefix}.ge')
|
||||
|
||||
# 2.4.4. Memory Instructions
|
||||
self.load = functools.partial(self.generator.add_statement, f'{prefix}.load')
|
||||
|
||||
@ -253,7 +253,7 @@ def _load_memory_stored_returned_value(
|
||||
assert isinstance(wasm_value, int), wasm_value
|
||||
return 0 != wasm_value
|
||||
|
||||
if ret_type3 in (type3types.i32, type3types.i64):
|
||||
if ret_type3 in (type3types.i8, type3types.i32, type3types.i64):
|
||||
assert isinstance(wasm_value, int), wasm_value
|
||||
return wasm_value
|
||||
|
||||
|
||||
97
tests/integration/test_lang/test_ord.py
Normal file
97
tests/integration/test_lang/test_ord.py
Normal file
@ -0,0 +1,97 @@
|
||||
import struct
|
||||
|
||||
import pytest
|
||||
|
||||
from ..helpers import Suite
|
||||
|
||||
TYPE_LIST = [
|
||||
'u8', 'u32', 'u64',
|
||||
'i8', 'i32', 'i64',
|
||||
'f32', 'f64',
|
||||
]
|
||||
|
||||
BOUND_MAP = {
|
||||
'u8': struct.unpack('<BB', bytes.fromhex('00FF')),
|
||||
'u32': struct.unpack('<II', bytes.fromhex('00000000FFFFFFFF')),
|
||||
'u64': struct.unpack('<QQ', bytes.fromhex('0000000000000000FFFFFFFFFFFFFFFF')),
|
||||
'i8': struct.unpack('<bb', bytes.fromhex('807F')),
|
||||
'i32': struct.unpack('<ii', bytes.fromhex('00000080FFFFFF7F')),
|
||||
'i64': struct.unpack('<qq', bytes.fromhex('0000000000000080FFFFFFFFFFFFFF7F')),
|
||||
'f32': struct.unpack('<ff', bytes.fromhex('01000000FFFF7F7F')),
|
||||
'f64': struct.unpack('<dd', bytes.fromhex('0000000000001000FFFFFFFFFFFFEF7F')),
|
||||
}
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', TYPE_LIST)
|
||||
@pytest.mark.parametrize('test_lft,test_opr,test_rgt,test_out', [
|
||||
(1, '<', 2, True, ),
|
||||
(1, '<', 0, False, ),
|
||||
|
||||
(1, '<=', 1, True, ),
|
||||
(1, '<=', 0, False, ),
|
||||
|
||||
(1, '>', 0, True, ),
|
||||
(1, '>', 1, False, ),
|
||||
|
||||
(1, '>=', 0, True, ),
|
||||
(1, '>=', 2, False, ),
|
||||
])
|
||||
def test_ord_operators(type_, test_lft, test_opr, test_rgt, test_out):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry(lft: {type_}, rgt: {type_}) -> bool:
|
||||
return lft {test_opr} rgt
|
||||
"""
|
||||
|
||||
if type_[0] == 'f':
|
||||
test_lft = float(test_lft)
|
||||
test_rgt = float(test_rgt)
|
||||
|
||||
result = Suite(code_py).run_code(test_lft, test_rgt)
|
||||
|
||||
assert test_out is result.returned_value
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', TYPE_LIST)
|
||||
@pytest.mark.parametrize('test_mth,test_lft,test_rgt,test_out', [
|
||||
('min', 1, 2, 1),
|
||||
('min', 2, 1, 1),
|
||||
('min', 2, 2, 2),
|
||||
|
||||
('max', 1, 2, 2),
|
||||
('max', 2, 1, 2),
|
||||
('max', 2, 2, 2),
|
||||
])
|
||||
def test_ord_methods(type_, test_mth, test_lft, test_rgt, test_out):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry(lft: {type_}, rgt: {type_}) -> {type_}:
|
||||
return {test_mth}(lft, rgt)
|
||||
"""
|
||||
|
||||
if type_[0] == 'f':
|
||||
test_lft = float(test_lft)
|
||||
test_rgt = float(test_rgt)
|
||||
|
||||
result = Suite(code_py).run_code(test_lft, test_rgt)
|
||||
|
||||
assert test_out == result.returned_value
|
||||
|
||||
@pytest.mark.integration_test
|
||||
@pytest.mark.parametrize('type_', TYPE_LIST)
|
||||
@pytest.mark.parametrize('test_mth', ['min', 'max'])
|
||||
def test_ord_bounds_min_max(type_, test_mth):
|
||||
code_py = f"""
|
||||
@exported
|
||||
def testEntry(lft: {type_}, rgt: {type_}) -> {type_}:
|
||||
return {test_mth}(lft, rgt)
|
||||
"""
|
||||
|
||||
test_lft, test_rgt = BOUND_MAP[type_]
|
||||
|
||||
result = Suite(code_py).run_code(test_lft, test_rgt)
|
||||
|
||||
if 'min' == test_mth:
|
||||
assert test_lft == result.returned_value
|
||||
else:
|
||||
assert test_rgt == result.returned_value
|
||||
Loading…
x
Reference in New Issue
Block a user