refactor: move meta and random modules from vm and cli into new aux library category

Restructure module hierarchy by extracting meta and random from the core VM and CLI-specific modules into a new "aux" (auxiliary) directory. This introduces WREN_AUX_META and WREN_AUX_RANDOM configuration flags, updates include paths and build system to compile aux sources separately, removes random module registration from CLI modules.c, and adjusts the VM's module loading to implicitly import core into all modules regardless of name.
This commit is contained in:
Bob Nystrom
2015-10-18 05:09:48 +00:00
parent 455c1dc7c1
commit 88a4e0a4e9
15 changed files with 264 additions and 167 deletions
-94
View File
@@ -1,94 +0,0 @@
#include "vm.h"
#include "wren.h"
// Implements the well equidistributed long-period linear PRNG (WELL512a).
//
// https://en.wikipedia.org/wiki/Well_equidistributed_long-period_linear
//
// Code from: http://www.lomont.org/Math/Papers/2008/Lomont_PRNG_2008.pdf
typedef struct
{
uint32_t state[16];
uint32_t index;
} Well512;
static uint32_t advanceState(Well512* well)
{
uint32_t a, b, c, d;
a = well->state[well->index];
c = well->state[(well->index + 13) & 15];
b = a ^ c ^ (a << 16) ^ (c << 15);
c = well->state[(well->index + 9) & 15];
c ^= (c >> 11);
a = well->state[well->index] = b ^ c;
d = a ^ ((a << 5) & 0xda442d24U);
well->index = (well->index + 15) & 15;
a = well->state[well->index];
well->state[well->index] = a ^ b ^ d ^ (a << 2) ^ (b << 18) ^ (c << 28);
return well->state[well->index];
}
void randomAllocate(WrenVM* vm)
{
Well512* well = (Well512*)wrenAllocateForeign(vm, sizeof(Well512));
well->index = 0;
}
void randomSeed0(WrenVM* vm)
{
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
srand((uint32_t)time(NULL));
for (int i = 0; i < 16; i++)
{
well->state[i] = rand();
}
}
void randomSeed1(WrenVM* vm)
{
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
srand((uint32_t)wrenGetArgumentDouble(vm, 1));
for (int i = 0; i < 16; i++)
{
well->state[i] = rand();
}
}
void randomSeed16(WrenVM* vm)
{
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
for (int i = 0; i < 16; i++)
{
well->state[i] = (uint32_t)wrenGetArgumentDouble(vm, i + 1);
}
}
void randomFloat(WrenVM* vm)
{
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
// A double has 53 bits of precision in its mantissa, and we'd like to take
// full advantage of that, so we need 53 bits of random source data.
// First, start with 32 random bits, shifted to the left 21 bits.
double result = (double)advanceState(well) * (1 << 21);
// Then add another 21 random bits.
result += (double)(advanceState(well) & ((1 << 21) - 1));
// Now we have a number from 0 - (2^53). Divide be the range to get a double
// from 0 to 1.0 (half-inclusive).
result /= 9007199254740992.0;
wrenReturnDouble(vm, result);
}
void randomInt0(WrenVM* vm)
{
Well512* well = (Well512*)wrenGetArgumentForeign(vm, 0);
wrenReturnDouble(vm, (double)advanceState(well));
}
-49
View File
@@ -1,49 +0,0 @@
foreign class Random {
construct new() {
seed_()
}
construct new(seed) {
if (seed is Num) {
seed_(seed)
} else if (seed is Sequence) {
if (seed.isEmpty) Fiber.abort("Sequence cannot be empty.")
// TODO: Empty sequence.
var seeds = []
for (element in seed) {
if (!(element is Num)) Fiber.abort("Sequence elements must all be numbers.")
seeds.add(element)
if (seeds.count == 16) break
}
// Cycle the values to fill in any missing slots.
var i = 0
while (seeds.count < 16) {
seeds.add(seeds[i])
i = i + 1
}
seed_(
seeds[0], seeds[1], seeds[2], seeds[3],
seeds[4], seeds[5], seeds[6], seeds[7],
seeds[8], seeds[9], seeds[10], seeds[11],
seeds[12], seeds[13], seeds[14], seeds[15])
} else {
Fiber.abort("Seed must be a number or a sequence of numbers.")
}
}
foreign seed_()
foreign seed_(seed)
foreign seed_(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16)
foreign float()
float(max) { float() * max }
float(min, max) { float() * (max - min) + min }
foreign int()
int(max) { (float() * max).floor }
int(min, max) { (float() * (max - min)).floor + min }
}
-51
View File
@@ -1,51 +0,0 @@
// Generated automatically from src/module/random.wren. Do not edit.
static const char* randomModuleSource =
"foreign class Random {\n"
" construct new() {\n"
" seed_()\n"
" }\n"
"\n"
" construct new(seed) {\n"
" if (seed is Num) {\n"
" seed_(seed)\n"
" } else if (seed is Sequence) {\n"
" if (seed.isEmpty) Fiber.abort(\"Sequence cannot be empty.\")\n"
"\n"
" // TODO: Empty sequence.\n"
" var seeds = []\n"
" for (element in seed) {\n"
" if (!(element is Num)) Fiber.abort(\"Sequence elements must all be numbers.\")\n"
"\n"
" seeds.add(element)\n"
" if (seeds.count == 16) break\n"
" }\n"
"\n"
" // Cycle the values to fill in any missing slots.\n"
" var i = 0\n"
" while (seeds.count < 16) {\n"
" seeds.add(seeds[i])\n"
" i = i + 1\n"
" }\n"
"\n"
" seed_(\n"
" seeds[0], seeds[1], seeds[2], seeds[3],\n"
" seeds[4], seeds[5], seeds[6], seeds[7],\n"
" seeds[8], seeds[9], seeds[10], seeds[11],\n"
" seeds[12], seeds[13], seeds[14], seeds[15])\n"
" } else {\n"
" Fiber.abort(\"Seed must be a number or a sequence of numbers.\")\n"
" }\n"
" }\n"
"\n"
" foreign seed_()\n"
" foreign seed_(seed)\n"
" foreign seed_(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16)\n"
"\n"
" foreign float()\n"
" float(max) { float() * max }\n"
" float(min, max) { float() * (max - min) + min }\n"
"\n"
" foreign int()\n"
" int(max) { (float() * max).floor }\n"
" int(min, max) { (float() * (max - min)).floor + min }\n"
"}\n";