<commit_before>/*
 * Copyright LWJGL. All rights reserved.
 * License terms: http://lwjgl.org/license.php
 */
package org.lwjgl.generator

import java.io.*
import java.lang.Math.max
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.nio.ByteBuffer
import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors

/*
	A template will be generated in the following cases:

	- The target Java source does not exist.
	- The source template has a later timestamp than the target.
	- Any file in the source package has later timestamp than the target.
	- Any file in the generator itself has later timestamp than the target. (implies re-generation of all templates)

	Example template: /src/main/kotlin/org/lwjgl/opengl/templates/ARB_imaging.kt

	- Generator source      -> /src/main/kotlin/org/lwjgl/generator/
	- Source package        -> /src/main/kotlin/org/lwjgl/opengl/
	- Source template       -> /src/main/kotlin/org/lwjgl/opengl/templates/ARB_imaging.kt

	- Target source (Java)  -> modules/core/src/generated/java/org/lwjgl/opengl/ARBImaging.java
	- Target source (C)     -> modules/core/src/generated/c/opengl/org_lwjgl_opengl_ARBImaging.c
*/

private val DUMMY_PACKAGE = "*"

enum class Binding(val key: String, val packageName: String) {
	EGL("binding.egl", "org.lwjgl.egl"),
	GLFW("binding.glfw", "org.lwjgl.glfw"),
	JAWT("binding.jawt", "org.lwjgl.system.jawt"),
	NANOVG("binding.nanovg", "org.lwjgl.nanovg"),
	NFD("binding.nfd", "org.lwjgl.util.nfd"),
	OPENAL("binding.openal", "org.lwjgl.openal"),
	OPENCL("binding.opencl", "org.lwjgl.opencl"),
	OPENGL("binding.opengl", "org.lwjgl.opengl"),
	OPENGLES("binding.opengles", "org.lwjgl.opengles"),
	OVR("binding.ovr", "org.lwjgl.ovr"),
	PAR("binding.par", "org.lwjgl.util.par"),
	STB("binding.stb", "org.lwjgl.stb"),
	VULKAN("binding.vulkan", "org.lwjgl.vulkan"),

	MACOSX_OBJC("binding.macosx.objc", DUMMY_PACKAGE);

	val enabled: Boolean
		get() = System.getProperty(key, "false").toBoolean()
}

fun dependsOn(binding: Binding, init: () -> NativeClass): NativeClass? = if ( binding.enabled ) init() else null

fun main(args: Array<String>) {
	if ( args.size < 2 )
		throw IllegalArgumentException("The code Generator requires 2 paths as arguments: a) the template source path and b) the generation target path")

	val validateDirectory = { name: String, path: String ->
		if ( !File(path).isDirectory )
			throw IllegalArgumentException("Invalid $name path: $path")
	}

	validateDirectory("template source", args[0])
	validateDirectory("generation target", args[1])

	// Makes sure we use \n during generation, even on Windows.
	System.setProperty("line.separator", "\n")

	Generator(args[0], args[1]) {
		// We discover templates reflectively.
		// For a package passed to the generate function, we
		// search for a <package>.templates.TemplatesPackage class file
		// and run any public static methods that return a NativeClass object.

		// Note: For a Kotlin package X.Y.Z, <Z>Package is the class Kotlin generates that contains
		// all top-level functions/properties in that package. Example:
		// org.lwjgl.opengl -> org.lwjgl.opengl.OpenglPackage (the first letter is capitalized)

		val pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())

		// Generate bindings

		val bindingsSystem = arrayOf(
			"org.lwjgl.system.jemalloc",
			"org.lwjgl.system.libc",
			"org.lwjgl.system.libffi",
			"org.lwjgl.system.linux",
			"org.lwjgl.system.macosx",
			"org.lwjgl.system.windows",

			"org.lwjgl.util.simd",
			"org.lwjgl.util.xxhash"
		)
		val bindingsModular = Binding.values().asSequence().filter { it.packageName !== DUMMY_PACKAGE }

		CountDownLatch(bindingsSystem.size + bindingsModular.count()).let { latch ->
			fun generate(packageName: String, binding: Binding? = null) {
				pool.submit {
					this@Generator.generate(packageName, binding)
					latch.countDown()
				}
			}

			bindingsSystem.forEach { generate(it) }
			bindingsModular.forEach { generate(it.packageName, it) }

			latch.await()
		}

		// Generate utility classes. These are auto-registered during the process above.

		CountDownLatch(4).let { latch ->
			fun submit(work: () -> Unit) {
				pool.submit(work)
				latch.countDown()
			}

			submit { generate("struct", Generator.structs) }
			submit { generate("callback", Generator.callbacks) }
			submit { generate("custom class", Generator.customClasses) }

			submit { generate(JNI) }

			latch.await()
		}

		pool.shutdown()
	}
}

class Generator(
	val srcPath: String,
	val trgPath: String,
	generate: Generator.() -> Unit
) {

	companion object {
		val structs = ArrayList<Struct>()
		val callbacks = ArrayList<CallbackFunction>()
		val customClasses = ArrayList<GeneratorTarget>()
<commit_msg>Catch and print generation exceptions<commit_after>/*
 * Copyright LWJGL. All rights reserved.
 * License terms: http://lwjgl.org/license.php
 */
package org.lwjgl.generator

import java.io.*
import java.lang.Math.max
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.nio.ByteBuffer
import java.util.*
import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors

/*
	A template will be generated in the following cases:

	- The target Java source does not exist.
	- The source template has a later timestamp than the target.
	- Any file in the source package has later timestamp than the target.
	- Any file in the generator itself has later timestamp than the target. (implies re-generation of all templates)

	Example template: /src/main/kotlin/org/lwjgl/opengl/templates/ARB_imaging.kt

	- Generator source      -> /src/main/kotlin/org/lwjgl/generator/
	- Source package        -> /src/main/kotlin/org/lwjgl/opengl/
	- Source template       -> /src/main/kotlin/org/lwjgl/opengl/templates/ARB_imaging.kt

	- Target source (Java)  -> modules/core/src/generated/java/org/lwjgl/opengl/ARBImaging.java
	- Target source (C)     -> modules/core/src/generated/c/opengl/org_lwjgl_opengl_ARBImaging.c
*/

private val DUMMY_PACKAGE = "*"

enum class Binding(val key: String, val packageName: String) {
	EGL("binding.egl", "org.lwjgl.egl"),
	GLFW("binding.glfw", "org.lwjgl.glfw"),
	JAWT("binding.jawt", "org.lwjgl.system.jawt"),
	NANOVG("binding.nanovg", "org.lwjgl.nanovg"),
	NFD("binding.nfd", "org.lwjgl.util.nfd"),
	OPENAL("binding.openal", "org.lwjgl.openal"),
	OPENCL("binding.opencl", "org.lwjgl.opencl"),
	OPENGL("binding.opengl", "org.lwjgl.opengl"),
	OPENGLES("binding.opengles", "org.lwjgl.opengles"),
	OVR("binding.ovr", "org.lwjgl.ovr"),
	PAR("binding.par", "org.lwjgl.util.par"),
	STB("binding.stb", "org.lwjgl.stb"),
	VULKAN("binding.vulkan", "org.lwjgl.vulkan"),

	MACOSX_OBJC("binding.macosx.objc", DUMMY_PACKAGE);

	val enabled: Boolean
		get() = System.getProperty(key, "false").toBoolean()
}

fun dependsOn(binding: Binding, init: () -> NativeClass): NativeClass? = if ( binding.enabled ) init() else null

fun main(args: Array<String>) {
	if ( args.size < 2 )
		throw IllegalArgumentException("The code Generator requires 2 paths as arguments: a) the template source path and b) the generation target path")

	val validateDirectory = { name: String, path: String ->
		if ( !File(path).isDirectory )
			throw IllegalArgumentException("Invalid $name path: $path")
	}

	validateDirectory("template source", args[0])
	validateDirectory("generation target", args[1])

	// Makes sure we use \n during generation, even on Windows.
	System.setProperty("line.separator", "\n")

	Generator(args[0], args[1]) {
		// We discover templates reflectively.
		// For a package passed to the generate function, we
		// search for a <package>.templates.TemplatesPackage class file
		// and run any public static methods that return a NativeClass object.

		// Note: For a Kotlin package X.Y.Z, <Z>Package is the class Kotlin generates that contains
		// all top-level functions/properties in that package. Example:
		// org.lwjgl.opengl -> org.lwjgl.opengl.OpenglPackage (the first letter is capitalized)

		val pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())

		// Generate bindings

		val bindingsSystem = arrayOf(
			"org.lwjgl.system.jemalloc",
			"org.lwjgl.system.libc",
			"org.lwjgl.system.libffi",
			"org.lwjgl.system.linux",
			"org.lwjgl.system.macosx",
			"org.lwjgl.system.windows",

			"org.lwjgl.util.simd",
			"org.lwjgl.util.xxhash"
		)
		val bindingsModular = Binding.values().asSequence().filter { it.packageName !== DUMMY_PACKAGE }

		CountDownLatch(bindingsSystem.size + bindingsModular.count()).let { latch ->
			fun generate(packageName: String, binding: Binding? = null) {
				pool.submit {
					try {
						this@Generator.generate(packageName, binding)
					} catch(e: Exception) {
						e.printStackTrace()
					}
					latch.countDown()
				}
			}

			bindingsSystem.forEach { generate(it) }
			bindingsModular.forEach { generate(it.packageName, it) }

			latch.await()
		}

		// Generate utility classes. These are auto-registered during the process above.

		CountDownLatch(4).let { latch ->
			fun submit(work: () -> Unit) {
				try {
					pool.submit(work)
				} catch(e: Exception) {
					e.printStackTrace()
				}
				latch.countDown()
			}

			submit { generate("struct", Generator.structs) }
			submit { generate("callback", Generator.callbacks) }
			submit { generate("custom class", Generator.customClasses) }

			submit { generate(JNI) }

			latch.await()
		}

		pool.shutdown()
	}
}

class Generator(
	val srcPath: String,
	val trgPath: String,
	generate: Generator.() -> Unit
) {

	companion object {
		val structs = ArrayList<Struct>()
		val callbacks = ArrayList<CallbackFunction>()
		val customClasses = ArrayList<GeneratorTarget>()

{'fraction_non_alphanumeric': 0.13601808095335935, 'fraction_numerical': 0.0014382576535853708, 'mean_word_length': 3.979539641943734, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, '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': '3402823', 'n_tokens_mistral': 3582, 'n_tokens_neox': 3285, 'n_words': 748}