#include <v_lib.h>
#include "cspace.h"
#include "eval.h"
#include "util.h"
#include "messages.h"

vboolean
evalGlobals(vhandle_t script)
{
	CALLER_NAME(evalGlobals)
	vboolean res = true;
	while(res && lexSkip_r(script,ipl_key_global))
	{
		if(!lexNextIs(script,ipl_open_brace))
		{
			SYN_EXPECTED(script,ipl_open_brace);
			res = false;
			break;
		}
		while(res && lexNext(script))
		{
			char *last = lexLast(script);
			if(STR_EQ(last,ipl_close_brace))
				break;
			if(STR_EQ(last,ipl_key_random_seed))
			{
				if(!lexNextInteger(script,(s32_p)&random_seed))
				{
					SYN_EXPECTED(script,ipl_integer);
					res = false;
				}
				continue;
			}
			if(STR_EQ(last,ipl_key_alias))
			{
				char *alias_key;
				if(lexNext(script))
					alias_key = strDup(lexLast(script));
				else
					alias_key = NULL;
				if(alias_key && lexNext(script))
					lexDefineAlias(script,alias_key,lexLast(script));
				else
				{
					SYN_UNEXPECTED_EOF(script);
					res = false;
				}
				if(alias_key)
					memFree(alias_key);
				continue;
			}
			SYN_UNEXPECTED(script,last);
			res = false;
		}
	}
	lexSetInteger(script,LEX_CURRENT_LINE,1);
	return res;
}

int main(int argc,char *argv[])
{
	CALLER_NAME(main)
	vhandle_t script;
	vboolean result;
	u32_t nbytes, nblocks, nhandles;
	u32_t nbytes_out, nblocks_out, nhandles_out;
	logStartConsoleLog();
	logUpperLevel(LOG_TRACE);
	if(argc != 2)
	{
		puts(ipl_usage);
		return -1;
	}
	if(STR_EQ(argv[1],"--help"))
	{
		puts(ipl_usage);
		return 0;
	}
	if(STR_EQ(argv[1],"--help-ipl"))
	{
		evalHelp();
		return 0;
	}
	if(STR_EQ(argv[1],"--help-state"))
	{
		stateHelp();
		return 0;
	}
	script = lexParseFile(argv[1],"{}");
	if(script == LIBV_INVALID_HANDLE)
	{
		ERROR_GENERIC_2ARG(ipl_unable_to_open,argv[1]);
		return -1;
	}
	lexSetInteger(script,LEX_COMMENT_CHAR,IPL_COMMENT_CHAR);
	lexEnable(script,LEX_ONE_CHAR_COMMENTS);
	lexEnable(script,LEX_ALIAS_TRANSLATION);
	result = evalGlobals(script);
	if(result)
	{
		random_gen = ranCreateGenerator(random_seed);
		V_ASSERT(random_gen);
		result = evalAll(script);
	}
	memStats(&nbytes,&nblocks,&nhandles);
	ranDestroyGenerator(random_gen);
	inputCollectGarbage();
	evalFreeAllArgs();
	evalFreeAllOperands();
	evalDestroyAllFourierTransformers();
	lexDestroy(script);
	logStopConsoleLog();
	memStats(&nbytes_out,&nblocks_out,&nhandles_out);
	printf(ipl_exit_status,
		result ? ipl_success : ipl_error, nbytes, nbytes_out);
	return (result) ? 0 : -1;
}
