Login
7 branches 0 tags
Ben (X13/Arch) Added CLAUDE.md 19db192 10 days ago 1256 Commits
nujel / lib / nujel-private.h
/*\
 |  nujel-private.h
 |
 |  This file contains all the internal definitions needed for the Nujel runtime.
 |  No external program should include this file, since it WILL change a lot and
 |  a lot of the functions aren't very easy to use. To interface to Nujel one
 |  should use nujel-public.h instead.
\*/
#ifndef NUJEL_LIB_NUJEL_PRIVATE
#define NUJEL_LIB_NUJEL_PRIVATE

#ifndef NUJEL_AMALGAMATION
#include "nujel.h"
#endif

#include <stdlib.h>
#include <string.h>

/*\
 |  Core
\*/
#define MAX_OPEN_FILE_DESCRIPTORS 250
#define PI    (3.1415926535897932384626433832795)

lType lTypecast(const lType a, const lType b);

struct lClass {
	const lSymbol *name;
	lClass *parent;
	lTree *methods;
	lTree *staticMethods;
};
extern lClass lClassList[64];

struct lArray {
	lVal *data;
	union {
		lArray *nextFree;
		struct {
			i32 length;
			u8 flags;
		};
	};
};
#define ARRAY_IMMUTABLE 1

typedef enum {
	lbvtUndefined = 0,
	lbvtS8,
	lbvtU8,
	lbvtS16,
	lbvtU16,
	lbvtS32,
	lbvtU32,
	lbvtS64,
	lbvtF32,
	lbvtF64
} lBufferViewType;

struct lBufferView {
	union {
		lBuffer *buf;
		lBufferView *nextFree;
	};
	size_t offset;
	size_t length;
	u8 type;
	u8 flags;
};
#define BUFFER_VIEW_IMMUTABLE 1

struct lBuffer {
	union {
		void *buf;
		const char *data;
		lBuffer *nextFree;
	};
	i32 length;
	u8 flags;
};
#define BUFFER_IMMUTABLE 1
#define BUFFER_STATIC 2

struct lSymbol {
	u32 hash;
	union {
		char c[94];
		struct lSymbol *nextFree;
	};
};

struct lBytecodeArray {
	lBytecodeOp *data;
	lArray *literals;
	union {
		lBytecodeOp *dataEnd;
		struct lBytecodeArray *nextFree;
	};
	u8 flags;
};

struct lNFunc {
	union {
		lVal (*fp)();
		lVal (*fpC)(lClosure *);
		lVal (*fpV)(lVal);
		lVal (*fpCV)(lClosure *, lVal);
		lVal (*fpVV)(lVal, lVal);
		lVal (*fpCVV)(lClosure *, lVal, lVal);
		lVal (*fpVVV)(lVal, lVal, lVal);
		lVal (*fpCVVV)(lClosure *, lVal, lVal, lVal);
		lVal (*fpVVVV)(lVal, lVal, lVal, lVal);
		lVal (*fpCVVVV)(lClosure *, lVal, lVal, lVal, lVal);
		lVal (*fpVVVVV)(lVal, lVal, lVal, lVal, lVal);
		lVal (*fpCVVVVV)(lClosure *, lVal, lVal, lVal, lVal, lVal);
		lVal (*fpVVVVVV)(lVal, lVal, lVal, lVal, lVal, lVal);
		lVal (*fpCVVVVVV)(lClosure *, lVal, lVal ,lVal, lVal, lVal, lVal);
		lVal (*fpVVVVVVV)(lVal, lVal, lVal ,lVal, lVal, lVal, lVal);
		lVal (*fpCVVVVVVV)(lClosure *, lVal, lVal, lVal ,lVal, lVal, lVal, lVal);
		lVal (*fpR)(lVal);
		lVal (*fpCR)(lClosure *, lVal);
	};
	const lSymbol *name;
	lTree *meta;
	lVal args;
	u8 argCount;
};

#define NFUNC_FOLD 1
#define NFUNC_PURE 2

struct lTree {
	lTree *left;
	lTree *right;
	union {
		const lSymbol *key;
		lTree *nextFree;
	};
	lVal value;
	i16 height;
	u8 flags;
};
#define TREE_IMMUTABLE 1

struct lMapEntry {
	lVal key;
	lVal val;
};

struct lMap {
	u32 length;
	u16 size;
	u8 flags;
	union {
		lMapEntry *entries;
		lMap *nextFree;
	};
};
#define MAP_IMMUTABLE 1

struct lClosure {
	union {
		lClosure *parent;
		lClosure *nextFree;
	};
	lTree *data, *meta;
	lBytecodeArray *text;
	const lBytecodeOp *ip;
	union {
		lVal args;
		lVal exceptionHandler;
	};
	u16 sp;
	u8 type;
};

