How do we facilitate these constructs in C2?
I've been thinking something along the lines of:
type Foo interface {
void foo($Foo foo);
void bar($Foo foo);
}
type X struct {
i32 a;
i32 b;
}
type Y struct {
i32 a;
i32 b;
}
func X.foo(X* x) { ... }
func X.bar(X* x) { ... }
func Y.foo(Y* x) { ... }
func Y.bar(Y* x, i32 z) { ... }
func void getFoo($Foo a) // <- Use a sigil to indicate that this is NOT a struct!!!
{
a.foo();
a.bar();
}
X x;
$Foo foo = $Foo(&x);
$Foo foo2 = $Foo(&y) // ERROR!
getFoo(x); // Fine! (Implicit wrap)
getFoo(y); // BAD
Possible extension, optional methods:
type Foo2 interface {
void foo($Foo foo);
void bar($Foo foo) @(optional);
}
func void doFoo($Foo a) // <- Use a sigil to indicate that this is NOT a struct!!!
{
a.foo();
if (a.bar?) a.bar();
a.bar?(); // Call if a.bar() exists.
}
[/code]
I'm envisioning something like this:
interface $Foo defines a struct like this:
struct __interface_Foo {
uint32_t identifier;
uint32_t bitfield; // 1 has optionals, rest is available
void (*foo)(void *);
void (*bar)(void *);
uint8_t[] optionalBitmap;
}
The last part is obviously if we have optionals. The point here would be to avoid having to retrieve the function pointer to see if it's implemented or not, instead the corresponding bit is checked. This avoids a load från L1/L2.
A $Foo "object" looks like:
struct {
void *instance;
struct __interface_Foo *interface;
}
This should be very similar how Go does it.
There are some outstanding questions to this:
- How is memory handled? If I want to free a list of $Foos, can I do so, or do I need to free the underlying pointer?
- Can I directly create a $Foo of X, or do I need to wrap the X (like in the example)
- Is it fine to just structurally adopt $Foo on the fly, or do we want a much more rigid system?
- Can the syntax be simplified?
- What pieces does this hook up to?
- Can we cut away more "magic"
I am not entirely sure that this should be in C2, but I think it's worth exploring quite a bit.