assemblyscript icon indicating copy to clipboard operation
assemblyscript copied to clipboard

Support classes that operate like structs/value-types on the stack

Open leighmcculloch opened this issue 2 years ago • 8 comments

Something that would be useful for some applications of wasm modules is to be able to define structured types that are stored on the stack.

This is also useful in cases when it is desirable to avoid use of the heap/linear-memory, but code structure would benefit from storing multiple values inside a structure together, like a class.

This could be a decorator, similar to @unmanaged. It's worth noting that @unmanaged gets us part-way in that the memory the type uses on the heap is smaller and doesn't have the GC header.

It might look like this.

@stack
class Config {
  constructor(public field: u64) { }
}

I imagine there are a few terms that would suit, such as:

  • @stack
  • @struct
  • @valueType

Related to #2253

leighmcculloch avatar Apr 08 '22 05:04 leighmcculloch

This may be possible via @record and tuples. But it required multi-values Wasm proposal. We have discussed this more than once in the chat room and in the issues

MaxGraey avatar Apr 08 '22 06:04 MaxGraey

As it happens we're only interested in types that are represented as single u64 values -- not enough wasm producers or consumers support multivalues to bother with that.

All this feature wants is a "newtype", a way of declaring some type that is representationally equal to an existing wasm type but type-disjoint, so it can't be used as an argument in an incorrect context.

graydon avatar Apr 08 '22 15:04 graydon

So if I understand correctly, the type-disjoint bit is the difference to #2253 here, exposing the underlying value as a quasi field. The observation that this can quickly go into the direction of multi-value seems valid, though. Perhaps to recap the bits on multi-value, even though not exactly the same here but for reference: Options thought about so far are tuple types, say [i32, f64], but these would confuse TypeScript since it sees these as arrays. Another one, that is more aligned with this issue, was return types like : { a: i32, b: f64 }, which would work since there are no such object types yet (must be a class name), but has its own issues, like mandatory destructuring into multiple locals upon receiving such a return value, and of course, again the question what TS will do with it. Getting to the edge of what's possible to express with TS syntax.

dcodeIO avatar Apr 09 '22 08:04 dcodeIO

Reminds me that there is a related mechanism already doing something similar:

@final @unmanaged
class Stacky<T> {
  @inline constructor(value: T) {
    return changetype<Stacky<T>>(value);
  }
  get value(): T {
    return changetype<T>(this);
  }
}

var stacky = new Stacky<usize>(42);
stacky.value;

Currently limited to usize, though. Needs some way to annotate the this type. Perhaps a starting point?

dcodeIO avatar Apr 09 '22 08:04 dcodeIO

Passing small classes by value (<= 32 bytes) would go a long way in making AssemblyScript a viable choice over C++ or Rust when targeting wasm

jeaiii avatar Apr 19 '22 18:04 jeaiii

Proposal a style to create a stack value if could support this feature: a built function: let foo = stackNew<Foo>(...).

yjhmelody avatar Jul 07 '22 16:07 yjhmelody

Return multi-value could be optimized to pass a new multi-value pointer as arg to hold it.

yjhmelody avatar Jul 07 '22 16:07 yjhmelody

Any news about this? It would be awesome to have structs like in Rust!

gfusee avatar Oct 07 '22 16:10 gfusee