Skip to content

Commit e2a825a

Browse files
author
Max Moiseev
committed
[stdlib] doc comments and minor edits in integers prototype
1 parent 2191ab2 commit e2a825a

File tree

1 file changed

+88
-34
lines changed

1 file changed

+88
-34
lines changed

test/Prototypes/Integers.swift.gyb

Lines changed: 88 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,22 @@ public func _log(@autoclosure message: ()->String) {
125125
//===----------------------------------------------------------------------===//
126126
//===--- Arithmetic -------------------------------------------------------===//
127127
//===----------------------------------------------------------------------===//
128+
129+
/// Arithmetic protocol declares methods backing binary arithmetic operators,
130+
/// such as `+`, `-` and `*`; and their mutating counterparts. These methods
131+
/// operate on arguments of the same type.
132+
///
133+
/// Both mutating and non-mutating operations are declared in the protocol, but
134+
/// only the mutating ones are required. Should conforming type omit
135+
/// non-mutating implementations, they will be provided by a protocol extension.
136+
/// Implementation in that case will copy `self`, perform a mutating operation
137+
/// on it and return the resulting value.
128138
public protocol Arithmetic {
129139
/// Initialize to zero
130140
init()
131141

132142
% for x in binaryArithmetic:
133-
// defaulted using an InPlace counterpart, but can be used as an
143+
// defaulted using an in-place counterpart, but can be used as an
134144
// optimization hook
135145
@warn_unused_result
136146
func ${x.name}(${x.firstArg} rhs: Self) -> Self
@@ -151,6 +161,11 @@ extension Arithmetic {
151161
% end
152162
}
153163

164+
/// SignedArithmetic protocol will only be conformed to by signed numbers,
165+
/// otherwise it would be posible to negate an unsigned value.
166+
///
167+
/// The only method of this protocol has the default implementation in an
168+
/// extension, that uses a parameterless initializer and subtraction.
154169
public protocol SignedArithmetic : Arithmetic {
155170
func negate() -> Self
156171
}
@@ -187,16 +202,46 @@ public prefix func -<T: SignedArithmetic>(x: T) -> T {
187202
public typealias Word = Int${word_bits}
188203
public typealias UWord = UInt${word_bits}
189204

190-
% IntegerBase = 'Comparable, Arithmetic,' + \
205+
% IntegerBase = 'Comparable, Arithmetic, ' + \
191206
% 'IntegerLiteralConvertible, CustomStringConvertible'
192207

208+
/// Integer protocol is a base for all the integer types that are available in
209+
/// the standard library, and besides should be suffecient to implement
210+
/// arbitrary precision integer types.
211+
///
212+
/// `isEqual(to:)` and `isLess(than:)` methods are the ones responsible for
213+
/// `Equatable` and `Comparable` protocol conformances. In a way similar to how
214+
/// arithmetic operations are dispatched in `Arithmetic`, `==` and `<` operators
215+
/// for homogenous comparisons have default implementations that call
216+
/// `isEqual(to:)` and `isLess(than:)` respectively.
217+
///
218+
/// This protocol adds 3 new initializers to the parameterless one, inherited
219+
/// from `Arithmetic`. These initializers allow to construct values of type
220+
/// from instances of any other type, conforming to `Integer`, using different
221+
/// strategies:
222+
/// - Perform checks whether the value is representable in `Self`
223+
/// - Try to represent the value without bounds checking
224+
/// - Substitute values beyond `Self` bounds with maximum/minimum value of
225+
/// `Self` respectively
193226
public protocol Integer : ${IntegerBase} {
194227

195228
// FIXME(compiler limitation): Ideally, this constraint would just be :
196229
// Integer. Until we get recursive protocol requirements, that isn't
197230
// possible.
231+
232+
/// A type that can hold absolute values of all the possible values of `Self`.
233+
/// Concrete types do not have to provide a typealias for it as it can be
234+
/// inferred from an `absoluteValue` property. This property (and type) can be
235+
/// useful in operations that are simpler to implement in terms of
236+
/// (potentially larger) unsigned values, for example, printing a value of an
237+
/// integer (it's just adding a '-' character in front of an absolute value).
238+
/// Please note, that `absoluteValue` property should not in general be used
239+
/// as a substitute for an `abs` free function, that returns a value of the
240+
/// same type.
198241
associatedtype AbsoluteValue : ${IntegerBase}
199242

243+
static var isSigned: Bool { get }
244+
200245
/// An absolute value of the represented number.
201246
///
202247
/// Please note that `absoluteValue` has a different type than `self`, and so
@@ -207,28 +252,26 @@ public protocol Integer : ${IntegerBase} {
207252
// the interface and error messages (and on the type checker) than
208253
// does having many operator overloads.
209254
@warn_unused_result
210-
func isEqualTo(rhs: Self) -> Bool
211-
255+
func isEqual(to rhs: Self) -> Bool
212256
@warn_unused_result
213-
func isLessThan(rhs: Self) -> Bool
257+
func isLess(than rhs: Self) -> Bool
214258

215259
init<T : Integer>(_ source: T)
216-
217260
init<T : Integer>(extendingOrTruncating source: T)
218261
init<T : Integer>(clamping source: T)
219262

263+
/// Return n-th word in the underlying representation of `self`.
220264
@warn_unused_result
221265
func nthWord(n: Word) -> UWord
222266

223-
static var isSigned: Bool { get }
224-
225-
// A number of bits in current representation of `self`
226-
// Will be constant for fixed-width integer types.
267+
/// A number of bits in current representation of `self`
268+
/// Will be constant for fixed-width integer types.
227269
var bitWidth : Word { get }
228270

229271
/// If `self` is negative, returns the index of the least significant bit of
230272
/// our representation such that all more-significant bits are 1.
231273
/// Has the value -1 if `self` is 0.
274+
/// Has the value equal to `bitWidth - 1` for fixed width integers.
232275
var signBitIndex: Word { get }
233276
}
234277

@@ -242,13 +285,13 @@ extension Integer {
242285
@_transparent
243286
@warn_unused_result
244287
public func == <T : Integer>(lhs:T, rhs: T) -> Bool {
245-
return lhs.isEqualTo(rhs)
288+
return lhs.isEqual(to: rhs)
246289
}
247290

248291
@_transparent
249292
@warn_unused_result
250293
public func < <T : Integer>(lhs: T, rhs: T) -> Bool {
251-
return lhs.isLessThan(rhs)
294+
return lhs.isLess(than: rhs)
252295
}
253296

254297
//===--- Heterogeneous comparison -----------------------------------------===//
@@ -353,15 +396,34 @@ public enum ArithmeticOverflow {
353396
case none, overflow
354397
}
355398

399+
/// A protocol for all the fixed width integer types. Main addition to the
400+
/// `Integer` protocol is binary bitwise operations and bit shifts.
401+
///
402+
/// `WithOverflow` family of methods is used in default implementations of
403+
/// mutating arithmetic methods (from `Arithmetic` protocol), provided by a
404+
/// protocol extension. Having these methods allows to provide both safe
405+
/// (trapping) and unsafe implementation of arithmetic operations without
406+
/// duplicating code.
407+
///
408+
/// Bitwise binary and shift operators are implemented the same way as
409+
/// arithmetic operations: free function dispatches a call to a corresponding
410+
/// protocol method.
411+
///
412+
/// `doubleWidthMultiply` method is a necessary building block to implement
413+
/// support for integer types of a greater width and as a consequence, arbitrary
414+
/// precision integers.
356415
public protocol FixedWidthInteger : Integer {
357416
static var bitWidth : Word { get }
358417

418+
static var max: Self { get }
419+
static var min: Self { get }
420+
359421
% for x in binaryArithmetic:
360422
%{
361423
comment = '''
362-
/// Return a pair consisting of `self` ${x.operator} `rhs`,
424+
/// Return a pair consisting of `self` {} `rhs`,
363425
/// truncated to fit if necessary, and a flag indicating whether an
364-
/// arithmetic overflow occurred.''' + ('''
426+
/// arithmetic overflow occurred.'''.format(x.operator) + ('''
365427
///
366428
/// - Precondition: `rhs != 0`''' if x.kind == '/' else '')
367429
}%
@@ -372,18 +434,14 @@ ${comment}
372434
) -> (partialValue: Self, overflow: ArithmeticOverflow)
373435
% end
374436

375-
@warn_unused_result
376-
func doubleWidthMultiply(other: Self) -> (high: Self, low: AbsoluteValue)
377-
378-
static var max: Self { get }
379-
380-
static var min: Self { get }
381-
382437
% for x in binaryBitwise + maskingShifts:
383438
@warn_unused_result
384439
func ${x.name}(rhs: Self) -> Self
385440
% end
386441

442+
@warn_unused_result
443+
func doubleWidthMultiply(other: Self) -> (high: Self, low: AbsoluteValue)
444+
387445
init(_truncatingBits bits: UWord)
388446
}
389447

@@ -695,12 +753,12 @@ public struct ${Self}
695753
}
696754

697755
@warn_unused_result
698-
public func isEqualTo(rhs: ${Self}) -> Bool {
756+
public func isEqual(to rhs: ${Self}) -> Bool {
699757
return Bool(Builtin.cmp_eq_Int${bits}(_storage, rhs._storage))
700758
}
701759

702760
@warn_unused_result
703-
public func isLessThan(rhs: ${Self}) -> Bool {
761+
public func isLess(than rhs: ${Self}) -> Bool {
704762
return Bool(Builtin.cmp_${u}lt_Int${bits}(_storage, rhs._storage))
705763
}
706764

@@ -889,13 +947,13 @@ public struct DoubleWidth<
889947
}
890948

891949
@warn_unused_result
892-
public func isEqualTo(rhs: DoubleWidth<T>) -> Bool {
950+
public func isEqual(to rhs: DoubleWidth<T>) -> Bool {
893951
return (_storage.high == rhs._storage.high) &&
894952
(_storage.low == rhs._storage.low)
895953
}
896954

897955
@warn_unused_result
898-
public func isLessThan(rhs: DoubleWidth<T>) -> Bool {
956+
public func isLess(than rhs: DoubleWidth<T>) -> Bool {
899957
if _storage.high < rhs._storage.high {
900958
return true
901959
}
@@ -913,10 +971,6 @@ public struct DoubleWidth<
913971
fatalError()
914972
}
915973

916-
public init<T : Integer>(clamping source: T) {
917-
fatalError()
918-
}
919-
920974
@warn_unused_result
921975
public func nthWord(n: Word) -> UWord {
922976
if T.bitWidth < ${word_bits} || T.bitWidth % ${word_bits} != 0 {
@@ -1101,13 +1155,13 @@ public struct ${Self}
11011155
}
11021156

11031157
@warn_unused_result
1104-
public func isEqualTo(rhs: ${Self}) -> Bool {
1105-
return _storage.isEqualTo(rhs._storage)
1158+
public func isEqual(to rhs: ${Self}) -> Bool {
1159+
return _storage.isEqual(to: rhs._storage)
11061160
}
11071161

11081162
@warn_unused_result
1109-
public func isLessThan(rhs: ${Self}) -> Bool {
1110-
return _storage.isLessThan(rhs._storage)
1163+
public func isLess(than rhs: ${Self}) -> Bool {
1164+
return _storage.isLess(than: rhs._storage)
11111165
}
11121166

11131167
% for x in binaryArithmetic:
@@ -1705,7 +1759,7 @@ tests.test("DoubleWidth/Int8/not equal") {
17051759
expectNotEqual(a, b)
17061760
}
17071761

1708-
tests.test("DoubleWidth/Int8/isLessThan") {
1762+
tests.test("DoubleWidth/Int8/isLess(than:)") {
17091763
let a = DoubleWidth<Int8>.min
17101764
let z = DoubleWidth<Int8>()
17111765
let b = DoubleWidth<Int8>.max

0 commit comments

Comments
 (0)