Login
7 branches 0 tags
Ben (Win10) Fixed win32 0de15ea 4 years ago 203 Commits
nujel / bin / main.c
/*
 * Wolkenwelten - Copyright (C) 2020-2021 - Benjamin Vincent Schulenburg
 *
 * This project uses the MIT license, a copy should be included under /LICENSE
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <setjmp.h>

#include "../lib/api.h"
#include "misc.h"
#include "operation/readline.h"
#include "operation/io.h"

extern char binlib_no_data[];
lClosure *mainClosure;

#ifdef __EMSCRIPTEN__
/* To be used for the WASM REPL, since we don't run continuously there */
const char *run(const char *line){
	const int SP = lRootsGet();
	lVal *exp = lRootsValPush(lCons(NULL,NULL));
	exp->vList.car = lValSym("repl/wasm");
	exp->vList.cdr = lCons(NULL,NULL);
	exp->vList.cdr->vList.car = lValString(line);
	lVal *v = lEval(mainClosure,exp);
	const char *ret = v ? lReturnDisplayVal(v) : "";
	lRootsRet(SP);
	return ret;
}
#endif

void *readEvalStringRaw(void *cl, void *str){
	lClosure *c = (lClosure *)cl;
	const char *expr = str;
	lVal *v = lnfDo(c,lRead(expr));
	return v;
}

void *evalRaw(void *cl, void *body){
	return lEval((lClosure *)cl,(lVal *)body);
}

lClosure *createRoolClosure(bool loadStdLib){
	lClosure *c;
	if(loadStdLib){
		c = lClosureNewRoot();
		lOperationsIO(c);
		lOperationsReadline(c);
		lnfDo(c,lRead((const char *)binlib_no_data));
		lGarbageCollect();
	}else{
		c = lClosureNewRootNoStdLib();
		lOperationsIO(c);
		lOperationsReadline(c);
	}
	return c;
}

/* Parse options that might radically alter runtime behaviour, like running
 * without the stdlib (probably for using an alternative build of the stdlib )
 */
lClosure *parsePreOptions(int argc, char *argv[]){
	bool loadStdLib = true;
	bool readNext   = false;
	lClosure *c     = NULL;
	for(int i=1;i<argc;i++){
		if(readNext){
			if(c == NULL){c = createRoolClosure(loadStdLib);}
			size_t len = 0;
			char *str = loadFile(argv[i],&len);
			lExceptionTry(readEvalStringRaw,c,str);
			free(str);
			readNext = false;
		}else if(argv[i][0] == '-'){
			for(const char *opts = &argv[i][1];*opts;opts++){
				switch(*opts){
				case 'r':
					readNext = true;
					break;
				case 'n':
					loadStdLib = false;
					break;
				case 'v':
					lVerbose = true;
					break;
				}
			}
		}
	}
	if(c == NULL){c = createRoolClosure(loadStdLib);}

	if(lVerbose){
		printf("sizeof(lClosure): %u\n",(uint)sizeof(lClosure));
		printf("sizeof(lVal): %u\n",    (uint)sizeof(lVal));
		printf("sizeof(lArray): %u\n",  (uint)sizeof(lArray));
		printf("sizeof(lString): %u\n", (uint)sizeof(lString));
		printf("sizeof(lTree): %u\n", (uint)sizeof(lTree));
		printf("sizeof(jmp_buf): %u\n", (uint)sizeof(jmp_buf));
		printf("\n\nRoot Closure Data Size: %u\n",lTreeSize(c->data));
		lWriteVal(lValTree(c->data));
	}
	return c;
}



void initNujel(int argc, char *argv[], lClosure *c){
	lVal *ret = NULL;
	const int SP = lRootsGet();
	for(int i = argc-1; i >= 0; i--){
		ret = lCons(lValString(argv[i]), ret);
	}
	lRootsRet(SP);
	RVP(ret);
	ret = lCons(lValSym("repl/init"), ret);
	lRootsRet(SP);
	RVP(ret);
	lExceptionTry(evalRaw,c,ret);
}

int main(int argc, char *argv[]){
	setvbuf(stdout, NULL, _IONBF, 0);
	setvbuf(stderr, NULL, _IONBF, 0);
	lInit();
	setIOSymbols();

	initNujel(argc,argv,parsePreOptions(argc,argv));
	return 0;
}