Skip to content

Commit

Permalink
Update struct setter
Browse files Browse the repository at this point in the history
  • Loading branch information
squid233 committed Dec 17, 2023
1 parent cd8a3f9 commit 3f1dca9
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,5 @@
*/
@Const
@Struct
public class CConstStructTest {
int x, y, z;
public record CConstStructTest(int x, int y, int z) {
}
125 changes: 120 additions & 5 deletions src/main/java/overrun/marshal/StructProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,23 @@ private void writeFile(
.addArgument(Spec.literal("count"))));
});

// slice
classSpec.addMethod(new MethodSpec(simpleClassName, "get"), methodSpec -> {
methodSpec.setDocument("""
{@return a slice of this struct}
@param index the index of the slice\
""");
methodSpec.addParameter(long.class, "index");
methodSpec.addStatement(Spec.returnStatement(new ConstructSpec(simpleClassName)
.addArgument(new InvokeSpec("this._memorySegment", "asSlice")
.addArgument(Spec.operatorSpec("*",
Spec.literal("index"),
new InvokeSpec("_LAYOUT", "byteSize")))
.addArgument("_LAYOUT"))
.addArgument(Spec.literal("1L"))));
});

// member
forEach(fields, false, e -> {
final TypeMirror eType = e.asType();
Expand All @@ -278,7 +295,9 @@ private void writeFile(
// getter
final Spec castSpec = Spec.cast(returnType,
new InvokeSpec(Spec.accessSpec("this", nameString), "get")
.addArgument("_memorySegment"));
.addArgument("this._memorySegment")
.addArgument("0L")
.addArgument("index"));
addGetterAt(classSpec, e, generateN ? "nget" : "get", returnType,
(isMemorySegment && longSized != null || isArray && sized != null) ?
new InvokeSpec(Spec.parentheses(castSpec), "reinterpret")
Expand Down Expand Up @@ -323,15 +342,38 @@ private void writeFile(

// setter
if (!typeConst && e.getAnnotation(Const.class) == null) {
addSetterAt(classSpec, e, generateN ? "nset" : "set", returnType,
Spec.statement(new InvokeSpec(Spec.accessSpec("this", nameString), "set")
.addArgument("this._memorySegment")
.addArgument("0L")
.addArgument("index")
.addArgument("value")));
if (generateN) {
final InvokeSpec invokeSpec = new InvokeSpec("this", "nset" + capitalized + "At");
if (isString(eType)) {
final StrCharset strCharset = e.getAnnotation(StrCharset.class);
final InvokeSpec alloc = new InvokeSpec("_segmentAllocator", "allocateFrom")
.addArgument("value");
if (strCharset != null) {
alloc.addArgument(createCharset(file, strCharset.value()));
}
invokeSpec.addArgument(alloc);
} else if (isArray) {
} else {
invokeSpec.addArgument("value");
}
invokeSpec.addArgument("index");
addSetterAt(classSpec, e, "set", simplify(eType.toString()), Spec.statement(invokeSpec));
}
}
}
// TODO: 2023/12/17 squid233: struct, upcall
});

// override
addIStructImpl(classSpec, MemorySegment.class, "segment", Spec.literal("_memorySegment"));
addIStructImpl(classSpec, MemorySegment.class, "segment", Spec.literal("this._memorySegment"));
addIStructImpl(classSpec, StructLayout.class, "layout", Spec.literal("_LAYOUT"));
addIStructImpl(classSpec, long.class, "elementCount", new InvokeSpec("_sequenceLayout", "elementCount"));
addIStructImpl(classSpec, long.class, "elementCount", new InvokeSpec("this._sequenceLayout", "elementCount"));
});

final JavaFileObject sourceFile = processingEnv.getFiler().createSourceFile(packageName + '.' + simpleClassName);
Expand All @@ -340,11 +382,57 @@ private void writeFile(
}
}

private void addSetterAt(ClassSpec classSpec, VariableElement e, String setType, String valueType, Spec setter) {
final String member = e.getSimpleName().toString();
final TypeMirror eType = e.asType();
final boolean insertAllocator = "set".equals(setType) && (isString(eType) || isArray(eType));
classSpec.addMethod(new MethodSpec("void", setType + capitalize(member) + "At"), methodSpec -> {
final String eDoc = getDocument(e);
methodSpec.setDocument("""
Sets %s at the given index.
%s@param value the value
@param index the index\
""".formatted(eDoc != null ? eDoc : "{@code " + e.getSimpleName() + '}', insertAllocator ? "@param _segmentAllocator the allocator\n " : ""));
if (insertAllocator) {
methodSpec.addParameter(SegmentAllocator.class, "_segmentAllocator");
}
methodSpec.addParameter(valueType, "value");
methodSpec.addParameter(long.class, "index");
methodSpec.addStatement(setter);
});
addSetter(classSpec, e, setType, valueType, insertAllocator);
}

