WebAssembly / component-model

Repository for design and specification of the Component Model
Other
898 stars 75 forks source link

working with gc types #317

Open oovm opened 4 months ago

oovm commented 4 months ago

Add Canonical ABI options to support passing parameters by reference type

oovm commented 3 months ago

I realized that the discriminant actually is required for variants that have multiple arms of the same type, like:

variant either-list {
    left(list<u8>),
    right(list<u8>),
}

In this case, both left and right would have the same (ref eq) subtype.

@fitzgen It occurred to me that the method compiled to (ref eq) still exists, that is, each variant is actually a new type.

If a language went the (enum, ref null eq) route, then the binding might look like (rust pseudocode):

enum Variants {
    Null,                 // (0, 0, 0)
    Bool { value: i32 },  // (1, i32, 0)
    U64 { value: i64 },   // (2, i64) , flatten i64 to i32 + i32
    I64 { value: i64 },   // (3, i64) , flatten i64 to i32 + i32
}

impl Variants {
    fn is_bool(&self) -> bool {
        match self {
            Variants::Bool { value } => true,
            _ => false,
        }
    }
}

If a language took the (ref eq) route, then the binding might look like (C# pseudocode):

// (struct $variants)
abstract class Variants
{
    // (struct $None)
    // (ref eq $variants)
    class Null : Variants
    {
        public override bool isBool()
        {
            return false;
        }
    }
    // (struct $Bool (field value i32))
    // (ref eq $variants)
    class Bool : Variants
    {
        int value;

        public override bool isBool()
        {
            return true;
        }
    }

    // (struct $U64 (field value u64))
    // (ref eq $variants)
    class U64 : Variants
    {
        long value;

        public override bool isBool()
        {
            return false;
        }
    }
    // (struct $U64 (field value i64))
    // (ref eq $variants)
    class I64 : Variants
    {
        int value;

        public override bool isBool()
        {
            return false;
        }
    }

    // virtual table pointer
    public abstract bool isBool();

    // static method
    public static bool isBool(Variants v)
    {
        switch (v)
        {
            case Null _:
                return false;
            case Bool _:
                return true;
            case U64 _:
                return false;
            case I64 _:
                return false;
            default:
                throw new Exception("unreachable");
        }
    }
}

These languages are more likely to implement variant determination through virtual tables

I think it would also help to achieve: https://github.com/WebAssembly/component-model/issues/136

oovm commented 3 months ago

reference-type now focuses on the mapping of three heap types: string, array, and struct.

The reference types corresponding to option, result, variants have been moved to https://github.com/WebAssembly/component-model/issues/325

kevmoo commented 2 weeks ago

Super excited about the possibilities here. What's the status?

oovm commented 2 weeks ago

The unprepared part is mainly the implementation of the python validator (definitions.py), which has recently changed.

I have not been able to spend too much time on implementing this part recently due to my employer, so I am very sorry.