carp-lang / Carp

A statically typed lisp, without a GC, for real-time applications.
Apache License 2.0
5.51k stars 174 forks source link

"receiver" templates #1387

Open scolsen opened 2 years ago

scolsen commented 2 years ago

Sometimes, I'd like to write wrapper functions for struct access in carp, either because there's some additional behavior involved or because I simply want to refer to fields by a different name:

struct Foo {
 int fooFields;
 FooData fooData[1];
};
typedef struct Foo Foo

In carp, if I want to refer to fooFields as just Foo.fields there's currently three ways to do so:

Option three is preferable because:

However, of all the options, it is the only one that alters the type signature which can matter if one is wrapping a struct that's typically passed by value. The first two options allow one to define accessors on value structs, while the last will only take a reference which might force the programmer to make reference conversions in other contexts.

I think it'd be great to have "receiver templates" that allow you to register a value struct and accessor functions on the struct with name overrides for any of the fields. Bonus points if we find a way to do this "in-place" instead of needing to define functions; e.g. a call like: (Foo.fields foo) should translate directly to the c foo.fooFields in-place.

eriksvedang commented 2 years ago

Yeah, that would be nice. Do you have any idea for what syntax to use for this?

scolsen commented 2 years ago

Maybe something like: (as <c-name> <override>) could work?

(register-type Foo [(as fooFields fields) Int])

Then this would generate the accessors etc. with the name fields instead of fooFields. This wouldn't solve the "pass by value" vs pass by reference thing though. For that we could introduce a separate form:

(register-struct Foo [fooFields])

That generates signatures that take value arguments instead of references, or we could just generate both reference style and value style getters/setters for all types, or we could just say having to ref cast every now and then isn't a huge deal so it's not something we need.