IoMessage *IoMessage_newParseNextMessageChain(void *state, IoLexer *lexer) { IoCoroutine *current = IoState_currentCoroutine(state); Coro *coro = IoCoroutine_cid(current); size_t left = Coro_bytesLeftOnStack(coro); /* if (Coro_stackSpaceAlmostGone(coro)) { // need to make Coroutine support a stack of Coros which it frees when released // return IoCoroutine_internallyChain(current, context, IoMessage_...); Coro *newCoro = Coro_new(); ParseContext p = {state, lexer, newCoro, coro, NULL}; printf("Warning IoMessage_newParseNextMessageChain doing callc with %i bytes left to avoid stack overflow\n", left); Coro_startCoro_(coro, newCoro, &p, (CoroStartCallback *)IoMessage_coroNewParseNextMessageChain); Coro_free(newCoro); return p.result; } */ IoMessage *self = IoMessage_new(state); if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage_parseName(self, lexer); } if (IoLexer_topType(lexer) == OPENPAREN_TOKEN) { IoMessage_parseArgs(self, lexer); } if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage_parseNext(self, lexer); } while (IoLexer_topType(lexer) == TERMINATOR_TOKEN) { IoLexer_pop(lexer); if (IoTokenType_isValidMessageName(IoLexer_topType(lexer))) { IoMessage *eol = IoMessage_newWithName_(state, ((IoState*)state)->semicolonSymbol); IoMessage_rawSetNext(self, eol); IoMessage_parseNext(eol, lexer); } } return self; }
void Level_attach(Level *self, IoMessage *msg) { switch (self->type) { case ATTACH: IoMessage_rawSetNext(self->message, msg); break; case ARG: IoMessage_addArg_(self->message, msg); break; case NEW: self->message = msg; break; case UNUSED: break; } }
void Level_finish(Level *self) { if (self->message) { IoMessage_rawSetNext(self->message, NULL); // Remove extra () we added in for operators, but don't 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; }
void IoMessage_parseNext(IoMessage *self, IoLexer *lexer) { IoMessage *next = IoMessage_newParseNextMessageChain(IOSTATE, lexer); IoMessage_rawSetNext(self, next); }
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); } 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); } 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); } { // `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_cachedResult_(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 C's 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 it's 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); } }