0

here is my js code that I would like to convert to AssemblyScript

function make_func_array(size){
  function f1(w){
    w.val+=1
  }
  function f2(w){
    w.val+=10
  }
  var ans=[]
  for (let i=0;i<size;i++){
    ans.push(f1)
    ans.push(f2)    
  }
  return ans
}

function run_ar(ar,val){
  var w={val}
  for(let f of ar){
    f(w)
  }
  return w.val
}

var ar=make_func_array(10)
var ans=run_ar(ar,3)
console.log('ans',ans)

it uses an array of functions to execute some rudimentary calculation

my question is: does AssemblyScript supports array of functions? how would it write it in AssemblyScript?

yigal
  • 3,923
  • 8
  • 37
  • 59

2 Answers2

2

yes, that's possible. Just need fill types

declare function log(i: i32): void;

class W {
  val: i32;
}

function makeFnArr(size: i32): Array<(w: W) => void> {
  const f1 = (w: W): void => {
    w.val += 1;
  }

  const f2 = (w: W): void => {
    w.val += 10;
  }

  let ans: Array<(w: W) => void> = [];
  for (let i = 0; i < size; i++) {
    ans.push(f1);
    ans.push(f2);   
  }

  return ans;
}

function runArr(arr: Array<(w: W) => void>, val: i32): i32 {
  let w: W = { val };
  for (let i = 0, len = arr.length; i < len; i++) {
    let fn = arr[i];
    fn(w);
  }
  return w.val;
}

var arr = makeFnArr(10);
var ans = runArr(arr, 3);

log(ans);

AssemblySctipt playground

MaxGraey
  • 351
  • 2
  • 6
  • Thank you so much for such a complete answer!. I add that in my benchmark program at https://github.com/yigalirani/speed_test/blob/master/js/assembly/index.ts the goal was to compare the performance of JS and AS in the above calculation (which is modeled after the tokenizer module in my XML Marker program). The result might surprise you: performance of JS and AS are about the same and are about a quarter of the performance of CPP – yigal Jan 19 '21 at 06:24
  • @yigal I'm not surprised. Wasm and JS is sharing a lot of codegen parts and this is not best example mobilizing the full potential of WebAssembly. Regarding comparision with C/C++. Most of WebAssembly runtimes still miss some important loop optimizations like loop unrolling for example: https://bugs.chromium.org/p/v8/issues/detail?id=11298. So I guess gap between JS and native will be decrease even more in future – MaxGraey Jan 20 '21 at 08:35
  • Also compariosion is not precise. C++ version uses preallocated array: https://github.com/yigalirani/speed_test/blob/master/cspeed/cspeed.cpp#L15 while AS version use dynamic array. For proper comparision C++ should use std::vector without reserve constructor and two push_back calls as well I guess) Another one diff: C++ doesn't use boxed class while AS/JS version wrap "val" into a class object – MaxGraey Jan 20 '21 at 08:40
1

You can convert a function to a usize pointer by writing e.g. changetype<usize>(() => true); (where () => true here is a simple function that returns true). Then you can make an array of usize.

To call the function. Use changetype to convert it back to a function again: changetype<() => boolean>(funcPointer)().

Here's an example for use in a synthesizer made with AssemblyScript: https://gist.github.com/petersalomonsen/5b795090ead4f192e7f5ee5dcdd17392#file-wasmsong2-mix-ts-L337

Peter Salomonsen
  • 5,525
  • 2
  • 24
  • 38