while loop support, and native functions (including ffi!)

This commit is contained in:
2023-09-06 19:07:28 -07:00
parent ddff6cb365
commit 236f812caf
34 changed files with 467 additions and 115 deletions

View File

@ -120,11 +120,12 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
extensionOf = "NodeVisitor<T>",
returnType = "List<T>",
parameters = mutableListOf(
KotlinParameter("nodeLists", type = "List<Node>", vararg = true)
KotlinParameter("nodeLists", type = "List<Node?>", vararg = true)
),
isImmediateExpression = true
)
visitAllFunction.body.add("nodeLists.asSequence().flatten().map { visit(it) }.toList()")
visitAllFunction.body.add(
"nodeLists.asSequence().flatten().filterNotNull().map { visit(it) }.toList()")
visitorExtensionSet.functions.add(visitAllFunction)
write("NodeVisitorExtensions.kt", KotlinWriter(visitorExtensionSet))
@ -239,16 +240,18 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
kotlinClassLike.inherits.add("$parentName()")
}
for (value in type.values) {
val member = KotlinMember(value.name, toKotlinType(value.typeRef))
member.abstract = value.abstract
if (type.isParentAbstract(value)) {
member.overridden = true
if (type.values != null) {
for (value in type.values!!) {
val member = KotlinMember(value.name, toKotlinType(value.typeRef))
member.abstract = value.abstract
if (type.isParentAbstract(value)) {
member.overridden = true
}
if (role == AstTypeRole.ValueHolder) {
member.mutable = true
}
kotlinClassLike.members.add(member)
}
if (role == AstTypeRole.ValueHolder) {
member.mutable = true
}
kotlinClassLike.members.add(member)
}
if (role == AstTypeRole.Enum) {
@ -279,25 +282,26 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
),
isImmediateExpression = true
)
val anyListMembers = type.values.any { it.typeRef.form == AstTypeRefForm.List }
val anyListMembers = type.values?.any { it.typeRef.form == AstTypeRefForm.List } ?: false
val elideVisitChildren: Boolean
if (anyListMembers) {
val visitParameters = type.values.mapNotNull {
val visitParameters = (type.values?.mapNotNull {
if (it.typeRef.primitive != null) {
null
} else if (it.typeRef.type != null &&
!world.typeRegistry.roleOfType(it.typeRef.type).isNodeInherited()) {
null
} else if (it.typeRef.form == AstTypeRefForm.Single) {
} else if (it.typeRef.form == AstTypeRefForm.Single ||
it.typeRef.form == AstTypeRefForm.Nullable) {
"listOf(${it.name})"
} else {
it.name
}
}.joinToString(", ")
} ?: emptyList()).joinToString(", ")
elideVisitChildren = visitParameters.isEmpty()
visitChildrenFunction.body.add("visitor.visitAll(${visitParameters})")
} else {
val visitParameters = type.values.mapNotNull {
val visitParameters = (type.values?.mapNotNull {
if (it.typeRef.primitive != null) {
null
} else if (it.typeRef.type != null &&
@ -306,7 +310,7 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
} else {
it.name
}
}.joinToString(", ")
} ?: emptyList()).joinToString(", ")
elideVisitChildren = visitParameters.isEmpty()
visitChildrenFunction.body.add("visitor.visitNodes(${visitParameters})")
}
@ -341,9 +345,12 @@ class AstCodegen(val pkg: String, val outputDirectory: Path, val world: AstWorld
"Any?"
))
equalsFunction.body.add("if (other !is ${type.name}) return false")
val predicate = equalsAndHashCodeMembers.mapNotNull {
var predicate = equalsAndHashCodeMembers.mapNotNull {
if (it == "type") null else "other.${it} == $it"
}.joinToString(" && ")
if (predicate.isEmpty()) {
predicate = "true"
}
equalsFunction.body.add("return $predicate")
kotlinClassLike.functions.add(equalsFunction)

View File

@ -1,17 +1,24 @@
package gay.pizza.pork.buildext.ast
class AstType(val name: String, var parent: AstType? = null) {
private val internalValues = mutableListOf<AstValue>()
private var internalValues: MutableList<AstValue>? = null
private val internalEnums = mutableListOf<AstEnum>()
val values: List<AstValue>
val values: List<AstValue>?
get() = internalValues
val enums: List<AstEnum>
get() = internalEnums
internal fun markHasValues() {
if (internalValues == null) {
internalValues = mutableListOf()
}
}
internal fun addValue(value: AstValue) {
internalValues.add(value)
markHasValues()
internalValues!!.add(value)
}
internal fun addEnum(enum: AstEnum) {
@ -25,7 +32,7 @@ class AstType(val name: String, var parent: AstType? = null) {
var current = parent
while (current != null) {
val abstract = current.values.firstOrNull {
val abstract = current.values?.firstOrNull {
it.name == value.name && it.abstract
}
if (abstract != null) {

View File

@ -2,6 +2,6 @@ package gay.pizza.pork.buildext.ast
data class AstTypeDescription(
val parent: String? = null,
val values: List<AstValueDescription> = emptyList(),
val values: List<AstValueDescription>? = null,
val enums: List<AstEnumDescription> = emptyList()
)

View File

@ -21,13 +21,14 @@ class AstTypeRegistry {
when {
type.enums.isNotEmpty() ->
AstTypeRole.Enum
type.parent == null && type.values.isEmpty() ->
type.parent == null && type.values == null ->
AstTypeRole.RootNode
type.parent != null && type.values.all { it.abstract } ->
type.parent != null && (type.values == null ||
(type.values!!.isNotEmpty() && type.values!!.all { it.abstract })) ->
AstTypeRole.HierarchyNode
type.parent != null && type.values.none { it.abstract } ->
type.parent != null && (type.values != null && type.values!!.none { it.abstract }) ->
AstTypeRole.AstNode
type.parent == null && type.values.isNotEmpty() ->
type.parent == null && (type.values != null && type.values!!.isNotEmpty()) ->
AstTypeRole.ValueHolder
else -> throw RuntimeException("Unable to determine role of type ${type.name}")
}

View File

@ -39,10 +39,13 @@ class AstWorld {
type.parent = world.typeRegistry.lookup(typeDescription.parent)
}
for (value in typeDescription.values) {
val typeRef = AstTypeRef.parse(value.type, world.typeRegistry)
val typeValue = AstValue(value.name, typeRef, abstract = value.required)
type.addValue(typeValue)
if (typeDescription.values != null) {
type.markHasValues()
for (value in typeDescription.values) {
val typeRef = AstTypeRef.parse(value.type, world.typeRegistry)
val typeValue = AstValue(value.name, typeRef, abstract = value.required)
type.addValue(typeValue)
}
}
for (enum in typeDescription.enums) {