typestr — a hidden Plan 9 gem

Excerpts from 9fans describing an undocumented feature Ken added to the Plan 9 C compilers shortly before he left:

Original

/sys/src/cmd/cc/funct.c gives a further glimmer of illumination.

and

Typestr was one of the things to come out of Ken's parting flurry of activity. Here's the complete documentation:

#include <u.h>
#include <libc.h>

typestr struct _cmplx Cmplx;
struct _cmplx
{
	double r;
	double i;
};

int Zconv(va_list*, Fconv*);
#pragma varargck type "Z" Cmplx

void
main(void)
{
	Cmplx a, b;
	int ia[10];
	double d;
	fmtinstall('Z', Zconv);
	a = (Cmplx){1, 0};
	b = (Cmplx){0, 1};
	a = -((a + b) - (b - a)) + -((a - b) - (b + a));
	print("a = %Z\n", a);
	a += b;
	print("a = %Z\n", a);
	if(a == a)
	print("ok\n");
	a = (d = a);
	print("d = %g\n", d);
	print("a = %Z\n", a);
	a = (Cmplx)1.0;
	print("a = %Z\n", a);
}

/*
* print conversion
*/
int
Zconv(va_list *arg, Fconv *fp)
{
	char s[50];
	Cmplx z;
	z = va_arg(*arg, Cmplx);
	sprint(s, "(%g %g)", z.r, z.i);
	strconv(s, fp);
	return sizeof(z);
}

/*
* operators
*/
Cmplx
_cmplx_pos_(Cmplx a)
{
	Cmplx r;
	r.r = +a.r;
	r.i = +a.i;
	return r;
}

Cmplx
_cmplx_neg_(Cmplx a)
{
	Cmplx r;
	r.r = -a.r;
	r.i = -a.i;
	return r;
}

Cmplx
_cmplx_add_(Cmplx a, Cmplx b)
{
	Cmplx r;
	r.r = a.r + b.r;
	r.i = a.i + b.i;
	return r;
}

Cmplx
_cmplx_sub_(Cmplx a, Cmplx b)
{
	Cmplx r;
	r.r = a.r - b.r;
	r.i = a.i - b.i;
	return r;
}

int
_cmplx_eq_(Cmplx a, Cmplx b)
{
	Cmplx r;
	return a.r == b.r && a.i == b.i;
}

/*
* assignment-op (can be made from assig and op)
*/
Cmplx
_cmplx_asadd_(Cmplx *a, Cmplx b)
{
	*a = *a + b;
	return *a;
}

Cmplx
_cmplx_assub_(Cmplx *a, Cmplx b)
{
	*a = *a - b;
	return *a;
}

/*
* conversions
*/
int
_cmplx_i_(Cmplx a)
{
	return sqrt(a.r*a.r + a.i*a.i);
}

double
_cmplx_d_(Cmplx a)
{
	return sqrt(a.r*a.r + a.i*a.i);
}

Cmplx
_d_cmplx_(double a)
{
	Cmplx r;
	r.r = a;
	r.i = 0;
	return r;
}

From IRC:

<aap> didn't ken actually implement some sort of OOP in plan 9 C?
<mveety> because it does the weird ass smalltalk object model
<aap> qrstuv played with this i think
<mveety> aap: what do you mean?
<henesy> mveety, does obj-c typically compile down to c then asm? or just obj-c -> asm?
<aap> i forget what the feature was called...typeclass?
<ndeuteron> typestr?
<aap> maybe that
<mveety> henesy: the early compilers did that
<mveety> i've never heard of the plan9 c object oriented shit
<aap> qrstuv: you know something about this, right?
<Ori_B> mveety: the closest is struct embedding, as far as I know.
<Ori_B> aap: is that what you're talking about?
<aap> no, it was more
<Ori_B> hm. no idea then.
<aap> something like overloading operators iirc?
<aap> shit, i forget
<Ori_B> aap: oh.
<Ori_B> yeah, that's typestr.
<mveety> the anon members of structs is kinda oo
<Ori_B> it's in there.
<mveety> like the struct { QLock; int shit; }; stuff
<mveety> what typestr?
<Ori_B> mveety: something like "typestr Bigint foo;; Bigint foo_add(Bigint a, Bigint b) { ... }"
<Ori_B> and you can use the '+' operator on bigints
<Ori_B> I'm probably getting the syntax horribly wrong.
<Ori_B> but that's the general idea.
<mveety> oh fuck i need that in my life
<mveety> is this in the compiler paper?
<Ori_B> I don't think it's documented.
<Ori_B> I think it was the last thing ken did before leaving bell labs.
<Ori_B> there's just an email on 9fans, AFAIK
<mveety> http://comp.os.plan9.narkive.com/J6OjU7wO/9fans-kenc-operator-overloading