/* [ʞ] src/gdjn.h
 *  ~ lexi hale <lexi@hale.su>
 *  🄯 AGPLv3
 *  ? core types and declarations used by gdjn
 */

#pragma once
#include <assert.h>
#include <stdint.h>
#include "janet.h"
#include "interface.h"

typedef void (*GDExtensionInterfacePrintError)(const char *p_description, const char *p_function, const char *p_file, int32_t p_line, GDExtensionBool p_editor_notify);

#define _emit(fn, msg) \
	(gdjn_ctx -> gd.fn((msg), __func__, __FILE__, __LINE__, true))
#define _warn(msg) _emit(warn, msg)
#define _err(msg)  _emit(err, msg)

typedef GDExtensionBool gdBool;

#define _alloc(ty, n) \
	((typeof(ty)*)gdjn_alloc(sizeof(ty) * (n)))
#define _realloc(v, ty, n) \
	((typeof(ty)*)gdjn_realloc((v), sizeof(ty) * (n)))
#define _free(v) \
	(gdjn_ctx -> gd.free(v))
#define _sz(r) ((sizeof(r) / sizeof(*r)))

#define _t(T) \
	(gdjn_ctx -> gd.t.gd_##T)
#define _method(name) \
	static void name  \
	(	GDExtensionClassInstancePtr self,    \
		const GDExtensionConstTypePtr* argv, \
		GDExtensionTypePtr ret               \
	)


typedef struct gdjn {
	struct gdjn_gd {
		GDExtensionClassLibraryPtr lib;

		GDExtensionInterfaceGetProcAddress getProc;

		GDExtensionInterfaceMemAlloc   alloc;
		GDExtensionInterfaceMemRealloc realloc;
		GDExtensionInterfaceMemFree    free;

		GDExtensionInterfacePrintError err;
		GDExtensionInterfacePrintErrorWithMessage errMsg;
		GDExtensionInterfacePrintWarning warn;
		GDExtensionInterfacePrintWarningWithMessage warnMsg;

		GDExtensionInterfaceGetVariantFromTypeConstructor
			wrap;
		GDExtensionInterfaceGetVariantToTypeConstructor
			cast;

		gdjn_typeDB t;
		gd_array dox;

		GDExtensionObjectPtr
			janetLang_inst,
			janetLoader_inst,
			janetSaver_inst;
	} gd;
	struct gdjn_jn {
		JanetTable* api;
	} jn;
} gdjn;

extern gdjn* gdjn_ctx;

[[gnu::alloc_size(1)]] static inline
void* gdjn_alloc(size_t sz) {
	return gdjn_ctx -> gd.alloc(sz);
}
[[gnu::alloc_size(2)]] static inline
void* gdjn_realloc(void* v, size_t sz) {
	return gdjn_ctx -> gd.realloc(v, sz);
}


typedef struct gdjn_gd gdjn_gd; // derp
typedef struct gdjn_jn gdjn_jn;

typedef struct gdjn_class_def gdjn_class_def;

void
gdjn_dox
(	gd_dictionary* page
);
