Implements the Ord type class

This commit is contained in:
Johan B.W. de Vries 2025-04-09 12:40:15 +02:00
parent 46dbc90475
commit 94c8f9388c
8 changed files with 492 additions and 30 deletions

View File

@ -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__,
] + [

View File

@ -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}')

View File

@ -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

View File

@ -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',

View File

@ -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.
"""

View File

@ -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')

View File

@ -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

View 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