@@ -142,6 +142,14 @@ public class ExportSwift {
142142 hint: " Only primitive types and types defined in the same module are allowed "
143143 )
144144 }
145+
146+ private func diagnoseNestedOptional( node: some SyntaxProtocol , type: String ) {
147+ diagnose (
148+ node: node,
149+ message: " Nested optional types are not supported: \( type) " ,
150+ hint: " Use a single optional like String? instead of String?? or Optional<Optional<T>> "
151+ )
152+ }
145153
146154 override func visit( _ node: FunctionDeclSyntax ) -> SyntaxVisitorContinueKind {
147155 switch state {
@@ -183,17 +191,32 @@ public class ExportSwift {
183191
184192 var parameters : [ Parameter ] = [ ]
185193 for param in node. signature. parameterClause. parameters {
186- guard let type = self . parent. lookupType ( for: param. type) else {
194+ let resolvedType = self . parent. lookupType ( for: param. type)
195+
196+ if let type = resolvedType, case . optional( let wrappedType) = type, wrappedType. isOptional {
197+ diagnoseNestedOptional ( node: param. type, type: param. type. trimmedDescription)
198+ continue
199+ }
200+
201+ guard let type = resolvedType else {
187202 diagnoseUnsupportedType ( node: param. type, type: param. type. trimmedDescription)
188203 continue
189204 }
205+
190206 let name = param. secondName? . text ?? param. firstName. text
191207 let label = param. firstName. text
192208 parameters. append ( Parameter ( label: label, name: name, type: type) )
193209 }
194210 let returnType : BridgeType
195211 if let returnClause = node. signature. returnClause {
196- guard let type = self . parent. lookupType ( for: returnClause. type) else {
212+ let resolvedType = self . parent. lookupType ( for: returnClause. type)
213+
214+ if let type = resolvedType, case . optional( let wrappedType) = type, wrappedType. isOptional {
215+ diagnoseNestedOptional ( node: returnClause. type, type: returnClause. type. trimmedDescription)
216+ return nil
217+ }
218+
219+ guard let type = resolvedType else {
197220 diagnoseUnsupportedType ( node: returnClause. type, type: returnClause. type. trimmedDescription)
198221 return nil
199222 }
@@ -712,10 +735,53 @@ public class ExportSwift {
712735 }
713736
714737 func lookupType( for type: TypeSyntax ) -> BridgeType ? {
715- if let primitive = BridgeType ( swiftType: type. trimmedDescription) {
716- return primitive
738+ // 1. Handle T? syntax (OptionalTypeSyntax)
739+ if let optionalType = type. as ( OptionalTypeSyntax . self) {
740+ let wrappedType = optionalType. wrappedType
741+ if let baseType = lookupType ( for: wrappedType) {
742+ return . optional( baseType)
743+ }
744+ }
745+
746+ // 2. Handle Optional<T> syntax (IdentifierTypeSyntax with generic arguments)
747+ if let identifierType = type. as ( IdentifierTypeSyntax . self) ,
748+ identifierType. name. text == " Optional " ,
749+ let genericArgs = identifierType. genericArgumentClause? . arguments,
750+ genericArgs. count == 1 ,
751+ let argType = genericArgs. first? . argument {
752+ if let baseType = lookupType ( for: argType) {
753+ return . optional( baseType)
754+ }
755+ }
756+
757+ // 3. Handle Swift.Optional<T> syntax (MemberTypeSyntax)
758+ if let memberType = type. as ( MemberTypeSyntax . self) ,
759+ let baseType = memberType. baseType. as ( IdentifierTypeSyntax . self) ,
760+ baseType. name. text == " Swift " ,
761+ memberType. name. text == " Optional " ,
762+ let genericArgs = memberType. genericArgumentClause? . arguments,
763+ genericArgs. count == 1 ,
764+ let argType = genericArgs. first? . argument {
765+ if let wrappedType = lookupType ( for: argType) {
766+ return . optional( wrappedType)
767+ }
768+ }
769+
770+ // 4. Handle type aliases - try to resolve through type declaration resolver first
771+ if let aliasDecl = typeDeclResolver. resolveTypeAlias ( type) {
772+ // Recursively lookup the aliased type
773+ if let resolvedType = lookupType ( for: aliasDecl. initializer. value) {
774+ return resolvedType
775+ }
717776 }
718777
778+ // 5. Handle primitive types before falling back to other type declarations
779+ let typeName = type. trimmedDescription
780+ if let primitiveType = BridgeType . primitive ( swiftType: typeName) {
781+ return primitiveType
782+ }
783+
784+ // 6. Try to resolve other type declarations
719785 guard let typeDecl = typeDeclResolver. resolve ( type) else {
720786 return nil
721787 }
@@ -831,9 +897,19 @@ public class ExportSwift {
831897 } else {
832898 argumentsToLift = liftingInfo. parameters. map { ( name, _) in param. name + name. capitalizedFirstLetter }
833899 }
900+
901+ // For optional types, use Optional<WrappedType> syntax instead of WrappedType?
902+ let typeNameForIntrinsic : String
903+ switch param. type {
904+ case . optional( let wrappedType) :
905+ typeNameForIntrinsic = " Optional< \( wrappedType. swiftType) > "
906+ default :
907+ typeNameForIntrinsic = param. type. swiftType
908+ }
909+
834910 liftedParameterExprs. append (
835911 ExprSyntax (
836- " \( raw: param . type . swiftType ) .bridgeJSLiftParameter( \( raw: argumentsToLift. joined ( separator: " , " ) ) ) "
912+ " \( raw: typeNameForIntrinsic ) .bridgeJSLiftParameter( \( raw: argumentsToLift. joined ( separator: " , " ) ) ) "
837913 )
838914 )
839915 for (name, type) in zip ( argumentsToLift, liftingInfo. parameters. map { $0. type } ) {
@@ -928,6 +1004,12 @@ public class ExportSwift {
9281004 return
9291005 }
9301006
1007+ // Handle optional types that use special storage functions and return Void
1008+ if case . optional( _) = returnType {
1009+ append ( " return ret.bridgeJSLowerReturn() " )
1010+ return
1011+ }
1012+
9311013 append ( " return ret.bridgeJSLowerReturn() " )
9321014 }
9331015
@@ -1085,6 +1167,8 @@ public class ExportSwift {
10851167 return " \( paramName) Float.bridgeJSLiftParameter(_swift_js_pop_param_f32()) "
10861168 case . double:
10871169 return " \( paramName) Double.bridgeJSLiftParameter(_swift_js_pop_param_f64()) "
1170+ case . optional( _) :
1171+ return " /* Optional associated value lifting not yet implemented */nil " // Placeholder
10881172 default :
10891173 return " \( paramName) Int.bridgeJSLiftParameter(_swift_js_pop_param_int32()) "
10901174 }
@@ -1121,6 +1205,8 @@ public class ExportSwift {
11211205 bodyLines. append ( " _swift_js_push_f32( \( paramName) ) " )
11221206 case . double:
11231207 bodyLines. append ( " _swift_js_push_f64( \( paramName) ) " )
1208+ case . optional( _) :
1209+ bodyLines. append ( " // Optional associated value lowering not yet implemented " ) // Placeholder
11241210 default :
11251211 bodyLines. append (
11261212 " preconditionFailure( \" BridgeJS: unsupported associated value type in generated code \" ) "
@@ -1331,24 +1417,55 @@ extension AttributeListSyntax {
13311417}
13321418
13331419extension BridgeType {
1420+ // This initializer is primarily for string-based type descriptions,
1421+ // especially for internal and raw type lookups.
1422+ // For full SwiftSyntax based parsing, `ExportSwift.lookupType(for:)` should be used.
13341423 init ? ( swiftType: String ) {
1424+ // Use SwiftSyntax to parse the string into a TypeSyntax for robust optional detection
1425+ let typeSyntax = TypeSyntax ( stringLiteral: swiftType)
1426+
1427+ // 1. Handle T? syntax (OptionalTypeSyntax)
1428+ if let optionalType = typeSyntax. as ( OptionalTypeSyntax . self) {
1429+ let wrappedTypeString = optionalType. wrappedType. trimmedDescription
1430+ if let baseType = BridgeType ( swiftType: wrappedTypeString) {
1431+ self = . optional( baseType)
1432+ return
1433+ }
1434+ }
1435+
1436+ // 2. Handle Optional<T> syntax (IdentifierTypeSyntax with generic arguments)
1437+ if let identifierType = typeSyntax. as ( IdentifierTypeSyntax . self) ,
1438+ identifierType. name. text == " Optional " ,
1439+ let genericArgs = identifierType. genericArgumentClause? . arguments,
1440+ genericArgs. count == 1 ,
1441+ let argType = genericArgs. first? . argument {
1442+ let innerTypeString = argType. trimmedDescription
1443+ if let baseType = BridgeType ( swiftType: innerTypeString) {
1444+ self = . optional( baseType)
1445+ return
1446+ }
1447+ }
1448+
1449+ // Fallback to primitive type handling if not an optional
1450+ if let primitive = BridgeType . primitive ( swiftType: swiftType) {
1451+ self = primitive
1452+ return
1453+ }
1454+
1455+ return nil
1456+ }
1457+
1458+ // Helper for direct primitive type mapping (used by init? and elsewhere)
1459+ fileprivate static func primitive( swiftType: String ) -> BridgeType ? {
13351460 switch swiftType {
1336- case " Int " :
1337- self = . int
1338- case " Float " :
1339- self = . float
1340- case " Double " :
1341- self = . double
1342- case " String " :
1343- self = . string
1344- case " Bool " :
1345- self = . bool
1346- case " Void " :
1347- self = . void
1348- case " JSObject " :
1349- self = . jsObject( nil )
1350- default :
1351- return nil
1461+ case " Int " : return . int
1462+ case " Float " : return . float
1463+ case " Double " : return . double
1464+ case " String " : return . string
1465+ case " Bool " : return . bool
1466+ case " Void " : return . void
1467+ case " JSObject " : return . jsObject( nil )
1468+ default : return nil
13521469 }
13531470 }
13541471}
@@ -1377,6 +1494,7 @@ extension BridgeType {
13771494 case . jsObject( let name? ) : return name
13781495 case . swiftHeapObject( let name) : return name
13791496 case . void: return " Void "
1497+ case . optional( let wrappedType) : return " \( wrappedType. swiftType) ? "
13801498 case . caseEnum( let name) : return name
13811499 case . rawValueEnum( let name, _) : return name
13821500 case . associatedValueEnum( let name) : return name
@@ -1400,6 +1518,7 @@ extension BridgeType {
14001518 ( " caseId " , . i32)
14011519 ] )
14021520 }
1521+
14031522
14041523 func liftParameterInfo( ) throws -> LiftingIntrinsicInfo {
14051524 switch self {
@@ -1411,6 +1530,11 @@ extension BridgeType {
14111530 case . jsObject: return . jsObject
14121531 case . swiftHeapObject: return . swiftHeapObject
14131532 case . void: return . void
1533+ case . optional( let wrappedType) :
1534+ // Optional parameters include optionality flag plus wrapped type parameters
1535+ var optionalParams : [ ( name: String , type: WasmCoreType ) ] = [ ( " isSome " , . i32) ]
1536+ optionalParams. append ( contentsOf: try wrappedType. liftParameterInfo ( ) . parameters)
1537+ return LiftingIntrinsicInfo ( parameters: optionalParams)
14141538 case . caseEnum: return . caseEnum
14151539 case . rawValueEnum( _, let rawType) :
14161540 switch rawType {
@@ -1458,6 +1582,9 @@ extension BridgeType {
14581582 case . jsObject: return . jsObject
14591583 case . swiftHeapObject: return . swiftHeapObject
14601584 case . void: return . void
1585+ case . optional( _) :
1586+ // Optional return values use special storage functions and return void
1587+ return LoweringIntrinsicInfo ( returnType: nil )
14611588 case . caseEnum: return . caseEnum
14621589 case . rawValueEnum( _, let rawType) :
14631590 switch rawType {
0 commit comments