/*#io
docCopyright("Steve Dekorte", 2002)
docLicense("BSD revised")
*/

#ifdef IOSTATE_C 
#define IO_IN_C_FILE
#endif
#include "Common_inline.h"
#ifdef IO_DECLARE_INLINES

IOINLINE IoObject *IOTRUE(const IoObject *const self)
{
	return IOSTATE->ioTrue;
}

IOINLINE int ISTRUE(const IoObject *const self)
{
	return self != IOSTATE->ioNil && self != IOSTATE->ioFalse;
}

IOINLINE IoObject *IOFALSE(const IoObject *const self)
{
	return IOSTATE->ioFalse;
}

IOINLINE int ISFALSE(const IoObject *const self)
{
	return self == IOSTATE->ioNil || self == IOSTATE->ioFalse;
}

IOINLINE IoObject *IOBOOL(const IoObject *const self, const int b)
{
	return b ? IOTRUE(self) : IOFALSE(self);
}

//static int stackPos = -1;

//#define RETAIN_DEBUG
//#define IO_DISABLE_POP 1

//printf("immediately free %p\n", (void *)self);

IOINLINE void *IoState_stackRetain_(IoState *self, IoObject *v)
{ 
	//printf("IoState_stackRetain_(%p, %p) %p\n", self, v, self->currentIoStack);
	Stack_push_(self->currentIoStack, v); 
#ifdef RETAIN_DEBUG
	printf("rpush %i %p\n", (int)Stack_totalSize(self->currentIoStack), v);
#endif
	return v;
}

IOINLINE void IoState_clearRetainStack(IoState *self)
{ 
	//printf("IoState_clearRetainStack\n");
#ifndef IO_DISABLE_POP 
	Stack_clear(((IoState *)self)->currentIoStack); 
#ifdef RETAIN_DEBUG
	printf("rclear %i\n", (int)Stack_totalSize(self->currentIoStack));
#endif
#endif
}

IOINLINE void IoState_pushRetainPool(void *self)
{ 
	Stack_pushMark(((IoState *)self)->currentIoStack); 
#ifdef RETAIN_DEBUG
	printf("rmark push\n");
#endif
}

IOINLINE void IoState_clearTopPool(void *self)
{
#ifndef IO_DISABLE_POP 
	Stack *stack = ((IoState *)self)->currentIoStack;
	//Stack_popMark(stack);
	//Stack_pushMark(stack);
	Stack_clearTop(stack);
#endif
}

IOINLINE void IoState_popRetainPool(void *self)
{
#ifndef IO_DISABLE_POP 
	Stack *stack = ((IoState *)self)->currentIoStack;
	Stack_popMark(stack);
#endif
}


IOINLINE void IoState_popRetainPoolExceptFor_(void *state, void *obj)
{
	IoState *self = (IoState *)state;
#ifndef IO_DISABLE_POP 
	IoState_popRetainPool(self);
	//#ifdef IO_DEBUG_COLLECTOR
	
	/*
	if (Coro_object(Scheduler_currentCoro(self->scheduler)) == 0x0)
	{
		Scheduler_selfTest(self->scheduler);
		IoState_fatalError_(self, "IoState collector error: attempt to add Io object to Io stack while not in a Io controlled coroutine.\n"); 
	}
	*/
	
	/*#endif*/
#endif
	IoState_stackRetain_(self, (IoObject *)obj);
}

#define IOMESSAGEDATA(self) ((IoMessageData *)self->data)

IOINLINE IoObject *IoMessage_locals_quickValueArgAt_(IoMessage *self, IoObject *locals, int n)
{
	IoMessage *m = (IoMessage *)List_at_(IOMESSAGEDATA(self)->args, n);
	
	if (m) 
	{ 
		IoMessageData *md = IOMESSAGEDATA(m);
		IoObject *v = md->cachedResult;
		
		if (v && !md->attachedMessage && !md->nextMessage) 
		{
			return v;
		}
		
		return IoMessage_locals_performOn_(m, locals, locals); 
	}
	
	return IOSTATE->ioNil;
}

