bytes[idx] for any expression idx

More steps towards buffer example
This commit is contained in:
Johan B.W. de Vries 2022-07-02 21:48:39 +02:00
parent 374231d206
commit 27fa1cc76d
4 changed files with 54 additions and 51 deletions

View File

@ -1,3 +1,4 @@
<!DOCTYPE html>
<html>
<head>
<title>Examples - Buffer</title>
@ -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));
});
</script>

View File

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

View File

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

View File

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