Author Topic: Vtables and similar ”OO”-ish concerns  (Read 8962 times)

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Vtables and similar ”OO”-ish concerns
« 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/

bas

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Re: Vtables and similar ”OO”-ish concerns
« Reply #1 on: November 13, 2018, 08:42:09 AM »
Yes, nice overview. I often use the Method Dispatch method described there..

lerno

  • Full Member
  • ***
  • Posts: 247
    • View Profile
Re: Vtables and similar ”OO”-ish concerns
« Reply #2 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:

  • 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.