<commit_before>#define _DEFAULT_SOURCE
#include "lua_object.h"
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#include <stdio.h>

#include <string.h>

#include "../scene.h"
#include "../global.h"

#include "globlua.h"

#include "lua_vector.h"
#include "lua_colliders.h"
#include "lua_scene.h"
#include "lua_input.h"

#define TYPE_NAME "object"

struct cdata{
	size_t len;
	char* data;
};

int dumpwriter(lua_State* l, const void* p, size_t sz, void* ud)
{
	UNUSED(l);
	struct cdata* d = (struct cdata*)ud;
	void* t = realloc(d->data, d->len + sz);
	d->data = t;
	memcpy(d->data + d->len, p, sz);
	d->len += sz;
	return 0;
}

const char* dumpreader(lua_State* l, void* data, size_t* sz)
{
	UNUSED(l);
	struct cdata* d = (struct cdata*)data;
	*sz = d->len;
	return d->data;
}

void dup_lua_table(lua_State* l1, lua_State* l2)
{
	size_t n = 0;
	lua_newtable(l2);
	lua_pushnil(l1);
	while(lua_next(l1, -2) != 0) {
		const char* key = lua_tolstring(l1, -2, NULL);
		lua_pushstring(l2, key);

		struct cdata dat = { 0, NULL };
		int dumpres = lua_dump(l1, dumpwriter, &dat);
		if(dumpres != 0) {
			luaL_error(l1, "Dump failed");
		}
		int loadres = lua_load(l2, dumpreader, &dat, key);
		if(loadres != 0) {
			luaL_error(l1, "Load failed");
		}
		free(dat.data);

		lua_pop(l1, 1);

		lua_rawset(l2, -3);
		n++;
	}
	lua_pop(l1, 1);
}

void add_behaviour(lua_State* l, object* o, const char* name)
{
	behaviour* obj_threads = (behaviour*)o->tag;
	size_t num_behaviours = 0;
	if(obj_threads != NULL) {
		while(obj_threads[num_behaviours++].name != NULL) {
			const char* behn = obj_threads[num_behaviours++].name;
			if(name != NULL && strcmp(behn, name) == 0) {
				luaL_error(l, "Object already has this behaviour");
			}
		}
	} else {
		num_behaviours = 1;
	}

	behaviour* n = (behaviour*)realloc(obj_threads,
			(num_behaviours+1) * sizeof(behaviour));
	if (n == NULL) {
		luaL_error(l, "Memory allocation error.");
	}
	o->tag = n; obj_threads = n;
	obj_threads[num_behaviours].name = NULL;
	obj_threads[num_behaviours].thread = NULL;

	obj_threads[num_behaviours-1].name = strdup(name);
	obj_threads[num_behaviours-1].thread = luaL_newstate();
	lua_State* t = obj_threads[num_behaviours-1].thread;
	luaL_openlibs(t);
	luaG_register_all(t, get_scene_registry(l), get_input_registry(l));

	lua_pushstring(l, "geng.behaviours");
	lua_rawget(l, LUA_REGISTRYINDEX);
	if(lua_isnil(l, -1)) {
		luaL_error(l, "No behaviour table");
	}

	lua_pushstring(t, "geng.behaviours");
	dup_lua_table(l, t);
	lua_rawset(t, LUA_REGISTRYINDEX);
	lua_pop(l, -1);

	lua_pushstring(l, "geng.prefabs");
	lua_rawget(l, LUA_REGISTRYINDEX);
	if(lua_isnil(l, -1)) {
		luaL_error(l, "No prefab table");
	}

	lua_pushstring(t, "geng.prefabs");
	dup_lua_table(l, t);
	lua_rawset(t, LUA_REGISTRYINDEX);
	lua_pop(l, -1);

	lua_pushstring(t, "geng.behaviours");
	lua_rawget(t, LUA_REGISTRYINDEX);

	lua_pushstring(t, name);
	lua_rawget(t, -2);
	if(lua_isnil(t, -1)) {
		// Reset thread state
		lua_pop(t, 2);
		luaL_error(l, "Unknown behaviour.");
	}

	int run_result = lua_resume(t, 0);
	switch(run_result) {
		case 0:
		case LUA_YIELD: {
			// OK
			return;
			}
		case LUA_ERRRUN:
		case LUA_ERRMEM:
		case LUA_ERRERR:{
			const char* error = lua_tolstring(t, -1, NULL);
			luaL_error(l, error);
			}
	}
	return;
}



