Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 34 additions & 40 deletions Sources/JExtractSwift/ImportedDecls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,39 @@ import Foundation
import JavaTypes
import SwiftSyntax

protocol ImportedDecl: Hashable {
protocol ImportedDecl {

}

public typealias JavaPackage = String

public struct ImportedProtocol: ImportedDecl {
public var identifier: String
}

/// Describes a Swift nominal type (e.g., a class, struct, enum) that has been
/// imported and is being translated into Java.
public struct ImportedNominalType: ImportedDecl {
public var name: ImportedTypeName
public let swiftTypeName: String
public let javaType: JavaType
public var swiftMangledName: String?
public var kind: NominalTypeKind

public var initializers: [ImportedFunc] = []
public var methods: [ImportedFunc] = []

public init(name: ImportedTypeName, kind: NominalTypeKind) {
self.name = name
public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil, kind: NominalTypeKind) {
self.swiftTypeName = swiftTypeName
self.javaType = javaType
self.swiftMangledName = swiftMangledName
self.kind = kind
}

var translatedType: TranslatedType {
TranslatedType(
cCompatibleConvention: .direct,
originalSwiftType: "\(raw: swiftTypeName)",
cCompatibleSwiftType: "UnsafeRawPointer",
cCompatibleJavaMemoryLayout: .heapObject,
javaType: javaType
)
}
}

public enum NominalTypeKind {
Expand All @@ -47,7 +57,7 @@ public enum NominalTypeKind {
case `struct`
}

public struct ImportedParam: Hashable {
public struct ImportedParam {
let param: FunctionParameterSyntax

var firstName: String? {
Expand Down Expand Up @@ -78,7 +88,7 @@ public struct ImportedParam: Hashable {
}

// The mapped-to Java type of the above Java type, collections and optionals may be replaced with Java ones etc.
var type: ImportedTypeName
var type: TranslatedType
}

extension ImportedParam {
Expand All @@ -91,30 +101,6 @@ extension ImportedParam {
}
}

public struct ImportedTypeName: Hashable {
public var swiftTypeName: String

public var swiftMangledName: String = ""

public var javaType: JavaType

public var isVoid: Bool { javaType == .void }

public var fullyQualifiedName: String { javaType.description }

/// Retrieve the Java class name that this type describes, or nil if it
/// doesn't represent a class at all.
public var javaClassName: String? {
javaType.className
}

public init(swiftTypeName: String, javaType: JavaType, swiftMangledName: String? = nil) {
self.swiftTypeName = swiftTypeName
self.javaType = javaType
self.swiftMangledName = swiftMangledName ?? ""
}
}

// TODO: this is used in different contexts and needs a cleanup
public enum SelfParameterVariant {
/// Make a method that accepts the raw memory pointer as a MemorySegment
Expand All @@ -130,7 +116,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible {
/// this will contain that declaration's imported name.
///
/// This is necessary when rendering accessor Java code we need the type that "self" is expecting to have.
public var parentName: ImportedTypeName?
var parentName: TranslatedType?
public var hasParent: Bool { parentName != nil }

/// This is a full name such as init(cap:name:).
Expand All @@ -155,7 +141,7 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible {
return identifier
}

public var returnType: ImportedTypeName
public var returnType: TranslatedType
public var parameters: [ImportedParam]

public func effectiveParameters(selfVariant: SelfParameterVariant?) -> [ImportedParam] {
Expand All @@ -172,13 +158,21 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible {
case .pointer:
let selfParam: FunctionParameterSyntax = "self$: $swift_pointer"
params.append(
ImportedParam(param: selfParam, type: java_lang_foreign_MemorySegment(swiftTypeName: "Self.self"))
ImportedParam(
param: selfParam,
type: parentName
)
)

case .memorySegment:
let selfParam: FunctionParameterSyntax = "self$: $java_lang_foreign_MemorySegment"
var parentForSelf = parentName
parentForSelf.javaType = .javaForeignMemorySegment
params.append(
ImportedParam(param: selfParam, type: java_lang_foreign_MemorySegment(swiftTypeName: ""))
ImportedParam(
param: selfParam,
type: parentForSelf
)
)

case .wrapper:
Expand All @@ -201,9 +195,9 @@ public struct ImportedFunc: ImportedDecl, CustomStringConvertible {
public var isInit: Bool = false

public init(
parentName: ImportedTypeName?,
parentName: TranslatedType?,
identifier: String,
returnType: ImportedTypeName,
returnType: TranslatedType,
parameters: [ImportedParam]
) {
self.parentName = parentName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public struct ForeignValueLayout: CustomStringConvertible {
}

extension ForeignValueLayout {
public static let SwiftSelf = Self(inlineComment: "Self", javaConstant: "SWIFT_SELF")
public static let SwiftPointer = Self(javaConstant: "SWIFT_POINTER")

public static let SwiftBool = Self(javaConstant: "SWIFT_BOOL")
Expand All @@ -63,6 +62,7 @@ extension ForeignValueLayout {
public static let SwiftInt64 = Self(javaConstant: "SWIFT_INT64")
public static let SwiftInt32 = Self(javaConstant: "SWIFT_INT32")
public static let SwiftInt16 = Self(javaConstant: "SWIFT_INT16")
public static let SwiftUInt16 = Self(javaConstant: "SWIFT_UINT16")
public static let SwiftInt8 = Self(javaConstant: "SWIFT_INT8")

public static let SwiftFloat = Self(javaConstant: "SWIFT_FLOAT")
Expand Down
7 changes: 0 additions & 7 deletions Sources/JExtractSwift/JavaTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@

import JavaTypes

func java_lang_foreign_MemorySegment(swiftTypeName: String) -> ImportedTypeName {
ImportedTypeName(
swiftTypeName: swiftTypeName,
javaType: .javaForeignMemorySegment
)
}

extension JavaType {
/// The description of the type java.lang.foreign.MemorySegment.
static var javaForeignMemorySegment: JavaType {
Expand Down
56 changes: 1 addition & 55 deletions Sources/JExtractSwift/Swift2JavaTranslator+MemoryLayouts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import SwiftBasicFormat
import SwiftParser
import SwiftSyntax

let SWIFT_POINTER = "SWIFT_POINTER"

extension Swift2JavaTranslator {
public func javaMemoryLayoutDescriptors(
forParametersOf decl: ImportedFunc,
Expand All @@ -31,61 +29,9 @@ extension Swift2JavaTranslator {
// decl.isInit ? nil : .wrapper

for param in decl.effectiveParameters(selfVariant: selfVariant) {
if let paramLayout = javaMemoryLayoutDescriptor(param.type) {
layouts.append(paramLayout)
}
layouts.append(param.type.foreignValueLayout)
}

return layouts
}

// This may reach for another types $layout I think
public func javaMemoryLayoutDescriptor(_ ty: ImportedTypeName) -> ForeignValueLayout? {
switch ty.swiftTypeName {
case "Bool":
return .SwiftBool
case "Int":
return .SwiftInt
case "Int32":
return .SwiftInt32
case "Int64":
return .SwiftInt64
case "Float":
return .SwiftFloat
case "Double":
return .SwiftDouble
case "Void":
return nil
case "Never":
return nil
case "Swift.UnsafePointer<Swift.UInt8>":
return .SwiftPointer
default:
break
}

// not great?
if ty.swiftTypeName == "Self.self" {
return .SwiftPointer
}

// not great?
if ty.swiftTypeName == "(any Any.Type)?" {
return .SwiftPointer
}

if ty.swiftTypeName == "() -> ()" {
return .SwiftPointer
}

// TODO: Java has OptionalLong, OptionalInt, OptionalDouble types.
// if ty.swiftTypeName.hasSuffix("?") {
// if ty.swiftTypeName == "Int?" {
// return JavaOptionalLong
// } else ..
// }

// Last fallback is to try to get the type's $layout()
return ForeignValueLayout(inlineComment: ty.swiftTypeName, customType: ty.fullyQualifiedName)
}
}
29 changes: 14 additions & 15 deletions Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extension Swift2JavaTranslator {
var printer = CodePrinter()

for (_, ty) in importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key }) {
let filename = "\(ty.name.javaClassName!).java"
let filename = "\(ty.javaType).java"
log.info("Printing contents: \(filename)")
printImportedClass(&printer, ty)

Expand Down Expand Up @@ -116,7 +116,7 @@ extension Swift2JavaTranslator {
printer.print(
"""
// FIXME: this detecting is somewhat off
public static final String TYPE_METADATA_NAME = "\(decl.name.swiftMangledName)";
public static final String TYPE_METADATA_NAME = "\(decl.swiftMangledName!)";
static final MemorySegment TYPE_METADATA = SwiftKit.getTypeByMangledNameInEnvironment(TYPE_METADATA_NAME);
"""
)
Expand Down Expand Up @@ -165,7 +165,7 @@ extension Swift2JavaTranslator {
}

public func printClass(_ printer: inout CodePrinter, _ decl: ImportedNominalType, body: (inout CodePrinter) -> Void) {
printer.printTypeDecl("public final class \(decl.name.javaClassName!)") { printer in
printer.printTypeDecl("public final class \(decl.javaType)") { printer in
// ==== Storage of the class
// FIXME: implement the self storage for the memory address and accessors
printClassSelfProperty(&printer, decl)
Expand Down Expand Up @@ -274,7 +274,7 @@ extension Swift2JavaTranslator {
printer.print(
"""
/** Instances are created using static {@code init} methods rather than through the constructor directly. */
private \(decl.name.javaClassName!)(MemorySegment selfMemorySegment) {
private \(decl.javaType)(MemorySegment selfMemorySegment) {
this.selfMemorySegment = selfMemorySegment;
}
"""
Expand Down Expand Up @@ -307,7 +307,7 @@ extension Swift2JavaTranslator {
// SWIFT_INT.withName("heapObject"),
// ...
// SWIFT_INT.withName("cap")
).withName("\(decl.name.javaClassName!)"); // TODO: is the name right?
).withName("\(decl.javaType)"); // TODO: is the name right?

/**
* When other types refer to this type, they refer to by a pointer,
Expand Down Expand Up @@ -421,15 +421,15 @@ extension Swift2JavaTranslator {
* \(decl.swiftDeclRaw ?? "")
* }
*/
public static \(parentName.javaClassName!) init(\(renderJavaParamDecls(decl, selfVariant: .none))) {
public static \(parentName.javaType) init(\(renderJavaParamDecls(decl, selfVariant: .none))) {
var mh$ = \(descClassIdentifier).HANDLE;
try {
if (TRACE_DOWNCALLS) {
traceDowncall(\(renderForwardParams(decl, selfVariant: nil)));
}

var self = (MemorySegment) mh$.invokeExact(\(renderForwardParams(decl, selfVariant: nil)), TYPE_METADATA);
return new \(parentName.javaClassName!)(self);
return new \(parentName.javaType)(self);
} catch (Throwable ex$) {
throw new AssertionError("should not reach here", ex$);
}
Expand Down Expand Up @@ -524,10 +524,10 @@ extension Swift2JavaTranslator {
decl: ImportedFunc,
selfVariant: SelfParameterVariant?
) {
let returnTy = decl.returnType.fullyQualifiedName
let returnTy = decl.returnType.javaType

let maybeReturnCast: String
if decl.returnType.isVoid {
if decl.returnType.javaType == .void {
maybeReturnCast = "" // nothing to return or cast to
} else {
maybeReturnCast = "return (\(returnTy))"
Expand Down Expand Up @@ -601,7 +601,7 @@ extension Swift2JavaTranslator {
}

for p in decl.effectiveParameters(selfVariant: selfVariant) {
let param = "\(p.type.fullyQualifiedName) \(p.effectiveName ?? nextUniqueParamName())"
let param = "\(p.type.javaType.description) \(p.effectiveName ?? nextUniqueParamName())"
ps.append(param)
}

Expand Down Expand Up @@ -641,7 +641,7 @@ extension Swift2JavaTranslator {
selfVariant: .pointer
)

if decl.returnType.isVoid {
if decl.returnType.javaType == .void {
printer.print("FunctionDescriptor.ofVoid(");
printer.indent()
} else {
Expand All @@ -655,10 +655,9 @@ extension Swift2JavaTranslator {
// when initializing, we return a pointer to the newly created object
printer.print("/* -> */\(ForeignValueLayout.SwiftPointer)", .parameterNewlineSeparator(returnTyIsLastTy))
} else {
if var returnDesc = javaMemoryLayoutDescriptor(decl.returnType) {
returnDesc.inlineComment = " -> "
printer.print(returnDesc, .parameterNewlineSeparator(returnTyIsLastTy))
}
var returnDesc = decl.returnType.foreignValueLayout
returnDesc.inlineComment = " -> "
printer.print(returnDesc, .parameterNewlineSeparator(returnTyIsLastTy))
}
}

Expand Down
Loading