Пример #1
0
static void defineMethod(WrenVM* vm, const char* className,
                         const char* methodName, int numParams,
                         WrenForeignMethodFn methodFn, bool isStatic)
{
  ASSERT(className != NULL, "Must provide class name.");

  int length = (int)strlen(methodName);
  ASSERT(methodName != NULL, "Must provide method name.");
  ASSERT(strlen(methodName) < MAX_METHOD_NAME, "Method name too long.");

  ASSERT(numParams >= 0, "numParams cannot be negative.");
  ASSERT(numParams <= MAX_PARAMETERS, "Too many parameters.");

  ASSERT(methodFn != NULL, "Must provide method function.");

  // Find or create the class to bind the method to.
  int classSymbol = wrenSymbolTableFind(&vm->globalNames,
                               className, strlen(className));
  ObjClass* classObj;

  if (classSymbol != -1)
  {
    // TODO: Handle name is not class.
    classObj = AS_CLASS(vm->globals.data[classSymbol]);
  }
  else
  {
    // The class doesn't already exist, so create it.
    size_t length = strlen(className);
    ObjString* nameString = AS_STRING(wrenNewString(vm, className, length));

    WREN_PIN(vm, nameString);

    // TODO: Allow passing in name for superclass?
    classObj = wrenNewClass(vm, vm->objectClass, 0, nameString);
    wrenDefineGlobal(vm, className, length, OBJ_VAL(classObj));

    WREN_UNPIN(vm);
  }

  // Create a name for the method, including its arity.
  char name[MAX_METHOD_SIGNATURE];
  strncpy(name, methodName, length);
  for (int i = 0; i < numParams; i++)
  {
    name[length++] = ' ';
  }
  name[length] = '\0';

  // Bind the method.
  int methodSymbol = wrenSymbolTableEnsure(vm, &vm->methodNames, name, length);

  Method method;
  method.type = METHOD_FOREIGN;
  method.fn.foreign = methodFn;

  if (isStatic) classObj = classObj->obj.classObj;

  wrenBindMethod(vm, classObj, methodSymbol, method);
}
Пример #2
0
// Defines one of the overloads of the special "call(...)" method on Fn.
//
// These methods have their own unique method type to handle pushing the
// function onto the callstack and checking its arity.
static void fnCall(WrenVM* vm, const char* signature)
{
  int symbol = wrenSymbolTableEnsure(vm, &vm->methodNames, signature,
                                     strlen(signature));
  Method method;
  method.type = METHOD_FN_CALL;
  wrenBindMethod(vm, vm->fnClass, symbol, method);
}
Пример #3
0
void wrenBindSuperclass(WrenVM* vm, ObjClass* subclass, ObjClass* superclass)
{
  ASSERT(superclass != NULL, "Must have superclass.");

  subclass->superclass = superclass;

  // Include the superclass in the total number of fields.
  subclass->numFields += superclass->numFields;

  // Inherit methods from its superclass.
  for (int i = 0; i < superclass->methods.count; i++)
  {
    wrenBindMethod(vm, subclass, i, superclass->methods.data[i]);
  }
}
Пример #4
0
static void bindMethod(WrenVM* vm, int methodType, int symbol,
                       ObjClass* classObj, Value methodValue)
{
  ObjFn* methodFn = IS_FN(methodValue) ? AS_FN(methodValue)
                                       : AS_CLOSURE(methodValue)->fn;

  // Methods are always bound against the class, and not the metaclass, even
  // for static methods, so that constructors (which are static) get bound like
  // instance methods.
  wrenBindMethodCode(classObj, methodFn);

  Method method;
  method.type = METHOD_BLOCK;
  method.fn.obj = AS_OBJ(methodValue);

  if (methodType == CODE_METHOD_STATIC)
  {
    classObj = classObj->obj.classObj;
  }

  wrenBindMethod(vm, classObj, symbol, method);
}
Пример #5
0
void wrenBindSuperclass(WrenVM* vm, ObjClass* subclass, ObjClass* superclass)
{
  ASSERT(superclass != NULL, "Must have superclass.");

  subclass->superclass = superclass;

  // Include the superclass in the total number of fields.
  if (subclass->numFields != -1)
  {
    subclass->numFields += superclass->numFields;
  }
  else
  {
    ASSERT(superclass->numFields == 0,
           "A foreign class cannot inherit from a class with fields.");
  }

  // Inherit methods from its superclass.
  for (int i = 0; i < superclass->methods.count; i++)
  {
    wrenBindMethod(vm, subclass, i, superclass->methods.data[i]);
  }
}