IOINLINE IoObject *IoMessage_locals_valueArgAt_(IoMessage *self, IoObject *locals, int n)
{
	List *args = IOMESSAGEDATA(self)->args;
	IoMessage *m = (IoMessage *)List_at_(args, n);
	
	if (m) 
	{ 
		return IoMessage_locals_performOn_(m, locals, locals); 
	}
	
	return IOSTATE->ioNil;
}

/*
IOINLINE IoObject *IoMessage_locals_valueOrEvalArgAt_(IoMessage *self, IoObject *locals, int n)
{
	List *args = IOMESSAGEDATA(self)->args;
	IoMessage *m = (IoMessage *)List_at_(args, n);
	
	if (m) 
	{ 
		return IoMessage_locals_performOn_(m, locals, locals); 
	}
	
	return IOSTATE->ioNil;
}
*/


#include "IoMark.h"

IOINLINE IoObject *IoMessage_locals_firstStringArg(IoMessage *self, IoObject *locals)
{
	// special case this, since it's used for setSlot() 
	List *args = IOMESSAGEDATA(self)->args;
	
	if (List_size(args))
	{
		IoMessage *m = (IoMessage *)List_rawAt_(args, 0);
		
		if (m) 
		{ 
			IoMessageData *md = IOMESSAGEDATA(m);
			IoObject *v = md->cachedResult;
			
			//if (v && ISSYMBOL(v) && !md->attachedMessage && !md->nextMessage) 
			
			// avoid calling IoMessage_locals, if possible 
			
			if (v && 
			    v->mark.isSymbol && 
			    (md->attachedMessage == 0x0) && 
			    (md->nextMessage == 0x0)) 
			{
				return v;
			}
		}
	}
	
	return IoMessage_locals_symbolArgAt_(self, locals, 0);
}

/*
 IOINLINE void IoMessage_break(IoMessage *self, IoObject *v)
 {
	 IoState *state = IOSTATE;
	 state->stopStatus = MESSAGE_STOP_STATUS_BREAK;
	 state->returnValue = v;
 }
 
 IOINLINE void IoMessage_continue(IoMessage *self)
 { 
	 ((IoState *)IOSTATE)->stopStatus = MESSAGE_STOP_STATUS_CONTINUE; 
 }
 
 IOINLINE void IoMessage_return_(IoMessage *self, IoObject *v)
 { 
	 IoState *state = IOSTATE;
	 state->stopStatus = MESSAGE_STOP_STATUS_RETURN; 
	 state->returnValue = v;
 }
 
 IOINLINE int IoMessage_isStopped(IoMessage *self)
 { 
	 int status = ((IoState *)IOSTATE)->stopStatus;
	 return status & (
				   MESSAGE_STOP_STATUS_BREAK | 
				   MESSAGE_STOP_STATUS_RETURN | 
				   MESSAGE_STOP_STATUS_CONTINUE); 
 }
 
 IOINLINE int IoMessage_isBrokenOrReturned(IoMessage *self)
 { 
	 int status = ((IoState *)IOSTATE)->stopStatus;
	 return status & (MESSAGE_STOP_STATUS_BREAK | MESSAGE_STOP_STATUS_RETURN); 
 }
 
 IOINLINE int IoMessage_isBroken(IoMessage *self)
 { 
	 int status = ((IoState *)IOSTATE)->stopStatus;
	 return (status == MESSAGE_STOP_STATUS_BREAK); 
 }
 
 IOINLINE void IoMessage_resetStopStatus(IoMessage *self)
 {  
	 ((IoState *)IOSTATE)->stopStatus = MESSAGE_STOP_STATUS_NORMAL; 
 }
 
 IOINLINE int IoMessage_stopStatus(IoMessage *self)
 {  
	 return ((IoState *)IOSTATE)->stopStatus; 
 }
 
 
 IOINLINE int IoMessage_handleStatus(IoMessage *doMessage)
 {
	 switch (IoMessage_stopStatus(doMessage))
	 {
		 case MESSAGE_STOP_STATUS_RETURN:
			 return 1;
			 
		 case MESSAGE_STOP_STATUS_BREAK:
			 IoMessage_resetStopStatus(doMessage); 
			 return 1;
			 
		 case MESSAGE_STOP_STATUS_CONTINUE:
			 IoMessage_resetStopStatus(doMessage); 
	 }
	 
	 return 0;
 }
 */

#undef IO_IN_C_FILE
#endif