object_ref* luaG_checkobject(lua_State* L, int index)
{
	object_ref* o;
	luaL_checktype(L, index, LUA_TUSERDATA);
	o = (object_ref*)luaL_checkudata(L, index, TYPE_NAME);
	if (o == NULL) luaL_typerror(L, index, TYPE_NAME);
	return o;
}

object_ref* luaG_pushobject(lua_State *L, object* obj)
{
	object_ref* o = (object_ref*)lua_newuserdata(L, sizeof(object_ref));
	luaL_getmetatable(L, TYPE_NAME);
	lua_setmetatable(L, -2);
	o->o = obj;
	return o;
}

static int lua_object_delete(lua_State* l)
{
	object_ref* o = luaG_checkobject(l, 1);
	delete_object(o->o->parent, o->o);
	return 0;
}

static int lua_add_behaviour(lua_State* l)
{
	object_ref* o = luaG_checkobject(l, 1);
	const char* name = luaL_checklstring(l, 2, NULL);
	if(name == NULL) {
		luaL_error(l, "Valid behaviour name required");
	}
	add_behaviour(l, o->o, name);
	return 0;
}

static int lua_object_equals(lua_State* l)
{
	object_ref* a = luaG_checkobject(l, 1);
	object_ref* b = luaG_checkobject(l, 2);

	lua_pushboolean(l, a->o == b->o);
	return 1;
}

static int lua_object_tostring(lua_State *L)
{
	object_ref* o = luaG_checkobject(L, 1);
	lua_pushstring(L, o->o->name);
	return 1;
}

