Move meta and random to "aux" modules.

Wren now has three classes of modules:

- The one magic "core" module that's built in and always needed.
- Auxiliary libraries like "meta" and "random". These do not have any
  dependencies, so can be used even when you embed Wren inside an
  application. But they're also optional and can be disabled if you
  don't need them.
- CLI modules. These ones need libuv and are tied to the CLI wrapper
  around the VM.
This commit is contained in:
Bob Nystrom
2015-10-17 22:09:48 -07:00
parent 3ca480cbf4
commit e5176607d9
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";