int prTempoClock_Sched(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; double delta, beats; int err; TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } if (!SlotEq(&g->thread->clock, a)) { beats = clock->ElapsedBeats(); //post("shouldn't call TempoClock-sched from a different clock. Use schedAbs.\n"); //return errFailed; } else { err = slotDoubleVal(&g->thread->beats, &beats); if (err) return errNone; // return nil OK, just don't schedule } err = slotDoubleVal(b, &delta); if (err) return errNone; // return nil OK, just don't schedule beats += delta; if (beats == dInfinity) return errNone; // return nil OK, just don't schedule clock->Add(beats, c); return errNone; }
bool identDict_lookupNonNil(PyrObject *dict, PyrSlot *key, int hash, PyrSlot *result) { again: PyrSlot *dictslots = dict->slots; PyrSlot *arraySlot = dictslots + ivxIdentDict_array; if (isKindOfSlot(arraySlot, class_array)) { PyrObject *array = slotRawObject(arraySlot); int index = arrayAtIdentityHashInPairsWithHash(array, key, hash); if (SlotEq(key, array->slots + index)) { slotCopy(result,&array->slots[index + 1]); return true; } } PyrClass *identDictClass = s_identitydictionary->u.classobj; PyrSlot *parentSlot = dictslots + ivxIdentDict_parent; PyrSlot * protoSlot = dictslots + ivxIdentDict_proto; if (isKindOfSlot(parentSlot, identDictClass)) { if (isKindOfSlot(protoSlot, identDictClass)) { // recursive call. if (identDict_lookupNonNil(slotRawObject(protoSlot), key, hash, result)) return true; } dict = slotRawObject(parentSlot); goto again; // tail call } else { if (isKindOfSlot(protoSlot, identDictClass)) { dict = slotRawObject(protoSlot); goto again; // tail call } } return false; }
int arrayAtIdentityHashInPairsWithHash(PyrObject *array, PyrSlot *key, int hash) { PyrSlot *slots, *test; unsigned int i, start, end, maxHash; maxHash = array->size >> 1; start = (hash % maxHash) << 1; end = array->size; slots = array->slots; for (i=start; i<end; i+=2) { test = slots + i; if (IsNil(test) || SlotEq(test, key)) return i; } end = start - 2; for (i=0; i<=end; i+=2) { test = slots + i; if (IsNil(test) || SlotEq(test, key)) return i; } return -2; }
int arrayAtIdentityHash(PyrObject *array, PyrSlot *key) { PyrSlot *slots, *test; unsigned int i, start, end, hash, maxHash; hash = calcHash(key); maxHash = array->size; start = hash % maxHash; end = array->size; slots = array->slots; for (i=start; i<end; i++) { test = slots + i; if (IsNil(test) || SlotEq(test, key)) return i; } end = start - 1; for (i=0; i<=end; i++) { test = slots + i; if (IsNil(test) || SlotEq(test, key)) return i; } return -1; }
int prTempoClock_Beats(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp; double beats, seconds; if (SlotEq(&g->thread->clock, a)) { int err = slotDoubleVal(&g->thread->beats, &beats); if (err) return errWrongType; } else { TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } int err = slotDoubleVal(&g->thread->seconds, &seconds); if (err) return errWrongType; beats = clock->SecsToBeats(seconds); } SetFloat(a, beats); return errNone; }