IO_METHOD(IoSeq, replaceMap) { /*doc Sequence replaceMap(aMap) In the receiver, the keys of aMap replaced with its values. Returns self. */ IoMap *map = IoMessage_locals_mapArgAt_(m, locals, 0); UArray *ba = DATA(self); IO_ASSERT_NOT_SYMBOL(self); PHASH_FOREACH(IoMap_rawHash(map), k, v, { IoSymbol *subSeq = k; IoSymbol *otherSeq = v; if (ISSEQ(otherSeq)) { UArray_replace_with_(ba, DATA(subSeq), DATA(otherSeq)); } else { IoState_error_(IOSTATE, m, "argument 0 to method '%s' must be a Map with Sequence values, not '%s'", CSTRING(IoMessage_name(m)), IoObject_name(otherSeq)); } } );
IoObject *IoDBI_initWithDriversPath(IoDBI *self, IoObject *locals, IoMessage *m) { /*doc DBI initWithDriversPath Initialize the DBI environment with the specified libdbi driver path. */ IoObject *dir = IoMessage_locals_valueArgAt_(m, locals, 0); if (ISSYMBOL(dir)) { DATA(self)->driverCount = dbi_initialize(CSTRING(dir)); } else { IoState_error_(IOSTATE, m, "argument 0 to method '%s' must be a Symbol, not a '%s'\n", CSTRING(IoMessage_name(m)), IoObject_name(dir)); } if (DATA(self)->driverCount == -1) { IoState_error_(IOSTATE, m, "*** IoDBI error during dbi_initialize\n"); } else { DATA(self)->didInit = 1; } return IONUMBER(DATA(self)->driverCount); }
IoObject *IoDBI_with(IoDBI *self, IoObject *locals, IoMessage *m) { //doc DBI with(driverName) Get a new connection with the given driver. IoObject *name = IoMessage_locals_valueArgAt_(m, locals, 0); if (!ISSYMBOL(name)) { IoState_error_(IOSTATE, m, "argument 0 to method '%s' must be a Symbol, not a '%s'\n", CSTRING(IoMessage_name(m)), IoObject_name(name)); return IONIL(self); } if (DATA(self)->didInit != 1) { IoDBI_init(self, locals, m); } dbi_conn c = dbi_conn_new(CSTRING(name)); if (c == NULL) { IoState_error_(IOSTATE, m, "libdbi error during dbi_conn_new\n"); return IONIL(self); } return IoDBIConn_new(IOSTATE, c); }
void IoMessage_opShuffle_(IoMessage *self) { if (IoObject_rawGetSlot_(self, IOSTATE->opShuffleSymbol) && IoMessage_name(self) != IOSTATE->noShufflingSymbol) { IoMessage_locals_performOn_(IOSTATE->opShuffleMessage, IOSTATE->lobby, self); } }
static void IoAssertNotSymbol(IoSeq *self, IoMessage *m) { if (ISSYMBOL(self)) { IoState_error_(IOSTATE, m, "'%s' cannot be called on an immutable Sequence", CSTRING(IoMessage_name(m))); } }
IO_METHOD(IoNumber, repeat) { /*doc Number repeat(optionalIndex, expression) Evaluates message a number of times that corresponds to the receivers integer value. This is significantly faster than a for() or while() loop. */ IoMessage_assertArgCount_receiver_(m, 1, self); { IoState *state = IOSTATE; IoSymbol *indexSlotName; IoMessage *doMessage; double i, max = CNUMBER(self); IoObject *result = IONIL(self); if(IoMessage_argCount(m) > 1) { indexSlotName = IoMessage_name(IoMessage_rawArgAt_(m, 0)); doMessage = IoMessage_rawArgAt_(m, 1); } else { indexSlotName = 0; doMessage = IoMessage_rawArgAt_(m, 0); } IoState_pushRetainPool(state); for (i = 0; i < max; i ++) { /* if (result != locals && result != self) { IoState_immediatelyFreeIfUnreferenced_(state, result); } */ IoState_clearTopPool(state); if (indexSlotName) { IoObject_setSlot_to_(locals, indexSlotName, IONUMBER(i)); } result = IoMessage_locals_performOn_(doMessage, locals, locals); if (IoState_handleStatus(IOSTATE)) { break; } } IoState_popRetainPoolExceptFor_(IOSTATE, result); return result; } }
void Level_finish(Level *self) { if (self->message) { IoMessage_rawSetNext_(self->message, NULL); // Remove extra () we added in for operators, but do not need any more if ( IoMessage_argCount(self->message) == 1 ) { IoMessage *arg = IoMessage_rawArgAt_(self->message, 0); if ( IoSeq_rawSize(IoMessage_name(arg)) == 0 && IoMessage_argCount(arg) == 1 && IoMessage_rawNext(arg) == NULL ) { List_copy_(IoMessage_rawArgList(self->message), IoMessage_rawArgList(arg)); List_removeAll(IoMessage_rawArgList(arg)); } } } self->type = UNUSED; }
int IoMessage_rawIsEOL(IoMessage *self) { return IoMessage_name(self) == IOSTATE->semicolonSymbol; }
void Levels_attach(Levels *self, IoMessage *msg, List *expressions) { // TODO clean up this method. IoState *state = IoObject_state(msg); IoSymbol *messageSymbol = IoMessage_name(msg); char *messageName = CSTRING(messageSymbol); int precedence = Levels_levelForOp(self, messageName, messageSymbol, msg); int msgArgCount = IoMessage_argCount(msg); /* // o a := b c ; d becomes o setSlot("a", b c) ; d // // a attaching // := msg // b c msg->next */ if (Levels_isAssignOperator(self, messageSymbol)) { Level *currentLevel = Levels_currentLevel(self); IoMessage *attaching = currentLevel->message; IoSymbol *setSlotName; if (attaching == NULL) // := b ; { // Could be handled as, message(:= 42) -> setSlot(nil, 42) IoState_error_(state, msg, "compile error: %s requires a symbol to its left.", messageName); return; } if (IoMessage_argCount(attaching) > 0) // a(1,2,3) := b ; { IoState_error_(state, msg, "compile error: The symbol to the left of %s cannot have arguments.", messageName); return; } if (msgArgCount > 1) // setSlot("a") :=(b, c, d) e ; { IoState_error_(state, msg, "compile error: Assign operator passed multiple arguments, e.g., a := (b, c).", messageName); return; } { // a := b ; IoSymbol *slotName = DATA(attaching)->name; IoSymbol *quotedSlotName = IoSeq_newSymbolWithFormat_(state, "\"%s\"", CSTRING(slotName)); IoMessage *slotNameMessage = IoMessage_newWithName_returnsValue_(state, quotedSlotName, slotName); IoMessage_rawCopySourceLocation(slotNameMessage, attaching); // a := b ; -> a("a") := b ; IoMessage_addArg_(attaching, slotNameMessage); setSlotName = Levels_nameForAssignOperator(self, state, messageSymbol, slotName, msg); } // a("a") := b ; -> setSlot("a") := b ; DATA(attaching)->name = IoObject_addingRef_(attaching, setSlotName); currentLevel->type = ATTACH; if (msgArgCount > 0) // setSlot("a") :=(b c) d e ; { // b c IoMessage *arg = IoMessage_rawArgAt_(msg, 0); if (DATA(msg)->next == NULL || IoMessage_rawIsEOL(DATA(msg)->next)) { IoMessage_addArg_(attaching, arg); } else { // () IoMessage *foo = IoMessage_newWithName_(state, IoState_symbolWithCString_(state, "")); IoMessage_rawCopySourceLocation(foo, attaching); // () -> (b c) IoMessage_addArg_(foo, arg); // (b c) -> (b c) d e ; IoMessage_rawSetNext_(foo, DATA(msg)->next); // setSlot("a") :=(b c) d e ; -> setSlot("a", (b c) d e ;) :=(b c) d e ; IoMessage_addArg_(attaching, foo); } } else // setSlot("a") := b ; { // setSlot("a") := or setSlot("a") := ; IoMessage *mn = DATA(msg)->next; IoSymbol *name = mn ? DATA(mn)->name : NULL; IoSymbol *semi = IoObject_state(msg)->semicolonSymbol; //if (mn == NULL || IoMessage_rawIsEOL(mn)) if (mn == NULL || name == semi) { IoState_error_(state, msg, "compile error: %s must be followed by a value.", messageName); } // setSlot("a") := b c ; -> setSlot("a", b c ;) := b c ; IoMessage_addArg_(attaching, DATA(msg)->next); } // process the value (b c d) later (setSlot("a", b c d) := b c d ;) if (DATA(msg)->next != NULL && !IoMessage_rawIsEOL(DATA(msg)->next)) { List_push_(expressions, DATA(msg)->next); } { IoMessage *last = msg; while (DATA(last)->next != NULL && !IoMessage_rawIsEOL(DATA(last)->next)) { last = DATA(last)->next; } IoMessage_rawSetNext_(attaching, DATA(last)->next); // Continue processing in IoMessage_opShuffle loop IoMessage_rawSetNext_(msg, DATA(last)->next); if (last != msg) { IoMessage_rawSetNext_(last, NULL); } } // make sure b in 1 := b gets executed IoMessage_rawSetCachedResult_(attaching, NULL); } else if (IoMessage_rawIsEOL(msg)) { Levels_popDownTo(self, IO_OP_MAX_LEVEL-1); Level_attachAndReplace(Levels_currentLevel(self), msg); } else if (precedence != -1) // is an operator { if (msgArgCount > 0) { // move arguments off to their own message to make () after operators behave like Cs grouping () IoMessage *brackets = IoMessage_newWithName_(state, IoState_symbolWithCString_(state, "")); IoMessage_rawCopySourceLocation(brackets, msg); List_copy_(IoMessage_rawArgList(brackets), IoMessage_rawArgList(msg)); List_removeAll(IoMessage_rawArgList(msg)); // Insert the brackets message between msg and its next message IoMessage_rawSetNext_(brackets, DATA(msg)->next); IoMessage_rawSetNext_(msg, brackets); } Levels_popDownTo(self, precedence); Levels_attachToTopAndPush(self, msg, precedence); } else { Level_attachAndReplace(Levels_currentLevel(self), msg); } }
IoObject *IoMessage_locals_performOn_(IoMessage *self, IoObject *locals, IoObject *target) { IoState *state = IOSTATE; IoMessage *m = self; IoObject *result = target; IoObject *cachedTarget = target; //IoObject *semicolonSymbol = state->semicolonSymbol; //IoMessageData *md; IoMessageData *md; if (state->receivedSignal) { IoState_callUserInterruptHandler(IOSTATE); } do { //md = DATA(m); //printf("%s %i\n", CSTRING(IoMessage_name(m)), state->stopStatus); //printf(" %s\n", CSTRING(IoMessage_name(m))); if(state->showAllMessages) { printf("M:%s:%s:%i\n", CSTRING(IoMessage_name(m)), CSTRING(IoMessage_rawLabel(m)), IoMessage_rawLineNumber(m)); } md = DATA(m); if(md->name == state->semicolonSymbol) { target = cachedTarget; } else { result = md->cachedResult; // put it on the stack? /* if(state->debugOn) { char *s = CSTRING(DATA(m)->name); printf("%s\n", s); if (strcmp(s, "clone") == 0) { printf("found '%s'\n", s); } } */ if (!result) { IoState_pushRetainPool(state); #ifdef IOMESSAGE_INLINE_PERFORM if(IoObject_tag(target)->performFunc == NULL) { result = IoObject_perform(target, locals, m); } else { result = IoObject_tag(target)->performFunc(target, locals, m); } #else result = IoObject_tag(target)->performFunc(target, locals, m); #endif IoState_popRetainPoolExceptFor_(state, result); } //IoObject_freeIfUnreferenced(target); target = result; if (state->stopStatus != MESSAGE_STOP_STATUS_NORMAL) { return state->returnValue; /* result = state->returnValue; if (result) { //IoState_stackRetain_(state, result); return result; } printf("IoBlock no result!\n"); return state->ioNil; */ } } } while ((m = md->next)); return result; }