Using __traits (identifier, ...) and a template alias seems to work for me:
import std.stdio;
/// Two kinds of enums:
/// A named enum.
enum VmParams {
OBJ_MIN_CAP,
PROTO_SLOT_IDX,
FPTR_SLOT_IDX,
}
/// An anonymous one.
enum {
ATTR_CONFIGURABLE = 3,
ATTR_WRITABLE,
ATTR_ENUMERABLE,
ATTR_DELETED,
ATTR_GETSET,
ATTR_DEFAULT
}
/// A dummy Vm class for example purpose.
class Vm {
/// Stores values.
int [string] table;
/// The "classic" runtime const API.
void defRTConst (string id, int val) {
table [id] = val;
}
/// Using an alias with the identifier trait.
void rtConst (alias p) () {
table [__traits (identifier, p)] = p;
}
/// Initializes our .table member.
this () {
/// Using the allMembers traits we can process all the members
of a
/// named enum.
foreach (member; __traits (allMembers, VmParams)) {
int value = mixin ("VmParams." ~ member);
this.defRTConst (member, value);
}
/// Without duplicating the name and its value.
rtConst!ATTR_CONFIGURABLE;
rtConst!ATTR_WRITABLE;
rtConst!ATTR_ENUMERABLE;
rtConst!ATTR_DELETED;
rtConst!ATTR_GETSET;
rtConst!ATTR_DEFAULT;
/* rtConst won't work with local variables:
// auto foo = ATTR_DEFAULT;
// rtConst!foo;
The code above raises a compiler error:
Error: template instance rtConst!(foo) cannot use local
'foo' as parameter to non-global template rtConst(alias p)()
*/
}
}
void main () {
Vm vm = new Vm;
vm.table.writeln;
/// output:
/// ["OBJ_MIN_CAP":0, "ATTR_WRITABLE":4, "ATTR_ENUMERABLE":5,
"ATTR_GETSET":7, "PROTO_SLOT_IDX":1, "FPTR_SLOT_IDX":2,
"ATTR_CONFIGURABLE":3, "ATTR_DELETED":6, "ATTR_DEFAULT":8]
}
On 08/12/2014 07:36 PM, Maxime Chevalier-Boisvert wrote:
In my JavaScript VM, I have a function whose purpose is to expose D/host
constants to the JavaScript runtime code running inside the VM. This
makes for somewhat redundant code, as follows:
vm.defRTConst("OBJ_MIN_CAP"w, OBJ_MIN_CAP);
vm.defRTConst("PROTO_SLOT_IDX"w, PROTO_SLOT_IDX);
vm.defRTConst("FPTR_SLOT_IDX"w, FPTR_SLOT_IDX);
vm.defRTConst("ATTR_CONFIGURABLE"w , ATTR_CONFIGURABLE);
vm.defRTConst("ATTR_WRITABLE"w , ATTR_WRITABLE);
vm.defRTConst("ATTR_ENUMERABLE"w , ATTR_ENUMERABLE);
vm.defRTConst("ATTR_DELETED"w , ATTR_DELETED);
vm.defRTConst("ATTR_GETSET"w , ATTR_GETSET);
vm.defRTConst("ATTR_DEFAULT"w , ATTR_DEFAULT);
I'm just wondering if there's a way to template defRTConst so that the
name of an identifier I'm passing (e.g.: ATTR_DEFAULT) can be captured
by the template, making it so that I don't also need to pass the name as
a string. I expect the answer to be no, but maybe someone with more
knowledge of D template magic knows better.