module wasm;

import ldc.attributes;

import dlib.util;
import std.format;

enum SprintfType : size_t
{
	None,
	U8,
	I8,
	U16,
	I16,
	U32,
	I32,
	U64,
	I64,
	SizeT,
	F32,
	F64,
	Bool,
	String,
	U8Array,
	I8Array,
	U16Array,
	I16Array,
	U32Array,
	I32Array,
	U64Array,
	I64Array,
	F32Array,
	F64Array,
	Char,
	CharArray,
	Pointer,
}

template WasmModule(string _module)
{
	enum WasmModule = llvmAttr("wasm-import-module", _module);
}

template WasmName(string name)
{
	enum WasmName = llvmAttr("wasm-import-name", name);
}

extern extern(C) @WasmModule!("env"):

@WasmName!("Console") void
Console(string str, bool write_line);

@WasmName!("Console2") void
Console2(size_t length, const(void)* ptr, bool write_line);

@WasmName!("Abort") void
Abort(string message) @nogc;

@WasmName!("SprintfLoadValue") void 
SprintfLoadValue(const(void)* ptr, SprintfType type) @nogc;

@WasmName!("SprintfLoadArray") void 
SprintfLoadArray(size_t length, const(void)* ptr, SprintfType type) @nogc;

@WasmName!("SprintfEnd") size_t
SprintfEnd(char[] buffer, string format) @nogc;

@WasmName!("pow") double
pow(double base, double exponent) @nogc;

@WasmName!("cos") double
cos(double x) @nogc;

@WasmName!("acos") double
acos(double x) @nogc;

void
Abortf(Args...)(string fmt, Args args) @nogc
{
	char[1024] buffer;

	string abort_message = Str(sformat(buffer, fmt, args));

	Abort(abort_message);
}

export void 
_start() 
{
	import dlib.alloc;
	import dlib.util;
	import std.format;

	MallocInit(256, 16, (void*).sizeof*2);

	ResetScratch(MB(2));

	char[100] buffer;
	uint[2] arr = [1, 2];
	sformat(buffer, "%s", arr);
}

version(DLIB_TEST) export void 
RunTests()
{
	import dlib;

	DLibTestMath();
	DLibTestUtil();
	DLibTestAlloc();

	Console("Tests succeeded", true);
}
