Login
7 branches 0 tags
Ben (X13/Arch) Most conditionals are now special forms e98a7bc 4 years ago 60 Commits
nujel / lib / datatypes / native-function.c
/*
 * Wolkenwelten - Copyright (C) 2020-2021 - Benjamin Vincent Schulenburg
 *
 * This project uses the MIT license, a copy should be included under /LICENSE
 */
#include "closure.h"
#include "list.h"
#include "native-function.h"
#include "val.h"
#include "../reader.h"

lNFunc   lNFuncList[NFN_MAX];
uint     lNFuncActive = 0;
uint     lNFuncMax    = 1;
uint     lNFuncFFree  = 0;

void lInitNativeFunctions(){
	lNFuncActive = 0;
	lNFuncMax    = 1;
}

void lNFuncFree(uint i){
	if((i == 0) || (i >= lNFuncMax)){return;}
	lNFunc *nfn = &lNFuncList[i];
	if(nfn->nextFree != 0){return;}
	lNFuncActive--;
	nfn->fp       = NULL;
	nfn->doc      = NULL;
	nfn->nextFree = lNFuncFFree;
	nfn->flags    = 0;
	lNFuncFFree   = i;
}

uint lNFuncAlloc(){
	lNFunc *ret;
	if(lNFuncFFree == 0){
		if(lNFuncMax >= NFN_MAX-1){
			lPrintError("lNFunc OOM ");
			return 0;
		}
		ret = &lNFuncList[lNFuncMax++];
	}else{
		ret = &lNFuncList[lNFuncFFree & NFN_MASK];
		lNFuncFFree = ret->nextFree;
	}
	lNFuncActive++;
	*ret = (lNFunc){0};
	return ret - lNFuncList;
}

lVal *lValNativeFunc(lVal *(*func)(lClosure *,lVal *), lVal *args, lVal *docString){
	lVal *v = lValAlloc();
	if(v == NULL){return NULL;}
	v->type    = ltNativeFunc;
	v->flags  |= lfConst;
	v->vCdr    = lNFuncAlloc();
	if(v->vCdr == 0){
		lValFree(v);
		return NULL;
	}
	lNFunc *fn = &lNFN(v->vCdr);
	fn->fp     = func;
	fn->doc    = lCons(args,docString);
	return v;
}

lVal *lAddNativeFunc(lClosure *c, const char *sym, const char *args, const char *doc, lVal *(*func)(lClosure *,lVal *)){
	lVal *lNF = lValNativeFunc(func,lRead(args),lValString(doc));
	return lDefineAliased(c,lNF,sym);
}

lVal *lAddSpecialForm(lClosure *c, const char *sym, const char *args, const char *doc, lVal *(*func)(lClosure *,lVal *)){
	lVal *lNF = lValNativeFunc(func,lRead(args),lValString(doc));
	lNF->type = ltSpecialForm;
	return lDefineAliased(c,lNF,sym);
}