jco icon indicating copy to clipboard operation
jco copied to clipboard

First-class importable enums and variants

Open guybedford opened this issue 2 years ago • 1 comments

After discussing this one with @dbaeumer, I think there might be merit in having some kind of first-class runtime primitives for enums and variants.

So instead of passing a string or a { tag, val } object shape, to instead have a singular importable type instance which represents the enum or variant.

This would mean, for example, with an interface like HTTP, instead of creating an outgoing request like:

import { Fields, OutgoingRequest } from 'wasi:http/[email protected]';
const req = new OutgoingRequest(
  { tag: 'get' },
  '/',
  { tag: 'HTTPS' },
  'site.com',
  new Fields([])
);

we would instead write:

import { Method, Scheme, Fields, OutgoingRequest } from 'wasi:http/[email protected]';
const req = new OutgoingRequest(
  Method.Get,
  '/',
  Scheme.Https,
  'site.com',
  new Fields([])
);

This would be a major change to the bindgen, but could be worth considering at some point.

guybedford avatar Oct 26 '23 21:10 guybedford

To further elaborate on this support, here is a more involved example of the JCO transpile generation for the following WIT:

package foo:bar;

interface bar {
  type x = y;

  variant y {
    a(string),
    b(u32)
  }

  record z {
    a: u32
  }

  enum e {
    first,
    second,
  }

  flags f {
    a,
    b
  }

  q: func(x: x, y: y, z: z, e: e, f: f);
}

world bar {
  export bar;
}

We should support:

import { bar } from 'foo:bar';
const { X, Y, E, F } = bar;
bar.q(X.a('string'), Y.a(2), { a: 4 }, E.first, F.a | F.b);

Note that only the "primitive types" variant, flags and enum get treated this way, and not records, tuple, option or result.

For option and result primitives though, we need to figure out how to get a handle to them - either as some kind of special import or dare I say global.

guybedford avatar Jan 23 '24 19:01 guybedford