Skip to content

[jextract] Rework translation #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 4, 2025
Merged

Conversation

rintaro
Copy link
Member

@rintaro rintaro commented May 29, 2025

  • Utilize SwiftFunctionSignature and the cdecl-lowering facilities throughout the code base.
    • SwiftFunctionSignature is created from the DeclSyntax in Swift2JavaVisitor.
    • LoweredFunctionSignature describing @cdecl thunk, is created from SwiftFunctionSignature.
    • TranslatedFunctionSignature describing generated Java API, is created from LoweredFunctionSignature. (Swift2JavaTranslator+JavaTranslation.swift)
    • ImportedFunc is now basically just a wrapper of TranslatedFunctionSignature with the name.
  • Remove ImportedVariable, instead variables are described as ImportedFunc as accessors.
  • Now supports methods returning imported type values. E.g. func factory(arg: Int) -> MyClass such methods require SwiftArena passed-in.
  • Built-in lowerings (e.g. toCString(String) for String -> C string conversion) are now implemented in JavaKit.
  • Stop emitting MyClass::apiName$descriptor() method etc. as they were not used.
  • Use the @cdecl thunk name as the function descriptor class name, for simplicity.
  • Getter and setter accessors are now completely separate API. No more HANDLE_GET and HANDLE_SET etc. Instead descriptor class is split to $get or $set suffixed name.
Actual output of MyClass.java ▼
// Generated by jextract-swift
// Swift module: MySwiftLibrary

package com.example.swift;

import org.swift.swiftkit.*;
import org.swift.swiftkit.SwiftKit;
import org.swift.swiftkit.util.*;
import java.lang.foreign.*;
import java.lang.invoke.*;
import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.concurrent.atomic.*;
import java.nio.charset.StandardCharsets;

public final class MySwiftClass extends SwiftValue implements SwiftHeapObject {
  static final String LIB_NAME = "MySwiftLibrary";
  static final Arena LIBRARY_ARENA = Arena.ofAuto();
  @SuppressWarnings("unused")
  private static final boolean INITIALIZED_LIBS = initializeLibs();
  static boolean initializeLibs() {
      System.loadLibrary(SwiftKit.STDLIB_DYLIB_NAME);
      System.loadLibrary("SwiftKitSwift");
      System.loadLibrary(LIB_NAME);
      return true;
  }
  
  public static final SwiftAnyType TYPE_METADATA =
      new SwiftAnyType(SwiftKit.swiftjava.getType("MySwiftLibrary", "MySwiftClass"));
  public final SwiftAnyType $swiftType() {
      return TYPE_METADATA;
  }
  
  private static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
  public static final GroupLayout $LAYOUT() {
      return $LAYOUT;
  }
  public final GroupLayout $layout() {
      return $LAYOUT;
  }
  
  public MySwiftClass(MemorySegment segment, SwiftArena arena) {
    super(segment, arena);
  }
  
  // ==== --------------------------------------------------
  // MySwiftClass.init
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_init_len_cap {
    public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
      /* len: */SwiftValueLayout.SWIFT_INT,
      /* cap: */SwiftValueLayout.SWIFT_INT,
      /* _result: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_init_len_cap");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printInitializerDowncallConstructors(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:320
  /**
   * Create an instance of {@code MySwiftClass}.
   *
   * {@snippet lang=swift :
   * public init(len: Int, cap: Int)
   * }
   */
  public MySwiftClass(long len, long cap) {
    this(len, cap, SwiftArena.ofAuto());
  } // printInitializerDowncallConstructor(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:424
  /**
   * Create an instance of {@code MySwiftClass}.
   *
   * {@snippet lang=swift :
   * public init(len: Int, cap: Int)
   * }
   */
  public MySwiftClass(long len, long cap, SwiftArena swiftArena$) {
    super(() -> {
      var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_init_len_cap.HANDLE;
      try {
        MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT());
        if (SwiftKit.TRACE_DOWNCALLS) {
            SwiftKit.traceDowncall(len, cap, _result);
        }
        mh$.invokeExact(len, cap, _result);
        return _result;
      } catch (Throwable ex$) {
        throw new AssertionError("should not reach here", ex$);
      }
    }, swiftArena$);
  } // printInitializerDowncallConstructor(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:424
  
