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