vibe coding templates; has anyone gotten it to work yet?
monkyyy
crazymonkyyy at gmail.com
Thu Sep 17 04:04:35 UTC 2026
On Saturday, 12 September 2026 at 18:30:35 UTC, monkyyy wrote:
>
mostly manual code with ai slop comments for those who feel that
huges comments improve code :)
```d
import std;
mixin template makemachine(alias opsstorage){
// `mixin template` + `mixin makemachine!(...)` below splices
these members
// directly into the host struct's own scope -- step() below
can reference
// `commands`, `programcounter`, `route` unqualified because
they're not
// inherited or imported, they're injected as if typed
directly into
// floatmachine's body. that's also why `command[100]
commands;` on
// floatmachine compiles even though it's declared *before*
the mixin that
// defines `command` -- D resolves aggregate members in two
passes, so
// forward references to a type introduced later in the same
struct body
// (mixin-injected or not) are fine. this one's easy to miss
because it
// looks like it should be an ordering bug and isn't.
alias opsfunc=udafilter!(opsstorage,"op");
alias complexopsfunc=udafilter!(opsstorage,"complexop");
enum totalcommands=opsfunc.length+complexopsfunc.length;
static assert(totalcommands<256,"TODO");
alias command=ubyte;
void step(){
// `lable:` here labels the switch statement itself, not
a loop.
// `break lable;` inside a switch already means the same
as a bare
// `break;` -- switch cases break out by default, no
fallthrough to
// guard against here. the label is inert; it'd only do
real work if
// this switch were nested inside a loop and you needed
to break the
// *outer* construct specifically.
lable:switch(commands[programcounter]){
static foreach(I,A;opsfunc){
// static foreach unrolls at compile time, so by
the time this
// switch exists as a runtime construct, `case
I:` for every I
// has already been substituted with its literal
compile-time
// value -- these are ordinary constant case
labels, D doesn't
// know or care that they came from a loop.
case I:{
ref auto popit(Q)(){ return route!Q.pop(); }
// `ref auto`, not `auto ref`. `auto ref` is
D's forwarding-ref
// idiom and it's for PARAMETERS (bind an
lvalue arg by ref, an
// rvalue arg by value) -- putting it on a
return position is a
// different, much less common spelling and I
wouldn't trust it
// to mean "infer the type but infer it as
ref" without checking.
// `ref` *before* `auto` on the return side
is what actually says
// that. got this backwards in my head before
actually compiling it.
//
// staticMap!(popit,Parameters!A) does not
call anything and does
// not decide what order those calls happen
in. it's a pure
// compile-time rewrite:
AliasSeq!(popit!P0,popit!P1,...). the
// pop() calls, and their order, only happen
once this gets spliced
// into A(...) below -- at that point it's an
ordinary call
// expression and ordinary call-expression
rules apply, nothing
// staticMap-specific.
//
// I originally said D leaves call-argument
order unspecified.
// that's stale: old dmd frontends evaluated
extern(D) args
// right-to-left (matching cdecl
register-passing order) and most
// D folklore still repeats "unspecified"
because of that history.
// the current spec locks it down --
extern(D) call arguments are
// evaluated strictly left to right -- and I
confirmed this with
// ldc2 1.36 at -O0 and -O3 (same order both
times: it's decided
// by the frontend AST, optimization can't
touch it). this is
// extern(D)-specific; it would not hold for
extern(C).
//
// also non-obvious: popit!P0 and popit!P1
get spliced below with
// no explicit (). that's legal because D
lets you omit the parens
// on a call to a niladic function used in
expression position --
// it's still an actual call, not a bare
function reference. (same
// trick as writing `a.pop.writeln` instead
of `a.pop().writeln()`
// down in the stack unittest below.)
auto r=A(staticMap!(popit,Parameters!A));
// ref genuinely survives the whole chain
above -- verified by
// giving an op `ref` params, mutating them,
and watching the
// change land back in stack.data even though
`length` had
// already moved past that slot. real
capability (in-place ops,
// no push/pop round-trip) and real hazard (a
"popped" slot is
// still live, writable storage until the
next push overwrites
// it -- and opIndex below always reads
data[length-1] no matter
// what index you ask for, so a stray read of
a stale slot is an
// easy way to get bitten by both bugs at
once).
static if(!is(typeof(r)==void))
route!(typeof(r)).push(r);
programcounter++;
}
break lable;
}
static foreach(I,A;complexopsfunc){
case I+opsfunc.length: A(this);
break lable;
}
default: assert(0);
}
}
}
template innate(T,discrim...){
// eponymous template keyed on (T, discrim...): every
distinct set of
// compile-time arguments gets its OWN static-storage
variable, generated
// for free by the type system -- no hashmap, no registry.
but that also
// means it's one variable shared by every stack!T that asks
for this same
// discrim, for the life of the program, not a per-instance
default.
// verified: mutating innate!(int,"stack") between two pop()
calls on an
// otherwise-empty stack changes what the *next* pop returns,
even though
// nothing was pushed in between (see unittest below).
T innate;
}
template udafilter(alias A,string what){//
https://github.com/dlang/phobos/issues/10546
alias udafilter=AliasSeq!();
static foreach(B;__traits(allMembers,A)){
static if(hasUDA!(__traits(getMember,A,B),what)){
udafilter=AliasSeq!(__traits(getMember,A,B),udafilter);
// prepend, not append -- the 10546 workaround for
building an AliasSeq
// inside static foreach only works in this
direction. side effect I
// hadn't clocked until wiring opcodes up for real:
opsfunc ends up in
// REVERSE declaration order. sub is declared after
add below but gets
// opcode 0; add gets opcode 1. confirmed by running
it, see unittest.
}}}
struct stack(T){
// fixed T[16] means stack!T is a plain value type: assigning
or passing one
// by value copies all 16 slots, no heap, no indirection.
that's presumably
// *why* complexops take `ref M m` -- without `ref` a
complexop would be
// handed a throwaway copy of the whole machine, stack and
all, and any
// mutation (like isrunning=false) would vanish when the
function returned.
T[16] data;
int length;
// `i` is accepted but never read -- every call to opIndex
returns the same
// top-of-stack element regardless of what index you ask for.
harmless today
// only because the sole caller (pop, below) always asks for
index 0.
//
// separately, this only compiles as a `ref`-returning
function *because*
// both branches of the `?:` are lvalues of the same type:
`data[length-1]`
// (an array element) and `innate!(T,"stack")` (a static
variable) are both
// lvalues, so the conditional expression itself is an lvalue
and can be
// returned by ref. swap the innate branch for a literal
(`:0` instead of
// `:innate!(...)`) and it stops compiling -- confirmed:
"cannot modify
// constant" -- because a literal isn't an lvalue and ref
can't bind to it.
ref T opIndex(int
i)=>length?data[length-1]:innate!(T,"stack");
ref T pop(){
// `&this[0]` takes the address of whatever opIndex's
`ref T` return
// refers to -- legal specifically because opIndex
returns by ref; you
// can't take `&` of an ordinary by-value return (D won't
let you take
// the address of an rvalue). so `o` really does point at
the live
// storage slot, not a copy.
//
// the order here matters and is easy to get backwards:
`o` is computed
// *before* `length--`. if you decremented first and then
asked for
// `&this[0]`, opIndex would read the *new*
(already-decremented)
// length and hand back a different element than the one
you meant to
// pop.
auto o=&this[0];
length--;
// clamps length at 0 rather than going negative, but
doesn't guard
// against calling pop() on an empty stack in the first
place -- when
// length is already 0, opIndex's ternary takes the false
branch and
// `o` points at innate!(T,"stack") instead of erroring.
so popping an
// empty stack repeatedly just keeps handing back
whatever's currently
// sitting in that one shared sentinel, silently,
forever. verified:
// two pops on an empty stack return the same value
twice, and
// mutating innate!(int,"stack") in between changes what
the third
// pop returns, with no push() in sight.
if(length<0){length=0;}
return *o;
}
void push(T a){
// no capacity check against the fixed T[16] -- a 17th
push indexes
// data[16], which is out of bounds. verified this
actually traps
// rather than silently corrupting: default build (bounds
checking on)
// throws core.exception.ArrayIndexError. that protection
goes away
// under `-release`/`-boundscheck=off`, at which point
it's a real
// buffer overflow instead of a caught exception.
data[length++]=a;
}
}
unittest{
stack!int a;
// T.init for float is NaN (D floats default-init to nan, not
0 -- unlike
// int, which defaults to 0). relevant here because this same
stack!T
// template gets instantiated as stack!float below, and every
unused slot
// in that T[16] prints as `nan` rather than `0` in the final
unittest's
// dump -- not garbage, just float's actual default value
showing through.
innate!(int,"stack")=1000;
a.push(1);
a.push(2);
//a.pop.writeln;
//a.writeln;
//a.pop.writeln;
//a.pop.writeln;
// none of these assert anything -- as written this unittest
can't fail no
// matter what pop()/opIndex do, it's exercising push() only.
the commented
// lines are presumably where the actual checking was meant
to go.
}
struct floatops{
// `static:` applies the static storage class to every member
declared
// until the next label or closing brace -- add/halt are
effectively free
// functions namespaced under floatops, not instance methods.
no `this`,
// so udafilter never needs a floatops *value* to exist;
`A(...)` in step()
// calls these directly off the type. that's what makes
floatops usable as
// a pure compile-time "table" rather than an object you
construct.
static:
// `@"op"` is a bare string literal used as a UDA -- there's
no dedicated
// tag type, hasUDA!(symbol,"op") just matches by value+type.
lightweight,
// but stringly-typed: `@"ops"` (typo) silently tags nothing
and there's no
// compiler error to catch it, it just quietly doesn't show
up in opsfunc.
@"op" float add(float a,float b)=>a+b;
@"op" float sub(float a,float b)=>a-b;
// templated on `M` rather than hardcoding `floatmachine` --
floatops is
// written before floatmachine even exists in this file, and
more to the
// point, it's meant to be mixed into any host machine type,
not just this
// one. that's the actual reason complexops need to be
generic here, where
// ops don't: ops only ever touch `route!T`-addressed
storage, complexops
// touch the machine itself.
@"complexop" void halt(M)(ref M m){
"halting".writeln;
m.isrunning=false;
}
}
struct floatmachine{
// the field is named the same as the enclosing struct on
purpose: inside
// floatmachine's own scope (including step(), injected by
the mixin
// below), unqualified `floatmachine` resolves to this
*field*, not the
// type. legal, but reads as a typo if you're not expecting
it.
stack!float floatmachine;
// `command` (=ubyte, 0-255) indexes into a 100-element array
with no
// compile-time relationship between the two sizes --
programcounter can
// walk past 99 with nothing stopping it until bounds
checking traps at
// runtime (or doesn't, under -release).
command[100] commands;
ubyte programcounter;
bool isrunning=true;
// `route(T:float)` reads like "only float is routed,
anything else fails
// to compile" -- and that's *mostly* true, but I said
something stronger
// than this earlier and it doesn't hold up: `T:float` in a
specialization
// is a type-convertibility match, not an exact-equality one.
verified:
// route!int, route!double, and route!ubyte all successfully
resolve to
// this exact same `stack!float` storage -- only genuinely
unrelated types
// (string, a plain struct) actually fail to match. so an op
declared with
// `int` or `double` parameters wouldn't get a compile error
here at all;
// it'd silently share float storage and every pop/push would
implicitly
// convert through float. the "missing route is a
compile-time contract"
// claim I made before is only true for types with no
implicit path to
// float, which is a narrower guarantee than it sounded like.
alias route(T:float)=floatmachine;
mixin makemachine!(floatops);
}
unittest{
//floatmachine.totalcommands.writeln;
floatmachine m;
m.floatmachine.push(10.0); // pushed first
m.floatmachine.push(3.0); // pushed second, so this pops
first
m.commands[0]=0; // sub -- opcode 0 because of the
prepend/reversal noted above
m.step;
// first pop (3.0) binds to sub's first param `a`, LTR
call-arg rule above.
// so this is sub(3.0,10.0) = -7, not sub(10.0,3.0) = 7.
m.floatmachine[0].writeln;
m.commands[1]=2; // halt = opsfunc.length(2) + 0
m.step;
// default struct printing (no custom toString) dumps every
field
// recursively, including the *full* underlying T[16] of the
nested
// stack!float -- not just the logically-valid prefix up to
`length`.
// that's why the dump below shows both the live result (-7)
and the
// stale-but-still-present 3 sitting right behind it at
data[1], plus a
// run of nan past that (float's default-init value, not
garbage) --
// this print is basically a free window into exactly the
"popped slots
// are still live storage" point flagged up in step() above.
m.writeln;
}
```
More information about the Digitalmars-d-learn
mailing list