typedef enum closureType {
	closureDefault = 0,
	closureCall = 1,
	closureLet = 2,
	closureTry = 3,
} closureType;


struct lThread {
	lBytecodeArray *text;

	lVal *valueStack;
	lClosure **closureStack;

	int sp;
	int valueStackSize;

	int csp;
	int closureStackSize;
};

/*\
 |  Closure related procedures
\*/
lClosure *lClosureNew        (lClosure *parent, closureType t);
lClosure *lClosureNewFunCall (lVal args, lVal lambda);
bool      lHasClosureSym     (lClosure *c, const lSymbol *s, lVal *v);

/*\
 |  lVal related procedures
\*/
int       lValCompare      (const lVal a, const lVal b);
bool      lValEqual        (const lVal a, const lVal b);
i64       lValGreater      (const lVal a, const lVal b);
lVal      lValStringError  (const char *bufStart, const char *bufEnd, const char *errStart, const char *err, const char *errEnd);

/*\
 |  Bytecode related definitions
\*/
typedef enum lOpcode {
	lopNOP             =  0x0,
	lopRet             =  0x1,
	lopIntByte         =  0x2,
	lopIntAdd          =  0x3,
	lopApply           =  0x4,
	lopSetVal          =  0x5,
	lopPushValExt      =  0x6,
	lopDefVal          =  0x7,
	lopDefValExt       =  0x8,
	lopJmp             =  0x9,
	lopJt              =  0xA,
	lopJf              =  0xB,
	lopDup             =  0xC,
	lopDrop            =  0xD,
	lopGetVal          =  0xE,
	lopGetValExt       =  0xF,
	lopSetValExt       = 0x10,
	lopCar             = 0x11,
	lopCdr             = 0x12,
	lopClosurePush     = 0x13,
	lopCons            = 0x14,
	lopLet             = 0x15,
	lopClosurePop      = 0x16,
	lopFnDynamic       = 0x17,
	lopMacroDynamic    = 0x18,
	lopTry             = 0x19,
	lopPushVal         = 0x1A,
	lopPushTrue        = 0x1B,
	lopPushFalse       = 0x1C,
	lopEval            = 0x1D,
	lopLessPred        = 0x1E,
	lopLessEqPred      = 0x1F,
	lopEqualPred       = 0x20,
	lopGreaterEqPred   = 0x21,
	lopGreaterPred     = 0x22,
	lopIncInt          = 0x23,
	lopPushNil         = 0x24,
	lopAdd             = 0x25,
	lopSub             = 0x26,
	lopMul             = 0x27,
	lopDiv             = 0x28,
	lopRem             = 0x29,
	lopZeroPred        = 0x2A,
	lopRef             = 0x2B,
	lopCadr            = 0x2C,
	lopMutableEval     = 0x2D,
	lopList            = 0x2E,
	lopThrow           = 0x2F,
	lopApplyCollection = 0x30,
	lopBitShiftLeft    = 0x31,
	lopBitShiftRight   = 0x32,
	lopBitAnd          = 0x33,
	lopBitOr           = 0x34,
	lopBitXor          = 0x35,
	lopBitNot          = 0x36,
	lopGenSet          = 0x37,
	lopUnequalPred     = 0x38,
} lOpcode;

lVal  lBytecodeEval        (lClosure *c, lBytecodeArray *ops);
lVal  lValBytecodeArray    (const lBytecodeOp *ops, int opsLength, lArray *literals);

/*\
 | Workarounds for missing builtins
\*/
#if false
uint32_t __builtin_popcount(uint32_t x);
uint64_t __builtin_popcountll(uint64_t x);
#endif

#if defined(__TINYC__)
void __sync_synchronize();
#endif


/*
 | Compatibility procedures
 */
u64 getMSecs();
void lAddPlatformVars(lClosure *c);

/*\
 | GC related procedures
\*/
lSymbol *lRootsSymbolPush(lSymbol *v);
void lDefineTypeVars(lClosure *c);
extern int lGCRuns;
extern lMap *lSymbolTable;

extern bool lGCShouldRunSoon;

void lGarbageCollect(lThread *ctx);

/*\
 | Allocator related definitions
\*/
#define SYM_MAX (1<<14)
#define NFN_MAX (1<<10)
#define ARR_MAX (1<<14)
#define CLO_MAX (1<<17)
#define TRR_MAX (1<<15)
#define BCA_MAX (1<<14)
#define BUF_MAX (1<<15)
#define BFV_MAX (1<<14)
#define TRE_MAX (1<<18)
#define CON_MAX (1<<18)
#define MAP_MAX (1<<15)

