<commit_before>#include "lovr/event.h"
#include "event/event.h"
#include "util.h"

static int nextEvent(lua_State* L) {
  Event* event = lovrEventPoll();

  if (!event) {
    return 0;
  }

  switch (event->type) {
    case EVENT_QUIT:
      lua_pushstring(L, "quit");
      lua_pushnumber(L, event->data.quit.exitCode);
      return 2;

    case EVENT_CONTROLLER_ADDED: {
      lua_pushstring(L, "controlleradded");
      luax_pushtype(L, Controller, event->data.controlleradded.controller);
      return 2;
   }

    case EVENT_CONTROLLER_REMOVED: {
      lua_pushstring(L, "controllerremoved");
      luax_pushtype(L, Controller, event->data.controllerremoved.controller);
      return 2;
    }

    default:
      return 0;
  }
}

const luaL_Reg lovrEvent[] = {
  { "clear", l_lovrEventClear },
  { "poll", l_lovrEventPoll },
  { "pump", l_lovrEventPump },
  { "push", l_lovrEventPush },
  { "quit", l_lovrEventQuit },
  { NULL, NULL }
};

int l_lovrEventInit(lua_State* L) {
  lua_newtable(L);
  luaL_register(L, NULL, lovrEvent);
  map_init(&EventTypes);
  map_set(&EventTypes, "quit", EVENT_QUIT);
  lovrEventInit();
  return 1;
}

int l_lovrEventClear(lua_State* L) {
  lovrEventClear();
  return 0;
}

int l_lovrEventPoll(lua_State* L) {
  lua_pushcclosure(L, nextEvent, 0);
  return 1;
}

int l_lovrEventPump(lua_State* L) {
  lovrEventPump();
  return 0;
}

int l_lovrEventPush(lua_State* L) {
  EventType type = *(EventType*) luax_checkenum(L, 1, &EventTypes, "event type");
  EventData data;
<commit_msg>Get closure on that lovr.event memory leak;<commit_after>#include "lovr/event.h"
#include "event/event.h"
#include "util.h"

static int pollRef;

static int nextEvent(lua_State* L) {
  Event* event = lovrEventPoll();

  if (!event) {
    return 0;
  }

  switch (event->type) {
    case EVENT_QUIT:
      lua_pushstring(L, "quit");
      lua_pushnumber(L, event->data.quit.exitCode);
      return 2;

    case EVENT_CONTROLLER_ADDED: {
      lua_pushstring(L, "controlleradded");
      luax_pushtype(L, Controller, event->data.controlleradded.controller);
      return 2;
   }

    case EVENT_CONTROLLER_REMOVED: {
      lua_pushstring(L, "controllerremoved");
      luax_pushtype(L, Controller, event->data.controllerremoved.controller);
      return 2;
    }

    default:
      return 0;
  }
}

const luaL_Reg lovrEvent[] = {
  { "clear", l_lovrEventClear },
  { "poll", l_lovrEventPoll },
  { "pump", l_lovrEventPump },
  { "push", l_lovrEventPush },
  { "quit", l_lovrEventQuit },
  { NULL, NULL }
};

int l_lovrEventInit(lua_State* L) {
  lua_newtable(L);
  luaL_register(L, NULL, lovrEvent);

  // Store nextEvent in the registry to avoid creating a closure every time we poll for events.
  lua_pushcfunction(L, nextEvent);
  pollRef = luaL_ref(L, LUA_REGISTRYINDEX);

  map_init(&EventTypes);
  map_set(&EventTypes, "quit", EVENT_QUIT);
  lovrEventInit();
  return 1;
}

int l_lovrEventClear(lua_State* L) {
  lovrEventClear();
  return 0;
}

int l_lovrEventPoll(lua_State* L) {
  lua_rawgeti(L, LUA_REGISTRYINDEX, pollRef);
  return 1;
}

int l_lovrEventPump(lua_State* L) {
  lovrEventPump();
  return 0;
}

int l_lovrEventPush(lua_State* L) {
  EventType type = *(EventType*) luax_checkenum(L, 1, &EventTypes, "event type");
  EventData data;

{'fraction_non_alphanumeric': 0.13359828798532558, 'fraction_numerical': 0.0064200550290431065, 'mean_word_length': 3.9129129129129128, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, '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': '3344912', 'n_tokens_mistral': 1311, 'n_tokens_neox': 1256, 'n_words': 250}