static int lua_object_position(lua_State* l)
{<commit_msg>Remove string arg from stack<commit_after>#define _DEFAULT_SOURCE
#include "lua_object.h"
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

#include <stdio.h>

#include <string.h>

#include "../scene.h"
#include "../global.h"

#include "globlua.h"

#include "lua_vector.h"
#include "lua_colliders.h"
#include "lua_scene.h"
#include "lua_input.h"

#define TYPE_NAME "object"

struct cdata{
	size_t len;
	char* data;
};

int dumpwriter(lua_State* l, const void* p, size_t sz, void* ud)
{
	UNUSED(l);
	struct cdata* d = (struct cdata*)ud;
	void* t = realloc(d->data, d->len + sz);
	d->data = t;
	memcpy(d->data + d->len, p, sz);
	d->len += sz;
	return 0;
}

const char* dumpreader(lua_State* l, void* data, size_t* sz)
{
	UNUSED(l);
	struct cdata* d = (struct cdata*)data;
	*sz = d->len;
	return d->data;
}

void dup_lua_table(lua_State* l1, lua_State* l2)
{
	size_t n = 0;
	lua_newtable(l2);
	lua_pushnil(l1);
	while(lua_next(l1, -2) != 0) {
		const char* key = lua_tolstring(l1, -2, NULL);
		lua_pushstring(l2, key);

		struct cdata dat = { 0, NULL };
		int dumpres = lua_dump(l1, dumpwriter, &dat);
		if(dumpres != 0) {
			luaL_error(l1, "Dump failed");
		}
		int loadres = lua_load(l2, dumpreader, &dat, key);
		if(loadres != 0) {
			luaL_error(l1, "Load failed");
		}
		free(dat.data);

		lua_pop(l1, 1);

		lua_rawset(l2, -3);
		n++;
	}
	lua_pop(l1, 1);
}

void add_behaviour(lua_State* l, object* o, const char* name)
{
	behaviour* obj_threads = (behaviour*)o->tag;
	size_t num_behaviours = 0;
	if(obj_threads != NULL) {
		while(obj_threads[num_behaviours++].name != NULL) {
			const char* behn = obj_threads[num_behaviours++].name;
			if(name != NULL && strcmp(behn, name) == 0) {
				luaL_error(l, "Object already has this behaviour");
			}
		}
	} else {
		num_behaviours = 1;
	}

	behaviour* n = (behaviour*)realloc(obj_threads,
			(num_behaviours+1) * sizeof(behaviour));
	if (n == NULL) {
		luaL_error(l, "Memory allocation error.");
	}
	o->tag = n; obj_threads = n;
	obj_threads[num_behaviours].name = NULL;
	obj_threads[num_behaviours].thread = NULL;

	obj_threads[num_behaviours-1].name = strdup(name);
	obj_threads[num_behaviours-1].thread = luaL_newstate();
	lua_State* t = obj_threads[num_behaviours-1].thread;
	luaL_openlibs(t);
	luaG_register_all(t, get_scene_registry(l), get_input_registry(l));

	lua_pushstring(l, "geng.behaviours");
	lua_rawget(l, LUA_REGISTRYINDEX);
	if(lua_isnil(l, -1)) {
		luaL_error(l, "No behaviour table");
	}

	lua_pushstring(t, "geng.behaviours");
	dup_lua_table(l, t);
	lua_rawset(t, LUA_REGISTRYINDEX);
	lua_pop(l, -1);

	lua_pushstring(l, "geng.prefabs");
	lua_rawget(l, LUA_REGISTRYINDEX);
	if(lua_isnil(l, -1)) {
		luaL_error(l, "No prefab table");
	}

	lua_pushstring(t, "geng.prefabs");
	dup_lua_table(l, t);
	lua_rawset(t, LUA_REGISTRYINDEX);
	lua_pop(l, -1);

	lua_pushstring(t, "geng.behaviours");
	lua_rawget(t, LUA_REGISTRYINDEX);

	lua_pushstring(t, name);
	lua_rawget(t, -2);
	if(lua_isnil(t, -1)) {
		// Reset thread state
		lua_pop(t, 2);
		luaL_error(l, "Unknown behaviour.");
	}

	int run_result = lua_resume(t, 0);
	switch(run_result) {
		case 0:
		case LUA_YIELD: {
			// OK
			return;
			}
		case LUA_ERRRUN:
		case LUA_ERRMEM:
		case LUA_ERRERR:{
			const char* error = lua_tolstring(t, -1, NULL);
			luaL_error(l, error);
			}
	}
	return;
}



object_ref* luaG_checkobject(lua_State* L, int index)
{
	object_ref* o;
	luaL_checktype(L, index, LUA_TUSERDATA);
	o = (object_ref*)luaL_checkudata(L, index, TYPE_NAME);
	if (o == NULL) luaL_typerror(L, index, TYPE_NAME);
	return o;
}

object_ref* luaG_pushobject(lua_State *L, object* obj)
{
	object_ref* o = (object_ref*)lua_newuserdata(L, sizeof(object_ref));
	luaL_getmetatable(L, TYPE_NAME);
	lua_setmetatable(L, -2);
	o->o = obj;
	return o;
}

static int lua_object_delete(lua_State* l)
{
	object_ref* o = luaG_checkobject(l, 1);
	delete_object(o->o->parent, o->o);
	return 0;
}

static int lua_add_behaviour(lua_State* l)
{
	object_ref* o = luaG_checkobject(l, 1);
	const char* name = luaL_checklstring(l, 2, NULL);
	if(name == NULL) {
		luaL_error(l, "Valid behaviour name required");
	}
	lua_remove(l, 1);
	add_behaviour(l, o->o, name);
	return 0;
}

static int lua_object_equals(lua_State* l)
{
	object_ref* a = luaG_checkobject(l, 1);
	object_ref* b = luaG_checkobject(l, 2);

	lua_pushboolean(l, a->o == b->o);
	return 1;
}

static int lua_object_tostring(lua_State *L)
{
	object_ref* o = luaG_checkobject(L, 1);
	lua_pushstring(L, o->o->name);
	return 1;
}

static int lua_object_position(lua_State* l)
{
{'fraction_non_alphanumeric': 0.16360822462967056, 'fraction_numerical': 0.011828432456334291, 'mean_word_length': 4.711489898989899, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1253968', 'n_tokens_mistral': 4240, 'n_tokens_neox': 3986, 'n_words': 802}