Skip to content

Commit

Permalink
Consolidate domain name types to NotBlankString
Browse files Browse the repository at this point in the history
The code has replaced multiple instances of generic String types used for domain names with NotBlankString. This enforces a constraint where domain names cannot be blank and reduces redundancy in validations. Any function, struct or enum now requires a non-blank identifier for easier referencing and error-checking. Also, the assert function has been replaced by check for better error handling.
  • Loading branch information
Alexandre Mommers committed Feb 14, 2024
1 parent 0770f9b commit 41129aa
Show file tree
Hide file tree
Showing 69 changed files with 308 additions and 232 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,10 @@ class KlangPlugin : Plugin<Project> {
.map { Triple(it.sourceFile, workingDirectory.resolve(it.sourcePath), it.onSuccess) }
.forEach { (fileToParse, sourcePath, onSuccess) ->
val localFileToParse = File(fileToParse)
assert(localFileToParse.exists()) { "File to parse does not exist" }
assert(localFileToParse.isFile()) { "${localFileToParse.absolutePath} is not a file" }
assert(localFileToParse.canRead()) { "${localFileToParse.absolutePath} is not readable" }
assert(localFileToParse.length() > 0) { "${localFileToParse.absolutePath} is empty" }
check(localFileToParse.exists()) { "File to parse does not exist" }
check(localFileToParse.isFile()) { "${localFileToParse.absolutePath} is not a file" }
check(localFileToParse.canRead()) { "${localFileToParse.absolutePath} is not readable" }
check(localFileToParse.length() > 0) { "${localFileToParse.absolutePath} is empty" }

extension.declarations = when (extension.parsingMethod) {
ParsingMethod.Docker -> {
Expand Down
11 changes: 1 addition & 10 deletions klang/jextract/src/main/kotlin/klang/test.kt
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
package klang

import org.openjdk.jextract.Declaration
import org.openjdk.jextract.JextractTool
import org.openjdk.jextract.impl.CodeGenerator
import org.openjdk.jextract.impl.IncludeHelper
import org.openjdk.jextract.impl.Parser
import org.openjdk.jextract.impl.Writer
import java.io.File
import java.io.IOException
import java.io.UncheckedIOException
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import java.util.stream.Collectors
import java.util.stream.Stream
import javax.tools.JavaFileObject
import kotlin.io.path.exists

fun parse(headers: List<Path>, vararg parserOptions: String?): Declaration.Scoped {
val source = if (headers.size > 1) generateTmpSource(headers) else headers.iterator().next()!!
return Parser().parse(source, Stream.of(*parserOptions).collect(Collectors.toList()))
}

private fun generateTmpSource(headers: List<Path>): Path {
assert(headers.size > 1)
check(headers.size > 1)
try {
val tmpFile = Files.createTempFile("jextract", ".h")
tmpFile.toFile().deleteOnExit()
Expand Down
13 changes: 11 additions & 2 deletions klang/klang/src/main/kotlin/klang/CDefaultDeclaration.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package klang

import klang.domain.FixeSizeType
import klang.domain.NotBlankString
import klang.domain.PlatformDependantSizeType
import klang.domain.VoidType

fun DeclarationRepository.insertCDefaultDeclaration() {
save(VoidType)
save(PlatformDependantSizeType(32..64, "size_t"))
save(PlatformDependantSizeType(32..64, NotBlankString("size_t")))
byteType.forEach { save(FixeSizeType(8, it)) }
shortType.forEach { save(FixeSizeType(16, it)) }
intType.forEach { save(FixeSizeType(32, it)) }
Expand All @@ -19,24 +20,32 @@ fun DeclarationRepository.insertCDefaultDeclaration() {

// 8 bits
private val byteType = listOf("char", "unsigned char", "uint16_t", "int16_t")
.map { NotBlankString(it) }

// 16 bits
private val shortType = listOf("short", "unsigned short", "uint8_t", "int8_t")
.map { NotBlankString(it) }

// 32 bits
private val intType = listOf("int", "unsigned int", "uint32_t", "int32_t")
.map { NotBlankString(it) }

// 32 to 64 bits
private val longType = listOf("long", "unsigned long")
.map { NotBlankString(it) }

// 32 to 64 bits
private val charType = listOf("wchar_t")
.map { NotBlankString(it) }

// 64 bits
private val int64Type = listOf("uint64_t", "int64_t")
.map { NotBlankString(it) }

// 32 bits
private val floatType = listOf("float")
.map { NotBlankString(it) }

// 64 bits
private val doubleType = listOf("double")
private val doubleType = listOf("double")
.map { NotBlankString(it) }
28 changes: 20 additions & 8 deletions klang/klang/src/main/kotlin/klang/DeclarationRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ val libraryDeclarationsFilter: (ResolvableDeclaration) -> Boolean = { resolvabl
}
}

val allDeclarationsFilter: (ResolvableDeclaration) -> Boolean = { _ -> true }

interface DeclarationRepository {

val declarations: Set<NativeDeclaration>
Expand All @@ -18,27 +20,37 @@ interface DeclarationRepository {
fun update(nativeEnumeration: NativeDeclaration, provider: () -> NativeDeclaration): NativeDeclaration
fun resolveTypes(filter: (ResolvableDeclaration) -> Boolean = libraryDeclarationsFilter)

fun findEnumerationByName(name: String) = findDeclarationByName<NativeEnumeration>(name)
fun findEnumerationByName(name: String) = findEnumerationByName(NotBlankString(name))
fun findEnumerationByName(name: NotBlankString) = findDeclarationByName<NativeEnumeration>(name)

fun findStructureByName(name: String) = findDeclarationByName<NativeStructure>(name)
fun findStructureByName(name: String) = findStructureByName(NotBlankString(name))
fun findStructureByName(name: NotBlankString) = findDeclarationByName<NativeStructure>(name)

fun findFunctionByName(name: String) = findDeclarationByName<NativeFunction>(name)
fun findFunctionByName(name: String) = findFunctionByName(NotBlankString(name))
fun findFunctionByName(name: NotBlankString) = findDeclarationByName<NativeFunction>(name)

fun findTypeAliasByName(name: String) = findDeclarationByName<NativeTypeAlias>(name)
fun findTypeAliasByName(name: String) = findTypeAliasByName(NotBlankString(name))
fun findTypeAliasByName(name: NotBlankString) = findDeclarationByName<NativeTypeAlias>(name)

fun findObjectiveCClassByName(name: String) = findDeclarationByName<ObjectiveCClass>(name)
fun findObjectiveCClassByName(name: String) = findObjectiveCClassByName(NotBlankString(name))
fun findObjectiveCClassByName(name: NotBlankString) = findDeclarationByName<ObjectiveCClass>(name)

fun findObjectiveCProtocolByName(name: String) = findDeclarationByName<ObjectiveCProtocol>(name)
fun findObjectiveCProtocolByName(name: String) = findObjectiveCProtocolByName(NotBlankString(name))
fun findObjectiveCProtocolByName(name: NotBlankString) = findDeclarationByName<ObjectiveCProtocol>(name)

fun findObjectiveCCategoryByName(name: String) = findDeclarationByName<ObjectiveCCategory>(name)
fun findObjectiveCCategoryByName(name: String) = findObjectiveCCategoryByName(NotBlankString(name))
fun findObjectiveCCategoryByName(name: NotBlankString) = findDeclarationByName<ObjectiveCCategory>(name)

fun findLibraryDeclaration() = declarations.asSequence()
.filterIsInstance<SourceableDeclaration>()
.filter { it.source is DeclarationOrigin.LibraryHeader }
.toList()
}

inline fun <reified T : NameableDeclaration> DeclarationRepository.findDeclarationByName(declarationName: String) = declarations

inline fun <reified T : NameableDeclaration> DeclarationRepository.findDeclarationByName(declarationName: String) = findDeclarationByName<T>(NotBlankString(declarationName))

inline fun <reified T : NameableDeclaration> DeclarationRepository.findDeclarationByName(declarationName: NotBlankString) = declarations
.asSequence()
.filterIsInstance<T>()
.firstOrNull { it.name == declarationName }
33 changes: 17 additions & 16 deletions klang/klang/src/main/kotlin/klang/ObjectiveCDefaultDeclarations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,32 @@ package klang

import klang.domain.DeclarationOrigin
import klang.domain.NameableDeclaration
import klang.domain.NotBlankString
import klang.domain.ObjectiveCProtocol

object ObjectiveCRootClass: NameableDeclaration {
override val name: String = "NSObject"
override val name: NotBlankString = NotBlankString("NSObject")
override val source: DeclarationOrigin = DeclarationOrigin.PlatformHeader
}


fun DeclarationRepository.insertObjectiveCDefaultDeclaration() {
save(ObjectiveCRootClass)
// TODO: insert default declarations with correct method
save(ObjectiveCProtocol("NSSecureCoding", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSXPCProxyCreating", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSLocking", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSProgressReporting", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSStream", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSProxy", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSXMLNode", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSClassDescription", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSUserScriptTask", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSSecureCoding"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSXPCProxyCreating"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSLocking"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSProgressReporting"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSStream"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSProxy"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSXMLNode"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSClassDescription"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSUserScriptTask"), setOf(), listOf(), listOf()))

save(ObjectiveCProtocol("NSScanner", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSOrderedSet", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSMutableOrderedSet", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSProcessInfo", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSXMLParser", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol("NSProtocolChecker", setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSScanner"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSOrderedSet"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSMutableOrderedSet"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSProcessInfo"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSXMLParser"), setOf(), listOf(), listOf()))
save(ObjectiveCProtocol(NotBlankString("NSProtocolChecker"), setOf(), listOf(), listOf()))
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ sealed interface NativeDeclaration {
* This interface represents a nameable declaration.
*/
interface NameableDeclaration : SourceableDeclaration {
val name: String
val name: NotBlankString
}

interface ResolvableDeclaration {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import klang.DeclarationRepository
val AnonymousEnumeration = "AnonymousEnumeration"

data class NativeEnumeration(
override val name: String,
override val name: NotBlankString,
var values: List<Pair<String, Long>> = emptyList(),
//TODO add support for other types
var type: TypeRef = typeOf("int").unchecked("Type 'int' not found"),
Expand Down
2 changes: 1 addition & 1 deletion klang/klang/src/main/kotlin/klang/domain/NativeFunction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package klang.domain
import klang.DeclarationRepository

data class NativeFunction(
override val name: String,
override val name: NotBlankString,
var returnType: TypeRef,
val arguments: List<Argument>,
override val source: DeclarationOrigin = DeclarationOrigin.UnknownOrigin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data class SubStructureField(override val name: String, val structure: NativeStr
* @property isUnion Indicates whether the structure is a union
*/
data class NativeStructure(
override val name: String,
override val name: NotBlankString,
var fields: List<StructureField> = listOf(),
var isUnion: Boolean = false,
override val source: DeclarationOrigin = DeclarationOrigin.UnknownOrigin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package klang.domain
import klang.DeclarationRepository

data class NativeTypeAlias(
override val name: String,
override val name: NotBlankString,
var typeRef: TypeRef,
override val source: DeclarationOrigin = DeclarationOrigin.UnknownOrigin
) :NameableDeclaration, NativeDeclaration, ResolvableDeclaration {
Expand Down
2 changes: 1 addition & 1 deletion klang/klang/src/main/kotlin/klang/domain/NativeVariable.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package klang.domain

data class NativeVariable(
override val name: String,
override val name: NotBlankString,
val type: String,
override val source: DeclarationOrigin
): NameableDeclaration, NativeDeclaration
16 changes: 16 additions & 0 deletions klang/klang/src/main/kotlin/klang/domain/NotBlankString.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package klang.domain

fun notBlankString(value: String) = value.takeIf(String::isNotBlank)
?.let { NotBlankString(value) }

@JvmInline
value class NotBlankString(val value: String) : Comparable<String> by value {

init {
check(value.isNotBlank()) { error("value cannot be blank")}
}

override fun toString(): String {
return value
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import klang.DeclarationRepository
internal val AnonymousCategoryName = "AnonymousCategory"

data class ObjectiveCCategory(
override val name: String,
override val name: NotBlankString,
var superType: TypeRef,
val methods: List<ObjectiveCClass.Method>,
override val source: DeclarationOrigin = DeclarationOrigin.UnknownOrigin
Expand Down
8 changes: 4 additions & 4 deletions klang/klang/src/main/kotlin/klang/domain/ObjectiveCClass.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package klang.domain
import klang.DeclarationRepository

data class ObjectiveCClass(
override val name: String,
override val name: NotBlankString,
var superType: TypeRef?,
var protocols: Set<TypeRef>,
var properties: List<Property>,
Expand All @@ -13,7 +13,7 @@ data class ObjectiveCClass(
) : NameableDeclaration, ResolvableDeclaration {

data class Property(
override val name: String,
override val name: NotBlankString,
val type: String,
val assign: Boolean? = null,
val readwrite: Boolean? = null,
Expand All @@ -23,7 +23,7 @@ data class ObjectiveCClass(
) : NameableDeclaration

data class Method(
override val name: String,
override val name: NotBlankString,
var returnType: TypeRef,
val instance: Boolean,
val arguments: List<Argument> = listOf(),
Expand Down Expand Up @@ -61,7 +61,7 @@ data class ObjectiveCClass(
categories = declarations
.asSequence()
.filterIsInstance<ObjectiveCCategory>()
.filter { it.superType.referenceAsString == name }
.filter { it.superType.referenceAsString == name.value }
.toSet()

methods.forEach { with(it) { resolve() } }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package klang.domain

data class ObjectiveCProtocol(
override val name: String,
override val name: NotBlankString,
val protocols: Set<String>,
var properties: List<ObjectiveCClass.Property>,
var methods: List<ObjectiveCClass.Method>,
Expand Down
8 changes: 4 additions & 4 deletions klang/klang/src/main/kotlin/klang/domain/PrimitiveType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ package klang.domain
sealed class PrimitiveType: NameableDeclaration

data object VoidType: PrimitiveType() {
override val name: String = "void"
override val name: NotBlankString = NotBlankString("void")
override val source: DeclarationOrigin = DeclarationOrigin.PlatformHeader
}

class FixeSizeType(val size: Int, override val name: String, val isFloating: Boolean = false, override val source: DeclarationOrigin = DeclarationOrigin.PlatformHeader): PrimitiveType()
class PlatformDependantSizeType(val size: IntRange, override val name: String, override val source: DeclarationOrigin = DeclarationOrigin.PlatformHeader): PrimitiveType()
class FixeSizeType(val size: Int, override val name: NotBlankString, val isFloating: Boolean = false, override val source: DeclarationOrigin = DeclarationOrigin.PlatformHeader): PrimitiveType()
class PlatformDependantSizeType(val size: IntRange, override val name: NotBlankString, override val source: DeclarationOrigin = DeclarationOrigin.PlatformHeader): PrimitiveType()

data object StringType: PrimitiveType() {
override val name: String = "char *"
override val name: NotBlankString = NotBlankString("char *")
override val source: DeclarationOrigin = DeclarationOrigin.PlatformHeader
}

Expand Down
Loading

0 comments on commit 41129aa

Please sign in to comment.