Skip to content

Commit a61ff50

Browse files
author
Chris Williams
committed
Int->Int Failable Initializers
1 parent 9c37b30 commit a61ff50

File tree

1 file changed

+60
-33
lines changed

1 file changed

+60
-33
lines changed

stdlib/public/core/FixedPoint.swift.gyb

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,6 @@ public struct ${Self}
256256
}
257257
% end
258258

259-
/// Create an instance initialized to `value`.
260-
@_transparent public
261-
init(_ value: ${Self}) { self = value }
262259

263260
% if bits > 8:
264261
/// Creates an integer from its big-endian representation, changing the
@@ -429,44 +426,72 @@ extension ${Self} {
429426
extension ${Self} : SignedNumber {}
430427
% end
431428

432-
// Construction from other integer types
433-
@_transparent
434-
extension ${Self} {
435-
% for src_ty in all_integer_types(word_bits):
436-
% srcBits = src_ty.bits
437-
% srcSigned = src_ty.is_signed
438-
% Src = src_ty.stdlib_name
439-
% (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext')
440-
% if Self != Src:
441-
public init(_ v: ${Src}) {
429+
430+
%{
431+
import gyb
432+
433+
fixed_fixed_conversion_function = gyb.parse_template("fixed_fixed_conversion_function",
434+
"""
442435
%
443-
let srcNotWord = v._value
436+
let srcNotWord = value._value
437+
let result: (value: Builtin.${BuiltinName}, error: Builtin.Int1)
444438
%
445-
% if srcBits == bits and srcSign == sign:
446-
let dstNotWord = srcNotWord
439+
% if srcBits == bits and srcSign == sign: # Exact same size/signedness.
440+
result = (srcNotWord, false._value)
447441
%
448-
% elif srcBits == bits:
449-
let tmp = Builtin.${srcSign}_to_${sign}_checked_conversion_Int${srcBits}(srcNotWord)
450-
Builtin.condfail(tmp.1)
451-
let dstNotWord = tmp.0
442+
% elif srcBits == bits: # Same size, switching signs.
443+
result = Builtin.${srcSign}_to_${sign}_checked_conversion_Int${srcBits}(srcNotWord)
452444
%
453-
% elif srcBits > bits:
454-
let tmp = Builtin.${srcSign}_to_${sign}_checked_trunc_Int${srcBits}_Int${bits}(srcNotWord)
455-
Builtin.condfail(tmp.1)
456-
let dstNotWord = tmp.0
445+
% elif srcBits > bits: # Larger input, check for truncation.
446+
result = Builtin.${srcSign}_to_${sign}_checked_trunc_Int${srcBits}_Int${bits}(srcNotWord)
457447
%
458-
% elif srcSigned and not signed:
459-
let tmp = Builtin.s_to_u_checked_conversion_Int${srcBits}(srcNotWord)
460-
Builtin.condfail(tmp.1)
461-
let dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(tmp.0)
448+
% elif srcSigned and not signed: # Smaller size input, signed going to unsigned.
449+
let (tmp, signError) = Builtin.s_to_u_checked_conversion_Int${srcBits}(srcNotWord)
450+
result = (Builtin.${srcExt}_Int${srcBits}_Int${bits}(tmp), signError)
462451
%
463-
% else:
464-
let dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(srcNotWord)
452+
% else: # Smaller size input, unsigned to signed or unsigned to unsigned.
453+
result = (Builtin.${srcExt}_Int${srcBits}_Int${bits}(srcNotWord), false._value)
465454
% end
466-
%
467-
self._value = dstNotWord
455+
%
456+
% if not safelyConvertable:
457+
${error_check}
458+
% end
459+
self._value = result.value
460+
""")
461+
}%
462+
463+
% for src_ty in all_integer_types(word_bits):
464+
% srcBits = src_ty.bits
465+
% srcSigned = src_ty.is_signed
466+
% Src = src_ty.stdlib_name
467+
% (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext')
468+
% safelyConvertable = (srcBits < bits and (srcSign == sign or signed)) or (srcBits == bits and srcSign == sign)
469+
470+
@_transparent
471+
extension ${Self} {
472+
473+
@_transparent
474+
public init(_ value: ${Src}) {
475+
${gyb.execute_template(
476+
fixed_fixed_conversion_function,
477+
error_check="Builtin.condfail(result.error)",
478+
**locals()
479+
)
480+
}
481+
}
482+
483+
% if safelyConvertable:
484+
@available(*, message: "Converting ${Src} to ${Self} will always succeed.")
485+
% end
486+
@_transparent
487+
public init?(exactly value: ${Src}) {
488+
${gyb.execute_template(
489+
fixed_fixed_conversion_function,
490+
error_check="if Bool(result.error) == true { return nil }",
491+
**locals()
492+
)
493+
}
468494
}
469-
% end
470495

471496
% if should_define_truncating_bit_pattern_init(src_ty=src_ty, dst_ty=self_ty):
472497
/// Construct a `${Self}` having the same bitwise representation as
@@ -488,8 +513,10 @@ extension ${Self} {
488513
}
489514

490515
% end
516+
}
491517
% end
492518

519+
extension ${Self} {
493520
/// Construct a `${Self}` having the same memory representation as
494521
/// the `${OtherSelf}` `bitPattern`. No range or overflow checking
495522
/// occurs, and the resulting `${Self}` may not have the same numeric

0 commit comments

Comments
 (0)