Skip to content

Commit

Permalink
Cleanup: Move returnvalue processing to ReturnValue class
Browse files Browse the repository at this point in the history
  • Loading branch information
jwharm committed Nov 13, 2022
1 parent d03d4ed commit 5075ad5
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private String generateConstructorHelper(Writer writer) throws IOException {

// Generate preprocessing statements for all parameters
if (parameters != null) {
parameters.generatePreprocessing(writer);
parameters.generatePreprocessing(writer, 2);
}

// Allocate GError pointer
Expand Down Expand Up @@ -183,7 +183,7 @@ private String generateConstructorHelper(Writer writer) throws IOException {

// Generate post-processing actions for parameters
if (parameters != null) {
parameters.generatePostprocessing(writer);
parameters.generatePostprocessing(writer, 2);
}

writer.write(" return RESULT;\n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,8 @@ public Repository getRepository() {
public String toString() {
return this.getClass().getSimpleName() + " " + this.name;
}

protected String tab(int tabs) {
return " ".repeat(tabs * 4);
}
}
36 changes: 4 additions & 32 deletions generator/src/main/java/io/github/jwharm/javagi/model/Method.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public void generate(Writer writer, boolean isInterface, boolean isStatic) throw

// Generate preprocessing statements for all parameters
if (parameters != null) {
parameters.generatePreprocessing(writer);
parameters.generatePreprocessing(writer, 2);
}

// Allocate GError pointer
Expand Down Expand Up @@ -179,39 +179,11 @@ public void generate(Writer writer, boolean isInterface, boolean isStatic) throw

// Generate post-processing actions for parameters
if (parameters != null) {
parameters.generatePostprocessing(writer);
parameters.generatePostprocessing(writer, 2);
}

// If the return value is an array, try to convert it to a Java array
if (returnValue.array != null) {
String len = returnValue.array.size();
if (len != null) {
if (getReturnValue().nullable) {
switch (panamaReturnType) {
case "MemoryAddress" -> writer.write(" if (RESULT.equals(MemoryAddress.NULL)) return null;\n");
case "MemorySegment" -> writer.write(" if (RESULT.address().equals(MemoryAddress.NULL)) return null;\n");
default -> System.err.println("Unexpected nullable return type: " + panamaReturnType);
}
}
String valuelayout = Conversions.getValueLayout(returnValue.array.type);
if (returnValue.array.type.isPrimitive && (! returnValue.array.type.isBoolean())) {
// Array of primitive values
writer.write(" return MemorySegment.ofAddress(RESULT.get(ValueLayout.ADDRESS, 0), " + len + " * " + valuelayout + ".byteSize(), Interop.getScope()).toArray(" + valuelayout + ");\n");
} else {
// Array of proxy objects
writer.write(" " + returnValue.array.type.qualifiedJavaType + "[] resultARRAY = new " + returnValue.array.type.qualifiedJavaType + "[" + len + "];\n");
writer.write(" for (int I = 0; I < " + len + "; I++) {\n");
writer.write(" var OBJ = RESULT.get(" + valuelayout + ", I);\n");
writer.write(" resultARRAY[I] = " + returnValue.getNewInstanceString(returnValue.array.type, "OBJ", false) + ";\n");
writer.write(" }\n");
writer.write(" return resultARRAY;\n");
}
} else {
returnValue.generateReturnStatement(writer, 2);
}
} else {
returnValue.generateReturnStatement(writer, 2);
}
// Generate code to process and return the result value
returnValue.generate(writer, panamaReturnType, 2);

writer.write(" }\n");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,36 +121,39 @@ public boolean checkNull() {
* generate a null check for NotNull parameters, and generate pointer allocation logic for
* pointer parameters.
* @param writer The source code file writer
* @param indent How many tabs to indent
* @throws IOException Thrown when an error occurs while writing to the file
*/
public void generatePreprocessing(Writer writer) throws IOException {
public void generatePreprocessing(Writer writer, int indent) throws IOException {

// Generate null-check
// Don't null-check parameters that are hidden from the Java API, or primitive values
if (! (isInstanceParameter() || isErrorParameter() || isUserDataParameter() || isDestroyNotify() || varargs
|| (type != null && type.isPrimitive && (! type.isPointer())))) {
if (! nullable) {
writer.write(" java.util.Objects.requireNonNull(" + name
writer.write(tab(indent) + "java.util.Objects.requireNonNull(" + name
+ ", \"" + "Parameter '" + name + "' must not be null\");\n");
}
}

// Generate pointer allocation
if (isOutParameter()) {
writer.write(" MemorySegment " + name + "POINTER = Interop.getAllocator().allocate(" + Conversions.getValueLayout(type) + ");\n");
writer.write(tab(indent) + "MemorySegment " + name + "POINTER = Interop.getAllocator().allocate(" + Conversions.getValueLayout(type) + ");\n");

} else if (type != null && type.isAliasForPrimitive() && type.isPointer()) {
String typeStr = type.girElementInstance.type.simpleJavaType;
typeStr = Conversions.primitiveClassName(typeStr);
writer.write(" Pointer" + typeStr + " " + name + "POINTER = new Pointer" + typeStr + "(" + name + ".getValue());\n");
writer.write(tab(indent) + "Pointer" + typeStr + " " + name + "POINTER = new Pointer" + typeStr + "(" + name + ".getValue());\n");
}
}

/**
* Generate code to do post-processing of the parameter after the function call.
* @param writer The source code file writer
* @param indent How many tabs to indent
* @throws IOException Thrown when an error occurs while writing to the file
*/
public void generatePostprocessing(Writer writer) throws IOException {
public void generatePostprocessing(Writer writer, int indent) throws IOException {
if (isOutParameter()) {
if (array == null) {
// First the regular (non-array) out-parameters. These could include an out-parameter with
Expand All @@ -174,21 +177,21 @@ public void generatePostprocessing(Writer writer) throws IOException {
String valuelayout = Conversions.getValueLayout(array.type);
if (array.type.isPrimitive && (! array.type.isBoolean())) {
// Array of primitive values
writer.write(" " + name + ".set(");
writer.write(tab(indent) + name + ".set(");
writer.write("MemorySegment.ofAddress(" + name + "POINTER.get(ValueLayout.ADDRESS, 0), " + len + " * " + valuelayout + ".byteSize(), Interop.getScope()).toArray(" + valuelayout + "));\n");
} else {
// Array of proxy objects
writer.write(" " + array.type.qualifiedJavaType + "[] " + name + "ARRAY = new " + array.type.qualifiedJavaType + "[" + len + "];\n");
writer.write(" for (int I = 0; I < " + len + "; I++) {\n");
writer.write(" var OBJ = " + name + "POINTER.get(" + valuelayout + ", I);\n");
writer.write(" " + name + "ARRAY[I] = ");
writer.write(tab(indent) + array.type.qualifiedJavaType + "[] " + name + "ARRAY = new " + array.type.qualifiedJavaType + "[" + len + "];\n");
writer.write(tab(indent) + "for (int I = 0; I < " + len + "; I++) {\n");
writer.write(tab(indent + 1) + "var OBJ = " + name + "POINTER.get(" + valuelayout + ", I);\n");
writer.write(tab(indent + 1) + name + "ARRAY[I] = ");
writer.write(getNewInstanceString(array.type, "OBJ", false) + ";\n");
writer.write(" }\n");
writer.write(" " + name + ".set(" + name + "ARRAY);\n");
writer.write(tab(indent) + "}\n");
writer.write(tab(indent) + name + ".set(" + name + "ARRAY);\n");
}
}
} else if (type != null && type.isAliasForPrimitive() && type.isPointer()) {
writer.write(" " + name + ".setValue(" + name + "POINTER.get());\n");
writer.write(tab(indent + 1) + name + ".setValue(" + name + "POINTER.get());\n");
}

// If the parameter has attribute transfer-ownership="full", we don't need to unref it anymore.
Expand All @@ -197,7 +200,7 @@ public void generatePostprocessing(Writer writer) throws IOException {
&& "full".equals(transferOwnership)
&& (! isOutParameter())
&& (type.cType == null || (! type.cType.endsWith("**")))) {
writer.write(" " + (isInstanceParameter() ? "this" : name) + ".yieldOwnership();\n");
writer.write(tab(indent) + (isInstanceParameter() ? "this" : name) + ".yieldOwnership();\n");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,31 +137,33 @@ public void generateCParameters(Writer writer, String throws_) throws IOExceptio
/**
* Generate preprocessing statements for all parameters
* @param writer The source code file writer
* @param indent How many tabs to indent
* @throws IOException Thrown when an error occurs while writing
*/
public void generatePreprocessing(Writer writer) throws IOException {
public void generatePreprocessing(Writer writer, int indent) throws IOException {
for (Parameter p : parameterList) {
p.generatePreprocessing(writer);
p.generatePreprocessing(writer, indent);
}
}

/**
* Generate postprocessing statements for all parameters
* @param writer The source code file writer
* @param indent How many tabs to indent
* @throws IOException Thrown when an error occurs while writing
*/
public void generatePostprocessing(Writer writer) throws IOException {
public void generatePostprocessing(Writer writer, int indent) throws IOException {
// First the regular (non-array) out-parameters. These could include an out-parameter with
// the length of an array out-parameter, so we have to process these first.
for (Parameter p : parameterList) {
if (p.array == null) {
p.generatePostprocessing(writer);
p.generatePostprocessing(writer, indent);
}
}
// Secondly, process the array out parameters
for (Parameter p : parameterList) {
if (p.array != null) {
p.generatePostprocessing(writer);
p.generatePostprocessing(writer, indent);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,65 @@
import java.io.IOException;
import java.io.Writer;

import io.github.jwharm.javagi.generator.Conversions;

public class ReturnValue extends Parameter {

public ReturnValue(GirElement parent, String transferOwnership, String nullable) {
super(parent, null, transferOwnership, nullable, null, null);
}

/**
* Generate code to process and return the function call result.
* @param writer The source code file writer
* @param panamaReturnType The type of the value that was returned by the downcall
* @param indent How many tabs to indent
* @throws IOException Thrown when an error occurs while writing
*/
public void generate(Writer writer, String panamaReturnType, int indent) throws IOException {
// If the return value is an array, try to convert it to a Java array
if (array != null) {
String len = array.size();
if (len != null) {
if (nullable) {
switch (panamaReturnType) {
case "MemoryAddress" -> writer.write(tab(indent) + "if (RESULT.equals(MemoryAddress.NULL)) return null;\n");
case "MemorySegment" -> writer.write(tab(indent) + "if (RESULT.address().equals(MemoryAddress.NULL)) return null;\n");
default -> System.err.println("Unexpected nullable return type: " + panamaReturnType);
}
}
String valuelayout = Conversions.getValueLayout(array.type);
if (array.type.isPrimitive && (! array.type.isBoolean())) {
// Array of primitive values
writer.write(tab(indent) + "return MemorySegment.ofAddress(RESULT.get(ValueLayout.ADDRESS, 0), " + len + " * " + valuelayout + ".byteSize(), Interop.getScope()).toArray(" + valuelayout + ");\n");
} else {
// Array of proxy objects
writer.write(tab(indent) + array.type.qualifiedJavaType + "[] resultARRAY = new " + array.type.qualifiedJavaType + "[" + len + "];\n");
writer.write(tab(indent) + "for (int I = 0; I < " + len + "; I++) {\n");
writer.write(tab(indent) + " var OBJ = RESULT.get(" + valuelayout + ", I);\n");
writer.write(tab(indent) + " resultARRAY[I] = " + getNewInstanceString(array.type, "OBJ", false) + ";\n");
writer.write(tab(indent) + "}\n");
writer.write(tab(indent) + "return resultARRAY;\n");
}
} else {
generateReturnStatement(writer, indent);
}
} else {
generateReturnStatement(writer, indent);
}
}

/**
* Generate the return statement for a function or method call.
* @param writer The source code file writer
* @param indent How many tabs to indent
* @throws IOException Thrown when an error occurs while writing
*/
public void generateReturnStatement(Writer writer, int indent) throws IOException {
if (type != null && type.isVoid()) {
return;
}
writer.write(" ".repeat(indent * 4) + "return ");
writer.write(tab(indent) + "return ");
generateReverseInterop(writer, "RESULT", false);
writer.write(";\n");
}
Expand Down

0 comments on commit 5075ad5

Please sign in to comment.