  // ==== --------------------------------------------------
  // getter:MySwiftClass.len
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_len$get {
    public static final FunctionDescriptor DESC = FunctionDescriptor.of(
      /* -> */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_len$get");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public var len: Int
   * }
   */
  public long getLen() {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_len$get.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(this.$memorySegment());
      }
      return (long)mh$.invokeExact(this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // setter:MySwiftClass.len
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_len$set {
    public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
      /* newValue: */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_len$set");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public var len: Int
   * }
   */
  public void setLen(long newValue) {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_len$set.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(newValue, this.$memorySegment());
      }
      mh$.invokeExact(newValue, this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // getter:MySwiftClass.cap
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_cap$get {
    public static final FunctionDescriptor DESC = FunctionDescriptor.of(
      /* -> */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_cap$get");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public var cap: Int
   * }
   */
  public long getCap() {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_cap$get.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(this.$memorySegment());
      }
      return (long)mh$.invokeExact(this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // setter:MySwiftClass.cap
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_cap$set {
    public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
      /* newValue: */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_cap$set");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public var cap: Int
   * }
   */
  public void setCap(long newValue) {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_cap$set.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(newValue, this.$memorySegment());
      }
      mh$.invokeExact(newValue, this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // getter:MySwiftClass.counter
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_counter$get {
    public static final FunctionDescriptor DESC = FunctionDescriptor.of(
      /* -> */SwiftValueLayout.SWIFT_INT32,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_counter$get");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public var counter: Int32
   * }
   */
  public int getCounter() {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_counter$get.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(this.$memorySegment());
      }
      return (int)mh$.invokeExact(this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // setter:MySwiftClass.counter
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_counter$set {
    public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
      /* newValue: */SwiftValueLayout.SWIFT_INT32,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_counter$set");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public var counter: Int32
   * }
   */
  public void setCounter(int newValue) {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_counter$set.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(newValue, this.$memorySegment());
      }
      mh$.invokeExact(newValue, this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // MySwiftClass.factory
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_factory_len_cap {
    public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
      /* len: */SwiftValueLayout.SWIFT_INT,
      /* cap: */SwiftValueLayout.SWIFT_INT,
      /* _result: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_factory_len_cap");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public static func factory(len: Int, cap: Int) -> MySwiftClass
   * }
   */
  public static MySwiftClass factory(long len, long cap) {
    return factory(len, cap, SwiftArena.ofAuto());
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public static func factory(len: Int, cap: Int) -> MySwiftClass
   * }
   */
  public static MySwiftClass factory(long len, long cap, SwiftArena swiftArena$) {
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_factory_len_cap.HANDLE;
    try {
      MemorySegment _result = swiftArena$.allocate(MySwiftClass.$LAYOUT());
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(len, cap, _result);
      }
      return new MySwiftClass(_result, swiftArena$);
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // MySwiftClass.voidMethod
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_voidMethod {
    public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_voidMethod");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public func voidMethod()
   * }
   */
  public void voidMethod() {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_voidMethod.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(this.$memorySegment());
      }
      mh$.invokeExact(this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // MySwiftClass.takeIntMethod
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_takeIntMethod_i {
    public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
      /* i: */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_takeIntMethod_i");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public func takeIntMethod(i: Int)
   * }
   */
  public void takeIntMethod(long i) {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_takeIntMethod_i.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(i, this.$memorySegment());
      }
      mh$.invokeExact(i, this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // MySwiftClass.echoIntMethod
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_echoIntMethod_i {
    public static final FunctionDescriptor DESC = FunctionDescriptor.of(
      /* -> */SwiftValueLayout.SWIFT_INT,
      /* i: */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_echoIntMethod_i");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public func echoIntMethod(i: Int) -> Int
   * }
   */
  public long echoIntMethod(long i) {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_echoIntMethod_i.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(i, this.$memorySegment());
      }
      return (long)mh$.invokeExact(i, this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // MySwiftClass.makeIntMethod
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_makeIntMethod {
    public static final FunctionDescriptor DESC = FunctionDescriptor.of(
      /* -> */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_makeIntMethod");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public func makeIntMethod() -> Int
   * }
   */
  public long makeIntMethod() {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_makeIntMethod.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(this.$memorySegment());
      }
      return (long)mh$.invokeExact(this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  
  // ==== --------------------------------------------------
  // MySwiftClass.makeRandomIntMethod
  
  private static class swiftjava_MySwiftLibrary_MySwiftClass_makeRandomIntMethod {
    public static final FunctionDescriptor DESC = FunctionDescriptor.of(
      /* -> */SwiftValueLayout.SWIFT_INT,
      /* self: */SwiftValueLayout.SWIFT_POINTER
    );
    public static final MemorySegment ADDR =
      MySwiftLibrary.findOrThrow("swiftjava_MySwiftLibrary_MySwiftClass_makeRandomIntMethod");
    public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
  } // printFunctionDowncallMethods(_:_:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:338
  /**
   * Downcall to Swift:
   * {@snippet lang=swift :
   * public func makeRandomIntMethod() -> Int
   * }
   */
  public long makeRandomIntMethod() {
    $ensureAlive();
    var mh$ = swiftjava_MySwiftLibrary_MySwiftClass_makeRandomIntMethod.HANDLE;
    try {
      if (SwiftKit.TRACE_DOWNCALLS) {
          SwiftKit.traceDowncall(this.$memorySegment());
      }
      return (long)mh$.invokeExact(this.$memorySegment());
    } catch (Throwable ex$) {
      throw new AssertionError("should not reach here", ex$);
    }
  } // printFuncDowncallMethod(_:_:isAutoArenaWrapper:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:481
  @Override
  public String toString() {
      return getClass().getSimpleName()
          + "("
          + SwiftKit.nameOfSwiftType($swiftType().$memorySegment(), true)
          + ")@"
          + $memorySegment();
  }
} // printNominal(_:_:body:) @ JExtractSwift/Swift2JavaTranslator+JavaThunkPrinting.swift:194

@rintaro rintaro force-pushed the jextract-rework-r branch 4 times, most recently from e5111e9 to 5bc7668 Compare May 29, 2025 22:54
@rintaro rintaro force-pushed the jextract-rework-r branch 2 times, most recently from a01680f to fcb71fe Compare May 29, 2025 23:03
@rintaro rintaro force-pushed the jextract-rework-r branch 2 times, most recently from 70f9407 to d597a64 Compare May 31, 2025 16:33
@rintaro rintaro force-pushed the jextract-rework-r branch 7 times, most recently from 5732e36 to 54b9299 Compare June 3, 2025 19:45
@@ -26,7 +26,7 @@ public struct ForeignValueLayout: CustomStringConvertible, Equatable {

public init(inlineComment: String? = nil, javaConstant: String) {
self.inlineComment = inlineComment
self.value = javaConstant
self.value = "SwiftValueLayout.\(javaConstant)"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


// When the type is some custom type, e.g. another Swift struct that we imported,
// we need to import its layout. We do this by calling $layout() on it.
// we need to import its layout. We do this by calling $LAYOUT() on it.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this because openjdk seems to use uppercase for these?

Copy link
Member Author

@rintaro rintaro Jun 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is $layout() method as an instance method. I added $LAYOUT() as a static method because this is rendered as ClassName.$LAYOUT(). Maybe we could just use $LAYOUT static field, but I wasn't sure it's OK to make it public.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

public static final ... LAYOUT field is fine I think, it'd help differentiate the field and method. TBD if we need both, but we can decide this later. Uppercase like that does look a bit weird so I'd go for a constant which then looks "expected" being uppercase.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good. Updated. While I am here, I removed needsMemoryLayoutCall from the type and added .$LAYOUT in the constructor.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks 👍

Copy link
Collaborator

@ktoso ktoso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks all fine to me, thank you @rintaro.

Just few minor comments, one of which you already fixed, which can be done anytime in the future. LGTM, please merge at will 👍

FYI @madsodgaard -- with this merged, it'll be a good time for you to introduce the protocol to pick between ffm and jni modes 👍

}

for (param, isLast) in cFunc.parameters.withIsLast {
printer.print("/* \(param.name ?? "_"): */", .continue)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor / doesn't have to be in this PR: I think we had an effectiveParamLabel somewhere?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This actually never be nil. cFunc is created from LoweredFunctionSignature created by lowerFunctionSignature() which actually gives a name to every parameter.

* Create an instance of {@code \(className)}.
*
* {@snippet lang=swift :
* \(decl.signatureString)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow up:

Silly but I think now if a signature contains /**/ because we take the raw syntax with the trivia that would break rendering of the source file because the */ will end the comment.

We probably should sanitize that and add a test for it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added FIXME on ImportedFunc.signatureString

case .getter: "get\(decl.name.toCamelCase)"
case .setter: "set\(decl.name.toCamelCase)"
case .function: decl.name
case .initializer: fatalError("unreachable")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

give this a better reason string why we crash?

self.needsMemoryLayoutCall = true
// When the type is some custom type, e.g. another Swift struct that we imported,
// we need to import its layout. We do this by referring $LAYOUT on it.
self.value = "\(customType).$LAYOUT"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for updating that to a property

returnTy = typeAnnotation.type
} else {
returnTy = "Swift.Void"
func importAccessor(kind: SwiftAPIKind) throws {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yay!

extension SyntaxProtocol {
/// Look in the comment text prior to the node to find a mangled name
/// identified by "// MANGLED NAME: ".
var mangledNameFromComment: String? {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup we dont need this anymore, thank you

// }
for decl in nominal.methods {
decls.append(contentsOf: render(forFunc: decl))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yay, variables - thank you

* Utilize `SwiftFunctionSignature` and the cdecl-lowering  facilities
  throughout the code base.
  * `SwiftFunctionSignature` is created from the `DeclSyntax` in
    `Swift2JavaVisitor`.
  * `LoweredFunctionSignature` describing `@cdecl` thunk, is created
    from `SwiftFunctionSignature`.
  * `TranslatedFunctionSignature` describing generated Java API, is
    created from `LoweredFunctionSignature`.
    (Swift2JavaTranslator+JavaTranslation.swift)
  * `ImportedFunc` is now basically just a wrapper of
    `TranslatedFunctionSignature` with the `name`.

* Remove `ImportedVariable`, instead variables are described as
  `ImportedFunc` as accessors.
* Support APIs returning imported type values. E.g.
  `func factory(arg: Int) -> MyClass` such methods require `SwiftArena`
  parameter passed-in.
* Built-in lowerings (e.g. `toCString(String)` for `String` -> C string
  conversion) are now implemented in JavaKit.
* Stop emitting `MyClass::apiName$descriptor()` method etc. as they were
  not used.
* Use the `@cdecl` thunk name as the function descriptor class name, for
  simplicity.
* Getter and setter accessors are now completely separate API. No more
  `HANDLE_GET` and `HANDLE_SET` etc. Instead descriptor class is split
  to `$get` or `$set` suffixed name.
@rintaro rintaro force-pushed the jextract-rework-r branch from c2d4cc5 to 637d800 Compare June 4, 2025 17:17
@rintaro rintaro changed the title [WIP][jextract] Rework translation [jextract] Rework translation Jun 4, 2025
@rintaro rintaro merged commit abd05a0 into swiftlang:main Jun 4, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants