Skip to content

Commit

Permalink
Fix reduce with native function & implement it in javascript
Browse files Browse the repository at this point in the history
  • Loading branch information
loredanacirstea committed Jun 10, 2020
1 parent a5aefe6 commit 6b93338
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 19 deletions.
34 changes: 32 additions & 2 deletions contracts/mal_like_tay.sol
Original file line number Diff line number Diff line change
Expand Up @@ -863,10 +863,40 @@ object "Taylor" {
let fptr := mload(add(ptrs, 32))
let list_ptr := mload(add(ptrs, 64))
let accum_ptr := mload(add(ptrs, 96))
result_ptr := _reduceInner(add(fptr, 4), list_ptr, accum_ptr)

let sigsig := mslice(fptr, 4)
switch sigsig
case 0x04000004 {
result_ptr := _reduceInnerNative(mslice(add(fptr, 4), 4), list_ptr, accum_ptr)
}
default {
result_ptr := _reduceInnerLambda(add(fptr, 4), list_ptr, accum_ptr)
}
}

function _reduceInnerNative(sig, list_ptr, accum_ptr) -> result_ptr {
let list_arity := listTypeSize(mslice(list_ptr, 4))
let arg_ptr := add(list_ptr, 4)
let accum_length := getTypedLength(accum_ptr)

// iterate over list & apply function on each arg
for { let i := 0 } lt(i, list_arity) { i := add(i, 1) } {
let arg_length := getTypedLength(arg_ptr)
let dataptr := allocate(add(add(4, arg_length), accum_length))
mslicestore(dataptr, sig, 4)
mmultistore(add(dataptr, 4), accum_ptr, accum_length)
mmultistore(add(add(dataptr, 4), accum_length), arg_ptr, arg_length)

let end, res := eval(dataptr, 0)

mmultistore(accum_ptr, res, getTypedLength(res))
arg_ptr := add(arg_ptr, arg_length)
}

result_ptr := accum_ptr
}

function _reduceInner(lambda_body_ptr, list_ptr, accum_ptr) -> result_ptr {
function _reduceInnerLambda(lambda_body_ptr, list_ptr, accum_ptr) -> result_ptr {
let list_arity := listTypeSize(mslice(list_ptr, 4))
let arg_ptr := add(list_ptr, 4)
let accum_length := getTypedLength(accum_ptr)
Expand Down
6 changes: 6 additions & 0 deletions src/mal_backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ modifyEnv('js-eval', (orig_func, str) => {
return interop.js_to_mal(answ);
})

/* Taylor */

mal.reps(`
(def! reduce (fn* (f xs init) (if (empty? xs) init (reduce f (rest xs) (f init (first xs)) ))))
`)

/* EVM */

mal.reps(`
Expand Down
43 changes: 26 additions & 17 deletions tests/maltay.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,6 @@ it('test bytes contig', async function () {
expect(resp).toBe('0x221111ccdd221111ccdd');
});

it('test reduce', async function () {
let resp;

await MalTay.sendAndWait('(def! myfunc2 (fn* (a b) (add a b)) )');

resp = await MalTay.call('(myfunc2 4 5)');
expect(resp).toBe(9);

resp = await MalTay.call('(myfunc2 0 5)');
expect(resp).toBe(5);

resp = await MalTay.call('(reduce myfunc2 (list 5 8 2) 0)');
expect(resp).toBe(15);
});

it('test recursive', async function () {
let resp;

Expand All @@ -170,7 +155,7 @@ it('test recursive fibonacci', async function () {
expect(resp).toBe(21);
});

it('test reduce recursive', async function () {
it.skip('test reduce recursive', async function () {
let expr, resp;

await MalTay.sendAndWait('(def! myfunc3 (fn* (a b) (add a b)) )');
Expand Down Expand Up @@ -437,6 +422,30 @@ describe.each([
}
});

it('test reduce', async function () {
let resp;

resp = await instance.call('(reduce add (list) 2)');
expect(resp).toBe(2);

resp = await instance.call('(reduce add (list 5 8 2) 0)');
expect(resp).toBe(15);

resp = await instance.call('(reduce sub (list 45 8 2) 100)');
expect(resp).toBe(45);

await instance.sendAndWait('(def! myfunc2 (fn* (a b) (add a b)) )');

resp = await instance.call('(myfunc2 4 5)');
expect(resp).toBe(9);

resp = await instance.call('(myfunc2 0 5)');
expect(resp).toBe(5);

resp = await instance.call('(reduce myfunc2 (list 5 8 2) 0)');
expect(resp).toBe(15);
});

test(`add`, async () => {
resp = await instance.call('(add 9 3)');
expect(resp).toBe(12);
Expand Down Expand Up @@ -741,7 +750,7 @@ describe.each([
it('test logs', async function() {
if (backendname === 'chain') {
const resp = await instance.getFns();
expect(resp.length).toBe(3);
expect(resp.length).toBe(4);
}
});
});
Expand Down

0 comments on commit 6b93338

Please sign in to comment.