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
|
||||
- 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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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:
|
||||
"""
|
||||
|
||||
@ -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')
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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