From 27fa1cc76dedbb96ba397b153ce3bce693a2df59 Mon Sep 17 00:00:00 2001 From: "Johan B.W. de Vries" Date: Sat, 2 Jul 2022 21:48:39 +0200 Subject: [PATCH] bytes[idx] for any expression idx More steps towards buffer example --- examples/buffer.html | 45 +++++++++++++++++++------------------- examples/buffer.py | 4 ++++ py2wasm/compiler.py | 5 +---- py2wasm/ourlang.py | 51 +++++++++++++++++++++++--------------------- 4 files changed, 54 insertions(+), 51 deletions(-) diff --git a/examples/buffer.html b/examples/buffer.html index c5e13ba..d21c84d 100644 --- a/examples/buffer.html +++ b/examples/buffer.html @@ -1,3 +1,4 @@ + Examples - Buffer @@ -15,38 +16,36 @@ let importObject = {}; let results = document.getElementById('results'); +function log(txt) +{ + let span = document.createElement('span'); + span.innerHTML = txt; + results.appendChild(span); + let br = document.createElement('br'); + results.appendChild(br); +} + WebAssembly.instantiateStreaming(fetch('buffer.wasm'), importObject) .then(app => { // Allocate room within the memory of the WebAssembly class let size = 8; - let offset = app.instance.exports.___new_reference___(4 * size); - var i32 = new Uint32Array(app.instance.exports.memory.buffer, offset, size); + + // TODO: Use bytes constructor + let offset = app.instance.exports.___new_reference___(size); + new Uint32Array(app.instance.exports.memory.buffer, offset, 1)[0] = size; + var i8arr = new Uint8Array(app.instance.exports.memory.buffer, offset + 4, size); + //Fill it let sum = 0; for (var i = 0; i < size; i++) { - i32[i] = i; - sum += i; + i8arr[i] = i + 5; + sum += i8arr[i]; + let from_wasm = app.instance.exports.index(offset, i); + log('i8arr[' + i + '] = ' + from_wasm); } - { - let span = document.createElement('span'); - span.innerHTML = 'expected result = ' + sum; - results.appendChild(span); - let br = document.createElement('br'); - results.appendChild(br); - } - - { - let span = document.createElement('span'); - span.innerHTML = 'actual result = ' + app.instance.exports.sum(offset); - results.appendChild(span); - let br = document.createElement('br'); - results.appendChild(br); - } - - for (var i = 0; i < size; i++) { - console.log(i32[i]); - } + log('expected result = ' + sum); + log('actual result = ' + app.instance.exports.sum(offset)); }); diff --git a/examples/buffer.py b/examples/buffer.py index 6700f6c..74eb023 100644 --- a/examples/buffer.py +++ b/examples/buffer.py @@ -1,3 +1,7 @@ @exported def sum() -> i32: # TODO: Should be [i32] -> i32 return 0 # TODO: Implement me + +@exported +def index(inp: bytes, idx: i32) -> i32: + return inp[idx] diff --git a/py2wasm/compiler.py b/py2wasm/compiler.py index 4b71bae..95f66d7 100644 --- a/py2wasm/compiler.py +++ b/py2wasm/compiler.py @@ -140,11 +140,8 @@ def expression(inp: ourlang.Expression) -> Statements: if not isinstance(inp.type, ourlang.OurTypeUInt8): raise NotImplementedError(inp, inp.type) - if not isinstance(inp.offset, int): - raise NotImplementedError(inp, inp.offset) - yield from expression(inp.varref) - yield wasm.Statement('i32.const', str(inp.offset)) + yield from expression(inp.index) yield wasm.Statement('call', '$___access_bytes_index___') return diff --git a/py2wasm/ourlang.py b/py2wasm/ourlang.py index 49398f7..1ff4ae2 100644 --- a/py2wasm/ourlang.py +++ b/py2wasm/ourlang.py @@ -331,19 +331,19 @@ class AccessBytesIndex(Expression): """ Access a bytes index for reading """ - __slots__ = ('varref', 'offset', ) + __slots__ = ('varref', 'index', ) varref: VariableReference - offset: int + index: Expression - def __init__(self, type_: OurType, varref: VariableReference, offset: int) -> None: + def __init__(self, type_: OurType, varref: VariableReference, index: Expression) -> None: super().__init__(type_) self.varref = varref - self.offset = offset + self.index = index def render(self) -> str: - return f'{self.varref.render()}[{self.offset}]' + return f'{self.varref.render()}[{self.index.render()}]' class AccessStructMember(Expression): """ @@ -1020,13 +1020,6 @@ class OurVisitor: if not isinstance(node.slice, ast.Index): _raise_static_error(node, 'Must subscript using an index') - if not isinstance(node.slice.value, ast.Constant): - _raise_static_error(node, 'Must subscript using a constant index') # FIXME: Implement variable indexes - - idx = node.slice.value.value - if not isinstance(idx, int): - _raise_static_error(node, 'Must subscript using a constant integer index') - if not isinstance(node.ctx, ast.Load): _raise_static_error(node, 'Must be load context') @@ -1034,27 +1027,37 @@ class OurVisitor: _raise_static_error(node, f'Undefined variable {node.value.id}') node_typ = our_locals[node.value.id] + + slice_expr = self.visit_Module_FunctionDef_expr( + module, function, our_locals, module.types['i32'], node.slice.value, + ) + if isinstance(node_typ, OurTypeBytes): return AccessBytesIndex( module.types['u8'], VariableReference(node_typ, node.value.id), - idx, + slice_expr, ) - if not isinstance(node_typ, OurTypeTuple): - _raise_static_error(node, f'Cannot take index of non-tuple {node.value.id}') + if isinstance(node_typ, OurTypeTuple): + if not isinstance(slice_expr, ConstantInt32): + _raise_static_error(node, 'Must subscript using a constant index') - if len(node_typ.members) <= idx: - _raise_static_error(node, f'Index {idx} out of bounds for tuple {node.value.id}') + idx = slice_expr.value - member = node_typ.members[idx] - if exp_type != member.type: - _raise_static_error(node, f'Expected {exp_type.render()}, {node.value.id}[{idx}] is actually {member.type.render()}') + if len(node_typ.members) <= idx: + _raise_static_error(node, f'Index {idx} out of bounds for tuple {node.value.id}') - return AccessTupleMember( - VariableReference(node_typ, node.value.id), - member, - ) + member = node_typ.members[idx] + if exp_type != member.type: + _raise_static_error(node, f'Expected {exp_type.render()}, {node.value.id}[{idx}] is actually {member.type.render()}') + + return AccessTupleMember( + VariableReference(node_typ, node.value.id), + member, + ) + + _raise_static_error(node, f'Cannot take index of {node_typ.render()} {node.value.id}') def visit_Module_FunctionDef_Constant(self, module: Module, function: Function, exp_type: OurType, node: ast.Constant) -> Expression: del module