Exemple #1
0
Levels *Levels_new(IoMessage *msg)
{
	Levels *self = io_calloc(1, sizeof(Levels));

	IoState *state = IoObject_state(msg);
	IoSymbol *operatorTableSymbol = IoState_symbolWithCString_(state, "OperatorTable");

	// Be ultra flexable, and try to use the first message's operator table.
	IoObject *opTable = IoObject_rawGetSlot_(msg, operatorTableSymbol);

	// Otherwise, use Core OperatorTable, and if that doesn't exist, create it.
	if (opTable == NULL)
	{
		// There is a chance the message didn't have it, but the core did---due
		// to the Core not being part of the message's protos. Use Core
		// Message's OperatorTable
		opTable = IoObject_rawGetSlot_(state->core, operatorTableSymbol);

		// If Core doesn't have an OperatorTable, then create it.
		if (opTable == NULL)
		{
			opTable = IoObject_new(state);
			IoObject_setSlot_to_(state->core, operatorTableSymbol, opTable);
			IoObject_setSlot_to_(opTable, IoState_symbolWithCString_(state, "precedenceLevelCount"), IoState_numberWithDouble_(state, IO_OP_MAX_LEVEL));
		}
	}

	self->operatorTable = getOpTable(opTable, "operators", IoState_createOperatorTable);
	self->assignOperatorTable = getOpTable(opTable, "assignOperators", IoState_createAssignOperatorTable);

	self->stack = List_new();
	Levels_reset(self);
	return self;
}
Exemple #2
0
IO_METHOD(IoObject, platformVersion)
{
	char platformVersion[256];

	/*doc System platformVersion
	Returns the version id of the OS.
	*/

#if defined(_WIN32)

	OSVERSIONINFO os;

	os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
	GetVersionEx(&os);

	snprintf(platformVersion, sizeof(platformVersion) - 1, "%d.%d",
		(int)os.dwMajorVersion, (int)os.dwMinorVersion);

#elif defined(unix) || defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__)
	/* Why Apple and NetBSD don't define 'unix' I'll never know. */
	struct utsname os;
	int ret = uname(&os);

	if (ret == 0)
	{
		snprintf(platformVersion, 256, "%s.%s", os.version, os.release);
		//sprintf(platformVersion, (size_t)sizeof(platformVersion) - 1, (const char *)os.release);
	}
#endif

	return IoState_symbolWithCString_(IOSTATE, platformVersion);
}
Exemple #3
0
IoCFunction *IoCFunction_newWithFunctionPointer_tag_name_(void *state,
												IoUserFunction *func,
												IoTag *typeTag,
												const char *funcName)
{
	IoCFunction *proto = IoState_protoWithInitFunction_((IoState *)state, IoCFunction_proto);
	IoCFunction *self = IOCLONE(proto);
	DATA(self)->typeTag = typeTag;
	DATA(self)->func = func;
	DATA(self)->uniqueName = IoState_symbolWithCString_((IoState *)state, funcName);
	return self;
}
Exemple #4
0
IoMessage *IoMessage_newParse(void *state, IoLexer *lexer)
{
	if (IoLexer_errorToken(lexer))
	{
		IoMessage *m;
		IoSymbol *errorString;

		// Maybe the nil message could be used here. Or even a NULL.
		IoSymbol *error = IoState_symbolWithCString_(state, "Error");
		m = IoMessage_newWithName_returnsValue_(state, error, error);
		errorString = IoState_symbolWithCString_((IoState *)state, IoLexer_errorDescription(lexer));
		IoLexer_free(lexer); // hack for now - the caller should be responsible for this
		IoState_error_(state, m, "compile error: %s", CSTRING(errorString));
	}

	if (IoLexer_topType(lexer) == TERMINATOR_TOKEN)
	{
		IoLexer_pop(lexer);
	}

	if (IoTokenType_isValidMessageName(IoLexer_topType(lexer)))
	{
		IoMessage *self = IoMessage_newParseNextMessageChain(state, lexer);

		if (IoLexer_topType(lexer) != NO_TOKEN)
		{
			// TODO: Exception as the end was expected
			IoState_error_(state, self, "compile error: %s", "unused tokens");
		}

		return self;
	}

	return IoMessage_newWithName_returnsValue_(state,
											   IoState_symbolWithCString_((IoState*)state, "nil"),
											   ((IoState*)state)->ioNil
											   );
}
Exemple #5
0
IO_METHOD(IoObject, installPrefix)
{

	char acPath[256];
	char root[256];
	if( GetModuleFileName( NULL, acPath, 256 ) != 0)
	{
		// guaranteed file name of at least one character after path
		strcpy(( strrchr( acPath, '\\' ) ), "\\..\\");
		_fullpath(root,acPath,256);
	}

	return IoState_symbolWithCString_(IOSTATE, root);
}
Exemple #6
0
IO_METHOD(IoObject, getEnvironmentVariable)
{
	/*doc System getEnvironmentVariable(nameString)
	Returns a string with the value of the environment
	variable whose name is specified by nameString.
	*/

	IoSymbol *key = IoMessage_locals_symbolArgAt_(m, locals, 0);
	char *s = getenv(CSTRING(key));

	if (!s)
	{
		return ((IoState *)IOSTATE)->ioNil;
	}

	return IoState_symbolWithCString_(IOSTATE, s);
}
Exemple #7
0
IoMap *getOpTable(IoObject *self, const char *slotName, IoMap *create(IoState *state))
{
	IoSymbol *symbol = IoState_symbolWithCString_(IOSTATE, slotName);
	IoObject *operators = IoObject_rawGetSlot_(self, symbol);

	if (operators && ISMAP(operators))
	{
		return operators;
	}
	else
	{
		// Not strictly correct as if the message has it's own empty
		// OperatorTable slot, we'll create one for it instead of using
		// Core Message OperatorTable operators. Oh well.

		IoMap *result = create(IOSTATE);
		IoObject_setSlot_to_(self, symbol, result);
		return result;
	}
}
Exemple #8
0
IoObject *IoCurses_input(IoCurses *self, IoObject *locals, IoMessage *m)
{
	/*doc Curses input(n)
	Returns user input up to a return, or a maximun of n characters.
	*/

	int length = 1;
	char string[length+1];

	if (IoMessage_argCount(m) > 0)
	{
		length = IoNumber_asInt(IoMessage_locals_numberArgAt_(m, locals, 0));
	}

	if (innstr(string, length) == ERR)
	{
		return IONIL(self);
	}

	return IoState_symbolWithCString_(IOSTATE, string);
}
Exemple #9
0
IoObject *IoCurses_get(IoCurses *self, IoObject *locals, IoMessage *m)
{
	/*doc Curses get(n)
	Returns n characters from the terminal. n is optional and defaults to 1.
	*/

	int inputCharacterLimit = IO_CURSES_INPUT_BUFFER_LENGTH;
	char string[inputCharacterLimit];

	if (IoMessage_argCount(m) > 0)
	{
		IoNumber *number = IoMessage_locals_numberArgAt_(m, locals, 0);
		inputCharacterLimit = IoNumber_asInt(number);
	}

	if (getnstr(string, inputCharacterLimit) == ERR)
	{
		return IONIL(self);
	}

	return IoState_symbolWithCString_(IOSTATE, string);
}
Exemple #10
0
IoMessage *IoMessage_newFromText_label_(void *state, const char *text, const char *label)
{
	IoSymbol *labelSymbol = IoState_symbolWithCString_((IoState *)state, label);
	return IoMessage_newFromText_labelSymbol_(state, text, labelSymbol);
}
Exemple #11
0
IO_METHOD(IoObject, platform)
{
	/*doc System platform
	Returns a string description of the platform.
	*/

	char *platform = "Unknown";

#if defined(__CYGWIN__)

	platform = "cygwin";

#elif defined(__MINGW32__)

	platform = "mingw";

#elif defined(_WIN32)

	OSVERSIONINFO os;

	os.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
	GetVersionEx(&os);

	switch(os.dwPlatformId)
	{
		case VER_PLATFORM_WIN32_WINDOWS:
			switch(os.dwMinorVersion)
			{
				case 0:
					platform = "Windows 95";
					break;
				case 10:
					platform = "Windows 98";
					break;
				case 90:
					platform = "Windows ME";
					break;
				default:
					platform = "Windows 9X";
					break;
			}
			break;

		case VER_PLATFORM_WIN32_NT:
			if (os.dwMajorVersion == 3 || os.dwMajorVersion == 4)
			{
				platform = "Windows NT";
			}
			else if (os.dwMajorVersion == 5)
			{
				switch(os.dwMinorVersion)
				{
					case 0:
						platform = "Windows 2000";
						break;
					case 1:
						platform = "Windows XP";
						break;
					default:
						platform = "Windows";
						break;
				}
			}
			else
			{
				platform = "Windows";
			}
			break;

		default: platform = "Windows";
	}

#elif defined(unix) || defined(__APPLE__) || defined(__NetBSD__) || defined(__OpenBSD__)
	/* Why Apple and NetBSD don't define 'unix' I'll never know. */
	struct utsname os;
	int ret = uname(&os);

	if (ret == 0)
	{
		platform = os.sysname;
	}
#endif

	return IoState_symbolWithCString_(IOSTATE, platform);
}
Exemple #12
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);
			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);
	}
}