C2 forum

General Category => Ideas => Topic started by: lerno on November 12, 2018, 06:13:20 PM

Title: Vtables and similar ”OO”-ish concerns
Post by: lerno on November 12, 2018, 06:13:20 PM
I stumbled over this (old) article:

https://lwn.net/Articles/444910/

This is about various OO-like constructs in the Linux kernel. I think it’s important to have a discussion on how to facilitate this in C2 without sacrificing low level predictabilty over layouts, sizes etc.

Follow up here: https://lwn.net/Articles/446317/
Title: Re: Vtables and similar ”OO”-ish concerns
Post by: bas on November 13, 2018, 08:42:09 AM
Yes, nice overview. I often use the Method Dispatch method described there..
Title: Re: Vtables and similar ”OO”-ish concerns
Post by: lerno on November 13, 2018, 08:26:11 PM
How do we facilitate these constructs in C2?

I've been thinking something along the lines of:

Code: [Select]
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:

Code: [Select]
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:

Code: [Select]
struct {
  void *instance;
  struct __interface_Foo *interface;
}

This should be very similar how Go does it.

There are some outstanding questions to this:


I am not entirely sure that this should be in C2, but I think it's worth exploring quite a bit.