Removed the len special casing
This commit is contained in:
parent
292c9548fb
commit
d3e38b96b2
3
TODO.md
3
TODO.md
@ -23,9 +23,6 @@
|
|||||||
- At first glance, looks like failure in the typing system
|
- At first glance, looks like failure in the typing system
|
||||||
- Related to the FIXME in phasm_type3?
|
- Related to the FIXME in phasm_type3?
|
||||||
- Related: Parser is putting stuff in ModuleDataBlock
|
- Related: Parser is putting stuff in ModuleDataBlock
|
||||||
- WEBASSEMBLY_BUILTIN_BYTES_OPS is special cased
|
|
||||||
- Should be part of a prelude (?)
|
|
||||||
- In Haskell this is not a type class
|
|
||||||
- Casting is not implemented except u32 which is special cased
|
- Casting is not implemented except u32 which is special cased
|
||||||
- Make prelude more an actual thing
|
- Make prelude more an actual thing
|
||||||
- Merge in type3types.LOOKUP_TABLE
|
- Merge in type3types.LOOKUP_TABLE
|
||||||
|
|||||||
@ -76,10 +76,6 @@ def expression(inp: ourlang.Expression) -> str:
|
|||||||
return str(inp.variable.name)
|
return str(inp.variable.name)
|
||||||
|
|
||||||
if isinstance(inp, ourlang.UnaryOp):
|
if isinstance(inp, ourlang.UnaryOp):
|
||||||
if (
|
|
||||||
inp.operator in ourlang.WEBASSEMBLY_BUILTIN_BYTES_OPS):
|
|
||||||
return f'{inp.operator}({expression(inp.right)})'
|
|
||||||
|
|
||||||
if inp.operator == 'cast':
|
if inp.operator == 'cast':
|
||||||
mtyp = type3(inp.type3)
|
mtyp = type3(inp.type3)
|
||||||
if mtyp is None:
|
if mtyp is None:
|
||||||
|
|||||||
@ -233,6 +233,9 @@ INSTANCES = {
|
|||||||
'a=f32': stdlib_types.f32_natnum_arithmic_shift_right,
|
'a=f32': stdlib_types.f32_natnum_arithmic_shift_right,
|
||||||
'a=f64': stdlib_types.f64_natnum_arithmic_shift_right,
|
'a=f64': stdlib_types.f64_natnum_arithmic_shift_right,
|
||||||
},
|
},
|
||||||
|
prelude.Sized_.methods['len']: {
|
||||||
|
'a=bytes': stdlib_types.bytes_sized_len,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def phasm_compile(inp: ourlang.Module) -> wasm.Module:
|
def phasm_compile(inp: ourlang.Module) -> wasm.Module:
|
||||||
@ -458,12 +461,6 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
|
|||||||
|
|
||||||
assert isinstance(inp.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR
|
assert isinstance(inp.type3, type3types.Type3), type3placeholders.TYPE3_ASSERTION_ERROR
|
||||||
|
|
||||||
if inp.type3 == prelude.u32:
|
|
||||||
if inp.operator == 'len':
|
|
||||||
if inp.right.type3 == prelude.bytes_:
|
|
||||||
wgn.i32.load()
|
|
||||||
return
|
|
||||||
|
|
||||||
if inp.operator == 'cast':
|
if inp.operator == 'cast':
|
||||||
if inp.type3 == prelude.u32 and inp.right.type3 == prelude.u8:
|
if inp.type3 == prelude.u32 and inp.right.type3 == prelude.u8:
|
||||||
# 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
|
||||||
|
|||||||
@ -4,14 +4,11 @@ Contains the syntax tree for ourlang
|
|||||||
import enum
|
import enum
|
||||||
from typing import Dict, Iterable, List, Optional, Union
|
from typing import Dict, Iterable, List, Optional, Union
|
||||||
|
|
||||||
from typing_extensions import Final
|
|
||||||
|
|
||||||
from . import prelude
|
from . import prelude
|
||||||
from .type3.placeholders import PlaceholderForType, Type3OrPlaceholder
|
from .type3.placeholders import PlaceholderForType, Type3OrPlaceholder
|
||||||
from .type3.typeclasses import Type3ClassMethod
|
from .type3.typeclasses import Type3ClassMethod
|
||||||
from .type3.types import Type3
|
from .type3.types import Type3
|
||||||
|
|
||||||
WEBASSEMBLY_BUILTIN_BYTES_OPS: Final = ('len', )
|
|
||||||
|
|
||||||
class Expression:
|
class Expression:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -490,14 +490,6 @@ class OurVisitor:
|
|||||||
)
|
)
|
||||||
unary_op.type3 = prelude.u32
|
unary_op.type3 = prelude.u32
|
||||||
return unary_op
|
return unary_op
|
||||||
elif node.func.id == 'len':
|
|
||||||
if 1 != len(node.args):
|
|
||||||
_raise_static_error(node, f'Function {node.func.id} requires 1 arguments but {len(node.args)} are given')
|
|
||||||
|
|
||||||
return UnaryOp(
|
|
||||||
'len',
|
|
||||||
self.visit_Module_FunctionDef_expr(module, function, our_locals, node.args[0]),
|
|
||||||
)
|
|
||||||
elif node.func.id == 'foldl':
|
elif node.func.id == 'foldl':
|
||||||
if 3 != len(node.args):
|
if 3 != len(node.args):
|
||||||
_raise_static_error(node, f'Function {node.func.id} requires 3 arguments but {len(node.args)} are given')
|
_raise_static_error(node, f'Function {node.func.id} requires 3 arguments but {len(node.args)} are given')
|
||||||
|
|||||||
@ -241,6 +241,12 @@ Floating = Type3Class('Floating', [a], methods={
|
|||||||
instance_type_class(Floating, f32)
|
instance_type_class(Floating, f32)
|
||||||
instance_type_class(Floating, f64)
|
instance_type_class(Floating, f64)
|
||||||
|
|
||||||
|
Sized_ = Type3Class('Sized', [a], methods={
|
||||||
|
'len': [a, u32],
|
||||||
|
}, operators={}) # FIXME: Once we get type class families, add [] here
|
||||||
|
|
||||||
|
instance_type_class(Sized_, bytes_)
|
||||||
|
|
||||||
PRELUDE_TYPE_CLASSES = {
|
PRELUDE_TYPE_CLASSES = {
|
||||||
'Eq': Eq,
|
'Eq': Eq,
|
||||||
'Ord': Ord,
|
'Ord': Ord,
|
||||||
@ -271,4 +277,5 @@ PRELUDE_METHODS = {
|
|||||||
**Integral.methods,
|
**Integral.methods,
|
||||||
**IntNum.methods,
|
**IntNum.methods,
|
||||||
**NatNum.methods,
|
**NatNum.methods,
|
||||||
|
**Sized_.methods,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -858,3 +858,10 @@ def f32_intnum_neg(g: Generator) -> None:
|
|||||||
|
|
||||||
def f64_intnum_neg(g: Generator) -> None:
|
def f64_intnum_neg(g: Generator) -> None:
|
||||||
g.f64.neg()
|
g.f64.neg()
|
||||||
|
|
||||||
|
## ###
|
||||||
|
## Class Sized
|
||||||
|
|
||||||
|
def bytes_sized_len(g: Generator) -> None:
|
||||||
|
# The length is stored in the first 4 bytes
|
||||||
|
g.i32.load()
|
||||||
|
|||||||
@ -245,7 +245,7 @@ class MustImplementTypeClassConstraint(ConstraintBase):
|
|||||||
type3: placeholders.Type3OrPlaceholder
|
type3: placeholders.Type3OrPlaceholder
|
||||||
|
|
||||||
DATA = {
|
DATA = {
|
||||||
'bytes': {'Foldable', 'Sized'},
|
'bytes': {'Foldable'},
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, type_class3: Union[str, typeclasses.Type3Class], type3: placeholders.Type3OrPlaceholder, comment: Optional[str] = None) -> None:
|
def __init__(self, type_class3: Union[str, typeclasses.Type3Class], type3: placeholders.Type3OrPlaceholder, comment: Optional[str] = None) -> None:
|
||||||
|
|||||||
@ -48,12 +48,6 @@ def expression(ctx: Context, inp: ourlang.Expression) -> ConstraintGenerator:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(inp, ourlang.UnaryOp):
|
if isinstance(inp, ourlang.UnaryOp):
|
||||||
if 'len' == inp.operator:
|
|
||||||
yield from expression(ctx, inp.right)
|
|
||||||
yield MustImplementTypeClassConstraint('Sized', inp.right.type3)
|
|
||||||
yield SameTypeConstraint(prelude.u32, inp.type3, comment='len :: Sized a => a -> u32')
|
|
||||||
return
|
|
||||||
|
|
||||||
if 'cast' == inp.operator:
|
if 'cast' == inp.operator:
|
||||||
yield from expression(ctx, inp.right)
|
yield from expression(ctx, inp.right)
|
||||||
yield CastableConstraint(inp.right.type3, inp.type3)
|
yield CastableConstraint(inp.right.type3, inp.type3)
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
import pytest
|
|
||||||
|
|
||||||
from ..helpers import Suite
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration_test
|
|
||||||
def test_bytes_length():
|
|
||||||
code_py = """
|
|
||||||
@exported
|
|
||||||
def testEntry(f: bytes) -> u32:
|
|
||||||
return len(f)
|
|
||||||
"""
|
|
||||||
|
|
||||||
result = Suite(code_py).run_code(b'This yet is another test')
|
|
||||||
|
|
||||||
assert 24 == result.returned_value
|
|
||||||
20
tests/integration/test_lang/test_sized.py
Normal file
20
tests/integration/test_lang/test_sized.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ..helpers import Suite
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.integration_test
|
||||||
|
@pytest.mark.parametrize('type_, in_put, exp_result', [
|
||||||
|
('bytes', b'Hello, world!', 13),
|
||||||
|
# ('u8[4]', (1, 2, 3, 4), 4), # FIXME: Implement this
|
||||||
|
])
|
||||||
|
def test_len(type_, in_put, exp_result):
|
||||||
|
code_py = f"""
|
||||||
|
@exported
|
||||||
|
def testEntry(f: {type_}) -> u32:
|
||||||
|
return len(f)
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = Suite(code_py).run_code(in_put)
|
||||||
|
|
||||||
|
assert exp_result == result.returned_value
|
||||||
Loading…
x
Reference in New Issue
Block a user