Removed the len special casing

This commit is contained in:
Johan B.W. de Vries 2025-04-27 12:37:17 +02:00
parent 292c9548fb
commit d3e38b96b2
11 changed files with 38 additions and 47 deletions

View File

@ -23,9 +23,6 @@
- At first glance, looks like failure in the typing system
- Related to the FIXME in phasm_type3?
- 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
- Make prelude more an actual thing
- Merge in type3types.LOOKUP_TABLE

View File

@ -76,10 +76,6 @@ def expression(inp: ourlang.Expression) -> str:
return str(inp.variable.name)
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':
mtyp = type3(inp.type3)
if mtyp is None:

View File

@ -233,6 +233,9 @@ INSTANCES = {
'a=f32': stdlib_types.f32_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:
@ -458,12 +461,6 @@ def expression(wgn: WasmGenerator, inp: ourlang.Expression) -> None:
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.type3 == prelude.u32 and inp.right.type3 == prelude.u8:
# Nothing to do, you can use an u8 value as a u32 no problem

View File

@ -4,14 +4,11 @@ Contains the syntax tree for ourlang
import enum
from typing import Dict, Iterable, List, Optional, Union
from typing_extensions import Final
from . import prelude
from .type3.placeholders import PlaceholderForType, Type3OrPlaceholder
from .type3.typeclasses import Type3ClassMethod
from .type3.types import Type3
WEBASSEMBLY_BUILTIN_BYTES_OPS: Final = ('len', )
class Expression:
"""

View File

@ -490,14 +490,6 @@ class OurVisitor:
)
unary_op.type3 = prelude.u32
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':
if 3 != len(node.args):
_raise_static_error(node, f'Function {node.func.id} requires 3 arguments but {len(node.args)} are given')

View File

@ -241,6 +241,12 @@ Floating = Type3Class('Floating', [a], methods={
instance_type_class(Floating, f32)
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 = {
'Eq': Eq,
'Ord': Ord,
@ -271,4 +277,5 @@ PRELUDE_METHODS = {
**Integral.methods,
**IntNum.methods,
**NatNum.methods,
**Sized_.methods,
}

View File

@ -858,3 +858,10 @@ def f32_intnum_neg(g: Generator) -> None:
def f64_intnum_neg(g: Generator) -> None:
g.f64.neg()
## ###
## Class Sized
def bytes_sized_len(g: Generator) -> None:
# The length is stored in the first 4 bytes
g.i32.load()

View File

@ -245,7 +245,7 @@ class MustImplementTypeClassConstraint(ConstraintBase):
type3: placeholders.Type3OrPlaceholder
DATA = {
'bytes': {'Foldable', 'Sized'},
'bytes': {'Foldable'},
}
def __init__(self, type_class3: Union[str, typeclasses.Type3Class], type3: placeholders.Type3OrPlaceholder, comment: Optional[str] = None) -> None:

View File

@ -48,12 +48,6 @@ def expression(ctx: Context, inp: ourlang.Expression) -> ConstraintGenerator:
return
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:
yield from expression(ctx, inp.right)
yield CastableConstraint(inp.right.type3, inp.type3)

View File

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

View 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