Exemple #1
0
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;
}
Exemple #2
0
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;
	}
}
Exemple #3
0
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;
}
Exemple #4
0
void IoMessage_parseNext(IoMessage *self, IoLexer *lexer)
{
	IoMessage *next = IoMessage_newParseNextMessageChain(IOSTATE, lexer);
	IoMessage_rawSetNext(self, next);
}
Exemple #5
0
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);
	}
}