Reimplements casting and foldl
Probably not 100% type checked yet. Also, fixed logical right shift; standard says the type is different.
This commit is contained in:
parent
a164976f63
commit
1afa3efc31
@ -297,11 +297,10 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
|||||||
wgn.i32.load()
|
wgn.i32.load()
|
||||||
return
|
return
|
||||||
|
|
||||||
# TODO: Broken after new type system
|
if inp.operator == 'cast':
|
||||||
# if inp.operator == 'cast':
|
if inp.type3 == type3types.u32 and inp.right.type3 == type3types.u8:
|
||||||
# if isinstance(inp.type, typing.TypeUInt32) and isinstance(inp.right.type, typing.TypeUInt8):
|
# Nothing to do, you can use an u8 value as a u32 no problem
|
||||||
# # Nothing to do, you can use an u8 value as a u32 no problem
|
return
|
||||||
# return
|
|
||||||
|
|
||||||
raise NotImplementedError(expression, inp.type3, inp.operator)
|
raise NotImplementedError(expression, inp.type3, inp.operator)
|
||||||
|
|
||||||
@ -397,10 +396,8 @@ def expression_fold(wgn: WasmGenerator, inp: ourlang.Fold) -> None:
|
|||||||
"""
|
"""
|
||||||
assert isinstance(inp.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
|
assert isinstance(inp.type3, type3types.Type3), type3types.TYPE3_ASSERTION_ERROR
|
||||||
|
|
||||||
raise NotImplementedError('TODO: Broken after new type system')
|
if inp.iter.type3 is not type3types.bytes:
|
||||||
|
raise NotImplementedError(expression_fold, inp, inp.iter.type3)
|
||||||
if inp.iter.type.__class__.__name__ != 'TypeBytes':
|
|
||||||
raise NotImplementedError(expression, inp, inp.iter.type)
|
|
||||||
|
|
||||||
wgn.add_statement('nop', comment='acu :: u8')
|
wgn.add_statement('nop', comment='acu :: u8')
|
||||||
acu_var = wgn.temp_var_u8(f'fold_{codestyle.type3(inp.type3)}_acu')
|
acu_var = wgn.temp_var_u8(f'fold_{codestyle.type3(inp.type3)}_acu')
|
||||||
|
|||||||
@ -563,8 +563,6 @@ class OurVisitor:
|
|||||||
if 2 != len(func.posonlyargs):
|
if 2 != len(func.posonlyargs):
|
||||||
_raise_static_error(node, f'Function {node.func.id} requires a function with 2 arguments but a function with {len(func.posonlyargs)} args is given')
|
_raise_static_error(node, f'Function {node.func.id} requires a function with 2 arguments but a function with {len(func.posonlyargs)} args is given')
|
||||||
|
|
||||||
raise NotImplementedError('TODO: Broken after new type system')
|
|
||||||
|
|
||||||
return Fold(
|
return Fold(
|
||||||
Fold.Direction.LEFT,
|
Fold.Direction.LEFT,
|
||||||
func,
|
func,
|
||||||
|
|||||||
@ -147,6 +147,50 @@ class SameTypeConstraint(ConstraintBase):
|
|||||||
|
|
||||||
return f'SameTypeConstraint({args}, comment={repr(self.comment)})'
|
return f'SameTypeConstraint({args}, comment={repr(self.comment)})'
|
||||||
|
|
||||||
|
class CastableConstraint(ConstraintBase):
|
||||||
|
"""
|
||||||
|
A type can be cast to another type
|
||||||
|
"""
|
||||||
|
__slots__ = ('from_type3', 'to_type3', )
|
||||||
|
|
||||||
|
from_type3: types.Type3OrPlaceholder
|
||||||
|
to_type3: types.Type3OrPlaceholder
|
||||||
|
|
||||||
|
def __init__(self, from_type3: types.Type3OrPlaceholder, to_type3: types.Type3OrPlaceholder, comment: Optional[str] = None) -> None:
|
||||||
|
super().__init__(comment=comment)
|
||||||
|
|
||||||
|
self.from_type3 = from_type3
|
||||||
|
self.to_type3 = to_type3
|
||||||
|
|
||||||
|
def check(self, smap: SubstitutionMap) -> CheckResult:
|
||||||
|
ftyp = self.from_type3
|
||||||
|
if isinstance(ftyp, types.PlaceholderForType) and ftyp in smap:
|
||||||
|
ftyp = smap[ftyp]
|
||||||
|
|
||||||
|
ttyp = self.to_type3
|
||||||
|
if isinstance(ttyp, types.PlaceholderForType) and ttyp in smap:
|
||||||
|
ttyp = smap[ttyp]
|
||||||
|
|
||||||
|
if isinstance(ftyp, types.PlaceholderForType) or isinstance(ttyp, types.PlaceholderForType):
|
||||||
|
return RequireTypeSubstitutes()
|
||||||
|
|
||||||
|
if ftyp is types.u8 and ttyp is types.u32:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return Error(f'Cannot cast {ftyp.name} to {ttyp.name}')
|
||||||
|
|
||||||
|
def human_readable(self) -> HumanReadableRet:
|
||||||
|
return (
|
||||||
|
'{to_type3}({from_type3})',
|
||||||
|
{
|
||||||
|
'to_type3': self.to_type3,
|
||||||
|
'from_type3': self.from_type3,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f'CastableConstraint({repr(self.from_type3)}, {repr(self.to_type3)}, comment={repr(self.comment)})'
|
||||||
|
|
||||||
class MustImplementTypeClassConstraint(ConstraintBase):
|
class MustImplementTypeClassConstraint(ConstraintBase):
|
||||||
"""
|
"""
|
||||||
A type must implement a given type class
|
A type must implement a given type class
|
||||||
@ -162,7 +206,7 @@ class MustImplementTypeClassConstraint(ConstraintBase):
|
|||||||
'u64': {'BitWiseOperation', 'BasicMathOperation'},
|
'u64': {'BitWiseOperation', 'BasicMathOperation'},
|
||||||
'i32': {'BasicMathOperation'},
|
'i32': {'BasicMathOperation'},
|
||||||
'i64': {'BasicMathOperation'},
|
'i64': {'BasicMathOperation'},
|
||||||
'bytes': {'Sized'},
|
'bytes': {'Foldable', 'Sized'},
|
||||||
'f32': {'BasicMathOperation', 'FloatingPoint'},
|
'f32': {'BasicMathOperation', 'FloatingPoint'},
|
||||||
'f64': {'BasicMathOperation', 'FloatingPoint'},
|
'f64': {'BasicMathOperation', 'FloatingPoint'},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from .constraints import (
|
|||||||
Context,
|
Context,
|
||||||
|
|
||||||
ConstraintBase,
|
ConstraintBase,
|
||||||
CanBeSubscriptedConstraint,
|
CastableConstraint, CanBeSubscriptedConstraint,
|
||||||
LiteralFitsConstraint, MustImplementTypeClassConstraint, SameTypeConstraint,
|
LiteralFitsConstraint, MustImplementTypeClassConstraint, SameTypeConstraint,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,6 +52,11 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
|
|||||||
yield SameTypeConstraint(inp.right.type3, inp.type3, comment='sqrt :: FloatingPoint a => a -> a')
|
yield SameTypeConstraint(inp.right.type3, inp.type3, comment='sqrt :: FloatingPoint a => a -> a')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if 'cast' == inp.operator:
|
||||||
|
yield from expression(ctx, inp.right)
|
||||||
|
yield CastableConstraint(inp.right.type3, inp.type3)
|
||||||
|
return
|
||||||
|
|
||||||
raise NotImplementedError(expression, inp, inp.operator)
|
raise NotImplementedError(expression, inp, inp.operator)
|
||||||
|
|
||||||
if isinstance(inp, ourlang.BinaryOp):
|
if isinstance(inp, ourlang.BinaryOp):
|
||||||
@ -69,10 +74,8 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
|
|||||||
yield from expression(ctx, inp.right)
|
yield from expression(ctx, inp.right)
|
||||||
|
|
||||||
yield MustImplementTypeClassConstraint('BitWiseOperation', inp.left.type3)
|
yield MustImplementTypeClassConstraint('BitWiseOperation', inp.left.type3)
|
||||||
yield SameTypeConstraint(inp.left.type3, inp.type3,
|
yield SameTypeConstraint(inp.left.type3, inp.right.type3, inp.type3,
|
||||||
comment=f'({inp.operator}) :: a -> u64 -> a')
|
comment=f'({inp.operator}) :: a -> a -> a')
|
||||||
yield SameTypeConstraint(type3types.u64, inp.right.type3,
|
|
||||||
comment=f'({inp.operator}) :: a -> u64 -> a')
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if inp.operator in ('+', '-', '*', '/', ):
|
if inp.operator in ('+', '-', '*', '/', ):
|
||||||
@ -112,6 +115,16 @@ def expression(ctx: Context, inp: ourlang.Expression) -> Generator[ConstraintBas
|
|||||||
comment=f'The type of a struct member reference is the same as the type of struct member {inp.struct_type3.name}.{inp.member}')
|
comment=f'The type of a struct member reference is the same as the type of struct member {inp.struct_type3.name}.{inp.member}')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if isinstance(inp, ourlang.Fold):
|
||||||
|
yield from expression(ctx, inp.base)
|
||||||
|
yield from expression(ctx, inp.iter)
|
||||||
|
|
||||||
|
yield SameTypeConstraint(inp.func.posonlyargs[0].type3, inp.func.returns_type3, inp.base.type3, inp.type3,
|
||||||
|
comment='foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b')
|
||||||
|
yield MustImplementTypeClassConstraint('Foldable', inp.iter.type3)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
raise NotImplementedError(expression, inp)
|
raise NotImplementedError(expression, inp)
|
||||||
|
|
||||||
def function(ctx: Context, inp: ourlang.Function) -> Generator[ConstraintBase, None, None]:
|
def function(ctx: Context, inp: ourlang.Function) -> Generator[ConstraintBase, None, None]:
|
||||||
|
|||||||
@ -111,7 +111,9 @@ def testEntry() -> {type_}:
|
|||||||
return 10 >> 3
|
return 10 >> 3
|
||||||
"""
|
"""
|
||||||
|
|
||||||
result = Suite(code_py).run_code()
|
# Check with wasmtime, as other engines don't mind if the type
|
||||||
|
# doesn't match. They'll complain when: (>>) : u32 -> u64 -> u32
|
||||||
|
result = Suite(code_py).run_code(runtime='wasmtime')
|
||||||
|
|
||||||
assert 1 == result.returned_value
|
assert 1 == result.returned_value
|
||||||
assert TYPE_MAP[type_] == type(result.returned_value)
|
assert TYPE_MAP[type_] == type(result.returned_value)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user