mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 13:11:32 +00:00
while loop support, and native functions (including ffi!)
This commit is contained in:
@ -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)
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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()
|
||||
)
|
||||
|
@ -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}")
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user