MVP #1

Merged
jbwdevries merged 73 commits from idea_crc32 into master 2022-08-21 12:59:21 +00:00
6 changed files with 45 additions and 35 deletions
Showing only changes of commit 4881cb6d4b - Show all commits

View File

@ -38,6 +38,8 @@ WebAssembly.instantiateStreaming(fetch('buffer.wasm'), importObject)
let offset = stdlib_types___alloc_bytes__(size) let offset = stdlib_types___alloc_bytes__(size)
var i8arr = new Uint8Array(app.instance.exports.memory.buffer, offset + 4, size); var i8arr = new Uint8Array(app.instance.exports.memory.buffer, offset + 4, size);
log('len(i8arr) = ' + app.instance.exports.length(offset));
//Fill it //Fill it
for (var i = 0; i < size; i++) { for (var i = 0; i < size; i++) {
i8arr[i] = i + 5; i8arr[i] = i + 5;

View File

@ -1,3 +1,7 @@
@exported @exported
def index(inp: bytes, idx: i32) -> i32: def index(inp: bytes, idx: i32) -> i32:
return inp[idx] return inp[idx]
@exported
def length(inp: bytes) -> i32:
return len(inp)

View File

@ -231,7 +231,7 @@ def expression(inp: ourlang.Expression) -> Statements:
yield from expression(inp.varref) yield from expression(inp.varref)
yield from expression(inp.index) yield from expression(inp.index)
yield wasm.Statement('call', '$___access_bytes_index___') yield wasm.Statement('call', '$stdlib.types.__subscript_bytes__')
return return
if isinstance(inp, ourlang.AccessStructMember): if isinstance(inp, ourlang.AccessStructMember):
@ -381,7 +381,7 @@ def module(inp: ourlang.Module) -> wasm.Module:
stdlib_alloc.__find_free_block__, stdlib_alloc.__find_free_block__,
stdlib_alloc.__alloc__, stdlib_alloc.__alloc__,
stdlib_types.__alloc_bytes__, stdlib_types.__alloc_bytes__,
_generate____access_bytes_index___(inp), stdlib_types.__subscript_bytes__,
] + [ ] + [
function(x) function(x)
for x in inp.functions.values() for x in inp.functions.values()
@ -413,38 +413,6 @@ def _generate____new_reference___(mod: ourlang.Module) -> wasm.Function:
], ],
) )
def _generate____access_bytes_index___(mod: ourlang.Module) -> wasm.Function:
return wasm.Function(
'___access_bytes_index___',
None,
[
('byt', type_(mod.types['i32']), ),
('ofs', type_(mod.types['i32']), ),
],
[
],
type_(mod.types['i32']),
[
wasm.Statement('local.get', '$ofs'),
wasm.Statement('local.get', '$byt'),
i32.load(),
wasm.Statement('i32.lt_u'),
wasm.Statement('if', comment='$ofs < len($byt)'),
wasm.Statement('local.get', '$byt'),
wasm.Statement('i32.const', '4', comment='Leading size field'),
wasm.Statement('i32.add'),
wasm.Statement('local.get', '$ofs'),
wasm.Statement('i32.add'),
wasm.Statement('i32.load8_u', comment='Within bounds'),
wasm.Statement('return'),
wasm.Statement('end'),
wasm.Statement('i32.const', str(0), comment='Out of bounds'),
wasm.Statement('return'),
],
)
def _generate_tuple_constructor(inp: ourlang.TupleConstructor) -> Statements: def _generate_tuple_constructor(inp: ourlang.TupleConstructor) -> Statements:
yield wasm.Statement('i32.const', str(inp.tuple.alloc_size())) yield wasm.Statement('i32.const', str(inp.tuple.alloc_size()))
yield wasm.Statement('call', '$___new_reference___') yield wasm.Statement('call', '$___new_reference___')

View File

@ -113,7 +113,7 @@ def __alloc__(g: Generator, alloc_size: i32) -> i32:
g.local.get(alloc_size) g.local.get(alloc_size)
g.i32.store() g.i32.store()
# Return address of the allocated bytes # Return address of the allocated memory, skipping the allocator header
g.local.get(result) g.local.get(result)
g.i32.const(4) # Header size g.i32.const(4) # Header size
g.i32.add() g.i32.add()

View File

@ -30,3 +30,37 @@ def __alloc_bytes__(g: Generator, length: i32) -> i32:
g.local.get(result) g.local.get(result)
return i32('return') # To satisfy mypy return i32('return') # To satisfy mypy
@func_wrapper()
def __subscript_bytes__(g: Generator, adr: i32, ofs: i32) -> i32:
"""
Returns an index from a bytes value
If ofs is more than the length of the bytes, this
function returns 0, following the 'no undefined behaviour'
philosophy.
adr i32 The pointer for the allocated bytes
ofs i32 The offset within the allocated bytes
"""
g.local.get(ofs)
g.local.get(adr)
g.i32.load()
g.i32.lt_u()
with g.if_():
# The offset is less than the length
g.local.get(adr)
g.i32.const(4) # Bytes header
g.i32.add()
g.local.get(ofs)
g.i32.add()
g.i32.load8_u()
g.return_()
# The offset is outside the allocated bytes
g.i32.const(0)
g.return_()
return i32('return') # To satisfy mypy

View File

@ -30,9 +30,11 @@ class Generator_i32:
# irelop # irelop
self.eq = functools.partial(self.generator.add, 'i32.eq') self.eq = functools.partial(self.generator.add, 'i32.eq')
self.ne = functools.partial(self.generator.add, 'i32.ne') self.ne = functools.partial(self.generator.add, 'i32.ne')
self.lt_u = functools.partial(self.generator.add, 'i32.lt_u')
# 2.4.4. Memory Instructions # 2.4.4. Memory Instructions
self.load = functools.partial(self.generator.add, 'i32.load') self.load = functools.partial(self.generator.add, 'i32.load')
self.load8_u = functools.partial(self.generator.add, 'i32.load8_u')
self.store = functools.partial(self.generator.add, 'i32.store') self.store = functools.partial(self.generator.add, 'i32.store')
def const(self, value: int, comment: Optional[str] = None) -> None: def const(self, value: int, comment: Optional[str] = None) -> None: