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

import java.io.PrintWriter
import java.lang.Math.*
import java.util.*
import java.util.regex.Pattern

val EXT_FLAG = ""

val NULL = "{@code NULL}"

enum class CallingConvention(val method: String) {
	DEFAULT("invoke"),
	STDCALL("call") // __stdcall on Windows, default on other systems
}

/**
 * The Generator can be customized with binding-specific overrides using this class. This class must implemented for bindings that are loaded dynamically. It
 * is not necessary for libraries that are static compiled/linked into the LWJGL natives.
 */
abstract class APIBinding(
	packageName: String,
	className: String,
	val callingConvention: CallingConvention = CallingConvention.STDCALL
) : CustomClass(packageName, className) {

	init {
		javaImport(
			"org.lwjgl.system.*",
			"java.util.Set"
		)
	}

	private val _classes: MutableList<NativeClass> = ArrayList()

	protected fun getClasses(
		comparator: (NativeClass, NativeClass) -> Int = { o1, o2 -> o1.templateName.compareTo(o2.templateName) }
	): List<NativeClass> {
		val classes = ArrayList(_classes)
		Collections.sort(classes) { o1, o2 -> comparator(o1, o2) }
		return classes
	}

	override fun getLastModified(root: String): Long {
		return max(
			super.getLastModified(root),
			getDirectoryLastModified("$root/templates")
		)
	}

	fun addCapabilities(clazz: NativeClass) {
		_classes.add(clazz)
	}

	/** If true, different platforms/devices/contexts return different function addresses. */
	open fun isLocal(nativeClass: NativeClass) = false // GL, GLES & EGL are global, CL & AL are local

	/** If false, a capabilities instance is not available in the current thread or process. A parameter must provide the instance. */
	open val hasCurrentCapabilities: Boolean = true // GL has thread-local capabilities, AL has process-wide capabilities (unless ALC_EXT_thread_local_context is used), CL has the ICD.

	open fun generateFunctionAddress(writer: PrintWriter, function: NativeClassFunction) {
		val instanceParameter = if ( hasCurrentCapabilities )
			""
		else {
			try {
				// Use the first ObjectType parameters
				function.getParams() { it.nativeType is ObjectType }.first().name
			} catch (e: Exception) {
				throw IllegalStateException("Neither a Capabilities modifier nor an object parameter were found on function ${function.name}")
			}
		}

		val variable = if ( function.returns.has(Address) ) RESULT else FUNCTION_ADDRESS

		writer.println("\t\tlong $variable = getInstance($instanceParameter).${function.simpleName};")
	}

	abstract fun PrintWriter.generateFunctionGetters(nativeClass: NativeClass)

	// OVERRIDES

	/** Can be overriden to generate additional parameters for the NativeClass constructor. */
	open fun printConstructorParams(writer: PrintWriter, nativeClass: NativeClass) = Unit

	/** Can be overriden to implement custom function address retrieval. */
	open fun getFunctionAddressCall(function: NativeClassFunction) = "provider.getFunctionAddress(\"${function.nativeName}\")"

	/** Can be overriden to generate binding-specific alternative methods. */
	open fun generateAlternativeMethods(
		writer: PrintWriter,
		function: NativeClassFunction,
		transforms: MutableMap<QualifiedType, FunctionTransform<out QualifiedType>>
	) = Unit

	/** Can be overriden to generate binding-specific javadoc. If this function returns false, the default javadoc will be generated. */
	open fun printCustomJavadoc(writer: PrintWriter, function: NativeClassFunction, documentation: String) = false

	/** Can be overriden to implement a custom condition for checking the function address. */
	open fun shouldCheckFunctionAddress(function: NativeClassFunction) = !hasCurrentCapabilities

	/** Can be overriden to add custom parameter checks. */
	open fun addParameterChecks(
		checks: MutableList<String>,
		mode: GenerationMode,
		parameter: Parameter,
		hasTransform: Parameter.(FunctionTransform<Parameter>) -> Boolean
	) = Unit

}

/** An APIBinding without an associated capabilities class.  */
abstract class SimpleBinding(
	callingConvention: CallingConvention
) : APIBinding("n/a", "n/a", callingConvention) {
	override fun getFunctionAddressCall(function: NativeClassFunction) = "checkFunctionAddress(${super.getFunctionAddressCall(function)})"
	override fun PrintWriter.generateContent() = Unit
}

/** Creates a simple APIBinding that stores the shared library and function pointers inside the binding class. The shared library is never unloaded. */
fun simpleBinding(
	libraryName: String,
	libraryExpression: String = "\"$libraryName\"",
	callingConvention: CallingConvention = CallingConvention.DEFAULT
) = object : SimpleBinding(callingConvention) {
	override fun PrintWriter.generateFunctionGetters(nativeClass: NativeClass) {
		val libraryReference = libraryName.toUpperCase()
<commit_msg>Support IgnoreMissing in simple bindings<commit_after>/*
 * Copyright LWJGL. All rights reserved.
 * License terms: http://lwjgl.org/license.php
 */
package org.lwjgl.generator

import java.io.PrintWriter
import java.lang.Math.*
import java.util.*
import java.util.regex.Pattern

val EXT_FLAG = ""

val NULL = "{@code NULL}"

enum class CallingConvention(val method: String) {
	DEFAULT("invoke"),
	STDCALL("call") // __stdcall on Windows, default on other systems
}

/**
 * The Generator can be customized with binding-specific overrides using this class. This class must implemented for bindings that are loaded dynamically. It
 * is not necessary for libraries that are static compiled/linked into the LWJGL natives.
 */
abstract class APIBinding(
	packageName: String,
	className: String,
	val callingConvention: CallingConvention = CallingConvention.STDCALL
) : CustomClass(packageName, className) {

	init {
		javaImport(
			"org.lwjgl.system.*",
			"java.util.Set"
		)
	}

	private val _classes: MutableList<NativeClass> = ArrayList()

	protected fun getClasses(
		comparator: (NativeClass, NativeClass) -> Int = { o1, o2 -> o1.templateName.compareTo(o2.templateName) }
	): List<NativeClass> {
		val classes = ArrayList(_classes)
		Collections.sort(classes) { o1, o2 -> comparator(o1, o2) }
		return classes
	}

	override fun getLastModified(root: String): Long {
		return max(
			super.getLastModified(root),
			getDirectoryLastModified("$root/templates")
		)
	}

	fun addCapabilities(clazz: NativeClass) {
		_classes.add(clazz)
	}

	/** If true, different platforms/devices/contexts return different function addresses. */
	open fun isLocal(nativeClass: NativeClass) = false // GL, GLES & EGL are global, CL & AL are local

	/** If false, a capabilities instance is not available in the current thread or process. A parameter must provide the instance. */
	open val hasCurrentCapabilities: Boolean = true // GL has thread-local capabilities, AL has process-wide capabilities (unless ALC_EXT_thread_local_context is used), CL has the ICD.

	open fun generateFunctionAddress(writer: PrintWriter, function: NativeClassFunction) {
		val instanceParameter = if ( hasCurrentCapabilities )
			""
		else {
			try {
				// Use the first ObjectType parameters
				function.getParams() { it.nativeType is ObjectType }.first().name
			} catch (e: Exception) {
				throw IllegalStateException("Neither a Capabilities modifier nor an object parameter were found on function ${function.name}")
			}
		}

		val variable = if ( function.returns.has(Address) ) RESULT else FUNCTION_ADDRESS

		writer.println("\t\tlong $variable = getInstance($instanceParameter).${function.simpleName};")
	}

	abstract fun PrintWriter.generateFunctionGetters(nativeClass: NativeClass)

	// OVERRIDES

	/** Can be overriden to generate additional parameters for the NativeClass constructor. */
	open fun printConstructorParams(writer: PrintWriter, nativeClass: NativeClass) = Unit

	/** Can be overriden to implement custom function address retrieval. */
	open fun getFunctionAddressCall(function: NativeClassFunction) = "provider.getFunctionAddress(\"${function.nativeName}\")"

	/** Can be overriden to generate binding-specific alternative methods. */
	open fun generateAlternativeMethods(
		writer: PrintWriter,
		function: NativeClassFunction,
		transforms: MutableMap<QualifiedType, FunctionTransform<out QualifiedType>>
	) = Unit

	/** Can be overriden to generate binding-specific javadoc. If this function returns false, the default javadoc will be generated. */
	open fun printCustomJavadoc(writer: PrintWriter, function: NativeClassFunction, documentation: String) = false

	/** Can be overriden to implement a custom condition for checking the function address. */
	open fun shouldCheckFunctionAddress(function: NativeClassFunction) = !hasCurrentCapabilities

	/** Can be overriden to add custom parameter checks. */
	open fun addParameterChecks(
		checks: MutableList<String>,
		mode: GenerationMode,
		parameter: Parameter,
		hasTransform: Parameter.(FunctionTransform<Parameter>) -> Boolean
	) = Unit

}

/** An APIBinding without an associated capabilities class.  */
abstract class SimpleBinding(
	callingConvention: CallingConvention
) : APIBinding("n/a", "n/a", callingConvention) {
	override fun getFunctionAddressCall(function: NativeClassFunction) = super.getFunctionAddressCall(function).let { if ( function.has(IgnoreMissing) ) it else "checkFunctionAddress($it)" }
	override fun PrintWriter.generateContent() = Unit
}

/** Creates a simple APIBinding that stores the shared library and function pointers inside the binding class. The shared library is never unloaded. */
fun simpleBinding(
	libraryName: String,
	libraryExpression: String = "\"$libraryName\"",
	callingConvention: CallingConvention = CallingConvention.DEFAULT
) = object : SimpleBinding(callingConvention) {
	override fun PrintWriter.generateFunctionGetters(nativeClass: NativeClass) {
		val libraryReference = libraryName.toUpperCase()

{'fraction_non_alphanumeric': 0.09452786455708959, 'fraction_numerical': 0.001612415600120931, 'mean_word_length': 5.021844660194175, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 23, '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': '5396702', 'n_tokens_mistral': 2846, 'n_tokens_neox': 2683, 'n_words': 869}