import { wrapped } from "../functions" ; import { expressionSkipsCopy , FunctionMap , PossibleRepresentation , ReifiedType , TypeParameterHost } from "../reified" ; import { Scope } from "../scope" ; import { lookupForMap } from "../utils" ; import { binary , call , conditional , conformance , expr , functionValue , literal , logical , optional , read , representationsForTypeValue , reuse , typeFromValue , typeIsDirectlyComparable , typeTypeValue , ArgGetter , Value } from "../values" ; import { applyDefaultConformances , binaryBuiltin , returnTodo , reuseArgs } from "./common" ; export function unwrapOptional ( value , type , scope ) { return call ( functionValue ( "Swift.(swift-to-js).unwrapOptional()" , undefined , "(T.Type, T?) -> T" ) , [ type , value ] , [ type , type ] , scope ) ; } export function optionalIsNone ( value , type , scope ) { return call ( functionValue ( "Swift.(swift-to-js).optionalIsNone()" , undefined , "(T.Type, T?) -> Bool" ) , [ type , value ] , [ type , type ] , scope ) ; } export function optionalIsSome ( value , type , scope ) { return call ( functionValue ( "Swift.(swift-to-js).optionalIsSome()" , undefined , "(T.Type, T?) -> Bool" ) , [ type , value ] , [ type , type ] , scope ) ; } function copyOptional ( value , type , scope ) { return call ( functionValue ( "Swift.(swift-to-js).copyOptional()" , undefined , "(T.Type, T?) -> T?" ) , [ type , value ] , [ type , type ] , scope ) ; } export function emptyOptional ( type , scope ) { return optional ( type , undefined ) ; } export function wrapInOptional ( value , type , scope ) { return optional ( type , value ) ; } export function Optional ( globalScope , typeParameters ) { const [ wrappedType ] = typeParameters ( "Wrapped" ) ; const reified = typeFromValue ( wrappedType , globalScope ) ; if ( wrappedType . kind !== "type" ) { throw new TypeError ( `Runtime types are not supported as Self in Self?` ) ; } const isDirectlyComparable = typeIsDirectlyComparable ( wrappedType , globalScope ) ; const compareEqual = wrapped ( isDirectlyComparable ? binaryBuiltin ( "===" , 0 ) : ( scope , arg ) => { const equalMethod = call ( functionValue ( "==" , conformance ( wrappedType , "Equatable" , scope ) , "() -> () -> Bool" ) , [ wrappedType ] , [ typeTypeValue ] , scope ) ; return reuseArgs ( arg , 0 , scope , [ "lhs" , "rhs" ] , ( lhs , rhs ) => { return conditional ( optionalIsNone ( lhs , wrappedType , scope ) , optionalIsNone ( rhs , wrappedType , scope ) , logical ( "&&" , optionalIsSome ( rhs , wrappedType , scope ) , call ( equalMethod , [ unwrapOptional ( lhs , wrappedType , scope ) , unwrapOptional ( rhs , wrappedType , scope ) , ] , [ wrappedType , wrappedType ] , scope ) , scope ) , scope ) ; } ) ; } , "(Self?, Self?) -> Bool" ) ; const compareUnequal = wrapped ( isDirectlyComparable ? binaryBuiltin ( "!==" , 0 ) : ( scope , arg ) => { const unequalMethod = call ( functionValue ( "!=" , conformance ( wrappedType , "Equatable" , scope ) , "() -> () -> Bool" ) , [ wrappedType ] , [ typeTypeValue ] , scope ) ; return reuseArgs ( arg , 0 , scope , [ "lhs" , "rhs" ] , ( lhs , rhs ) => { return conditional ( optionalIsNone ( lhs , wrappedType , scope ) , optionalIsSome ( rhs , wrappedType , scope ) , logical ( "||" , optionalIsNone ( rhs , wrappedType , scope ) , call ( unequalMethod , [ unwrapOptional ( lhs , wrappedType , scope ) , unwrapOptional ( rhs , wrappedType , scope ) , ] , [ wrappedType , wrappedType ] , scope ) , scope ) , scope ) ; } ) ; } , "(Self?, Self?) -> Bool" ) ; return { functions : lookupForMap ( { "none" : ( scope ) => emptyOptional ( wrappedType , scope ) , "some" : wrapped ( ( scope , arg ) => wrapInOptional ( arg ( 0 , "wrapped" ) , wrappedType , scope ) , "(Self) -> Self?" ) , "==" : compareEqual , "!=" : compareUnequal , "flatMap" : returnTodo , } as FunctionMap ) , conformances : applyDefaultConformances ( { Object : { functions : { ":rep" : wrapped ( ( innerScope ) => { return conditional ( binary ( "&" , representationsForTypeValue ( wrappedType , innerScope ) , literal ( PossibleRepresentation . Null ) , innerScope ) , literal ( PossibleRepresentation . Array ) , binary ( "|" , representationsForTypeValue ( wrappedType , innerScope ) , literal ( PossibleRepresentation . Null ) , innerScope ) , innerScope ) ; } , "() -> Int" ) , } , requirements : [ ] , } , ExpressibleByNilLiteral : { functions : { "init(nilLiteral:)" : wrapped ( ( scope ) => emptyOptional ( wrappedType , scope ) , "() -> Self" ) , } , requirements : [ ] , } , Equatable : { functions : { "==" : compareEqual , "!=" : compareUnequal , } , requirements : [ ] , } , } , globalScope ) , defaultValue ( scope ) { return emptyOptional ( wrappedType , scope ) ; } , copy : true ? ( value , scope ) => { const expression = read ( value , scope ) ; if ( expressionSkipsCopy ( expression ) ) { return expr ( expression ) ; } const copier = reified . copy ; if ( copier ) { return reuse ( expr ( expression ) , scope , "copyValue" , ( source ) => { return conditional ( optionalIsNone ( source , wrappedType , scope ) , emptyOptional ( wrappedType , scope ) , wrapInOptional ( copier . call ( reified , source , scope ) , wrappedType , scope ) , scope ) ; } ) ; } else { return copyOptional ( value , wrappedType , scope ) ; } } : undefined , innerTypes : { } , } ; }