private void addSetter(ClassSpec classSpec, VariableElement e, String setType, String valueType, boolean insertAllocator) {
final String name = setType + capitalize(e.getSimpleName().toString());
classSpec.addMethod(new MethodSpec("void", name), methodSpec -> {
final String eDoc = getDocument(e);
methodSpec.setDocument("""
Sets the first %s.
%s@param value the value\
""".formatted(eDoc != null ? eDoc : "{@code " + e.getSimpleName() + '}', insertAllocator ? "@param _allocator the allocator\n " : ""));
if (insertAllocator) {
methodSpec.addParameter(SegmentAllocator.class, "_segmentAllocator");
}
methodSpec.addParameter(valueType, "value");
methodSpec.addStatement(Spec.statement(new InvokeSpec("this", name + "At")
.also(invokeSpec -> {
if (insertAllocator) {
invokeSpec.addArgument("_segmentAllocator");
}
})
.addArgument("value")
.addArgument("0L")));
});
}

private void addGetterAt(ClassSpec classSpec, VariableElement e, String getType, String returnType, Spec returnValue) {
final Sized sized = e.getAnnotation(Sized.class);
final boolean insertCount = "get".equals(getType) && sized == null && isArray(e.asType());
classSpec.addMethod(new MethodSpec(returnType, getType + capitalize(e.getSimpleName().toString()) + "At"), methodSpec -> {
final LongSized longSized = e.getAnnotation(LongSized.class);
final Sized sized = e.getAnnotation(Sized.class);
final boolean insertCount = "get".equals(getType) && sized == null && isArray(e.asType());
final String eDoc = getDocument(e);
methodSpec.setDocument("""
Gets %s at the given index.
Expand All @@ -360,6 +448,33 @@ private void addGetterAt(ClassSpec classSpec, VariableElement e, String getType,
methodSpec.addParameter(long.class, "index");
methodSpec.addStatement(Spec.returnStatement(returnValue));
});
addGetter(classSpec, e, getType, returnType, insertCount);
}

private void addGetter(ClassSpec classSpec, VariableElement e, String getType, String returnType, boolean insertCount) {
final String name = getType + capitalize(e.getSimpleName().toString());
classSpec.addMethod(new MethodSpec(returnType, name), methodSpec -> {
final LongSized longSized = e.getAnnotation(LongSized.class);
final Sized sized = e.getAnnotation(Sized.class);
final String eDoc = getDocument(e);
methodSpec.setDocument("""
Gets the first %s.
%s@return %1$s\
""".formatted(eDoc != null ? eDoc : "{@code " + e.getSimpleName() + '}', insertCount ? "@param count the length of the array\n " : ""));
addAnnotationValue(methodSpec, longSized, LongSized.class, LongSized::value);
addAnnotationValue(methodSpec, sized, Sized.class, Sized::value);
if (insertCount) {
methodSpec.addParameter(int.class, "count");
}
methodSpec.addStatement(Spec.returnStatement(new InvokeSpec("this", name + "At")
.also(invokeSpec -> {
if (insertCount) {
invokeSpec.addArgument("count");
}
})
.addArgument("0L")));
});
}

private static void addIStructImpl(ClassSpec classSpec, Class<?> aClass, String name, Spec spec) {
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/overrun/marshal/struct/Const.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
* <pre>{@code
* @Const
* @Struct
* class Vector2 {
* int x, y;
* record Vector2(int x, int y) {
* }
* }</pre>
*
Expand Down
15 changes: 11 additions & 4 deletions src/main/java/overrun/marshal/struct/Struct.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,20 @@

/**
* Marks a class or interface as a struct provider.
* <p>
* The generated class contains a {@link java.lang.foreign.StructLayout StructLayout} with name "{@code _LAYOUT}".
* You can link it in the documentation.
* <h2>Example</h2>
* <pre>{@code
* @Struct
* <pre><code>
* &#47;**
* * {&#64;linkplain _LAYOUT Layout}
* *&#47;
* &#64;Struct
* class Point {
* &#64;Skip
* int _LAYOUT;
* int x, y;
* }
* }</pre>
* }</code></pre>
*
* @author squid233
* @see Const
Expand Down

0 comments on commit 3f1dca9

Please sign in to comment.