2015-02-25 16:07:54 +01:00
|
|
|
#include <ctype.h>
|
2015-03-03 09:06:34 +01:00
|
|
|
#include <errno.h>
|
2013-11-10 06:01:18 +01:00
|
|
|
#include <math.h>
|
2013-10-27 19:28:15 +01:00
|
|
|
#include <string.h>
|
2015-09-15 16:46:09 +02:00
|
|
|
#include <time.h>
|
2013-10-27 19:28:15 +01:00
|
|
|
|
2015-02-25 06:09:04 +01:00
|
|
|
#include "wren_common.h"
|
2013-11-28 17:00:55 +01:00
|
|
|
#include "wren_core.h"
|
2015-04-04 06:22:58 +02:00
|
|
|
#include "wren_primitive.h"
|
2013-11-28 17:11:50 +01:00
|
|
|
#include "wren_value.h"
|
2013-10-27 19:28:15 +01:00
|
|
|
|
2015-09-13 19:03:02 +02:00
|
|
|
#include "wren_core.wren.inc"
|
2013-12-22 20:50:00 +01:00
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(bool_not)
|
2014-01-02 16:32:00 +01:00
|
|
|
{
|
|
|
|
|
RETURN_BOOL(!AS_BOOL(args[0]));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(bool_toString)
|
2014-01-02 16:32:00 +01:00
|
|
|
{
|
|
|
|
|
if (AS_BOOL(args[0]))
|
|
|
|
|
{
|
2015-03-16 06:32:20 +01:00
|
|
|
RETURN_VAL(CONST_STRING(vm, "true"));
|
2014-01-02 16:32:00 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2015-03-16 06:32:20 +01:00
|
|
|
RETURN_VAL(CONST_STRING(vm, "false"));
|
2014-01-02 16:32:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(class_name)
|
2014-01-29 00:31:11 +01:00
|
|
|
{
|
2015-03-21 20:22:04 +01:00
|
|
|
RETURN_OBJ(AS_CLASS(args[0])->name);
|
2014-01-29 00:31:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-14 17:48:45 +01:00
|
|
|
DEF_PRIMITIVE(class_supertype)
|
|
|
|
|
{
|
|
|
|
|
ObjClass* classObj = AS_CLASS(args[0]);
|
|
|
|
|
|
|
|
|
|
// Object has no superclass.
|
|
|
|
|
if (classObj->superclass == NULL) RETURN_NULL;
|
feat: reverse argument order of List.insert to index-first convention
The previous signature `insert(element, index)` was counter-intuitive and inconsistent with every major language's list API. This commit swaps the parameters to `insert(index, element)`, matching the convention used by Ruby, JavaScript, C++, Lua, C#, Java, and Python. All documentation, C implementation, and test files are updated to reflect the new order.
2015-03-15 22:51:24 +01:00
|
|
|
|
2015-03-14 17:48:45 +01:00
|
|
|
RETURN_OBJ(classObj->superclass);
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-30 16:39:43 +02:00
|
|
|
DEF_PRIMITIVE(class_toString)
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
{
|
2015-06-30 16:39:43 +02:00
|
|
|
RETURN_OBJ(AS_CLASS(args[0])->name);
|
2014-04-05 03:24:55 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fiber_new)
|
2014-04-05 03:24:55 +02:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateFn(vm, args[1], "Argument")) return PRIM_FIBER;
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
|
|
|
|
|
ObjFiber* newFiber = wrenNewFiber(vm, AS_OBJ(args[1]));
|
|
|
|
|
|
2014-01-13 04:37:11 +01:00
|
|
|
// The compiler expects the first slot of a function to hold the receiver.
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
// Since a fiber's stack is invoked directly, it doesn't have one, so put it
|
|
|
|
|
// in here.
|
|
|
|
|
// TODO: Is there a cleaner solution?
|
|
|
|
|
// TODO: If we make growable stacks, make sure this grows it.
|
|
|
|
|
newFiber->stack[0] = NULL_VAL;
|
2014-12-31 19:34:27 +01:00
|
|
|
newFiber->stackTop++;
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
|
2014-01-29 00:31:11 +01:00
|
|
|
RETURN_OBJ(newFiber);
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fiber_abort)
|
2015-01-01 19:40:14 +01:00
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->error = args[1];
|
|
|
|
|
|
|
|
|
|
// If the error is explicitly null, it's not really an abort.
|
2015-09-30 16:32:39 +02:00
|
|
|
return IS_NULL(args[1]) ? PRIM_VALUE : PRIM_FIBER;
|
2015-01-01 19:40:14 +01:00
|
|
|
}
|
|
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
// Transfer execution to [fiber] coming from the current fiber whose stack has
|
|
|
|
|
// [args].
|
|
|
|
|
//
|
|
|
|
|
// [isCall] is true if [fiber] is being called and not transferred.
|
|
|
|
|
//
|
|
|
|
|
// [hasValue] is true if a value in [args] is being passed to the new fiber.
|
|
|
|
|
// Otherwise, `null` is implicitly being passed.
|
|
|
|
|
static PrimitiveResult runFiber(WrenVM* vm, ObjFiber* fiber, Value* args,
|
|
|
|
|
bool isCall, bool hasValue)
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
{
|
2015-08-31 07:15:37 +02:00
|
|
|
if (isCall)
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
{
|
2015-08-31 07:15:37 +02:00
|
|
|
if (fiber->caller != NULL) RETURN_ERROR("Fiber has already been called.");
|
2015-09-13 19:03:02 +02:00
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
// Remember who ran it.
|
|
|
|
|
fiber->caller = vm->fiber;
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
}
|
2015-09-13 19:03:02 +02:00
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
if (fiber->numFrames == 0)
|
|
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->error = wrenStringFormat(vm, "Cannot $ a finished fiber.",
|
2015-08-31 07:15:37 +02:00
|
|
|
isCall ? "call" : "transfer to");
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
2015-08-31 07:15:37 +02:00
|
|
|
}
|
2015-09-13 19:03:02 +02:00
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
if (!IS_NULL(fiber->error))
|
2015-08-31 07:15:37 +02:00
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->error = wrenStringFormat(vm, "Cannot $ an aborted fiber.",
|
2015-08-31 07:15:37 +02:00
|
|
|
isCall ? "call" : "transfer to");
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
2015-08-31 07:15:37 +02:00
|
|
|
}
|
2015-09-13 19:03:02 +02:00
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
// When the calling fiber resumes, we'll store the result of the call in its
|
|
|
|
|
// stack. If the call has two arguments (the fiber and the value), we only
|
|
|
|
|
// need one slot for the result, so discard the other slot now.
|
|
|
|
|
if (hasValue) vm->fiber->stackTop--;
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
// If the fiber was paused, make yield() or transfer() return the result.
|
|
|
|
|
if (fiber->stackTop > fiber->stack)
|
|
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
fiber->stackTop[-1] = hasValue ? args[1] : NULL_VAL;
|
2015-08-31 07:15:37 +02:00
|
|
|
}
|
2015-09-13 19:03:02 +02:00
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber = fiber;
|
|
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
}
|
|
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
DEF_PRIMITIVE(fiber_call)
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
{
|
2015-08-31 07:15:37 +02:00
|
|
|
return runFiber(vm, AS_FIBER(args[0]), args, true, false);
|
|
|
|
|
}
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
DEF_PRIMITIVE(fiber_call1)
|
|
|
|
|
{
|
|
|
|
|
return runFiber(vm, AS_FIBER(args[0]), args, true, true);
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-07 21:32:11 +01:00
|
|
|
DEF_PRIMITIVE(fiber_current)
|
|
|
|
|
{
|
|
|
|
|
RETURN_OBJ(fiber);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fiber_error)
|
2014-10-15 15:36:42 +02:00
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
RETURN_VAL(AS_FIBER(args[0])->error);
|
2014-10-15 15:36:42 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fiber_isDone)
|
2014-04-14 16:23:05 +02:00
|
|
|
{
|
|
|
|
|
ObjFiber* runFiber = AS_FIBER(args[0]);
|
2015-09-30 07:57:03 +02:00
|
|
|
RETURN_BOOL(runFiber->numFrames == 0 || !IS_NULL(runFiber->error));
|
2014-04-14 16:23:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
DEF_PRIMITIVE(fiber_suspend)
|
2014-04-14 16:23:05 +02:00
|
|
|
{
|
2015-08-31 07:15:37 +02:00
|
|
|
// Switching to a null fiber tells the interpreter to stop and exit.
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber = NULL;
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
2014-04-14 16:23:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
DEF_PRIMITIVE(fiber_transfer)
|
2014-04-14 16:23:05 +02:00
|
|
|
{
|
2015-08-31 07:15:37 +02:00
|
|
|
return runFiber(vm, AS_FIBER(args[0]), args, false, false);
|
|
|
|
|
}
|
2014-04-14 16:23:05 +02:00
|
|
|
|
2015-08-31 07:15:37 +02:00
|
|
|
DEF_PRIMITIVE(fiber_transfer1)
|
|
|
|
|
{
|
|
|
|
|
return runFiber(vm, AS_FIBER(args[0]), args, false, true);
|
2014-04-14 16:23:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
DEF_PRIMITIVE(fiber_transferError)
|
2014-10-15 15:36:42 +02:00
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
PrimitiveResult result = runFiber(vm, AS_FIBER(args[0]), args, false, true);
|
2015-09-30 16:32:39 +02:00
|
|
|
if (result == PRIM_FIBER) vm->fiber->error = args[1];
|
2015-09-30 07:57:03 +02:00
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2014-10-15 15:36:42 +02:00
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
DEF_PRIMITIVE(fiber_try)
|
|
|
|
|
{
|
|
|
|
|
ObjFiber* tried = AS_FIBER(args[0]);
|
2015-08-31 07:15:37 +02:00
|
|
|
// TODO: Use runFiber().
|
2015-09-30 07:57:03 +02:00
|
|
|
if (tried->numFrames == 0) RETURN_ERROR("Cannot try a finished fiber.");
|
|
|
|
|
if (tried->caller != NULL) RETURN_ERROR("Fiber has already been called.");
|
2014-10-15 15:36:42 +02:00
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber = tried;
|
|
|
|
|
|
2014-10-15 15:36:42 +02:00
|
|
|
// Remember who ran it.
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->caller = fiber;
|
|
|
|
|
vm->fiber->callerIsTrying = true;
|
2014-10-15 15:36:42 +02:00
|
|
|
|
|
|
|
|
// If the fiber was yielded, make the yield call return null.
|
2015-09-30 07:57:03 +02:00
|
|
|
if (vm->fiber->stackTop > vm->fiber->stack)
|
2014-10-15 15:36:42 +02:00
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->stackTop[-1] = NULL_VAL;
|
2014-10-15 15:36:42 +02:00
|
|
|
}
|
2015-09-30 07:57:03 +02:00
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
2014-10-15 15:36:42 +02:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fiber_yield)
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber = fiber->caller;
|
|
|
|
|
|
2015-03-07 21:32:11 +01:00
|
|
|
// Unhook this fiber from the one that called it.
|
2014-04-14 16:23:05 +02:00
|
|
|
fiber->caller = NULL;
|
2014-10-15 15:36:42 +02:00
|
|
|
fiber->callerIsTrying = false;
|
2015-09-13 19:03:02 +02:00
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
if (vm->fiber != NULL)
|
2015-03-07 21:32:11 +01:00
|
|
|
{
|
|
|
|
|
// Make the caller's run method return null.
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->stackTop[-1] = NULL_VAL;
|
2015-03-07 21:32:11 +01:00
|
|
|
}
|
2015-09-30 07:57:03 +02:00
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fiber_yield1)
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber = fiber->caller;
|
|
|
|
|
|
2015-03-07 21:32:11 +01:00
|
|
|
// Unhook this fiber from the one that called it.
|
2014-04-14 16:23:05 +02:00
|
|
|
fiber->caller = NULL;
|
2014-10-15 15:36:42 +02:00
|
|
|
fiber->callerIsTrying = false;
|
2014-04-14 16:23:05 +02:00
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
if (vm->fiber != NULL)
|
2015-03-07 21:32:11 +01:00
|
|
|
{
|
|
|
|
|
// Make the caller's run method return the argument passed to yield.
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->stackTop[-1] = args[1];
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
// When the yielding fiber resumes, we'll store the result of the yield
|
|
|
|
|
// call in its stack. Since Fiber.yield(value) has two arguments (the Fiber
|
|
|
|
|
// class and the value) and we only need one slot for the result, discard
|
|
|
|
|
// the other slot now.
|
2015-03-07 21:32:11 +01:00
|
|
|
fiber->stackTop--;
|
|
|
|
|
}
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
feat: implement fiber primitives with create, run, yield and caller tracking
Add core fiber functionality including Fiber.create, Fiber.run, Fiber.yield
primitives with value passing between fibers. Introduce PRIM_RUN_FIBER result
type for interpreter loop, add caller field to ObjFiber struct for yield
resumption, and update GC marking to traverse fiber caller chains. Modify
wrenNewFiber to accept a function/closure argument and initialize the first
call frame. Add debug stack printing with fiber pointer. Include test suite
covering fiber creation, run, yield, value passing, type checking, and
caller resumption.
2014-01-12 20:02:07 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fn_new)
|
2015-01-24 05:33:05 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateFn(vm, args[1], "Argument")) return PRIM_FIBER;
|
2015-01-24 05:33:05 +01:00
|
|
|
|
|
|
|
|
// The block argument is already a function, so just return it.
|
|
|
|
|
RETURN_VAL(args[1]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(fn_arity)
|
2015-01-24 05:33:05 +01:00
|
|
|
{
|
|
|
|
|
RETURN_NUM(AS_FN(args[0])->arity);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-26 20:42:20 +01:00
|
|
|
static PrimitiveResult callFn(WrenVM* vm, Value* args, int numArgs)
|
2014-02-04 18:34:05 +01:00
|
|
|
{
|
2014-02-10 16:53:09 +01:00
|
|
|
ObjFn* fn;
|
|
|
|
|
if (IS_CLOSURE(args[0]))
|
|
|
|
|
{
|
|
|
|
|
fn = AS_CLOSURE(args[0])->fn;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fn = AS_FN(args[0]);
|
|
|
|
|
}
|
2014-02-15 20:21:24 +01:00
|
|
|
|
2015-01-24 05:33:05 +01:00
|
|
|
if (numArgs < fn->arity) RETURN_ERROR("Function expects more arguments.");
|
2014-02-15 20:21:24 +01:00
|
|
|
|
2014-02-04 18:34:05 +01:00
|
|
|
return PRIM_CALL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-26 20:42:20 +01:00
|
|
|
DEF_PRIMITIVE(fn_call0) { return callFn(vm, args, 0); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call1) { return callFn(vm, args, 1); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call2) { return callFn(vm, args, 2); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call3) { return callFn(vm, args, 3); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call4) { return callFn(vm, args, 4); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call5) { return callFn(vm, args, 5); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call6) { return callFn(vm, args, 6); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call7) { return callFn(vm, args, 7); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call8) { return callFn(vm, args, 8); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call9) { return callFn(vm, args, 9); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call10) { return callFn(vm, args, 10); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call11) { return callFn(vm, args, 11); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call12) { return callFn(vm, args, 12); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call13) { return callFn(vm, args, 13); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call14) { return callFn(vm, args, 14); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call15) { return callFn(vm, args, 15); }
|
|
|
|
|
DEF_PRIMITIVE(fn_call16) { return callFn(vm, args, 16); }
|
2015-03-02 16:24:04 +01:00
|
|
|
|
|
|
|
|
DEF_PRIMITIVE(fn_toString)
|
2014-02-15 20:36:01 +01:00
|
|
|
{
|
2015-03-16 06:32:20 +01:00
|
|
|
RETURN_VAL(CONST_STRING(vm, "<fn>"));
|
2014-02-15 20:36:01 +01:00
|
|
|
}
|
2014-01-02 16:32:00 +01:00
|
|
|
|
2015-07-10 18:18:22 +02:00
|
|
|
DEF_PRIMITIVE(list_new)
|
2014-04-08 16:31:23 +02:00
|
|
|
{
|
|
|
|
|
RETURN_OBJ(wrenNewList(vm, 0));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_add)
|
2013-11-27 03:02:10 +01:00
|
|
|
{
|
2015-03-22 20:22:47 +01:00
|
|
|
wrenValueBufferWrite(vm, &AS_LIST(args[0])->elements, args[1]);
|
2014-01-01 22:25:24 +01:00
|
|
|
RETURN_VAL(args[1]);
|
2013-11-27 03:02:10 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_clear)
|
2013-11-27 08:11:11 +01:00
|
|
|
{
|
2015-03-22 20:22:47 +01:00
|
|
|
wrenValueBufferClear(vm, &AS_LIST(args[0])->elements);
|
2014-01-01 22:25:24 +01:00
|
|
|
RETURN_NULL;
|
2013-11-27 08:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_count)
|
2013-11-24 22:38:31 +01:00
|
|
|
{
|
2015-03-22 20:22:47 +01:00
|
|
|
RETURN_NUM(AS_LIST(args[0])->elements.count);
|
2013-11-24 22:38:31 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_insert)
|
2013-11-25 04:08:46 +01:00
|
|
|
{
|
2013-11-27 08:11:11 +01:00
|
|
|
ObjList* list = AS_LIST(args[0]);
|
2013-11-25 04:08:46 +01:00
|
|
|
|
feat: implement list_removeAt primitive with capacity shrink and test suite
Add DEF_PRIMITIVE(list_removeAt) to src/primitives.c that removes an element at a given index from an ObjList, shifts remaining elements up, shrinks capacity when excess is detected via LIST_GROW_FACTOR, and returns the removed Value. Register the primitive as "removeAt " on vm->listClass. Create test/list/remove_at.wren covering removal at positive indices 0,1,2, negative indices -1,-2,-3, out-of-bounds cases returning null, and verification that the removed value is returned.
2013-11-27 19:20:32 +01:00
|
|
|
// count + 1 here so you can "insert" at the very end.
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], list->elements.count + 1,
|
2015-03-22 20:22:47 +01:00
|
|
|
"Index");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2013-11-25 04:08:46 +01:00
|
|
|
|
feat: reverse argument order of List.insert to index-first convention
The previous signature `insert(element, index)` was counter-intuitive and inconsistent with every major language's list API. This commit swaps the parameters to `insert(index, element)`, matching the convention used by Ruby, JavaScript, C++, Lua, C#, Java, and Python. All documentation, C implementation, and test files are updated to reflect the new order.
2015-03-15 22:51:24 +01:00
|
|
|
wrenListInsert(vm, list, args[2], index);
|
|
|
|
|
RETURN_VAL(args[2]);
|
2013-11-27 08:11:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_iterate)
|
2013-12-25 06:04:11 +01:00
|
|
|
{
|
2014-02-15 02:24:06 +01:00
|
|
|
ObjList* list = AS_LIST(args[0]);
|
|
|
|
|
|
2013-12-25 06:04:11 +01:00
|
|
|
// If we're starting the iteration, return the first index.
|
2014-02-15 02:24:06 +01:00
|
|
|
if (IS_NULL(args[1]))
|
|
|
|
|
{
|
2015-03-22 20:22:47 +01:00
|
|
|
if (list->elements.count == 0) RETURN_FALSE;
|
2014-02-15 02:24:06 +01:00
|
|
|
RETURN_NUM(0);
|
|
|
|
|
}
|
2013-12-25 06:04:11 +01:00
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateInt(vm, args[1], "Iterator")) return PRIM_FIBER;
|
2014-01-02 16:32:00 +01:00
|
|
|
|
|
|
|
|
// Stop if we're out of bounds.
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
double index = AS_NUM(args[1]);
|
2015-03-22 20:22:47 +01:00
|
|
|
if (index < 0 || index >= list->elements.count - 1) RETURN_FALSE;
|
2013-12-25 06:04:11 +01:00
|
|
|
|
|
|
|
|
// Otherwise, move to the next index.
|
2014-01-01 22:25:24 +01:00
|
|
|
RETURN_NUM(index + 1);
|
2013-12-25 06:04:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_iteratorValue)
|
2013-12-25 06:04:11 +01:00
|
|
|
{
|
|
|
|
|
ObjList* list = AS_LIST(args[0]);
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], list->elements.count, "Iterator");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2014-01-02 16:32:00 +01:00
|
|
|
|
2015-03-22 20:22:47 +01:00
|
|
|
RETURN_VAL(list->elements.data[index]);
|
2013-12-25 06:04:11 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_removeAt)
|
feat: implement list_removeAt primitive with capacity shrink and test suite
Add DEF_PRIMITIVE(list_removeAt) to src/primitives.c that removes an element at a given index from an ObjList, shifts remaining elements up, shrinks capacity when excess is detected via LIST_GROW_FACTOR, and returns the removed Value. Register the primitive as "removeAt " on vm->listClass. Create test/list/remove_at.wren covering removal at positive indices 0,1,2, negative indices -1,-2,-3, out-of-bounds cases returning null, and verification that the removed value is returned.
2013-11-27 19:20:32 +01:00
|
|
|
{
|
|
|
|
|
ObjList* list = AS_LIST(args[0]);
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], list->elements.count, "Index");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
feat: implement list_removeAt primitive with capacity shrink and test suite
Add DEF_PRIMITIVE(list_removeAt) to src/primitives.c that removes an element at a given index from an ObjList, shifts remaining elements up, shrinks capacity when excess is detected via LIST_GROW_FACTOR, and returns the removed Value. Register the primitive as "removeAt " on vm->listClass. Create test/list/remove_at.wren covering removal at positive indices 0,1,2, negative indices -1,-2,-3, out-of-bounds cases returning null, and verification that the removed value is returned.
2013-11-27 19:20:32 +01:00
|
|
|
|
2014-01-01 22:25:24 +01:00
|
|
|
RETURN_VAL(wrenListRemoveAt(vm, list, index));
|
feat: implement list_removeAt primitive with capacity shrink and test suite
Add DEF_PRIMITIVE(list_removeAt) to src/primitives.c that removes an element at a given index from an ObjList, shifts remaining elements up, shrinks capacity when excess is detected via LIST_GROW_FACTOR, and returns the removed Value. Register the primitive as "removeAt " on vm->listClass. Create test/list/remove_at.wren covering removal at positive indices 0,1,2, negative indices -1,-2,-3, out-of-bounds cases returning null, and verification that the removed value is returned.
2013-11-27 19:20:32 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_subscript)
|
2013-11-27 08:11:11 +01:00
|
|
|
{
|
|
|
|
|
ObjList* list = AS_LIST(args[0]);
|
2013-11-25 04:08:46 +01:00
|
|
|
|
2014-01-30 18:12:44 +01:00
|
|
|
if (IS_NUM(args[1]))
|
|
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], list->elements.count,
|
2015-03-22 20:22:47 +01:00
|
|
|
"Subscript");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2014-01-30 18:12:44 +01:00
|
|
|
|
2015-03-22 20:22:47 +01:00
|
|
|
RETURN_VAL(list->elements.data[index]);
|
2014-01-30 18:12:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!IS_RANGE(args[1]))
|
|
|
|
|
{
|
|
|
|
|
RETURN_ERROR("Subscript must be a number or a range.");
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 00:33:21 +01:00
|
|
|
int step;
|
2015-03-22 20:22:47 +01:00
|
|
|
uint32_t count = list->elements.count;
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t start = calculateRange(vm, AS_RANGE(args[1]), &count, &step);
|
2015-09-30 16:32:39 +02:00
|
|
|
if (start == UINT32_MAX) return PRIM_FIBER;
|
2014-01-30 18:12:44 +01:00
|
|
|
|
2015-01-21 00:33:21 +01:00
|
|
|
ObjList* result = wrenNewList(vm, count);
|
2015-03-21 20:22:04 +01:00
|
|
|
for (uint32_t i = 0; i < count; i++)
|
2014-01-30 18:12:44 +01:00
|
|
|
{
|
2015-09-02 07:14:55 +02:00
|
|
|
result->elements.data[i] = list->elements.data[start + i * step];
|
2014-01-30 18:12:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RETURN_OBJ(result);
|
2013-11-25 04:08:46 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(list_subscriptSetter)
|
2013-12-21 18:37:59 +01:00
|
|
|
{
|
|
|
|
|
ObjList* list = AS_LIST(args[0]);
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], list->elements.count,
|
2015-03-22 20:22:47 +01:00
|
|
|
"Subscript");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2013-12-21 18:37:59 +01:00
|
|
|
|
2015-03-22 20:22:47 +01:00
|
|
|
list->elements.data[index] = args[2];
|
2014-01-01 22:25:24 +01:00
|
|
|
RETURN_VAL(args[2]);
|
2013-12-21 18:37:59 +01:00
|
|
|
}
|
|
|
|
|
|
2015-07-10 18:18:22 +02:00
|
|
|
DEF_PRIMITIVE(map_new)
|
feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 07:27:35 +01:00
|
|
|
{
|
|
|
|
|
RETURN_OBJ(wrenNewMap(vm));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_subscript)
|
feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 07:27:35 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateKey(vm, args[1])) return PRIM_FIBER;
|
2015-01-25 21:39:19 +01:00
|
|
|
|
2015-01-26 02:42:36 +01:00
|
|
|
ObjMap* map = AS_MAP(args[0]);
|
2015-03-07 21:41:18 +01:00
|
|
|
Value value = wrenMapGet(map, args[1]);
|
|
|
|
|
if (IS_UNDEFINED(value)) RETURN_NULL;
|
2015-01-25 21:39:19 +01:00
|
|
|
|
2015-03-07 21:41:18 +01:00
|
|
|
RETURN_VAL(value);
|
feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 07:27:35 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_subscriptSetter)
|
feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 07:27:35 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateKey(vm, args[1])) return PRIM_FIBER;
|
2015-01-25 21:39:19 +01:00
|
|
|
|
feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 07:27:35 +01:00
|
|
|
wrenMapSet(vm, AS_MAP(args[0]), args[1], args[2]);
|
|
|
|
|
RETURN_VAL(args[2]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_clear)
|
2015-01-25 17:39:44 +01:00
|
|
|
{
|
2015-01-26 02:42:36 +01:00
|
|
|
wrenMapClear(vm, AS_MAP(args[0]));
|
2015-01-25 17:39:44 +01:00
|
|
|
RETURN_NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_containsKey)
|
2015-01-25 21:39:19 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateKey(vm, args[1])) return PRIM_FIBER;
|
2015-01-25 21:39:19 +01:00
|
|
|
|
2015-03-07 21:41:18 +01:00
|
|
|
RETURN_BOOL(!IS_UNDEFINED(wrenMapGet(AS_MAP(args[0]), args[1])));
|
2015-01-25 21:39:19 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_count)
|
feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 07:27:35 +01:00
|
|
|
{
|
|
|
|
|
RETURN_NUM(AS_MAP(args[0])->count);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_iterate)
|
2015-01-25 19:27:38 +01:00
|
|
|
{
|
|
|
|
|
ObjMap* map = AS_MAP(args[0]);
|
|
|
|
|
|
|
|
|
|
if (map->count == 0) RETURN_FALSE;
|
|
|
|
|
|
2015-02-25 06:56:33 +01:00
|
|
|
// If we're starting the iteration, start at the first used entry.
|
|
|
|
|
uint32_t index = 0;
|
|
|
|
|
|
|
|
|
|
// Otherwise, start one past the last entry we stopped at.
|
2015-01-25 19:27:38 +01:00
|
|
|
if (!IS_NULL(args[1]))
|
|
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateInt(vm, args[1], "Iterator")) return PRIM_FIBER;
|
2015-01-25 19:27:38 +01:00
|
|
|
|
2015-02-25 06:56:33 +01:00
|
|
|
if (AS_NUM(args[1]) < 0) RETURN_FALSE;
|
|
|
|
|
index = (uint32_t)AS_NUM(args[1]);
|
|
|
|
|
|
|
|
|
|
if (index >= map->capacity) RETURN_FALSE;
|
|
|
|
|
|
|
|
|
|
// Advance the iterator.
|
|
|
|
|
index++;
|
2015-01-25 19:27:38 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-25 06:56:33 +01:00
|
|
|
// Find a used entry, if any.
|
|
|
|
|
for (; index < map->capacity; index++)
|
2015-01-25 19:27:38 +01:00
|
|
|
{
|
|
|
|
|
if (!IS_UNDEFINED(map->entries[index].key)) RETURN_NUM(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we get here, walked all of the entries.
|
|
|
|
|
RETURN_FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_remove)
|
2015-01-26 02:42:36 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateKey(vm, args[1])) return PRIM_FIBER;
|
2015-01-26 04:50:54 +01:00
|
|
|
|
2015-01-26 02:42:36 +01:00
|
|
|
RETURN_VAL(wrenMapRemoveKey(vm, AS_MAP(args[0]), args[1]));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_keyIteratorValue)
|
2015-01-25 19:27:38 +01:00
|
|
|
{
|
|
|
|
|
ObjMap* map = AS_MAP(args[0]);
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], map->capacity, "Iterator");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2015-01-25 19:27:38 +01:00
|
|
|
|
|
|
|
|
MapEntry* entry = &map->entries[index];
|
|
|
|
|
if (IS_UNDEFINED(entry->key))
|
|
|
|
|
{
|
|
|
|
|
RETURN_ERROR("Invalid map iterator value.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RETURN_VAL(entry->key);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(map_valueIteratorValue)
|
2015-01-25 19:27:38 +01:00
|
|
|
{
|
|
|
|
|
ObjMap* map = AS_MAP(args[0]);
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], map->capacity, "Iterator");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2015-01-25 19:27:38 +01:00
|
|
|
|
|
|
|
|
MapEntry* entry = &map->entries[index];
|
|
|
|
|
if (IS_UNDEFINED(entry->key))
|
|
|
|
|
{
|
|
|
|
|
RETURN_ERROR("Invalid map iterator value.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RETURN_VAL(entry->value);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(null_not)
|
2015-01-16 06:50:01 +01:00
|
|
|
{
|
|
|
|
|
RETURN_VAL(TRUE_VAL);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(null_toString)
|
2013-12-08 03:47:40 +01:00
|
|
|
{
|
2015-03-16 06:32:20 +01:00
|
|
|
RETURN_VAL(CONST_STRING(vm, "null"));
|
2013-12-08 03:47:40 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(num_fromString)
|
2015-02-23 05:06:17 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateString(vm, args[1], "Argument")) return PRIM_FIBER;
|
2015-02-23 05:06:17 +01:00
|
|
|
|
2015-02-25 16:07:54 +01:00
|
|
|
ObjString* string = AS_STRING(args[1]);
|
|
|
|
|
|
|
|
|
|
// Corner case: Can't parse an empty string.
|
|
|
|
|
if (string->length == 0) RETURN_NULL;
|
2015-02-23 05:06:17 +01:00
|
|
|
|
2015-03-03 09:06:34 +01:00
|
|
|
errno = 0;
|
2015-02-23 05:06:17 +01:00
|
|
|
char* end;
|
2015-02-25 16:07:54 +01:00
|
|
|
double number = strtod(string->value, &end);
|
|
|
|
|
|
|
|
|
|
// Skip past any trailing whitespace.
|
2015-04-01 15:43:44 +02:00
|
|
|
while (*end != '\0' && isspace((unsigned char)*end)) end++;
|
2015-02-23 05:06:17 +01:00
|
|
|
|
2015-03-03 09:06:34 +01:00
|
|
|
if (errno == ERANGE)
|
|
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
vm->fiber->error = CONST_STRING(vm, "Number literal is too large.");
|
2015-09-30 16:32:39 +02:00
|
|
|
return PRIM_FIBER;
|
2015-03-03 09:06:34 +01:00
|
|
|
}
|
|
|
|
|
|
2015-02-25 16:07:54 +01:00
|
|
|
// We must have consumed the entire string. Otherwise, it contains non-number
|
|
|
|
|
// characters and we can't parse it.
|
|
|
|
|
if (end < string->value + string->length) RETURN_NULL;
|
2015-02-23 05:06:17 +01:00
|
|
|
|
|
|
|
|
RETURN_NUM(number);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-19 21:12:50 +01:00
|
|
|
DEF_PRIMITIVE(num_pi)
|
|
|
|
|
{
|
|
|
|
|
RETURN_NUM(3.14159265358979323846);
|
|
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
// Defines a primitive on Num that calls infix [op] and returns [type].
|
|
|
|
|
#define DEF_NUM_INFIX(name, op, type) \
|
|
|
|
|
DEF_PRIMITIVE(num_##name) \
|
|
|
|
|
{ \
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateNum(vm, args[1], "Right operand")) return PRIM_FIBER; \
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_##type(AS_NUM(args[0]) op AS_NUM(args[1])); \
|
|
|
|
|
}
|
2013-10-31 15:04:44 +01:00
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_NUM_INFIX(minus, -, NUM)
|
|
|
|
|
DEF_NUM_INFIX(plus, +, NUM)
|
|
|
|
|
DEF_NUM_INFIX(multiply, *, NUM)
|
|
|
|
|
DEF_NUM_INFIX(divide, /, NUM)
|
|
|
|
|
DEF_NUM_INFIX(lt, <, BOOL)
|
|
|
|
|
DEF_NUM_INFIX(gt, >, BOOL)
|
|
|
|
|
DEF_NUM_INFIX(lte, <=, BOOL)
|
|
|
|
|
DEF_NUM_INFIX(gte, >=, BOOL)
|
|
|
|
|
|
|
|
|
|
// Defines a primitive on Num that call infix bitwise [op].
|
|
|
|
|
#define DEF_NUM_BITWISE(name, op) \
|
|
|
|
|
DEF_PRIMITIVE(num_bitwise##name) \
|
|
|
|
|
{ \
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateNum(vm, args[1], "Right operand")) return PRIM_FIBER; \
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
uint32_t left = (uint32_t)AS_NUM(args[0]); \
|
|
|
|
|
uint32_t right = (uint32_t)AS_NUM(args[1]); \
|
|
|
|
|
RETURN_NUM(left op right); \
|
|
|
|
|
}
|
2013-10-31 15:04:44 +01:00
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_NUM_BITWISE(And, &)
|
|
|
|
|
DEF_NUM_BITWISE(Or, |)
|
|
|
|
|
DEF_NUM_BITWISE(Xor, ^)
|
|
|
|
|
DEF_NUM_BITWISE(LeftShift, <<)
|
|
|
|
|
DEF_NUM_BITWISE(RightShift, >>)
|
2013-10-31 15:04:44 +01:00
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
// Defines a primitive method on Num that returns the result of [fn].
|
|
|
|
|
#define DEF_NUM_FN(name, fn) \
|
|
|
|
|
DEF_PRIMITIVE(num_##name) \
|
|
|
|
|
{ \
|
|
|
|
|
RETURN_NUM(fn(AS_NUM(args[0]))); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEF_NUM_FN(abs, fabs)
|
|
|
|
|
DEF_NUM_FN(acos, acos)
|
|
|
|
|
DEF_NUM_FN(asin, asin)
|
|
|
|
|
DEF_NUM_FN(atan, atan)
|
|
|
|
|
DEF_NUM_FN(ceil, ceil)
|
|
|
|
|
DEF_NUM_FN(cos, cos)
|
|
|
|
|
DEF_NUM_FN(floor, floor)
|
|
|
|
|
DEF_NUM_FN(negate, -)
|
|
|
|
|
DEF_NUM_FN(sin, sin)
|
|
|
|
|
DEF_NUM_FN(sqrt, sqrt)
|
|
|
|
|
DEF_NUM_FN(tan, tan)
|
2013-10-31 15:04:44 +01:00
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(num_mod)
|
2013-11-10 06:01:18 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateNum(vm, args[1], "Right operand")) return PRIM_FIBER;
|
2014-01-01 22:25:24 +01:00
|
|
|
RETURN_NUM(fmod(AS_NUM(args[0]), AS_NUM(args[1])));
|
2013-11-10 06:01:18 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(num_eqeq)
|
2013-11-05 18:57:57 +01:00
|
|
|
{
|
2014-01-01 22:25:24 +01:00
|
|
|
if (!IS_NUM(args[1])) RETURN_FALSE;
|
|
|
|
|
RETURN_BOOL(AS_NUM(args[0]) == AS_NUM(args[1]));
|
2013-11-05 18:57:57 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(num_bangeq)
|
2013-11-05 18:57:57 +01:00
|
|
|
{
|
2014-01-01 22:25:24 +01:00
|
|
|
if (!IS_NUM(args[1])) RETURN_TRUE;
|
|
|
|
|
RETURN_BOOL(AS_NUM(args[0]) != AS_NUM(args[1]));
|
2013-11-05 18:57:57 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(num_bitwiseNot)
|
2013-12-05 07:09:31 +01:00
|
|
|
{
|
|
|
|
|
// Bitwise operators always work on 32-bit unsigned ints.
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_NUM(~(uint32_t)AS_NUM(args[0]));
|
2013-12-05 07:09:31 +01:00
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_dotDot)
|
2014-02-24 16:27:43 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateNum(vm, args[1], "Right hand side of range")) return PRIM_FIBER;
|
2014-02-24 16:27:43 +01:00
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
double from = AS_NUM(args[0]);
|
|
|
|
|
double to = AS_NUM(args[1]);
|
|
|
|
|
RETURN_VAL(wrenNewRange(vm, from, to, true));
|
2014-02-24 16:27:43 +01:00
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_dotDotDot)
|
2014-02-24 16:27:43 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateNum(vm, args[1], "Right hand side of range")) return PRIM_FIBER;
|
2014-02-24 16:27:43 +01:00
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
double from = AS_NUM(args[0]);
|
|
|
|
|
double to = AS_NUM(args[1]);
|
|
|
|
|
RETURN_VAL(wrenNewRange(vm, from, to, false));
|
2014-02-24 16:27:43 +01:00
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_atan2)
|
2015-02-16 11:29:14 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_NUM(atan2(AS_NUM(args[0]), AS_NUM(args[1])));
|
2015-02-16 11:29:14 +01:00
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_fraction)
|
2015-02-16 11:29:14 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
double dummy;
|
|
|
|
|
RETURN_NUM(modf(AS_NUM(args[0]) , &dummy));
|
2015-02-16 11:29:14 +01:00
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_isNan)
|
2015-02-16 11:29:14 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_BOOL(isnan(AS_NUM(args[0])));
|
2015-02-16 11:29:14 +01:00
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_sign)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
double value = AS_NUM(args[0]);
|
|
|
|
|
if (value > 0)
|
|
|
|
|
{
|
|
|
|
|
RETURN_NUM(1);
|
|
|
|
|
}
|
|
|
|
|
else if (value < 0)
|
|
|
|
|
{
|
|
|
|
|
RETURN_NUM(-1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
RETURN_NUM(0);
|
|
|
|
|
}
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_toString)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_VAL(wrenNumToString(vm, AS_NUM(args[0])));
|
|
|
|
|
}
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
DEF_PRIMITIVE(num_truncate)
|
|
|
|
|
{
|
|
|
|
|
double integer;
|
|
|
|
|
modf(AS_NUM(args[0]) , &integer);
|
|
|
|
|
RETURN_NUM(integer);
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-05-01 16:55:28 +02:00
|
|
|
DEF_PRIMITIVE(object_same)
|
|
|
|
|
{
|
|
|
|
|
RETURN_BOOL(wrenValuesEqual(args[1], args[2]));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(object_not)
|
2015-01-16 06:50:01 +01:00
|
|
|
{
|
|
|
|
|
RETURN_VAL(FALSE_VAL);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(object_eqeq)
|
2013-11-26 16:52:37 +01:00
|
|
|
{
|
2015-01-26 08:26:59 +01:00
|
|
|
RETURN_BOOL(wrenValuesEqual(args[0], args[1]));
|
2013-11-26 16:52:37 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(object_bangeq)
|
2013-11-26 16:52:37 +01:00
|
|
|
{
|
2015-01-26 08:26:59 +01:00
|
|
|
RETURN_BOOL(!wrenValuesEqual(args[0], args[1]));
|
2013-11-26 16:52:37 +01:00
|
|
|
}
|
|
|
|
|
|
2015-06-19 16:58:07 +02:00
|
|
|
DEF_PRIMITIVE(object_is)
|
|
|
|
|
{
|
|
|
|
|
if (!IS_CLASS(args[1]))
|
|
|
|
|
{
|
|
|
|
|
RETURN_ERROR("Right operand must be a class.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ObjClass *classObj = wrenGetClass(vm, args[0]);
|
|
|
|
|
ObjClass *baseClassObj = AS_CLASS(args[1]);
|
|
|
|
|
|
|
|
|
|
// Walk the superclass chain looking for the class.
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (baseClassObj == classObj) RETURN_BOOL(true);
|
|
|
|
|
|
|
|
|
|
classObj = classObj->superclass;
|
|
|
|
|
}
|
|
|
|
|
while (classObj != NULL);
|
|
|
|
|
|
|
|
|
|
RETURN_BOOL(false);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(object_toString)
|
2013-12-22 20:50:00 +01:00
|
|
|
{
|
2015-06-30 16:39:43 +02:00
|
|
|
Obj* obj = AS_OBJ(args[0]);
|
|
|
|
|
Value name = OBJ_VAL(obj->classObj->name);
|
|
|
|
|
RETURN_VAL(wrenStringFormat(vm, "instance of @", name));
|
2013-12-22 20:50:00 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(object_type)
|
2013-11-26 16:52:37 +01:00
|
|
|
{
|
2014-01-29 00:31:11 +01:00
|
|
|
RETURN_OBJ(wrenGetClass(vm, args[0]));
|
2013-11-26 16:52:37 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_from)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_NUM(AS_RANGE(args[0])->from);
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_to)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_NUM(AS_RANGE(args[0])->to);
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_min)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
|
|
|
|
ObjRange* range = AS_RANGE(args[0]);
|
|
|
|
|
RETURN_NUM(fmin(range->from, range->to));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_max)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
|
|
|
|
ObjRange* range = AS_RANGE(args[0]);
|
|
|
|
|
RETURN_NUM(fmax(range->from, range->to));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_isInclusive)
|
2014-01-20 22:20:22 +01:00
|
|
|
{
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_BOOL(AS_RANGE(args[0])->isInclusive);
|
2014-01-20 22:20:22 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_iterate)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
|
|
|
|
ObjRange* range = AS_RANGE(args[0]);
|
|
|
|
|
|
2014-01-20 22:20:22 +01:00
|
|
|
// Special case: empty range.
|
|
|
|
|
if (range->from == range->to && !range->isInclusive) RETURN_FALSE;
|
|
|
|
|
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
// Start the iteration.
|
|
|
|
|
if (IS_NULL(args[1])) RETURN_NUM(range->from);
|
|
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateNum(vm, args[1], "Iterator")) return PRIM_FIBER;
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
|
|
|
|
|
double iterator = AS_NUM(args[1]);
|
|
|
|
|
|
2014-01-20 22:20:22 +01:00
|
|
|
// Iterate towards [to] from [from].
|
|
|
|
|
if (range->from < range->to)
|
|
|
|
|
{
|
|
|
|
|
iterator++;
|
|
|
|
|
if (iterator > range->to) RETURN_FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
iterator--;
|
|
|
|
|
if (iterator < range->to) RETURN_FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!range->isInclusive && iterator == range->to) RETURN_FALSE;
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
|
2014-01-20 22:20:22 +01:00
|
|
|
RETURN_NUM(iterator);
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_iteratorValue)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
|
|
|
|
// Assume the iterator is a number so that is the value of the range.
|
|
|
|
|
RETURN_VAL(args[1]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(range_toString)
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
{
|
|
|
|
|
ObjRange* range = AS_RANGE(args[0]);
|
2015-03-16 06:32:20 +01:00
|
|
|
|
|
|
|
|
Value from = wrenNumToString(vm, range->from);
|
|
|
|
|
wrenPushRoot(vm, AS_OBJ(from));
|
|
|
|
|
|
|
|
|
|
Value to = wrenNumToString(vm, range->to);
|
|
|
|
|
wrenPushRoot(vm, AS_OBJ(to));
|
|
|
|
|
|
|
|
|
|
Value result = wrenStringFormat(vm, "@$@", from,
|
|
|
|
|
range->isInclusive ? ".." : "...", to);
|
|
|
|
|
|
|
|
|
|
wrenPopRoot(vm);
|
|
|
|
|
wrenPopRoot(vm);
|
|
|
|
|
RETURN_VAL(result);
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-27 15:43:36 +01:00
|
|
|
DEF_PRIMITIVE(string_fromCodePoint)
|
|
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateInt(vm, args[1], "Code point")) return PRIM_FIBER;
|
2015-03-27 15:43:36 +01:00
|
|
|
|
|
|
|
|
int codePoint = (int)AS_NUM(args[1]);
|
|
|
|
|
if (codePoint < 0)
|
|
|
|
|
{
|
|
|
|
|
RETURN_ERROR("Code point cannot be negative.");
|
|
|
|
|
}
|
|
|
|
|
else if (codePoint > 0x10ffff)
|
|
|
|
|
{
|
|
|
|
|
RETURN_ERROR("Code point cannot be greater than 0x10ffff.");
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-28 04:44:07 +01:00
|
|
|
RETURN_VAL(wrenStringFromCodePoint(vm, codePoint));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEF_PRIMITIVE(string_byteAt)
|
|
|
|
|
{
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], string->length, "Index");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2015-03-28 04:44:07 +01:00
|
|
|
|
|
|
|
|
RETURN_NUM((uint8_t)string->value[index]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-11 08:52:18 +02:00
|
|
|
DEF_PRIMITIVE(string_byteCount)
|
|
|
|
|
{
|
|
|
|
|
RETURN_NUM(AS_STRING(args[0])->length);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-28 04:44:07 +01:00
|
|
|
DEF_PRIMITIVE(string_codePointAt)
|
|
|
|
|
{
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], string->length, "Index");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2015-03-28 04:44:07 +01:00
|
|
|
|
|
|
|
|
// If we are in the middle of a UTF-8 sequence, indicate that.
|
|
|
|
|
const uint8_t* bytes = (uint8_t*)string->value;
|
|
|
|
|
if ((bytes[index] & 0xc0) == 0x80) RETURN_NUM(-1);
|
|
|
|
|
|
|
|
|
|
// Decode the UTF-8 sequence.
|
|
|
|
|
RETURN_NUM(wrenUtf8Decode((uint8_t*)string->value + index,
|
|
|
|
|
string->length - index));
|
2015-03-27 15:43:36 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_contains)
|
2013-10-27 19:28:15 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateString(vm, args[1], "Argument")) return PRIM_FIBER;
|
2014-01-03 19:47:26 +01:00
|
|
|
|
2015-01-07 22:05:33 +01:00
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
ObjString* search = AS_STRING(args[1]);
|
2013-10-27 19:28:15 +01:00
|
|
|
|
refactor: remove unused WrenVM* parameter from buffer init, string find, and debug print functions
Remove the `WrenVM* vm` parameter from `wrenValueBufferInit`, `wrenByteBufferInit`,
`wrenIntBufferInit`, `wrenStringBufferInit`, `wrenSymbolTableInit`,
`wrenMethodBufferInit`, `wrenStringFind`, and `wrenDebugPrintStackTrace`
functions across the compiler, core, debug, utils, value, and VM modules.
Update all call sites and macro definitions to match the simplified signatures,
eliminating dead parameters that were never used within the function bodies.
2015-03-23 06:17:40 +01:00
|
|
|
RETURN_BOOL(wrenStringFind(string, search) != UINT32_MAX);
|
2013-10-27 19:28:15 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_endsWith)
|
2015-01-10 23:45:14 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateString(vm, args[1], "Argument")) return PRIM_FIBER;
|
2015-01-10 23:45:14 +01:00
|
|
|
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
ObjString* search = AS_STRING(args[1]);
|
|
|
|
|
|
|
|
|
|
// Corner case, if the search string is longer than return false right away.
|
|
|
|
|
if (search->length > string->length) RETURN_FALSE;
|
|
|
|
|
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
RETURN_BOOL(memcmp(string->value + string->length - search->length,
|
|
|
|
|
search->value, search->length) == 0);
|
2015-01-10 23:45:14 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_indexOf)
|
2015-01-10 23:45:14 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateString(vm, args[1], "Argument")) return PRIM_FIBER;
|
2015-01-10 23:45:14 +01:00
|
|
|
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
ObjString* search = AS_STRING(args[1]);
|
|
|
|
|
|
refactor: remove unused WrenVM* parameter from buffer init, string find, and debug print functions
Remove the `WrenVM* vm` parameter from `wrenValueBufferInit`, `wrenByteBufferInit`,
`wrenIntBufferInit`, `wrenStringBufferInit`, `wrenSymbolTableInit`,
`wrenMethodBufferInit`, `wrenStringFind`, and `wrenDebugPrintStackTrace`
functions across the compiler, core, debug, utils, value, and VM modules.
Update all call sites and macro definitions to match the simplified signatures,
eliminating dead parameters that were never used within the function bodies.
2015-03-23 06:17:40 +01:00
|
|
|
uint32_t index = wrenStringFind(string, search);
|
2015-02-05 05:23:50 +01:00
|
|
|
RETURN_NUM(index == UINT32_MAX ? -1 : (int)index);
|
2015-01-10 23:45:14 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_iterate)
|
2015-01-23 05:58:22 +01:00
|
|
|
{
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
|
|
|
|
|
// If we're starting the iteration, return the first index.
|
|
|
|
|
if (IS_NULL(args[1]))
|
|
|
|
|
{
|
|
|
|
|
if (string->length == 0) RETURN_FALSE;
|
|
|
|
|
RETURN_NUM(0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateInt(vm, args[1], "Iterator")) return PRIM_FIBER;
|
2015-01-23 05:58:22 +01:00
|
|
|
|
2015-02-25 06:56:33 +01:00
|
|
|
if (AS_NUM(args[1]) < 0) RETURN_FALSE;
|
|
|
|
|
uint32_t index = (uint32_t)AS_NUM(args[1]);
|
2015-01-23 05:58:22 +01:00
|
|
|
|
|
|
|
|
// Advance to the beginning of the next UTF-8 sequence.
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
index++;
|
2015-02-25 06:56:33 +01:00
|
|
|
if (index >= string->length) RETURN_FALSE;
|
2015-01-23 05:58:22 +01:00
|
|
|
} while ((string->value[index] & 0xc0) == 0x80);
|
|
|
|
|
|
|
|
|
|
RETURN_NUM(index);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-28 04:44:07 +01:00
|
|
|
DEF_PRIMITIVE(string_iterateByte)
|
|
|
|
|
{
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
|
|
|
|
|
// If we're starting the iteration, return the first index.
|
|
|
|
|
if (IS_NULL(args[1]))
|
|
|
|
|
{
|
|
|
|
|
if (string->length == 0) RETURN_FALSE;
|
|
|
|
|
RETURN_NUM(0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateInt(vm, args[1], "Iterator")) return PRIM_FIBER;
|
2015-03-28 04:44:07 +01:00
|
|
|
|
|
|
|
|
if (AS_NUM(args[1]) < 0) RETURN_FALSE;
|
|
|
|
|
uint32_t index = (uint32_t)AS_NUM(args[1]);
|
|
|
|
|
|
|
|
|
|
// Advance to the next byte.
|
|
|
|
|
index++;
|
|
|
|
|
if (index >= string->length) RETURN_FALSE;
|
|
|
|
|
|
|
|
|
|
RETURN_NUM(index);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_iteratorValue)
|
2015-01-23 05:58:22 +01:00
|
|
|
{
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
2015-09-30 07:57:03 +02:00
|
|
|
uint32_t index = validateIndex(vm, args[1], string->length, "Iterator");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == UINT32_MAX) return PRIM_FIBER;
|
2015-01-23 05:58:22 +01:00
|
|
|
|
|
|
|
|
RETURN_VAL(wrenStringCodePointAt(vm, string, index));
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_startsWith)
|
2015-01-10 23:45:14 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateString(vm, args[1], "Argument")) return PRIM_FIBER;
|
2015-01-10 23:45:14 +01:00
|
|
|
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
ObjString* search = AS_STRING(args[1]);
|
|
|
|
|
|
|
|
|
|
// Corner case, if the search string is longer than return false right away.
|
|
|
|
|
if (search->length > string->length) RETURN_FALSE;
|
|
|
|
|
|
|
|
|
|
RETURN_BOOL(memcmp(string->value, search->value, search->length) == 0);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_plus)
|
2013-10-31 15:04:44 +01:00
|
|
|
{
|
2015-09-30 16:32:39 +02:00
|
|
|
if (!validateString(vm, args[1], "Right operand")) return PRIM_FIBER;
|
2015-03-16 06:32:20 +01:00
|
|
|
RETURN_VAL(wrenStringFormat(vm, "@@", args[0], args[1]));
|
2013-10-31 15:04:44 +01:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:24:04 +01:00
|
|
|
DEF_PRIMITIVE(string_subscript)
|
2013-11-24 19:45:07 +01:00
|
|
|
{
|
|
|
|
|
ObjString* string = AS_STRING(args[0]);
|
|
|
|
|
|
2015-01-17 08:20:56 +01:00
|
|
|
if (IS_NUM(args[1]))
|
|
|
|
|
{
|
2015-09-30 07:57:03 +02:00
|
|
|
int index = validateIndex(vm, args[1], string->length, "Subscript");
|
2015-09-30 16:32:39 +02:00
|
|
|
if (index == -1) return PRIM_FIBER;
|
2015-01-17 08:20:56 +01:00
|
|
|
|
2015-01-23 01:38:03 +01:00
|
|
|
RETURN_VAL(wrenStringCodePointAt(vm, string, index));
|
2015-01-17 08:20:56 +01:00
|
|
|
}
|
2013-11-24 19:45:07 +01:00
|
|
|
|
2015-01-17 08:20:56 +01:00
|
|
|
if (!IS_RANGE(args[1]))
|
|
|
|
|
{
|
|
|
|
|
RETURN_ERROR("Subscript must be a number or a range.");
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-21 00:33:21 +01:00
|
|
|
int step;
|
2015-09-02 07:14:55 +02:00
|
|
|
uint32_t count = string->length;
|
2015-09-30 07:57:03 +02:00
|
|
|
int start = calculateRange(vm, AS_RANGE(args[1]), &count, &step);
|
2015-09-30 16:32:39 +02:00
|
|
|
if (start == -1) return PRIM_FIBER;
|
2015-01-17 08:20:56 +01:00
|
|
|
|
2015-09-02 07:14:55 +02:00
|
|
|
RETURN_VAL(wrenNewStringFromRange(vm, string, start, count, step));
|
2013-11-24 19:45:07 +01:00
|
|
|
}
|
|
|
|
|
|
2015-09-01 17:16:04 +02:00
|
|
|
DEF_PRIMITIVE(string_toString)
|
|
|
|
|
{
|
|
|
|
|
RETURN_VAL(args[0]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-15 16:46:09 +02:00
|
|
|
DEF_PRIMITIVE(system_clock)
|
|
|
|
|
{
|
|
|
|
|
RETURN_NUM((double)clock() / CLOCKS_PER_SEC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DEF_PRIMITIVE(system_writeString)
|
|
|
|
|
{
|
2015-09-16 08:01:43 +02:00
|
|
|
if (vm->config.writeFn != NULL)
|
|
|
|
|
{
|
|
|
|
|
vm->config.writeFn(vm, AS_CSTRING(args[1]));
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-15 16:46:09 +02:00
|
|
|
RETURN_VAL(args[1]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-03 17:00:55 +02:00
|
|
|
// Creates either the Object or Class class in the core library with [name].
|
2015-08-06 16:13:11 +02:00
|
|
|
static ObjClass* defineClass(WrenVM* vm, ObjModule* module, const char* name)
|
2013-11-26 16:52:37 +01:00
|
|
|
{
|
2015-03-16 06:32:20 +01:00
|
|
|
ObjString* nameString = AS_STRING(wrenStringFormat(vm, "$", name));
|
2015-01-21 16:56:06 +01:00
|
|
|
wrenPushRoot(vm, (Obj*)nameString);
|
2014-01-29 00:31:11 +01:00
|
|
|
|
2015-04-03 17:00:55 +02:00
|
|
|
ObjClass* classObj = wrenNewSingleClass(vm, 0, nameString);
|
|
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
wrenDefineVariable(vm, module, name, nameString->length, OBJ_VAL(classObj));
|
2014-01-29 00:31:11 +01:00
|
|
|
|
2015-01-21 16:56:06 +01:00
|
|
|
wrenPopRoot(vm);
|
2013-11-26 16:52:37 +01:00
|
|
|
return classObj;
|
|
|
|
|
}
|
feat: add `is` operator for type checking and refactor primitives registration
Add TOKEN_IS token and CODE_IS bytecode to support runtime type checking via the `is` keyword. Refactor primitive registration by replacing `registerPrimitives` with `loadCore`, which compiles a core library string to define built-in classes (Bool, Class, Function, Num, Null, String, IO) and then attaches primitive methods to them. Update Primitive typedef to remove unused numArgs parameter, and add findGlobal helper to retrieve globals by name. Include test files for class syntax, class instantiation, and the new `is` operator.
2013-11-08 02:07:32 +01:00
|
|
|
|
2013-11-28 17:00:55 +01:00
|
|
|
void wrenInitializeCore(WrenVM* vm)
|
2013-10-27 19:28:15 +01:00
|
|
|
{
|
2015-08-06 16:13:11 +02:00
|
|
|
ObjModule* coreModule = wrenGetCoreModule(vm);
|
2015-09-13 19:03:02 +02:00
|
|
|
|
2013-12-22 05:44:37 +01:00
|
|
|
// Define the root Object class. This has to be done a little specially
|
2015-05-01 16:55:28 +02:00
|
|
|
// because it has no superclass.
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->objectClass = defineClass(vm, coreModule, "Object");
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->objectClass, "!", object_not);
|
|
|
|
|
PRIMITIVE(vm->objectClass, "==(_)", object_eqeq);
|
|
|
|
|
PRIMITIVE(vm->objectClass, "!=(_)", object_bangeq);
|
2015-06-19 16:58:07 +02:00
|
|
|
PRIMITIVE(vm->objectClass, "is(_)", object_is);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->objectClass, "toString", object_toString);
|
|
|
|
|
PRIMITIVE(vm->objectClass, "type", object_type);
|
2013-11-26 16:52:37 +01:00
|
|
|
|
2015-05-01 16:55:28 +02:00
|
|
|
// Now we can define Class, which is a subclass of Object.
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->classClass = defineClass(vm, coreModule, "Class");
|
2014-01-04 20:08:31 +01:00
|
|
|
wrenBindSuperclass(vm, vm->classClass, vm->objectClass);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->classClass, "name", class_name);
|
2015-03-14 17:48:45 +01:00
|
|
|
PRIMITIVE(vm->classClass, "supertype", class_supertype);
|
2015-06-30 16:39:43 +02:00
|
|
|
PRIMITIVE(vm->classClass, "toString", class_toString);
|
2014-04-03 02:42:30 +02:00
|
|
|
|
2015-05-01 16:55:28 +02:00
|
|
|
// Finally, we can define Object's metaclass which is a subclass of Class.
|
2015-08-06 16:13:11 +02:00
|
|
|
ObjClass* objectMetaclass = defineClass(vm, coreModule, "Object metaclass");
|
2015-05-01 16:55:28 +02:00
|
|
|
|
|
|
|
|
// Wire up the metaclass relationships now that all three classes are built.
|
|
|
|
|
vm->objectClass->obj.classObj = objectMetaclass;
|
|
|
|
|
objectMetaclass->obj.classObj = vm->classClass;
|
|
|
|
|
vm->classClass->obj.classObj = vm->classClass;
|
|
|
|
|
|
|
|
|
|
// Do this after wiring up the metaclasses so objectMetaclass doesn't get
|
|
|
|
|
// collected.
|
|
|
|
|
wrenBindSuperclass(vm, objectMetaclass, vm->classClass);
|
|
|
|
|
|
|
|
|
|
PRIMITIVE(objectMetaclass, "same(_,_)", object_same);
|
|
|
|
|
|
2013-12-22 05:44:37 +01:00
|
|
|
// The core class diagram ends up looking like this, where single lines point
|
|
|
|
|
// to a class's superclass, and double lines point to its metaclass:
|
|
|
|
|
//
|
2015-05-01 16:55:28 +02:00
|
|
|
// .------------------------------------. .====.
|
|
|
|
|
// | .---------------. | # #
|
|
|
|
|
// v | v | v #
|
|
|
|
|
// .---------. .-------------------. .-------. #
|
|
|
|
|
// | Object |==>| Object metaclass |==>| Class |=="
|
|
|
|
|
// '---------' '-------------------' '-------'
|
|
|
|
|
// ^ ^ ^ ^ ^
|
|
|
|
|
// | .--------------' # | #
|
|
|
|
|
// | | # | #
|
|
|
|
|
// .---------. .-------------------. # | # -.
|
|
|
|
|
// | Base |==>| Base metaclass |======" | # |
|
|
|
|
|
// '---------' '-------------------' | # |
|
|
|
|
|
// ^ | # |
|
|
|
|
|
// | .------------------' # | Example classes
|
|
|
|
|
// | | # |
|
|
|
|
|
// .---------. .-------------------. # |
|
|
|
|
|
// | Derived |==>| Derived metaclass |==========" |
|
|
|
|
|
// '---------' '-------------------' -'
|
2013-12-22 05:44:37 +01:00
|
|
|
|
2015-04-03 17:00:55 +02:00
|
|
|
// The rest of the classes can now be defined normally.
|
2015-09-13 19:03:02 +02:00
|
|
|
wrenInterpret(vm, "", coreModuleSource);
|
2015-04-03 17:00:55 +02:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->boolClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Bool"));
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->boolClass, "toString", bool_toString);
|
|
|
|
|
PRIMITIVE(vm->boolClass, "!", bool_not);
|
2013-11-04 06:38:58 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->fiberClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Fiber"));
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->fiberClass->obj.classObj, "new(_)", fiber_new);
|
|
|
|
|
PRIMITIVE(vm->fiberClass->obj.classObj, "abort(_)", fiber_abort);
|
2015-03-07 21:32:11 +01:00
|
|
|
PRIMITIVE(vm->fiberClass->obj.classObj, "current", fiber_current);
|
2015-08-31 07:15:37 +02:00
|
|
|
PRIMITIVE(vm->fiberClass->obj.classObj, "suspend()", fiber_suspend);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->fiberClass->obj.classObj, "yield()", fiber_yield);
|
|
|
|
|
PRIMITIVE(vm->fiberClass->obj.classObj, "yield(_)", fiber_yield1);
|
|
|
|
|
PRIMITIVE(vm->fiberClass, "call()", fiber_call);
|
|
|
|
|
PRIMITIVE(vm->fiberClass, "call(_)", fiber_call1);
|
|
|
|
|
PRIMITIVE(vm->fiberClass, "error", fiber_error);
|
|
|
|
|
PRIMITIVE(vm->fiberClass, "isDone", fiber_isDone);
|
2015-08-31 07:15:37 +02:00
|
|
|
PRIMITIVE(vm->fiberClass, "transfer()", fiber_transfer);
|
|
|
|
|
PRIMITIVE(vm->fiberClass, "transfer(_)", fiber_transfer1);
|
2015-09-30 07:57:03 +02:00
|
|
|
PRIMITIVE(vm->fiberClass, "transferError(_)", fiber_transferError);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->fiberClass, "try()", fiber_try);
|
2014-01-04 20:08:31 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->fnClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Fn"));
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->fnClass->obj.classObj, "new(_)", fn_new);
|
|
|
|
|
|
|
|
|
|
PRIMITIVE(vm->fnClass, "arity", fn_arity);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call()", fn_call0);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_)", fn_call1);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_)", fn_call2);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_)", fn_call3);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_)", fn_call4);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_)", fn_call5);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_)", fn_call6);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_)", fn_call7);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_)", fn_call8);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_)", fn_call9);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_)", fn_call10);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_)", fn_call11);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_)", fn_call12);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call13);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call14);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call15);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "call(_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_)", fn_call16);
|
|
|
|
|
PRIMITIVE(vm->fnClass, "toString", fn_toString);
|
2013-11-06 15:52:28 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->nullClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Null"));
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->nullClass, "!", null_not);
|
|
|
|
|
PRIMITIVE(vm->nullClass, "toString", null_toString);
|
feat: add `is` operator for type checking and refactor primitives registration
Add TOKEN_IS token and CODE_IS bytecode to support runtime type checking via the `is` keyword. Refactor primitive registration by replacing `registerPrimitives` with `loadCore`, which compiles a core library string to define built-in classes (Bool, Class, Function, Num, Null, String, IO) and then attaches primitive methods to them. Update Primitive typedef to remove unused numArgs parameter, and add findGlobal helper to retrieve globals by name. Include test files for class syntax, class instantiation, and the new `is` operator.
2013-11-08 02:07:32 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->numClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Num"));
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->numClass->obj.classObj, "fromString(_)", num_fromString);
|
2015-03-19 21:12:50 +01:00
|
|
|
PRIMITIVE(vm->numClass->obj.classObj, "pi", num_pi);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->numClass, "-(_)", num_minus);
|
|
|
|
|
PRIMITIVE(vm->numClass, "+(_)", num_plus);
|
|
|
|
|
PRIMITIVE(vm->numClass, "*(_)", num_multiply);
|
|
|
|
|
PRIMITIVE(vm->numClass, "/(_)", num_divide);
|
|
|
|
|
PRIMITIVE(vm->numClass, "<(_)", num_lt);
|
|
|
|
|
PRIMITIVE(vm->numClass, ">(_)", num_gt);
|
|
|
|
|
PRIMITIVE(vm->numClass, "<=(_)", num_lte);
|
|
|
|
|
PRIMITIVE(vm->numClass, ">=(_)", num_gte);
|
|
|
|
|
PRIMITIVE(vm->numClass, "&(_)", num_bitwiseAnd);
|
|
|
|
|
PRIMITIVE(vm->numClass, "|(_)", num_bitwiseOr);
|
|
|
|
|
PRIMITIVE(vm->numClass, "^(_)", num_bitwiseXor);
|
|
|
|
|
PRIMITIVE(vm->numClass, "<<(_)", num_bitwiseLeftShift);
|
|
|
|
|
PRIMITIVE(vm->numClass, ">>(_)", num_bitwiseRightShift);
|
|
|
|
|
PRIMITIVE(vm->numClass, "abs", num_abs);
|
2015-03-14 14:52:16 +01:00
|
|
|
PRIMITIVE(vm->numClass, "acos", num_acos);
|
|
|
|
|
PRIMITIVE(vm->numClass, "asin", num_asin);
|
|
|
|
|
PRIMITIVE(vm->numClass, "atan", num_atan);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->numClass, "ceil", num_ceil);
|
|
|
|
|
PRIMITIVE(vm->numClass, "cos", num_cos);
|
|
|
|
|
PRIMITIVE(vm->numClass, "floor", num_floor);
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
PRIMITIVE(vm->numClass, "-", num_negate);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->numClass, "sin", num_sin);
|
|
|
|
|
PRIMITIVE(vm->numClass, "sqrt", num_sqrt);
|
2015-03-14 14:40:23 +01:00
|
|
|
PRIMITIVE(vm->numClass, "tan", num_tan);
|
refactor: remove inline local variable declarations in list primitives and delete redundant math primitives from wren_core.c
Consolidate temporary variable usage in list_add, list_count, and list_iterate by directly inlining AS_LIST/AS_NUM calls. Remove the entire block of num_abs, num_acos, num_asin, num_atan, num_atan2, num_ceil, num_cos, num_floor, and num_fraction primitive definitions to eliminate boilerplate.
2015-03-21 22:57:43 +01:00
|
|
|
PRIMITIVE(vm->numClass, "%(_)", num_mod);
|
|
|
|
|
PRIMITIVE(vm->numClass, "~", num_bitwiseNot);
|
|
|
|
|
PRIMITIVE(vm->numClass, "..(_)", num_dotDot);
|
|
|
|
|
PRIMITIVE(vm->numClass, "...(_)", num_dotDotDot);
|
|
|
|
|
PRIMITIVE(vm->numClass, "atan(_)", num_atan2);
|
|
|
|
|
PRIMITIVE(vm->numClass, "fraction", num_fraction);
|
|
|
|
|
PRIMITIVE(vm->numClass, "isNan", num_isNan);
|
|
|
|
|
PRIMITIVE(vm->numClass, "sign", num_sign);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->numClass, "toString", num_toString);
|
2015-03-04 00:29:19 +01:00
|
|
|
PRIMITIVE(vm->numClass, "truncate", num_truncate);
|
2015-01-16 06:50:01 +01:00
|
|
|
|
|
|
|
|
// These are defined just so that 0 and -0 are equal, which is specified by
|
|
|
|
|
// IEEE 754 even though they have different bit representations.
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->numClass, "==(_)", num_eqeq);
|
|
|
|
|
PRIMITIVE(vm->numClass, "!=(_)", num_bangeq);
|
feat: replace Wren Range class with native C object for performance
Remove the Range class definition from corelib.wren and implement it as a native C type with ObjRange struct, adding native methods for from, to, min, max, iterate, and iteratorValue. Move range operator handling from Num class to native num_dotDot and num_dotDotDot functions. Update VM to support OBJ_RANGE type in marking, printing, and type checking. Add comprehensive test suite for range operations including ordered, backwards, and exclusive ranges.
2014-01-20 17:45:15 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->stringClass = AS_CLASS(wrenFindVariable(vm, coreModule, "String"));
|
2015-03-27 15:43:36 +01:00
|
|
|
PRIMITIVE(vm->stringClass->obj.classObj, "fromCodePoint(_)", string_fromCodePoint);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->stringClass, "+(_)", string_plus);
|
|
|
|
|
PRIMITIVE(vm->stringClass, "[_]", string_subscript);
|
2015-09-11 08:52:18 +02:00
|
|
|
PRIMITIVE(vm->stringClass, "byteAt_(_)", string_byteAt);
|
|
|
|
|
PRIMITIVE(vm->stringClass, "byteCount_", string_byteCount);
|
2015-09-11 16:56:01 +02:00
|
|
|
PRIMITIVE(vm->stringClass, "codePointAt_(_)", string_codePointAt);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->stringClass, "contains(_)", string_contains);
|
|
|
|
|
PRIMITIVE(vm->stringClass, "endsWith(_)", string_endsWith);
|
|
|
|
|
PRIMITIVE(vm->stringClass, "indexOf(_)", string_indexOf);
|
|
|
|
|
PRIMITIVE(vm->stringClass, "iterate(_)", string_iterate);
|
2015-03-28 04:44:07 +01:00
|
|
|
PRIMITIVE(vm->stringClass, "iterateByte_(_)", string_iterateByte);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->stringClass, "iteratorValue(_)", string_iteratorValue);
|
|
|
|
|
PRIMITIVE(vm->stringClass, "startsWith(_)", string_startsWith);
|
2015-09-01 17:16:04 +02:00
|
|
|
PRIMITIVE(vm->stringClass, "toString", string_toString);
|
2013-10-28 06:45:40 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->listClass = AS_CLASS(wrenFindVariable(vm, coreModule, "List"));
|
2015-07-10 18:18:22 +02:00
|
|
|
PRIMITIVE(vm->listClass->obj.classObj, "new()", list_new);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->listClass, "[_]", list_subscript);
|
|
|
|
|
PRIMITIVE(vm->listClass, "[_]=(_)", list_subscriptSetter);
|
|
|
|
|
PRIMITIVE(vm->listClass, "add(_)", list_add);
|
|
|
|
|
PRIMITIVE(vm->listClass, "clear()", list_clear);
|
|
|
|
|
PRIMITIVE(vm->listClass, "count", list_count);
|
|
|
|
|
PRIMITIVE(vm->listClass, "insert(_,_)", list_insert);
|
|
|
|
|
PRIMITIVE(vm->listClass, "iterate(_)", list_iterate);
|
|
|
|
|
PRIMITIVE(vm->listClass, "iteratorValue(_)", list_iteratorValue);
|
|
|
|
|
PRIMITIVE(vm->listClass, "removeAt(_)", list_removeAt);
|
2013-12-22 20:50:00 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->mapClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Map"));
|
2015-07-10 18:18:22 +02:00
|
|
|
PRIMITIVE(vm->mapClass->obj.classObj, "new()", map_new);
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->mapClass, "[_]", map_subscript);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "[_]=(_)", map_subscriptSetter);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "clear()", map_clear);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "containsKey(_)", map_containsKey);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "count", map_count);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "remove(_)", map_remove);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "iterate_(_)", map_iterate);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "keyIteratorValue_(_)", map_keyIteratorValue);
|
|
|
|
|
PRIMITIVE(vm->mapClass, "valueIteratorValue_(_)", map_valueIteratorValue);
|
feat: add initial Map class with hash table, subscript, and count support
Implement the core Map data structure in Wren, including the ObjMap type with
hash table storage, native methods for instantiation, subscript get/set, and
count. Add Map class declaration to core.wren with a basic toString stub.
Introduce MapEntry struct and hash table growth logic with configurable load
factor. Add test files for map creation, count tracking, key type support
(including null, bool, num, string, range, and class keys), and growth
behavior. Refactor list capacity constants into shared MIN_CAPACITY and
GROW_FACTOR macros. Change object equality operators to use wrenValuesSame
instead of wrenValuesEqual.
2015-01-25 07:27:35 +01:00
|
|
|
|
2015-08-06 16:13:11 +02:00
|
|
|
vm->rangeClass = AS_CLASS(wrenFindVariable(vm, coreModule, "Range"));
|
2015-03-02 16:24:04 +01:00
|
|
|
PRIMITIVE(vm->rangeClass, "from", range_from);
|
|
|
|
|
PRIMITIVE(vm->rangeClass, "to", range_to);
|
|
|
|
|
PRIMITIVE(vm->rangeClass, "min", range_min);
|
|
|
|
|
PRIMITIVE(vm->rangeClass, "max", range_max);
|
|
|
|
|
PRIMITIVE(vm->rangeClass, "isInclusive", range_isInclusive);
|
|
|
|
|
PRIMITIVE(vm->rangeClass, "iterate(_)", range_iterate);
|
|
|
|
|
PRIMITIVE(vm->rangeClass, "iteratorValue(_)", range_iteratorValue);
|
|
|
|
|
PRIMITIVE(vm->rangeClass, "toString", range_toString);
|
2015-01-23 05:58:22 +01:00
|
|
|
|
2015-09-15 16:46:09 +02:00
|
|
|
ObjClass* systemClass = AS_CLASS(wrenFindVariable(vm, coreModule, "System"));
|
|
|
|
|
PRIMITIVE(systemClass->obj.classObj, "clock", system_clock);
|
|
|
|
|
PRIMITIVE(systemClass->obj.classObj, "writeString_(_)", system_writeString);
|
|
|
|
|
|
2015-01-23 05:58:22 +01:00
|
|
|
// While bootstrapping the core types and running the core library, a number
|
2015-02-17 16:21:51 +01:00
|
|
|
// of string objects have been created, many of which were instantiated
|
|
|
|
|
// before stringClass was stored in the VM. Some of them *must* be created
|
|
|
|
|
// first -- the ObjClass for string itself has a reference to the ObjString
|
|
|
|
|
// for its name.
|
2015-01-23 05:58:22 +01:00
|
|
|
//
|
2015-02-17 16:21:51 +01:00
|
|
|
// These all currently have a NULL classObj pointer, so go back and assign
|
|
|
|
|
// them now that the string class is known.
|
2015-01-23 05:58:22 +01:00
|
|
|
for (Obj* obj = vm->first; obj != NULL; obj = obj->next)
|
|
|
|
|
{
|
|
|
|
|
if (obj->type == OBJ_STRING) obj->classObj = vm->stringClass;
|
|
|
|
|
}
|
2013-11-06 00:40:21 +01:00
|
|
|
}
|