Category talk:Wren-dynamic: Difference between revisions

Content added Content deleted
(→‎Source code: Added some enums and removed the type aliases which are no longer needed.)
(→‎Source code: Flags enums now support an optional zero value member.)
Line 59: Line 59:
}
}


/* Flags creates a 'flags' enum with up to 32 read-only static members.
/* Flags creates a 'flags' enum with up to 32 read-only static members, plus an optional zero member.
Members are assigned in order an integer value starting from 1 and multiplying by 2 each time.
Members are assigned in order an integer value starting from 1 and multiplying by 2 each time, unless
they have a zero member, when the first member has a value of 0.
The flags enum has:
The flags enum has:
1. static property getters for each member, and
1. static property getters for each member,
2. a static 'members' property which returns a list of its members as strings.
2. a static 'hasZero' property which returns whether or not there is a zero member, and
3. a static 'members' property which returns a list of its members as strings.
*/
*/
class Flags {
class Flags {
// Creates a class for the Flags enum (with an underscore after the name) and
// Creates a class for the Flags enum (with an underscore after the name) and
// returns a reference to it.
// returns a reference to it.
static create(name, members) {
static create(name, members, hasZero) {
if (name.type != String || name == "") Fiber.abort("Name must be a non-empty string.")
if (name.type != String || name == "") Fiber.abort("Name must be a non-empty string.")
if (members.isEmpty ||members.count > 32) {
if (members.isEmpty || members.count > (hasZero ? 33 : 32)) {
Fiber.abort("A flags enum must have between 1 and 32 members.")
Fiber.abort("A flags enum must have between 1 and 32 members, plus an optional zero member.")
}
}
if (hasZero.type != Bool) Fiber.abort("'hasZero' must be true or false.")
name = name + "_"
name = name + "_"
var s = "class %(name) {\n"
var s = "class %(name) {\n"
for (i in 0...members.count) {
for (i in 0...members.count) {
var m = members[i]
var m = members[i]
s = s + " static %(m) { %(1 << i) }\n"
if (i == 0 && hasZero) {
s = s + " static %(m) { 0 }\n"
} else if (hasZero) {
s = s + " static %(m) { %(1 << (i-1)) }\n"
} else {
s = s + " static %(m) { %(1 << i) }\n"
}
}
}
var mems = members.map { |m| "\"%(m)\"" }.join(", ")
var mems = members.map { |m| "\"%(m)\"" }.join(", ")
s = s + " static hasZero { %(hasZero) }\n"
s = s + " static members { [%(mems)] }\n}\n"
s = s + " static members { [%(mems)] }\n}\n"
s = s + "return %(name)"
s = s + "return %(name)"
Line 85: Line 95:
}
}


// Returns the zero based index into the Fields property for a given Flags enum member.
// Convenience version of above method which does not have a member with a value of zero.
static indexOf(member) { (member.log / 2.log).round }
static create(name, members) { create(name, members, false) }

// Returns the zero based index into the Fields property
// for a given Flags enum member and whether or not there is a zero member.
// Returns -1 if the member doesn't exist.
static indexOf(member, hasZero, memCount) {
if (hasZero.type != Bool) Fiber.abort("'hasZero' must be true or false.")
var maxCount = hasZero ? 33 : 32
if (memCount.type != Num || !memCount.isInteger || memCount < 1 || memCount > maxCount) {
Fiber.abort("Member count must be between 1 and %(maxCount).")
}
var limit = hasZero ? 1 << (memCount-2) : 1 << (memCount-1)
if (member.type != Num || !member.isInteger || member < 0 || member > limit) {
Fiber.abort("Member must be a non-negative integer <= %(limit).")
}
if (member == 0) return hasZero ? 0 : -1
if (member & (member-1) != 0) return -1 // not a power of two
var res = (member.log / 2.log).round
return hasZero ? res + 1 : res
}

// Convenience versions of above method where the number of members is assumed to be the maximum.
static indexOf(member, hasZero) { indexOf(member, hasZero, hasZero ? 33 : 32) }
static indexOf(member) { indexOf(member, false, 32) } // assumes no zero memmber
}
}