Ejemplo n.º 1
0
bool validateNum(WrenVM* vm, Value arg, const char* argName)
{
  if (IS_NUM(arg)) return true;

  vm->fiber->error = wrenStringFormat(vm, "$ must be a number.", argName);
  return false;
}
Ejemplo n.º 2
0
bool validateString(WrenVM* vm, Value arg, const char* argName)
{
  if (IS_STRING(arg)) return true;

  vm->fiber->error = wrenStringFormat(vm, "$ must be a string.", argName);
  return false;
}
Ejemplo n.º 3
0
bool validateIntValue(WrenVM* vm, double value, const char* argName)
{
  if (trunc(value) == value) return true;

  vm->fiber->error = wrenStringFormat(vm, "$ must be an integer.", argName);
  return false;
}
Ejemplo n.º 4
0
bool validateString(WrenVM* vm, Value* args, int index, const char* argName)
{
  if (IS_STRING(args[index])) return true;

  args[0] = wrenStringFormat(vm, "$ must be a string.", argName);
  return false;
}
Ejemplo n.º 5
0
bool validateFn(WrenVM* vm, Value arg, const char* argName)
{
  if (IS_FN(arg) || IS_CLOSURE(arg)) return true;

  vm->fiber->error = wrenStringFormat(vm, "$ must be a function.", argName);
  return false;
}
Ejemplo n.º 6
0
bool validateFn(WrenVM* vm, Value* args, int index, const char* argName)
{
  if (IS_FN(args[index]) || IS_CLOSURE(args[index])) return true;

  args[0] = wrenStringFormat(vm, "$ must be a function.", argName);
  return false;
}
Ejemplo n.º 7
0
bool validateNum(WrenVM* vm, Value* args, int index, const char* argName)
{
  if (IS_NUM(args[index])) return true;

  args[0] = wrenStringFormat(vm, "$ must be a number.", argName);
  return false;
}
Ejemplo n.º 8
0
ObjClass* wrenNewClass(WrenVM* vm, ObjClass* superclass, int numFields,
                       ObjString* name)
{
  // Create the metaclass.
  Value metaclassName = wrenStringFormat(vm, "@ metaclass", OBJ_VAL(name));
  wrenPushRoot(vm, AS_OBJ(metaclassName));

  ObjClass* metaclass = wrenNewSingleClass(vm, 0, AS_STRING(metaclassName));
  metaclass->obj.classObj = vm->classClass;

  wrenPopRoot(vm);

  // Make sure the metaclass isn't collected when we allocate the class.
  wrenPushRoot(vm, (Obj*)metaclass);

  // Metaclasses always inherit Class and do not parallel the non-metaclass
  // hierarchy.
  wrenBindSuperclass(vm, metaclass, vm->classClass);

  ObjClass* classObj = wrenNewSingleClass(vm, numFields, name);

  // Make sure the class isn't collected while the inherited methods are being
  // bound.
  wrenPushRoot(vm, (Obj*)classObj);

  classObj->obj.classObj = metaclass;
  wrenBindSuperclass(vm, classObj, superclass);

  wrenPopRoot(vm);
  wrenPopRoot(vm);

  return classObj;
}
Ejemplo n.º 9
0
bool validateIntValue(WrenVM* vm, Value* args, double value,
                      const char* argName)
{
  if (trunc(value) == value) return true;

  args[0] = wrenStringFormat(vm, "$ must be an integer.", argName);
  return false;
}
Ejemplo n.º 10
0
// 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)
{
  if (isCall)
  {
    if (fiber->caller != NULL) RETURN_ERROR("Fiber has already been called.");
    
    // Remember who ran it.
    fiber->caller = vm->fiber;
  }
  else
  {
    // Edge case: If we are transferring to ourself, immediately return the
    // value. We can't treat this like an actual transfer since when we set the
    // return below, it would overwrite the fiber being transferred to.
    if (fiber == vm->fiber) RETURN_VAL(hasValue ? args[1] : NULL_VAL);
  }
  
  if (fiber->numFrames == 0)
  {
    args[0] = wrenStringFormat(vm, "Cannot $ a finished fiber.",
                               isCall ? "call" : "transfer to");
    return PRIM_ERROR;
  }
  
  if (fiber->error != NULL)
  {
    args[0] = wrenStringFormat(vm, "Cannot $ an aborted fiber.",
                               isCall ? "call" : "transfer to");
    return PRIM_ERROR;
  }
  
  // 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--;

  // If the fiber was paused, make yield() or transfer() return the result.
  if (fiber->stackTop > fiber->stack)
  {
    *(fiber->stackTop - 1) = hasValue ? args[1] : NULL_VAL;
  }
  
  return PRIM_RUN_FIBER;
}
Ejemplo n.º 11
0
// Creates either the Object or Class class in the core module with [name].
static ObjClass* defineClass(WrenVM* vm, ObjModule* module, const char* name)
{
  ObjString* nameString = AS_STRING(wrenStringFormat(vm, "$", name));
  wrenPushRoot(vm, (Obj*)nameString);

  ObjClass* classObj = wrenNewSingleClass(vm, 0, nameString);

  wrenDefineVariable(vm, module, name, nameString->length, OBJ_VAL(classObj));

  wrenPopRoot(vm);
  return classObj;
}
Ejemplo n.º 12
0
// Validates that [value] is an integer within `[0, count)`. Also allows
// negative indices which map backwards from the end. Returns the valid positive
// index value. If invalid, reports an error and returns `UINT32_MAX`.
static uint32_t validateIndexValue(WrenVM* vm, uint32_t count, double value,
                                   const char* argName)
{
  if (!validateIntValue(vm, value, argName)) return UINT32_MAX;
  
  // Negative indices count from the end.
  if (value < 0) value = count + value;
  
  // Check bounds.
  if (value >= 0 && value < count) return (uint32_t)value;
  
  vm->fiber->error = wrenStringFormat(vm, "$ out of bounds.", argName);
  return UINT32_MAX;
}