#define allocatorTypes() \
	defineAllocator(lArray, ARR_MAX) \
	defineAllocator(lClosure, CLO_MAX) \
	defineAllocator(lTree, TRE_MAX) \
	defineAllocator(lTreeRoot, TRR_MAX) \
	defineAllocator(lMap, MAP_MAX) \
	defineAllocator(lBytecodeArray, BCA_MAX) \
	defineAllocator(lBuffer, BUF_MAX) \
	defineAllocator(lBufferView, BFV_MAX) \
	defineAllocator(lPair, CON_MAX)

#define defineAllocator(T, typeMax) \
extern T T##List[typeMax]; \
extern uint T##Max;	   \
extern uint T##Active; \
extern u8 T##MarkMap[typeMax]; \
extern T * T##FFree; \
T * T##AllocRaw();

allocatorTypes()
#undef defineAllocator

extern u8 lSymbolMarkMap[SYM_MAX];

extern lNFunc   lNFuncList[NFN_MAX];
extern uint     lNFuncMax;


static inline int lClosureID(const lClosure *n){
	return n - lClosureList;
}
static inline int lNFuncID(const lNFunc *n){
	return n - lNFuncList;
}

/*\
 | Symbolic procedures
\*/
extern lSymbol  lSymbolList [SYM_MAX];
extern lSymbol *lSymbolFFree;
extern uint     lSymbolActive;
extern uint     lSymbolMax;

extern lSymbol *symType;
extern lSymbol *symArguments;
extern lSymbol *symCode;
extern lSymbol *symData;
extern lSymbol *symName;
extern lSymbol *symRef;

extern lSymbol *lSymLTNil;
extern lSymbol *lSymLTBool;
extern lSymbol *lSymLTPair;
extern lSymbol *lSymLTLambda;
extern lSymbol *lSymLTInt;
extern lSymbol *lSymLTFloat;
extern lSymbol *lSymLTString;
extern lSymbol *lSymLTSymbol;
extern lSymbol *lSymLTKeyword;
extern lSymbol *lSymLTNativeFunction;
extern lSymbol *lSymLTEnvironment;
extern lSymbol *lSymLTMacro;
extern lSymbol *lSymLTArray;
extern lSymbol *lSymLTTree;
extern lSymbol *lSymLTMap;
extern lSymbol *lSymLTBytecodeArray;
extern lSymbol *lSymLTBuffer;
extern lSymbol *lSymLTBufferView;
extern lSymbol *lSymLTFileHandle;
extern lSymbol *lSymLTUnknownType;
extern lSymbol *lSymLTType;
extern lSymbol *lSymLTAny;

extern lSymbol *symNull;
extern lSymbol *symQuote;
extern lSymbol *symQuasiquote;
extern lSymbol *symUnquote;
extern lSymbol *symUnquoteSplicing;
extern lSymbol *symArr;
extern lSymbol *symTreeNew;
extern lSymbol *symMapNew;
extern lSymbol *symDocumentation;
extern lSymbol *symPure;
extern lSymbol *symFold;

extern lSymbol *lSymVMError;


void      lSymbolInit   ();
void      lSymbolFree   (lSymbol *s);

lSymbol  *getTypeSymbol (const lVal a);
lSymbol  *getTypeSymbolT(const lType T);

lNFunc *         lNFuncAlloc         ();
lBytecodeArray * lBytecodeArrayAlloc (size_t len);
lBufferView *    lBufferViewAlloc    (lBuffer *buf, lBufferViewType type, size_t offset, size_t length, bool immutable);
int              lBufferViewTypeSize (lBufferViewType T);

lTree *lTreeNew    (const lSymbol *s, lVal v);
lTree *lTreeDup    (const lTree *t);
int    lTreeSize   (const lTree *t);
lVal   lTreeRef    (const lTree *t, const lSymbol *s);
lTree *lTreeInsert (lTree *t, const lSymbol *s, lVal v);

lVal lnfArrNew  (lVal v);
lVal lnfTreeNew(lVal v);
lVal lnfMapNew(lVal v);
u32  lHashString(const char *str, i32 len);
lVal lnfSerialize(lVal val);
lVal lnfDeserialize(lVal val);

/*\
 |  Operations
\*/
void lOperationsArithmetic ();
void lOperationsBuffer     ();
void lOperationsCore       ();
void lOperationsSpecial    ();
void lOperationsGeneric    ();
void lOperationsTree       ();
void lOperationsMap        ();
void lOperationsArray      ();
void lOperationsString     ();
void lOperationsBytecode   ();

lVal lValBytecodeOp(lBytecodeOp v);
lVal lGenericRef(lVal col, lVal key);
lVal lGenericSet(lVal col, lVal key, lVal v);

void lTypesInit();
lVal lMethodLookup(const lSymbol *method, lVal self);

#endif