ALPHA: breaking changes expected. What that means
NanoC

Macros with @m token templates

@m transforms NanoC tokens; it is separate from emitted $ C preprocessor definitions. Captures use $name; typed capture kinds include ident, tokens and block. Variadic captures use ...; repetition uses $(...)* and optional separators. $fresh(name) creates deterministic unique identifiers. Macro expansion does not promise to evaluate arguments once: that is the macro author's responsibility.

NanoC
@m identity($x)
  ($x)
@m getter($name,$field)
  f $name(p: *Point) i32
    < p->$field
s Point
  x: i32
@getter(get_x,x)
f main()
  p: Point = {42}
  < @identity(get_x(&p))!=42
C
typedef struct Point Point;
struct Point {
    int x;
};

int get_x(Point *p) {
    return p->x;
}

int main(void) {
    Point p = {42};
    return (get_x(&p)) !=42;
}

An executable macro uses @m name($x) = followed by an indented translate-time program. Use quote, emit, token inspection and existing transformations for library abstractions. No defer, ownership or container runtime is built in. Escape a literal dollar through $$ inside a template, so C macro definitions can be generated.