Adjust test cases.

Swift SVN r17964
This commit is contained in:
Ted Kremenek
2014-05-12 22:01:52 +00:00
parent d3f2e3816a
commit fad874708e
921 changed files with 60542 additions and 21542 deletions

View File

@@ -1,3 +1,5 @@
:orphan:
Hacking on Swift
================

View File

@@ -6,11 +6,13 @@ swift - the amazingly new programming language
=head1 SYNOPSIS
B<swift> [B<-c>|B<-S>|B<-i>] B<-sdk=>I<SDK-path> B<-g>
[B<-O0>|B<-O1>|B<-O2>|B<-O3>]
B<swift> [B<-emit-object>|B<-emit-assembly>|B<-emit-library>|B<-i>]
[-help]
B<-o> I<output-file>
I<input-filenames>
The full list of supported options is available via "swift -help".
=head1 DESCRIPTION
B<Swift> is a new, high performance systems programming language. It has a clean

View File

@@ -1,4 +1,4 @@
//===--- SwiftTargetInfo.cpp --------------------------------------------*-===//
//===--- SwiftTargetInfo.cpp ----------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -19,63 +19,137 @@
#include "IRGenModule.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DataLayout.h"
#include "swift/IRGen/Options.h"
#include "swift/ABI/System.h"
#include "swift/AST/IRGenOptions.h"
using namespace swift;
using namespace irgen;
/// Creates a generic SwiftTargetInfo with conservative values that should
/// be valid for any platform absent more specific information.
static SwiftTargetInfo getGenericSwiftTargetInfo(IRGenModule &IGM) {
auto pointerSize = IGM.DataLayout.getPointerSizeInBits();
// Assume no spare bits in pointers.
llvm::BitVector pointerSpareBits(pointerSize, false);
// Assume all bit patterns are reserved by the ObjC runtime.
llvm::BitVector objcReservedBits(pointerSize, true);
// Assume no special alignment of heap objects.
Alignment heapObjectAlignment(1);
// Assume only zero is an invalid pointer.
uint64_t leastValidPointerValue = 1;
return SwiftTargetInfo(std::move(pointerSpareBits),
std::move(objcReservedBits),
heapObjectAlignment,
leastValidPointerValue);
/// Initialize a bit vector to be equal to the given bit-mask.
static void setToMask(llvm::BitVector &bits, uint64_t mask) {
// This is a ridiculously inefficient way of doing this.
for (unsigned i = 0, e = bits.size(); i != e; ++i) {
if (mask & (1ULL << i)) {
bits.set(i);
} else {
bits.reset(i);
}
}
}
/// Creates SwiftTargetInfo for X86-64 platforms.
static SwiftTargetInfo getX86_64SwiftTargetInfo(IRGenModule &IGM) {
// User space only uses the low 47 bits of a pointer.
// FIXME: In kernel mode, the highest bit is occupied.
llvm::BitVector pointerSpareBits(47, false);
pointerSpareBits.resize(64, true);
/// Configures target-specific information for arm64 platforms.
static void configureARM64(IRGenModule &IGM, const llvm::Triple &triple,
SwiftTargetInfo &target) {
setToMask(target.PointerSpareBits,
SWIFT_ABI_ARM64_SWIFT_SPARE_BITS_MASK);
setToMask(target.ObjCPointerReservedBits,
SWIFT_ABI_ARM64_OBJC_RESERVED_BITS_MASK);
// Objective-C reserves the lowest and highest bits for tagged pointers.
llvm::BitVector objcReservedBits(64, false);
objcReservedBits[0] = true;
objcReservedBits[63] = true;
if (triple.isOSDarwin()) {
target.LeastValidPointerValue =
SWIFT_ABI_DARWIN_ARM64_LEAST_VALID_POINTER;
}
// Heap objects are 16-byte-aligned.
Alignment heapObjectAlignment(16);
// CGPoint and CGRect are both returned in registers.
target.MaxScalarsForDirectResult = 4;
// The null 4K page is always unmapped.
// FIXME: Are additional null pages always unmapped on some platforms?
uint64_t leastValidPointerValue = 4096;
// arm64 has no special objc_msgSend variants, not even stret.
target.ObjCUseStret = false;
return SwiftTargetInfo(std::move(pointerSpareBits),
std::move(objcReservedBits),
heapObjectAlignment,
leastValidPointerValue);
// arm64 requires marker assembly for objc_retainAutoreleasedReturnValue.
target.ObjCRetainAutoreleasedReturnValueMarker =
"mov\tfp, fp\t\t; marker for objc_retainAutoreleaseReturnValue";
}
/// Configures target-specific information for x86-64 platforms.
static void configureX86_64(IRGenModule &IGM, const llvm::Triple &triple,
SwiftTargetInfo &target) {
setToMask(target.PointerSpareBits,
SWIFT_ABI_X86_64_SWIFT_SPARE_BITS_MASK);
setToMask(target.ObjCPointerReservedBits,
SWIFT_ABI_X86_64_OBJC_RESERVED_BITS_MASK);
if (triple.isOSDarwin()) {
target.LeastValidPointerValue =
SWIFT_ABI_DARWIN_X86_64_LEAST_VALID_POINTER;
}
// On simulator targets, use null instead of &_objc_empty_vtable.
if (triple.isiOS())
target.ObjCUseNullForEmptyVTable = true;
// x86-64 has every objc_msgSend variant known to humankind.
target.ObjCUseFPRet = true;
target.ObjCUseFP2Ret = true;
}
/// Configures target-specific information for 32-bit x86 platforms.
static void configureX86(IRGenModule &IGM, const llvm::Triple &triple,
SwiftTargetInfo &target) {
// On simulator targets, use null instead of &_objc_empty_vtable.
if (triple.isiOS())
target.ObjCUseNullForEmptyVTable = true;
// x86 uses objc_msgSend_fpret but not objc_msgSend_fp2ret.
target.ObjCUseFPRet = true;
}
/// Configures target-specific information for 32-bit arm platforms.
static void configureARM(IRGenModule &IGM, const llvm::Triple &triple,
SwiftTargetInfo &target) {
// ARM requires marker assembly for objc_retainAutoreleasedReturnValue.
target.ObjCRetainAutoreleasedReturnValueMarker =
"mov\tr7, r7\t\t@ marker for objc_retainAutoreleaseReturnValue";
}
/// Configure a default target.
SwiftTargetInfo::SwiftTargetInfo(unsigned numPointerBits)
: PointerSpareBits(numPointerBits, false),
ObjCPointerReservedBits(numPointerBits, true),
HeapObjectAlignment(numPointerBits / 8),
LeastValidPointerValue(SWIFT_ABI_DEFAULT_LEAST_VALID_POINTER)
{
setToMask(PointerSpareBits,
SWIFT_ABI_DEFAULT_SWIFT_SPARE_BITS_MASK);
setToMask(ObjCPointerReservedBits,
SWIFT_ABI_DEFAULT_OBJC_RESERVED_BITS_MASK);
}
SwiftTargetInfo SwiftTargetInfo::get(IRGenModule &IGM) {
llvm::Triple triple(IGM.Opts.Triple);
auto pointerSize = IGM.DataLayout.getPointerSizeInBits();
/// Prepare generic target information.
SwiftTargetInfo target(pointerSize);
switch (triple.getArch()) {
case llvm::Triple::x86_64:
return getX86_64SwiftTargetInfo(IGM);
configureX86_64(IGM, triple, target);
break;
case llvm::Triple::x86:
configureX86(IGM, triple, target);
break;
case llvm::Triple::arm:
configureARM(IGM, triple, target);
break;
case llvm::Triple::arm64:
configureARM64(IGM, triple, target);
break;
default:
return getGenericSwiftTargetInfo(IGM);
// FIXME: Complain here? Default target info is unlikely to be correct.
break;
}
// The JIT does not support absolute symbols, so we have to use null
// for &objc_empty_vtable.
if (IGM.Opts.UseJIT) {
target.ObjCUseNullForEmptyVTable = true;
}
return target;
}

View File

@@ -26,40 +26,52 @@ namespace irgen {
class IRGenModule;
class SwiftTargetInfo {
explicit SwiftTargetInfo(unsigned numPointerBits);
public:
SwiftTargetInfo(llvm::BitVector &&pointerSpareBits,
llvm::BitVector &&objcPointerReservedBits,
Alignment heapObjectAlignment,
uint64_t leastValidPointerValue)
: PointerSpareBits(std::move(pointerSpareBits)),
ObjCPointerReservedBits(std::move(objcPointerReservedBits)),
HeapObjectAlignment(heapObjectAlignment),
LeastValidPointerValue(leastValidPointerValue)
{}
/// Produces a SwiftTargetInfo object appropriate to the target.
static SwiftTargetInfo get(IRGenModule &IGM);
/// The spare bit mask for pointers. Bits set in this mask are unused by
/// pointers of any alignment.
const llvm::BitVector PointerSpareBits;
llvm::BitVector PointerSpareBits;
/// The reserved bit mask for Objective-C pointers. Pointer values with
/// bits from this mask set are reserved by the ObjC runtime and cannot be
/// used for Swift value layout when a reference type may reference ObjC
/// objects.
const llvm::BitVector ObjCPointerReservedBits;
llvm::BitVector ObjCPointerReservedBits;
/// The alignment of heap objects.
const Alignment HeapObjectAlignment;
/// The alignment of heap objects. By default, assume pointer alignment.
Alignment HeapObjectAlignment;
/// The least integer value that can theoretically form a valid pointer.
/// This excludes addresses in the null page(s) guaranteed to be unmapped by
/// the platform.
const uint64_t LeastValidPointerValue;
/// By default, assume that there's an entire page free.
///
/// This excludes addresses in the null page(s) guaranteed to be
/// unmapped by the platform.
///
/// Changes to this must be kept in sync with swift/Runtime/Metadata.h.
uint64_t LeastValidPointerValue;
/// The maximum number of scalars that we allow to be returned directly.
/// FIXME Until rdar://14679857, this must be set such that
/// NSRect and NSPoint structs are returned correctly.
unsigned MaxScalarsForDirectResult = 3;
/// Inline assembly to mark a call to objc_retainAutoreleasedReturnValue.
llvm::StringRef ObjCRetainAutoreleasedReturnValueMarker;
/// Some architectures have specialized objc_msgSend variants.
bool ObjCUseStret = true;
bool ObjCUseFPRet = false;
bool ObjCUseFP2Ret = false;
bool ObjCUseNullForEmptyVTable = false;
};
}
}
#endif

View File

@@ -1,114 +1,281 @@
//===----------------------------------------------------------------------===//
// Swift Algorithm Library.
// ===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
func minElement<
R : Enumerator
requires R.Element : Comparable>(range : R)
-> R.Element {
var result = range.next()
while !range.isEmpty() {
var next = range.next()
if next < result { result = next }
R : Sequence
where R.GeneratorType.Element : Comparable>(range: R)
-> R.GeneratorType.Element {
var g = range.generate()
var result = g.next()!
for e in GeneratorSequence(g) {
if e < result { result = e }
}
return result
}
func maxElement<
R : Enumerator
requires R.Element : Comparable>(range : R)
-> R.Element {
var result = range.next()
while !range.isEmpty() {
var next = range.next()
if next > result { result = next }
R : Sequence
where R.GeneratorType.Element : Comparable>(range: R)
-> R.GeneratorType.Element {
var g = range.generate()
var result = g.next()!
for e in GeneratorSequence(g) {
if e > result { result = e }
}
return result
}
func find<T : Equatable>(array : T[], value : T) -> Int {
var idx = 0
for elt in array {
if elt == value { return idx }
++idx
// Returns the first index where value appears in domain or nil if
// domain doesn't contain the value. O(countElements(domain))
func find<
C: Collection where C.GeneratorType.Element : Equatable
>(domain: C, value: C.GeneratorType.Element) -> C.IndexType? {
for i in indices(domain) {
if domain[i] == value {
return i
}
return -1
}
return nil
}
// FIXME: use generic predicated sort()
// BLOCKED: <rdar://problem/12780569> Crash in IRGen while making sort()/map() generic
func sort<T : Comparable>(array : T[]) -> T[] {
var result = array.copy()
for i in 0..result.length {
for j in i+1..result.length {
if result[j] < result[i] {
// FIXME: Use swap()
// BLOCKED: <rdar://problem/12782554> write-back properties do not work
var temp = result[i]
result[i] = result[j]
result[j] = temp
func insertionSort<
C: MutableCollection where C.IndexType: BidirectionalIndex
>(
inout elements: C,
range: Range<C.IndexType>,
inout less: (C.GeneratorType.Element, C.GeneratorType.Element)->Bool
) {
if range {
let start = range.startIndex
// Keep track of the end of the initial sequence of sorted
// elements.
var sortedEnd = start
// One element is trivially already-sorted, thus pre-increment
// Continue until the sorted elements cover the whole sequence
while (++sortedEnd != range.endIndex) {
// get the first unsorted element
var x: C.GeneratorType.Element = elements[sortedEnd]
// Look backwards for x's position in the sorted sequence,
// moving elements forward to make room.
var i = sortedEnd
do {
let predecessor: C.GeneratorType.Element = elements[i.pred()]
// if x doesn't belong before y, we've found its position
if !less(x, predecessor) {
break
}
// Move y forward
elements[i] = predecessor
}
while --i != start
if i != sortedEnd {
// Plop x into position
elements[i] = x
}
}
}
return result
}
// FIXME: make generic
// BLOCKED: <rdar://problem/12780569> Crash in IRGen while making sort()/map() generic
func sort(array : String[], pred : (String, String) -> Bool) -> String[] {
var result = array.copy()
for i in 0..result.length {
for j in i+1..result.length {
if pred(result[j], result[i]) {
// FIXME: Use swap()
// BLOCKED: <rdar://problem/12782554> write-back properties do not work
var temp = result[i]
result[i] = result[j]
result[j] = temp
/// Partition a non empty range into two partially sorted regions:
/// [start..idx), [idx..end)
func partition<C: MutableCollection where C.IndexType: SignedInteger>(
inout elements: C,
range: Range<C.IndexType>,
inout less: (C.GeneratorType.Element, C.GeneratorType.Element)->Bool
) -> C.IndexType {
var i = range.startIndex
var j = range.endIndex - 1
let pivot = (i + j) / 2
while i <= j {
while less(elements[i], elements[pivot]) {
i++
}
while less(elements[pivot], elements[j]) {
j--
}
if i <= j {
swap(&elements[i], &elements[j])
i++
j--
}
}
}
return result
return i
}
// FIXME: make generic
// BLOCKED: <rdar://problem/12780569> Crash in IRGen while making sort()/map() generic
func sort(array : (key: String, value: Int)[],
pred : ((key: String, value: Int), (key: String, value: Int)) -> Bool)
-> (key: String, value: Int)[] {
var result = array.copy()
for i in 0..result.length {
for j in i+1..result.length {
if pred(result[j], result[i]) {
// FIXME: Use swap()
// BLOCKED: <rdar://problem/12782554> write-back properties do not work
var temp = result[i]
result[i] = result[j]
result[j] = temp
}
}
}
return result
func quickSort<C: MutableCollection where C.IndexType: SignedInteger>(
inout elements: C,
range: Range<C.IndexType>,
less: (C.GeneratorType.Element, C.GeneratorType.Element)->Bool
) {
var comp = less
_quickSort(&elements, range, &comp)
}
// FIXME: map() should support returning an array of a different type:
// func map<U>(f : (T) -> U) -> U[] {
func map<T>(array : T[], fn : (T) -> T) -> T[] {
var result = new T[array.length]
for i in 0..array.length {
result[i] = fn(array[i])
func _quickSort<C: MutableCollection where C.IndexType: SignedInteger>(
inout elements: C,
range: Range<C.IndexType>,
inout less: (C.GeneratorType.Element, C.GeneratorType.Element)->Bool
) {
// Insertion sort is better at handling smaller regions.
let cnt = count(range)
if cnt < 16 {
insertionSort(&elements, range, &less)
return
}
return result
// Partition and sort.
let part_idx : C.IndexType = partition(&elements, range, &less)
_quickSort(&elements, range.startIndex...part_idx, &less);
_quickSort(&elements, part_idx...range.endIndex, &less);
}
func swap<T>(a : [byref] T, b : [byref] T) {
var c = a
a = b
b = c
struct Less<T: Comparable> {
static func compare(x: T, _ y: T) -> Bool {
return x < y
}
}
// FIXME -- BLOCKED: <rdar://problem/12695123> Crash while trying to make min/max generic
//func min<T : Comparable>(x : T, y : T, rest : T...) -> T {
func min(x : Int, y : Int, rest : Int...) -> Int {
func sort<T>(var array: T[], pred: (T, T) -> Bool) -> T[] {
quickSort(&array, 0...array.count, pred)
return array
}
/// The functions below are a copy of the functions above except that
/// they don't accept a predicate and they are hardcoded to use the less-than
/// comparator.
func sort<T : Comparable>(var array: T[]) -> T[] {
quickSort(&array, 0...array.count)
return array
}
func insertionSort<
C: MutableCollection where C.IndexType: BidirectionalIndex,
C.GeneratorType.Element: Comparable>(
inout elements: C,
range: Range<C.IndexType>) {
if range {
let start = range.startIndex
// Keep track of the end of the initial sequence of sorted
// elements.
var sortedEnd = start
// One element is trivially already-sorted, thus pre-increment
// Continue until the sorted elements cover the whole sequence
while (++sortedEnd != range.endIndex) {
// get the first unsorted element
var x: C.GeneratorType.Element = elements[sortedEnd]
// Look backwards for x's position in the sorted sequence,
// moving elements forward to make room.
var i = sortedEnd
do {
let predecessor: C.GeneratorType.Element = elements[i.pred()]
// if x doesn't belong before y, we've found its position
if !Less.compare(x, predecessor) {
break
}
// Move y forward
elements[i] = predecessor
}
while --i != start
if i != sortedEnd {
// Plop x into position
elements[i] = x
}
}
}
}
/// Partition a non empty range into two partially sorted regions:
/// [start..idx), [idx..end)
func partition<C: MutableCollection where C.GeneratorType.Element: Comparable, C.IndexType: SignedInteger>(
inout elements: C,
range: Range<C.IndexType>) -> C.IndexType {
var i = range.startIndex
var j = range.endIndex - 1
let pivot = (i + j) / 2
while i <= j {
while Less.compare(elements[i], elements[pivot]) {
i++
}
while Less.compare(elements[pivot], elements[j]) {
j--
}
if i <= j {
swap(&elements[i], &elements[j])
i++
j--
}
}
return i
}
func quickSort<C: MutableCollection where C.GeneratorType.Element: Comparable, C.IndexType: SignedInteger>(
inout elements: C,
range: Range<C.IndexType>) {
_quickSort(&elements, range)
}
func _quickSort<C: MutableCollection where C.GeneratorType.Element: Comparable, C.IndexType: SignedInteger>(
inout elements: C, range: Range<C.IndexType>) {
// Insertion sort is better at handling smaller regions.
let cnt = count(range)
if cnt < 16 {
insertionSort(&elements, range)
return
}
// Partition and sort.
let part_idx : C.IndexType = partition(&elements, range)
_quickSort(&elements, range.startIndex...part_idx);
_quickSort(&elements, part_idx...range.endIndex);
}
//// End of non-predicate sort functions.
func swap<T>(inout a : T, inout b : T) {
// Semantically equivalent to (a, b) = (b, a).
// Microoptimized to avoid retain/release traffic.
let p1 = Builtin.addressof(&a)
let p2 = Builtin.addressof(&b)
// Take from P1.
let tmp : T = Builtin.take(p1)
// Transfer P2 into P1.
Builtin.initialize(Builtin.take(p2) as T, p1)
// Initialize P2.
Builtin.initialize(tmp, p2)
}
func min<T : Comparable>(x: T, y: T, rest: T...) -> T {
var r = x
if y < x {
r = y
@@ -121,22 +288,7 @@ func min(x : Int, y : Int, rest : Int...) -> Int {
return r
}
func min(x : Double, y : Double, rest : Double...) -> Double {
var r = x
if y < x {
r = y
}
for z in rest {
if z < r {
r = z
}
}
return r
}
// FIXME -- BLOCKED: <rdar://problem/12695123> Crash while trying to make min/max generic
//func max<T : Comparable>(x : T, y : T, rest : T...) -> T {
func max(x : Int, y : Int, rest : Int...) -> Int {
func max<T : Comparable>(x: T, y: T, rest: T...) -> T {
var r = y
if y < x {
r = x
@@ -149,80 +301,237 @@ func max(x : Int, y : Int, rest : Int...) -> Int {
return r
}
func max(x : Double, y : Double, rest : Double...) -> Double {
var r = y
if y < x {
r = x
}
for z in rest {
if z >= r {
r = z
}
}
return r
}
func split<
Seq: Sliceable,
IsSeparator: Predicate
requires IsSeparator.Arguments == Seq.Element
>(seq: Seq,
isSeparator: IsSeparator,
maxSplit: Int = Int.max(),
func split<Seq: Sliceable, R:LogicValue>(
seq: Seq,
isSeparator: (Seq.GeneratorType.Element)->R,
maxSplit: Int = Int.max,
allowEmptySlices: Bool = false
) -> Seq[] {
) -> Seq.SliceType[] {
var result = Vector<Seq>()
var result = Array<Seq.SliceType>()
var startIndex = allowEmptySlices ? Some(seq.begin()) : None
// FIXME: could be simplified pending <rdar://problem/15032945>
// (ternary operator not resolving some/none)
var startIndex: Optional<Seq.IndexType>
= allowEmptySlices ? .Some(seq.startIndex) : .None
var splits = 0
for j in indices(seq) {
if apply(isSeparator, seq.__getitem__(j)) {
if isSeparator(seq[j]) {
if startIndex {
var i = startIndex.get()
result.append(seq.__slice__(i, j))
startIndex = Some(j.succ())
var i = startIndex!
result.append(seq[i...j])
startIndex = .Some(j.succ())
if ++splits >= maxSplit {
break
}
if !allowEmptySlices {
startIndex = None
startIndex = .None
}
}
}
else {
if !startIndex {
startIndex = Some(j)
startIndex = .Some(j)
}
}
}
for i in startIndex { // destructuring bind
result.append(seq.__slice__(i, seq.end()))
switch startIndex {
case .Some(var i):
result.append(seq[i...seq.endIndex])
default:
()
}
return result.takeArray()
return result
}
// FIXME: Until <rdar://problem/13985164> is fixed, we can't build
// generic algorithms that work on Enumerables, so we're operating on
// Enumerators here.
/// \brief Return true iff the elements of e1 are equal to the initial
/// elements of e2
func startsWith<
E0: Enumerator, E1: Enumerator
requires
E0.Element == E1.Element,
E0.Element : Equatable
>(e0: E0, e1: E1) -> Bool
S0: Sequence, S1: Sequence
where
S0.GeneratorType.Element == S1.GeneratorType.Element,
S0.GeneratorType.Element : Equatable
>(s0: S0, s1: S1) -> Bool
{
while !e0.isEmpty() {
if e1.isEmpty() { return true }
if e0.next() != e1.next() {
var g1 = s1.generate()
for e0 in s0 {
var e1 = g1.next()
if !e1 { return true }
if e0 != e1! {
return false
}
}
return e1.isEmpty()
return g1.next() ? false : true
}
struct EnumerateGenerator<Base: Generator> : Generator, Sequence {
typealias Element = (index: Int, element: Base.Element)
var base: Base
var count: Int
init(_ base: Base) {
self.base = base
count = 0
}
mutating func next() -> Element? {
var b = base.next()
if !b { return .None }
return .Some((index: count++, element: b!))
}
// Every Generator is also a single-pass Sequence
typealias GeneratorType = EnumerateGenerator<Base>
func generate() -> GeneratorType {
return self
}
}
func enumerate<Seq : Sequence>(
seq: Seq
) -> EnumerateGenerator<Seq.GeneratorType> {
return EnumerateGenerator(seq.generate())
}
/// Return true iff `a1` and `a2` contain the same elements.
func equal<
S1 : Sequence, S2 : Sequence
where
S1.GeneratorType.Element == S2.GeneratorType.Element,
S1.GeneratorType.Element : Equatable
>(a1: S1, a2: S2) -> Bool
{
var g1 = a1.generate()
var g2 = a2.generate()
while true {
var e1 = g1.next()
var e2 = g2.next()
if e1 && e2 {
if e1! != e2! {
return false
}
}
else {
return !e1 == !e2
}
}
}
/// Return true iff `a1` and `a2` contain the same elements, using
/// `pred` as equality `==` comparison.
func equal<
S1 : Sequence, S2 : Sequence
where
S1.GeneratorType.Element == S2.GeneratorType.Element
>(a1: S1, a2: S2,
pred: (S1.GeneratorType.Element, S1.GeneratorType.Element) -> Bool) -> Bool
{
var g1 = a1.generate()
var g2 = a2.generate()
while true {
var e1 = g1.next()
var e2 = g2.next()
if e1 && e2 {
if !pred(e1!, e2!) {
return false
}
}
else {
return !e1 == !e2
}
}
}
/// Return true iff a1 precedes a2 in a lexicographical ("dictionary")
/// ordering, using "<" as the comparison between elements.
func lexicographicalCompare<
S1 : Sequence, S2 : Sequence
where
S1.GeneratorType.Element == S2.GeneratorType.Element,
S1.GeneratorType.Element : Comparable>(
a1: S1, a2: S2) -> Bool {
var g1 = a1.generate()
var g2 = a2.generate()
while true {
var e1_ = g1.next()
var e2_ = g2.next()
if let e1 = e1_ {
if let e2 = e2_ {
if e1 < e2 {
return true
}
if e2 < e1 {
return false
}
continue // equivalent
}
return false
}
return e2_.getLogicValue()
}
}
/// Return true iff a1 precedes a2 in a lexicographical ("dictionary")
/// ordering, using less as the comparison between elements.
func lexicographicalCompare<
S1 : Sequence, S2 : Sequence
where
S1.GeneratorType.Element == S2.GeneratorType.Element
>(
a1: S1, a2: S2,
less: (S1.GeneratorType.Element,S1.GeneratorType.Element)->Bool
) -> Bool {
var g1 = a1.generate()
var g2 = a2.generate()
while true {
var e1_ = g1.next()
var e2_ = g2.next()
if let e1 = e1_ {
if let e2 = e2_ {
if less(e1, e2) {
return true
}
if less(e2, e1) {
return false
}
continue // equivalent
}
return false
}
return e2_.getLogicValue()
}
}
/// \brief return true iff an element in seq satisfies predicate
func contains<
S: Sequence, L: LogicValue
>(seq: S, predicate: (S.GeneratorType.Element)->L) -> Bool {
for a in seq {
if predicate(a) {
return true
}
}
return false
}
/// \brief return true iff x is in seq
func contains<
S: Sequence where S.GeneratorType.Element: Equatable
>(seq: S, x: S.GeneratorType.Element) -> Bool {
return contains(seq, { $0 == x })
}
func reduce<S: Sequence, U>(
sequence: S, initial: U, combine: (U, S.GeneratorType.Element)->U
) -> U {
var result = initial
for element in sequence {
result = combine(result, element)
}
return result
}

View File

@@ -15,8 +15,7 @@
//
//===----------------------------------------------------------------------===//
struct ArrayBody {
struct _ArrayBody {
init(count: Int, capacity: Int, elementTypeIsBridgedVerbatim: Bool = false) {
assert(count >= 0)
assert(capacity >= 0)

View File

@@ -1,4 +1,4 @@
//===--- ArrayBuffer.swift - Dynamically-allocated storage for Swift Array ---===//
//===--- ArrayBuffer.swift - Dynamic storage for Swift Array --------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -15,22 +15,325 @@
//
//===----------------------------------------------------------------------===//
// A HeapBuffer whose storage contains zero or more consecutive Elements
class ArrayBufferStorage<T>
: HeapBufferStorage<CountAndCapacity, T> {
import SwiftShims
destructor() {
let p = HeapBuffer(self).elementStorage
for i in 0...HeapBuffer(self).value.count {
(p + i).destroy()
enum _ArrayCastDirection { case Up, Down }
@final
class IndirectArrayBuffer {
init<T>(_ buffer: NativeArrayBuffer<T>, _ mutable: Bool) {
self.buffer = buffer.storage
self.isMutable = mutable
self.isCocoa = false
}
init(_ x: CocoaArray) {
self.buffer = x
self.isMutable = false
self.isCocoa = true
}
init(castFrom: IndirectArrayBuffer, direction: _ArrayCastDirection) {
self.buffer = castFrom.buffer
self.isMutable = direction == .Down
self.isCocoa = castFrom.isCocoa
}
// When this buffer has immutable storage and it is modified, the
// storage is replaced with mutable storage.
func replaceStorage<T>(buffer: NativeArrayBuffer<T>) {
self.buffer = buffer.storage
self.isMutable = true
self.isCocoa = false
}
var buffer: AnyObject?
var isMutable: Bool
var isCocoa: Bool
func getNative<T>() -> NativeArrayBuffer<T> {
assert(!isCocoa)
return NativeArrayBuffer(
buffer ? reinterpretCast(buffer) as NativeArrayStorage<T> : nil)
}
func getCocoa() -> CocoaArray {
assert(isCocoa)
return reinterpretCast(buffer!) as CocoaArray
}
}
func arrayBuffer<T>(_:T.metatype, count: Int, capacity: Int) -> HeapBuffer<CountAndCapacity, T> {
return HeapBuffer(
ArrayBufferStorage<T>,
CountAndCapacity(count: count, capacity: capacity),
capacity
struct ArrayBuffer<T> : ArrayBufferType {
var storage: Builtin.NativeObject?
var indirect: IndirectArrayBuffer {
assert(_isClassOrObjCExistential(T.self))
return Builtin.castFromNativeObject(storage!)
}
typealias Element = T
/// create an empty buffer
init() {
storage = !_isClassOrObjCExistential(T.self)
? nil : Builtin.castToNativeObject(
IndirectArrayBuffer(NativeArrayBuffer<T>(), false))
}
init(_ cocoa: CocoaArray) {
assert(_isClassOrObjCExistential(T.self))
storage = Builtin.castToNativeObject(IndirectArrayBuffer(cocoa))
}
/// An ArrayBuffer<T> containing the same elements.
/// Requires: the elements actually have dynamic type T.
init<U>(castFrom: ArrayBuffer<U>, direction: _ArrayCastDirection) {
assert(_canBeClass(T.self))
assert(_canBeClass(U.self))
storage = Builtin.castToNativeObject(
IndirectArrayBuffer(castFrom: castFrom.indirect, direction: direction))
}
var dynamicElementType: Any.Type {
return _isNative ? _native.dynamicElementType : AnyObject.self
}
}
extension ArrayBuffer {
/// Adopt the storage of x
init(_ buffer: NativeBuffer) {
if !_isClassOrObjCExistential(T.self) {
self.storage
= buffer.storage ? Builtin.castToNativeObject(buffer.storage!) : nil
}
else {
self.storage = Builtin.castToNativeObject(
IndirectArrayBuffer(buffer, true))
}
}
/// Return true iff this buffer's storage is uniquely-referenced.
mutating func isUniquelyReferenced() -> Bool {
return Swift.isUniquelyReferenced(&storage)
}
/// Convert to an NSArray.
/// Precondition: isBridgedToObjectiveC(Element.self)
/// O(1) if the element type is bridged verbatim, O(N) otherwise
func asCocoaArray() -> CocoaArray {
assert(
isBridgedToObjectiveC(T.self),
"Array element type is not bridged to ObjectiveC")
return _fastPath(_isNative) ? _native.asCocoaArray() : _nonNative!
}
var _hasMutableBuffer: Bool {
if !_isClassOrObjCExistential(T.self) {
return true
}
return indirect.isMutable && Swift.isUniquelyReferenced(&indirect.buffer)
}
/// If this buffer is backed by a uniquely-referenced mutable
/// NativeArrayBuffer that can be grown in-place to allow the self
/// buffer store minimumCapacity elements, returns that buffer.
/// Otherwise, returns nil
mutating func requestUniqueMutableBuffer(minimumCapacity: Int)
-> NativeBuffer?
{
if _fastPath(Swift.isUniquelyReferenced(&storage) && _hasMutableBuffer) {
let b = _native
return b.capacity >= minimumCapacity ? b : nil
}
return nil
}
/// If this buffer is backed by a NativeArrayBuffer, return it.
/// Otherwise, return nil. Note: the result's elementStorage may
/// not match ours, if we are a SliceBuffer.
func requestNativeBuffer() -> NativeBuffer? {
return self._native
}
/// Copy the given subRange of this buffer into uninitialized memory
/// starting at target. Return a pointer past-the-end of the
/// just-initialized memory.
func _uninitializedCopy(
subRange: Range<Int>, target: UnsafePointer<T>
) -> UnsafePointer<T> {
if _fastPath(_isNative) {
return _native._uninitializedCopy(subRange, target: target)
}
let nonNative = _nonNative!
let nsSubRange = SwiftShims._SwiftNSRange(
location:subRange.startIndex,
length: subRange.endIndex - subRange.startIndex)
let buffer = reinterpretCast(target) as UnsafePointer<AnyObject>
// Copies the references out of the NSArray without retaining them
nonNative.getObjects(buffer, range: nsSubRange)
// Make another pass to retain the copied objects
var result = target
for i in subRange {
result.initialize(result.get())
++result
}
return result
}
/// Return a SliceBuffer containing the given subRange of values
/// from this buffer.
subscript(subRange: Range<Int>) -> SliceBuffer<T> {
if _fastPath(_isNative) {
return _native[subRange]
}
let nonNative = self._nonNative
let subRangeCount = countElements(subRange)
// Look for contiguous storage in the NSArray
let cocoa = CocoaArrayWrapper(nonNative!)
let start = cocoa.contiguousStorage(subRange)
if start != nil {
return SliceBuffer(owner: nonNative, start: UnsafePointer(start),
count: subRangeCount, hasNativeBuffer: false)
}
// No contiguous storage found; we must allocate
var result = NativeArrayBuffer<T>(count: subRangeCount, minimumCapacity: 0)
// Tell Cocoa to copy the objects into our storage
cocoa.buffer.getObjects(
UnsafePointer(result.elementStorage),
range: _SwiftNSRange(location: subRange.startIndex, length: subRangeCount)
)
return SliceBuffer(result)
}
/// If the elements are stored contiguously, a pointer to the first
/// element. Otherwise, nil.
var elementStorage: UnsafePointer<T> {
if (_fastPath(_isNative)) {
return _native.elementStorage
}
return nil
}
/// How many elements the buffer stores
var count: Int {
get {
return _fastPath(_isNative) ? _native.count : _nonNative!.count
}
set {
// Allow zero here for the case where elements have been moved
// out of the buffer during reallocation
assert(
newValue == 0 || newValue >= count,
"We don't yet know how to shrink an array")
assert(_isNative, "attempting to update count of Cocoa array")
_native.count = newValue
}
}
/// How many elements the buffer can store without reallocation
var capacity: Int {
return _fastPath(_isNative) ? _native.capacity : _nonNative!.count
}
/// Get/set the value of the ith element
subscript(i: Int) -> T {
get {
if _fastPath(_isNative) {
return _native[i]
}
return reinterpretCast(_nonNative!.objectAtIndex(i))
}
nonmutating set {
if _fastPath(_hasMutableBuffer) {
_native[i] = newValue
}
else {
indirect.replaceStorage(_copyCollectionToNativeArrayBuffer(self))
_native[i] = newValue
}
}
}
/// An object that keeps the elements stored in this buffer alive
var owner: AnyObject? {
return _fastPath(_isNative) ? _native.storage : _nonNative!
}
/// A value that identifies first mutable element, if any. Two
/// arrays compare === iff they are both empty or if their buffers
/// have the same identity and count.
var identity: Word {
let p = elementStorage
return p != nil ? reinterpretCast(p) : reinterpretCast(owner)
}
//===--- Collection conformance -----------------------------------------===//
var startIndex: Int {
return 0
}
var endIndex: Int {
return count
}
func generate() -> IndexingGenerator<ArrayBuffer> {
return IndexingGenerator(self)
}
//===--- private --------------------------------------------------------===//
typealias Storage = NativeArrayStorage<T>
typealias NativeBuffer = NativeArrayBuffer<T>
func _invariantCheck() -> Bool {
return true
}
var _isNative: Bool {
if !_isClassOrObjCExistential(T.self) {
return true
}
else {
return !indirect.isCocoa
}
}
/// Our native representation, if any. If there's no native
/// representation, the result is an empty buffer.
var _native: NativeBuffer {
if !_isClassOrObjCExistential(T.self) {
return NativeBuffer(
reinterpretCast(storage) as NativeArrayStorage<T>?)
}
else {
let i = indirect
return _fastPath(!i.isCocoa) ? i.getNative() : NativeBuffer()
}
}
var _nonNative: CocoaArray? {
if !_isClassOrObjCExistential(T.self) {
return nil
}
else {
let i = indirect
return _fastPath(!i.isCocoa) ? nil : i.getCocoa()
}
}
}

View File

@@ -10,10 +10,7 @@
//
//===----------------------------------------------------------------------===//
/// Serves as the buffer for an ArrayType. An ArrayBufferType does
/// not impose value semantics on its elements, and whether its
/// elements are actually being managed by copy-on-write (COW) is, in
/// principle, unknown to the buffer.
/// The underlying buffer for an ArrayType conforms to ArrayBufferType
protocol ArrayBufferType : MutableCollection {
/// The type of elements stored in the buffer
typealias Element
@@ -22,7 +19,7 @@ protocol ArrayBufferType : MutableCollection {
init()
/// Adopt the storage of x
init(x: NativeArrayBuffer<Element>)
init(_ buffer: NativeArrayBuffer<Element>)
/// Copy the given subRange of this buffer into uninitialized memory
/// starting at target. Return a pointer past-the-end of the
@@ -30,26 +27,30 @@ protocol ArrayBufferType : MutableCollection {
func _uninitializedCopy(subRange: Range<Int>, target: UnsafePointer<Element>)
-> UnsafePointer<Element>
/// Convert to an NSArray in O(1).
/// Convert to an NSArray.
/// Precondition: isBridgedToObjectiveC(Element.self)
/// O(1) if the element type is bridged verbatim, O(N) otherwise
func asCocoaArray() -> CocoaArray
/// Convert to a NativeArrayBuffer storing the same elements.
/// managedByCopyOnWrite is destined to be removed soon, but it
/// indicates whether the buffer is to be marked for copying in
/// copyWithZone.
func toNativeBuffer(managedByCopyOnWrite: Bool)
-> NativeArrayBuffer<Element>
/// Get/set the index'th element
subscript(index: Int) -> Element { get nonmutating set}
/// Return true iff this buffer's storage is uniquely-referenced.
/// NOTE: this does not mean the buffer is mutable. Other factors
/// may need to be considered, such as whether the buffer could be
/// some immutable Cocoa container.
mutating func isUniquelyReferenced() -> Bool
/// If this buffer is backed by a uniquely-referenced mutable
/// NativeArrayBuffer that can be grown in-place to allow the self
/// buffer store minimumCapacity elements, returns that buffer.
/// Otherwise, returns nil. Note: the result's elementStorage may
/// not match ours, if we are a SliceBuffer.
///
/// Note: this function must remain mutating; otherwise the buffer
/// may acquire spurious extra references, which will cause
/// unnecessary reallocation.
mutating func requestUniqueMutableBuffer(minimumCapacity: Int)
-> NativeArrayBuffer<Element>?
/// Returns true iff this buffer is mutable. NOTE: a true result
/// does not mean the buffer is uniquely-referenced.
func isMutable() -> Bool
/// If this buffer is backed by a NativeArrayBuffer, return it.
/// Otherwise, return nil. Note: the result's elementStorage may
/// not match ours, if we are a SliceBuffer.
func requestNativeBuffer() -> NativeArrayBuffer<Element>?
/// Return a SliceBuffer containing the given subRange of values
/// from this buffer.
@@ -60,4 +61,16 @@ protocol ArrayBufferType : MutableCollection {
/// How many elements the buffer can store without reallocation
var capacity: Int {get}
/// An object that keeps the elements stored in this buffer alive
var owner: AnyObject? {get}
/// If the elements are stored contiguously, a pointer to the first
/// element. Otherwise, nil.
var elementStorage: UnsafePointer<Element> {get}
/// A value that identifies first mutable element, if any. Two
/// arrays compare === iff they are both empty, or if their buffers
/// have the same identity and count.
var identity: Word {get}
}

View File

@@ -11,46 +11,107 @@
//===----------------------------------------------------------------------===//
protocol ArrayType
// FIXME: must start with Collection; see <rdar://problem/16465340>
: Collection,
_ArrayType,
MutableCollection,
Sliceable,
ArrayLiteralConvertible,
ConditionallyBridgedToObjectiveC
: _ArrayType,
Collection,
MutableSliceable,
ArrayLiteralConvertible
{
//===--- public interface -----------------------------------------------===//
/// Construct an empty Array
init()
/// Construct an array of count elements, each initialized to value
init(count: Int, value: Self.GeneratorType.Element)
/// How many elements the Array stores
var count: Int {get}
/// How many elements the Array can store without reallocation
var capacity: Int {get}
mutating func reserve(n: Int)
mutating func append(element: Self.GeneratorType.Element)
/// true if and only if the Array is empty
var isEmpty: Bool {get}
/// An object that guarantees the lifetime of this array's elements
var owner: AnyObject? {get}
/// If the elements are stored contiguously, a pointer to the first
/// element. Otherwise, nil.
var elementStorage: UnsafePointer<Element> {get}
subscript(index: Int) -> Self.GeneratorType.Element {get nonmutating set}
//===--- basic mutations ------------------------------------------------===//
/// Reserve enough space to store newCapacity elements in O(N). If
/// newCapacity is less than count, has no effect. PostCondition:
/// the array has mutable contiguous storage
mutating func reserve(newCapacity: Int)
/// Append newElement to the Array in O(1) (amortized)
mutating func append(newElement: Self.GeneratorType.Element)
/// Remove an element from the end of the Array in O(1). Returns:
/// the removed element. Requires: count > 0
mutating func popLast() -> Self.GeneratorType.Element
/// Insert an element at the given index in O(N). Requires: atIndex
/// <= count
mutating func insert(atIndex: Int, newElement: Self.GeneratorType.Element)
/// Remove the element at the given index. Returns: the removed
/// element. Worst case complexity: O(N). Requires: count > index
mutating func removeAt(index: Int) -> Self.GeneratorType.Element
/// Erase all the elements and release the storage
mutating func clear()
/// Erase all the elements. If keepStorage is true, capacity will not change
mutating func clear(keepStorage: Bool)
//===--- algorithms -----------------------------------------------------===//
func reduce<U>(initial: U, combine: (U, Self.GeneratorType.Element) -> U) -> U
mutating func sort(
isOrderedBefore: (
Self.GeneratorType.Element, Self.GeneratorType.Element
) -> Bool
)
//===--- implementation detail -----------------------------------------===//
typealias Buffer : ArrayBufferType
init(_: Buffer)
mutating func _adopt(
newBuffer: NativeArrayBuffer<Self.GeneratorType.Element>)
// Returns true iff Self can allow its buffer to be directly
// mutated. *Must* remain a mutating function and not a get-only
// property if we are to have a hope of accurate uniqueness checks
mutating func _hasMutableBuffer() -> Bool
// Copy elements from the given subRange into the range starting at
// target, returning a pointer past-the-end of the target range
func _uninitializedCopy(
subRange: Range<Self.IndexType>,
target: UnsafePointer<Self.GeneratorType.Element>
) -> UnsafePointer<Self.GeneratorType.Element>
// Update this Array's idea of its count. Does NOT construct or
// destroy elements to ensure that count is accurate.
mutating func _updateCount(newCount: Int)
init(_ buffer: Buffer)
var buffer: Buffer {get set}
}
struct _ArrayTypeMirror<T : ArrayType> : Mirror {
let _value : T
init(_ v : T) { _value = v }
var value: Any { return (_value as Any) }
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return nil }
var count: Int { return _value.count }
subscript(i: Int) -> (String, Mirror) {
if (i >= 0) && (i < count) {
return ("[\(i)]",reflect(_value[i]))
}
fatal("don't ask")
}
var summary: String {
if count == 1 { return "1 element" }
return "\(count) elements"
}
var quickLookObject: QuickLookObject? { return nil }
var disposition: MirrorDisposition { return .IndexContainer }
}

View File

@@ -24,15 +24,9 @@
//
//===----------------------------------------------------------------------===//
% for Self in ['NativeArray', 'Slice', 'NewArray']:
struct ${Self}<T> {
% for Self in ['NativeArray', 'Slice', 'Array']:
struct ${Self}<T> : MutableCollection, Sliceable {
typealias Element = T
typealias Buffer = ${'Array' if Self.startswith('New') else Self}Buffer<T>
var buffer: Buffer
}
extension ${Self} : Collection {
var startIndex: Int {
return 0
}
@@ -41,32 +35,636 @@ extension ${Self} : Collection {
return buffer.count
}
subscript(i: Int) -> Element {
subscript(index: Int) -> Element {
get {
return buffer[i]
assert(index < count, "Array index out of range")
return buffer[index]
}
nonmutating set {
assert(index < count, "Array index out of range")
buffer[index] = newValue
}
}
func generate() -> IndexingGenerator<${Self}> {
return IndexingGenerator(self)
}
typealias SliceType = Slice<T>
subscript(subRange: Range<Int>) -> SliceType {
get {
return Slice(buffer[subRange])
}
set {
if self[subRange] !== newValue {
replace(&self, subRange, newValue)
}
}
}
//===--- private --------------------------------------------------------===//
typealias Buffer = ${'Array' if Self.startswith('New') else Self}Buffer<T>
init(_ buffer: Buffer) {
self.buffer = buffer
}
var buffer: Buffer
}
extension ${Self} /*: _ArrayType*/ {
func toNativeBuffer(managedByCopyOnWrite: Bool)
-> NativeArrayBuffer<Element> {
return buffer.toNativeBuffer(managedByCopyOnWrite)
extension ${Self} : ArrayLiteralConvertible {
static func convertFromArrayLiteral(elements: Element...) -> ${Self} {
return ${Self}(_extractOrCopyToNativeArrayBuffer(elements.buffer))
}
}
extension ${Self} {
func asCocoaArray() -> CocoaArray {
return buffer.asCocoaArray()
}
}
extension ${Self} : ArrayType {
/// Construct an empty ${Self}
init() {
buffer = Buffer()
}
init<S: Sequence where S.GeneratorType.Element == Buffer.Element>(_ s: S) {
self = ${Self}(Buffer(s~>_copyToNativeArrayBuffer()))
}
/// Construct an array of count elements, each initialized to value
init(count: Int, value: T) {
assert(count >= 0)
buffer = Buffer()
reserve(count)
var p = buffer.elementStorage
for _ in 0...count {
p++.initialize(value)
}
buffer.count = count
}
/// How many elements the ${Self} stores
var count: Int {
get {
return buffer.count
}
/// How many elements the ${Self} can store without reallocation
var capacity: Int {
return buffer.capacity
}
/// true if and only if the ${Self} is empty
var isEmpty: Bool {
return count == 0
}
/// An object that guarantees the lifetime of this array's elements
var owner: AnyObject? {
return buffer.owner
}
/// If the elements are stored contiguously, a pointer to the first
/// element. Otherwise, nil.
var elementStorage: UnsafePointer<Element> {
return buffer.elementStorage
}
//===--- basic mutations ------------------------------------------------===//
/// Returns a new array that does not share the underlying storage with this
/// array.
/// Complexity: O(N)
func copy() -> ${Self} {
var result = self
result.reserve(0)
return result
}
/// Ensure the uniqueness of the array.
/// Complexity: O(N)
mutating func unshare() {
reserve(0)
}
/// Ensure the array has enough mutable contiguous storage to store
/// newCapacity elements in. Note: does not affect count.
/// Complexity: O(N)
mutating func reserve(newCapacity: Int) {
if !buffer.requestUniqueMutableBuffer(newCapacity) {
var newBuffer = NativeArrayBuffer<T>(count: count, minimumCapacity: newCapacity)
buffer._uninitializedCopy(0...count, target: newBuffer.elementStorage)
buffer = Buffer(newBuffer)
}
assert(capacity >= newCapacity)
}
/// Append newElement to the ${Self} in O(1) (amortized)
mutating func append(newElement: T) {
_arrayAppend(&buffer, newElement)
}
/// Remove an element from the end of the ${Self} in O(1).
/// Requires: count > 0
mutating func popLast() -> T {
assert(count > 0, "can't pop from an empty ${Self}")
let c = count
let result = self[c - 1]
replace(&self, (c - 1)...c, EmptyCollection())
return result
}
/// Insert an element at the given index in O(N). Requires: atIndex
/// <= count
mutating func insert(atIndex: Int, newElement: T) {
replace(&self, atIndex...atIndex, CollectionOfOne(newElement))
}
/// Remove the element at the given index. Worst case complexity:
/// O(N). Requires: index < count
mutating func removeAt(index: Int) -> T {
let result = self[index]
replace(&self, index...(index + 1), EmptyCollection())
return result
}
/// Erase all the elements and release the storage
mutating func clear() {
buffer = Buffer()
}
/// Erase all the elements. If keepStorage is true, capacity will not change
mutating func clear(keepStorage: Bool) {
if !keepStorage {
clear()
}
else {
replace(&self, indices(self), EmptyCollection())
}
}
//===--- algorithms -----------------------------------------------------===//
func reduce<U>(initial: U, combine: (U, T)->U) -> U {
return Swift.reduce(self, initial, combine)
}
mutating func sort(isOrderedBefore: (T, T)->Bool) {
quickSort(&self, indices(self), isOrderedBefore)
}
func map<U>(transform: (T)->U) -> ${Self}<U> {
var result = ${Self}<U>()
let count = self.count
result.reserve(count)
var p = result.buffer.elementStorage
for i in 0...count {
p++.initialize( transform(self[i]) )
}
result.buffer.count = count
return result
}
}
extension ${Self} : Reflectable {
func getMirror() -> Mirror {
return _ArrayTypeMirror(self)
}
}
extension ${Self} {
@transparent
func _cPointerArgs() -> (AnyObject?, Builtin.RawPointer) {
let p = elementStorage
if _fastPath(p != nil || count == 0) {
return (owner, p.value)
}
let n = _extractOrCopyToNativeArrayBuffer(self.buffer)
return (n.owner, n.elementStorage.value)
}
// Conversion to C pointer arguments
@transparent @conversion
func __conversion() -> CConstPointer<T> {
return CConstPointer(_cPointerArgs())
}
@transparent @conversion
func __conversion() -> CConstVoidPointer {
return CConstVoidPointer(_cPointerArgs())
}
}
%if Self != 'Array': # // Array does not necessarily have contiguous storage
extension ${Self} {
func withUnsafePointerToElements<R>(body: (UnsafePointer<T>)->R) -> R {
return buffer.withUnsafePointerToElements(body)
}
}
%end
%end
extension Array {
static func convertFromHeapArray(
base: Builtin.RawPointer,
owner: Builtin.NativeObject,
count: Builtin.Word
) -> Array {
let elements = UnsafeArray(
start: reinterpretCast(base) as UnsafePointer<T>,
length: reinterpretCast(count) as Int
)
let r = Array(elements)
_fixLifetime(owner)
return r
}
}
struct _InitializeMemoryFromCollection<C: Collection> : PointerFunction {
func call(rawMemory: UnsafePointer<C.GeneratorType.Element>) {
var p = rawMemory
for x in newValues {
p++.initialize(x)
}
}
init(_ newValues: C) {
self.newValues = newValues
}
var newValues: C
}
func replace<
A: ArrayType, C: Collection
where C.GeneratorType.Element == A.Buffer.Element, A.IndexType == Int
>(
inout target: A, subRange: Range<Int>, newValues: C
) {
assert(subRange.startIndex >= 0)
assert(subRange.endIndex >= subRange.startIndex)
assert(subRange.endIndex <= target.endIndex)
let oldCount = target.count
let eraseCount = countElements(subRange)
let insertCount = numericCast(countElements(newValues)) as Int
var newBuffer = _demandUniqueMutableBuffer(
&target.buffer, oldCount + insertCount - eraseCount)
if _fastPath(!newBuffer) {
let growth = insertCount - eraseCount
let elements = target.buffer.elementStorage
assert(elements != nil)
let oldTailIndex = subRange.endIndex
let oldTailStart = elements + oldTailIndex
let newTailIndex = oldTailIndex + growth
let newTailStart = oldTailStart + growth
let tailCount = oldCount - subRange.endIndex
if growth > 0 {
// Slide the tail part of the buffer forwards, in reverse order
// so as not to self-clobber.
newTailStart.moveInitializeBackwardFrom(oldTailStart, count: tailCount)
// Assign over the original subRange
var i = newValues.startIndex
for j in subRange {
elements[j] = newValues[i++]
}
// Initialize the hole left by sliding the tail forward
for j in oldTailIndex...newTailIndex {
(elements + j).initialize(newValues[i++])
}
}
else { // We're not growing the buffer
// Assign all the new elements into the start of the subRange
var i = subRange.startIndex
for j in indices(newValues) {
elements[i++] = newValues[j]
}
// If the size didn't change, we're done.
if growth == 0 {
return
}
// Move the tail backward to cover the shrinkage.
let shrinkage = -growth
if tailCount > shrinkage { // If the tail length exceeds the shrinkage
// Assign over the rest of the replaced range with the first
// part of the tail.
newTailStart.moveAssignFrom(oldTailStart, count: shrinkage)
// slide the rest of the tail back
oldTailStart.moveInitializeFrom(
oldTailStart + shrinkage, count: tailCount - shrinkage)
}
else { // tail fits within erased elements
// Assign over the start of the replaced range with the tail
newTailStart.moveAssignFrom(oldTailStart, count: tailCount)
// destroy elements remaining after the tail in subRange
(newTailStart + tailCount).destroy(shrinkage - tailCount)
}
}
}
else {
_arrayOutOfPlaceUpdate(
&target.buffer, &newBuffer,
subRange.startIndex, insertCount,
_InitializeMemoryFromCollection(newValues)
)
}
}
@assignment
func += <
A: ArrayType, S: Sequence
where S.GeneratorType.Element == A.Buffer.Element
>(inout lhs: A, rhs: S) {
_arrayAppendSequence(&lhs.buffer, rhs)
}
@assignment
func += <
A: ArrayType, C: Collection
where C.GeneratorType.Element == A.Buffer.Element
>(inout lhs: A, rhs: C) {
let rhsCount = numericCast(countElements(rhs)) as Int
let oldCount = lhs.count
let capacity = lhs.capacity
let newCount = oldCount + rhsCount
// Ensure uniqueness, mutability, and sufficient storage. Note that
// for consistency, we need unique lhs even if rhs is empty.
lhs.reserve(newCount > capacity ? max(newCount, capacity * 2) : newCount)
var p = lhs.buffer.elementStorage + oldCount
for x in rhs {
(p++).initialize(x)
}
lhs.buffer.count = newCount
}
@assignment
func += <
A: ArrayType
>(inout lhs: A, rhs: A.Buffer.Element) {
lhs += CollectionOfOne(rhs)
}
//===--- generic helpers --------------------------------------------------===//
/// Ensure there's a NativeArrayBuffer capable of storing
/// max(newCount, minimumCapacity) elements, with count set to
/// newCount.
///
/// If source has sufficient capacity, returns nil. Otherwise,
/// returns a new buffer.
///
/// NOTE: does not initialize or destroy any elements. In general,
/// the buffer that satisfies the capacity request now has a count
/// that does not match its number of initialized elements, and that
/// needs to be corrected before the buffer can go back into circulation.
func _demandUniqueMutableBuffer<Buffer: ArrayBufferType>(
inout source: Buffer, newCount: Int, minimumCapacity: Int = 0)
-> NativeArrayBuffer<Buffer.Element>? {
assert(newCount >= 0)
let requiredCapacity = max(newCount, minimumCapacity)
if let b = source.requestUniqueMutableBuffer(requiredCapacity) {
source.count = newCount
return nil
}
let newCapacity = max(
requiredCapacity,
newCount > source.capacity ? source.capacity * 2 : source.capacity)
return NativeArrayBuffer(count: newCount, minimumCapacity: newCapacity)
}
protocol PointerFunction {
typealias Element
func call(UnsafePointer<Element>)
}
/// initialize the elements of dest by copying the first headCount
/// items from source, calling initializeNewElements on the next
/// uninitialized element, and finally by copying the last N items
/// from source into the N remaining uninitialized elements of dest.
///
/// As an optimization, may move elements out of source rather than
/// copying when it isUniquelyReferenced.
func _arrayOutOfPlaceUpdate<
Buffer: ArrayBufferType, Initializer: PointerFunction
where Initializer.Element == Buffer.Element
>(
inout source: Buffer,
inout dest: NativeArrayBuffer<Buffer.Element>?,
headCount: Int, // Count of initial source elements to copy/move
newCount: Int, // Count of new elements to insert
initializeNewElements: Initializer
) {
assert(headCount >= 0)
assert(newCount >= 0)
// Count of trailing source elements to copy/move
let tailCount = dest!.count - headCount - newCount
assert(headCount + tailCount <= source.count)
let sourceCount = source.count
let oldCount = sourceCount - headCount - tailCount
let destStart = dest!.elementStorage
let newStart = destStart + headCount
let newEnd = newStart + newCount
// Check to see if we have storage we can move from
if let backing = source.requestUniqueMutableBuffer(sourceCount) {
let sourceStart = source.elementStorage
let oldStart = sourceStart + headCount
// Destroy any items that may be lurking in a SliceBuffer before
// its real first element
let backingStart = backing.elementStorage
let sourceOffset = sourceStart - backingStart
backingStart.destroy(sourceOffset)
// Move the head items
destStart.moveInitializeFrom(sourceStart, count: headCount)
// Destroy unused source items
oldStart.destroy(oldCount)
initializeNewElements.call(newStart)
// Move the tail items
newEnd.moveInitializeFrom(oldStart + oldCount, count: tailCount)
// Destroy any items that may be lurking in a SliceBuffer after
// its real last element
let backingEnd = backingStart + backing.count
let sourceEnd = sourceStart + sourceCount
sourceEnd.destroy(sourceEnd - backingEnd)
backing.count = 0
}
else {
let newStart = source._uninitializedCopy(0...headCount, target: destStart)
initializeNewElements.call(newStart)
source._uninitializedCopy(headCount + oldCount...sourceCount,
target: newEnd)
}
source = Buffer(dest!)
}
struct InitializePointer<T> : PointerFunction {
func call(rawMemory: UnsafePointer<T>) {
// FIXME: maybe we should move here instead of copying?
rawMemory.initialize(newValue)
}
@transparent
init(_ newValue: T) {
self.newValue = newValue
}
var newValue: T
}
func _arrayAppend<Buffer: ArrayBufferType>(
inout buffer: Buffer, newValue: Buffer.Element
) {
let oldCount = buffer.count
var newBuffer = _demandUniqueMutableBuffer(&buffer, oldCount + 1)
if _fastPath(!newBuffer) {
(buffer.elementStorage + oldCount).initialize(newValue)
}
else {
_arrayOutOfPlaceUpdate(
&buffer, &newBuffer, oldCount, 1, InitializePointer(newValue))
}
}
struct IgnorePointer<T> : PointerFunction {
func call(_:UnsafePointer<T>) {}
}
func _arrayReserve<Buffer: ArrayBufferType>(
inout buffer: Buffer, newCapacity: Int
) {
let oldCount = buffer.count
var newBuffer = _demandUniqueMutableBuffer(&buffer, oldCount, minimumCapacity: newCapacity)
if _slowPath(newBuffer) {
_arrayOutOfPlaceUpdate(&buffer, &newBuffer, oldCount, 1, IgnorePointer())
}
}
func _extractOrCopyToNativeArrayBuffer<
Buffer: ArrayBufferType where Buffer.GeneratorType.Element == Buffer.Element
>(source: Buffer)
-> NativeArrayBuffer<Buffer.Element>
{
if let n = source.requestNativeBuffer() {
return n
}
return _copyCollectionToNativeArrayBuffer(source)
}
/// Append items from newItems to buffer
func _arrayAppendSequence<
Buffer: ArrayBufferType,
S: Sequence where S.GeneratorType.Element == Buffer.Element
>(
inout buffer: Buffer, newItems: S
) {
var stream = newItems.generate()
var nextItem = stream.next()
if !nextItem {
return
}
// This will force uniqueness
_arrayAppend(&buffer, nextItem!)
var count = buffer.count
nextItem = stream.next()
while nextItem {
let capacity = buffer.capacity
let base = buffer.elementStorage
while nextItem && count < capacity {
(base + count++).initialize(nextItem!)
nextItem = stream.next()
}
buffer.count = count
if nextItem {
_arrayReserve(&buffer, capacity * 2)
}
}
}
/// Returns true iff these arrays reference exactly the same elements.
func ===<T: ArrayType, U: ArrayType>(lhs: T, rhs: U) -> Bool {
let lhsCount = lhs.count
if lhsCount != rhs.count {
return false
}
return lhsCount == 0 || lhs.buffer.identity == rhs.buffer.identity
}
/// Returns false iff these arrays reference exactly the same
/// elements.
func !==<T: ArrayType, U: ArrayType>(lhs: T, rhs: U) -> Bool {
return !(lhs === rhs)
}
/// Returns an Array<Base> containing the same elements as a in
/// O(1). Requires: Base is a base class or base @objc protocol (such
/// as AnyObject) of Derived.
func _arrayUpCast<Derived, Base>(a: Array<Derived>) -> Array<Base> {
return Array(ArrayBuffer<Base>(castFrom: a.buffer, direction: .Up))
}
/// Returns an Array<Derived> containing the same elements as a in
/// O(1). Requires: a is known to contain only elements of type
/// Derived, and Base is a base class or base @objc protocol (such as
/// AnyObject) of Derived.
func _arrayDownCast<Base, Derived>(a: Array<Base>) -> Array<Derived> {
return Array(ArrayBuffer<Derived>(castFrom: a.buffer, direction: .Down))
}
/// Return the most-derived element type known to be stored in a's
/// buffer. O(1)
func _arrayElementType<T>(a: Array<T>) -> Any.Type {
return a.buffer.dynamicElementType
}
/// Returns an Array<Derived> containing the same elements as a in
/// O(1) iff a's buffer elements are dynamically known to have
/// type Derived or a type derived from Derived.
func _arrayCheckedDownCast<Base, Derived>(a: Array<Base>) -> Array<Derived>? {
return _arrayDownCast(a)
}
/// Convert a to its corresponding bridged array type.
/// Precondition: T is bridged to objective C
/// O(1) if T is bridged verbatim, O(N) otherwise
func _arrayBridgeToObjectiveC<T: _BridgedToObjectiveC>(
a: Array<T>
) -> Array<T.ObjectiveCType> {
return Array(ArrayBuffer(a.asCocoaArray()))
}
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:

View File

@@ -1,18 +1,193 @@
// Classic C assert(), plus a message.
func assert(fn : [auto_closure] () -> Bool, message : String = "") {
}
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// These trap functions promise to emit the debugger trap instruction and not
// print anything; therefore these functions clobber far fewer registers and
// are more useful for debugging and automated crash reporting infrastructure.
//
// Fatal errors, which always stop the program regardless of build
// configuration.
//
// "Expensive" asserts that are debug only
func debugTrap(fn : [auto_closure] () -> Bool = false, message : String = "") {
}
// "Important" and/or cheap asserts that are always enabled
func alwaysTrap(cond : Bool = false, message : String = "") {
if !cond {
/// A fatal error occurred and program execution must stop. In
/// builds with assertions enabled, currently prints message to the
/// console and executes a minimal debugger trap. In non-assert
/// builds, just executes a minimal debugger trap.
@transparent
@noreturn
func fatal(
message: StaticString,
file: StaticString = __FILE__, line: UWord = __LINE__
) {
if _isDebug() {
_fatal_error_message("fatal error", message, file, line)
} else if _isFast() {
_conditionallyUnreachable()
} else {
Builtin.int_trap()
}
}
/// If condition is false, invoke `fatal(message)`
@transparent
func securityCheck<L: LogicValue>(
condition: L,
_ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
if _isDebug() {
if !_branchHint(condition.getLogicValue(), true) {
_fatal_error_message("fatal error", message, file, line)
}
} else {
if !_branchHint(condition.getLogicValue(), true) {
Builtin.int_trap()
}
}
}
/// If `error` is true, executes `fatal("Overflow/underflow")`.
/// Otherwise returns `result`.
@transparent
func overflowChecked<T>(
args: (T, Bool),
file: StaticString = __FILE__, line: UWord = __LINE__
) -> T {
let (result, error) = args
if _isDebug() {
if _branchHint(error, false) {
fatal("Overflow/underflow", file: file, line: line)
}
} else {
Builtin.condfail(error.value)
return result
}
return result
}
//
// Assertions, which may have no effect on program semantics,
// depending on the build configuration
//
// FIXME: Dispatching to this overload is needed as a workaround for
// <rdar://problem/15889294>
@transparent
func assert(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only assert in debug mode.
if _isDebug() {
if !_branchHint(condition(), true) {
_fatal_error_message("assertion failed", message, file, line)
}
}
}
/// Traditional C-style assert with an optional message.
///
/// When assertions are enabled and `condition` is false, stop program
/// execution in a debuggable state after printing a message. When
/// assertions are disabled, `condition` is not even evaluated.
@transparent
func assert<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only in debug mode.
if _isDebug() {
assert(condition().getLogicValue(), message, file: file, line: line)
}
}
/// Internal checks are to be used for checking correctness conditions in the
/// standard library. They are only enable when the standard library is built
/// with the build configuration INTERNAL_CHECKS_ENABLED enabled. Otherwise, the
/// call to this function is a noop.
@transparent
func _internal_check(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
#if INTERNAL_CHECKS_ENABLED
if !_branchHint(condition(), true) {
_fatal_error_message("internal check failed", message, file, line)
}
#endif
}
@transparent
func _internal_check<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
#if INTERNAL_CHECKS_ENABLED
if !_branchHint(condition(), true) {
_internal_check(condition().getLogicValue(), message, file: file, line: line)
}
#endif
}
/// Library precondition checks are enabled in debug and release mode but not in
/// fast mode. In release mode they don't print an error message but just trap.
/// In debug mode they print an error message and abort.
@transparent
func _precondition_safety_check(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only check in debug and release mode. In release mode just trap.
if _isDebug() {
if !_branchHint(condition(), true) {
_fatal_error_message("precondition failed", message, file, line)
}
} else if _isRelease() {
if !_branchHint(condition(), true) {
Builtin.int_trap()
}
}
}
@transparent
func _precondition_safety_check<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only in debug and release mode.
if _isDebug() || _isRelease() {
_precondition_safety_check(condition().getLogicValue(), message, file: file, line: line)
}
}
/// Library partial safety checks are only enabled in debug mode and print an
/// error message on failure.
@transparent
func _partial_safety_check(
condition: @auto_closure () -> Bool, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only assert in debug and release mode.
if _isDebug() {
if !_branchHint(condition(), true) {
_fatal_error_message("safety check failed", message, file, line)
}
}
}
@transparent
func _partial_safety_check<T : LogicValue>(
condition: @auto_closure () -> T, _ message: StaticString = StaticString(),
file: StaticString = __FILE__, line: UWord = __LINE__
) {
// Only in debug mode.
if _isDebug() {
_partial_safety_check(condition().getLogicValue(), message, file: file, line: line)
}
}

View File

@@ -1,21 +1,86 @@
/// True if we are going to print a message about a failed assertion.
///
/// FIXME: this should be an atomic bool.
var _in_assert_fail : Bool = false
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
func _assert_fail(message: String, file: String, line: Int) {
if _in_assert_fail {
// Prevent recursive assertions. This can happen if the original one was
// triggered by String or print().
//
// FIXME: this should be implemented with compare-and-exchange.
abort()
}
_in_assert_fail = true
if message.isEmpty() {
print("assertion failed: file \(file), line \(line)\n")
} else {
print("assertion failed: \(message): file \(file), line \(line)\n")
}
// Implementation Note: this file intentionally uses very LOW-LEVEL
// CONSTRUCTS, so that assert and fatal may be used liberally in
// building library abstractions without fear of infinite recursion.
//
// FIXME: We could go farther with this simplification, e.g. avoiding
// UnsafePointer
@transparent
func _isDebug() -> Bool {
// The values for the assert_configuration call are:
// 0 .. Debug
// 1 .. Release
// 2 .. Fast
return Int32(Builtin.assert_configuration()) == 0;
}
@transparent
func _isRelease() -> Bool {
// The values for the assert_configuration call are:
// 0 .. Debug
// 1 .. Release
// 2 .. Fast
return Int32(Builtin.assert_configuration()) == 1;
}
@transparent
func _isFast() -> Bool {
// The values for the assert_configuration call are:
// 0 .. Debug
// 1 .. Release
// 2 .. Fast
return Int32(Builtin.assert_configuration()) == 2;
}
@asmname("swift_reportFatalError")
func _reportFatalError(
header: Builtin.RawPointer, headerLength: Builtin.Word,
message: Builtin.RawPointer, messageLength: Builtin.Word,
file: Builtin.RawPointer, fileLength: Builtin.Word,
line: UWord)
@asmname("swift_reportUnimplementedInitializer")
func _reportUnimplementedInitializer(
className: Builtin.RawPointer, classNameLength: Builtin.Word,
file: Builtin.RawPointer, fileLength: Builtin.Word,
line: UWord, column: UWord,
initName: Builtin.RawPointer, initNameLength: Builtin.Word)
@noreturn
func _fatal_error_message(header: StaticString, message: StaticString,
file: StaticString, line: UWord)
{
_reportFatalError(header.start, header.byteSize,
message.start, message.byteSize,
file.start, file.byteSize, line)
Builtin.int_trap()
}
/// Prints a fatal error message when a unimplemented initializer gets
/// called by the Objective-C runtime.
@noreturn
func _unimplemented_initializer(className: StaticString,
file: StaticString = __FILE__,
line: UWord = __LINE__,
column: UWord = __LINE__,
initName: StaticString = __FUNCTION__)
{
_reportUnimplementedInitializer(className.start, className.byteSize,
file.start, file.byteSize, line, column,
initName.start, initName.byteSize)
Builtin.int_trap()
}

View File

@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
//
// Used to index T? and SequenceOfOne<T>
// Used to index SequenceOfOne<T>
//
//===----------------------------------------------------------------------===//
enum Bit : Int, RandomAccessIndex {
@@ -25,6 +25,14 @@ enum Bit : Int, RandomAccessIndex {
assert(self == .one, "Can't decrement past zero")
return .zero
}
func distanceTo(other: Bit) -> Int {
return toRaw().distanceTo(other.toRaw())
}
func advancedBy(distance: Int) -> Bit {
return toRaw().advancedBy(distance) > 0 ? one : zero
}
}
func == (lhs: Bit, rhs: Bit) -> Bool {
@@ -35,38 +43,32 @@ func < (lhs: Bit, rhs: Bit) -> Bool {
return lhs.toRaw() < rhs.toRaw()
}
extension Bit : NumericOperations {
static func _withOverflow(x: Int, b: Bool) -> (Bit, Bool) {
extension Bit : IntegerArithmetic {
static func _withOverflow(x: Int, _ b: Bool) -> (Bit, Bool) {
return (Bit.fromRaw(x)!, b)
}
static func add(lhs: Bit, rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.add(lhs.toRaw(), rhs.toRaw()))
static func uncheckedAdd(lhs: Bit, _ rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.uncheckedAdd(lhs.toRaw(), rhs.toRaw()))
}
static func sub(lhs: Bit, rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.add(lhs.toRaw(), rhs.toRaw()))
static func uncheckedSubtract(lhs: Bit, _ rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.uncheckedSubtract(lhs.toRaw(), rhs.toRaw()))
}
static func mul(lhs: Bit, rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.add(lhs.toRaw(), rhs.toRaw()))
static func uncheckedMultiply(lhs: Bit, _ rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.uncheckedMultiply(lhs.toRaw(), rhs.toRaw()))
}
static func div(lhs: Bit, rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.add(lhs.toRaw(), rhs.toRaw()))
static func uncheckedDivide(lhs: Bit, _ rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.uncheckedDivide(lhs.toRaw(), rhs.toRaw()))
}
static func rem(lhs: Bit, rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.add(lhs.toRaw(), rhs.toRaw()))
static func uncheckedModulus(lhs: Bit, _ rhs: Bit) -> (Bit, Bool) {
return _withOverflow(Int.uncheckedModulus(lhs.toRaw(), rhs.toRaw()))
}
func toIntMax() -> IntMax {
return IntMax(toRaw())
}
}
// This overload is needed to work around the ambiguity of the two
// generic "-" operators for RandomAccessIndex.
func - (lhs: Bit, rhs: Bit) -> Bit {
return Bit.fromRaw( lhs.toRaw() - rhs.toRaw() )!
}

View File

@@ -1,36 +1,64 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Bool Datatype and Supporting Operators
//===----------------------------------------------------------------------===//
// Bool is the standard way to reason about truth values.
oneof Bool {
false, true
struct Bool {
var value: Builtin.Int1
/// \brief Default-initialize Boolean value to \c false.
constructor() { this = .false }
@transparent
init() { value = Builtin.trunc_Word_Int1(0.value) }
@transparent
init(_ v : Builtin.Int1) { value = v }
static var false : Bool {
@transparent
get {
return Bool()
}
}
static var true : Bool {
@transparent
get {
return Bool(Builtin.trunc_Word_Int1(1.value))
}
}
}
// FIXME: Convert these to immutable vars when we have them.
var true : Bool {
@transparent
get {
return Bool.true
}
}
var false : Bool {
@transparent
get {
return Bool.false
}
}
extension Bool : LogicValue, ReplPrintable {
@transparent func _getBuiltinLogicValue() -> Builtin.Int1 {
return value
}
// *private* helper function for forming Bools
func [asmname="swift_getBool"] _getBool(v : Builtin.Int1) -> Bool;
extension Bool : LogicValue {
// FIXME: Implement pattern matching or equality testing to implement this.
func [asmname="_TSb13getLogicValuefRSbFT_Bi1_"] _getBuiltinLogicValue() -> Builtin.Int1
func getLogicValue() -> Bool { return this }
@transparent func getLogicValue() -> Bool { return self }
func replPrint() {
if this {
if self {
print("true")
} else {
print("false")
@@ -38,80 +66,68 @@ extension Bool : LogicValue {
}
// Bool can be constructed from LogicValue
constructor(v : LogicValue) {
this = v.getLogicValue()
init(_ v : LogicValue) {
self = v.getLogicValue()
}
}
// This is a magic entrypoint known to the compiler.
@transparent func _getBool(v: Builtin.Int1) -> Bool { return Bool(v) }
//===----------------------------------------------------------------------===//
// Standard Operators
//===----------------------------------------------------------------------===//
// Unary bitwise complement.
func [prefix] ~(a : Bool) -> Bool {
@prefix @transparent func ~(a: Bool) -> Bool {
return a ^ true
}
// Unary logical complement.
func [prefix] !(a : Bool) -> Bool {
@prefix @transparent func !(a: Bool) -> Bool {
return ~a
}
@transparent
func ==(lhs: Bool, rhs: Bool) -> Bool {
return Bool(Builtin.cmp_eq_Int1(lhs.value, rhs.value))
}
@transparent
extension Bool : Equatable, Hashable {
func __equal__(rhs: Bool) -> Bool {
return _getBool(Builtin.cmp_eq_Int1(_getBuiltinLogicValue(),
rhs._getBuiltinLogicValue()))
}
func hashValue() -> Int {
return this? 1 : 0
var hashValue: Int {
return self ? 1 : 0
}
}
// Bitwise 'and'.
func & (lhs : Bool, rhs : Bool) -> Bool {
return _getBool(Builtin.and_Int1(lhs._getBuiltinLogicValue(),
rhs._getBuiltinLogicValue()))
@transparent func & (lhs: Bool, rhs: Bool) -> Bool {
return Bool(Builtin.and_Int1(lhs.value, rhs.value))
}
// Bitwise 'xor'.
func ^ (lhs : Bool, rhs : Bool) -> Bool {
return _getBool(Builtin.xor_Int1(lhs._getBuiltinLogicValue(),
rhs._getBuiltinLogicValue()))
@transparent func ^ (lhs: Bool, rhs: Bool) -> Bool {
return Bool(Builtin.xor_Int1(lhs.value, rhs.value))
}
// Bitwise 'or'.
func | (lhs : Bool, rhs : Bool) -> Bool {
return _getBool(Builtin.or_Int1(lhs._getBuiltinLogicValue(),
rhs._getBuiltinLogicValue()))
}
// Short circuiting logical operators.
func && (lhs: Bool, rhs: [auto_closure] ()->Bool) -> Bool {
if lhs {
return rhs()
}
return false
}
func || (lhs: Bool, rhs: [auto_closure] ()->Bool) -> Bool {
if lhs {
return true
}
return rhs()
@transparent func | (lhs: Bool, rhs: Bool) -> Bool {
return Bool(Builtin.or_Int1(lhs.value, rhs.value))
}
// Compound assignment (with bitwise and)
func [assignment] &= (lhs : [byref] Bool, rhs : Bool) {
@assignment @transparent func &= (inout lhs: Bool, rhs: Bool) {
lhs = lhs & rhs
}
// Compound assignment (with bitwise or)
func [assignment] |= (lhs : [byref] Bool, rhs : Bool) {
@assignment @transparent func |= (inout lhs: Bool, rhs: Bool) {
lhs = lhs | rhs
}
// Compound assignment (with bitwise xor)
func [assignment] ^= (lhs : [byref] Bool, rhs : Bool) {
@assignment @transparent func ^= (inout lhs: Bool, rhs: Bool) {
lhs = lhs ^ rhs
}

View File

@@ -1,27 +1,587 @@
/// \brief A means of accepting "out" parameters from Objective-C
/// functions taking the parameters by pointer
func withOutArgument<T, Result>(
arg: @inout T,
f: (UnsafePointer<T>)->Result
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// \brief Invokes body with an UnsafePointer to arg and returns the
/// result. Useful for calling Objective-C APIs that take "in/out"
/// parameters (and default-constructible "out" parameters) by pointer
func withUnsafePointer<T, Result>(
inout arg: T,
body: (UnsafePointer<T>)->Result
) -> Result
{
return f(UnsafePointer<T>(Builtin.addressof(&arg)))
return body(UnsafePointer<T>(Builtin.addressof(&arg)))
}
/// \brief A means of accepting @autorelease "out" parameters from
/// Objective-C functions, which can be tricky because they are
/// not handed to us at +1 like other objects.
func withAutoReleasedOutArgument<T, Result>(
arg: @inout T?,
f: (UnsafePointer<T>)->Result
) -> Result
{
var buffer: Builtin.RawPointer = Builtin.inttoptr_Int64(0.value)
var address = UnsafePointer<T>(Builtin.addressof(&buffer))
var result = f(address)
/// \brief Like withUnsafePointer, but passes pointers to arg0 and
/// arg1
func withUnsafePointers<A0, A1, Result>(
inout arg0: A0,
inout arg1: A1,
body: (UnsafePointer<A0>, UnsafePointer<A1>)->Result
) -> Result {
return withUnsafePointer(&arg0) {
arg0 in withUnsafePointer(&arg1) {
arg1 in body(arg0, arg1)
}
}
}
arg = Int64(Builtin.ptrtoint_Int64(buffer)) == 0
? .None : .Some(address.get())
/// \brief Like withUnsafePointer, but passes pointers to arg0, arg1,
/// and arg2
func withUnsafePointers<A0, A1, A2, Result>(
inout arg0: A0,
inout arg1: A1,
inout arg2: A2,
body: (UnsafePointer<A0>, UnsafePointer<A1>, UnsafePointer<A2>)->Result
) -> Result {
return withUnsafePointer(&arg0) {
arg0 in withUnsafePointer(&arg1) {
arg1 in withUnsafePointer(&arg2) {
arg2 in body(arg0, arg1, arg2)
}
}
}
}
/// FIXME: workaround for <rdar://problem/15637771> Need a way to
/// constrain a generic argument to being a class
@class_protocol @objc
protocol ObjCClassType {}
/// \brief Invokes body with an UnsafePointer to a nil T, sets arg to
/// the value of that T (or .None if the T is still nil), and returns
/// the result of the invocation
///
/// Useful for calling Objective-C APIs that take class instances by
/// pointer as @autorelease "out" parameters.
func withUnsafePointerToObject<T: AnyObject, Result>(
inout arg: T?,
body: (UnsafePointer<ImplicitlyUnwrappedOptional<T>>)->Result
) -> Result {
var buffer: Builtin.RawPointer = Builtin.inttoptr_Word(0.value)
var address = UnsafePointer<ImplicitlyUnwrappedOptional<T>>(Builtin.addressof(&buffer))
var result = body(address)
arg = address.get()
return result
}
/// A Swift Array or Dictionary of types conforming to
/// _BridgedToObjectiveC can be passed to ObjectiveC as an NSArray or
/// NSDictionary, respectively. The elements of the resulting NSArray
/// or NSDictionary will be the result of calling bridgeToObjectiveC
/// on each elmeent of the source container.
protocol _BridgedToObjectiveC {
typealias ObjectiveCType: AnyObject
func bridgeToObjectiveC() -> ObjectiveCType
}
/// Whether a given type conforming to this protocol bridges to
/// ObjectiveC is only knowable at runtime. Array<T> is an example;
/// it is bridges to ObjectiveC iff T does, too.
protocol _ConditionallyBridgedToObjectiveC : _BridgedToObjectiveC {
class func isBridgedToObjectiveC() -> Bool
}
/// Attempt to convert x to its ObjectiveC representation. If T
/// conforms to _BridgedToObjectiveC, returns the result of calling its
/// bridgeToObjectiveC() method. Otherwise, if T is a class type,
/// returns x. Otherwise, the result is empty.
@asmname("swift_bridgeToObjectiveC")
func bridgeToObjectiveC<T>(x: T) -> AnyObject?
/// If T conforms to _ConditionallyBridgedToObjectiveC, returns
/// T.isBridgedToObjectiveC(). Otherwise, if T conforms to
/// _BridgedToObjectiveC or T is a class type, returns true
@asmname("swift_isBridgedToObjectiveC")
func isBridgedToObjectiveC<T>(_: T.Type) -> Bool
/// A type that's bridged "verbatim" does not conform to
/// _BridgedToObjectiveC, and can have its bits reinterpreted as an
/// AnyObject. This function does not necessarily detect all such
/// types (there may be false negatives) but when it returns true, the
/// storage Array<T> can be reinterpretCast as an array of AnyObject
@asmname("swift_isBridgedVerbatimToObjectiveC")
func isBridgedVerbatimToObjectiveC<T>(_: T.Type) -> Bool
// -- Pointer argument bridging
@transparent
var _nilNativeObject: AnyObject? {
return nil
}
@transparent
var _nilRawPointer: Builtin.RawPointer {
return Builtin.inttoptr_Word(0.value)
}
/// A mutable C pointer argument.
///
/// This type has no operations of its own, but has implicit conversions
/// to allow passing any of the following to a C or ObjC API:
///
/// - 'nil', which gets passed as a null pointer,
/// - an inout argument of the referenced type, which gets passed as a pointer
/// to the inout-ed lvalue (or its writeback temporary, if it is a computed
/// lvalue),
/// - an inout argument of the Array<T> type, which gets passed as a pointer
/// to the beginning of the array,
/// - an UnsafePointer<T>, which is passed as-is.
///
/// The value consists of an owner-value pair. During bridging, a strong
/// reference to the owner is held for the duration of the call, and the pointer
/// value is passed down to the C or Objective-C entry point. This allows
/// types that own heap storage, such as Array, to convert themselves to
/// a pointer and still guarantee that their storage will be held for the
/// duration of the call.
///
/// Pointers to ObjC object pointer type ``NSFoo**`` are not mapped to this
/// type; they instead get mapped to ObjCMutablePointer<T>. ``void*`` pointers
/// are mapped to CMutableVoidPointer.
struct CMutablePointer<T> : Equatable {
let owner: AnyObject?
let value: Builtin.RawPointer
/// Conversion from an inout scalar.
@transparent
static func __inout_conversion(inout scalar: T) -> CMutablePointer {
// No owner pointer for an inout scalar; the lifetime guarantee of writeback
// is sufficient.
return CMutablePointer(owner: _nilNativeObject,
value: Builtin.addressof(&scalar))
}
/// Conversion from an inout array.
@transparent
static func __inout_conversion(inout a: Array<T>) -> CMutablePointer {
assert(a.elementStorage != nil || a.count == 0)
// TODO: Putting a canary at the end of the array in checked builds might
// be a good idea
// The callee that receives the pointer may mutate through it, so
// force uniqueness by calling reserve(0).
a.reserve(0)
return CMutablePointer(owner: a.owner, value: a.elementStorage.value)
}
/// True if this is a scoped pointer, meaning it has a owner reference
/// that guarantees the lifetime of the referenced memory.
@transparent
var scoped: Bool {
return owner.getLogicValue()
}
/// Make the pointer available as an UnsafePointer within a closure.
@transparent
func withUnsafePointer<U>(f: UnsafePointer<T> -> U) -> U {
let result = f(UnsafePointer<T>(value))
// Ensure the owner pointer stays alive for the duration of the closure.
_fixLifetime(owner)
return result
}
}
@transparent
func == <T> (lhs: CMutablePointer<T>, rhs: CMutablePointer<T>) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
// Also make CMutablePointer comparable to CConstPointer.
@transparent
func == <T> (lhs: CMutablePointer<T>, rhs: CConstPointer<T>) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
@transparent
func == <T> (lhs: CConstPointer<T>, rhs: CMutablePointer<T>) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
/// A mutable C void pointer argument.
///
/// This type has no operations of its own, but has implicit conversions
/// to allow passing any of the following to a C or ObjC API:
///
/// - 'nil', which gets passed as a null pointer,
/// - an inout argument of any type, which gets passed as a pointer
/// to the inout-ed lvalue (or its writeback temporary, if it is a computed
/// lvalue),
/// - an inout argument of Array<T> type for any T, which gets passed as a
/// pointer to the beginning of the array,
/// - an UnsafePointer<T> for any T or COpaquePointer, which is passed as-is.
///
/// The value consists of an owner-value pair. During bridging, a strong
/// reference to the owner is held for the duration of the call, and the pointer
/// value is passed down to the C or Objective-C entry point. This allows
/// types that own heap storage, such as Array, to convert themselves to
/// a pointer and still guarantee that their storage will be held for the
/// duration of the call.
struct CMutableVoidPointer : Equatable {
let owner: AnyObject?
let value: Builtin.RawPointer
/// Conversion from an inout scalar.
@transparent
static func __inout_conversion<T>(inout scalar: T) -> CMutableVoidPointer {
// No owner pointer for an inout scalar; the lifetime guarantee of writeback
// is sufficient.
return CMutableVoidPointer(owner: _nilNativeObject,
value: Builtin.addressof(&scalar))
}
/// Conversion from an inout array.
@transparent
static func __inout_conversion<T>(inout a: Array<T>)
-> CMutableVoidPointer {
assert(a.elementStorage != nil || a.count == 0)
// TODO: Putting a canary at the end of the array in checked builds might
// be a good idea.
// The callee that receives the pointer may mutate through it, so
// force uniqueness by calling reserve(0).
a.reserve(0)
return CMutableVoidPointer(owner: a.owner,
value: a.elementStorage.value)
}
/// True if this is a scoped pointer, meaning it has a owner reference
/// that guarantees the lifetime of the referenced memory.
@transparent
var scoped: Bool {
return owner.getLogicValue()
}
/// Make the pointer available as an UnsafePointer within a closure.
@transparent
func withUnsafePointer<T, U>(f: UnsafePointer<T> -> U) -> U {
let result = f(UnsafePointer(value))
// Ensure the owner pointer stays alive for the duration of the closure.
_fixLifetime(owner)
return result
}
}
@transparent
func == (lhs: CMutableVoidPointer, rhs: CMutableVoidPointer) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
/// A mutable pointer-to-ObjC-pointer argument.
///
/// This type has implicit conversions to allow passing any of the following
/// to a C or ObjC API:
///
/// - 'nil', which gets passed as a null pointer,
/// - an inout argument of the referenced type, which gets passed as a pointer
/// to a writeback temporary with autoreleasing ownership semantics,
/// - an UnsafePointer<T>, which is passed as-is.
///
/// Unlike CMutablePointer, passing pointers to mutable arrays of ObjC class
/// pointers is not directly supported. Unlike UnsafePointer<T>,
/// ObjCMutablePointer must reference storage that does not own a reference
/// count to the referenced value. UnsafePointer's operations, by contrast,
/// assume that the referenced storage owns values loaded from or stored to it.
///
/// This type does not carry an owner pointer unlike the other C*Pointer types
/// because it only needs to reference the results of inout conversions, which
/// already have writeback-scoped lifetime.
struct ObjCMutablePointer<T /* TODO : class */> : Equatable {
let value: Builtin.RawPointer
@transparent
init(_ value: Builtin.RawPointer) {
self.value = value
}
/// Create the writeback temporary for inout conversion.
@transparent
static func __writeback_conversion_get(x: T) -> Builtin.RawPointer {
// Reinterpreting the object reference as a RawPointer gives us a
// nonowning reference to the original value.
return reinterpretCast(x)
}
/// Commit the writeback temporary back to the original inout parameter.
@transparent
static func __writeback_conversion_set(x: Builtin.RawPointer) -> T {
// Reinterpreting the RawPointer back to an object reference gives us a +1
// reference to the object again.
return reinterpretCast(x)
}
/// Conversion from an inout scalar.
///
/// Variables always have strong ownership semantics in Swift, but "NSFoo**"
/// pointers in ARC have autoreleasing ownership by default, so doing this
/// properly requires a writeback temporary.
@transparent
static func __writeback_conversion(
inout autoreleasingTemp: Builtin.RawPointer
) -> ObjCMutablePointer {
return ObjCMutablePointer(Builtin.addressof(&autoreleasingTemp))
}
@transparent
func isNull() -> Bool {
return UnsafePointer<T>(self).isNull()
}
/// Retrieve the value the pointer points to.
@transparent
func get() -> T {
assert(!isNull())
// We can do a strong load normally.
return UnsafePointer<T>(self).get()
}
/// Set the value the pointer points to, copying over the previous value.
///
/// ObjCMutablePointers are assumed to reference a value with __autoreleasing
/// ownership semantics, like 'NSFoo**' in ARC. This autoreleases the
/// argument before trivially storing it to the referenced memory.
@transparent
func set(newValue: T) {
assert(!isNull())
// Autorelease the object reference.
Builtin.retain(reinterpretCast(newValue) as AnyObject?)
Builtin.autorelease(reinterpretCast(newValue) as AnyObject?)
// Trivially assign it as a COpaquePointer; the pointer references an
// autoreleasing slot, so retains/releases of the original value are
// unneeded.
UnsafePointer<COpaquePointer>(UnsafePointer<T>(self))
.set(reinterpretCast(newValue))
}
}
@transparent
func == <T> (lhs: ObjCMutablePointer<T>, rhs: ObjCMutablePointer<T>) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
/// A const C pointer argument.
///
/// This type has no operations of its own, but has implicit conversions
/// to allow passing any of the following to a C or ObjC API:
///
/// - 'nil', which gets passed as a null pointer,
/// - an inout argument of the referenced type, which gets passed as a pointer
/// to the inout-ed lvalue (or its writeback temporary, if it is a computed
/// lvalue),
/// - a value argument of the Array<T> type, which gets passed as a pointer
/// to the beginning of the array.
///
/// The value consists of an owner-value pair. During bridging, a strong
/// reference to the owner is held for the duration of the call, and the pointer
/// value is passed down to the C or Objective-C entry point. This allows
/// types that own heap storage, such as Array, to convert themselves to
/// a pointer and still guarantee that their storage will be held for the
/// duration of the call.
struct CConstPointer<T> : Equatable {
// TODO: Owner should become AnyObject? when the new Array implementation
// comes online.
let owner: AnyObject?
let value: Builtin.RawPointer
@transparent
init(_ owner: AnyObject?, _ value: Builtin.RawPointer) {
self.owner = owner
self.value = value
}
// Conversion from an inout scalar.
@transparent
static func __inout_conversion(inout scalar: T) -> CConstPointer {
// No owner pointer for an inout scalar; the lifetime guarantee of writeback
// is sufficient.
return CConstPointer(_nilNativeObject, Builtin.addressof(&scalar))
}
/// True if this is a scoped pointer, meaning it has a owner reference
/// that guarantees the lifetime of the referenced memory.
@transparent
var scoped: Bool {
return owner.getLogicValue()
}
/// Make the pointer available as an UnsafePointer within a closure.
@transparent
func withUnsafePointer<U>(f: UnsafePointer<T> -> U) -> U {
let result = f(UnsafePointer<T>(value))
// Ensure the owner pointer stays alive for the duration of the closure.
_fixLifetime(owner)
return result
}
}
@transparent
func == <T> (lhs: CConstPointer<T>, rhs: CConstPointer<T>) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
struct CConstVoidPointer : Equatable {
// TODO: Owner should become AnyObject? when the new Array implementation
// comes online.
let owner: AnyObject?
let value: Builtin.RawPointer
@transparent
init(_ owner: AnyObject?, _ value: Builtin.RawPointer) {
self.owner = owner
self.value = value
}
// Conversion from an inout scalar.
@transparent
static func __inout_conversion<T>(inout scalar: T) -> CConstVoidPointer {
// No owner pointer for an inout scalar; the lifetime guarantee of writeback
// is sufficient.
return CConstVoidPointer(_nilNativeObject, Builtin.addressof(&scalar))
}
/// True if this is a scoped pointer, meaning it has a owner reference
/// that guarantees the lifetime of the referenced memory.
@transparent
var scoped: Bool {
return owner.getLogicValue()
}
/// Make the pointer available as an UnsafePointer within a closure.
@transparent
func withUnsafePointer<T, U>(f: UnsafePointer<T> -> U) -> U {
let result = f(UnsafePointer(value))
// Ensure the owner pointer stays alive for the duration of the closure.
_fixLifetime(owner)
return result
}
}
@transparent
func ==(lhs: CConstVoidPointer, rhs: CConstVoidPointer) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
//
// Conversions from nil to bridging pointer types.
//
extension _Nil {
@transparent @conversion
func __conversion<T>() -> CMutablePointer<T> {
return CMutablePointer(owner: _nilNativeObject, value: _nilRawPointer)
}
@transparent @conversion
func __conversion() -> CMutableVoidPointer {
return CMutableVoidPointer(owner: _nilNativeObject, value: _nilRawPointer)
}
@transparent @conversion
func __conversion<T>() -> CConstPointer<T> {
return CConstPointer(_nilNativeObject, _nilRawPointer)
}
@transparent @conversion
func __conversion() -> CConstVoidPointer {
return CConstVoidPointer(_nilNativeObject, _nilRawPointer)
}
@transparent @conversion
func __conversion<T>() -> ObjCMutablePointer<T> {
return ObjCMutablePointer(_nilRawPointer)
}
}
//
// Conversions from COpaquePointer to C*VoidPointer
//
extension COpaquePointer {
@transparent @conversion
func __conversion() -> CMutableVoidPointer {
return CMutableVoidPointer(owner: _nilNativeObject, value: value)
}
@transparent @conversion
func __conversion() -> CConstVoidPointer {
return CConstVoidPointer(_nilNativeObject, value)
}
}
//
// Native-to-bridged conversion functions from C*Pointer to UnsafePointer
//
@transparent
func _convertCConstPointerToUnsafePointer<T>(p: CConstPointer<T>)
-> UnsafePointer<T> {
return UnsafePointer(p.value)
}
@transparent
func _convertCConstVoidPointerToCOpaquePointer(p: CConstVoidPointer)
-> COpaquePointer {
return COpaquePointer(p.value)
}
@transparent
func _convertCMutablePointerToUnsafePointer<T>(p: CMutablePointer<T>)
-> UnsafePointer<T> {
return UnsafePointer(p.value)
}
@transparent
func _convertCMutableVoidPointerToCOpaquePointer(p: CMutableVoidPointer)
-> COpaquePointer {
return COpaquePointer(p.value)
}
@transparent
func _convertObjCMutablePointerToUnsafePointer<T>(p: ObjCMutablePointer<T>)
-> UnsafePointer<T> {
return UnsafePointer(p.value)
}
//
// Bridged-to-native conversion functions from UnsafePointer to C*Pointer
//
// UnsafePointers will be bridged back into C*Pointer types in argument
// position, where they should reference storage lifetime-guaranteed for
// the duration of the function being called. We can thus safely bridge
// the arguments to C*Pointer types with nil owner references.
@transparent
func _convertUnsafePointerToCConstPointer<T>(p: UnsafePointer<T>)
-> CConstPointer<T> {
return CConstPointer(_nilNativeObject, p.value)
}
@transparent
func _convertCOpaquePointerToCConstVoidPointer(p: COpaquePointer)
-> CConstVoidPointer {
return CConstVoidPointer(_nilNativeObject, p.value)
}
@transparent
func _convertUnsafePointerToCMutablePointer<T>(p: UnsafePointer<T>)
-> CMutablePointer<T> {
return CMutablePointer(owner: _nilNativeObject, value: p.value)
}
@transparent
func _convertCOpaquePointerToCMutableVoidPointer(p: COpaquePointer)
-> CMutableVoidPointer {
return CMutableVoidPointer(owner: _nilNativeObject, value: p.value)
}
@transparent
func _convertUnsafePointerToObjCMutablePointer<T>(p: UnsafePointer<T>)
-> ObjCMutablePointer<T> {
return ObjCMutablePointer(p.value)
}

View File

@@ -1,17 +1,138 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// \brief Definitions that make elements of Builtin usable in real
/// code without gobs of boilerplate. These APIs will probably *not*
/// be exposed outside the stdlib.
func sizeof<T>(_:T.metatype) -> Int {
return Int(Word(Builtin.sizeof(T)))
@transparent
func sizeof<T>(_:T.Type) -> Int {
return Int(Builtin.sizeof(T.self))
}
func sizeof<T>(_:T) -> Int {
return Int(Word(Builtin.sizeof(T)))
@transparent
func sizeofValue<T>(_:T) -> Int {
return sizeof(T.self)
}
// FIXME: should be a constructor of UnsafePointer
func addressof<T>(x: @inout T) -> UnsafePointer<T> {
return UnsafePointer<T>(Builtin.addressof(&x))
@transparent
func alignof<T>(_:T.Type) -> Int {
return Int(Builtin.alignof(T.self))
}
@transparent
func alignofValue<T>(_:T) -> Int {
return alignof(T.self)
}
@transparent
func strideof<T>(_:T.Type) -> Int {
return Int(Builtin.strideof(T.self))
}
@transparent
func strideofValue<T>(_:T) -> Int {
return strideof(T.self)
}
func roundUpToAlignment(offset: Int, alignment: Int) -> Int {
return (offset + alignment - 1) / alignment * alignment
}
@transparent
func _canBeClass<T>(_: T.Type) -> Bool {
return Bool(Builtin.canBeClass(T.self))
}
/// A brutal bit-cast of something to anything of the same size
@transparent
func reinterpretCast<T, U>(var x: T) -> U {
assert(sizeof(T.self) == sizeof(U.self),
"can't reinterpretCast values of different sizes")
return UnsafePointer<U>(Builtin.addressof(&x)).get()
}
/// `reinterpretCast` something to `AnyObject`
@transparent
func _reinterpretCastToAnyObject<T>(x: T) -> AnyObject {
return reinterpretCast(x)
}
@transparent
func ==(lhs: Builtin.NativeObject, rhs: Builtin.NativeObject) -> Bool {
return (reinterpretCast(lhs) as Int) == (reinterpretCast(rhs) as Int)
}
@transparent
func !=(lhs: Builtin.NativeObject, rhs: Builtin.NativeObject) -> Bool {
return (reinterpretCast(lhs) as Int) != (reinterpretCast(rhs) as Int)
}
@transparent
func ==(lhs: Builtin.RawPointer, rhs: Builtin.RawPointer) -> Bool {
return (reinterpretCast(lhs) as Int) == (reinterpretCast(rhs) as Int)
}
@transparent
func !=(lhs: Builtin.RawPointer, rhs: Builtin.RawPointer) -> Bool {
return (reinterpretCast(lhs) as Int) != (reinterpretCast(rhs) as Int)
}
/// Tell the optimizer that this code is unreachable if condition is
/// known at compile-time to be true. If condition is false, or true
/// but not a compile-time constant, this call has no effect.
@transparent
func _unreachable(condition: Bool = true) {
if condition {
// FIXME: use a parameterized version of Builtin.unreachable when
// <rdar://problem/16806232> is closed.
Builtin.unreachable()
}
}
/// Tell the optimizer that this code is unreachable if this builtin is
/// reachable after constant folding build configuration builtins.
@transparent @noreturn
func _conditionallyUnreachable() {
Builtin.conditionallyUnreachable()
}
@asmname("swift_isClassOrObjCExistential")
func _swift_isClassOrObjCExistential<T>(x: T.Type) -> Bool
/// Returns true iff T is a class type
func _isClassOrObjCExistential<T>(x: T.Type) -> Bool {
return _canBeClass(x)
// FIXME: Dirty hack; see <rdar://problem/16823238>
&& sizeof(x) == sizeof(AnyObject)
&& _swift_isClassOrObjCExistential(x)
}
//===----------------------------------------------------------------------===//
// Branch hints
//===----------------------------------------------------------------------===//
@transparent
func _branchHint<C: LogicValue>(actual: C, expected: Bool) -> Bool {
return Bool(Builtin.int_expect_Int1(actual.getLogicValue().value, expected.value))
}
@transparent
func _fastPath<C: LogicValue>(x: C) -> Bool {
return _branchHint(x.getLogicValue(), true)
}
@transparent
func _slowPath<C: LogicValue>(x: C) -> Bool {
return _branchHint(x.getLogicValue(), false)
}

View File

@@ -1,20 +1,53 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// CString Type
//===----------------------------------------------------------------------===//
// XXX FIXME: we need a clean memory management story here
struct CString : BuiltinStringLiteralConvertible, StringLiteralConvertible{
struct CString :
_BuiltinExtendedGraphemeClusterLiteralConvertible,
ExtendedGraphemeClusterLiteralConvertible,
_BuiltinStringLiteralConvertible, StringLiteralConvertible,
ReplPrintable {
var _bytesPtr : UnsafePointer<UInt8>
static func _convertFromBuiltinStringLiteral(value : Builtin.RawPointer,
byteSize : Builtin.Int64,
isASCII : Builtin.Int1) -> CString {
return CString(UnsafePointer(value))
@transparent
init(_ _bytesPtr : UnsafePointer<UInt8>) {
self._bytesPtr = _bytesPtr
}
typealias StringLiteralType = CString
static func convertFromStringLiteral(value : CString) -> CString {
static func _convertFromBuiltinExtendedGraphemeClusterLiteral(
start: Builtin.RawPointer,
byteSize: Builtin.Word,
isASCII: Builtin.Int1) -> CString {
return _convertFromBuiltinStringLiteral(start, byteSize: byteSize,
isASCII: isASCII)
}
static func convertFromExtendedGraphemeClusterLiteral(
value: CString) -> CString {
return convertFromStringLiteral(value)
}
static func _convertFromBuiltinStringLiteral(start: Builtin.RawPointer,
byteSize: Builtin.Word,
isASCII: Builtin.Int1) -> CString {
return CString(UnsafePointer(start))
}
static func convertFromStringLiteral(value: CString) -> CString {
return value
}
@@ -23,63 +56,63 @@ struct CString : BuiltinStringLiteralConvertible, StringLiteralConvertible{
}
func replPrint() {
print('"')
print("\"")
var i = 0
while _bytesPtr[i] != 0 {
var c = Char(UInt32(_bytesPtr[i]))
c.replPrintCharBody()
var c = UnicodeScalar(UInt32(_bytesPtr[i]))
print(c.escape())
i++
}
print('"')
print("\"")
}
/// \brief From a CString with possibly-transient lifetime, create a
/// nul-terminated array of 'C' char.
func persist() -> CChar[] {
var length = _strlen(self)
var result = new CChar[length + 1]
for var i = 0; i < length; ++i {
result[i] = CChar(_bytesPtr[i])
}
return result
}
}
func [asmname="strlen"] _strlen(arg : CString) -> Word
func [asmname="strcpy"] _strcpy(dest : CString, src : CString) -> CString
@asmname("strlen")
func _strlen(arg : CString) -> Int
@asmname("strcpy")
func _strcpy(dest: CString, src: CString) -> CString
@asmname("strcmp")
func _strcmp(dest: CString, src: CString) -> Int
@transparent
func ==(lhs: CString, rhs: CString) -> Bool {
if lhs._bytesPtr == rhs._bytesPtr { return true }
return _strcmp(lhs, rhs) == 0
}
@transparent
func <(lhs: CString, rhs: CString) -> Bool {
return _strcmp(lhs, rhs) < 0
}
extension CString : Equatable, Hashable, Comparable {
@transparent
var hashValue: Int {
return String.fromCString(self).hashValue
}
}
extension String {
/// Creates a new String by copying the null-terminated data referenced by
/// a CString.
static func fromCString(cs : CString) -> String {
static func fromCString(cs: CString) -> String {
var len = Int(_strlen(cs))
var buf = StringByteData.getNew(len + 1)
_strcpy(CString(buf.base), cs)
buf.length = len
buf.setASCII(false)
buf.setCString(true)
return String(buf)
return String(UTF8.self,
input: UnsafeArray(start: cs._bytesPtr, length: len))
}
static func fromCString(up : UnsafePointer<CChar>) -> String {
static func fromCString(up: UnsafePointer<CChar>) -> String {
return fromCString(CString(UnsafePointer<UInt8>(up)))
}
func _toCString() -> CString {
assert(str_value.isCString())
return CString(str_value.base)
}
func _toUnsafePointer() -> UnsafePointer<CChar> {
assert(str_value.isCString())
return UnsafePointer(str_value.base)
}
}
extension LifetimeManager {
/// \brief Returns an equivalent CString; lifetime of the underlying storage
/// is extended until the call to \c release().
func getCString(s : String) -> CString {
s._makeNulTerminated()
this.put(s.str_value.owner)
return s._toCString()
}
/// \brief Returns an equivalent UnsafePointer<CChar>; lifetime of the
/// underlying storage is extended until the call to \c release().
func getCString(s : String) -> UnsafePointer<CChar> {
s._makeNulTerminated()
this.put(s.str_value.owner)
return s._toUnsafePointer()
}
}

View File

@@ -1,148 +1,148 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// C Primitive Types
//===----------------------------------------------------------------------===//
/// \brief The C 'char' type.
/// The C 'char' type.
///
/// This will be the same as either \c CSignedChar (in the common
/// case) or \c CUnsignedChar, depending on the platform.
/// This will be the same as either `CSignedChar` (in the common
/// case) or `CUnsignedChar`, depending on the platform.
typealias CChar = Int8
/// \brief The C 'unsigned char' type.
/// The C 'unsigned char' type.
typealias CUnsignedChar = UInt8
/// \brief The C 'unsigned short' type.
/// The C 'unsigned short' type.
typealias CUnsignedShort = UInt16
/// \brief The C 'unsigned int' type.
/// The C 'unsigned int' type.
typealias CUnsignedInt = UInt32
/// \brief The C 'unsigned long' type.
typealias CUnsignedLong = UInt64
/// The C 'unsigned long' type.
typealias CUnsignedLong = UInt
/// \brief The C 'unsigned long long' type.
/// The C 'unsigned long long' type.
typealias CUnsignedLongLong = UInt64
/// \brief The C 'unsigned __int128' extended integer type.
typealias CUnsignedInt128 = UInt128
/// \brief The C 'signed char' type.
/// The C 'signed char' type.
typealias CSignedChar = Int8
/// \brief The C 'short' type.
/// The C 'short' type.
typealias CShort = Int16
/// \brief The C 'int' type.
/// The C 'int' type.
typealias CInt = Int32
/// \brief The C 'long' type.
typealias CLong = Int64
/// The C 'long' type.
typealias CLong = Int
/// \brief The C 'long long' type.
/// The C 'long long' type.
typealias CLongLong = Int64
/// \brief The C '__int128' extended integer type.
typealias CInt128 = Int128
/// \brief The C 'float' type.
/// The C 'float' type.
typealias CFloat = Float
/// \brief The C 'double' type.
/// The C 'double' type.
typealias CDouble = Double
/// FIXME: long double
/// \brief The C++ 'wchar_t' type.
///
/// FIXME: Is it actually UTF-32 on Darwin?
typealias CWideChar = Char
// FIXME: Is it actually UTF-32 on Darwin?
//
/// The C++ 'wchar_t' type.
typealias CWideChar = UnicodeScalar
/// \brief The C++11 'char16_t' type, which has UTF-16 encoding.
///
/// FIXME: Swift should probably have a UTF-16 type other than UInt16.
// FIXME: Swift should probably have a UTF-16 type other than UInt16.
//
/// The C++11 'char16_t' type, which has UTF-16 encoding.
typealias CChar16 = UInt16
/// \brief The C++11 'char32_t' type, which has UTF-32 encoding.
typealias CChar32 = Char
/// The C++11 'char32_t' type, which has UTF-32 encoding.
typealias CChar32 = UnicodeScalar
/// \brief The C '_Bool' and C++ 'bool' type.
struct CBool {
var value : UInt8
/// The C '_Bool' and C++ 'bool' type.
typealias CBool = Bool
/// \brief Allow use in a Boolean context.
func getLogicValue() -> Bool {
if value == 0 {
return false
}
return true
}
/// \brief Implicit conversion from C Boolean type to Swift Boolean
/// type.
func [conversion] __conversion() -> Bool {
return getLogicValue()
}
}
extension Bool {
/// \brief Implicit conversion from Swift Boolean type to C Boolean
/// type.
func [conversion] __conversion() -> CBool {
var result : CBool
if this {
result.value = 1
} else {
result.value = 0
}
return result
}
}
/// \brief A wrapper around an opaque C pointer.
/// A wrapper around an opaque C pointer.
///
/// Opaque pointers are used to represent C pointers to types that
/// cannot be represented in Swift, such as incomplete struct types.
struct COpaquePointer : Equatable, Hashable {
var value : Builtin.RawPointer
init() {
var zero : Int = 0
value = Builtin.inttoptr_Word(zero.value)
}
init(_ v: Builtin.RawPointer) {
value = v
}
static func null() -> COpaquePointer {
return COpaquePointer()
}
/// \brief Determine whether the given pointer is null.
/// Determine whether the given pointer is null.
func isNull() -> Bool {
return this == COpaquePointer.null()
return self == COpaquePointer.null()
}
func __equal__(rhs : COpaquePointer) -> Bool {
return _getBool(Builtin.cmp_eq_RawPointer(value, rhs.value))
}
func hashValue() -> Int {
return Int(Builtin.ptrtoint_Int64(value))
var hashValue: Int {
return Int(Builtin.ptrtoint_Word(value))
}
}
func ==(lhs: COpaquePointer, rhs: COpaquePointer) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
extension COpaquePointer {
/// \brief Convert a typed UnsafePointer to an opaque C pointer.
/// FIXME: Make this an implicit conversion?
/// FIXME: This shouldn't have to be in an extension.
constructor<T>(from : UnsafePointer<T>) {
// FIXME: Make this an implicit conversion?
// FIXME: This shouldn't have to be in an extension.
//
/// Convert a typed UnsafePointer to an opaque C pointer.
init<T>(_ from : UnsafePointer<T>) {
value = from.value;
}
}
extension String {
/// Returns an UnsafePointer to the base address of the string without
/// copying. The pointed-to string is not guaranteed to be null terminated
/// so cannot be safely passed to APIs that require a C string.
func cAddress() -> UnsafePointer<CChar> {
return UnsafePointer(str_value.base.value)
// Make nil work with COpaquePointer.
extension _Nil {
@conversion func __conversion() -> COpaquePointer {
return COpaquePointer()
}
}
/// \brief Access to the raw argc value from C.
var C_ARGC : CInt
// The C va_list type
struct CVaListPointer {
var value: UnsafePointer<Void>
/// \brief Access to the raw argv value from C. Accessing the argument vector
init(fromUnsafePointer from: UnsafePointer<Void>) {
value = from
}
@conversion
func __conversion() -> CMutableVoidPointer {
return CMutableVoidPointer(owner: _nilNativeObject, value: value.value)
}
}
/// Access to the raw argc value from C.
var C_ARGC : CInt = CInt()
/// Access to the raw argv value from C. Accessing the argument vector
/// through this pointer is unsafe.
var C_ARGV : UnsafePointer<CString>
var C_ARGV : UnsafePointer<CString> = UnsafePointer<CString>()
@asmname("memcpy")
func c_memcpy(`dest: UnsafePointer<Void>, `src: UnsafePointer<Void>, `size: UInt)

View File

@@ -1,18 +1,65 @@
// \brief Character represents some Unicode grapheme cluster as
// defined by a canonical, localized, or otherwise tailored
// segmentation algorithm.
enum Character {
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct IntEncoder : Sink {
var asInt: UInt64 = 0
var shift: UInt64 = 0
mutating func put(x: UTF8.CodeUnit) {
asInt |= UInt64(x) << shift
shift += 8
}
}
/// \brief Character represents some Unicode grapheme cluster as
/// defined by a canonical, localized, or otherwise tailored
/// segmentation algorithm.
enum Character :
_BuiltinExtendedGraphemeClusterLiteralConvertible,
ExtendedGraphemeClusterLiteralConvertible, Equatable {
// Fundamentally, it is just a String, but it is optimized for the
// common case where the UTF-8 representation fits in 63 bits. The
// remaining bit is used to discriminate between small and large
// representations. In the small representation, the unused bytes
// are filled with 0xFF
case SmallRepresentation(Builtin.Int63)
// representations. In the small representation, the unused bytes
// are filled with 0xFF.
//
// If the grapheme cluster can be represented in SmallRepresentation, it
// should be represented as such.
case LargeRepresentation(OnHeap<String>)
case SmallRepresentation(Builtin.Int63)
init(s: String) {
var length = s.str_value.length
alwaysTrap(length > 0, "Can't form a Character from an empty String")
init(_ scalar: UnicodeScalar) {
var IE = IntEncoder()
UTF8.encode(scalar, output: &IE)
IE.asInt |= (~0) << IE.shift
self = SmallRepresentation(Builtin.trunc_Int64_Int63(IE.asInt.value))
}
static func _convertFromBuiltinExtendedGraphemeClusterLiteral(
start: Builtin.RawPointer,
byteSize: Builtin.Word,
isASCII: Builtin.Int1) -> Character {
return Character(
String._convertFromBuiltinExtendedGraphemeClusterLiteral(
start, byteSize: byteSize, isASCII: isASCII))
}
static func convertFromExtendedGraphemeClusterLiteral(
value: Character) -> Character {
return value
}
init(_ s: String) {
// The small representation can accept up to 8 code units as long
// as the last one is a continuation. Since the high bit of the
// last byte is used for the enum's discriminator, we have to
@@ -22,28 +69,29 @@ enum Character {
// one-byte code points there, we simplify decoding by banning
// starting a code point in the last byte, and assuming that its
// high bit is 1.
if length < 8 || ((length == 8) && (s.str_value[7] >= 0x80)) {
var asInt = -1 // Start with all bits set.
securityCheck(
s.core.count != 0, "Can't form a Character from an empty String")
// Read the string backwards, shifting code units into the low
// byte
while length-- != 0 {
asInt <<= 8
asInt |= Int(s.str_value[length])
}
self = SmallRepresentation(Builtin.trunc_Int64_Int63(asInt.value))
var (count, initialUTF8) = s.core._encodeSomeUTF8(0)
let bits = sizeofValue(initialUTF8) * 8 - 1
if _fastPath(
count == s.core.count && (initialUTF8 & (1 << numericCast(bits))) != 0) {
self = SmallRepresentation(Builtin.trunc_Int64_Int63(initialUTF8.value))
}
else {
self = LargeRepresentation(OnHeap(s))
}
}
/// \brief return the index of the lowest byte that is 0xFF, or 8 if
/// there is none
static func _smallSize(value: UInt64) -> Int {
var mask: UInt64 = 0xFF
for (var i = 0; i < 8; ++i) {
if (value & 0xFF) == 0xFF {
if (value & mask) == mask {
return i
}
value >>= 8
mask <<= 8
}
return 8
}
@@ -51,17 +99,35 @@ enum Character {
static func _smallValue(value: Builtin.Int63) -> UInt64 {
return UInt64(Builtin.zext_Int63_Int64(value)) | (1<<63)
}
}
func [conversion] __conversion() -> String {
switch self {
extension String {
init(_ c: Character) {
switch c {
case .SmallRepresentation(var _63bits):
var value = Character._smallValue(_63bits)
var size = Character._smallSize(value)
var resultBytes = StringByteData(size)
resultBytes.appendBytes(UnsafePointer(Builtin.addressof(&value)), size)
return String(resultBytes)
self = String(
UTF8.self,
input: UnsafeArray(
start: UnsafePointer<UTF8.CodeUnit>(Builtin.addressof(&value)),
length: size))
case .LargeRepresentation(var value):
return value
self = value
}
}
}
func ==(lhs: Character, rhs: Character) -> Bool {
switch (lhs, rhs) {
case (.LargeRepresentation(let lhsValue), .LargeRepresentation(let rhsValue)):
return lhsValue == rhsValue
case (.SmallRepresentation(let lhsValue), .SmallRepresentation(let rhsValue)):
return Character._smallValue(lhsValue) == Character._smallValue(rhsValue)
default:
return false
}
}

View File

@@ -30,14 +30,14 @@ import SwiftShims
protocol CocoaArray : ObjCClassType {
func objectAtIndex(index: Int) -> AnyObject
func getObjects(UnsafePointer<AnyObject>) range(_SwiftNSRange)
func getObjects(UnsafePointer<AnyObject>, range: _SwiftNSRange)
func countByEnumeratingWithState(
state: UnsafePointer<_SwiftNSFastEnumerationState>)
objects(buffer: UnsafePointer<AnyObject>)
count(len: Int) -> Int
state: UnsafePointer<_SwiftNSFastEnumerationState>,
objects buffer: UnsafePointer<AnyObject>,
count len: Int) -> Int
func copyWithZone(zone: COpaquePointer) -> CocoaArray
func copyWithZone(COpaquePointer) -> CocoaArray
var count: Int {get}
}
@@ -71,9 +71,7 @@ struct CocoaArrayWrapper : Collection {
/// implementation of countByEnumeratingWithState.
func contiguousStorage(subRange: Range<Int>) -> UnsafePointer<AnyObject>
{
var enumerationState = _SwiftNSFastEnumerationState(
0, nil, nil, (0,0,0,0,0))
var enumerationState = _makeSwiftNSFastEnumerationState()
// This function currently returns nil unless the first
// subRange.endIndex items are stored contiguously. This is an
@@ -87,6 +85,11 @@ struct CocoaArrayWrapper : Collection {
? reinterpretCast(enumerationState.itemsPtr) + subRange.startIndex : nil
}
@transparent
init(_ buffer: CocoaArray) {
self.buffer = buffer
}
var buffer: CocoaArray
}

View File

@@ -1,42 +1,86 @@
protocol _Collection {
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct _CountElements {}
func _countElements<Args>(a: Args) -> (_CountElements, Args) {
return (_CountElements(), a)
}
// Default implementation of countElements for Collections
// Do not use this operator directly; call countElements(x) instead
func ~> <T: _Collection>(x:T, _:(_CountElements,()))
-> T.IndexType.DistanceType
{
return distance(x.startIndex, x.endIndex)
}
/// Return the number of elements in x. O(1) if T.IndexType is
/// RandomAccessIndex; O(N) otherwise.
func countElements <T: _Collection>(x: T) -> T.IndexType.DistanceType {
return x~>_countElements()
}
protocol _Collection : _Sequence {
typealias IndexType : ForwardIndex
func startIndex() -> IndexType
func endIndex() -> IndexType
var startIndex: IndexType {get}
var endIndex: IndexType {get}
// The declaration of Element and _subscript here is a trick used to
// break a cyclic conformance/deduction that Swift can't handle. We
// need something other than a Collection.StreamType.Element that can
// be used as ContainedStream<T>'s Element. Here we arrange for the
// need something other than a Collection.GeneratorType.Element that can
// be used as IndexingGenerator<T>'s Element. Here we arrange for the
// Collection itself to have an Element type that's deducible from
// its __getitem__ function. Ideally we'd like to constrain this
// Element to be the same as Collection.StreamType.Element (see
// its subscript. Ideally we'd like to constrain this
// Element to be the same as Collection.GeneratorType.Element (see
// below), but we have no way of expressing it today.
typealias _Element
func __getitem__(i: IndexType) -> _Element
subscript(i: IndexType) -> _Element {get}
}
protocol Collection : _Collection, Sequence {
func __getitem__(i: IndexType) -> StreamType.Element
subscript(i: IndexType) -> GeneratorType.Element {get}
// Do not use this operator directly; call countElements(x) instead
func ~> (_:Self, _:(_CountElements, ())) -> IndexType.DistanceType
}
/// \brief A stream type that could serve for a Collection given that
/// it already had an IndexType. Because of <rdar://problem/14396120>
/// we've had to factor _Collection out of Collection to make it useful
struct ContainedStream<C: _Collection> : Stream {
init(seq: C) {
// Default implementation of underestimateCount for Collections. Do not
// use this operator directly; call underestimateCount(s) instead
func ~> <T: _Collection>(x:T,_:(_UnderestimateCount,())) -> Int {
return numericCast(x~>_countElements())
}
protocol MutableCollection : Collection {
subscript(i: IndexType) -> GeneratorType.Element {get set}
}
/// A stream type that could serve for a Collection given that
/// it already had an IndexType.
struct IndexingGenerator<C: _Collection> : Generator, Sequence {
// Because of <rdar://problem/14396120> we've had to factor _Collection out
// of Collection to make it useful.
init(_ seq: C) {
self._elements = seq
self._position = seq.startIndex()
self._position = seq.startIndex
}
func generate() -> ContainedStream {
func generate() -> IndexingGenerator {
return self
}
@mutating
func next() -> C._Element? {
return _position == _elements.endIndex()
? .None : .Some(_elements.__getitem__(_position++))
mutating func next() -> C._Element? {
return _position == _elements.endIndex
? .None : .Some(_elements[_position++])
}
var _elements: C
var _position: C.IndexType
@@ -44,98 +88,42 @@ struct ContainedStream<C: _Collection> : Stream {
func indices<
Seq : Collection>(seq: Seq) -> Range<Seq.IndexType> {
return Range(seq.startIndex(), seq.endIndex())
return Range(start: seq.startIndex, end: seq.endIndex)
}
struct IndexedStream<
struct IndexedGenerator<
Seq: Collection, Indices: Sequence
where Seq.IndexType == Indices.StreamType.Element
// FIXME: Commenting out "Stream," below causes all kinds of deserialization crashes
> : Stream, Sequence, MultiPassStream {
where Seq.IndexType == Indices.GeneratorType.Element
> : Generator, Sequence {
var seq : Seq
var indices : Indices.StreamType
var indices : Indices.GeneratorType
typealias Element = Seq.StreamType.Element
typealias Element = Seq.GeneratorType.Element
@mutating
func next() -> Element? {
mutating func next() -> Element? {
var result = indices.next()
return result ? seq.__getitem__(result!) : .None
return result ? seq[result!] : .None
}
// Every Stream is also a single-pass Sequence
typealias StreamType = IndexedStream
func generate() -> StreamType {
// Every Generator is also a single-pass Sequence
typealias GeneratorType = IndexedGenerator
func generate() -> GeneratorType {
return self
}
init(seq: Seq, indices: Indices) {
init(sequence seq: Seq, indices: Indices) {
self.seq = seq
self.indices = indices.generate()
}
}
/*
/// \brief Adapt an Collection into an Sequence
struct CollectionSequence<Seq: Collection>
: Sequence {
var seq : Seq
typealias StreamType = ForwardCollectionStream<Seq>
func generate() -> StreamType {
return StreamType(self.seq)
}
init(seq: Seq) {
self.seq = seq
}
}
struct ReverseCollection<
Seq: Collection
where Seq.IndexType: BidirectionalIndex
> : Collection {
var seq : Seq
typealias StreamType = CollectionStream<Seq>
func generate() -> StreamType {
return StreamType(self.seq)
}
init(seq: Seq) {
self.seq = seq
}
}
func elements<
Seq: Collection>(seq: Seq) -> CollectionSequence<Seq> {
return CollectionSequence(seq)
}
func reverse<
Seq: Collection where Seq.IndexType: BidirectionalIndex
>(seq: Seq) -> ReverseCollectionSequence<Seq> {
return ReverseCollectionSequence(seq)
}
func reverse<
Seq: Collection where Seq.IndexType: BidirectionalIndex
>(e: CollectionSequence<Seq>) -> ReverseCollectionSequence<Seq> {
return ReverseCollectionSequence(e.seq)
}
func reverse<
Seq: Collection where Seq.IndexType: BidirectionalIndex
>(e: ReverseCollectionSequence<Seq>) -> CollectionSequence<Seq> {
return CollectionSequence(e.seq)
}
*/
/// \brief A wrapper for a BidirectionalIndex that reverses its
/// A wrapper for a BidirectionalIndex that reverses its
/// direction of traversal
struct ReverseIndex<I: BidirectionalIndex> : BidirectionalIndex {
var _base: I
init(_ base: I) { self._base = base }
func succ() -> ReverseIndex {
return ReverseIndex(_base.pred())
}
@@ -151,171 +139,53 @@ func == <I> (lhs: ReverseIndex<I>, rhs: ReverseIndex<I>) -> Bool {
struct Reverse<T: Collection where T.IndexType: BidirectionalIndex> : Collection {
typealias IndexType = ReverseIndex<T.IndexType>
typealias StreamType = ContainedStream<Reverse>
typealias GeneratorType = IndexingGenerator<Reverse>
func generate() -> ContainedStream<Reverse> {
return ContainedStream(self)
init(_ base: T) {
self._base = base
}
func startIndex() -> IndexType {
return ReverseIndex(_base.endIndex())
func generate() -> IndexingGenerator<Reverse> {
return IndexingGenerator(self)
}
func endIndex() -> IndexType {
return ReverseIndex(_base.startIndex())
var startIndex: IndexType {
return ReverseIndex(_base.endIndex)
}
func __getitem__(i: IndexType) -> T.StreamType.Element {
return _base.__getitem__(i._base.pred())
var endIndex: IndexType {
return ReverseIndex(_base.startIndex)
}
subscript(i: IndexType) -> T.GeneratorType.Element {
return _base[i._base.pred()]
}
var _base: T
}
protocol Sliceable: Collection {
func __slice__(start: IndexType, finish: IndexType) -> Self
protocol _Sliceable : Collection {}
protocol Sliceable : _Sliceable {
// FIXME: SliceType should also be Sliceable but we can't express
// that constraint (<rdar://problem/14375973> Include associated
// type information in protocol witness tables) Instead we constrain
// to _Sliceable; at least error messages will be more informative.
typealias SliceType: _Sliceable
subscript(_: Range<IndexType>) -> SliceType {get}
}
func dropFirst<Seq : Sliceable>(seq: Seq) -> Seq {
return seq.__slice__(seq.startIndex().succ(), seq.endIndex())
protocol MutableSliceable : Sliceable, MutableCollection {
subscript(_: Range<IndexType>) -> SliceType {get set}
}
func dropFirst<Seq : Sliceable>(seq: Seq) -> Seq.SliceType {
return seq[seq.startIndex.succ()...seq.endIndex]
}
func dropLast<
Seq: Sliceable
where Seq.IndexType: BidirectionalIndex
>(seq: Seq) -> Seq {
return seq.__slice__(seq.startIndex(), seq.endIndex().pred())
}
protocol ForwardIndex : Equatable {
func succ() -> Self
}
@prefix @assignment @transparent
func ++ <T : ForwardIndex> (x: @inout T) -> T {
x = x.succ()
return x
}
@postfix @assignment @transparent
func ++ <T : ForwardIndex> (x: @inout T) -> T {
var ret = x
x = x.succ()
return ret
}
protocol BidirectionalIndex : ForwardIndex {
func pred() -> Self
}
@prefix @assignment @transparent
func -- <T: BidirectionalIndex> (x: @inout T) -> T {
x = x.pred()
return x
}
@postfix @assignment @transparent
func -- <T: BidirectionalIndex> (x: @inout T) -> T {
var ret = x
x = x.pred()
return ret
}
protocol RandomAccessIndex : BidirectionalIndex, NumericOperations {
typealias DistanceType
type func sub(lhs: Self, rhs: Self) -> (DistanceType, Bool)
type func sub(lhs: Self, rhs: DistanceType) -> (Self, Bool)
type func add(lhs: Self, rhs: DistanceType) -> (Self, Bool)
// FIXME: Disabled pending <rdar://problem/14011860> (Default
// implementations in protocols)
func <(lhs: Self, rhs: Self) -> Bool /* {
return (lhs.sub(rhs)).isNegative()
} */
}
@transparent
func - <T : RandomAccessIndex>(x: T, y: T) -> T.DistanceType {
var tmp : (T.DistanceType, Bool) = T.sub(x, y)
alwaysTrap(tmp.1 == false)
return tmp.0
}
@transparent
func &- <T : RandomAccessIndex>(x: T, y: T) -> T.DistanceType {
return T.sub(x, y).0
}
@transparent
func - <T : RandomAccessIndex>(x: T, y: T.DistanceType) -> T {
var tmp = T.sub(x, y)
alwaysTrap(tmp.1 == false)
return tmp.0
}
@transparent
func &- <T : RandomAccessIndex>(x: T, y: T.DistanceType) -> T {
return T.sub(x, y).0
}
@infix @assignment @transparent
func += <T : RandomAccessIndex> (lhs: @inout T, rhs: T.DistanceType) {
var tmp = T.add(lhs, rhs)
alwaysTrap(tmp.1 == false)
lhs = tmp.0
}
@infix @assignment @transparent
func -= <
T: RandomAccessIndex where T.DistanceType: SignedNumber
> (lhs: @inout T, rhs: T.DistanceType) {
var tmp = T.add(lhs, -rhs)
alwaysTrap(tmp.1 == false)
lhs = tmp.0
}
@transparent
func + <T : RandomAccessIndex> (lhs: T, rhs: T.DistanceType) -> T {
var tmp = T.add(lhs, rhs)
alwaysTrap(tmp.1 == false)
return tmp.0
}
@transparent
func + <T : RandomAccessIndex> (lhs: T.DistanceType, rhs: T) -> T {
var tmp = T.add(rhs, lhs)
alwaysTrap(tmp.1 == false)
return tmp.0
}
@transparent
func &+ <T : RandomAccessIndex> (lhs: T, rhs: T) -> T {
return T.add(lhs, rhs).0
}
@transparent
func &+ <T : RandomAccessIndex> (lhs: T, rhs: T.DistanceType) -> T {
return T.add(lhs, rhs).0
}
@transparent
func &+ <T : RandomAccessIndex> (lhs: T.DistanceType, rhs: T) -> T {
return T.add(rhs, lhs).0
}
@transparent
func - <T : RandomAccessIndex where T.DistanceType : SignedNumber> (
lhs: T, rhs: T.DistanceType)
-> T {
var tmp = T.add(lhs, -rhs)
alwaysTrap(tmp.1 == false)
return tmp.0
}
@transparent
func &- <T : RandomAccessIndex where T.DistanceType : SignedNumber> (
lhs: T, rhs: T.DistanceType)
-> T {
return T.add(lhs, -rhs).0
>(seq: Seq) -> Seq.SliceType {
return seq[seq.startIndex...seq.endIndex.pred()]
}

View File

@@ -11,6 +11,10 @@
//===----------------------------------------------------------------------===//
struct GeneratorOfOne<T> : Generator, Sequence {
init(_ elements: T?) {
self.elements = elements
}
func generate() -> GeneratorOfOne {
return self
}
@@ -27,11 +31,15 @@ struct GeneratorOfOne<T> : Generator, Sequence {
struct CollectionOfOne<T> : Collection {
typealias IndexType = Bit
func startIndex() -> IndexType {
init(_ element: T) {
self.element = element
}
var startIndex: IndexType {
return .zero
}
func endIndex() -> IndexType {
var endIndex: IndexType {
return .one
}
@@ -39,14 +47,17 @@ struct CollectionOfOne<T> : Collection {
return GeneratorOfOne(element)
}
func __getitem__(i: IndexType) -> T {
subscript(i: IndexType) -> T {
assert(i == .zero, "Index out of range")
return element
}
subscript(i: IndexType) -> T {
return __getitem__(i)
}
val element: T
let element: T
}
// Specialization of countElements for CollectionOfOne<T>
func ~> <T>(x:CollectionOfOne<T>, _:(_CountElements, ())) -> Int {
return 1
}

View File

@@ -1,126 +1,230 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Intrinsic protocols shared with the compiler
//===----------------------------------------------------------------------===//
/// \brief Protocol describing types that can be used as array bounds.
/// Protocol describing types that can be used as array bounds.
///
/// Types that conform to the \c ArrayBound protocol can be used as array bounds
/// by providing an operation (\c getArrayBoundValue) that produces an integral
/// Types that conform to the `ArrayBound` protocol can be used as array bounds
/// by providing an operation (`getArrayBoundValue`) that produces an integral
/// value.
protocol ArrayBound {
typealias ArrayBoundType
func getArrayBoundValue() -> ArrayBoundType
}
/// \brief Protocol describing types that can be used as logical values within
/// Protocol describing types that can be used as logical values within
/// a condition.
///
/// Types that conform to the \c LogicValue protocol can be used as
/// condition in various control statements (\c if, \c while, C-style
/// \c for) as well as other logical value contexts (e.g., case
/// Types that conform to the `LogicValue` protocol can be used as
/// condition in various control statements (`if`, `while`, C-style
/// `for`) as well as other logical value contexts (e.g., `case`
/// statement guards).
protocol LogicValue {
func getLogicValue() -> Bool
}
protocol Generator {
/// A `Generator` is a `Sequence` that is consumed when iterated.
///
/// While it is safe to copy a `Generator`, only one copy should be advanced
/// with `next()`.
///
/// If an algorithm requires two `Generator`\ s for the same `Sequence` to be
/// advanced at the same time, and the specific `Sequence` type supports
/// that, then those `Generator` objects should be obtained from `Sequence` by
/// two distinct calls to `generate(). However in that case the algorithm
/// should probably require `Collection`, since `Collection` implies
/// multi-pass.
protocol Generator /* : Sequence */ {
// FIXME: Refinement pending <rdar://problem/14396120>
typealias Element
func next() -> Element?
mutating func next() -> Element?
}
protocol Sequence {
/// The `for...in` loop operates on `Sequence`\ s. It is unspecified whether
/// `for...in` consumes the sequence on which it operates.
protocol _Sequence {
}
protocol _Sequence_ : _Sequence {
typealias GeneratorType : Generator
func enumerate() -> GeneratorType
func generate() -> GeneratorType
}
protocol Sequence : _Sequence_ {
typealias GeneratorType : Generator
func generate() -> GeneratorType
func ~> (_:Self,_:(_UnderestimateCount,())) -> Int
func ~>(
_:Self, _: (_CopyToNativeArrayBuffer, ())
) -> NativeArrayBuffer<Self.GeneratorType.Element>
}
struct _CopyToNativeArrayBuffer {}
func _copyToNativeArrayBuffer<Args>(args: Args)
-> (_CopyToNativeArrayBuffer, Args)
{
return (_CopyToNativeArrayBuffer(), args)
}
// Operation tags for underestimateCount. See Index.swift for an
// explanation of operation tags.
struct _UnderestimateCount {}
func _underestimateCount<Args>(args: Args) -> (_UnderestimateCount, Args) {
return (_UnderestimateCount(), args)
}
// Default implementation of underestimateCount for Sequences. Do not
// use this operator directly; call underestimateCount(s) instead
func ~> <T: _Sequence>(s: T,_:(_UnderestimateCount, ())) -> Int {
return 0
}
/// Return an underestimate of the number of elements in the given
/// sequence, without consuming the sequence. For Sequences that are
/// actually Collections, this will return countElements(x)
func underestimateCount<T: Sequence>(x: T) -> Int {
return x~>_underestimateCount()
}
// Pending <rdar://problem/14011860> and <rdar://problem/14396120>,
// pass a Generator through GeneratorSequence to give it "Sequence-ness"
struct GeneratorSequence<G: Generator> : Generator, Sequence {
init(_ base: G) {
_base = base
}
mutating func next() -> G.Element? {
return _base.next()
}
func generate() -> GeneratorSequence {
return self
}
var _base: G
}
protocol RawRepresentable {
typealias RawType
static func fromRaw(_: RawType) -> Self?
class func fromRaw(raw: RawType) -> Self?
func toRaw() -> RawType
}
// TODO: This is an incomplete implementation of our option sets vision.
protocol RawOptionSet : RawRepresentable, LogicValue
/*FIXME: , BitwiseOperations*/ {
typealias RawType : BitwiseOperations
// Workaround for our lack of circular conformance checking. Allow == to be
// defined on _RawOptionSet in order to satisfy the Equatable requirement of
// RawOptionSet without a circularity our type-checker can't yet handle.
protocol _RawOptionSet: RawRepresentable {
typealias RawType : BitwiseOperations, Equatable
}
// TODO: This is an incomplete implementation of our option sets vision.
protocol RawOptionSet : _RawOptionSet, LogicValue, Equatable
/*FIXME: , BitwiseOperations*/ {
// A non-failable version of RawRepresentable.fromRaw.
static func fromMask(_: RawType) -> Self
class func fromMask(raw: RawType) -> Self
// FIXME: Disabled pending <rdar://problem/14011860> (Default
// implementations in protocols)
// The Clang importer synthesizes these for imported NS_OPTIONS.
/* static func fromRaw(raw: RawType) -> Self? { return fromMask(raw) } */
/* class func fromRaw(raw: RawType) -> Self? { return fromMask(raw) } */
/* func getLogicValue() -> Bool { return toRaw() != .allZeros() } */
}
protocol BuiltinIntegerLiteralConvertible {
static func _convertFromBuiltinIntegerLiteral(
protocol _BuiltinIntegerLiteralConvertible {
class func _convertFromBuiltinIntegerLiteral(
value: MaxBuiltinIntegerType) -> Self
}
protocol IntegerLiteralConvertible {
typealias IntegerLiteralType : BuiltinIntegerLiteralConvertible
static func convertFromIntegerLiteral(value: IntegerLiteralType) -> Self
typealias IntegerLiteralType : _BuiltinIntegerLiteralConvertible
class func convertFromIntegerLiteral(value: IntegerLiteralType) -> Self
}
protocol BuiltinFloatLiteralConvertible {
static func _convertFromBuiltinFloatLiteral(
protocol _BuiltinFloatLiteralConvertible {
class func _convertFromBuiltinFloatLiteral(
value: MaxBuiltinFloatType) -> Self
}
protocol FloatLiteralConvertible {
typealias FloatLiteralType : BuiltinFloatLiteralConvertible
static func convertFromFloatLiteral(value: FloatLiteralType) -> Self
typealias FloatLiteralType : _BuiltinFloatLiteralConvertible
class func convertFromFloatLiteral(value: FloatLiteralType) -> Self
}
protocol BuiltinCharacterLiteralConvertible {
static func _convertFromBuiltinCharacterLiteral(value: Builtin.Int21) -> Self
protocol _BuiltinCharacterLiteralConvertible {
class func _convertFromBuiltinCharacterLiteral(value: Builtin.Int32) -> Self
}
protocol CharacterLiteralConvertible {
typealias CharacterLiteralType : BuiltinCharacterLiteralConvertible
static func convertFromCharacterLiteral(value: CharacterLiteralType) -> Self
typealias CharacterLiteralType : _BuiltinCharacterLiteralConvertible
class func convertFromCharacterLiteral(value: CharacterLiteralType) -> Self
}
protocol BuiltinStringLiteralConvertible {
static func _convertFromBuiltinStringLiteral(value: Builtin.RawPointer,
byteSize: Builtin.Int64,
protocol _BuiltinExtendedGraphemeClusterLiteralConvertible {
class func _convertFromBuiltinExtendedGraphemeClusterLiteral(
start: Builtin.RawPointer,
byteSize: Builtin.Word,
isASCII: Builtin.Int1) -> Self
}
protocol StringLiteralConvertible {
typealias StringLiteralType : BuiltinStringLiteralConvertible
static func convertFromStringLiteral(value: StringLiteralType) -> Self
protocol ExtendedGraphemeClusterLiteralConvertible {
typealias ExtendedGraphemeClusterLiteralType : _BuiltinExtendedGraphemeClusterLiteralConvertible
class func convertFromExtendedGraphemeClusterLiteral(
value: ExtendedGraphemeClusterLiteralType) -> Self
}
protocol _BuiltinStringLiteralConvertible : _BuiltinExtendedGraphemeClusterLiteralConvertible {
class func _convertFromBuiltinStringLiteral(start: Builtin.RawPointer,
byteSize: Builtin.Word,
isASCII: Builtin.Int1) -> Self
}
protocol _BuiltinUTF16StringLiteralConvertible : _BuiltinStringLiteralConvertible {
class func _convertFromBuiltinUTF16StringLiteral(
start: Builtin.RawPointer,
numberOfCodeUnits: Builtin.Word) -> Self
}
protocol StringLiteralConvertible : ExtendedGraphemeClusterLiteralConvertible {
// FIXME: when we have default function implementations in protocols, provide
// an implementation of convertFromExtendedGraphemeClusterLiteral().
typealias StringLiteralType : _BuiltinStringLiteralConvertible
class func convertFromStringLiteral(value: StringLiteralType) -> Self
}
protocol ArrayLiteralConvertible {
typealias Element
static func convertFromArrayLiteral(elements: Element...) -> Self
class func convertFromArrayLiteral(elements: Element...) -> Self
}
protocol DictionaryLiteralConvertible {
typealias Key
typealias Value
static func convertFromDictionaryLiteral(elements: (Key, Value)...) -> Self
class func convertFromDictionaryLiteral(elements: (Key, Value)...) -> Self
}
protocol StringInterpolationConvertible {
static func convertFromStringInterpolation(strings: Self...) -> Self
class func convertFromStringInterpolation(strings: Self...) -> Self
}
//===----------------------------------------------------------------------===//
// REPL protocols
//===----------------------------------------------------------------------===//
// FIXME: This should be intrinsically available for any metatype--need a
// metatype root type
protocol ClassNameable {
static func className() -> String
}
protocol ReplPrintable {
func replPrint()
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,48 +1,67 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//////////////////////////////////////////
// FIXME: Workaround for inability to create existentials of protocols
// with associated types <rdar://problem/11689181> and for the
// inability to constrain nested generics based on the containing type
// <rdar://problem/11700999>
//
// with associated types <rdar://problem/11689181>
// This file contains "existentials" for the protocols defined in
// Policy.swift. Similar components should usually be defined next to
// their respective protocols.
struct GeneratorOf<T> : Generator {
def next() -> T? {
struct GeneratorOf<T> : Generator, Sequence {
init(_ next: ()->T?) {
self._next = next
}
init<G: Generator where G.Element == T>(var _ self_: G) {
self._next = { self_.next() }
}
mutating func next() -> T? {
return _next()
}
var _next : ()->T?
}
def existential<G: Generator>(base: G)
-> GeneratorOf<G.Element>
{
return GeneratorOf( { base.next() } )
}
struct EnumerableOf<T> : Enumerable {
def enumerate() -> GeneratorOf<T> {
return _enumerate()
func generate() -> GeneratorOf {
return self
}
var _enumerate : ()->GeneratorOf<T>
let _next: ()->T?
}
def existential<E: Enumerable>(base: E)
-> EnumerableOf<E.GeneratorType.Element>
{
return EnumerableOf<E.GeneratorType.Element>(
{ existential(base.enumerate()) }
)
struct SequenceOf<T> : Sequence {
init<G: Generator where G.Element == T>(_ generate: ()->G) {
_generate = { GeneratorOf(generate()) }
}
init<S: Sequence where S.GeneratorType.Element == T>(_ self_: S) {
self = SequenceOf({ self_.generate() })
}
func generate() -> GeneratorOf<T> {
return _generate()
}
let _generate: ()->GeneratorOf<T>
}
struct SinkOf<T> : Sink {
def put(x: T) {
init(_ put: (T)->()) {
_put = put
}
init<S: Sink where S.Element == T>(var _ base: S) {
_put = { base.put($0) }
}
func put(x: T) {
_put(x)
}
var _put : (T)->()
let _put: (T)->()
}
def existential<S: Sink>(base: S) -> SinkOf<S.Element> {
return SinkOf( { base.put($0) } )
}

View File

@@ -1,6 +1,6 @@
@# -*- mode: swift -*-
%# -*- mode: swift -*-
@# Ignore the following admonition; it applies to the resulting .swift file only
%# Ignore the following admonition; it applies to the resulting .swift file only
//// Automatically Generated From FixedPoint.gyb. Do Not Edit Directly!
//===----------------------------------------------------------------------===//
//
@@ -14,7 +14,7 @@
//
//===----------------------------------------------------------------------===//
@{
%{
#
# Utility code for later in this template
#
@@ -65,62 +65,109 @@ def intName(name, signed):
def otherIntName(name, signed):
return ('U' if signed else '') + baseIntName(name)
}@
}%
typealias IntMax = Int${maxBits}
typealias UIntMax = UInt${maxBits}
@ for (name, bits, signed) in allInts():
@ (sign, ext) = ('s', 'sext') if signed else ('u', 'zext')
@ BuiltinName = builtinIntName(name)
@ Self = intName(name, signed)
@ OtherSelf = otherIntName(name, signed)
@ ConstructIntType = 'Int' if Self != 'Int' else ''
@ ArrayBound = 'ArrayBound, ' if bits <= 64 else ''
protocol _Integer
: _BuiltinIntegerLiteralConvertible,
IntegerLiteralConvertible,
ReplPrintable,
ArrayBound,
Hashable,
IntegerArithmetic,
BitwiseOperations,
_Incrementable
{
}
struct ${Self} : BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible,
${ArrayBound}ReplPrintable {
protocol Integer : _Integer, RandomAccessIndex {
}
protocol _SignedInteger : _Integer, SignedNumber {
func toIntMax() -> IntMax
class func from(IntMax) -> Self
}
protocol SignedInteger : _SignedInteger, Integer {
}
protocol _UnsignedInteger : _Integer {
func toUIntMax() -> UIntMax
class func from(UIntMax) -> Self
}
protocol UnsignedInteger : _UnsignedInteger, Integer {
}
func numericCast<T : _SignedInteger, U : _SignedInteger>(x: T) -> U {
return .from(x.toIntMax())
}
func numericCast<T : _UnsignedInteger, U : _UnsignedInteger>(x: T) -> U {
return .from(x.toUIntMax())
}
func numericCast<T : _SignedInteger, U : _UnsignedInteger>(x: T) -> U {
return .from(UIntMax(x.toIntMax()))
}
func numericCast<T : _UnsignedInteger, U : _SignedInteger>(x: T) -> U {
return .from(IntMax(x.toUIntMax()))
}
% for (name, bits, signed) in allInts():
% (sign, ext) = ('s', 'sext') if signed else ('u', 'zext')
% BuiltinName = builtinIntName(name)
% Self = intName(name, signed)
% OtherSelf = otherIntName(name, signed)
% ConstructIntType = 'Int' if Self != 'Int' else ''
struct ${Self} : ${'SignedInteger' if sign == 's' else 'UnsignedInteger'}
{
var value: Builtin.${BuiltinName}
@@transparent
@transparent
init() {
var maxWidthZero: IntMax = 0
value = Builtin.truncOrBitCast_Int${maxBits}_${BuiltinName}(maxWidthZero.value)
}
@@transparent
init(v: Builtin.${BuiltinName}) {
@transparent
init(_ v: Builtin.${BuiltinName}) {
value = v
}
@@transparent
@transparent
init(_ value: ${Self}) { self = value }
@transparent
static func _convertFromBuiltinIntegerLiteral(value: Builtin.Int${builtinIntLiteralBits}) -> ${Self} {
return ${Self}(Builtin.s_to_${sign}_checked_trunc_Int${builtinIntLiteralBits}_${BuiltinName}(value).0)
}
@@transparent
@transparent
static func convertFromIntegerLiteral(value: ${Self}) -> ${Self} {
return value
}
@ if ArrayBound:
@@transparent
@transparent
func _getBuiltinArrayBoundValue() -> Builtin.Word {
@ if bits < wordBits:
% if bits < wordBits:
return Builtin.${ext}OrBitCast_${BuiltinName}_Word(self.value)
@ elif bits > wordBits:
% elif bits > wordBits:
return Builtin.truncOrBitCast_${BuiltinName}_Word(self.value)
@ elif BuiltinName == 'Word':
% elif BuiltinName == 'Word':
return self.value
@ else:
% else:
return Builtin.${CastToWord}(self.value)
@ end
% end
}
typealias ArrayBoundType = ${Self}
func getArrayBoundValue() -> ${Self} {
return self
}
@ end
func replPrint() {
print(${
@@ -128,247 +175,236 @@ struct ${Self} : BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible,
else (('String' if bits > 64 else 'Int64' if signed else 'UInt64') + '(self)')})
}
@ max = maskBits((bits - 1) if signed else bits)
@@transparent
% max = maskBits((bits - 1) if signed else bits)
@transparent
static var max: ${Self} { return ${max} }
@@transparent
@transparent
static var min: ${Self} { return ${'-%s-1' % max if signed else '0'} }
}
extension ${Self} : Hashable {
func hashValue() -> Int {
@ if bits < wordBits:
var hashValue: Int {
% if bits < wordBits:
return Int(Builtin.sextOrBitCast_${BuiltinName}_Word(self.value))
@ elif bits > wordBits:
% elif bits > wordBits:
var result: Int = 0
for var i = 0; i < (sizeof(self) * 8); i += sizeof(Int.self) * 8 {
for var i = 0; i < (sizeofValue(self) * 8); i += sizeof(Int.self) * 8 {
result ^= Int(self >> ${Self}(i)) & ~0
}
return result
@ elif BuiltinName == 'Word':
% elif BuiltinName == 'Word':
return Int(self.value)
@ else:
% else:
return Int(Builtin.${CastToWord}(self.value))
@ end
% end
}
}
@@transparent
@transparent
extension ${Self} : RandomAccessIndex {
@@transparent
@transparent
func succ() -> ${Self} {
return self + 1
}
@@transparent
@transparent
func pred() -> ${Self} {
return self - 1
}
@@transparent
func distanceTo(other: ${Self}) -> Int {
return ${ConstructIntType}(other - self)
}
typealias DistanceType = ${Self}
@@transparent
static func sub(lhs: ${Self}, rhs: ${Self}, reportOverflow: Bool) -> (DistanceType, Bool) {
var tmp = Builtin.${sign}sub_with_overflow_${BuiltinName}(lhs.value, rhs.value, reportOverflow.value)
return (${Self}(tmp.0), Bool(tmp.1))
}
@@transparent
static func add(lhs: ${Self}, rhs: DistanceType, reportOverflow: Bool) -> (${Self}, Bool) {
var tmp = Builtin.${sign}add_with_overflow_${BuiltinName}(lhs.value, rhs.value, reportOverflow.value)
return (${Self}(tmp.0), Bool(tmp.1))
}
@@transparent
static func mul(lhs: ${Self}, rhs: ${Self}, reportOverflow: Bool) -> (${Self}, Bool) {
var tmp = Builtin.${sign}mul_with_overflow_${BuiltinName}(lhs.value, rhs.value, reportOverflow.value)
return (${Self}(tmp.0), Bool(tmp.1))
}
@@transparent
static func div(lhs: ${Self}, rhs: ${Self}, reportOverflow: Bool) -> (${Self}, Bool) {
if rhs == 0 {
return (0, true)
}
@ if signed:
if lhs == ${Self}.min && rhs == -1 {
return (lhs, true)
}
@ end
var tmp = Builtin.${sign}div_${BuiltinName}(lhs.value, rhs.value)
return (${Self}(tmp), false)
}
@@transparent
static func rem(lhs: ${Self}, rhs: ${Self}, reportOverflow: Bool) -> (${Self}, Bool) {
if rhs == 0 {
return (0, true)
}
@ if signed:
if lhs == ${Self}.min && rhs == -1 {
return (0, true)
}
@ end
var tmp = Builtin.${sign}rem_${BuiltinName}(lhs.value, rhs.value)
return (${Self}(tmp), false)
@transparent
func distanceTo(other: ${Self}) -> ${Self}.DistanceType {
return numericCast((numericCast(other) as IntMax) - numericCast(self))
}
@@transparent
static func sub(lhs: ${Self}, rhs: ${Self}) -> (DistanceType, Bool) {
return sub(lhs, rhs, true)
@transparent
func advancedBy(amount: ${Self}.DistanceType) -> ${Self} {
return numericCast((numericCast(self) as IntMax) + numericCast(amount))
}
@@transparent
static func add(lhs: ${Self}, rhs: DistanceType) -> (${Self}, Bool) {
return add(lhs, rhs, true)
% for Method,op in [('Add', 'add'), ('Subtract', 'sub'), ('Multiply', 'mul')]:
@transparent
static func unchecked${Method}(lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, Bool) {
var tmp = Builtin.${sign}${op}_with_overflow_${BuiltinName}(lhs.value, rhs.value, false.value)
return (${Self}(tmp.0), Bool(tmp.1))
}
@@transparent
static func mul(lhs: ${Self}, rhs: ${Self}) -> (${Self}, Bool) {
return mul(lhs, rhs, true)
% end
% for Method,op in [('Divide', 'div'), ('Modulus', 'rem')]:
@transparent
static func unchecked${Method}(lhs: ${Self}, _ rhs: ${Self}) -> (${Self}, Bool) {
if rhs == 0 {
return (0, true)
}
@@transparent
static func div(lhs: ${Self}, rhs: ${Self}) -> (${Self}, Bool) {
return div(lhs, rhs, true)
% if signed:
if lhs == ${Self}.min && rhs == -1 {
return (0, true)
}
@@transparent
static func rem(lhs: ${Self}, rhs: ${Self}) -> (${Self}, Bool) {
return rem(lhs, rhs, true)
% end
// FIXME: currently doesn't detect overflow -- blocked by:
// <rdar://15735295> Need [su]{div,rem}_with_overflow IR
var tmp = Builtin.${sign}${op}_${BuiltinName}(lhs.value, rhs.value)
return (${Self}(tmp), false)
}
@@transparent
%end
% U = '' if signed else 'U'
@transparent
func to${U}IntMax() -> ${U}IntMax {
return ${'self' if Self == U+'Int%s'%maxBits else U+'IntMax(self)'}
}
% if not signed:
func toIntMax() -> IntMax {
return ${'self' if Self == 'Int%s' % maxBits else 'IntMax(self)'}
return IntMax(toUIntMax())
}
% end
@transparent
static func from(x: ${U}IntMax) -> ${Self} {
return ${'x' if Self == U+'Int%s'%maxBits else Self+'(x)'}
}
}
@ if signed:
@@transparent
extension ${Self} : SignedNumber {
@@transparent
static func negate(rhs: ${Self}) -> (${Self}, Bool) {
return ${Self}.sub(0, rhs)
}
@@transparent
static func abs(rhs: ${Self}) -> (${Self}, Bool) {
return rhs.isNegative() ? ${Self}.negate(rhs) : (rhs, false)
}
@@transparent
func isNegative() -> Bool { return self < 0 }
}
@ end
% if signed:
@transparent
extension ${Self} : SignedNumber {}
% end
@# FIXME: checked conversions of Word types
%# FIXME: checked conversions of Word types
// construction from other integer types
@@transparent
@transparent
extension ${Self} {
@ for (srcName, srcBits, srcSigned) in allInts():
@ Src = intName(srcName, srcSigned)
@ srcBuiltinName = builtinIntName(srcName)
@ (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext')
@ if Self != Src:
init(v: ${Src}) {
@
@ if srcBuiltinName == 'Word':
% for (srcName, srcBits, srcSigned) in allInts():
% Src = intName(srcName, srcSigned)
% srcBuiltinName = builtinIntName(srcName)
% (srcSign, srcExt) = ('s', 'sext') if srcSigned else ('u', 'zext')
% if Self != Src:
init(_ v: ${Src}) {
%
% if srcBuiltinName == 'Word':
var srcNotWord = Builtin.${CastFromWord}(v.value)
@ else:
% else:
var srcNotWord = v.value
@ end
@
@ if srcBits == bits and srcSign == sign:
% end
%
% if srcBits == bits and srcSign == sign:
var dstNotWord = srcNotWord
@
@ elif srcBits == bits:
%
% elif srcBits == bits:
var tmp = Builtin.${srcSign}_to_${sign}_checked_conversion_Int${srcBits}(srcNotWord)
Builtin.condfail(tmp.1)
var dstNotWord = tmp.0
@
@ elif srcBits > bits:
%
% elif srcBits > bits:
var tmp = Builtin.${srcSign}_to_${sign}_checked_trunc_Int${srcBits}_Int${bits}(srcNotWord)
Builtin.condfail(tmp.1)
var dstNotWord = tmp.0
@
@ elif srcSigned and not signed:
%
% elif srcSigned and not signed:
var tmp = Builtin.s_to_u_checked_conversion_Int${srcBits}(srcNotWord)
Builtin.condfail(tmp.1)
var dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(tmp.0)
@
@ else:
%
% else:
var dstNotWord = Builtin.${srcExt}_Int${srcBits}_Int${bits}(srcNotWord)
@ end
@
@ if BuiltinName == 'Word':
% end
%
% if BuiltinName == 'Word':
value = Builtin.${CastToWord}(dstNotWord)
@ else:
% else:
value = dstNotWord
@ end
% end
}
@ end
@ end
% end
% end
func as${'Unsigned' if signed else 'Signed'}() -> ${OtherSelf} {
return ${OtherSelf}(value)
}
}
// Operations with masking and non-masking versions
@ for op,method in ('+','add'), ('*','mul'), ('-','sub'):
@@transparent
func &${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return ${Self}.${method}(lhs, rhs, false).0
}
@@transparent
// Operations with potentially-static overflow checking
//
// FIXME: must use condfail in these operators, rather than
// overflowChecked, pending <rdar://problem/16271923> so that we don't
// foil static checking for numeric overflows.
% for op,method in ('+','add'), ('*','mul'), ('-','sub'):
@transparent
func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
var tmp = ${Self}.${method}(lhs, rhs)
Builtin.condfail(tmp.1.value)
return tmp.0
let (result, error) = Builtin.${sign}${method}_with_overflow_${BuiltinName}(
lhs.value, rhs.value, true.value)
// return overflowChecked((${Self}(result), Bool(error)))
Builtin.condfail(error)
return ${Self}(result)
}
@ end
% end
% for op,inst in [('/', 'div'), ('%', 'rem')]:
@transparent
func ${op}(lhs: ${Self}, rhs: ${Self}) -> ${Self} {
Builtin.condfail((rhs == 0).value)
% if signed:
Builtin.condfail(((lhs == ${Self}.min) & (rhs == -1)).value)
% end
// FIXME: currently doesn't detect overflow -- blocked by:
// <rdar://15735295> Need [su]{div,rem}_with_overflow IR
var tmp = Builtin.${sign}${inst}_${BuiltinName}(lhs.value, rhs.value)
return ${Self}(tmp)
}
%end
// Bitwise negate
@@transparent @@prefix
@transparent @prefix
func ~(rhs: ${Self}) -> ${Self} {
let mask = ${Self}.sub(0, 1).0
let mask = ${Self}.uncheckedSubtract(0, 1).0
return ${Self}(Builtin.xor_${BuiltinName}(rhs.value, mask.value))
}
@ for op, name in (
@ ('==','eq'), ('!=','ne'),
@ ('<',sign+'lt'), ('<=',sign+'le'),
@ ('>',sign+'gt'), ('>=',sign+'ge')):
@@transparent
% for op, name in (
% ('==','eq'), ('!=','ne'),
% ('<',sign+'lt'), ('<=',sign+'le'),
% ('>',sign+'gt'), ('>=',sign+'ge')):
@transparent
func ${op} (lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.cmp_${name}_${BuiltinName}(lhs.value, rhs.value))
}
@ end
% end
@ for op, name in (('<<','shl'), ('>>','ashr' if signed else 'lshr')):
@@transparent
% for op, name in (('<<','shl'), ('>>','ashr' if signed else 'lshr')):
@transparent
func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
@ if signed:
assert(U${Self}(rhs) < U${Self}(sizeof(rhs) * 8))
@ else:
assert(rhs < ${Self}(sizeof(rhs) * 8))
@ end
% if signed:
assert(U${Self}(rhs) < U${Self}(sizeofValue(rhs) * 8))
% else:
assert(rhs < ${Self}(sizeofValue(rhs) * 8))
% end
return ${Self}(Builtin.${name}_${BuiltinName}(lhs.value, rhs.value))
}
@ end
% end
@ for op, name in (('&','and'), ('^','xor'), ('|','or')):
@@transparent
% for op, name in (('&','and'), ('^','xor'), ('|','or')):
@transparent
func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return ${Self}(Builtin.${name}_${BuiltinName}(lhs.value, rhs.value))
}
@ end
% end
// bitwise operations
@@transparent
@transparent
extension ${Self} : BitwiseOperations {
static func allZeros() -> ${Self} { return 0 }
}
// Compound assignments
@ for op in '+', '-', '*', '<<', '>>', '&', '|', '^':
@@transparent @@assignment
% for op in '+', '-', '*', '<<', '>>', '&', '|', '^':
@transparent @assignment
func ${op}=(inout lhs: ${Self}, rhs: ${Self}) {
lhs = lhs ${op} rhs
}
@ end
@ end # for bits in allInts
% end
% end # for bits in allInts
typealias Word = Int
typealias UWord = UInt
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:

View File

@@ -1,6 +1,6 @@
@# -*- mode: swift -*-
%# -*- mode: swift -*-
@# Ignore the following admonition; it applies to the resulting .swift file only
%# Ignore the following admonition; it applies to the resulting .swift file only
//// Automatically Generated From FloatingPoint.gyb. Do Not Edit Directly
//===----------------------------------------------------------------------===//
//
@@ -14,7 +14,7 @@
//
//===----------------------------------------------------------------------===//
@{
%{
#
# Utility code for later in this template
#
@@ -49,7 +49,12 @@ def intName(name, signed):
return ('' if signed else 'U') + baseIntName(name)
def floatName(bits):
return 'Float' + str(bits)
if bits == 32:
return 'Float'
if bits == 64:
return 'Double'
if bits == 80:
return 'Float80'
def cFuncSuffix(bits):
if bits == 32:
@@ -116,37 +121,40 @@ def getInfinityExponent(bits):
return '0x7ff'
return 'error'
}@
}%
@ for bits in allFloatBits:
@ Self = floatName(bits)
% for bits in allFloatBits:
% Self = floatName(bits)
struct ${Self} : ReplPrintable {
var value: Builtin.FPIEEE${bits}
@@transparent
@transparent
init() {
var zero: Int64 = 0
value = Builtin.uitofp_Int64_FPIEEE${bits}(zero.value)
}
@@transparent
init(v: Builtin.FPIEEE${bits}) {
@transparent
init(_ v: Builtin.FPIEEE${bits}) {
value = v
}
func replPrint() {
@if bits == 64:
%if bits == 64:
print(self)
@else:
%else:
print(Double(self))
@end
%end
}
@transparent
init(_ value: ${Self}) { self = value }
}
@ if bits in allIntBits:
% if bits in allIntBits:
// Not transparent because the compiler crashes in that case.
//@@transparent
//@transparent
extension ${Self} : FloatingPointNumber {
typealias _BitsType = UInt${bits}
@@ -283,10 +291,10 @@ extension ${Self} /* : FloatingPointNumber */ {
}
}
}
@ end
% end
@@transparent
extension ${Self} : BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible {
@transparent
extension ${Self} : _BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible {
static func _convertFromBuiltinIntegerLiteral(value: Builtin.Int${builtinIntLiteralBits}) -> ${Self} {
return ${Self}(Builtin.itofp_with_overflow_Int${builtinIntLiteralBits}_FPIEEE${bits}(value))
}
@@ -296,65 +304,65 @@ extension ${Self} : BuiltinIntegerLiteralConvertible, IntegerLiteralConvertible
}
}
@@transparent
extension ${Self} : BuiltinFloatLiteralConvertible {
@transparent
extension ${Self} : _BuiltinFloatLiteralConvertible {
static func _convertFromBuiltinFloatLiteral(value: Builtin.FPIEEE${builtinFloatLiteralBits}) -> ${Self} {
@ if bits == builtinFloatLiteralBits:
% if bits == builtinFloatLiteralBits:
return ${Self}(value)
@ elif bits < builtinFloatLiteralBits:
% elif bits < builtinFloatLiteralBits:
return ${Self}(Builtin.fptrunc_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
@ else:
% else:
// FIXME: This is actually losing precision <rdar://problem/14073102>.
return ${Self}(Builtin.fpext_FPIEEE${builtinFloatLiteralBits}_FPIEEE${bits}(value))
@ end
% end
}
}
@@transparent
@transparent
extension ${Self} : FloatLiteralConvertible {
static func convertFromFloatLiteral(value: ${Self}) -> ${Self} {
return value
}
}
@@transparent
@transparent
func ==(lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.fcmp_oeq_FPIEEE${bits}(lhs.value, rhs.value))
}
@@transparent
@transparent
func <(lhs: ${Self}, rhs: ${Self}) -> Bool {
return Bool(Builtin.fcmp_olt_FPIEEE${bits}(lhs.value, rhs.value))
}
@@transparent
@transparent
extension ${Self} : Comparable {
}
extension ${Self} : Hashable {
func hashValue() -> Int {
var hashValue: Int {
var asBuiltinInt = Builtin.bitcast_FPIEEE${bits}_Int${bits}(value)
@ if bits >= 64:
% if bits >= 64:
return Int(Builtin.truncOrBitCast_Int${bits}_Word(asBuiltinInt))
@ elif bits <= 32:
% elif bits <= 32:
return Int(Builtin.sextOrBitCast_Int${bits}_Word(asBuiltinInt))
@ else:
% else:
error unhandled float size ${bits}
@ end
% end
}
}
extension ${Self} : SignedNumber {
@@transparent
static func negate(rhs: ${Self}) -> (${Self}, Bool) {
return (${Self}(Builtin.fneg_FPIEEE${bits}(rhs.value)), false)
@transparent
extension ${Self} : AbsoluteValuable {
@transparent
static func abs(x: ${Self}) -> ${Self} {
return ${Self}(Builtin.int_fabs_FPIEEE${bits}(x.value))
}
@@transparent
static func abs(rhs: ${Self}) -> (${Self}, Bool) {
return (${Self}(Builtin.int_fabs_FPIEEE${bits}(rhs.value)), false)
}
@@transparent
func isNegative() -> Bool { return self < 0 }
}
@prefix @transparent
func -(x: ${Self}) -> ${Self} {
return ${Self}(Builtin.fneg_FPIEEE${bits}(x.value))
}
//===----------------------------------------------------------------------===//
@@ -362,33 +370,33 @@ extension ${Self} : SignedNumber {
//===----------------------------------------------------------------------===//
// Construction from integers.
@@transparent
@transparent
extension ${Self} {
@ for (srcBits, srcSigned) in allInts():
@ That = intName(srcBits, srcSigned)
@ ThatBuiltinName = builtinIntName(srcBits)
@ sign = 's' if srcSigned else 'u'
init(v: ${That}) {
% for (srcBits, srcSigned) in allInts():
% That = intName(srcBits, srcSigned)
% ThatBuiltinName = builtinIntName(srcBits)
% sign = 's' if srcSigned else 'u'
init(_ v: ${That}) {
value = Builtin.${sign}itofp_${ThatBuiltinName}_FPIEEE${bits}(v.value)
}
@ end
% end
}
// Construction from other floating point numbers.
@@transparent
@transparent
extension ${Self} {
@ for srcBits in allFloatBits:
@ That = floatName(srcBits)
@ if Self != That:
init(v: ${That}) {
@ if srcBits > bits:
% for srcBits in allFloatBits:
% That = floatName(srcBits)
% if Self != That:
init(_ v: ${That}) {
% if srcBits > bits:
value = Builtin.fptrunc_FPIEEE${srcBits}_FPIEEE${bits}(v.value)
@ else:
% else:
value = Builtin.fpext_FPIEEE${srcBits}_FPIEEE${bits}(v.value)
@ end
% end
}
@ end
@ end
% end
% end
}
//===----------------------------------------------------------------------===//
@@ -396,31 +404,57 @@ extension ${Self} {
//===----------------------------------------------------------------------===//
// Unary plus
@@transparent @@prefix
@transparent @prefix
func + (rhs: ${Self}) -> ${Self} { return rhs }
@@transparent @@prefix @@assignment
@transparent @prefix @assignment
func ++ (inout rhs: ${Self}) -> ${Self} { rhs += 1.0; return rhs }
@@transparent @@prefix @@assignment
@transparent @prefix @assignment
func -- (inout rhs: ${Self}) -> ${Self} { rhs -= 1.0; return rhs }
@@transparent @@postfix @@assignment
@transparent @postfix @assignment
func ++ (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs += 1.0; return tmp }
@@transparent @@postfix @@assignment
@transparent @postfix @assignment
func -- (inout lhs: ${Self}) -> ${Self} { let tmp = lhs; lhs -= 1.0; return tmp }
@ for op, name in ('+','fadd'), ('-','fsub'),('*','fmul'), ('/','fdiv'):
@@transparent
@transparent
extension ${Self} : RandomAccessIndex {
@transparent
func succ() -> ${Self} {
return self + 1.0
}
@transparent
func pred() -> ${Self} {
return self - 1.0
}
@transparent
func distanceTo(other: ${Self}) -> ${Self}.DistanceType {
return Int(other-self)
}
@transparent
func advancedBy(amount: ${Self}.DistanceType) -> ${Self} {
return self + ${Self}(amount)
}
}
% for op, name in ('+','fadd'), ('-','fsub'),('*','fmul'), ('/','fdiv'):
@transparent
func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} {
return ${Self}(Builtin.${name}_FPIEEE${bits}(lhs.value, rhs.value))
}
@ end
% end
// Binary Remainder.
// The sign of the result matches the sign of the dividend.
// 1) This is consistent with '%' in C#, D, Java, and JavaScript
// 2) C99 requires this behavior for fmod*()
// 3) C++11 requires this behavior for std::fmod*()
@@asmname="fmod${cFuncSuffix(bits)}"
@asmname("fmod${cFuncSuffix(bits)}")
func % (lhs: ${Self}, rhs: ${Self}) -> ${Self}
// See Bool.swift for && and ||
@@ -430,26 +464,32 @@ func % (lhs: ${Self}, rhs: ${Self}) -> ${Self}
// In C, 100 is ?:
// In C, 90 is =, *=, += etc.
@ for op in '+', '-', '*', '/', '%':
@@transparent @@assignment
% for op in '+', '-', '*', '/', '%':
@transparent @assignment
func ${op}= (inout lhs: ${Self}, rhs: ${Self}) { lhs = lhs ${op} rhs }
@ end
% end
@ end # for bits in allFloatBits
% end # for bits in allFloatBits
// Construction of integers from floating point numbers.
@ for (bits, signed) in allInts():
@ sign = 's' if signed else 'u'
@ Self = intName(bits, signed)
@ BuiltinName = builtinIntName(bits)
@@transparent
% for (bits, signed) in allInts():
% sign = 's' if signed else 'u'
% Self = intName(bits, signed)
% BuiltinName = builtinIntName(bits)
@transparent
extension ${Self} {
@ for srcBits in allFloatBits:
@ That = floatName(srcBits)
init(v: ${That}) {
% for srcBits in allFloatBits:
% That = floatName(srcBits)
init(_ v: ${That}) {
assert(v >= ${That}(${Self}.min))
assert(v <= ${That}(${Self}.max))
value = Builtin.fpto${sign}i_FPIEEE${srcBits}_${BuiltinName}(v.value)
}
@ end
% end
}
@ end
% end
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:

View File

@@ -1,4 +1,16 @@
enum IEEEFloatingPointClass {
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
enum FloatingPointClassification {
case SignalingNaN
case QuietNaN
case NegativeInfinity
@@ -12,19 +24,19 @@ enum IEEEFloatingPointClass {
}
extension IEEEFloatingPointClass : Equatable {}
func ==(lhs: IEEEFloatingPointClass, rhs: IEEEFloatingPointClass) -> Bool {
extension FloatingPointClassification : Equatable {}
func ==(lhs: FloatingPointClassification, rhs: FloatingPointClassification) -> Bool {
switch (lhs, rhs) {
case (.SignalingNaN, .SignalingNaN):
case (.QuietNaN, .QuietNaN):
case (.NegativeInfinity, .NegativeInfinity):
case (.NegativeNormal, .NegativeNormal):
case (.NegativeSubnormal, .NegativeSubnormal):
case (.NegativeZero, .NegativeZero):
case (.PositiveZero, .PositiveZero):
case (.PositiveSubnormal, .PositiveSubnormal):
case (.PositiveNormal, .PositiveNormal):
case (.PositiveInfinity, .PositiveInfinity):
case (.SignalingNaN, .SignalingNaN),
(.QuietNaN, .QuietNaN),
(.NegativeInfinity, .NegativeInfinity),
(.NegativeNormal, .NegativeNormal),
(.NegativeSubnormal, .NegativeSubnormal),
(.NegativeZero, .NegativeZero),
(.PositiveZero, .PositiveZero),
(.PositiveSubnormal, .PositiveSubnormal),
(.PositiveNormal, .PositiveNormal),
(.PositiveInfinity, .PositiveInfinity):
return true
default:
@@ -33,29 +45,27 @@ func ==(lhs: IEEEFloatingPointClass, rhs: IEEEFloatingPointClass) -> Bool {
}
protocol IEEEFloatingPointNumber {
protocol FloatingPointNumber {
typealias _BitsType
static func _fromBitPattern(bits: _BitsType) -> Self
class func _fromBitPattern(bits: _BitsType) -> Self
func _toBitPattern() -> _BitsType
// FIXME: make these readonly static properties.
/// Returns positive infinity.
static func inf() -> Self
class func inf() -> Self
/// Returns a quiet NaN.
static func NaN() -> Self
class func NaN() -> Self
static func quietNaN() -> Self
static func signalingNaN() -> Self
class func quietNaN() -> Self
/// @{
/// IEEE 754-2008 Non-computational operations.
// IEEE 754 calls this 'class', but this name is a keyword, and is too
// general.
// FIXME: make readonly.
var floatingPointClass: IEEEFloatingPointClass
var floatingPointClass: FloatingPointClassification { get }
/// Returns true if this number has a negative sign.
func isSignMinus() -> Bool

View File

@@ -1,13 +1,27 @@
// This is just here to provide a type off of which to hang swift_bufferAllocate.
class RawBuffer {}
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
func [asmname="swift_isUniquelyReferenced"]
swift_isUniquelyReferenced(objPtr: Builtin.ObjectPointer) -> CBool
import SwiftShims
typealias _HeapObject = SwiftShims.HeapObject
func [asmname="swift_bufferAllocate"]
swift_bufferAllocate(bufferType: RawBuffer.metatype, size: Int) -> RawBuffer
// Provides a common type off of which to hang swift_bufferAllocate.
@objc class HeapBufferStorageBase {}
func [asmname="swift_bufferHeaderSize"] swift_bufferHeaderSize() -> Int
@asmname("swift_bufferAllocate")
func swift_bufferAllocate(
bufferType: HeapBufferStorageBase.Type, size: Int) -> AnyObject
@asmname("malloc_size")
func c_malloc_size(heapMemory: UnsafePointer<Void>) -> Int
/// \brief a class containing an ivar "value" of type Value, and
/// containing storage for an array of Element whose size is
@@ -18,7 +32,8 @@ func [asmname="swift_bufferHeaderSize"] swift_bufferHeaderSize() -> Int
/// template <class Value, class Element>
/// struct HeapBuffer {
/// Value value;
/// Element[]; // length determined at creation time
/// Element elementStorage[]; // length determined at creation time
///
/// HeapBuffer() = delete
/// static shared_ptr<HeapBuffer> create(Value init, int capacity);
/// }
@@ -27,66 +42,162 @@ func [asmname="swift_bufferHeaderSize"] swift_bufferHeaderSize() -> Int
/// construct and---if necessary---destroy Elements there yourself,
/// either in a derived class, or it can be in some manager object
/// that owns the HeapBuffer.
///
/// If you need to construct and destroy Elements, using a derived
/// class is a natural choice. However, don't add any ivars because we
/// have no way in the runtime to get the base allocation size of an
/// arbitrary class. As a result, we will fail to allocate memory for
/// them, and their storage will collide with that of the stored
/// Value.
class HeapBuffer<Value,Element> : RawBuffer {
typealias Self = HeapBuffer<Value,Element>
static func roundUpToAlignment(offset: Int, alignment: Int) -> Int {
return (offset + alignment - 1) / alignment * alignment
@objc class HeapBufferStorage<Value,Element> : HeapBufferStorageBase {
typealias Buffer = HeapBuffer<Value, Element>
deinit {
Buffer(self)._value.destroy()
}
}
@asmname("_swift_isUniquelyReferenced")
func _swift_isUniquelyReferenced(_: UnsafePointer<HeapObject>) -> Bool
// Return true if x is the only (strong) reference to the given RawBuffer
//
// This is an inout function for two reasons:
//
// 1. You should only call it when about to mutate the object.
// Doing so otherwise implies a race condition if the buffer is
// shared across threads.
//
// 2. When it is not an inout function, self is passed by
// value... thus bumping the reference count and disturbing the
// result we are trying to observe, Dr. Heisenberg!
//
// NOTE: this is not as safe as it could be; class types that come
// from Cocoa don't have a reference count stored inline where we're
// checking for it. However, we have no way to restrict T to being a
// native Swift class, and in fact we have no reasonable way of
// getting a class pointer out of some other types, such as an enum
// whose first case is a native Swift object and is statically known
// to be in that case, without affecting its reference count. Instead
// we accept everything; reinterpretCast will at least catch
// inappropriately-sized things at runtime.
func isUniquelyReferenced<T>(inout x: T) -> Bool {
return _swift_isUniquelyReferenced(reinterpretCast(x))
}
struct HeapBuffer<Value, Element> : LogicValue, Equatable {
typealias Storage = HeapBufferStorage<Value, Element>
let storage: Storage?
static func _valueOffset() -> Int {
return roundUpToAlignment(
swift_bufferHeaderSize(), Int(Builtin.alignof(Value)))
return roundUpToAlignment(sizeof(_HeapObject.self), alignof(Value.self))
}
static func _elementOffset() -> Int {
return roundUpToAlignment(
_valueOffset() + Int(Builtin.sizeof(Value)), Int(Builtin.alignof(Element)))
return roundUpToAlignment(_valueOffset() + sizeof(Value.self),
alignof(Element.self))
}
var _address: UnsafePointer<Int8> {
return UnsafePointer<Int8>(
Builtin.bridgeToRawPointer(Builtin.castToObjectPointer(this)))
return UnsafePointer(
Builtin.bridgeToRawPointer(self as Builtin.NativeObject))
}
var _value: UnsafePointer<Value> {
return UnsafePointer<Value>(
Self._valueOffset() + _address)
return UnsafePointer(
HeapBuffer._valueOffset() + _address)
}
var elementStorage: UnsafePointer<Element> {
return UnsafePointer<Element>(Self._elementOffset() + _address)
return UnsafePointer(HeapBuffer._elementOffset() + _address)
}
static func create(initializer: Value, capacity: Int) -> Self {
/// \brief Return the actual number of Elements we can possibly
/// store.
func _capacity() -> Int {
let allocatedSize = c_malloc_size(UnsafePointer(_address))
return (allocatedSize - HeapBuffer._elementOffset())
/ Int(Builtin.strideof(Element.self))
}
init() {
self.storage = .None
}
init(_ storage: Storage) {
self.storage = storage
}
/// \brief Create a HeapBuffer with self.value = initializer and
/// self._capacity() >= capacity.
init(
_ storageClass: HeapBufferStorageBase.Type,
_ initializer: Value, _ capacity: Int
) {
assert(capacity >= 0)
var totalSize = Self._elementOffset() + (
capacity == 0 ? 0
: (capacity - 1) * Int(Builtin.strideof(Element))
+ Int(Builtin.sizeof(Element)))
let totalSize = HeapBuffer._elementOffset() +
capacity * Int(Builtin.strideof(Element.self))
var self = swift_bufferAllocate(Self, totalSize) as! Self
self._value.init(initializer)
return self
}
destructor {
this._value.destroy()
self.storage = reinterpretCast(
swift_bufferAllocate(storageClass, totalSize))
self._value.initialize(initializer)
}
var value : Value {
get:
get {
return _value.get()
set(newValue):
}
nonmutating set(newValue) {
_value.set(newValue)
}
}
func getLogicValue() -> Bool {
return storage.getLogicValue()
}
subscript(i: Int) -> Element {
get {
return elementStorage[i]
}
nonmutating set(newValue) {
elementStorage[i] = newValue
}
}
@conversion
func __conversion() -> Builtin.NativeObject {
return reinterpretCast(storage)
}
static func fromNativeObject(x: Builtin.NativeObject) -> HeapBuffer {
return HeapBuffer(Builtin.castFromNativeObject(x) as Storage)
}
mutating func isUniquelyReferenced() -> Bool {
if !storage {
return false
}
var workaroundForRadar16119895 = reinterpretCast(storage) as COpaquePointer
return Swift.isUniquelyReferenced(&workaroundForRadar16119895)
}
}
// HeapBuffers are equal when they reference the same buffer
func == <Value, Element> (
lhs: HeapBuffer<Value, Element>,
rhs: HeapBuffer<Value, Element>) -> Bool {
return (lhs as Builtin.NativeObject) == (rhs as Builtin.NativeObject)
}
// OnHeap<T>
//
// A way to store a value on the heap. These values are likely to be
// implicitly shared, so it's safest if they're immutable.
//
struct OnHeap<T> {
typealias Buffer = HeapBuffer<T, Void>
init(_ value: T) {
_storage = HeapBuffer(Buffer.Storage.self, value, 0)
}
@conversion func __conversion() -> T {
return _storage._value.get()
}
var _storage: Buffer
}

View File

@@ -27,7 +27,7 @@ struct ImplicitlyUnwrappedOptional<T>: LogicValue, Reflectable {
var value: T? = .None
init() { value = .None }
init(v : T?) { value = v }
init(_ v : T?) { value = v }
static var None : ImplicitlyUnwrappedOptional {
@transparent get {

View File

@@ -14,120 +14,252 @@
//
//===----------------------------------------------------------------------===//
protocol ForwardIndex : Equatable {
//===----------------------------------------------------------------------===//
//===--- Dispatching advance and distance functions -----------------------===//
// These generic functions are for user consumption; they dispatch to the
// appropriate implementation for T.
/// Measure the distance between start and end.
///
/// If T models RandomAccessIndex, requires that start and end are
/// part of the same sequence and executes in O(1).
///
/// Otherwise, requires that end is reachable from start by
/// incrementation, and executes in O(N), where N is the function's
/// result.
func distance<T: ForwardIndex>(start: T, end: T) -> T.DistanceType {
return start~>_distanceTo(end)
}
/// Return the result of moving start by n positions. If T models
/// RandomAccessIndex, executes in O(1). Otherwise, executes in
/// O(abs(n)). If T does not model BidirectionalIndex, requires that n
/// is non-negative.
func advance<T: ForwardIndex>(start: T, n: T.DistanceType) -> T {
return start~>_advance(n)
}
/// Return the result of moving start by n positions, or until it
/// equals end. If T models RandomAccessIndex, executes in O(1).
/// Otherwise, executes in O(abs(n)). If T does not model
/// BidirectionalIndex, requires that n is non-negative.
func advance<T: ForwardIndex>(start: T, n: T.DistanceType, end: T) -> T {
return start~>_advance(n, end)
}
/// Operation tags for distance and advance
///
/// Operation tags allow us to use a single operator (~>) for
/// dispatching every generic function with a default implementation.
/// Only authors of specialized distance implementations need to touch
/// this tag.
struct _Distance {}
func _distanceTo<I>(end: I) -> (_Distance, (I)) {
return (_Distance(), (end))
}
struct _Advance {}
func _advance<D>(n: D) -> (_Advance, (D)) {
return (_Advance(), (n: n))
}
func _advance<D, I>(n: D, end: I) -> (_Advance, (D, I)) {
return (_Advance(), (n, end))
}
//===----------------------------------------------------------------------===//
//===--- ForwardIndex -----------------------------------------------------===//
// Protocols with default implementations are broken into two parts, a
// base and a more-refined part. From the user's point-of-view,
// however, _ForwardIndex and ForwardIndex should look like a single
// protocol. This technique gets used throughout the standard library
// to break otherwise-cyclic protocol dependencies, which the compiler
// isn't yet smart enough to handle.
protocol _Incrementable : Equatable {
func succ() -> Self
}
protocol _ForwardIndex : _Incrementable {
typealias DistanceType : _SignedInteger = Int
}
@prefix @assignment @transparent
func ++ <T : ForwardIndex> (inout x: T) -> T {
func ++ <T : _Incrementable> (inout x: T) -> T {
x = x.succ()
return x
}
@postfix @assignment @transparent
func ++ <T : ForwardIndex> (inout x: T) -> T {
func ++ <T : _Incrementable> (inout x: T) -> T {
var ret = x
x = x.succ()
return ret
}
protocol BidirectionalIndex : ForwardIndex {
protocol ForwardIndex : _ForwardIndex {
// This requirement allows generic distance() to find default
// implementations. Only the author of F and the author of a
// refinement of F having a non-default distance implementation need
// to know about it. These refinements are expected to be rare
// (which is why defaulted requirements are a win)
// Do not use these operators directly; call distance(start, end)
// and advance(start, n) instead
func ~> (start:Self, _ : (_Distance, Self)) -> DistanceType
func ~> (start:Self, _ : (_Advance, DistanceType)) -> Self
func ~> (start:Self, _ : (_Advance, (DistanceType, Self))) -> Self
}
// advance and distance implementations
/// Do not use this operator directly; call distance(start, end) instead
func ~> <T: _ForwardIndex>(start:T, rest: (_Distance, T)) -> T.DistanceType {
var p = start
var count: T.DistanceType = 0
let end = rest.1
while p != end {
++count
++p
}
return count
}
/// Do not use this operator directly; call advance(start, n) instead
@transparent
func ~> <T: _ForwardIndex>(
start: T, rest: (_Advance, T.DistanceType)
) -> T {
let n = rest.1
return _advanceForward(start, n)
}
func _advanceForward<T: _ForwardIndex>(start: T, n: T.DistanceType) -> T {
assert(n >= 0, "Only BidirectionalIndex can be advanced by a negative amount")
var p = start
for var i: T.DistanceType = 0; i != n; ++i {
++p
}
return p
}
/// Do not use this operator directly; call advance(start, n, end) instead
@transparent
func ~> <T: _ForwardIndex>(
start:T, rest: ( _Advance, (T.DistanceType, T))
) -> T {
return _advanceForward(start, rest.1.0, rest.1.1)
}
func _advanceForward<T: _ForwardIndex>(
start: T, n: T.DistanceType, end: T
) -> T {
assert(n >= 0, "Only BidirectionalIndex can be advanced by a negative amount")
var p = start
for var i: T.DistanceType = 0; i != n && p != end; ++i {
++p
}
return p
}
//===----------------------------------------------------------------------===//
//===--- BidirectionalIndex -----------------------------------------------===//
protocol _BidirectionalIndex : _ForwardIndex {
func pred() -> Self
}
protocol BidirectionalIndex : ForwardIndex, _BidirectionalIndex {
}
@prefix @assignment @transparent
func -- <T: BidirectionalIndex> (inout x: T) -> T {
func -- <T: _BidirectionalIndex> (inout x: T) -> T {
x = x.pred()
return x
}
@postfix @assignment @transparent
func -- <T: BidirectionalIndex> (inout x: T) -> T {
func -- <T: _BidirectionalIndex> (inout x: T) -> T {
var ret = x
x = x.pred()
return ret
}
protocol RandomAccessIndex : BidirectionalIndex, NumericOperations {
typealias DistanceType
class func sub(lhs: Self, rhs: Self) -> (DistanceType, Bool)
class func sub(lhs: Self, rhs: DistanceType) -> (Self, Bool)
class func add(lhs: Self, rhs: DistanceType) -> (Self, Bool)
func < (lhs: Self, rhs: Self) -> Bool
func <= (lhs: Self, rhs: Self) -> Bool
func > (lhs: Self, rhs: Self) -> Bool
func >= (lhs: Self, rhs: Self) -> Bool
}
// advance implementation
/// Do not use this operator directly; call advance(start, n) instead
@transparent
func - <T : RandomAccessIndex>(x: T, y: T) -> T.DistanceType {
return overflowChecked(T.sub(x, y))
func ~> <T: _BidirectionalIndex>(
start:T , rest: (_Advance, T.DistanceType)
) -> T {
let n = rest.1
if n >= 0 {
return _advanceForward(start, n)
}
var p = start
for var i: T.DistanceType = n; i != 0; ++i {
--p
}
return p
}
/// Do not use this operator directly; call advance(start, n, end) instead
@transparent
func &- <T : RandomAccessIndex>(x: T, y: T) -> T.DistanceType {
return T.sub(x, y).0
func ~> <T: _BidirectionalIndex>(
start:T, rest: (_Advance, (T.DistanceType, T))
) -> T {
let n = rest.1.0
let end = rest.1.1
if n >= 0 {
return _advanceForward(start, n, end)
}
var p = start
for var i: T.DistanceType = n; i != 0 && p != end; ++i {
--p
}
return p
}
//===----------------------------------------------------------------------===//
//===--- RandomAccessIndex ------------------------------------------------===//
protocol _RandomAccessIndex : _BidirectionalIndex {
func distanceTo(Self) -> DistanceType
func advancedBy(DistanceType) -> Self
}
protocol RandomAccessIndex : BidirectionalIndex, _RandomAccessIndex {
/* typealias DistanceType : IntegerArithmetic*/
}
// advance and distance implementations
/// Do not use this operator directly; call distance(start, end) instead
@transparent
func - <T : RandomAccessIndex>(x: T, y: T.DistanceType) -> T {
return overflowChecked(T.sub(x, y))
func ~> <T: _RandomAccessIndex>(start:T, rest:(_Distance, (T)))
-> T.DistanceType {
let end = rest.1
return start.distanceTo(end)
}
/// Do not use this operator directly; call advance(start, n) instead
@transparent
func &- <T : RandomAccessIndex>(x: T, y: T.DistanceType) -> T {
return T.sub(x, y).0
}
@infix @assignment @transparent
func += <T : RandomAccessIndex> (inout lhs: T, rhs: T.DistanceType) {
lhs = overflowChecked(T.add(lhs, rhs))
}
@infix @assignment @transparent
func -= <
T: RandomAccessIndex where T.DistanceType: SignedNumber
> (inout lhs: T, rhs: T.DistanceType) {
lhs = overflowChecked(T.add(lhs, -rhs))
func ~> <T: _RandomAccessIndex>(
start:T, rest:(_Advance, (T.DistanceType))
) -> T {
let n = rest.1
return start.advancedBy(n)
}
/// Do not use this operator directly; call advance(start, n, end) instead
@transparent
func + <T : RandomAccessIndex> (lhs: T, rhs: T.DistanceType) -> T {
return overflowChecked(T.add(lhs, rhs))
func ~> <T: _RandomAccessIndex>(
start:T, rest:(_Advance, (T.DistanceType, T))
) -> T {
let n = rest.1.0
let end = rest.1.1
let d = start.distanceTo(end)
return (n > 0 ? d < n : d > n) ? end : start.advancedBy(n)
}
@transparent
func + <T : RandomAccessIndex> (lhs: T.DistanceType, rhs: T) -> T {
return overflowChecked(T.add(rhs, lhs))
}
@transparent
func &+ <T : RandomAccessIndex> (lhs: T, rhs: T) -> T {
return T.add(lhs, rhs).0
}
@transparent
func &+ <T : RandomAccessIndex> (lhs: T, rhs: T.DistanceType) -> T {
return T.add(lhs, rhs).0
}
@transparent
func &+ <T : RandomAccessIndex> (lhs: T.DistanceType, rhs: T) -> T {
return T.add(rhs, lhs).0
}
@transparent
func - <T : RandomAccessIndex where T.DistanceType : SignedNumber> (
lhs: T, rhs: T.DistanceType)
-> T {
return overflowChecked(T.add(lhs, -rhs))
}
@transparent
func &- <T : RandomAccessIndex where T.DistanceType : SignedNumber> (
lhs: T, rhs: T.DistanceType)
-> T {
return T.add(lhs, -rhs).0
}

View File

@@ -19,13 +19,13 @@
% (x[:-1], x[-1]) for x in
% 'Add+ Subtract- Multiply* Divide/ Modulus%'.split()]
protocol _NumericOperations {
protocol _IntegerArithmetic {
% for name,_ in integerBinaryOps:
class func unchecked${name}(lhs: Self, rhs: Self) -> (Self, Bool)
class func unchecked${name}(lhs: Self, _ rhs: Self) -> (Self, Bool)
% end
}
protocol NumericOperations : _NumericOperations, Comparable {
protocol IntegerArithmetic : _IntegerArithmetic, Comparable {
// Checked arithmetic functions. Specific implementations in
// FixedPoint.swift.gyb support static checking for integer types.
% for _,op in integerBinaryOps:
@@ -38,42 +38,84 @@ protocol NumericOperations : _NumericOperations, Comparable {
% for name,op in integerBinaryOps:
@transparent
func ${op} <T: _NumericOperations>(lhs: T, rhs: T) -> T {
func ${op} <T: _IntegerArithmetic>(lhs: T, rhs: T) -> T {
return overflowChecked(T.unchecked${name}(lhs, rhs))
}
@transparent
func &${op} <T: _NumericOperations>(lhs: T, rhs: T) -> T {
func &${op} <T: _IntegerArithmetic>(lhs: T, rhs: T) -> T {
return T.unchecked${name}(lhs, rhs).0
}
@assignment @transparent
func ${op}= <T: _NumericOperations>(inout lhs: T, rhs: T) {
func ${op}= <T: _IntegerArithmetic>(inout lhs: T, rhs: T) {
lhs = lhs ${op} rhs
}
% end
protocol SignedNumber {
class func uncheckedNegate(_: Self) -> (Self, Bool)
class func uncheckedAbs(_: Self) -> (Self, Bool)
func isNegative() -> Bool
//===--- SignedNumber -----------------------------------------------------===//
// A numeric type that supports abs(x), +x and -x
//===----------------------------------------------------------------------===//
// Base protocol containing all the non-defaulted implentations. This
// protocol should be presented to users as part of SignedNumber.
protocol _SignedNumber : Comparable, IntegerLiteralConvertible {
// Subtraction is a requirement for SignedNumber
@infix func - (lhs: Self, rhs: Self) -> Self
}
@transparent
func abs <T: SignedNumber>(x: T) -> T {
return overflowChecked(T.uncheckedAbs(x))
// SignedNumber itself contains only operator requirements having
// default implementations on the base protocol.
protocol SignedNumber : _SignedNumber {
@prefix func - (x: Self) -> Self
// Do not use this operator directly; call abs(x) instead
func ~> (_:Self,_:(_Abs, ())) -> Self
}
// Unary negation in terms of subtraction. This is a default
// implementation; models of SignedNumber can provide their own
// implementations.
@prefix @transparent
func - <T: SignedNumber>(x: T) -> T {
return overflowChecked(T.uncheckedNegate(x))
func - <T : _SignedNumber>(x: T) -> T {
return 0 - x
}
// Unary +
@prefix @transparent
func + <T: SignedNumber>(x: T) -> T {
func + <T: _SignedNumber>(x: T) -> T {
return x
}
//===--- abs(x) -----------------------------------------------------------===//
struct _Abs {}
func _abs<Args>(args: Args) -> (_Abs, Args) {
return (_Abs(), args)
}
// Do not use this operator directly; call abs(x) instead
@transparent
func ~> <T : _SignedNumber>(x:T,_:(_Abs, ())) -> T {
return x < 0 ? -x : x
}
protocol AbsoluteValuable : SignedNumber {
class func abs(_:Self) -> Self
}
// Do not use this operator directly; call abs(x) instead
@transparent
func ~> <T : AbsoluteValuable>(x:T,_:(_Abs, ())) -> T {
return T.abs(x)
}
// Absolute value. Concrete instances of SignedNumber can specialize
// this function by conforming to AbsoluteValuable.
@transparent
func abs<T : SignedNumber>(x: T) -> T {
return x~>_abs()
}
// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:

View File

@@ -1,5 +1,20 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// This function should be opaque to the optimizer.
func [asmname="swift_keepAlive"] swift_keepAlive(objPtr : Builtin.ObjectPointer)
// BLOCKED: <rdar://problem/16464507> This function will be unnecessary when
// fix_lifetime is honored by the ARC optimizer.
@asmname("swift_keepAlive")
func swift_keepAlive<T>(inout _: T)
/// \brief An instance of this struct keeps the references registered with it
/// at +1 reference count until the call to \c release().
@@ -11,31 +26,99 @@ func [asmname="swift_keepAlive"] swift_keepAlive(objPtr : Builtin.ObjectPointer)
/// This class can be used to extend lifetime of objects to pass UnsafePointers
/// to them to C APIs.
class LifetimeManager {
var _managedRefs : Vector<Builtin.ObjectPointer>
var _managedRefs : Builtin.NativeObject[]
var _releaseCalled : Bool
constructor() {
_managedRefs = Vector<Builtin.ObjectPointer>()
init() {
_managedRefs = Array<Builtin.NativeObject>()
_releaseCalled = false
}
destructor {
alwaysTrap(_releaseCalled, "release() should have been called")
deinit {
if !_releaseCalled {
fatal("release() should have been called")
}
}
func put(objPtr : Builtin.ObjectPointer) {
func put(objPtr: Builtin.NativeObject) {
_managedRefs.append(objPtr)
}
// FIXME: Need class constraints for this to work properly.
// func put<T>(obj : T) {
// put(Builtin.castToObjectPointer(obj))
// func put<T>(obj: T) {
// put(Builtin.castToNativeObject(obj))
// }
/// \brief Call this function to end the forced lifetime extension.
func release() {
swift_keepAlive(Builtin.castToObjectPointer(_managedRefs))
_fixLifetime(_managedRefs.owner)
_releaseCalled = true
}
}
/// \brief Evaluate f() and return its result, ensuring that x is not
/// destroyed before f returns.
func withExtendedLifetime<T, Result>(
x: T, f: ()->Result
) -> Result {
let result = f()
_fixLifetime(x)
return result
}
/// \brief Evaluate f(x) and return its result, ensuring that x is not
/// destroyed before f returns.
func withExtendedLifetime<T, Result>(
x: T, f: (T)->Result
) -> Result {
let result = f(x)
_fixLifetime(x)
return result
}
// FIXME: this function can die once <rdar://problem/14497260> (need
// support for CF bridging) is solved.
/// \brief Pass a given object as a COpaquePointer at +0 to the given
/// function, returning its result. This function is useful for
/// calling CoreFoundation functions on NS types that are toll-free
/// bridged; you have to declare these functions as taking
/// COpaquePointer, obviously.
func withObjectAtPlusZero<Result>(x: AnyObject, f: (COpaquePointer)->Result) -> Result {
return withExtendedLifetime(x) {
return f(
COpaquePointer(UnsafePointer<Void>(Builtin.bridgeToRawPointer(Builtin.castToNativeObject(x)))))
}
}
extension String {
/// \brief Invoke f on the contents of this string, represented as
/// a nul-terminated array of char, ensuring that the array's
/// lifetime extends through the execution of f
func withCString<Result>(
f: (CString)->Result
) -> Result {
var u8 = self.nulTerminatedUTF8()
return u8.buffer.withUnsafePointerToElements {
f(CString($0))
}
}
/// \brief Invoke f on the contents of this string, represented as
/// a nul-terminated array of char, ensuring that the array's
/// lifetime extends through the execution of f
func withCString<Result>(
f: (UnsafePointer<CChar>)->Result
) -> Result {
var u8 = self.nulTerminatedUTF8()
return u8.buffer.withUnsafePointerToElements {
f(UnsafePointer($0))
}
}
}
@transparent
func _fixLifetime<T>(var x: T) {
swift_keepAlive(&x)
}

View File

@@ -1,4 +1,14 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// LogicValue
//===----------------------------------------------------------------------===//

View File

@@ -9,20 +9,26 @@
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct MapGenerator<Base: Generator, T> : Generator, Sequence {
struct _MapGenerator<Base: Generator, T> : Generator, Sequence {
mutating func next() -> T? {
return base.next().map(transform)
}
func generate() -> MapGenerator {
func generate() -> _MapGenerator {
return self
}
init(_ base: Base, _ transform: (Base.Element)->T) {
self.base = base
self.transform = transform
}
var base: Base
var transform: (Base.Element)->T
}
struct Map<Base: Collection, T> : Collection {
struct _Map<Base: Collection, T> : Collection {
var startIndex: Base.IndexType {
return base.startIndex
}
@@ -35,8 +41,13 @@ struct Map<Base: Collection, T> : Collection {
return transform(base[index])
}
func generate() -> MapGenerator<Base.GeneratorType, T> {
return MapGenerator(base.generate(), transform)
func generate() -> _MapGenerator<Base.GeneratorType, T> {
return _MapGenerator(base.generate(), transform)
}
init(_ base: Base, transform: (Base.GeneratorType.Element)->T) {
self.base = base
self.transform = transform
}
var base: Base

View File

@@ -19,7 +19,7 @@
% for FloatSize in [32,64]:
% Types.append( ('Float'+str(FloatSize),'.Float','Double($0)') )
% Types.append(('String','.Text','$0'))
% Types.append(('Bool','.Text','"\($0)"'))
% Types.append(('Bool','.Logical','$0'))
% Types.append(('Int','.Int','Int64($0)'))
% for Type in Types:

View File

@@ -1,73 +1,73 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Extern C functions
//===----------------------------------------------------------------------===//
// FIXME: Once we have an FFI interface, make these have proper function bodies
// The C "abort" function
func [asmname="abort"] abort()
@asmname("abort") func _abort()
func [asmname="putchar"]
c_putchar(val : Int32)
func [asmname="print_int"]
c_print_int(p : Builtin.RawPointer, buf_len : Int, x : Int128, Radix : Int,
uppercase : Bool) -> UInt64
func [asmname="print_uint"]
c_print_uint(p : Builtin.RawPointer, buf_len : Int, x : UInt128, Radix : Int,
uppercase : Bool) -> UInt64
func [asmname="print_double"]
c_print_double(p : Builtin.RawPointer, x : Double) -> UInt64
@asmname("putchar")
func c_putchar(value: Int32)
@asmname("print_int")
func c_print_int(p: Builtin.RawPointer, buf_len: Int, x: Int64, Radix: Int,
uppercase: Bool) -> UInt64
@asmname("print_uint")
func c_print_uint(p: Builtin.RawPointer, buf_len: Int, x: UInt64, Radix: Int,
uppercase: Bool) -> UInt64
@asmname("print_double")
func c_print_double(p: Builtin.RawPointer, x: Double) -> UInt64
func [asmname="mach_absolute_time"] mach_absolute_time() -> UInt64
func [asmname="swift_replOutputIsUTF8"] _isUTF8() -> Bool
@asmname("swift_replOutputIsUTF8") func _isUTF8() -> Bool
// Some file stuff
func [asmname="swift_file_open"]
c_file_open(filename : CString) -> CInt
@asmname("write")
func posix_write(fd: Int32, buf: Builtin.RawPointer, sz: Int) -> Int
func [asmname="swift_file_close"]
c_file_close(fd : Int32) -> Int32
@asmname("read")
func posix_read(fd: Int32, buf: Builtin.RawPointer, sz: Int) -> Int
func [asmname="swift_file_read"]
c_file_read(fd : Int32, buf : Builtin.RawPointer, sz : Int) -> Int
@asmname("llvm.ctlz.i64")
func __llvm_ctlz(value: Builtin.Int64, isZeroUndef: Builtin.Int1) -> Builtin.Int64
func [asmname="swift_file_size"]
c_file_size(filename : Builtin.RawPointer) -> Int
@transparent func countLeadingZeros(value: Int64) -> Int64 {
return Int64(__llvm_ctlz(value.value, false.value))
}
func [asmname="swift_fd_size"]
c_fd_size(fd : Int32) -> Int
@transparent func _autorelease(x: AnyObject) {
Builtin.retain(x)
Builtin.autorelease(x)
}
func [asmname="opendir"]
posix_opendir_hack(dir : Builtin.RawPointer) -> Builtin.RawPointer
/// Check if a given object (of value or reference type) conforms to the given
/// protocol.
@asmname("swift_stdlib_conformsToProtocol")
func _stdlib_conformsToProtocol<SourceType, DestType>(
value: SourceType, _: DestType.Type
) -> Bool
func [asmname="posix_readdir_hack"]
posix_readdir_hack(handle : Builtin.RawPointer) -> (Builtin.RawPointer, Int)
/// Cast the given object (of value or reference type) to the given protocol
/// type. Traps if the object does not conform to the protocol.
@asmname("swift_stdlib_dynamicCastToExistential1Unconditional")
func _stdlib_dynamicCastToExistential1Unconditional<SourceType, DestType>(
value: SourceType, _: DestType.Type
) -> DestType
func [asmname="closedir"]
posix_closedir_hack(handle : Builtin.RawPointer)
/// Cast the given object (of value or reference type) to the given protocol
/// type. Returns `.None` if the object does not conform to the protocol.
@asmname("swift_stdlib_dynamicCastToExistential1")
func _stdlib_dynamicCastToExistential1<SourceType, DestType>(
value: SourceType, _: DestType.Type
) -> DestType?
func [asmname="posix_isDirectory_hack"]
posix_isDirectory_hack(handle : Builtin.RawPointer) -> Int
func [asmname="getchar"]
getchar() -> Int32
func [asmname="open"]
posix_open(filename : Builtin.RawPointer, mode : Int32, perm : Int) -> Int32
func [asmname="close"]
posix_close(fd : Int32) -> Int32
func [asmname="lseek"]
posix_seek(fd : Int32, offset : Int, whence : Int32) -> Int
func [asmname="write"]
posix_write(fd : Int32, buf : Builtin.RawPointer, sz : Int) -> Int
func [asmname="read"]
posix_read(fd : Int32, buf : Builtin.RawPointer, sz : Int) -> Int
func [asmname="dup"]
posix_dup(fd : Int32) -> Int32

View File

@@ -23,64 +23,68 @@ import SwiftShims
// design.
@objc
class NSSwiftArray : HeapBufferStorageBase, CocoaArray {
typealias Buffer = HeapBuffer<ArrayBody, AnyObject>
typealias Buffer = HeapBuffer<_ArrayBody, AnyObject>
// Note: This method must be overridden by subclasses, and would be
// marked @abstract if we had such a feature. Moreover, those
// subclasses must be generic, so we can't allow this method to be @objc
// (methods of generic classes can't be @objc), so we use a tuple in the
// signature to prevent the inference of @objc here.
func _objectAtIndex(indexAndUnused: (Int, Bool)) -> AnyObject {
assert(false, "_objectAtIndex must be overridden")
return self
var dynamicElementType: Any.Type {
fatal("This var must be overridden")
}
/// Returns the object located at the specified index.
func objectAtIndex(index: Int) -> AnyObject {
return _objectAtIndex((index, true))
let buffer = reinterpretCast(self) as Buffer
// If used as an NSArray, the element type can have no fancy
// bridging; just get it and return it
assert(buffer.value.elementTypeIsBridgedVerbatim)
return buffer[index]
}
// Copies the objects contained in the array that fall within the
// specified range to aBuffer.
func getObjects(aBuffer: UnsafePointer<AnyObject>, range: _SwiftNSRange) {
// These objects are "returned" at +0, so treat them as values to
// avoid retains.
var dst = UnsafePointer<Word>(aBuffer)
let buffer = reinterpretCast(self) as Buffer
// If used as an NSArray, the element type can have no fancy
// bridging; just get it and return it
assert(buffer.value.elementTypeIsBridgedVerbatim)
if _fastPath(buffer.value.elementTypeIsBridgedVerbatim) {
dst.initializeFrom(
UnsafePointer(buffer.elementStorage + range.location),
count: range.length)
}
func getObjects(
objects: UnsafePointer<AnyObject>)range(range: _SwiftNSRange) {
var dst = objects
for i in range.location...range.location + range.length {
dst++.initialize(_objectAtIndex((i, true)))
dst++.initialize(reinterpretCast(buffer[i]))
}
}
func copyWithZone(_: COpaquePointer) -> CocoaArray {
// Copy-on-write keeps us from modifying this as long as Cocoa can
// see it.
return self
}
func countByEnumeratingWithState(
state: UnsafePointer<_SwiftNSFastEnumerationState>)
objects(UnsafePointer<AnyObject>) count(bufferSize: Int)
-> Int {
state: UnsafePointer<_SwiftNSFastEnumerationState>,
objects: UnsafePointer<AnyObject>, count bufferSize: Int
) -> Int {
var enumerationState = state.get()
let my = reinterpretCast(self) as Buffer
if _fastPath(my.value.elementTypeIsBridgedVerbatim) {
let buffer = reinterpretCast(self) as Buffer
// If used as an NSArray, the element type can have no fancy
// bridging; just get it and return it
assert(buffer.value.elementTypeIsBridgedVerbatim)
if enumerationState.state != 0 {
return 0
}
enumerationState.mutationsPtr = reinterpretCast(self)
enumerationState.itemsPtr = reinterpretCast(my.elementStorage)
enumerationState.mutationsPtr = _fastEnumerationStorageMutationsPtr
enumerationState.itemsPtr = reinterpretCast(buffer.elementStorage)
enumerationState.state = 1
state.set(enumerationState)
return my.value.count
}
// FIXME: Could optimize away this copy if we have a buffer that
// already contains AnyObjects.
let firstItem = Int(enumerationState.state)
let numItemsToCopy = min(self.count - firstItem, bufferSize)
getObjects(objects, range:_SwiftNSRange(firstItem, numItemsToCopy))
enumerationState.mutationsPtr = reinterpretCast(self)
enumerationState.itemsPtr = reinterpretCast(objects)
enumerationState.state += CUnsignedLong(numItemsToCopy)
state.set(enumerationState)
return numItemsToCopy
return buffer.value.count
}
var count: Int {

View File

@@ -15,28 +15,20 @@ import SwiftShims
// The empty array prototype. We use the same object for all empty
// [Native]Array<T>s.
let emptyNSSwiftArray : NSSwiftArray
= reinterpretCast(NativeArrayBuffer<Int>(0,0))
= reinterpretCast(NativeArrayBuffer<Int>(count: 0, minimumCapacity: 0))
// The class that implements the storage for a NativeArray<T>
@final class NativeArrayStorage<T> : NSSwiftArray {
typealias Masquerade = HeapBufferStorage<ArrayBody,T>
typealias Buffer = NativeArrayBuffer<T>
deinit {
let b = HeapBuffer(
reinterpretCast(self) as Masquerade
)
for i in 0...b.value.count {
(b.elementStorage + i).destroy()
}
b._value.destroy()
let b = Buffer(self)
b.elementStorage.destroy(b.count)
b.base._value.destroy()
}
@override func _objectAtIndex(indexAndUnused: (Int, Bool)) -> AnyObject {
let index = indexAndUnused.0
let b = HeapBuffer(
reinterpretCast(self) as Masquerade
)
return bridgeToObjectiveC((b.elementStorage + index).get())!
override var dynamicElementType: Any.Type {
return T.self
}
}
@@ -49,22 +41,22 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
{
base = HeapBuffer(
NativeArrayStorage<T>.self,
ArrayBody(),
_ArrayBody(),
max(count, minimumCapacity))
base.value = ArrayBody(
count, base._capacity(), isBridgedVerbatimToObjectiveC(T.self))
var bridged = false
if _canBeClass(T.self) {
bridged = isBridgedVerbatimToObjectiveC(T.self)
}
init(storage: NativeArrayStorage<T>?) {
base.value = _ArrayBody(count: count, capacity: base._capacity(),
elementTypeIsBridgedVerbatim: bridged)
}
init(_ storage: NativeArrayStorage<T>?) {
base = reinterpretCast(storage)
}
/// Append x to this buffer, growing it by 1 element.
mutating func append(x: T) {
self += x
}
func getLogicValue() -> Bool {
return base.getLogicValue()
}
@@ -75,6 +67,12 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
return base ? base.elementStorage : nil
}
/// A pointer to the first element, assuming that the elements are stored
/// contiguously.
var _unsafeElementStorage: UnsafePointer<T> {
return base.elementStorage
}
func withUnsafePointerToElements<R>(body: (UnsafePointer<T>)->R) -> R {
let p = base.elementStorage
return withExtendedLifetime(base) { body(p) }
@@ -100,8 +98,8 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
}
/// Adopt the storage of x
init(other: NativeArrayBuffer) {
self = other
init(_ buffer: NativeArrayBuffer) {
self = buffer
}
mutating func requestUniqueMutableBuffer(minimumCapacity: Int)
@@ -117,21 +115,24 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
return self
}
/// Convert to a NativeArrayBuffer storing the same elements.
func toNativeBuffer() -> NativeArrayBuffer<Element> {
return self
}
/// Get/set the value of the ith element
subscript(i: Int) -> T {
get {
assert(i >= 0 && i < count, "Array index out of range")
return elementStorage[i]
// If the index is in bounds, we can assume we have storage.
return _unsafeElementStorage[i]
}
@!mutating
set {
nonmutating set {
assert(i >= 0 && i < count, "Array index out of range")
elementStorage[i] = newValue
// If the index is in bounds, we can assume we have storage.
// FIXME: Manually swap because it makes the ARC optimizer happy. See
// <rdar://problem/16831852> check retain/release order
// _unsafeElementStorage[i] = newValue
var nv = newValue
let tmp = nv
nv = _unsafeElementStorage[i]
_unsafeElementStorage[i] = tmp
}
}
@@ -140,8 +141,7 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
get {
return base ? base.value.count : 0
}
@!mutating
set {
nonmutating set {
assert(newValue >= 0)
assert(
@@ -176,6 +176,7 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
for i in subRange {
dst++.initialize(src++.get())
}
_fixLifetime(owner)
return dst
}
@@ -184,10 +185,10 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
subscript(subRange: Range<Int>) -> SliceBuffer<T>
{
return SliceBuffer(
base.storage,
elementStorage + subRange.startIndex,
subRange.endIndex - subRange.startIndex,
true)
owner: base.storage,
start: elementStorage + subRange.startIndex,
count: subRange.endIndex - subRange.startIndex,
hasNativeBuffer: true)
}
/// Return true iff this buffer's storage is uniquely-referenced.
@@ -204,13 +205,20 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
return true
}
/// Convert to an NSArray in O(1).
/// Precondition: isBridgedToObjectiveC(Element.self)
/// Convert to an NSArray.
/// Precondition: T is bridged to Objective-C
/// O(1) if T is bridged verbatim, O(N) otherwise
func asCocoaArray() -> CocoaArray {
assert(
isBridgedToObjectiveC(T.self),
"Array element type is not bridged to ObjectiveC")
return count > 0 ? reinterpretCast(base.storage) : emptyNSSwiftArray
if count == 0 {
return emptyNSSwiftArray
}
if _fastPath(base.value.elementTypeIsBridgedVerbatim) {
return reinterpretCast(base.storage)
}
return NativeArray(self).map { bridgeToObjectiveC($0)! }.buffer.storage!
}
/// An object that keeps the elements stored in this buffer alive
@@ -218,12 +226,23 @@ struct NativeArrayBuffer<T> : ArrayBufferType, LogicValue {
return storage
}
/// A value that identifies first mutable element, if any. Two
/// arrays compare === iff they are both empty, or if their buffers
/// have the same identity and count.
var identity: Word {
return reinterpretCast(elementStorage)
}
var dynamicElementType: Any.Type {
return storage ? storage!.dynamicElementType : T.self
}
//===--- private --------------------------------------------------------===//
var storage: NativeArrayStorage<T>? {
return reinterpretCast(base.storage)
}
typealias Base = HeapBuffer<ArrayBody,T>
typealias Base = HeapBuffer<_ArrayBody, T>
var base: Base
}
@@ -241,9 +260,11 @@ func += <
(lhs.elementStorage + oldCount).initializeFrom(rhs)
}
else {
let newLHS = NativeArrayBuffer<T>(newCount, lhs.capacity * 2)
let newLHS = NativeArrayBuffer<T>(count: newCount,
minimumCapacity: lhs.capacity * 2)
if lhs.base {
newLHS.elementStorage.moveInitializeFrom(lhs.elementStorage, oldCount)
newLHS.elementStorage.moveInitializeFrom(lhs.elementStorage,
count: oldCount)
lhs.base.value.count = 0
}
lhs.base = newLHS.base
@@ -283,7 +304,7 @@ extension NativeArrayBuffer : Collection {
func ~> <
S: _Sequence_
>(
source: S, _: (_AsNativeArrayBuffer,())
source: S, _: (_CopyToNativeArrayBuffer,())
) -> NativeArrayBuffer<S.GeneratorType.Element>
{
var result = NativeArrayBuffer<S.GeneratorType.Element>()
@@ -291,23 +312,21 @@ func ~> <
// Using GeneratorSequence here essentially promotes the sequence to
// a Sequence from _Sequence_ so we can iterate the elements
for x in GeneratorSequence(source.generate()) {
result.append(x)
result += x
}
return result.take()
}
func ~> <
// FIXME: <rdar://problem/16466357> prevents this from being ":
// Collection"
C: protocol<_Collection,_Sequence_>
C: Collection
>(
source: C, _:(_AsNativeArrayBuffer, ())
source: C, _:(_CopyToNativeArrayBuffer, ())
) -> NativeArrayBuffer<C.GeneratorType.Element>
{
return _collectionAsNativeArrayBuffer(source)
return _copyCollectionToNativeArrayBuffer(source)
}
func _collectionAsNativeArrayBuffer<C: protocol<_Collection,_Sequence_>>(
func _copyCollectionToNativeArrayBuffer<C: protocol<_Collection,_Sequence_>>(
source: C
) -> NativeArrayBuffer<C.GeneratorType.Element>
{
@@ -335,21 +354,3 @@ protocol _ArrayType : Collection {
typealias Buffer : ArrayBufferType
var buffer: Buffer {get}
}
/*
// FIXME: Disabled pending <rdar://problem/16509573>
func ~> <
A: _ArrayType where A.Buffer.Element == A.Buffer.GeneratorType.Element
>(
source: A, _:(_AsNativeArrayBuffer,())
) -> NativeArrayBuffer<A.Buffer.Element>
{
return _toNativeArrayBuffer(source.buffer)
}
*/
func asNativeArrayBuffer<S: Sequence>(source: S)
-> NativeArrayBuffer<S.GeneratorType.Element>
{
return source~>_asNativeArrayBuffer()
}

View File

@@ -1,12 +1,47 @@
@asmname="swift_makeUnsafeNil" func _makeUnsafeNil() -> AnyObject
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct _Nil {
@conversion func __conversion() -> AnyObject {
return _makeUnsafeNil()
struct _Nil : Reflectable {
@conversion func __conversion<T: RawOptionSet>() -> T {
return .fromMask(.allZeros())
}
func getMirror() -> Mirror {
return _NilMirror()
}
}
/// A null pointer constant.
/// A null sentinel value.
var nil : _Nil {
return _Nil()
}
struct _NilMirror : Mirror {
var value: Any { return nil }
var valueType: Any.Type { return (nil as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 0 }
subscript(i: Int) -> (String, Mirror) { fatal("a _NilMirror has no children") }
var summary: String { return "nil" }
var quickLookObject: QuickLookObject? { return .None }
var disposition: MirrorDisposition { return .Aggregate }
}

View File

@@ -1,109 +1,180 @@
/* Optional<T>
Until we have working oneof types, we have this library-based oneof.
*/
// Users should never touch this type directly.
struct __NoneType {
func getLogicValue() -> Bool { return false }
}
func [prefix] !(x: __NoneType) -> Bool { return true }
extension __NoneType : Equatable {
func __equal__(rhs: __NoneType) -> Bool {
return true
}
}
// This constant is for public consumption
var None: __NoneType {
return __NoneType()
}
/*
//===----------------------------------------------------------------------===//
//
// FIXME: Until Swift supports partial ordering of generic functions,
// these will cause ambiguities against more useful overloads like
// those interactions with Optional<T>. Keep them on ice until then.
// This source file is part of the Swift.org open source project
//
func == <T>(lhs: __NoneType, rhs: T) -> Bool {
return rhs.isNone()
}
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
func != <T>(lhs: __NoneType, rhs: Optional<T>) -> Bool {
return !rhs.isNone()
}
// The compiler has special knowledge of Optional<T>, including the fact that
// it is an enum with cases named 'None' and 'Some'.
enum Optional<T>: LogicValue,Reflectable {
case None
case Some(T)
func == <T>(lhs: Optional<T>, rhs: __NoneType) -> Bool {
return lhs.isNone()
}
init() { self = .None }
func != <T>(lhs: Optional<T>, rhs: __NoneType) -> Bool {
return !lhs.isNone()
}
init(_ some: T) { self = .Some(some) }
*/
struct Optional<T>: Enumerable, LogicValue {
typealias EnumeratorType = Slice<T>
func getEnumeratorType() -> Slice<T> { return value }
constructor() {}
constructor(x: T) {
value = new T[1]
value[0] = x
}
constructor(x: __NoneType) {}
/// \brief Allow use in a Boolean context.
/// Allow use in a Boolean context.
@transparent
func getLogicValue() -> Bool {
return value.length > 0
switch self {
case .Some:
return true
case .None:
return false
}
}
func isNone() -> Bool {
return !getLogicValue()
/// Haskell's fmap, which was mis-named
func map<U>(f: (T)->U) -> U? {
switch self {
case .Some(var y):
return .Some(f(y))
case .None:
return .None
}
}
func get() -> T {
assert(value.length > 0)
return value[0]
}
var value: T[]
}
// Emulate .Some(x) tag constructor to be delivered by oneof
func Some<T>(x: T) -> Optional<T> {
return Optional(x)
}
// FIXME: Has no effect pending <rdar://problem/13785669>
extension __NoneType {
func [conversion] __conversion<T> () -> Optional<T> {
return Optional(None)
func getMirror() -> Mirror {
return _OptionalMirror(self)
}
}
func [prefix] ! <T>(x: Optional<T>) -> Bool {
return !x.getLogicValue()
// While this free function may seem obsolete, since an optional is
// often expressed as (x as T), it can lead to cleaner usage, i.e.
//
// map(x as T) { ... }
// vs
// (x as T).map { ... }
//
/// Haskell's fmap for Optionals.
func map<T, U>(x: T?, f: (T)->U) -> U? {
switch x {
case .Some(var y):
return .Some(f(y))
case .None:
return .None
}
}
func == <T>(lhs: __NoneType, rhs: Optional<T>) -> Bool {
return rhs.isNone()
// Intrinsics for use by language features.
@transparent
func _doesOptionalHaveValue<T>(inout v: T?) -> Builtin.Int1 {
return v.getLogicValue().value
}
func != <T>(lhs: __NoneType, rhs: Optional<T>) -> Bool {
return !rhs.isNone()
@transparent
func _getOptionalValue<T>(v: T?) -> T {
switch v {
case .Some(var x):
return x
case .None:
fatal("Can't unwrap Optional.None")
}
}
func == <T>(lhs: Optional<T>, rhs: __NoneType) -> Bool {
return lhs.isNone()
@transparent
func _injectValueIntoOptional<T>(v: T) -> Optional<T> {
return .Some(v)
}
func != <T>(lhs: Optional<T>, rhs: __NoneType) -> Bool {
return !lhs.isNone()
@transparent
func _injectNothingIntoOptional<T>() -> Optional<T> {
return .None
}
// Comparisons
func == <T: Equatable> (lhs: T?, rhs: T?) -> Bool {
switch (lhs,rhs) {
case (.Some(let l), .Some(let r)):
return l == r
case (.None, .None):
return true
default:
return false
}
}
func != <T: Equatable> (lhs: T?, rhs: T?) -> Bool {
return !(lhs == rhs)
}
struct _OptionalMirror<T> : Mirror {
let _value : Optional<T>
init(_ x : Optional<T>) {
_value = x
}
var value: Any { return _value }
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return _value ? 1 : 0 }
subscript(i: Int) -> (String, Mirror) {
switch (_value,i) {
case (.Some(let contents),0) : return ("Some",reflect(contents))
default: fatal("cannot extract this child index")
}
}
var summary: String {
switch _value {
case .Some(let contents): return reflect(contents).summary
default: return "nil"
}
}
var quickLookObject: QuickLookObject? { return .None }
var disposition: MirrorDisposition { return .Optional }
}
// FIXME: ordering comparison of Optionals disabled pending
func < <T: _Comparable> (lhs: T?, rhs: T?) -> Bool {
switch (lhs,rhs) {
case (.Some(let l), .Some(let r)):
return l < r
case (.None, .Some):
return true
default:
return false
}
}
func > <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
switch (lhs,rhs) {
case (.Some(let l), .Some(let r)):
return l > r
default:
return rhs < lhs
}
}
func <= <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
switch (lhs,rhs) {
case (.Some(let l), .Some(let r)):
return l <= r
default:
return !(rhs < lhs)
}
}
func >= <T: _Comparable>(lhs: T?, rhs: T?) -> Bool {
switch (lhs,rhs) {
case (.Some(let l), .Some(let r)):
return l >= r
default:
return !(lhs < rhs)
}
}

View File

@@ -1,113 +1,109 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// OutputStream and Formatting logic
//===----------------------------------------------------------------------===//
extension Bool : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
alwaysTrap(kind == 'v')
return Format(layout).printToString(String(this))
func format(kind: UnicodeScalar, layout: String) -> String {
securityCheck(kind == "v")
return Format(layout).printToString(String(self))
}
}
extension Int8 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
return Int64(this).format(kind, layout)
func format(kind: UnicodeScalar, layout: String) -> String {
return IntMax(self).format(kind, layout: layout)
}
}
extension UInt8 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
return UInt64(this).format(kind, layout)
func format(kind: UnicodeScalar, layout: String) -> String {
return UIntMax(self).format(kind, layout: layout)
}
}
extension Int16 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
return Int64(this).format(kind, layout)
func format(kind: UnicodeScalar, layout: String) -> String {
return IntMax(self).format(kind, layout: layout)
}
}
extension UInt16 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
return UInt64(this).format(kind, layout)
func format(kind: UnicodeScalar, layout: String) -> String {
return UIntMax(self).format(kind, layout: layout)
}
}
extension Int32 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
return Int64(this).format(kind, layout)
func format(kind: UnicodeScalar, layout: String) -> String {
return IntMax(self).format(kind, layout: layout)
}
}
extension UInt32 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
return UInt64(this).format(kind, layout)
func format(kind: UnicodeScalar, layout: String) -> String {
return UIntMax(self).format(kind, layout: layout)
}
}
extension Int64 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
var radix = 10
var uppercase = false
if kind == 'X' { uppercase = true; radix = 16 }
else if kind == 'x' { radix = 16 }
else if kind == 'o' { radix = 8 }
else if kind != 'v' { alwaysTrap() }
return Format(layout).printToString(
String(this, radix : radix, uppercase : uppercase))
extension Int : FormattedPrintable {
func format(kind: UnicodeScalar, layout: String) -> String {
return IntMax(self).format(kind, layout: layout)
}
}
extension UInt64 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
var radix = 10
var uppercase = false
if kind == 'X' { uppercase = true; radix = 16 }
else if kind == 'x' { radix = 16 }
else if kind == 'o' { radix = 8 }
else if kind != 'v' { alwaysTrap() }
return Format(layout).printToString(
String(this, radix : radix, uppercase : uppercase))
extension UInt : FormattedPrintable {
func format(kind: UnicodeScalar, layout: String) -> String {
return UIntMax(self).format(kind, layout: layout)
}
}
extension Int128 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
extension IntMax : FormattedPrintable {
func format(kind: UnicodeScalar, layout: String) -> String {
var radix = 10
var uppercase = false
if kind == 'X' { uppercase = true; radix = 16 }
else if kind == 'x' { radix = 16 }
else if kind == 'o' { radix = 8 }
else if kind != 'v' { alwaysTrap() }
if kind == "X" { uppercase = true; radix = 16 }
else if kind == "x" { radix = 16 }
else if kind == "o" { radix = 8 }
else if kind != "v" { fatal("Invalid format chacacter") }
return Format(layout).printToString(
String(this, radix : radix, uppercase : uppercase))
String(self, radix : radix, uppercase : uppercase))
}
}
extension UInt128 : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
extension UIntMax : FormattedPrintable {
func format(kind: UnicodeScalar, layout: String) -> String {
var radix = 10
var uppercase = false
if kind == 'X' { uppercase = true; radix = 16 }
else if kind == 'x' { radix = 16 }
else if kind == 'o' { radix = 8 }
else if kind != 'v' { alwaysTrap() }
if kind == "X" { uppercase = true; radix = 16 }
else if kind == "x" { radix = 16 }
else if kind == "o" { radix = 8 }
else if kind != "v" { fatal("Invalid format chacacter") }
return Format(layout).printToString(
String(this, radix : radix, uppercase : uppercase))
String(self, radix : radix, uppercase : uppercase))
}
}
extension Float : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
alwaysTrap(kind == 'v')
return Format(layout).printToString(String(this))
func format(kind: UnicodeScalar, layout: String) -> String {
securityCheck(kind == "v")
return Format(layout).printToString(String(self))
}
}
extension Double : FormattedPrintable {
func format(kind : Char, layout : String) -> String {
alwaysTrap(kind == 'v')
return Format(layout).printToString(String(this))
func format(kind: UnicodeScalar, layout: String) -> String {
securityCheck(kind == "v")
return Format(layout).printToString(String(self))
}
}
@@ -115,35 +111,32 @@ extension Double : FormattedPrintable {
// Formatted Printing
//===----------------------------------------------------------------------===//
struct Format {
struct Format : ReplPrintable {
var width : Int
var isValid : Bool
var leftJustify : Bool
constructor(layout : String) {
init(_ layout: String) {
isValid = true
leftJustify = false
width = 0
if !layout.isEmpty() {
if layout[0] == '-' {
leftJustify = true
layout = layout.substr(1)
}
if !layout.isEmpty() {
for c in layout.chars {
leftJustify = layout.startsWith("-")
var layoutSansJustification = layout.substr(leftJustify ? 1 : 0)
if !layoutSansJustification.isEmpty() {
for c in layoutSansJustification.unicodeScalars {
if !c.isDigit() {
isValid = false
break
}
width = width * 10 + Int(UInt32(c) - UInt32('0'))
width = width * 10 + Int(UInt32(c) - UInt32("0"))
}
}
}
}
func printString(s : String) {
func printString(s: String) {
/* Causes problems due to <rdar://problem/11529601>
if !isValid {
@@ -153,26 +146,28 @@ struct Format {
*/
var padding = max(width - s.size(), 0)
if !leftJustify {
for i in 0..padding { print(' ') }
for i in 0...padding { print(" ") }
}
print(s)
if leftJustify {
for i in 0..padding { print(' ') }
for i in 0...padding { print(" ") }
}
}
func printToString(s : String) -> String {
func printToString(s: String) -> String {
if !isValid {
return s
}
var r : String
var r: String
var padding = max(width - s.size(), 0)
if !leftJustify {
r = String(padding, ' ')
r = String(count: padding, character: " ")
} else {
r = String()
}
r = r + s
if leftJustify {
r = r + String(padding, ' ')
r = r + String(count: padding, character: " ")
}
return r
}
@@ -184,84 +179,120 @@ struct Format {
// Terminal input & output
class Console : Object {
func write(buf : UInt8[]) -> Int {
var r = posix_write(1, buf.base.value, buf.length)
alwaysTrap(r != -1)
@final class Console : OutputStreamable {
init() { }
func write(inout buf: UInt8[]) -> Int {
let count = buf.count
var r = 0
for var start = 0; start < count; start += 1024 {
let slice = buf[start...min(start + 1024, count)]
r = slice.withUnsafePointerToElements {
posix_write(1, $0.value, slice.count)
}
if r == -1 {
break
}
}
return r
}
func write(buf : String) -> Int {
var r = posix_write(1, buf.str_value.base.value, buf.length)
alwaysTrap(r != -1)
func write(buf: String) -> Int {
var r = 0
let p = buf.contiguousUTF8
if p != nil {
let r = posix_write(1, p.value, buf.core.count)
}
else {
var a = NativeArray<UInt8>(count: 1024, value: 0)
var count = 0
for u in buf.utf8 {
a[count++] = u
if count == a.count {
r = a.withUnsafePointerToElements {
posix_write(1, $0.value, count)
}
if r == -1 {
break
}
}
}
if count != 0 {
r = a.withUnsafePointerToElements {
posix_write(1, $0.value, count)
}
}
}
securityCheck(r != -1)
return r
}
func write(c : UInt8) {
func write(c: UInt8) {
var buf = new UInt8[1]
buf[0] = c
var r = write(buf)
alwaysTrap(r == 1)
var r = write(&buf)
securityCheck(r == 1)
}
}
var con : Console = Console()
protocol FormattedPrintable {
func format(kind : Char, layout : String) -> String
func format(kind: UnicodeScalar, layout: String) -> String
}
func splitFormat(format : String) -> (String, String, Char, String) {
var (before, afterPercent, foundPercent) = format.splitFirst('%')
func splitFormat(format: String) -> (String, String, UnicodeScalar, String) {
var (before, afterPercent, foundPercent) = format.splitFirst("%")
if !foundPercent {
return (before, "", Char(0), afterPercent)
return (before, "", UnicodeScalar(0), afterPercent)
}
var (layout, kind, after, found) = afterPercent.splitFirstIf({ $0.isAlpha() })
if !found {
return (before, "", Char(0), afterPercent)
return (before, "", UnicodeScalar(0), afterPercent)
}
return (before, layout, kind, after)
}
protocol OutputStreamable {
func write(buf : UInt8[]) -> Int
func write(inout buf: UInt8[]) -> Int
// FIXME: Add default implementation when language allows it:
func write(buf : String) -> Int
// {return write(buf.asUInt8())}
func write(buf: String) -> Int
// {return write(buf.asUTF8())}
}
// FIXME: Remove the FormattedPrintable[] overload if/when we can forward
// variadic arguments.
// BLOCKED: <rdar://problem/12134482> Can't forward variadic arguments
func printf(out : OutputStreamable, format : String, args : FormattedPrintable[]) {
func printf(out: OutputStreamable, format: String, args: FormattedPrintable[]) {
var index = 0
while !format.isEmpty() {
var (before, layout, kind, after) = splitFormat(format)
var remainingFormat = format
while !remainingFormat.isEmpty() {
var (before, layout, kind, after) = splitFormat(remainingFormat)
out.write(before)
if kind != Char(0) {
out.write(args[index++].format(kind, layout))
if kind != UnicodeScalar(0) {
out.write(args[index++].format(kind, layout: layout))
}
format = after
remainingFormat = after
}
}
func printf(out : OutputStreamable, format : String, args : FormattedPrintable...) {
func printf(out: OutputStreamable, format: String, args: FormattedPrintable...) {
printf(out, format, args)
}
func printf(format : String, args : FormattedPrintable...) {
func printf(format: String, args: FormattedPrintable...) {
printf(con, format, args)
}
// NOTE: the repl has builtin knowledge of this protocol
protocol ReplPrintable {
func replPrint()
}
// FIXME: This function shouldn't be necessary!
func replPrint<E : Enumerable requires E.EnumeratorType.Element: ReplPrintable>(s : E) {
print('[')
func replPrint<E : Sequence where E.GeneratorType.Element: ReplPrintable>(s: E) {
print("[")
var first = true
var total = 0
for i in s {
@@ -277,25 +308,42 @@ func replPrint<E : Enumerable requires E.EnumeratorType.Element: ReplPrintable>(
return
}
}
print(']')
print("]")
}
func print<E : Enumerable requires E.EnumeratorType.Element: ReplPrintable>(s : E) {
func print<E : Sequence where E.GeneratorType.Element: ReplPrintable>(s: E) {
replPrint(s)
}
// Some very basic output functions.
func [asmname="_TSs5printFT3valSi_T_"] print(val : Int)
func [asmname="_TSs5printFT3valSu_T_"] print(val : UInt64)
func [asmname="_TSs5printFT3valSd_T_"] print(val : Double)
func print(val : String) {
var len = val.byteLength()
for var i = 0; i < len; ++i {
c_putchar(Int32(val.str_value[i]))
}
@asmname("print_Int64") func print(value: Int64)
@asmname("print_UInt64") func print(value: UInt64)
@asmname("print_Double") func print(value: Double)
func print(value: Int) {
print(Int64(value))
}
func print(val : Char) {
var wc = UInt32(val)
func print(value: UInt) {
print(UInt64(value))
}
func print(value: Float) {
print(Double(value))
}
func print(value: String) {
value._encode(UTF8.self, output: SinkOf<UTF8.CodeUnit> {
c_putchar(Int32($0))
})
}
func print(value: Character) {
print(String(value))
}
func print(value: UnicodeScalar) {
var wc = UInt32(value)
if wc < 0x000080 {
c_putchar(Int32(wc))
return
@@ -317,12 +365,12 @@ func print(val : Char) {
c_putchar(Int32(0x80 | (wc & 0x00003F)))
return
}
// print(Char(0xFFFD))
alwaysTrap()
// print(UnicodeScalar(0xFFFD))
fatal("Invalid Unicode scalar")
}
func print(val : Bool) {
if val {
func print(value: Bool) {
if value {
print("true")
} else {
print("false")
@@ -330,40 +378,97 @@ func print(val : Bool) {
}
// Some derived output functions.
func println(val : Bool) {
print(val)
print('\n')
func println(value: Bool) {
print(value)
print("\n")
}
func println(val : Int) {
print(val)
print('\n')
func println(value: Int) {
print(Int64(value))
print("\n")
}
func println(val : UInt8) {
print(UInt64(val))
print('\n')
func println(value: UInt) {
print(UInt64(value))
print("\n")
}
func println(val : UInt16) {
print(UInt64(val))
print('\n')
func println(value: UInt8) {
print(UInt64(value))
print("\n")
}
func println(val : UInt32) {
print(UInt64(val))
print('\n')
func println(value: UInt16) {
print(UInt64(value))
print("\n")
}
func println(val : UInt64) {
print(val)
print('\n')
func println(value: UInt32) {
print(UInt64(value))
print("\n")
}
func println(val : Double) {
print(val)
print('\n')
func println(value: UInt64) {
print(value)
print("\n")
}
func println(val : String) {
print(val)
print('\n')
func println(value: Float) {
print(value)
print("\n")
}
func println(value: Double) {
print(value)
print("\n")
}
func println(value: String) {
print(value)
print("\n")
}
func println(val : Char) {
print(val)
print('\n')
func println(value: Character) {
print(value)
print("\n")
}
func println(value: UnicodeScalar) {
print(value)
print("\n")
}
func println() {
print("\n")
}
// FIXME: Proof-of-concept kludge to test the runtime basis for a generic
// print method.
/// The runtime has disgustingly inappropriate knowledge of this protocol. If
/// you change this, you must also change swift_printAny.
protocol Printable {
func printSelf()
}
extension Int : Printable {
func printSelf() {
print(self)
}
}
extension String : Printable {
func printSelf() {
print(self)
}
}
/// Print any Swift object, using its Printable conformance if it has one,
/// falling back to a default implementation.
@asmname("swift_printAny") func printAny<T>(x: T)
extension Array : Printable {
func printSelf() {
print("[")
if !isEmpty {
printAny(self[0])
for x in self[1...count] {
print(", ")
printAny(x)
}
}
print("]")
}
}

View File

@@ -1,328 +1,193 @@
// RUN: %swift %s -verify -parse-as-library
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Swift Standard Prolog Library.
//===----------------------------------------------------------------------===//
import SwiftShims
//===----------------------------------------------------------------------===//
// Standardized aliases
//===----------------------------------------------------------------------===//
typealias Void = ()
typealias Int = Int64
typealias UInt = UInt64
typealias Float = Float32
typealias Double = Float64
// FIXME/TBD: Consider adding "int", "double", etc as aliases for Int/Double.
// They violate the naming convention but lower the barrier to entry.
//===----------------------------------------------------------------------===//
// Default types for unconstrained number literals
// Aliases for floating point types
//===----------------------------------------------------------------------===//
// FIXME: it should be the other way round, Float = Float32, Double = Float64,
// but the type checker loses sugar currently, and ends up displaying 'FloatXX'
// in diagnostics.
typealias Float32 = Float
typealias Float64 = Double
//===----------------------------------------------------------------------===//
// Default types for unconstrained literals
//===----------------------------------------------------------------------===//
typealias IntegerLiteralType = Int
typealias FloatLiteralType = Double
typealias CharacterLiteralType = Char
// typealias CharacterLiteralType = ?
typealias ExtendedGraphemeClusterType = String
typealias StringLiteralType = String
//===----------------------------------------------------------------------===//
// Default types for unconstrained number literals
//===----------------------------------------------------------------------===//
typealias MaxBuiltinIntegerType = Builtin.Int128
// Integer literals are limited to 2048 bits.
// The intent is to have arbitrary-precision literals, but implementing that
// requires more work.
//
// Rationale: 1024 bits are enough to represent the absolute value of min/max
// IEEE Binary64, and we need 1 bit to represent the sign. Instead of using
// 1025, we use the next round number -- 2048.
typealias MaxBuiltinIntegerType = Builtin.Int2048
typealias MaxBuiltinFloatType = Builtin.FPIEEE64
//===----------------------------------------------------------------------===//
// Standard "typeof" function
//===----------------------------------------------------------------------===//
func typeof<T>(x:T) -> T.metatype { return Builtin.typeof(x) }
//===----------------------------------------------------------------------===//
// Standard protocols
//===----------------------------------------------------------------------===//
typealias Any = protocol<>
@class_protocol @objc
protocol AnyObject {}
// FIXME: These protocols are a workaround for
// <rdar://problem/13251236> remapping bound function type not
// implemented yet
protocol Callable {
typealias Arguments
typealias Result
func __call__(args: Arguments) -> Result
typealias AnyClass = AnyObject.Type
func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool {
switch (lhs, rhs) {
case (.Some(let l), .Some(let r)):
return Bool(Builtin.cmp_eq_RawPointer(
Builtin.bridgeToRawPointer(Builtin.castToNativeObject(l)),
Builtin.bridgeToRawPointer(Builtin.castToNativeObject(r))
))
case (.None, .None):
return true
default:
return false
}
}
protocol Predicate : Callable {
typealias Result : LogicValue
}
func apply<F: Callable>(f: F, args: F.Arguments) -> F.Result {
return f.__call__(args)
}
//
// Identifiable
//
protocol Identifiable {
func __eq__(rhs: This) -> Bool
}
func ===<T: Identifiable>(lhs: T, rhs: T) -> Bool {
return lhs.__eq__(rhs)
}
func !==<T: Identifiable>(lhs: T, rhs: T) -> Bool {
return !lhs.__eq__(rhs)
func !== (lhs: AnyObject?, rhs: AnyObject?) -> Bool {
return !(lhs === rhs)
}
//
// Equatable
//
protocol Equatable {
func __equal__(rhs: This) -> Bool
func == (lhs: Self, rhs: Self) -> Bool
}
func == <T: Equatable>(lhs: T, rhs: T) -> Bool {
return lhs.__equal__(rhs)
}
func != <T: Equatable>(lhs: T, rhs: T) -> Bool {
return !lhs.__equal__(rhs)
func != <T : Equatable>(lhs: T, rhs: T) -> Bool {
return !(lhs == rhs)
}
//
// Comparable
//
protocol Comparable : Equatable {
func __less__(rhs : This) -> Bool
}
func < <T: Comparable>(lhs: T, rhs: T) -> Bool {
return lhs.__less__(rhs)
}
func > <T: Comparable>(lhs: T, rhs: T) -> Bool {
return rhs.__less__(lhs)
}
func <= <T: Comparable>(lhs: T, rhs: T) -> Bool {
return !rhs.__less__(lhs)
}
func >= <T: Comparable>(lhs: T, rhs: T) -> Bool {
return !lhs.__less__(rhs)
protocol _Comparable {
func <(lhs: Self, rhs: Self) -> Bool
}
protocol ForwardIndex : Equatable {
func succ() -> This
func > <T : _Comparable>(lhs: T, rhs: T) -> Bool {
return rhs < lhs
}
func <= <T : _Comparable>(lhs: T, rhs: T) -> Bool {
return !(rhs < lhs)
}
func >= <T : _Comparable>(lhs: T, rhs: T) -> Bool {
return !(lhs < rhs)
}
func [prefix, assignment]
++ <T: ForwardIndex> (x: [byref] T)
-> T {
x = x.succ()
return x
protocol Comparable : _Comparable, Equatable {
func <=(lhs: Self, rhs: Self) -> Bool
func >=(lhs: Self, rhs: Self) -> Bool
func >(lhs: Self, rhs: Self) -> Bool
}
protocol BitwiseOperations {
func & (_: Self, _: Self) -> Self
func |(_: Self, _: Self) -> Self
func ^(_: Self, _: Self) -> Self
@prefix func ~(_: Self) -> Self
func [postfix, assignment]
++ <T: ForwardIndex> (x: [byref] T)
-> T {
var ret = x
x = x.succ()
return ret
}
protocol BidirectionalIndex : ForwardIndex {
func pred() -> This
}
func [prefix, assignment]
-- <T: BidirectionalIndex> (x: [byref] T)
-> T {
x = x.pred()
return x
}
func [postfix, assignment]
-- <T: BidirectionalIndex> (x: [byref] T)
-> T {
var ret = x
x = x.pred()
return ret
}
protocol RandomAccessIndex : BidirectionalIndex, Comparable {
typealias DistanceType
func __sub__(rhs: This) -> DistanceType
func __sub__(rhs: DistanceType) -> This
func __add__(offset: DistanceType) -> This
// FIXME: Disabled pending <rdar://problem/14011860> (Default
// implementations in protocols)
func __less__(rhs: This) -> Bool /* {
return (lhs.__sub__(rhs)).isNegative()
} */
}
func [infix] - <T: RandomAccessIndex>(x: T, y: T) -> T.DistanceType {
return x.__sub__(y)
}
func [infix] - <T: RandomAccessIndex>(x: T, y: T.DistanceType) -> T {
return x.__sub__(y)
}
protocol SignedNumber {
func __negate__() -> This
func isNegative() -> Bool
}
func [prefix] - <T: SignedNumber> (x: T) -> T {
return x.__negate__()
}
func [infix, assignment] +=
<T: RandomAccessIndex> (lhs: [byref] T, rhs: T.DistanceType) {
lhs = lhs.__add__(rhs)
}
func [infix, assignment] -= <
T: RandomAccessIndex requires T.DistanceType: SignedNumber
> (lhs: [byref] T, rhs: T.DistanceType) {
lhs = lhs.__add__(-rhs)
}
func [infix] +
<T: RandomAccessIndex> (lhs: T, rhs: T.DistanceType)
-> T {
return lhs.__add__(rhs)
}
func [infix] +
<T: RandomAccessIndex> (lhs: T.DistanceType, rhs: T)
-> T {
return rhs.__add__(lhs)
}
func [infix] -
<T: RandomAccessIndex requires T.DistanceType: SignedNumber> (
lhs: T, rhs: T.DistanceType)
-> T {
return lhs.__add__(-rhs)
/// The identity value for "|" and "^", and the fixed point for "&".
///
/// ::
///
/// x | allZeros() == x
/// x ^ allZeros() == x
/// x & allZeros() == allZeros()
/// x & ~allZeros() == x
///
///
/// FIXME: Should be a static property when we support those on protocols.
class func allZeros() -> Self
}
protocol Hashable : Equatable {
func hashValue() -> Int
/// Returns the hash value. The hash value is not guaranteed to be stable
/// across different invocations of the same program. Do not persist the hash
/// value across program runs.
var hashValue: Int { get }
}
/// \brief Protocol describing types that can be used as array bounds.
///
/// Types that conform to the \c ArrayBound protocol can be used as array bounds
/// by providing an operation (\c getArrayBoundValue) that produces an integral
/// value.
protocol ArrayBound {
typealias ArrayBoundType
func getArrayBoundValue() -> ArrayBoundType
}
/// \brief Protocol describing types that can be used as logical values within
/// a condition.
///
/// Types that conform to the \c LogicValue protocol can be used as
/// condition in various control statements (\c if, \c while, C-style
/// \c for) as well as other logical value contexts (e.g., case
/// statement guards).
protocol LogicValue {
func getLogicValue() -> Bool
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol Enumerator {
// The opposite of a Generator (like an Output Iterator)
protocol Sink {
typealias Element
func isEmpty() -> Bool
func next() -> Element
mutating func put(x: Element)
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol Enumerable {
typealias EnumeratorType : Enumerator
func getEnumeratorType() -> EnumeratorType
func == <T: _RawOptionSet>(a: T, b: T) -> Bool {
return a.toRaw() == b.toRaw()
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol BuiltinIntegerLiteralConvertible {
static func _convertFromBuiltinIntegerLiteral(
value : MaxBuiltinIntegerType) -> This
/* FIXME: These should be default implementations of the BitwiseOperations
conformance for RawOptionSet. */
func & <T: RawOptionSet>(a: T, b: T) -> T {
return T.fromMask(a.toRaw() & b.toRaw())
}
func | <T: RawOptionSet>(a: T, b: T) -> T {
return T.fromMask(a.toRaw() | b.toRaw())
}
func ^ <T: RawOptionSet>(a: T, b: T) -> T {
return T.fromMask(a.toRaw() ^ b.toRaw())
}
@prefix func ~ <T: RawOptionSet>(a: T) -> T {
return T.fromMask(~a.toRaw())
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol IntegerLiteralConvertible {
typealias IntegerLiteralType : BuiltinIntegerLiteralConvertible
static func convertFromIntegerLiteral(value : IntegerLiteralType) -> This
}
//===----------------------------------------------------------------------===//
// Standard pattern matching forms
//===----------------------------------------------------------------------===//
// NOTE: the compiler has builtin knowledge of this protocol
protocol BuiltinFloatLiteralConvertible {
static func _convertFromBuiltinFloatLiteral(
value : MaxBuiltinFloatType) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol FloatLiteralConvertible {
typealias FloatLiteralType : BuiltinFloatLiteralConvertible
static func convertFromFloatLiteral(value : FloatLiteralType) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol BuiltinCharacterLiteralConvertible {
static func _convertFromBuiltinCharacterLiteral(value : Builtin.Int32) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol CharacterLiteralConvertible {
typealias CharacterLiteralType : BuiltinCharacterLiteralConvertible
static func convertFromCharacterLiteral(value : CharacterLiteralType) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol BuiltinStringLiteralConvertible {
static func _convertFromBuiltinStringLiteral(value : Builtin.RawPointer,
byteSize : Builtin.Int64,
isASCII: Builtin.Int1) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol StringLiteralConvertible {
typealias StringLiteralType : BuiltinStringLiteralConvertible
static func convertFromStringLiteral(value : StringLiteralType) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol ArrayLiteralConvertible {
typealias Element
static func convertFromArrayLiteral(elements : Element...) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol DictionaryLiteralConvertible {
typealias Key
typealias Value
static func convertFromDictionaryLiteral(elements:(Key, Value)...) -> This
}
// NOTE: the compiler has builtin knowledge of this protocol
protocol StringInterpolationConvertible {
static func convertFromStringInterpolation(strings : This...) -> This
}
// NOTE: the repl has builtin knowledge of this protocol
// FIXME: This should be intrinsically available for any metatype--need a
// metatype root type
protocol ClassNameable {
static func className() -> String
// Equatable types can be matched in patterns by value equality.
@transparent @infix
func ~= <T : Equatable> (a: T, b: T) -> Bool {
return a == b
}
//===----------------------------------------------------------------------===//
// Standard operators
//===----------------------------------------------------------------------===//
// Standard postfix operators.
operator postfix ++ {}
operator postfix -- {}
// Optional<T> unwrapping operator is built into the compiler as a part of
// postfix expression grammar.
//
// operator postfix ! {}
// Standard prefix operators.
operator prefix ++ {}
operator prefix -- {}
operator prefix ! {}
@@ -330,154 +195,89 @@ operator prefix ~ {}
operator prefix + {}
operator prefix - {}
operator infix * {
associativity left
precedence 200
}
operator infix / {
associativity left
precedence 200
}
operator infix % {
associativity left
precedence 200
}
// Standard infix operators.
operator infix + {
associativity left
precedence 190
}
operator infix - {
associativity left
precedence 190
}
// "Exponentiative"
operator infix << {
associativity none
precedence 180
}
operator infix >> {
associativity none
precedence 180
}
operator infix << { associativity none precedence 160 }
operator infix >> { associativity none precedence 160 }
operator infix .. {
associativity none
precedence 175
}
// "Multiplicative"
operator infix < {
associativity none
precedence 170
}
operator infix <= {
associativity none
precedence 170
}
operator infix > {
associativity none
precedence 170
}
operator infix >= {
associativity none
precedence 170
}
operator infix * { associativity left precedence 150 }
operator infix &* { associativity left precedence 150 }
operator infix / { associativity left precedence 150 }
operator infix &/ { associativity left precedence 150 }
operator infix % { associativity left precedence 150 }
operator infix &% { associativity left precedence 150 }
operator infix & { associativity left precedence 150 }
operator infix == {
associativity none
precedence 160
}
operator infix != {
associativity none
precedence 160
}
operator infix === {
associativity none
precedence 160
}
operator infix !== {
associativity none
precedence 160
}
// "Additive"
operator infix & {
associativity left
precedence 150
}
operator infix + { associativity left precedence 140 }
operator infix &+ { associativity left precedence 140 }
operator infix - { associativity left precedence 140 }
operator infix &- { associativity left precedence 140 }
operator infix | { associativity left precedence 140 }
operator infix ^ { associativity left precedence 140 }
operator infix ^ {
associativity left
precedence 140
}
// FIXME: is this the right precedence level for "..." ?
operator infix ... { associativity none precedence 135 }
operator infix .. { associativity none precedence 135 }
operator infix | {
associativity left
precedence 130
}
// The cast operators 'as' and 'is' are hardcoded as if they had the
// following attributes:
// operator infix as { associativity none precedence 132 }
operator infix && {
associativity left
precedence 120
}
// "Comparative"
operator infix < { associativity none precedence 130 }
operator infix <= { associativity none precedence 130 }
operator infix > { associativity none precedence 130 }
operator infix >= { associativity none precedence 130 }
operator infix == { associativity none precedence 130 }
operator infix != { associativity none precedence 130 }
operator infix === { associativity none precedence 130 }
operator infix !== { associativity none precedence 130 }
// FIXME: ~= will be built into the compiler.
operator infix ~= { associativity none precedence 130 }
// "Conjunctive"
operator infix && { associativity left precedence 120 }
// "Disjunctive"
operator infix || { associativity left precedence 110 }
operator infix || {
associativity left
precedence 110
}
// User-defined ternary operators are not supported. The ? : operator is
// hardcoded as if it had the following attributes:
// operator ternary ? : {
// associativity right
// precedence 100
// }
// operator ternary ? : { associativity right precedence 100 }
operator infix *= {
associativity right
precedence 90
}
operator infix /= {
associativity right
precedence 90
}
operator infix %= {
associativity right
precedence 90
}
operator infix += {
associativity right
precedence 90
}
operator infix -= {
associativity right
precedence 90
}
operator infix <<= {
associativity right
precedence 90
}
operator infix >>= {
associativity right
precedence 90
}
operator infix &= {
associativity right
precedence 90
}
operator infix ^= {
associativity right
precedence 90
}
operator infix |= {
associativity right
precedence 90
}
operator infix &&= {
associativity right
precedence 90
}
operator infix ||= {
associativity right
precedence 90
}
// User-defined assignment operators are not supported. The = operator is
// hardcoded as if it had the following attributes:
// operator infix = { associativity right precedence 90 }
// Compound
operator infix *= { associativity right precedence 90 }
operator infix /= { associativity right precedence 90 }
operator infix %= { associativity right precedence 90 }
operator infix += { associativity right precedence 90 }
operator infix -= { associativity right precedence 90 }
operator infix <<= { associativity right precedence 90 }
operator infix >>= { associativity right precedence 90 }
operator infix &= { associativity right precedence 90 }
operator infix ^= { associativity right precedence 90 }
operator infix |= { associativity right precedence 90 }
operator infix &&= { associativity right precedence 90 }
operator infix ||= { associativity right precedence 90 }
// Workaround for <rdar://problem/14011860> SubTLF: Default
// implementations in protocols. Library authors should ensure
// that this operator never needs to be seen by end-users. See
// test/Prototypes/GenericDispatch.swift for a fully documented
// example of how this operator is used, and how its use can be hidden
// from users.
operator infix ~> { associativity left precedence 255 }

View File

@@ -1,17 +1,31 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct _Process {
// This variable gets (re-)initialized on-demand to reflect the actual argument vector
var _arguments : String[]
// Use lazy initialization of static properties to safely initialize the
// public 'arguments' property on first use.
static var _arguments: String[] = {
// FIXME: Use a by-index-initializing constructor of Array here when we
// have that, so we don't need this awkward closure initialization.
var _args = new String[Int(C_ARGC)]
for i in 0...Int(C_ARGC) {
_args[i] = String.fromCString(C_ARGV[i])
}
return _args
}()
var arguments : String[] {
// FIXME: this is not thread-safe. rdar://14193840
if _arguments.length == 0 {
_arguments = new String[Int(C_ARGC)]
for i in 0..Int(C_ARGC) {
_arguments[i] = String.fromCString(C_ARGV[i])
}
}
return _arguments
return _Process._arguments
}
}
var Process : _Process
var Process : _Process = _Process()

View File

@@ -1,18 +1,32 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// FIXME: Function types don't work yet as generic parameters
struct REPLExitHandler {
struct _REPLExitHandler {
var f : () -> ()
init(_ f: () -> ()) {
self.f = f
}
}
var replExitHandlers : Vector<REPLExitHandler> = Vector<REPLExitHandler>()
var _replExitHandlers = _REPLExitHandler[]()
func atREPLExit(handler:() -> ()) {
replExitHandlers.append(REPLExitHandler(handler))
func _atREPLExit(handler: () -> ()) {
_replExitHandlers.append(_REPLExitHandler(handler))
}
func replExit() {
while replExitHandlers.length > 0 {
var handler = replExitHandlers[replExitHandlers.length-1]
replExitHandlers.popBack()
func _replExit() {
for handler in Reverse(_replExitHandlers) {
handler.f()
}
}

View File

@@ -1,305 +1,199 @@
struct RangeEnumerator<T: ForwardIndex> : Enumerator, Enumerable {
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct RangeGenerator<T: ForwardIndex> : Generator, Sequence {
typealias Element = T
constructor(begin: T, end: T) {
this.begin_.value = begin
this.end_.value = end
@transparent
init(_ bounds: Range<T>) {
self.startIndex = bounds.startIndex
self.endIndex = bounds.endIndex
}
func isEmpty() -> Bool {
return begin_.value == end_.value
mutating func next() -> Element? {
if startIndex == endIndex {
return .None
}
return startIndex++
}
func next() -> Element {
var ret = begin_.value
begin_.value = begin_.value.succ()
// Every Generator is also a single-pass Sequence
typealias GeneratorType = RangeGenerator<T>
func generate() -> GeneratorType {
return self
}
var startIndex: T
var endIndex: T
}
struct StridedRangeGenerator<T: ForwardIndex> : Generator, Sequence {
typealias Element = T
@transparent
init(_ bounds: Range<T>, stride: T.DistanceType) {
self._bounds = bounds
self._stride = stride
}
mutating func next() -> Element? {
if !_bounds {
return .None
}
let ret = _bounds.startIndex
_bounds.startIndex = advance(_bounds.startIndex, _stride, _bounds.endIndex)
return ret
}
// Every Enumerator is also a single-pass Enumerable
typealias EnumeratorType = RangeEnumerator<T>
func getEnumeratorType() -> EnumeratorType {
return this
// Every Generator is also a single-pass Sequence
typealias GeneratorType = StridedRangeGenerator
func generate() -> GeneratorType {
return self
}
var begin_, end_: GenericIVar<T>
var _bounds: Range<T>
var _stride: T.DistanceType
}
struct Range<T: ForwardIndex> : Enumerable {
constructor(begin: T, end: T) {
this.begin_.value = begin
this.end_.value = end
struct Range<T: ForwardIndex> : LogicValue, Sliceable {
@transparent
init(start: T, end: T) {
_startIndex = start
_endIndex = end
}
func isEmpty() -> Bool {
return begin_.value == end_.value
return startIndex == endIndex
}
func begin() -> T {
return begin_.value
}
func end() -> T {
return end_.value
func getLogicValue() -> Bool {
return !isEmpty()
}
typealias EnumeratorType = RangeEnumerator<T>
func getEnumeratorType() -> EnumeratorType {
return EnumeratorType(begin_.value, end_.value)
subscript(i: T) -> T {
return i
}
var begin_, end_: GenericIVar<T>
subscript(x: Range<T>) -> Range {
return Range(start: x.startIndex, end: x.endIndex)
}
typealias GeneratorType = RangeGenerator<T>
func generate() -> RangeGenerator<T> {
return GeneratorType(self)
}
func by(stride: T.DistanceType) -> StridedRangeGenerator<T> {
return StridedRangeGenerator(self, stride: stride)
}
var startIndex: T {
get {
return _startIndex
}
set(newValue) {
_startIndex = newValue
}
}
var endIndex: T {
get {
return _endIndex
}
set(newValue) {
_endIndex = newValue
}
}
var _startIndex: T
var _endIndex: T
}
/// \brief Any model of ForwardIndex can be turned into a Range with min..max
func .. <Pos: ForwardIndex> (min : Pos, max : Pos) -> Range<Pos> {
return Range(min, max)
func count<I: RandomAccessIndex>(r: Range<I>) -> I.DistanceType {
return r.startIndex.distanceTo(r.endIndex)
}
struct ReverseRangeEnumerator<T: BidirectionalIndex> : Enumerator, Enumerable {
/// \brief Any model of ForwardIndex can be turned into a Range with min...max
@transparent
func ... <Pos : ForwardIndex> (min: Pos, max: Pos) -> Range<Pos> {
return Range(start: min, end: max)
}
@transparent
func .. <Pos : ForwardIndex> (min: Pos, max: Pos) -> Range<Pos> {
return Range(start: min, end: max.succ())
}
struct ReverseRangeGenerator<T: BidirectionalIndex> : Generator, Sequence {
typealias Element = T
constructor(begin: T, end: T) {
this.begin_.value = begin
this.end_.value = end
@transparent
init(start: T, pastEnd: T) {
self._bounds = (start,pastEnd)
}
mutating func next() -> Element? {
if _bounds.0 == _bounds.1 { return .None }
_bounds.1 = _bounds.1.pred()
return _bounds.1
}
// Every Generator is also a single-pass Sequence
typealias GeneratorType = ReverseRangeGenerator<T>
func generate() -> GeneratorType {
return self
}
var _bounds: (T, T)
}
struct ReverseRange<T: BidirectionalIndex> : Sequence {
init(start: T, pastEnd: T) {
self._bounds = (start, pastEnd)
}
init(range fwd: Range<T>) {
self._bounds = (fwd.startIndex, fwd.endIndex)
}
func isEmpty() -> Bool {
return begin_.value == end_.value
return _bounds.0 == _bounds.1
}
func next() -> Element {
end_.value = end_.value.pred()
return end_.value
func bounds() -> (T, T) {
return _bounds
}
// Every Enumerator is also a single-pass Enumerable
typealias EnumeratorType = ReverseRangeEnumerator<T>
func getEnumeratorType() -> EnumeratorType {
return this
typealias GeneratorType = ReverseRangeGenerator<T>
func generate() -> GeneratorType {
return GeneratorType(start: _bounds.0, pastEnd: _bounds.1)
}
var begin_, end_: GenericIVar<T>
var _bounds: (T, T)
}
struct ReverseRange<T: BidirectionalIndex> : Enumerable {
constructor(begin: T, end: T) {
this.begin_.value = begin
this.end_.value = end
}
//
// Pattern matching support for ranges
//
// Ranges can be used to match values contained within the range, e.g.:
// switch x {
// case 0...10:
// println("single digit")
// case _:
// println("too big")
// }
constructor(fwd: Range<T>) {
this.begin_.value = fwd.begin()
this.end_.value = fwd.end()
}
func isEmpty() -> Bool {
return begin_.value == end_.value
}
func begin() -> T {
return begin_.value
}
func end() -> T {
return end_.value
}
typealias EnumeratorType = ReverseRangeEnumerator<T>
func getEnumeratorType() -> EnumeratorType {
return EnumeratorType(begin_.value, end_.value)
}
var begin_, end_: GenericIVar<T>
}
// FIXME: make generic
// BLOCKED: <rdar://problem/12780068> Crash while trying to make iteration generic
struct IntEnumeratorType : Enumerator, Enumerable {
typealias Element = Int
var min : Int
var max : Int
var stride : Int
// FIXME: each/reduce should be moved out to generic methods, or methods that
// take the range as a protocol'd "enumeration/iterator" value.
func each(f : (Int) -> Void) {
for i in this { f(i) }
}
func reduce(val : Int, f : (Int, Int) -> Int) -> Int {
for i in this { val = f(val, i) }
return val
}
func by(s : Int) -> IntEnumeratorType {
var result = this
result.stride = s
return result
}
func isEmpty() -> Bool {
return min >= max
}
func contains(x : Int) -> Bool {
return min <= x && x < max
}
func next() -> Int {
var prev = min
min += stride
return prev
}
typealias EnumeratorType = IntEnumeratorType
func getEnumeratorType() -> IntEnumeratorType {
return this
}
func replPrint() {
print("\(min)..\(max)")
if stride != 1 {
print(" by \(stride)")
}
}
}
extension IntEnumeratorType : Equatable, Hashable {
func __equal__(rhs: IntEnumeratorType) -> Bool {
return min == rhs.min && max == rhs.max && stride == rhs.stride
}
func hashValue() -> Int {
return min ^ max
}
}
// FIXME: make generic
// BLOCKED: <rdar://problem/12780068> Crash while trying to make iteration generic
struct ReverseIntEnumeratorType : Enumerator, Enumerable {
typealias Element = Int
var min : Int
var max : Int
var stride : Int
// FIXME: each/reduce should be moved out to generic methods, or methods that
// take the range as a protocol'd "enumeration/iterator" value.
func each(f : (Int) -> Void) {
for i in this { f(i) }
}
func reduce(val : Int, f : (Int, Int) -> Int) -> Int {
for i in this { val = f(val, i) }
return val
}
func isEmpty() -> Bool {
return min >= max
}
func contains(x : Int) -> Bool {
return min <= x && x < max
}
func next() -> Int {
max -= stride
return max
}
typealias EnumeratorType = ReverseIntEnumeratorType
func getEnumeratorType() -> ReverseIntEnumeratorType {
return this
}
func replPrint() {
print("reverse(\(min)..\(max))")
if stride != 1 {
print(" by \(stride)")
}
}
}
extension ReverseIntEnumeratorType : Equatable, Hashable {
func __equal__(rhs: ReverseIntEnumeratorType) -> Bool {
return min == rhs.min && max == rhs.max && stride == rhs.stride
}
func hashValue() -> Int {
return min ^ max
}
}
func reverse<T: BidirectionalIndex>(rng: Range<T>) -> ReverseRange<T> {
return ReverseRange(rng.begin(), rng.end())
}
func reverse<T: BidirectionalIndex>(rng: ReverseRange<T>) -> Range<T> {
return Range(rng.begin(), rng.end())
}
func reverse(rng : IntEnumeratorType) -> ReverseIntEnumeratorType {
return ReverseIntEnumeratorType(rng.min, rng.max, rng.stride)
}
func reverse(rng : ReverseIntEnumeratorType) -> IntEnumeratorType {
return IntEnumeratorType(rng.min, rng.max, rng.stride)
}
func .. (min : Int, max : Int) -> IntEnumeratorType {
return IntEnumeratorType(min, max, 1)
}
// FIXME: make generic
// BLOCKED: <rdar://problem/12780068> Crash while trying to make iteration generic
struct DoubleEnumeratorType : Enumerator, Enumerable {
typealias Element = Double
var min : Double,
max : Double,
stride : Double
// FIXME: each/reduce should be moved out to generic methods, or methods that
// take the range as a protocol'd "enumeration/iterator" value.
func each(f : (Double) -> Void) {
for i in this { f(i) }
}
func reduce(val : Double, f : (Double, Double) -> Double) -> Double {
for i in this { val = f(val, i) }
return val
}
func by(s : Double) -> DoubleEnumeratorType {
var result = this
result.stride = s
return result
}
func isEmpty() -> Bool {
return min >= max
}
func next() -> Double {
var prev = min
min += stride
return prev
}
typealias EnumeratorType = DoubleEnumeratorType
func getEnumeratorType() -> DoubleEnumeratorType {
return this
}
func replPrint() {
print("\(min)..\(max)")
if stride != 1.0 {
print(" by \(stride)")
}
}
}
extension DoubleEnumeratorType : Equatable, Hashable {
func __equal__(rhs: DoubleEnumeratorType) -> Bool {
return min == rhs.min && max == rhs.max && stride == rhs.stride
}
func hashValue() -> Int {
return min.hashValue() ^ max.hashValue()
}
}
func .. (min : Double, max : Double) -> DoubleEnumeratorType {
return DoubleEnumeratorType(min, max, 1.0)
@infix func ~= <T: RandomAccessIndex where T.DistanceType : SignedInteger>(x: Range<T>, y: T) -> Bool {
let a = x.startIndex.distanceTo(y) >= 0
let b = y.distanceTo(x.endIndex) > 0
return a && b
}

View File

@@ -21,83 +21,392 @@ protocol Reflectable {
}
/// A unique identifier for a class instance. This can be used by reflection
/// clients to avoid visiting cycles in the object graph.
/// clients to recognize cycles in the object graph.
///
/// In Swift, only class instances have unique identities. There is no notion
/// of identity for structs, enums, or tuples.
struct ObjectIdentifier : Hashable {
val value: Builtin.RawPointer
let value: Builtin.RawPointer
func uintValue() -> UInt {
return UInt(Builtin.ptrtoint_Word(value))
}
// FIXME: Better hashing algorithm
func hashValue() -> Int {
var hashValue: Int {
return Int(Builtin.ptrtoint_Word(value))
}
init(_ x: AnyObject) {
self.value = reinterpretCast(x)
}
}
func ==(x: ObjectIdentifier, y: ObjectIdentifier) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(x.value, y.value))
}
/// The sum of types that can be used as a quick look representation.
///
/// This type must be binary-compatible with the 'QuickLookObject' struct in
/// stdlib/Runtime/Reflection.mm, and 'QuickLookObject?' must be binary
/// compatible with 'OptionalQuickLookObject' from the same.
///
/// NB: This type is somewhat carefully laid out to *suppress* enum layout
/// optimization so that it is easier to manufacture in the C++ runtime
/// implementation.
enum QuickLookObject {
/// Plain text.
case Text(String)
/// An integer numeric value.
case Int(Int64)
/// An unsigned integer numeric value.
case UInt(UInt64)
/// A floating-point numeric value.
case Float(Double)
/// An image.
/// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
case Image(Any)
/// A sound.
/// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
case Sound(Any)
/// A color.
/// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
case Color(Any)
/// A bezier path.
/// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
case BezierPath(Any)
/// An attributed string.
/// FIXME: Uses an Any to avoid coupling a particular Cocoa type.
case AttributedString(Any)
/// A rectangle
/// Uses explicit coordinates to avoid coupling a particular Cocoa type.
case Rectangle(Double,Double,Double,Double)
/// A point
/// Uses explicit coordinates to avoid coupling a particular Cocoa type.
case Point(Double,Double)
/// A size
/// Uses explicit coordinates to avoid coupling a particular Cocoa type.
case Size(Double,Double)
/// A logical value
case Logical(Bool)
/// A range
/// Uses explicit values to avoid coupling a particular Cocoa type.
case Range(UInt64, UInt64)
/// A GUI view
/// Uses an Any to avoid coupling a particular Cocoa type.
case View(Any)
/// A graphical sprite
/// Uses an Any to avoid coupling a particular Cocoa type.
case Sprite(Any)
/// A Uniform Resource Locator
case URL(String)
/// Raw data that has already been encoded in a format the IDE understands.
case _Raw(UInt8[], String)
}
/// How children of this value should be presented in the IDE.
enum MirrorDisposition {
/// As a struct.
case Struct
/// As a class.
case Class
/// As an enum.
case Enum
/// As a tuple.
case Tuple
/// As a miscellaneous aggregate with a fixed set of children.
case Aggregate
/// As a container that is accessed by index.
case IndexContainer
/// As a container that is accessed by key.
case KeyContainer
/// As a container that represents membership of its values.
case MembershipContainer
/// As a miscellaneous container with a variable number of children.
case Container
/// An Optional which can have either zero or one children.
case Optional
}
/// A protocol that provides a reflection interface to an underlying value.
protocol Mirror {
// The runtime has inappropriate knowledge of this protocol and how its
// witness tables are laid out. Changing this protocol requires a
// corresponding change to Reflection.cpp.
// FIXME: Most or all of these should be properties and subscripts when we
// can have those in protocols.
/// Copy the value out as an Any.
func getValue() -> Any
var value: Any { get }
/// Get the type of the value.
func getType() -> Any.metatype
var valueType: Any.Type { get }
/// Get the unique identifier for this value, if it has one.
/// Always returns Some value for class instances, and always returns None
/// for value types.
func getObjectIdentifier() -> ObjectIdentifier?
var objectIdentifier: ObjectIdentifier? { get }
/// Get the number of logical children this value has.
func getCount() -> Int
var count: Int { get }
/// Get a mirror for one of this value's children.
///
/// Returns a pair of the child's name and its mirror.
func getChild(i: Int) -> (String, Mirror)
subscript(i: Int) -> (String, Mirror) { get }
/// Get a string description of this value.
func getString() -> String
var summary: String { get }
/// Get a rich representation of this value for the IDE, if it has one.
func getIDERepresentation() -> IDERepresentable?
var quickLookObject: QuickLookObject? { get }
/// Get the disposition of the value.
var disposition: MirrorDisposition { get }
}
/// A protocol for objects that can be used as rich representations by the IDE.
/// These are serialized into a data type identifier and an array of bytes
/// for the IDE's consumption.
protocol IDERepresentable {
/// Get a string that describes the type of data.
func getTypeString() -> String
/// Get the raw data.
func getData() -> UInt8[]
/// An entry point that can be called from C++ code to get the summary string
/// for an arbitrary object. The memory pointed to by "out" is initialized with
/// the summary string.
@asmname("swift_getSummary") func _getSummary<T>(out: UnsafePointer<String>,
x: T) {
out.initialize(reflect(x).summary)
}
/// Produce a mirror for any value. If the value's type conforms to Reflectable,
/// invoke its getMirror() method; otherwise, fall back to an implementation
/// in the runtime that structurally reflects values of any type.
@asmname="swift_reflectAny" func reflect<T>(x: T) -> Mirror
@asmname("swift_reflectAny") func reflect<T>(x: T) -> Mirror
/// Unsafely produce a mirror for a value in memory whose lifetime is
/// guaranteed by holding a strong reference to a heap object.
/// This lets containers with heap storage vend mirrors for their elements
/// without unnecessary copying of the underlying value.
@asmname("swift_unsafeReflectAny") func unsafeReflect<T>(
owner: Builtin.NativeObject,
ptr: UnsafePointer<T>
) -> Mirror
/// Dump an object's contents using its mirror.
func dump<T>(x: T, name: String? = nil, indent: Int = 0,
maxDepth: Int = .max, maxItems: Int = .max) -> T {
var maxItemCounter = maxItems
var visitedItems = Dictionary<ObjectIdentifier, Int>()
_dumpWithMirror(reflect(x), name, indent, maxDepth,
&maxItemCounter, &visitedItems)
return x
}
/// Dump an object's contents using a mirror. User code should use dump().
func _dumpWithMirror(mirror: Mirror, name: String?,
indent: Int, maxDepth: Int,
inout maxItemCounter: Int,
inout visitedItems: Dictionary<ObjectIdentifier, Int>) {
if maxItemCounter <= 0 { return }
--maxItemCounter
for _ in 0...indent { print(" ") }
let count = mirror.count
let bullet = count == 0 ? "-"
: maxDepth <= 0 ? "" : ""
print("\(bullet) ")
if let nam = name {
print("\(nam): ")
}
print(mirror.summary)
if let id = mirror.objectIdentifier {
if let previous = visitedItems.find(id) {
println(" #\(previous)")
return
}
let identifier = visitedItems.count
visitedItems[id] = identifier
print(" #\(identifier)")
}
println()
if maxDepth <= 0 { return }
for i in 0...count {
if maxItemCounter <= 0 {
for _ in 0...(indent+4) { print(" ") }
let remainder = count - i
print("(\(remainder)")
if i > 0 { print(" more") }
if remainder == 1 {
println(" child)")
} else {
println(" children)")
}
return
}
let (name, child) = mirror[i]
_dumpWithMirror(child, name, indent + 2, maxDepth - 1,
&maxItemCounter, &visitedItems)
}
}
// -- Mirror implementations for basic data types
/// A mirror for a value that is represented as a simple value with no
/// children.
struct _LeafMirror<T>: Mirror {
let _value: T
let summaryFunction: T -> String
let quickLookFunction: T -> QuickLookObject?
init(_ value: T, _ summaryFunction: T -> String,
_ quickLookFunction: T -> QuickLookObject?) {
self._value = value
self.summaryFunction = summaryFunction
self.quickLookFunction = quickLookFunction
}
var value: Any { return _value }
var valueType: Any.Type { return value.dynamicType }
var objectIdentifier: ObjectIdentifier? { return nil }
var count: Int { return 0 }
subscript(i: Int) -> (String, Mirror) { fatal("no children") }
var summary: String { return summaryFunction(_value) }
var quickLookObject: QuickLookObject? { return quickLookFunction(_value) }
var disposition: MirrorDisposition { return .Aggregate }
}
// -- Implementation details for the runtime's Mirror implementation
/// Implementation detail of the runtime mirror implementation.
/// If this is changed, Reflection.cpp in the runtime must be changed to
/// correspond.
struct _MagicMirrorData {
val owner: Builtin.ObjectPointer
val ptr: Builtin.RawPointer
val metadata: Any.metatype
let owner: Builtin.NativeObject
let ptr: Builtin.RawPointer
let metadata: Any.Type
var value: Any {
@asmname("swift_MagicMirrorData_value") get
}
var valueType: Any.Type {
@asmname("swift_MagicMirrorData_valueType") get
}
var objcValue: Any {
@asmname("swift_MagicMirrorData_objcValue") get
}
var objcValueType: Any.Type {
@asmname("swift_MagicMirrorData_objcValueType") get
}
func _loadValue<T>() -> T {
return Builtin.load(ptr) as T
}
}
/// A thunk that returns a String by value, for C entry points.
func _returnString(inout s: String) -> String {
return s
struct _OpaqueMirror: Mirror {
let data: _MagicMirrorData
var value: Any { return data.value }
var valueType: Any.Type { return data.valueType }
var objectIdentifier: ObjectIdentifier? { return nil }
var count: Int { return 0 }
subscript(i: Int) -> (String, Mirror) { fatal("no children") }
var summary: String { return "<opaque>" }
var quickLookObject: QuickLookObject? { return nil }
var disposition: MirrorDisposition { return .Aggregate }
}
struct _TupleMirror: Mirror {
let data: _MagicMirrorData
var value: Any { return data.value }
var valueType: Any.Type { return data.valueType }
var objectIdentifier: ObjectIdentifier? { return nil }
var count: Int {
@asmname("swift_TupleMirror_count") get
}
subscript(i: Int) -> (String, Mirror) {
@asmname("swift_TupleMirror_subscript") get
}
var summary: String { return "(\(count) elements)" }
var quickLookObject: QuickLookObject? { return nil }
var disposition: MirrorDisposition { return .Tuple }
}
struct _StructMirror: Mirror {
let data: _MagicMirrorData
var value: Any { return data.value }
var valueType: Any.Type { return data.valueType }
var objectIdentifier: ObjectIdentifier? { return nil }
var count: Int {
@asmname("swift_StructMirror_count") get
}
subscript(i: Int) -> (String, Mirror) {
@asmname("swift_StructMirror_subscript") get
}
// FIXME: put the type name here
var summary: String { return "(\(count) elements)" }
var quickLookObject: QuickLookObject? { return nil }
var disposition: MirrorDisposition { return .Struct }
}
@asmname("swift_ClassMirror_count")
func _getClassCount(_MagicMirrorData) -> Int
@asmname("swift_ClassMirror_subscript")
func _getClassChild(Int, _MagicMirrorData) -> (String, Mirror)
struct _ClassMirror: Mirror {
let data: _MagicMirrorData
var value: Any { return data.value }
var valueType: Any.Type { return data.valueType }
var objectIdentifier: ObjectIdentifier? {
return data._loadValue() as ObjectIdentifier
}
var count: Int {
return _getClassCount(data)
}
subscript(i: Int) -> (String, Mirror) {
return _getClassChild(i, data)
}
// FIXME: put the type name here
var summary: String { return "(\(count) elements)" }
var quickLookObject: QuickLookObject? { return nil }
var disposition: MirrorDisposition { return .Class }
}
struct _ClassSuperMirror: Mirror {
let data: _MagicMirrorData
var value: Any { return data.value }
var valueType: Any.Type { return data.valueType }
// Suppress the value identifier for super mirrors.
var objectIdentifier: ObjectIdentifier? {
return nil
}
var count: Int {
return _getClassCount(data)
}
subscript(i: Int) -> (String, Mirror) {
return _getClassChild(i, data)
}
// FIXME: put the type name here
var summary: String { return "(\(count) elements)" }
var quickLookObject: QuickLookObject? { return nil }
var disposition: MirrorDisposition { return .Class }
}

View File

@@ -21,3 +21,14 @@ func _makeSwiftNSFastEnumerationState() -> _SwiftNSFastEnumerationState {
extra: (0, 0, 0, 0, 0))
}
/// A dummy value that is be used as the target for `mutationsPtr` in fast
/// enumeration implementations.
var _fastEnumerationStorageMutationsTarget: CUnsignedLong = 0
/// A dummy pointer to be used as `mutationsPtr` in fast enumeration
/// implementations.
var _fastEnumerationStorageMutationsPtr: UnsafePointer<CUnsignedLong> {
return UnsafePointer(
Builtin.addressof(&_fastEnumerationStorageMutationsTarget))
}

View File

@@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//
/// Buffer type for Slice<T>
struct SliceBuffer<T> : ArrayBufferType {
typealias Element = T
typealias NativeStorage = NativeArrayStorage<T>
@@ -33,10 +34,10 @@ struct SliceBuffer<T> : ArrayBufferType {
_invariantCheck()
}
init(x: NativeBuffer) {
owner = x.storage
start = x.elementStorage
_countAndFlags = (UInt(x.count) << 1) | 1
init(_ buffer: NativeBuffer) {
owner = buffer.storage
start = buffer.elementStorage
_countAndFlags = (UInt(buffer.count) << 1) | 1
_invariantCheck()
}
@@ -62,31 +63,51 @@ struct SliceBuffer<T> : ArrayBufferType {
return NativeBuffer(owner as NativeStorage)
}
/// A value that identifies first mutable element, if any. Two
/// arrays compare === iff they are both empty, or if their buffers
/// have the same identity and count.
var identity: Word {
return reinterpretCast(start)
}
/// An object that keeps the elements stored in this buffer alive
var owner: AnyObject?
var start: UnsafePointer<T>
var _countAndFlags: UInt
//===--- Non-essential bits ---------------------------------------------===//
//extension SliceBuffer : ArrayBufferType {
func asCocoaArray() -> CocoaArray {
// It's tempting to allocate a new instance of an NSArray subclass
// that just wraps this Slice. However, since we don't have a
// managedByCopyOnWrite bit in the dynamically-allocated storage,
// and we are in principle part of a mutable object, we need to
// copy eagerly in most cases. The one exception is when our
// owner is nil. We could think about doing that optimization
// someday.
assert(
isBridgedToObjectiveC(T.self),
"Array element type is not bridged to ObjectiveC")
_invariantCheck()
// FIXME: can't write this pending <rdar://problem/16397774>:
// return asArray(UnsafeArray(start, count)) as NativeArray<T>
var result = NativeArrayBuffer<T>()
result += UnsafeArray(start, count)
return result.asCocoaArray()
return _extractOrCopyToNativeArrayBuffer(self).asCocoaArray()
}
mutating func requestUniqueMutableBuffer(minimumCapacity: Int)
-> NativeBuffer?
{
_invariantCheck()
if _fastPath(_hasNativeBuffer && Swift.isUniquelyReferenced(&owner)) {
if capacity >= minimumCapacity {
return reinterpretCast(owner) as NativeBuffer
}
}
return nil
}
/// If this buffer is backed by a NativeArrayBuffer, return it.
/// Otherwise, return nil. Note: the result's elementStorage may
/// not match ours, since we are a SliceBuffer.
func requestNativeBuffer() -> NativeArrayBuffer<Element>? {
_invariantCheck()
if _fastPath(_hasNativeBuffer) {
return reinterpretCast(owner) as NativeBuffer
}
return nil
}
func _uninitializedCopy(
@@ -102,6 +123,10 @@ struct SliceBuffer<T> : ArrayBufferType {
return target
}
var elementStorage: UnsafePointer<T> {
return start
}
var count: Int {
get {
return Int(_countAndFlags >> 1)
@@ -133,20 +158,15 @@ struct SliceBuffer<T> : ArrayBufferType {
return Swift.isUniquelyReferenced(&owner)
}
func isMutable() -> Bool {
return _hasNativeBuffer
}
subscript(i: Int) -> T {
get {
assert(i >= 0, "negative slice index is out of range")
assert(i < count, "slice index out of range")
return start[i]
}
set {
nonmutating set {
assert(i >= 0, "negative slice index is out of range")
assert(i < count, "slice index out of range")
assert(isMutable())
start[i] = newValue
}
}
@@ -156,7 +176,27 @@ struct SliceBuffer<T> : ArrayBufferType {
assert(subRange.endIndex >= subRange.startIndex)
assert(subRange.endIndex <= count)
return SliceBuffer(
owner, start + subRange.startIndex,
subRange.endIndex - subRange.startIndex, _hasNativeBuffer)
owner: owner, start: start + subRange.startIndex,
count: subRange.endIndex - subRange.startIndex,
hasNativeBuffer: _hasNativeBuffer)
}
//===--- Collection conformance -----------------------------------------===//
var startIndex: Int {
return 0
}
var endIndex: Int {
return count
}
func generate() -> IndexingGenerator<SliceBuffer> {
return IndexingGenerator(self)
}
//===--- misc -----------------------------------------------------------===//
func withUnsafePointerToElements<R>(body: (UnsafePointer<T>)->R) -> R {
let start = self.start
return owner ? withExtendedLifetime(owner!) { body(start) } : body(start)
}
}

View File

@@ -1,3 +1,15 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// \brief An extremely simple string designed to represent something
/// "statically knowable".
@@ -7,36 +19,47 @@
// types, we are guaranteed that no assertions are involved in its
// construction. This feature is crucial for preventing infinite
// recursion even in non-asserting cases.
struct StaticString : BuiltinStringLiteralConvertible, StringLiteralConvertible {
struct StaticString
: _BuiltinExtendedGraphemeClusterLiteralConvertible,
ExtendedGraphemeClusterLiteralConvertible,
_BuiltinStringLiteralConvertible, StringLiteralConvertible {
var start: Builtin.RawPointer
var byteCount: Builtin.Word
var byteSize: Builtin.Word
var isASCII: Builtin.Int1
init() {
self = ""
}
init(start: Builtin.RawPointer, byteCount: Builtin.Word, isASCII: Builtin.Int1) {
init(
start: Builtin.RawPointer, byteSize: Builtin.Word, isASCII: Builtin.Int1
) {
self.start = start
self.byteCount = byteCount
self.byteSize = byteSize
self.isASCII = isASCII
}
// FIXME: this is a hackaround for <rdar://problem/15888736> fatal()
// can't take a StaticString?!
init(nulTerminated: CString) {
self.start = nulTerminated._bytesPtr.value
self.byteCount = _strlen(nulTerminated).value
self.isASCII = false.value
static func _convertFromBuiltinExtendedGraphemeClusterLiteral(
start: Builtin.RawPointer,
byteSize: Builtin.Word,
isASCII: Builtin.Int1) -> StaticString {
return _convertFromBuiltinStringLiteral(
start, byteSize: byteSize, isASCII: isASCII)
}
type func _convertFromBuiltinStringLiteral(
start: Builtin.RawPointer, byteCount: Builtin.Word, isASCII: Builtin.Int1
static func convertFromExtendedGraphemeClusterLiteral(
value: StaticString) -> StaticString {
return value
}
static func _convertFromBuiltinStringLiteral(
start: Builtin.RawPointer, byteSize: Builtin.Word, isASCII: Builtin.Int1
) -> StaticString {
return StaticString(start: start, byteCount: byteCount, isASCII: isASCII)
return StaticString(start: start, byteSize: byteSize, isASCII: isASCII)
}
type func convertFromStringLiteral(value: StaticString) -> StaticString {
static func convertFromStringLiteral(value: StaticString) -> StaticString {
return value
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +1,89 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Swift's String bridges NSString via this protocol and these
// variables, allowing the core stdlib to remain decoupled from
// Foundation.
/// \brief Effectively a proxy for NSString that doesn't mention it by
/// name. NSString's conformance to this protocol is declared in
/// Foundation.
@class_protocol @objc protocol _CocoaString {}
/// \brief Loading Foundation initializes these function variables
/// with useful values
func _cocoaStringBridgeNotInitialized<A,R>() -> (A)->R {
// FIXME: returning a closure as a workaround for
// <rdar://problem/15921334>
return {
(args:A) -> R in
fatal("Swift <==> Cocoa string bridge not initialized")
return (.None as R?)!
}
}
/// \brief produces a ContiguousString from a given subrange of a source
/// \brief produces a _StringBuffer from a given subrange of a source
/// _CocoaString, having the given minimum capacity.
var __swift_cocoaStringToContiguousString : (
var _cocoaStringToContiguous: (
source: _CocoaString, range: Range<Int>, minimumCapacity: Int
) -> ContiguousString = _cocoaStringBridgeNotInitialized()
) -> _StringBuffer = _cocoaStringToContiguousNotInitialized
func _cocoaStringToContiguousNotInitialized(
source: _CocoaString, range: Range<Int>, minimumCapacity: Int
) -> _StringBuffer {
fatal("_cocoaStringToContiguous not initialized")
}
/// \brief reads the entire contents of a _CocoaString into contiguous
/// storage of sufficient capacity.
var __swift_cocoaStringReadAll : (
var _cocoaStringReadAll: (
source: _CocoaString, destination: UnsafePointer<UTF16.CodeUnit>
) -> Void = _cocoaStringBridgeNotInitialized()
) -> Void = _cocoaStringReadAllNotInitialized
// FIXME: This will probably go away but is needed at least
// temporarily as a bridge to StringCore
var __swift_cocoaStringLength: (
func _cocoaStringReadAllNotInitialized(
source: _CocoaString, destination: UnsafePointer<UTF16.CodeUnit>
) -> Void {
fatal("_cocoaStringReadAll not initialized")
}
var _cocoaStringLength: (
source: _CocoaString
) -> Int = _cocoaStringBridgeNotInitialized()
) -> Int = _cocoaStringLengthNotInitialized
var _appendCocoaString : (
target: @inout String, rhs: String
) -> Void
// FIXME: Explicit default value is a workaround for <rdar://problem/15921520>
= { x,y in fatal("Swift <==> Cocoa string bridge not initialized") }
func _cocoaStringLengthNotInitialized(
source: _CocoaString
) -> Int {
fatal("_cocoaStringLength not initialized")
}
var _sliceCocoaString : (
target: StringCore, subRange: Range<Int>
) -> StringCore = _cocoaStringBridgeNotInitialized()
var _cocoaStringSlice: (
target: _StringCore, subRange: Range<Int>
) -> _StringCore = _cocoaStringSliceNotInitialized
var _indexCocoaString : (
target: StringCore, position: Int
) -> UTF16.CodeUnit = _cocoaStringBridgeNotInitialized()
func _cocoaStringSliceNotInitialized(
target: _StringCore, subRange: Range<Int>
) -> _StringCore {
fatal("_cocoaStringSlice not initialized")
}
var _cocoaStringSubscript: (
target: _StringCore, position: Int
) -> UTF16.CodeUnit = _cocoaStringSubscriptNotInitialized
func _cocoaStringSubscriptNotInitialized(
target: _StringCore, position: Int
) -> UTF16.CodeUnit {
fatal("_cocoaStringSubscript not initialized")
}
var _cocoaStringEncodeSomeUTF8: (
target: _StringCore, position: Int
) -> (_StringCore.IndexType, _StringCore.UTF8Chunk)
= _cocoaStringEncodeSomeUTF8NotInitialized
func _cocoaStringEncodeSomeUTF8NotInitialized(
target: _StringCore, position: Int
) -> (_StringCore.IndexType, _StringCore.UTF8Chunk) {
fatal("_cocoaStringEncodeSomeUTF8 not initialized")
}

View File

@@ -1,103 +1,180 @@
struct StringBufferIVars {
init() {
used = .null()
capacity = .null()
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct _StringBufferIVars {
init(_ elementWidth: Int) {
assert(elementWidth == 1 || elementWidth == 2)
usedEnd = .null()
capacityAndElementShift = elementWidth - 1
}
init(
used: UnsafePointer<UTF16.CodeUnit>,
capacity: UnsafePointer<UTF16.CodeUnit>
usedEnd: UnsafePointer<RawByte>,
byteCapacity: Int,
elementWidth: Int
) {
self.used = used
self.capacity = capacity
assert(elementWidth == 1 || elementWidth == 2)
assert((byteCapacity & 0x1) == 0)
self.usedEnd = usedEnd
self.capacityAndElementShift = byteCapacity + (elementWidth - 1)
}
var used, capacity: UnsafePointer<UTF16.CodeUnit>
var usedEnd: UnsafePointer<RawByte>
var capacityAndElementShift: Int
var byteCapacity: Int {
return capacityAndElementShift & ~0x1
}
var elementShift: Int {
return capacityAndElementShift & 0x1
}
}
// FIXME: Wanted this to be a subclass of
// HeapBuffer<StringBufferIVars,UTF16.CodeUnit>, but
// HeapBuffer<_StringBufferIVars,UTF16.CodeUnit>, but
// <rdar://problem/15520519> (Can't call static method of derived
// class of generic class with dependent argument type) prevents it.
struct StringBuffer {
typealias _Storage = HeapBuffer<StringBufferIVars, UTF16.CodeUnit>
struct _StringBuffer {
// Make this a buffer of UTF16 code units so that it's properly
// aligned for them if that's what we store.
typealias _Storage = HeapBuffer<_StringBufferIVars, UTF16.CodeUnit>
@conversion
func __conversion() -> _Storage {
return _storage
}
init(storage: _Storage) {
init(_ storage: _Storage) {
_storage = storage
}
init(capacity: Int, initialSize: Int = 0) {
_storage = _Storage.create(StringBufferIVars(), capacity)
self.used = _storage.elementStorage + initialSize
self.capacity = _storage.elementStorage + capacity
init(capacity: Int, initialSize: Int, elementWidth: Int) {
assert(elementWidth == 1 || elementWidth == 2)
let elementShift = elementWidth - 1
// We need at least 1 extra byte if we're storing 8-bit elements,
// because indexing will always grab 2 consecutive bytes at a
// time.
let capacityBump = 1 - elementShift
// Used to round capacity up to nearest multiple of 16 bits, the
// element size of our storage.
let divRound = 1 - elementShift
_storage = _Storage(_Storage.Storage.self,
_StringBufferIVars(elementWidth),
(capacity + capacityBump + divRound) >> divRound
)
self.usedEnd = start + (initialSize << elementShift)
_storage.value.capacityAndElementShift
= ((_storage._capacity() - capacityBump) << 1) + elementShift
}
init<
Encoding: UnicodeCodec, Input: Collection
where Input.StreamType.Element == Encoding.CodeUnit
where Input.GeneratorType.Element == Encoding.CodeUnit
>(
encoding: Encoding.metatype, input: Input, minimumCapacity: Int = 0
encoding: Encoding.Type, input: Input, minimumCapacity: Int = 0
) {
// Determine how many UTF16 code units we'll need
var utf16Count = 0
transcode(encoding, UTF16, input.generate(), SinkOf<UTF16.CodeUnit>({
_ in ++utf16Count;()
}))
var inputStream = input.generate()
var (utf16Count, isAscii) = UTF16.measure(encoding, input: inputStream)
// Allocate storage
self = StringBuffer(max(utf16Count, minimumCapacity))
self = _StringBuffer(
capacity: max(utf16Count, minimumCapacity),
initialSize: utf16Count,
elementWidth: isAscii ? 1 : 2)
var used = self.used
// Fill the storage
transcode(encoding, UTF16, input.generate(), SinkOf<UTF16.CodeUnit>( {
(used++).set($0)
} ))
self.used = used
if isAscii {
var p = UnsafePointer<UTF8.CodeUnit>(start)
transcode(encoding, UTF32.self, input.generate(), SinkOf {
(p++).set(UTF8.CodeUnit($0))
})
}
else {
var p = _storage.elementStorage
transcode(encoding, UTF16.self, input.generate(), SinkOf {
(p++).set($0)
})
}
}
var start : UnsafePointer<UTF16.CodeUnit> {
return _storage.elementStorage
/// \brief a pointer to the start of this buffer's data area
var start: UnsafePointer<RawByte> {
return UnsafePointer(_storage.elementStorage)
}
var used : UnsafePointer<UTF16.CodeUnit> {
return _storage.value.used
set(newValue):
_storage.value.used = newValue
/// \brief a past-the-end pointer for this buffer's stored data
var usedEnd: UnsafePointer<RawByte> {
get {
return _storage.value.usedEnd
}
set(newValue) {
_storage.value.usedEnd = newValue
}
}
var capacity : UnsafePointer<UTF16.CodeUnit> {
return _storage.value.capacity
set(newValue):
_storage.value.capacity = newValue
var usedCount: Int {
return (usedEnd - start) >> elementShift
}
@mutating
func grow(
oldUsed: UnsafePointer<UTF16.CodeUnit>,
newUsed: UnsafePointer<UTF16.CodeUnit>
) -> Bool {
if capacity < newUsed {
/// \brief a past-the-end pointer for this buffer's available storage
var capacityEnd: UnsafePointer<RawByte> {
return start + _storage.value.byteCapacity
}
/// \brief The number of elements that can be stored in this buffer
var capacity: Int {
return _storage.value.byteCapacity >> elementShift
}
/// \brief 1 if the buffer stores UTF16; 0 otherwise
var elementShift: Int {
return _storage.value.elementShift
}
/// \brief the number of bytes per element
var elementWidth: Int {
return elementShift + 1
}
mutating func grow(oldUsedEnd: UnsafePointer<RawByte>,
newUsedCount: Int) -> Bool {
if _slowPath(newUsedCount > capacity) {
return false
}
let newUsedEnd = start + (newUsedCount << elementShift)
if _fastPath(
self._storage.isUniquelyReferenced()
) {
usedEnd = newUsedEnd
return true
}
// FIXME: this function is currently NOT THREADSAFE. The test +
// assignment below should be replaced by a CAS, or we can fall back to
// checking isUniquelyReferenced, which is more conservative.
if used == oldUsed {
used = newUsed
// assignment below should be replaced by a CAS
if usedEnd == oldUsedEnd {
usedEnd = newUsedEnd
return true
}
return false
}
@conversion
func __conversion() -> AnyObject {
return _storage
func __conversion() -> AnyObject? {
return _storage.storage ? .Some(_storage.storage!) : .None
}
var _storage: HeapBuffer<StringBufferIVars, UTF16.CodeUnit>
var _storage: _Storage
}

View File

@@ -1,6 +1,18 @@
/// \brief The core implementation of a highly-optimizable String that
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// The core implementation of a highly-optimizable String that
/// can store both ASCII and UTF-16, and can wrap native Swift
/// StringBuffer or NSString instances.
/// _StringBuffer or NSString instances.
///
/// Usage note: when elements are 8 bits wide, this code may
/// dereference one past the end of the byte array that it owns, so
@@ -12,134 +24,460 @@
// size with the ternary operator. This is also the cause of the
// extra element requirement for 8 bit elements. See the
// implementation of subscript(Int) -> UTF16.CodeUnit below for details.
struct StringCore {
var baseAddress: COpaquePointer
struct _StringCore {
//===--------------------------------------------------------------------===//
// Internals
var _baseAddress: COpaquePointer
var _countAndFlags: UWord
var owner: AnyObject?
var _owner: AnyObject?
/// \brief (private) create the implementation of a string from its
/// component parts.
/// (private) create the implementation of a string from its component parts.
init(
baseAddress: COpaquePointer,
_countAndFlags: UWord,
owner: AnyObject?
) {
self.baseAddress = baseAddress
self._baseAddress = baseAddress
self._countAndFlags = _countAndFlags
self.owner = owner
self._owner = owner
_invariantCheck()
}
init(
baseAddress: COpaquePointer,
count: Int,
elementShift: Int,
hasOpaqueBuffer: Bool,
owner: AnyObject?
) {
assert(elementShift == 0 || elementShift == 1)
self.baseAddress = baseAddress
self._countAndFlags = (UWord(elementShift) << (UWord.bitSize() - 1))
| ((hasOpaqueBuffer ? 1 : 0) << (UWord.bitSize() - 2))
| UWord(count)
self.owner = owner
assert(UWord(count) & _flagMask == 0)
func _invariantCheck() {
assert(count >= 0)
if _baseAddress == .null() {
assert(cocoaBuffer,
"Only opaque cocoa strings may have a null base pointer")
assert(elementWidth == 2,
"Opaque cocoa strings should have an elementWidth of 2")
}
else if _baseAddress == _emptyStringBase {
assert(count == 0, "Empty string storage with non-zero length")
assert(!_owner, "String pointing at empty storage has owner")
}
else if let buffer = nativeBuffer {
assert(elementWidth == buffer.elementWidth,
"_StringCore elementWidth doesn't match its buffer's")
assert(UnsafePointer(_baseAddress) >= buffer.start)
assert(UnsafePointer(_baseAddress) <= buffer.usedEnd)
assert(UnsafePointer(_pointerToNth(count)) <= buffer.usedEnd)
}
}
/// \brief Create the implementation of an empty string. NOTE:
/// there is no null terminator in an empty string!
init() {
self.baseAddress = COpaquePointer()
self._countAndFlags = 0
self.owner = .None
}
/// \brief bitmask for the count part of _countAndFlags
/// Bitmask for the count part of _countAndFlags
var _countMask: UWord {
return UWord.max >> 2
}
/// \brief bitmask for the flags part of _countAndFlags
/// Bitmask for the flags part of _countAndFlags
var _flagMask: UWord {
return ~_countMask
}
/// \brief the number of elements stored
var count: Int {
return Int(_countAndFlags & _countMask)
set(newValue):
assert(UWord(newValue) & _flagMask == 0)
_countAndFlags = (_countAndFlags & _flagMask) | UWord(newValue)
}
/// \brief left shift amount to apply to an offset N so that when
/// added to a UnsafePointer<RawByte>, it traverses N elements
var elementShift: Int {
return Int(_countAndFlags >> (UWord.bitSize() - 1))
}
/// \brief the number of bytes per element
var elementSize: Int {
return elementShift + 1
}
/// \brief are we using an opaque NSString for storage?
var hasOpaqueBuffer: Bool {
return Word((_countAndFlags << 1).value) < 0
}
/// \brief Return the given sub-StringCore
subscript(subRange: Range<Int>) -> StringCore {
assert(subRange.startIndex() >= 0)
assert(subRange.endIndex() <= count)
let newCount = subRange.endIndex() - subRange.startIndex()
assert(UWord(newCount) & _flagMask == 0)
if (!hasOpaqueBuffer) {
return StringCore(
baseAddress: COpaquePointer(
UnsafePointer<RawByte>(baseAddress.value)
+ (subRange.startIndex() << elementShift)
),
_countAndFlags: (_countAndFlags & _flagMask) | UWord(newCount),
owner: owner)
}
return _opaqueSlice(subRange, newCount)
}
/// \brief helper function for the slicing subscript above.
/// Implements the slow path
func _opaqueSlice(subRange: Range<Int>, newCount: Int) -> StringCore {
alwaysTrap("IMPLEMENT ME")
}
/// \brief value by which to multiply a 2nd byte fetched in order to
/// Value by which to multiply a 2nd byte fetched in order to
/// assemble a UTF16 code unit from our contiguous storage. If we
/// store ASCII, this will be zero. Otherwise, it will be 0x100
var _highByteMultiplier: UTF16.CodeUnit {
return UTF16.CodeUnit(elementShift) << 8
}
/// \brief Get the Nth UTF16 Code Unit stored
/// Return a pointer to the Nth element of contiguous
/// storage. Caveats: The string must have contiguous storage; the
/// element may be 1 or 2 bytes wide, depending on elementWidth; the
/// result may be null if the string is empty.
func _pointerToNth(n: Int) -> COpaquePointer {
assert(hasContiguousStorage && n >= 0 && n <= count)
return COpaquePointer(
UnsafePointer<RawByte>(_baseAddress) + (n << elementShift))
}
static func _copyElements(
srcStart: COpaquePointer, srcElementWidth: Int,
dstStart: COpaquePointer, dstElementWidth: Int,
count: Int
) {
// Copy the old stuff into the new storage
if _fastPath(srcElementWidth == dstElementWidth) {
// No change in storage width; we can use memcpy
c_memcpy(
dest: UnsafePointer(dstStart),
src: UnsafePointer(srcStart),
size: UInt(count << (srcElementWidth - 1)))
}
else if (srcElementWidth < dstElementWidth) {
// Widening ASCII to UTF16; we need to copy the bytes manually
var dest = UnsafePointer<UTF16.CodeUnit>(dstStart)
var src = UnsafePointer<UTF8.CodeUnit>(srcStart)
let srcEnd = src + count
while (src != srcEnd) {
dest++.set(UTF16.CodeUnit(src++.get()))
}
}
else {
// Narrowing UTF16 to ASCII; we need to copy the bytes manually
var dest = UnsafePointer<UTF8.CodeUnit>(dstStart)
var src = UnsafePointer<UTF16.CodeUnit>(srcStart)
let srcEnd = src + count
while (src != srcEnd) {
dest++.set(UTF8.CodeUnit(src++.get()))
}
}
}
//===--------------------------------------------------------------------===//
// Initialization
init(
baseAddress: COpaquePointer,
count: Int,
elementShift: Int,
hasCocoaBuffer: Bool,
owner: AnyObject?
) {
assert(elementShift == 0 || elementShift == 1)
self._baseAddress = baseAddress
self._countAndFlags
= (UWord(elementShift) << UWord(sizeof(UWord.self) * 8 - 1))
| ((hasCocoaBuffer ? 1 : 0) << UWord(sizeof(UWord.self) * 8 - 2))
| UWord(count)
self._owner = owner
assert(UWord(count) & _flagMask == 0, "String too long to represent")
_invariantCheck()
}
/// Create a _StringCore that covers the entire length of the _StringBuffer.
init(_ buffer: _StringBuffer) {
self = _StringCore(
baseAddress: COpaquePointer(buffer.start),
count: buffer.usedCount,
elementShift: buffer.elementShift,
hasCocoaBuffer: false,
owner: buffer
)
}
/// Create the implementation of an empty string.
/// NOTE: there is no null terminator in an empty string!
init() {
self._baseAddress = _emptyStringBase
self._countAndFlags = 0
self._owner = .None
_invariantCheck()
}
//===--------------------------------------------------------------------===//
// Properties
/// The number of elements stored
var count: Int {
get {
return Int(_countAndFlags & _countMask)
}
set(newValue) {
assert(UWord(newValue) & _flagMask == 0)
_countAndFlags = (_countAndFlags & _flagMask) | UWord(newValue)
}
}
/// left shift amount to apply to an offset N so that when
/// added to a UnsafePointer<RawByte>, it traverses N elements
var elementShift: Int {
return Int(_countAndFlags >> UWord(sizeof(UWord.self) * 8 - 1))
}
/// the number of bytes per element
var elementWidth: Int {
return elementShift + 1
}
var hasContiguousStorage: Bool {
return _fastPath(_baseAddress != .null())
}
/// are we using an NSString for storage?
var hasCocoaBuffer: Bool {
return Word((_countAndFlags << 1).value) < 0
}
var startASCII: UnsafePointer<UTF8.CodeUnit> {
assert(elementWidth == 1, "String does not contain contiguous ASCII")
return UnsafePointer(_baseAddress)
}
var startUTF16: UnsafePointer<UTF16.CodeUnit> {
assert(
count == 0 || elementWidth == 2,
"String does not contain contiguous UTF16")
return UnsafePointer(_baseAddress)
}
/// the native _StringBuffer, if any, or .None.
var nativeBuffer: _StringBuffer? {
if !hasCocoaBuffer {
return _owner.map {
reinterpretCast($0) as _StringBuffer
}
}
return nil
}
/// the Cocoa String buffer, if any, or .None.
var cocoaBuffer: _CocoaString? {
if hasCocoaBuffer {
return _owner.map {
reinterpretCast($0) as _CocoaString
}
}
return nil
}
//===--------------------------------------------------------------------===//
// slicing
/// Return the given sub-_StringCore
subscript(subRange: Range<Int>) -> _StringCore {
assert(subRange.startIndex >= 0)
assert(subRange.endIndex <= count)
let newCount = subRange.endIndex - subRange.startIndex
assert(UWord(newCount) & _flagMask == 0)
if hasContiguousStorage {
return _StringCore(
baseAddress: _pointerToNth(subRange.startIndex),
_countAndFlags: (_countAndFlags & _flagMask) | UWord(newCount),
owner: _owner)
}
return _cocoaStringSlice(target: self, subRange: subRange)
}
/// Get the Nth UTF16 Code Unit stored
subscript(position: Int) -> UTF16.CodeUnit {
assert(position >= 0)
assert(position <= count)
if (!hasOpaqueBuffer) {
let p = UnsafePointer<UInt8>(baseAddress.value) + (position << elementShift)
if (_baseAddress != .null()) {
let p = UnsafePointer<UInt8>(_pointerToNth(position).value)
// Always dereference two bytes, but when elements are 8 bits we
// multiply the high byte by 0.
return UTF16.CodeUnit(p.get())
+ UTF16.CodeUnit((p + 1).get()) * _highByteMultiplier
}
return _opaqueSubscript(position)
return _cocoaStringSubscript(target: self, position: position)
}
/// \brief helper function for ordinary subscript above. Implements
/// the slow path
func _opaqueSubscript(position: Int) -> UTF16.CodeUnit {
alwaysTrap("IMPLEMENT ME")
/// Write the string, in the given encoding, to output.
func encode<
Encoding: UnicodeCodec,
Output: Sink
where Encoding.CodeUnit == Output.Element
>(encoding: Encoding.Type, output: Output)
{
if _fastPath(_baseAddress != .null()) {
if _fastPath(elementWidth == 1) {
var out = output
for x in UnsafeArray(
start: UnsafePointer<UTF8.CodeUnit>(_baseAddress), length: count
) {
Encoding.encode(UnicodeScalar(UInt32(x)), output: &out)
}
}
else {
transcode(UTF16.self, encoding,
UnsafeArray(
start: UnsafePointer<UTF16.CodeUnit>(_baseAddress),
length: count
),
output
)
}
}
else if (hasCocoaBuffer) {
_StringCore(
_cocoaStringToContiguous(source: cocoaBuffer!, range: 0...count,
minimumCapacity: 0)
).encode(encoding, output: output)
}
}
/// Attempt to claim unused capacity in the String's existing
/// native buffer, if any. Return zero and a pointer to the claimed
/// storage if successful. Otherwise, returns a suggested new
/// capacity and a null pointer.
///
/// Note: If successful, effectively appends garbage to the String
/// until it has newSize UTF16 code units; you must immediately copy
/// valid UTF16 into that storage.
///
/// Note: if unsuccessful because of insufficient space in an
/// existing buffer, the suggested new capacity will at least double
/// the existing buffer's storage
mutating func _claimCapacity(newSize: Int,
minElementWidth: Int) -> (Int, COpaquePointer) {
if _fastPath(nativeBuffer && elementWidth >= minElementWidth) {
var buffer = nativeBuffer!
// The buffer's "used" field must match this in order to be
// grown. Otherwise, some other String is using parts of
// the buffer beyond our last byte.
let matchUsed = _pointerToNth(count)
// Attempt to claim unused capacity in the buffer
if _fastPath(buffer.grow(
UnsafePointer<RawByte>(matchUsed.value), newUsedCount: newSize)) {
count = newSize
return (0, matchUsed)
}
else if newSize > buffer.capacity {
// Growth failed because of insufficient storage; double the size
return (max(buffer.capacity * 2, newSize), .null())
}
}
return (newSize, .null())
}
/// Ensure that this String references a _StringBuffer having
/// a capacity of at least newSize elements of at least the given width.
/// Effectively appends garbage to the String until it has newSize
/// UTF16 code units. Returns a pointer to the garbage code units;
/// you must immediately copy valid data into that storage.
mutating func _growBuffer(
newSize: Int, minElementWidth: Int
) -> COpaquePointer {
let (newCapacity, existingStorage)
= _claimCapacity(newSize, minElementWidth: minElementWidth)
if _fastPath(!existingStorage.isNull()) {
return existingStorage
}
// Allocate storage.
let newElementWidth =
minElementWidth >= elementWidth
? minElementWidth
: representableAsASCII() ? 1 : 2
var newStorage = _StringBuffer(capacity: newCapacity, initialSize: newSize,
elementWidth: newElementWidth)
var oldCount = count
if hasContiguousStorage {
_StringCore._copyElements(
_baseAddress, srcElementWidth: elementWidth,
dstStart: COpaquePointer(newStorage.start),
dstElementWidth: newElementWidth, count: oldCount)
}
else {
// Opaque cocoa buffers might not store ASCII, so assert that
// we've allocated for 2-byte elements.
// FIXME: can we get Cocoa to tell us quickly that an opaque
// string is ASCII? Do we care much about that edge case?
assert(newStorage.elementShift == 1)
_cocoaStringReadAll(source: cocoaBuffer!,
destination: UnsafePointer(newStorage.start))
}
self = _StringCore(newStorage)
return _pointerToNth(oldCount)
}
mutating func append(c: UnicodeScalar) {
_invariantCheck()
// How many bytes does it take to encode each UTF16 code unit of
// c if ASCII storage is available?
let minBytesPerCodeUnit = c.value <= 0x7f ? 1 : 2
// How many UTF16 code units does it take to encode c?
let utf16Width = c.value <= 0xFFFF ? 1 : 2
let destination = _growBuffer(count + utf16Width,
minElementWidth: minBytesPerCodeUnit)
if _fastPath(elementWidth == 1) {
assert(
_pointerToNth(count)
== COpaquePointer(UnsafePointer<RawByte>(destination) + 1))
UnsafePointer<UTF8.CodeUnit>(destination).set(UTF8.CodeUnit(c.value))
}
else {
let destination16 = UnsafePointer<UTF16.CodeUnit>(destination.value)
if _fastPath(utf16Width == 1) {
assert(_pointerToNth(count) == COpaquePointer(destination16 + 1))
destination16.set(UTF16.CodeUnit(c.value))
}
else {
assert(_pointerToNth(count) == COpaquePointer(destination16 + 2))
destination16.set(UTF16.leadSurrogate(c))
(destination16 + 1).set(UTF16.trailSurrogate(c))
}
}
_invariantCheck()
}
mutating func append(rhs: _StringCore) {
_invariantCheck()
let minElementWidth
= elementWidth >= rhs.elementWidth
? elementWidth
: rhs.representableAsASCII() ? 1 : 2
let destination = _growBuffer(count + rhs.count,
minElementWidth: minElementWidth)
if _fastPath(rhs.hasContiguousStorage) {
_StringCore._copyElements(
rhs._baseAddress, srcElementWidth: rhs.elementWidth,
dstStart: destination, dstElementWidth:elementWidth, count: rhs.count)
}
else {
assert(elementWidth == 2)
_cocoaStringReadAll(source: rhs.cocoaBuffer!,
destination: UnsafePointer(destination))
}
_invariantCheck()
}
/// Return true iff the contents of this string can be
/// represented as pure ASCII. O(N) in the worst case
func representableAsASCII() -> Bool {
if _slowPath(!hasContiguousStorage) {
return false
}
if _fastPath(elementWidth == 1) {
return true
}
return !contains(
UnsafeArray(start: UnsafePointer<UTF16.CodeUnit>(_baseAddress),
length: count)
) { $0 > 0x7f }
}
}
extension _StringCore : Collection {
var startIndex: Int {
return 0
}
var endIndex: Int {
return count
}
func generate() -> IndexingGenerator<_StringCore> {
return IndexingGenerator(self)
}
}
extension _StringCore : Sliceable {}
// Used to support a tighter invariant: all strings with contiguous
// storage have a non-NULL base address.
var _emptyStringStorage: UInt32 = 0
var _emptyStringBase: COpaquePointer {
return COpaquePointer(
UnsafePointer<UInt16>(Builtin.addressof(&_emptyStringStorage)))
}

View File

@@ -1,3 +1,16 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Interfaces with a questionable future that are needed in order to
// be a drop-in replacement for String
//
@@ -5,226 +18,162 @@ extension String {
init<
Encoding: UnicodeCodec, Input: Collection
where Input.StreamType.Element == Encoding.CodeUnit
where Input.GeneratorType.Element == Encoding.CodeUnit
>(
encoding: Encoding.metatype, input: Input
_ _encoding: Encoding.Type, input: Input
)
{
self = String(StringBuffer(encoding, input))
self = String(_StringBuffer(encoding: _encoding, input: input))
}
init(str_value : StringByteData) {
self = String(UTF8, UnsafeArray(str_value.base, str_value.length))
init(count sz: Int, character c: Character) {
let s = String(c)
self = String(_StringBuffer(capacity: s.core.count * sz,
initialSize: 0,
elementWidth: s.core.elementWidth))
for i in 0...sz {
self += s
}
}
init(sz: Int, c: UnicodeScalar) {
self = String(UTF32, GenerateN<UTF32.CodeUnit>(sz, c.value))
}
var str_value: StringByteData {
var utf8 = self.asUTF8()
return StringByteData.convertFromHeapArray(
utf8.base.value, utf8.owner,
utf8.count.value)
init(count: Int, scalar _c: UnicodeScalar) {
self = String(UTF32.self,
input: Repeat(count: count, repeatedValue: _c.value))
}
func asUTF8() -> UTF8.CodeUnit[] {
var result = new UTF8.CodeUnit[encodedLength(UTF8)]
var result = new UTF8.CodeUnit[_encodedLength(UTF8.self)]
var len = 0
encode(UTF8, SinkOf<UTF8.CodeUnit>({ result[len++] = $0 }))
_encode(UTF8.self, output: SinkOf<UTF8.CodeUnit>({ result[len++] = $0 }))
return result
}
func byteLength() -> Int {
return encodedLength(UTF8)
}
func nulTerminatedUTF8() -> StringByteData {
var buffer = str_value
var nul: UInt8[] = [0]
buffer.appendBytes(nul.base, 1)
swift_keepAlive(nul.owner)
return buffer
}
// FIXME: this typealias should die; it is only needed to satisfy
// test/NameBinding/library.swift. That test should be updated to
// not depend on stdlib details
typealias CharStreamType = UTF16Scalars.StreamType
var chars : UTF16Scalars {
return UTF16Scalars(_contiguous())
return _encodedLength(UTF8.self)
}
var lines : String[] {
return split('\n')
return split("\n")
}
func split(separator: UnicodeScalar) -> String[] {
var scalarSlices = swift.split(chars, { $0 == separator })
var scalarSlices = Swift.split(unicodeScalars, { $0 == separator })
return scalarSlices.map { $0 as String }
}
var bytes : StringByteData {
var result = StringByteData(byteLength())
encode(
UTF8, SinkOf<UTF8.CodeUnit>(
{
var tmp = $0
result.appendBytes(
UnsafePointer(Builtin.addressof(&tmp)), 1)
}
))
return result
}
func size() -> Int {
var count = 0
for c in chars {
for c in unicodeScalars {
++count
}
return count
}
var length: Int {
return size()
}
func isEmpty() -> Bool {
switch (representation) {
case .Opaque(var rep):
return rep.range.isEmpty()
case .Contiguous(var rep):
return rep.count == 0
}
}
type func _from(utf8: StringByteData) -> String {
return String(UTF8, UnsafeArray(utf8.base, utf8.length))
}
// FIXME: for some reason, making this function an actual overload
// of subscript breaks tests. Investigate later.
func subscript_(rng : IntStreamType) -> String {
return String._from(bytes[rng])
}
subscript (idx : Int) -> UnicodeScalar {
for (i, c) in swift.enumerate(chars) {
if i == idx {
return c
}
}
alwaysTrap()
return core.count == 0
}
}
extension String : ReplPrintable {
func replPrint() {
print('"')
for c in chars {
print("\"")
for c in unicodeScalars {
print(c.escape())
}
print('"')
print("\"")
}
}
extension String {
// FIXME: Locales make this interesting
var uppercase : String {
var str_value = self.bytes
var len = byteLength()
var resultArray = StringByteData.getNew(len)
var i = 0
while i != len {
var u8 = str_value[i]
let end = utf8.endIndex
var resultArray = NativeArray<UTF8.CodeUnit>(count: countElements(utf8),
value: 0)
var i = utf8.startIndex
var j = 0
while i != end {
let u8 = utf8[i++]
if u8 < 0x80 {
if (97 .. 123).contains(Int(u8)) {
resultArray[i] = u8 - 32
if 97...123 ~= u8 {
resultArray[j++] = u8 - 32
} else {
resultArray[i] = u8
resultArray[j++] = u8
}
i += 1
} else if u8 < 0xE0 {
resultArray[i] = u8
var u8_1 = str_value[i + 1]
if u8 == 0xC3 && (0xA0 .. 0xBF).contains(Int(u8_1)) && u8_1 != 0xB7 {
resultArray[i+1] = u8_1 - 0x20
resultArray[j++] = u8
let u8_1 = utf8[i++]
if u8 == 0xC3 && 0xA0...0xBF ~= Int(u8_1) && u8_1 != 0xB7 {
resultArray[j++] = u8_1 - 0x20
} else {
resultArray[i+1] = u8_1
resultArray[j++] = u8_1
}
i += 2
} else if u8 < 0xF0 {
resultArray[i] = u8
resultArray[i+1] = str_value[i+1]
resultArray[i+2] = str_value[i+2]
i += 3
} else {
resultArray[i] = u8
resultArray[i+1] = str_value[i+1]
resultArray[i+2] = str_value[i+2]
resultArray[i+3] = str_value[i+3]
i += 4
resultArray[j++] = u8
if u8 >= 0xF0 {
resultArray[j++] = utf8[i++]
}
resultArray[j++] = utf8[i++]
resultArray[j++] = utf8[i++]
}
}
return String._from(resultArray)
return String(UTF8.self, input: resultArray)
}
// FIXME: Locales make this interesting
var lowercase : String {
var str_value = self.bytes
var len = byteLength()
var resultArray = StringByteData.getNew(len)
var i = 0
while i != len {
var u8 = str_value[i]
let end = utf8.endIndex
var resultArray = NativeArray<UTF8.CodeUnit>(count: countElements(utf8),
value: 0)
var i = utf8.startIndex
var j = 0
while i != end {
let u8 = utf8[i++]
if u8 < 0x80 {
if (65 .. 91).contains(Int(u8)) {
resultArray[i] = u8 + 32
if 65...91 ~= u8 {
resultArray[j++] = u8 + 32
} else {
resultArray[i] = u8
resultArray[j++] = u8
}
i += 1
} else if u8 < 0xE0 {
resultArray[i] = u8
var u8_1 = str_value[i + 1]
if u8 == 0xC3 && (0x80 .. 0x9F).contains(Int(u8_1)) && u8_1 != 0x97 {
resultArray[i+1] = u8_1 + 0x20
resultArray[j++] = u8
let u8_1 = utf8[i++]
if u8 == 0xC3 && 0x80...0x9F ~= u8_1 && u8_1 != 0x97 {
resultArray[j++] = u8_1 + 0x20
} else {
resultArray[i+1] = u8_1
resultArray[j++] = u8_1
}
i += 2
} else if u8 < 0xF0 {
resultArray[i] = u8
resultArray[i+1] = str_value[i+1]
resultArray[i+2] = str_value[i+2]
i += 3
} else {
resultArray[i] = u8
resultArray[i+1] = str_value[i+1]
resultArray[i+2] = str_value[i+2]
resultArray[i+3] = str_value[i+3]
i += 4
resultArray[j++] = u8
if u8 >= 0xF0 {
resultArray[j++] = utf8[i++]
}
resultArray[j++] = utf8[i++]
resultArray[j++] = utf8[i++]
}
}
return String._from(resultArray)
return String(UTF8.self, input: resultArray)
}
init(c: UnicodeScalar) {
self = String(1, c)
init(_ _c: UnicodeScalar) {
self = String(count: 1, scalar: _c)
}
func _isAll(predicate: (UnicodeScalar) -> Bool) -> Bool {
for c in chars { if !predicate(c) { return false } }
for c in unicodeScalars { if !predicate(c) { return false } }
return true
}
func startsWith(prefix: String) -> Bool {
if prefix.size() > size() { return false }
return Swift.startsWith(self, prefix)
}
return self[0..prefix.size()] == prefix
func endsWith(suffix: String) -> Bool {
return Swift.startsWith(Reverse(self), Reverse(suffix))
}
func isAlpha() -> Bool { return _isAll({ $0.isAlpha() }) }
@@ -235,114 +184,125 @@ extension String {
extension String : FormattedPrintable {
func format(kind: UnicodeScalar, layout: String) -> String {
var toPrint = self
if kind == 'u' { toPrint = uppercase }
else if kind == 'l' { toPrint = lowercase }
if kind == "u" { toPrint = uppercase }
else if kind == "l" { toPrint = lowercase }
return Format(layout).printToString(toPrint)
}
}
/// \brief Represent a positive integer value in the given radix,
/// writing each UTF-16 code units into stream. The value of `ten'
/// should be either 'A' or 'a', depending on whether you want upper-
/// writing each ASCII character into stream. The value of `ten'
/// should be either "A" or "a", depending on whether you want upper-
/// or lower-case letters when radix > 10
func _formatPositiveInteger(
value: UInt64,
radix: UInt64,
ten: UnicodeScalar = 'a') ( stream: (UTF16.CodeUnit)->Void )
ten: UnicodeScalar = "a") ( stream: (UTF8.CodeUnit)->Void )
{
if value == 0 {
return
}
_formatPositiveInteger(value / radix, radix, ten)(stream)
_formatPositiveInteger(value / radix, radix, ten: ten)(stream: stream)
var digit = UInt32(value % radix)
var baseCharOrd : UInt32 = digit <= 9 ? '0'.value : ten.value - 10
stream(UTF16.CodeUnit(baseCharOrd + digit))
var baseCharOrd: UInt32 = digit <= 9 ? _asUnicodeCodePoint("0")
: _asUnicodeCodePoint(ten) - 10
stream(UTF8.CodeUnit(baseCharOrd + digit))
}
func _formatSignedInteger(
value: Int64,
radix: UInt64,
ten: UnicodeScalar = 'a') ( stream: (UTF16.CodeUnit)->Void ) {
ten: UnicodeScalar = "a") ( stream: (UTF8.CodeUnit)->Void ) {
if value == 0 {
stream (UTF16.CodeUnit('0'.value))
stream(UTF8.CodeUnit(_asUnicodeCodePoint("0")))
}
else {
if (value < 0) {
stream(UTF16.CodeUnit('-'.value))
let minusCharacter: UnicodeScalar = "-"
stream(UTF8.CodeUnit(_asUnicodeCodePoint("-")))
}
// Compute the absolute value without causing overflow when value
// == Int64.min
let absValue = value < 0 ? UInt64(~value) + 1 : UInt64(value)
_formatPositiveInteger(absValue, radix, ten)(stream)
_formatPositiveInteger(absValue, radix, ten: ten)(stream: stream)
}
}
// Conversions to string from other types.
extension String {
init(v: Int64, radix: Int = 10, uppercase: Bool = false) {
var format = _formatSignedInteger(v, UInt64(radix), uppercase ? 'A' : 'a')
var utf16Count = 0
format { _ in ++utf16Count;() }
var buffer = StringBuffer(utf16Count)
var used = buffer.used
format { used++.set($0) }
buffer.used = used
init(_ v: Int64, radix: Int = 10, uppercase: Bool = false) {
var format = _formatSignedInteger(v, UInt64(radix),
ten: uppercase ? "A" : "a")
var asciiCount = 0
format(stream: { _ in ++asciiCount;() })
var buffer = _StringBuffer(
capacity: asciiCount, initialSize: asciiCount, elementWidth: 1)
var p = UnsafePointer<UTF8.CodeUnit>(buffer.start)
format(stream: { p++.set($0) })
self = String(buffer)
}
init(v : UInt64, radix: Int = 10, uppercase: Bool = false) {
var format = _formatPositiveInteger(v, UInt64(radix), uppercase ? 'A' : 'a')
var utf16Count = v == 0 ? 1 : 0
format { _ in ++utf16Count;() }
var buffer = StringBuffer(utf16Count)
var used = buffer.used
format { used++.set($0) }
// FIXME: This function assumes UTF16
init(_ v: UInt64, radix: Int = 10, uppercase: Bool = false) {
var format = _formatPositiveInteger(v, UInt64(radix),
ten: uppercase ? "A" : "a")
var asciiCount = v == 0 ? 1 : 0
format(stream: { _ in ++asciiCount;() })
var buffer = _StringBuffer(
capacity: asciiCount, initialSize: asciiCount, elementWidth: 1)
var p = UnsafePointer<UTF8.CodeUnit>(buffer.start)
format(stream: { p++.set($0) })
if v == 0 {
used++.set(UTF16.CodeUnit('0'.value))
p++.set(UTF8.CodeUnit("0"))
}
buffer.used = used
self = String(buffer)
}
init(v : Int8, radix : Int = 10, uppercase : Bool = false) {
self = String(Int64(v), radix, uppercase)
init(_ v : Int8, radix : Int = 10, uppercase : Bool = false) {
self = String(Int64(v), radix: radix, uppercase: uppercase)
}
init(v : Int16, radix : Int = 10, uppercase : Bool = false) {
self = String(Int64(v), radix, uppercase)
init(_ v : Int16, radix : Int = 10, uppercase : Bool = false) {
self = String(Int64(v), radix: radix, uppercase: uppercase)
}
init(v : Int32, radix : Int = 10, uppercase : Bool = false) {
self = String(Int64(v), radix, uppercase)
init(_ v : Int32, radix : Int = 10, uppercase : Bool = false) {
self = String(Int64(v), radix: radix, uppercase: uppercase)
}
init(v : UInt8, radix : Int = 10, uppercase : Bool = false) {
self = String(UInt64(v), radix, uppercase)
init(_ v : Int, radix : Int = 10, uppercase : Bool = false) {
self = String(Int64(v), radix: radix, uppercase: uppercase)
}
init(v : UInt16, radix : Int = 10, uppercase : Bool = false) {
self = String(UInt64(v), radix, uppercase)
init(_ v : UInt8, radix : Int = 10, uppercase : Bool = false) {
self = String(UInt64(v), radix: radix, uppercase: uppercase)
}
init(v : UInt32, radix : Int = 10, uppercase : Bool = false) {
self = String(UInt64(v), radix, uppercase)
init(_ v : UInt16, radix : Int = 10, uppercase : Bool = false) {
self = String(UInt64(v), radix: radix, uppercase: uppercase)
}
init(_ v : UInt32, radix : Int = 10, uppercase : Bool = false) {
self = String(UInt64(v), radix: radix, uppercase: uppercase)
}
init(_ v : UInt, radix : Int = 10, uppercase : Bool = false) {
self = String(UInt64(v), radix: radix, uppercase: uppercase)
}
init(v : Double) {
var cCharBuf = Array<UInt8>(256, 0)
var n = Int(c_print_double(cCharBuf.base.value, v))
var buffer = StringBuffer(n)
var used = buffer.used
for i in 0..n {
used++.set(UTF16.CodeUnit(cCharBuf[i]))
init(_ v : Double) {
var cCharBuf = UInt8[](count: 256, value: 0)
var n = Int(c_print_double(cCharBuf.elementStorage.value, v))
var buffer = _StringBuffer(capacity: n, initialSize: n, elementWidth: 1)
var p = UnsafePointer<UTF8.CodeUnit>(buffer.start)
for i in 0...n {
p++.set(cCharBuf[i])
}
buffer.used = used
self = String(buffer)
}
init(v : Float) {
init(_ v : Float) {
self = String(Double(v))
}
init(b : Bool) {
init(_ b : Bool) {
if b {
self = "true"
} else {
@@ -356,19 +316,19 @@ extension String {
/// \brief If the string represents an integer that fits into an Int, returns
/// the corresponding integer.
func toInt() -> Int? {
var scalars = self.chars
var scalars = self.unicodeScalars
var start = scalars.startIndex()
if start == scalars.endIndex() {
var start = scalars.startIndex
if start == scalars.endIndex {
return .None
}
// Interpet '+' or '-' before the number.
var negativeFactor = -1
var firstC = scalars[start]
if (firstC == '+') {
if (firstC == "+") {
++start
} else if (firstC == '-') {
} else if (firstC == "-") {
++start
negativeFactor = 1
}
@@ -377,7 +337,7 @@ extension String {
// Since Int.min has a larger absolute value, perform addition with
// negative numbers; detect underflows before they happen.
var res : Int = 0
for c in scalars[start..scalars.endIndex()] {
for c in scalars[start...scalars.endIndex] {
if !c.isDigit() {
// Conversion failed if a non-digit is encountered.
return .None
@@ -389,7 +349,7 @@ extension String {
}
res = res * 10
var d : Int = (c - '0')
var d : Int = (c - "0")
// Underflow occurs if res - d < Int.min.
if res < Int.min + d {
return .None
@@ -411,12 +371,12 @@ extension String {
/// \brief Produce a substring of the given string from the given character
/// index to the end of the string.
func substr(start: Int) -> String {
var rng = chars
var startIndex = rng.startIndex()
for i in 0..start {
var rng = unicodeScalars
var startIndex = rng.startIndex
for i in 0...start {
++startIndex
}
return rng[startIndex..rng.endIndex()]
return rng[startIndex...rng.endIndex]
}
/// \brief Split the given string at the given delimiter character, returning
@@ -425,10 +385,10 @@ extension String {
func splitFirst(delim: UnicodeScalar)
-> (before: String, after: String, wasFound : Bool)
{
var rng = chars
var rng = unicodeScalars
for i in indices(rng) {
if rng[i] == delim {
return (rng[rng.startIndex()..i], rng[i.succ()..rng.endIndex()], true)
return (rng[rng.startIndex...i], rng[i.succ()...rng.endIndex], true)
}
}
return (self, "", false)
@@ -441,20 +401,20 @@ extension String {
func splitFirstIf(pred: (UnicodeScalar) -> Bool)
-> (before: String, found: UnicodeScalar, after: String, wasFound: Bool)
{
var rng = chars
var rng = unicodeScalars
for i in indices(rng) {
if pred(rng[i]) {
return (rng[rng.startIndex()..i], rng[i], rng[i.succ()..rng.endIndex()], true)
return (rng[rng.startIndex...i], rng[i], rng[i.succ()...rng.endIndex], true)
}
}
return (self, '🎃', String(), false)
return (self, "🎃", String(), false)
}
/// \brief Split the given string at each occurrence of a character for which
/// the given predicate evaluates true, returning an array of strings that
/// before/between/after those delimiters.
func splitIf(pred: (UnicodeScalar) -> Bool) -> String[] {
var scalarSlices = swift.split(chars, pred)
var scalarSlices = Swift.split(unicodeScalars, pred)
return scalarSlices.map { $0 as String }
}
}

View File

@@ -1,4 +1,4 @@
//===--- StringUTF8.swift - A UTF8 view of StringCore ---------------------===//
//===--- StringUTF8.swift - A UTF8 view of _StringCore ---------------------===//
//
// This source file is part of the Swift.org open source project
//
@@ -10,14 +10,14 @@
//
//===----------------------------------------------------------------------===//
//
// StringCore currently has three representations: Native ASCII,
// _StringCore currently has three representations: Native ASCII,
// Native UTF16, and Opaque Cocoa. Expose each of these as UTF8 in a
// way that will hopefully be efficient to traverse
//
//===----------------------------------------------------------------------===//
extension StringCore {
extension _StringCore {
// An integral type that holds a chunk of UTF8, starting in its low
// byte
typealias UTF8Chunk = UInt64
@@ -38,9 +38,9 @@ extension StringCore {
var result: UTF8Chunk = ~0 // start with all bits set
c_memcpy(
UnsafePointer(Builtin.addressof(&result)),
UnsafePointer(startASCII + i),
numericCast(utf16Count))
dest: UnsafePointer(Builtin.addressof(&result)),
src: UnsafePointer(startASCII + i),
size: numericCast(utf16Count))
return (i + utf16Count, result)
}
@@ -125,17 +125,22 @@ extension StringCore {
return (nextIndex, result)
}
else {
return _cocoaStringEncodeSomeUTF8(self, i)
return _cocoaStringEncodeSomeUTF8(target: self, position: i)
}
}
}
extension String {
struct UTF8View : Collection {
let _core: StringCore
let _core: _StringCore
init(_ _core: _StringCore) {
self._core = _core
}
struct Index : ForwardIndex {
init(_core: StringCore, _coreIndex: Int, _buffer: StringCore.UTF8Chunk) {
init(_ _core: _StringCore, _ _coreIndex: Int,
_ _buffer: _StringCore.UTF8Chunk) {
self._core = _core
self._coreIndex = _coreIndex
self._buffer = _buffer
@@ -158,9 +163,9 @@ extension String {
return Index(_core, _coreIndex, ~0)
}
let _core: StringCore
let _core: _StringCore
let _coreIndex: Int
let _buffer: StringCore.UTF8Chunk
let _buffer: _StringCore.UTF8Chunk
}
var startIndex: Index {

View File

@@ -1,23 +1,33 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// Conversions between different Unicode encodings. Note that these
// are *not* currently resilient to erroneous data.
import swift
typealias UnicodeScalar = Char
protocol UnicodeCodec {
typealias CodeUnit
static def decode(next: ()->CodeUnit?) -> UnicodeScalar?
static def encode(input: UnicodeScalar, output: (CodeUnit)->())
class func decode<G : Generator where G.Element == CodeUnit>(inout next:G) -> UnicodeScalar?
class func encode<S : Sink where S.Element == CodeUnit>(input: UnicodeScalar,inout output: S)
}
struct UTF8 : UnicodeCodec {
typealias CodeUnit = UInt8
static def decode(next: ()->CodeUnit?) -> UnicodeScalar? {
static func decode<G : Generator where G.Element == CodeUnit>(inout next:G) -> UnicodeScalar? {
var c = next()
var c = next.next()
if !c {
return .None
}
@@ -26,10 +36,10 @@ struct UTF8 : UnicodeCodec {
// one octet (7 bits)
if c0 < 0x80 {
return Char(UInt32(c0))
return UnicodeScalar(UInt32(c0))
}
var c1 = next()!
var c1 = next.next()!
// start with octet 1 (we'll mask off high bits later)
var result = UInt32(c0)
@@ -37,109 +47,231 @@ struct UTF8 : UnicodeCodec {
if c0 < 0xE0 {
return UnicodeScalar(result & 0x000007FF) // 11 bits
}
c1 = next()! // prefetch octet 3
c1 = next.next()! // prefetch octet 3
result = (result << 6) | UInt32(c1 & 0x3F) // merge octet 3
if c0 < 0xF0 {
return UnicodeScalar(result & 0x0000FFFF) // 16 bits
}
c1 = next()! // prefetch octet 4
c1 = next.next()! // prefetch octet 4
result = (result << 6) | UInt32(c1 & 0x3F) // merge octet 4
return UnicodeScalar(result & 0x001FFFFF) // 21 bits
}
static def encode(input: UnicodeScalar, output: (CodeUnit)->()) {
static func encode<S : Sink where S.Element == CodeUnit>(
input: UnicodeScalar,inout output: S) {
var c = UInt32(input)
var buf3 = UInt8(c)
var buf3 = UInt8(c & 0xFF)
if c >= UInt32(1<<7) {
c >>= 6
buf3 = (buf3 & 0x3F) | 0x80 // 10xxxxxx
var buf2 = UInt8(c)
var buf2 = UInt8(c & 0xFF)
if c < UInt32(1<<5) {
buf2 |= 0xC0 // 110xxxxx
}
else {
c >>= 6
buf2 = (buf2 & 0x3F) | 0x80 // 10xxxxxx
var buf1 = UInt8(c)
var buf1 = UInt8(c & 0xFF)
if c < UInt32(1<<4) {
buf1 |= 0xE0 // 1110xxxx
}
else {
c >>= 6
buf1 = (buf1 & 0x3F) | 0x80 // 10xxxxxx
output(UInt8(c | 0xF0)) // 11110xxx
output.put(UInt8(c | 0xF0)) // 11110xxx
}
output(buf1)
output.put(buf1)
}
output(buf2)
output.put(buf2)
}
output(buf3)
output.put(buf3)
}
var _value: UInt8
var _value = UInt8()
}
struct UTF16 : UnicodeCodec {
typealias CodeUnit = UInt16
static def decode(next: ()->CodeUnit?) -> UnicodeScalar? {
var first = next()
static func decode<G : Generator where G.Element == CodeUnit>(inout input:G) -> UnicodeScalar? {
let first = input.next()
if !first {
return .None
}
var unit0 = UInt32(first!)
let unit0 = UInt32(first!)
if (unit0 >> 11) != 0x1B {
return UnicodeScalar(unit0)
}
var unit1 = UInt32(next()!)
return UnicodeScalar(
0x10000
+ ((unit0 - 0xD800) << 10)
+ (unit1 - 0xDC00))
let unit1 = UInt32(input.next()!)
// FIXME: Uglified due to type checker performance issues.
var result : UInt32 = 0x10000
result += ((unit0 - 0xD800) << 10)
result += (unit1 - 0xDC00)
return UnicodeScalar(result)
}
static def encode(input: UnicodeScalar, output: (UInt16)->()) {
static func encode<S : Sink where S.Element == CodeUnit>(
input: UnicodeScalar,inout output: S) {
var scalarValue: UInt32 = UInt32(input)
if UInt32(UInt16(scalarValue)) == scalarValue {
output(UInt16(scalarValue))
if scalarValue <= UInt32(UInt16.max) {
output.put(UInt16(scalarValue))
}
else {
var lead_offset = UInt32(0xD800) - (0x10000 >> 10)
output(UInt16(lead_offset + (scalarValue >> 10)))
output(UInt16(0xDC00 + (scalarValue & 0x3FF)))
output.put(UInt16(lead_offset + (scalarValue >> 10)))
output.put(UInt16(0xDC00 + (scalarValue & 0x3FF)))
}
}
var _value: UInt16
var _value = UInt16()
}
struct UTF32 : UnicodeCodec {
typealias CodeUnit = UInt32
static def create(value: CodeUnit) -> UTF32 {
init(_ _value: UInt32) {
self._value = _value
}
static func create(value: CodeUnit) -> UTF32 {
return UTF32(value)
}
def value() -> CodeUnit {
func value() -> CodeUnit {
return self._value
}
static def decode(next: ()->CodeUnit?) -> UnicodeScalar? {
var x = next()
static func decode<G : Generator where G.Element == CodeUnit>(
inout input:G) -> UnicodeScalar? {
var x = input.next()
if x {
return UnicodeScalar(x!)
}
return .None
}
static def encode(input: UnicodeScalar, output: (UInt32)->()) {
output(UInt32(input))
static func encode<S : Sink where S.Element == CodeUnit>(
input: UnicodeScalar,inout output: S) {
output.put(UInt32(input))
}
var _value: UInt32
var _value = UInt32()
}
func transcode<
Input: Generator,
Output: Sink,
InputEncoding: UnicodeCodec,
OutputEncoding: UnicodeCodec
where InputEncoding.CodeUnit == Input.Element,
OutputEncoding.CodeUnit == Output.Element> (
inputEncoding: InputEncoding.Type, outputEncoding: OutputEncoding.Type,
var input: Input, var output: Output
) {
for var scalar = InputEncoding.decode(&input);
scalar;
scalar = InputEncoding.decode(&input)
{
var s = scalar!
OutputEncoding.encode(s, output: &output)
}
}
// Trivial transcoder; I'm hoping this will kick in for common cases
func transcode<
Input: Generator,
Output: Sink,
Encoding: UnicodeCodec
where Encoding.CodeUnit == Input.Element, Encoding.CodeUnit == Output.Element
> (
inputEncoding: Encoding.Type, outputEncoding: Encoding.Type,
var input: Input, var output: Output
) {
while true {
var x = input.next()
if !x {
break
}
output.put(x!)
}
}
protocol StringElement {
class func toUTF16CodeUnit(_: Self) -> UTF16.CodeUnit
class func fromUTF16CodeUnit(utf16: UTF16.CodeUnit) -> Self
}
extension UTF16.CodeUnit : StringElement {
static func toUTF16CodeUnit(x: UTF16.CodeUnit) -> UTF16.CodeUnit {
return x
}
static func fromUTF16CodeUnit(utf16: UTF16.CodeUnit) -> UTF16.CodeUnit {
return utf16
}
}
extension UTF8.CodeUnit : StringElement {
static func toUTF16CodeUnit(x: UTF8.CodeUnit) -> UTF16.CodeUnit {
return UTF16.CodeUnit(x)
}
static func fromUTF16CodeUnit(utf16: UTF16.CodeUnit) -> UTF8.CodeUnit {
return UTF8.CodeUnit(utf16)
}
}
extension UTF16 {
static func width(x: UnicodeScalar) -> Int {
return x.value <= 0xFFFF ? 1 : 2
}
static func leadSurrogate(x: UnicodeScalar) -> UTF16.CodeUnit {
assert(width(x) == 2)
return (UTF16.CodeUnit(x.value - 0x1_0000) >> 10) + 0xD800
}
static func trailSurrogate(x: UnicodeScalar) -> UTF16.CodeUnit {
assert(width(x) == 2)
return (UTF16.CodeUnit(x.value - 0x1_0000) & ((1 << 10) - 1)) + 0xDC00
}
static func copy<T: StringElement, U: StringElement>(
source: UnsafePointer<T>, destination: UnsafePointer<U>, count: Int
) {
if UWord(Builtin.strideof(T.self)) == UWord(Builtin.strideof(U.self)) {
c_memcpy(
dest: UnsafePointer(destination),
src: UnsafePointer(source),
size: UInt(count) * UInt(Builtin.strideof(U.self)))
}
else {
for i in 0...count {
let u16 = T.toUTF16CodeUnit((source + i).get())
(destination + i).set(U.fromUTF16CodeUnit(u16))
}
}
}
static func measure<Encoding: UnicodeCodec, Input: Generator where Encoding.CodeUnit == Input.Element>(
_: Encoding.Type, var input: Input
) -> (Int, Bool) {
var count = 0
var isAscii = true
while true {
if let x = Encoding.decode(&input) {
if x.value > 0x7f {
isAscii = false
}
count += width(x)
}
else {
break
}
}
return (count, isAscii)
}
}

View File

@@ -1,51 +1,66 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// UnicodeScalar Type
//===----------------------------------------------------------------------===//
struct UnicodeScalar : BuiltinCharacterLiteralConvertible, CharacterLiteralConvertible,
ReplPrintable {
var _value : Builtin.Int21
struct UnicodeScalar :
ExtendedGraphemeClusterLiteralConvertible, ReplPrintable {
var value : UInt32 {
get:
var zextValue = Builtin.zext_Int21_Int32(_value)
return UInt32(zextValue)
var _value: Builtin.Int32
var value: UInt32 {
get {
return UInt32(_value)
}
}
static func _convertFromBuiltinCharacterLiteral(val: Builtin.Int21) -> UnicodeScalar {
return UnicodeScalar(val)
}
static func convertFromCharacterLiteral(value: UnicodeScalar) -> UnicodeScalar {
return value
static func convertFromExtendedGraphemeClusterLiteral(
value: String) -> UnicodeScalar {
let unicodeScalars = value.unicodeScalars
return unicodeScalars[unicodeScalars.startIndex]
}
init() {
self._value = Builtin.trunc_Int32_Int21(Int32(0).value)
self._value = Int32(0).value
}
init(value : Builtin.Int21) {
init(_ value : Builtin.Int32) {
self._value = value
}
init(v : UInt32) {
init(_ v : UInt32) {
var lowHalf = v & 0xFFFF
// reserved in each plane
debugTrap(lowHalf != 0xFFFE && lowHalf != 0xFFFF)
assert(lowHalf != 0xFFFE && lowHalf != 0xFFFF)
// UTF-16 surrogate pair values are not valid code points
debugTrap(v < 0xD800 || v > 0xDFFF)
assert(v < 0xD800 || v > 0xDFFF)
// U+FDD0...U+FDEF are also reserved
debugTrap(v < 0xFDD0 || v > 0xFDEF)
assert(v < 0xFDD0 || v > 0xFDEF)
// beyond what is defined to be valid
debugTrap(v < 0x10FFFF)
assert(v < 0x10FFFF)
self._value = Builtin.trunc_Int32_Int21(v.value)
self._value = v.value
}
init(_ v: UnicodeScalar) {
// This constructor allows one to provide necessary type context to
// disambiguate between function overloads on 'String' and 'UnicodeScalar'.
self = v
}
func replPrint() {
print('\'')
print("\"")
print(escape())
print('\'')
print("\"")
}
func escape() -> String {
@@ -58,21 +73,21 @@ struct UnicodeScalar : BuiltinCharacterLiteralConvertible, CharacterLiteralConve
}
}
if self == '\\' {
if self == "\\" {
return "\\\\"
} else if self == '"' {
return "\\\""
} else if self == '\'' {
} else if self == "\'" {
return "\\\'"
} else if self == "\"" {
return "\\\""
} else if isPrint() {
return String(self)
} else if self == '\0' {
} else if self == "\0" {
return "\\0"
} else if self == '\n' {
} else if self == "\n" {
return "\\n"
} else if self == '\r' {
} else if self == "\r" {
return "\\r"
} else if self == '\t' {
} else if self == "\t" {
return "\\t"
} else if UInt32(self) < 128 {
return "\\x"
@@ -110,19 +125,19 @@ struct UnicodeScalar : BuiltinCharacterLiteralConvertible, CharacterLiteralConve
// FIXME: Locales make this interesting
func isAlpha() -> Bool {
return (self >= 'A' && self <= 'Z') || (self >= 'a' && self <= 'z')
return (self >= "A" && self <= "Z") || (self >= "a" && self <= "z")
}
// FIXME: Locales make this interesting
func isDigit() -> Bool {
return self >= '0' && self <= '9'
return self >= "0" && self <= "9"
}
// FIXME: Locales make this interesting
var uppercase : UnicodeScalar {
if self >= 'a' && self <= 'z' {
if self >= "a" && self <= "z" {
return UnicodeScalar(UInt32(self) - 32)
} else if self >= 'à' && self <= 'þ' && self != '÷' {
} else if self >= "à" && self <= "þ" && self != "÷" {
return UnicodeScalar(UInt32(self) - 32)
}
return self
@@ -130,9 +145,9 @@ struct UnicodeScalar : BuiltinCharacterLiteralConvertible, CharacterLiteralConve
// FIXME: Locales make this interesting
var lowercase : UnicodeScalar {
if self >= 'A' && self <= 'Z' {
if self >= "A" && self <= "Z" {
return UnicodeScalar(UInt32(self) + 32)
} else if self >= 'À' && self <= 'Þ' && self != '×' {
} else if self >= "À" && self <= "Þ" && self != "×" {
return UnicodeScalar(UInt32(self) + 32)
}
return self
@@ -143,43 +158,43 @@ struct UnicodeScalar : BuiltinCharacterLiteralConvertible, CharacterLiteralConve
// FIXME: The constraint-based type checker goes painfully exponential
// when we turn this into one large expression. Break it up for now,
// until we can optimize the constraint solver better.
if self == ' ' || self == '\t' { return true }
if self == '\n' || self == '\r' { return true }
return self == '\x0B' || self == '\x0C'
if self == " " || self == "\t" { return true }
if self == "\n" || self == "\r" { return true }
return self == "\x0B" || self == "\x0C"
}
}
extension UnicodeScalar : FormattedPrintable {
func format(kind: UnicodeScalar, layout: String) -> String {
return String(self).format(kind, layout)
return String(self).format(kind, layout: layout)
}
}
extension UnicodeScalar : Hashable {
func hashValue() -> Int {
var hashValue: Int {
return Int(self.value)
}
}
extension UnicodeScalar {
init(v : Int) {
init(_ v : Int) {
self = UnicodeScalar(UInt32(v))
}
}
extension UInt8 {
init(v : UnicodeScalar) {
debugTrap(v.value <= UInt32(UInt8.max), "Code point value does not fit into UInt8")
init(_ v : UnicodeScalar) {
assert(v.value <= UInt32(UInt8.max), "Code point value does not fit into UInt8")
self = UInt8(v.value)
}
}
extension UInt32 {
init(v : UnicodeScalar) {
init(_ v : UnicodeScalar) {
self = v.value
}
}
extension UInt64 {
init(v : UnicodeScalar) {
init(_ v : UnicodeScalar) {
self = UInt64(v.value)
}
}
@@ -216,3 +231,19 @@ extension UnicodeScalar {
return (self >= UnicodeScalar(0o040) && self <= UnicodeScalar(0o176))
}
}
/// Helpers to provide type context to guide type inference in code like::
///
/// var zero = _asUnicodeCodePoint('0')
func _asUnicodeCodePoint(us: UnicodeScalar) -> Builtin.Int32 {
return us._value
}
func _asUnicodeCodePoint(us: UnicodeScalar) -> UInt32 {
return us.value
}
func _asUTF16CodeUnit(us: UnicodeScalar) -> UTF16.CodeUnit {
var codePoint = us.value
assert(codePoint <= UInt32(UInt16.max))
return UTF16.CodeUnit(codePoint)
}

View File

@@ -15,7 +15,7 @@
/// When you use this type, you become partially responsible for
/// keeping the object alive.
struct Unmanaged<T: AnyObject> {
@unowned(unsafe) var _value: T
unowned(unsafe) var _value: T
@transparent
init(_private: T) { _value = _private }
@@ -85,13 +85,19 @@ struct Unmanaged<T: AnyObject> {
/// Get the value of this unmanaged reference as a managed
/// reference without consuming an unbalanced retain of it.
var unretainedValue: T {
///
/// This is useful when a function returns an unmanaged reference
/// and you know that you're not responsible for releasing the result.
func takeUnretainedValue() -> T {
return _value
}
/// Get the value of this unmanaged reference as a managed
/// reference and consume an unbalanced retain of it.
var retainedValue: T {
///
/// This is useful when a function returns an unmanaged reference
/// and you know that you're responsible for releasing the result.
func takeRetainedValue() -> T {
let result = _value
release()
return result
@@ -103,7 +109,7 @@ struct Unmanaged<T: AnyObject> {
/// for ensuring that the types are actually compatible at
/// runtime.
func bridgeUnretainedValueTo<U: AnyObject>() -> U {
return reinterpretCast(unretainedValue)
return reinterpretCast(takeUnretainedValue())
}
/// Get the value of this unmanaged reference as an managed
@@ -112,7 +118,7 @@ struct Unmanaged<T: AnyObject> {
/// for ensuring that the types are actually compatible at
/// runtime.
func bridgeRetainedValueTo<U: AnyObject>() -> U {
return reinterpretCast(retainedValue)
return reinterpretCast(takeRetainedValue())
}
/// Perform an unbalanced retain of the object.

View File

@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
/// \brief Wrapper for a contiguous array of T. UnsafeArray is both a
/// Wrapper for a contiguous array of T. UnsafeArray is both a
/// Collectionwhich is multi-pass if you use indices or call
/// generate() on itand a Generator, which can only be assumed to be
/// single-pass. It's not clear how well this combination will work
@@ -18,10 +18,6 @@
/// this an experiment.
struct UnsafeArray<T> : Collection, Generator {
func countElements() -> Int {
return endIndex - startIndex
}
var startIndex: Int {
return 0
}

View File

@@ -1,4 +1,16 @@
/// \brief A wrapper around a C pointer to type T.
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// A wrapper around a C pointer to type T.
///
/// This wrapper stores a C pointer to an object of type T, and is
/// intended to be used to interface with C libraries. It provides no
@@ -8,163 +20,329 @@
/// For C pointers for which the pointed-to type cannot be represented
/// directly in Swift, the \c COpaquePointer will be used instead.
struct UnsafePointer<T> : BidirectionalIndex, Comparable, Hashable {
/// \brief The underlying raw (untyped) pointer.
/// The underlying raw (untyped) pointer.
var value : Builtin.RawPointer
/// \brief Construct a null pointer.
constructor() {
this.value = Builtin.inttoptr_Int64(0.value)
/// Construct a null pointer.
init() {
self.value = Builtin.inttoptr_Word(0.value)
}
/// \brief Construct an UnsafePointer from a builtin raw pointer.
constructor(value : Builtin.RawPointer) {
this.value = value
/// Construct an UnsafePointer from a builtin raw pointer.
init(_ value : Builtin.RawPointer) {
self.value = value
}
/// \brief Convert from an opaque C pointer to a typed C pointer.
/// Convert from an opaque C pointer to a typed C pointer.
///
/// This is a fundamentally unsafe conversion.
constructor(other : COpaquePointer) {
init(_ other : COpaquePointer) {
value = other.value
}
/// \brief Convert from a pointer of a different type.
/// Construct an UnsafePointer from a given address in memory.
///
/// This is a fundamentally unsafe conversion.
constructor<U>(from : UnsafePointer<U>) {
init(_ value : Int) {
self.value = Builtin.inttoptr_Word(value.value)
}
/// Convert from a pointer of a different type.
///
/// This is a fundamentally unsafe conversion.
init<U>(_ from : UnsafePointer<U>) {
value = from.value
}
static func null() -> UnsafePointer<T> {
static func null() -> UnsafePointer {
return UnsafePointer()
}
/// \brief Get the address of an lvalue.
///
/// This is a fundamentally unsafe operation. The validity of the address
/// cannot be guaranteed beyond the scope of the statement containing the
/// constructed pointer. If the lvalue is a logical property, any value
/// written to the pointer will be written back to the property, and the
/// pointer will be invalidated at the end of the statement.
static func addressOf(lv : [byref] T) -> UnsafePointer<T> {
return UnsafePointer(Builtin.addressof(&lv))
}
static func alloc(num : Int) -> UnsafePointer<T> {
static func alloc(num: Int) -> UnsafePointer {
// Don't both with overflow checking.
var size = Int(Builtin.strideof(T)) * num
return UnsafePointer(Builtin.allocRaw(size.value, Builtin.alignof(T)))
var size = Int(Builtin.strideof(T.self)) * num
return UnsafePointer(Builtin.allocRaw(size.value, Builtin.alignof(T.self)))
}
func dealloc(num : Int) {
func dealloc(num: Int) {
// Overflow checking is actually not required here.
var size = Int(Builtin.strideof(T)) * num
var size = Int(Builtin.strideof(T.self)) * num
Builtin.deallocRaw(value, size.value)
}
/// \brief Retrieve the value the pointer points to.
/// Retrieve the value the pointer points to.
@transparent
func get() -> T {
debugTrap(!isNull())
return Builtin.load(value)
}
/// \brief Set the value the pointer points to, copying over the
/// Set the value the pointer points to, copying over the
/// previous value.
func set(newvalue : T) {
debugTrap(!isNull())
func set(newvalue: T) {
Builtin.assign(newvalue, value)
}
/// \brief Initialize the value the pointer points to, to construct
/// Initialize the value the pointer points to, to construct
/// an object where there was no object previously stored.
func init(newvalue : T) {
debugTrap(!isNull())
Builtin.init(newvalue, value)
func initialize(newvalue: T) {
Builtin.initialize(newvalue, value)
}
/// \brief Retrieve the value the pointer points to, moving it away
/// Retrieve the value the pointer points to, moving it away
/// from the location referenced in memory.
///
/// The object in memory should not be used again (except perhaps to
/// initialize or destroy it).
/// Postcondition: The value has been destroyed and the memory must
/// be initialized before being used again.
func move() -> T {
debugTrap(!isNull())
return Builtin.move(value)
return Builtin.take(value)
}
/// \brief Destroy the object the pointer points to.
/// Move count values beginning at source into uninitialized memory,
/// transforming the source values into raw memory, proceeding from
/// the last value to the first. Use this for copying ranges into
/// later memory that may overlap with the source range.
///
/// Requires: either `source` precedes `self` or follows `self + count`.
func moveInitializeBackwardFrom(source: UnsafePointer, count: Int) {
assert(
source <= self || source > self + count,
"moveInitializeBackwardFrom non-preceding overlapping range; use moveInitializeFrom instead")
var src = source + count
var dst = self + count
while dst != self {
(--dst).initialize((--src).move())
}
}
/// Assign from count values beginning at source into initialized
/// memory, transforming the source values into raw memory.
func moveAssignFrom(source: UnsafePointer, count: Int) {
assert(
source > self || source < self - count,
"moveAssignFrom non-following overlapping range")
for i in 0...count {
self[i] = (source + i).move()
}
}
/// Move count values beginning at source into raw memory,
/// transforming the source values into raw memory.
func moveInitializeFrom(source: UnsafePointer, count: Int) {
assert(
source >= self || source < self - count,
"moveInitializeFrom non-following overlapping range; use moveInitializeBackwardFrom")
for i in 0...count {
(self + i).initialize((source + i).move())
}
}
/// Copy count values beginning at source into raw memory.
func initializeFrom(source: UnsafePointer, count: Int) {
assert(
source >= self || source < self - count,
"initializeFrom non-following overlapping range")
for i in 0...count {
(self + i).initialize(source[i])
}
}
/// Copy the elements of `C` into raw memory.
func initializeFrom<
C: Collection where C._Element == T
>(
source: C
) {
var p = self
for x in source {
p++.initialize((x as T)!)
}
}
/// Destroy the object the pointer points to.
func destroy() {
debugTrap(!isNull())
Builtin.destroy(T, value)
Builtin.destroy(T.self, value)
}
/// Destroy the `count` objects the pointer points to.
func destroy(count: Int) {
Builtin.destroyArray(T.self, value, count.value)
}
func isNull() -> Bool {
return this == UnsafePointer.null()
return self == UnsafePointer.null()
}
subscript (i : Int) -> T {
get:
debugTrap(!isNull())
return (this + i).get()
set:
debugTrap(!isNull())
(this + i).set(value)
@transparent
get {
return (self + i).get()
}
@transparent
nonmutating set {
(self + i).set(newValue)
}
}
//
// Protocol conformance
//
func __equal__(rhs: UnsafePointer<T>) -> Bool {
return _getBool(Builtin.cmp_eq_RawPointer(value, rhs.value))
var hashValue: Int {
return Int(Builtin.ptrtoint_Word(value))
}
func __less__(rhs: UnsafePointer<T>) -> Bool {
return _getBool(Builtin.cmp_ult_RawPointer(value, rhs.value))
func succ() -> UnsafePointer {
return self + 1
}
func hashValue() -> Int {
return Int(Builtin.ptrtoint_Int64(value))
func pred() -> UnsafePointer {
return self - 1
}
func succ() -> UnsafePointer<T> {
return this + 1
//
// Conversion to C argument pointers
//
// FIXME: Should be in an extension, but that doesn't work yet.
@transparent @conversion
func __conversion() -> CMutablePointer<T> {
return CMutablePointer(owner: _nilNativeObject, value: value)
}
func pred() -> UnsafePointer<T> {
return this - 1
func __conversion() -> CMutableVoidPointer {
return CMutableVoidPointer(owner: _nilNativeObject, value: value)
}
@transparent @conversion
func __conversion() -> CConstPointer<T> {
return CConstPointer(_nilNativeObject, value)
}
@transparent @conversion
func __conversion() -> CConstVoidPointer {
return CConstVoidPointer(_nilNativeObject, value)
}
@transparent @conversion
func __conversion() -> ObjCMutablePointer<T> {
return ObjCMutablePointer(value)
}
/// Construct from a CConstPointer.
///
/// This is an explicit construction because it is not always safe.
/// It is only allowed to convert an unscoped pointer, that is, one
/// that does not have a lifetime-guaranteeing owner reference. To use
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
/// must be used instead.
init(_ cp: CConstPointer<T>) {
assert(!cp.scoped,
"scoped CConstPointers must be converted using withUnsafePointer")
self.value = cp.value
}
/// Construct from a CMutablePointer.
///
/// This is an explicit construction because it is not always safe.
/// It is only allowed to convert an unscoped pointer, that is, one
/// that does not have a lifetime-guaranteeing owner reference. To use
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
/// must be used instead.
init(_ cm: CMutablePointer<T>) {
assert(!cm.scoped,
"scoped CMutablePointers must be converted using withUnsafePointer")
self.value = cm.value
}
/// Construct from an ObjCMutablePointer.
///
/// This is an explicit construction
/// because it is unsafe--UnsafePointer's store operations assume that
/// the pointed-to storage has strong ownership, whereas ObjCMutablePointers
/// reference +0 storage. Any values stored through the resulting
/// UnsafePointer must be autoreleased.
init(_ op: ObjCMutablePointer<T>) {
self.value = op.value
}
/// Construct from a CConstVoidPointer.
///
/// This is an explicit construction because it is not always safe.
/// It is only allowed to convert an unscoped pointer, that is, one
/// that does not have a lifetime-guaranteeing owner reference. To use
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
/// must be used instead.
init(_ cp: CConstVoidPointer) {
assert(!cp.scoped,
"scoped CConstPointers must be converted using withUnsafePointer")
self.value = cp.value
}
/// Construct from a CMutableVoidPointer.
///
/// This is an explicit construction because it is not always safe.
/// It is only allowed to convert an unscoped pointer, that is, one
/// that does not have a lifetime-guaranteeing owner reference. To use
/// a scoped pointer as an UnsafePointer, the withUnsafePointer method
/// must be used instead.
init(_ cp: CMutableVoidPointer) {
assert(!cp.scoped,
"scoped CMutableVoidPointers must be converted using withUnsafePointer")
self.value = cp.value
}
}
// FIXME: Should we expose/use size_t and ptrdiff_t?
@transparent
func == <T> (lhs: UnsafePointer<T>, rhs: UnsafePointer<T>) -> Bool {
return Bool(Builtin.cmp_eq_RawPointer(lhs.value, rhs.value))
}
func + <T>(lhs : UnsafePointer<T>,
rhs : Int64) -> UnsafePointer<T> {
debugTrap(!lhs.isNull())
@transparent
func < <T>(lhs: UnsafePointer<T>, rhs: UnsafePointer<T>) -> Bool {
return Bool(Builtin.cmp_ult_RawPointer(lhs.value, rhs.value))
}
@transparent
func + <T>(lhs: UnsafePointer<T>, rhs: Int) -> UnsafePointer<T> {
return UnsafePointer(
Builtin.gep_Int64(lhs.value,
(rhs * Int(Builtin.strideof(T))).value))
Builtin.gep_Word(lhs.value, (rhs * Int(Builtin.strideof(T.self))).value))
}
func + <T>(lhs : Int64,
rhs : UnsafePointer<T>) -> UnsafePointer<T> {
@transparent
func + <T>(lhs: Int,
rhs: UnsafePointer<T>) -> UnsafePointer<T> {
return rhs + lhs
}
func - <T>(lhs : UnsafePointer<T>,
rhs : Int64) -> UnsafePointer<T> {
@transparent
func - <T>(lhs: UnsafePointer<T>, rhs: Int) -> UnsafePointer<T> {
return lhs + -rhs
}
func - <T>(lhs : UnsafePointer<T>,
rhs : UnsafePointer<T>) -> Int {
debugTrap((!lhs.isNull() && !rhs.isNull()) ||
(lhs.isNull() && rhs.isNull()),
"subtracting unrelated pointers")
return Int(Builtin.sub_Int64(Builtin.ptrtoint_Int64(lhs.value),
Builtin.ptrtoint_Int64(rhs.value)))
@transparent
func - <T>(lhs: UnsafePointer<T>, rhs: UnsafePointer<T>) -> Int {
return
Int(Builtin.sub_Word(Builtin.ptrtoint_Word(lhs.value),
Builtin.ptrtoint_Word(rhs.value)))
/ Int(Builtin.strideof(T.self))
}
func [assignment] += <T>(lhs : [byref] UnsafePointer<T>, rhs : Int64) {
@transparent
@assignment func += <T>(inout lhs: UnsafePointer<T>, rhs: Int) {
lhs = lhs + rhs
}
func [assignment] -= <T>(lhs : [byref] UnsafePointer<T>, rhs : Int64) {
@transparent
@assignment func -= <T>(inout lhs: UnsafePointer<T>, rhs: Int) {
lhs = lhs - rhs
}
/// A byte-sized thing that isn't designed to interoperate with
/// any other types; it makes a decent parameter to UnsafePointer when
/// you just want to do bytewise pointer arithmetic.
struct RawByte {
let _inaccessible: UInt8
}
// Make nil work with UnsafePointer
extension _Nil {
@transparent
@conversion func __conversion<T>() -> UnsafePointer<T> {
return .null()
}
}

View File

@@ -1,33 +1,57 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
protocol CVarArg {
func encode() -> Word[]
}
#if arch(x86_64)
let _x86_64CountGPRegisters = 6
let _x86_64CountSSERegisters = 8
let _x86_64SSERegisterWords = 2
let _x86_64RegisterSaveWords = _x86_64CountGPRegisters + _x86_64CountSSERegisters * _x86_64SSERegisterWords
#endif
@asmname="swift_runningOnX86_64" func swift_runningOnX86_64() -> Bool
func withVaList<R>(args: CVarArg[], f: (CVaList)->R) -> R {
var argList: C_va_list = makeC_va_list()
func withVaList<R>(args: CVarArg[], f: (CVaListPointer)->R) -> R {
var builder = VaListBuilder()
for a in args {
argList.append(a)
builder.append(a)
}
return f(argList)
return withVaList(builder, f)
}
func withVaList<R>(builder: VaListBuilder, f: (CVaListPointer)->R) -> R {
let result = f(builder.va_list())
_fixLifetime(builder)
return result
}
// FIXME: workaround for <rdar://problem/15715225>
func sizeof(_:Word.metatype) -> Int {
return Int(Word(Builtin.sizeof(Word)))
func getVaList(args: CVarArg[]) -> CVaListPointer {
var builder = VaListBuilder()
for a in args {
builder.append(a)
}
// FIXME: Use some Swift equivalent of NS_RETURNS_INNER_POINTER if we get one.
Builtin.retain(builder)
Builtin.autorelease(builder)
return builder.va_list()
}
func encodeBitsAsWords<T: CVarArg>(x: T) -> Word[] {
var result = Array<Word>(
(sizeof(T) + sizeof(Word) - 1) / sizeof(Word), 0)
c_memcpy(result.base, addressof(&x), UInt64(sizeof(T)))
var result = Word[](count: (sizeof(T.self) + sizeof(Word.self) - 1) / sizeof(Word.self), value: 0)
var tmp = x
c_memcpy(dest: UnsafePointer(result.elementStorage),
src: UnsafePointer(Builtin.addressof(&tmp)),
size: UInt(sizeof(T.self)))
return result
}
@@ -36,6 +60,12 @@ func encodeBitsAsWords<T: CVarArg>(x: T) -> Word[] {
// encoding.
// Signed types
extension Int : CVarArg {
func encode() -> Word[] {
return encodeBitsAsWords(self)
}
}
extension Int64 : CVarArg {
func encode() -> Word[] {
return encodeBitsAsWords(self)
@@ -61,6 +91,12 @@ extension Int8 : CVarArg {
}
// Unsigned types
extension UInt : CVarArg {
func encode() -> Word[] {
return encodeBitsAsWords(self)
}
}
extension UInt64 : CVarArg {
func encode() -> Word[] {
return encodeBitsAsWords(self)
@@ -103,14 +139,10 @@ extension Double : CVarArg {
}
}
protocol C_va_list {
func append(arg: CVarArg)
#if !arch(x86_64)
@conversion
func __conversion() -> COpaquePointer
}
struct BasicC_va_list : C_va_list {
@final
class VaListBuilder {
func append(arg: CVarArg) {
for x in arg.encode() {
@@ -118,43 +150,41 @@ struct BasicC_va_list : C_va_list {
}
}
@conversion
func __conversion() -> COpaquePointer {
return COpaquePointer(storage.base)
func va_list() -> CVaListPointer {
return CVaListPointer(fromUnsafePointer: UnsafePointer<Void>(storage.elementStorage))
}
var storage: Word[] = Array<Word>()
var storage = Word[]()
}
func &&<T: LogicValue>(a: T, b: @auto_closure () -> T) -> T {
return a ? b() : a
}
#else
func ||<T: LogicValue>(a: T, b: @auto_closure () -> T) -> T {
return a ? a : b()
}
struct X86_64_va_list : C_va_list {
@final
class VaListBuilder {
struct Header {
var gp_offset = CUnsignedInt(0)
var fp_offset = CUnsignedInt(_x86_64CountGPRegisters * sizeof(Word))
var fp_offset = CUnsignedInt(_x86_64CountGPRegisters * strideof(Word.self))
var overflow_arg_area: UnsafePointer<Word> = UnsafePointer<Word>.null()
var reg_save_area: UnsafePointer<Word> = UnsafePointer<Word>.null()
}
init() {
// prepare the register save area
storage = Array(_x86_64RegisterSaveWords, Word(0))
storage = Array(count: _x86_64RegisterSaveWords, value: 0)
}
func append(arg: CVarArg) {
var encoded = arg.encode()
if ((arg as Float) || (arg as Double)) && sseRegistersUsed < _x86_64CountSSERegisters {
var startIndex = _x86_64CountGPRegisters + (sseRegistersUsed * _x86_64SSERegisterWords)
var endIndex = startIndex + encoded.count
storage[startIndex..endIndex] = encoded
if ((arg as Float) || (arg as Double))
&& sseRegistersUsed < _x86_64CountSSERegisters {
var startIndex = _x86_64CountGPRegisters
+ (sseRegistersUsed * _x86_64SSERegisterWords)
for w in encoded {
storage[startIndex] = w
++startIndex
}
++sseRegistersUsed
}
else if encoded.count == 1 && gpRegistersUsed < _x86_64CountGPRegisters {
@@ -167,24 +197,20 @@ struct X86_64_va_list : C_va_list {
}
}
@conversion
func __conversion() -> COpaquePointer {
header.reg_save_area = storage.base
header.overflow_arg_area = storage.base + _x86_64RegisterSaveWords
return COpaquePointer(addressof(&self.header))
func va_list() -> CVaListPointer {
header.reg_save_area = storage.elementStorage
header.overflow_arg_area = storage.elementStorage + _x86_64RegisterSaveWords
return CVaListPointer(
fromUnsafePointer: UnsafePointer<Void>(
Builtin.addressof(&self.header)))
}
var gpRegistersUsed = 0
var sseRegistersUsed = 0
@final // Property must be final since it is used by Builtin.addressof.
var header = Header()
var storage: Word[]
}
func makeC_va_list() -> C_va_list {
if swift_runningOnX86_64() {
return X86_64_va_list()
}
else {
return BasicC_va_list()
}
}
#endif

View File

@@ -1,42 +1,49 @@
struct ZipEnumerator2<E0 : Enumerator, E1 : Enumerator> : Enumerator
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
struct ZipGenerator2<E0 : Generator, E1 : Generator> : Generator
{
typealias Element = (E0.Element,E1.Element)
constructor(e0: E0, e1: E1) {
baseEnumerators.value = (e0,e1)
init(_ e0: E0, _ e1: E1) {
baseStreams = (e0,e1)
}
func isEmpty() -> Bool {
if baseEnumerators.value.0.isEmpty() {
return true
}
return baseEnumerators.value.1.isEmpty()
mutating func next() -> Element? {
var e0 = baseStreams.0.next()
if !e0 { return .None }
var e1 = baseStreams.1.next()
if !e1 { return .None }
return .Some((e0!, e1!))
}
func next() -> Element {
return (
baseEnumerators.value.0.next(),
baseEnumerators.value.1.next())
}
var baseEnumerators : GenericIVar<(E0,E1)>
var baseStreams : (E0,E1)
}
struct Zip2<S0: Enumerable, S1: Enumerable> : Enumerable
struct Zip2<S0: Sequence, S1: Sequence> : Sequence
{
typealias Enumerator1 = S0.EnumeratorType
typealias Enumerator2 = S1.EnumeratorType
typealias EnumeratorType = ZipEnumerator2<Enumerator1, Enumerator2>
typealias Stream1 = S0.GeneratorType
typealias Stream2 = S1.GeneratorType
typealias GeneratorType = ZipGenerator2<Stream1, Stream2>
constructor(s0: S0, s1: S1) {
sequences.value = (s0,s1)
init(_ s0: S0, _ s1: S1) {
sequences = (s0,s1)
}
func getEnumeratorType() -> EnumeratorType {
return EnumeratorType(
sequences.value.0.getEnumeratorType(),
sequences.value.1.getEnumeratorType())
func generate() -> GeneratorType {
return GeneratorType(
sequences.0.generate(),
sequences.1.generate())
}
var sequences: GenericIVar<(S0,S1)>
var sequences: (S0,S1)
}

View File

@@ -1,5 +1,17 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Foundation
import AppKit
@exported import AppKit
class REPLApplication : NSApplication {
}
@@ -8,16 +20,72 @@ class REPLApplication : NSApplication {
func replApplicationMain() {
assert(NSApp === nil)
// Create a REPLApplication as the NSApp.
var app = REPLApplication.sharedApplication() as! REPLApplication
let app = (REPLApplication.sharedApplication() as REPLApplication)!
// Set the activation policy so we get a dock icon and can go foreground.
// FIXME: enum type
app.setActivationPolicy(
NSApplicationActivationPolicy(NSApplicationActivationPolicyRegular))
app.setActivationPolicy(.Regular)
// Run asynchronously.
app.performSelector("run", withObject:nil, afterDelay:0.0)
NSOperationQueue.mainQueue().addOperationWithBlock { app.run() }
// Quit the NSApplication when the REPL quits.
atREPLExit({ app.terminate(nil) })
_atREPLExit({ app.terminate(nil) })
}
struct _NSViewMirror : Mirror {
var _v : NSView
init(_ v : NSView) {_v = v}
var value: Any { get { return _v } }
var valueType: Any.Type { get { return (_v as Any).dynamicType } }
var objectIdentifier: ObjectIdentifier? { get { return .None } }
var count: Int { get { return 0 } }
subscript(_: Int) -> (String,Mirror) { get { fatal("don't ask") } }
var summary: String { get { return ""} }
var quickLookObject: QuickLookObject? { get {
// this code comes straight from the quicklooks
/*NSBitmapImageRep *b = (NSBitmapImageRep *)[%dataValueName% bitmapImageRepForCachingDisplayInRect:(NSRect)[%dataValueName% bounds]];
(void)[%dataValueName% cacheDisplayInRect:(NSRect)[%dataValueName% bounds] toBitmapImageRep:b];
(NSData *)[b representationUsingType:4 properties:nil];*/
let bounds = _v.bounds
// we need to do this check to avoid the @unchecked -> Any -> NSObject cast failure
if var b = _v.bitmapImageRepForCachingDisplayInRect(bounds) {
_v.cacheDisplayInRect(bounds, toBitmapImageRep: b)
// don't do the last step - return the image and the encoder will translate the NSImage to a TIFF alright
return .Some(.View(b))
}
return nil
} }
var disposition : MirrorDisposition { get { return .Aggregate } }
}
extension NSView : Reflectable {
func getMirror() -> Mirror {
return _NSViewMirror(self)
}
}
// Overlays for variadics.
extension NSGradient {
convenience init(colorsAndLocations objects: (AnyObject, CGFloat)...) {
let colors : AnyObject[] = new AnyObject[objects.count] { objects[$0].0 }
let locations = new CGFloat[objects.count] { objects[$0].1 }
self.init(colors: asNSArray(colors), atLocations: locations.elementStorage, colorSpace: NSColorSpace.genericRGBColorSpace())
_fixLifetime(locations)
}
}

View File

@@ -18,7 +18,51 @@
//===----------------------------------------------------------------------===//
extension CGPoint : Equatable {
static var zeroPoint: CGPoint { get { return CGPoint(0, 0) } }
static var zeroPoint: CGPoint { get { return CGPoint(x: 0, y: 0) } }
init() {
self.init(x: 0.0, y: 0.0)
}
init(x: Int, y: Int) {
self.init(x: CGFloat(x), y: CGFloat(y))
}
}
struct _CGPointMirror : Mirror {
let _value : CGPoint
init(_ x : CGPoint) {
_value = x
}
var value: Any { return _value }
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 2 }
subscript(i: Int) -> (String, Mirror) {
switch i {
case 0: return ("x",reflect(_value.x))
case 1: return ("y",reflect(_value.y))
default: fatal("cannot extract this child index")
}
}
var summary: String { return "(\(_value.x),\(_value.y))" }
var quickLookObject: QuickLookObject? { return .Some(.Point(Double(_value.x),Double(_value.y))) }
var disposition: MirrorDisposition { return .Aggregate }
}
extension CGPoint : Reflectable {
func getMirror() -> Mirror {
return _CGPointMirror(self)
}
}
func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
@@ -27,7 +71,51 @@ func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
extension CGSize : Equatable {
static var zeroSize: CGSize { get { return CGSize(0, 0) } }
static var zeroSize: CGSize { return CGSize(width: 0, height: 0) }
init() {
self.init(width: 0.0, height: 0.0)
}
init(width: Int, height: Int) {
self.init(width: CGFloat(width), height: CGFloat(height))
}
}
struct _CGSizeMirror : Mirror {
let _value : CGSize
init(_ x : CGSize) {
_value = x
}
var value: Any { return _value }
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 2 }
subscript(i: Int) -> (String, Mirror) {
switch i {
case 0: return ("x",reflect(_value.width))
case 1: return ("y",reflect(_value.height))
default: fatal("cannot extract this child index")
}
}
var summary: String { return "(\(_value.width),\(_value.height))" }
var quickLookObject: QuickLookObject? { return .Some(.Size(Double(_value.width),Double(_value.height))) }
var disposition: MirrorDisposition { return .Aggregate }
}
extension CGSize : Reflectable {
func getMirror() -> Mirror {
return _CGSizeMirror(self)
}
}
func == (lhs: CGSize, rhs: CGSize) -> Bool {
@@ -37,6 +125,14 @@ func == (lhs: CGSize, rhs: CGSize) -> Bool {
extension CGVector : Equatable {
static var zeroVector: CGVector { get { return CGVector(0, 0) } }
init(_ dx: CGFloat, _ dy: CGFloat) {
self.init(dx: CGFloat(dx), dy: CGFloat(dy))
}
init(_ dx: Int, _ dy: Int) {
self.init(CGFloat(dx), CGFloat(dy))
}
}
func == (lhs: CGVector, rhs: CGVector) -> Bool {
@@ -45,12 +141,24 @@ func == (lhs: CGVector, rhs: CGVector) -> Bool {
extension CGRect : Equatable {
static var zeroRect: CGRect { get { return CGRect(0, 0, 0, 0) } }
static var zeroRect: CGRect {
return CGRect(x: 0, y: 0, width: 0, height: 0)
}
static var nullRect: CGRect { get { return CGRectNull } }
static var infiniteRect: CGRect { get { return CGRectInfinite } }
init() {
self.init(origin: CGPoint(), size: CGSize())
}
init(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) {
self.init(origin:CGPoint(x, y), size:CGSize(width, height))
self.init(origin: CGPoint(x: x, y: y),
size: CGSize(width: width, height: height))
}
init(x: Int, y: Int, width: Int, height: Int) {
self.init(origin: CGPoint(x: x, y: y),
size: CGSize(width: width, height: height))
}
var width: CGFloat { get { return CGRectGetWidth(self) } }
@@ -72,7 +180,7 @@ extension CGRect : Equatable {
get { return CGRectStandardize(self) }
}
@mutating func standardize() {
mutating func standardize() {
self = self.standardizedRect
}
@@ -80,26 +188,26 @@ extension CGRect : Equatable {
get { return CGRectIntegral(self) }
}
@mutating func integerize() {
mutating func integerize() {
self = self.integerRect
}
func rectByInsetting(dx: CGFloat, dy: CGFloat) -> CGRect {
func rectByInsetting(`dx: CGFloat, dy: CGFloat) -> CGRect {
return CGRectInset(self, dx, dy)
}
@mutating func inset(dx: CGFloat, dy: CGFloat) {
self = self.rectByInsetting(dx, dy)
mutating func inset(`dx: CGFloat, dy: CGFloat) {
self = self.rectByInsetting(dx: dx, dy: dy)
}
func rectByOffsetting(dx: CGFloat, dy: CGFloat) -> CGRect {
func rectByOffsetting(`dx: CGFloat, dy: CGFloat) -> CGRect {
return CGRectOffset(self, dx, dy)
}
@mutating func offset(dx: CGFloat, dy: CGFloat) {
self = self.rectByOffsetting(dx, dy)
mutating func offset(`dx: CGFloat, dy: CGFloat) {
self = self.rectByOffsetting(dx: dx, dy: dy)
}
@@ -107,7 +215,7 @@ extension CGRect : Equatable {
return CGRectUnion(self, withRect)
}
@mutating func union(withRect: CGRect) {
mutating func union(withRect: CGRect) {
self = self.rectByUnion(withRect)
}
@@ -115,7 +223,7 @@ extension CGRect : Equatable {
return CGRectIntersection(self, withRect)
}
@mutating func intersect(withRect: CGRect) {
mutating func intersect(withRect: CGRect) {
self = self.rectByIntersecting(withRect)
}
@@ -143,6 +251,42 @@ extension CGRect : Equatable {
}
}
struct _CGRectMirror : Mirror {
let _value : CGRect
init(_ x : CGRect) {
_value = x
}
var value: Any { return _value }
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 2 }
subscript(i: Int) -> (String, Mirror) {
switch i {
case 0: return ("x",reflect(_value.origin))
case 1: return ("y",reflect(_value.size))
default: fatal("cannot extract this child index")
}
}
var summary: String { return "(\(_value.origin.x),\(_value.origin.y),\(_value.size.width),\(_value.size.height))" }
var quickLookObject: QuickLookObject? { return .Some(.Rectangle(Double(_value.origin.x),Double(_value.origin.y),Double(_value.size.width),Double(_value.size.height))) }
var disposition: MirrorDisposition { return .Aggregate }
}
extension CGRect : Reflectable {
func getMirror() -> Mirror {
return _CGRectMirror(self)
}
}
func == (lhs: CGRect, rhs: CGRect) -> Bool {
return CGRectEqualToRect(lhs, rhs)
}

View File

@@ -20,3 +20,16 @@ var errno : Int32 {
__error().set(newValue)
}
}
@availability(*, unavailable, message="Please use threads or posix_spawn*()")
func fork() -> Int32 {
errno = ENOSYS
return -1
}
@availability(*, unavailable, message="Please use threads or posix_spawn*()")
func vfork() -> Int32 {
errno = ENOSYS
return -1
}

View File

@@ -31,7 +31,13 @@ let DISPATCH_QUEUE_PRIORITY_HIGH = dispatch_queue_priority_t(2)
let DISPATCH_QUEUE_PRIORITY_DEFAULT = dispatch_queue_priority_t(0)
let DISPATCH_QUEUE_PRIORITY_LOW = dispatch_queue_priority_t(-2)
let DISPATCH_QUEUE_PRIORITY_BACKGROUND = dispatch_queue_priority_t(-32768)
// FIXME: DISPATCH_QUEUE_CONCURRENT
var DISPATCH_QUEUE_CONCURRENT : dispatch_queue_attr_t {
get { return _swift_dispatch_queue_concurrent() }
}
@asmname("_swift_dispatch_queue_concurrent")
func _swift_dispatch_queue_concurrent() -> dispatch_queue_attr_t
// dispatch/source.h
// FIXME: DISPATCH_SOURCE_TYPE_*
@@ -52,6 +58,63 @@ let DISPATCH_VNODE_RENAME = dispatch_source_vnode_flags_t(0x20)
let DISPATCH_VNODE_REVOKE = dispatch_source_vnode_flags_t(0x40)
let DISPATCH_TIMER_STRICT = dispatch_source_timer_flags_t(1)
var DISPATCH_SOURCE_TYPE_DATA_ADD : dispatch_source_type_t {
get { return _swift_dispatch_source_type_data_add() }
}
var DISPATCH_SOURCE_TYPE_DATA_OR : dispatch_source_type_t {
get { return _swift_dispatch_source_type_data_or() }
}
var DISPATCH_SOURCE_TYPE_MACH_SEND : dispatch_source_type_t {
get { return _swift_dispatch_source_type_mach_send() }
}
var DISPATCH_SOURCE_TYPE_MACH_RECV : dispatch_source_type_t {
get { return _swift_dispatch_source_type_mach_recv() }
}
var DISPATCH_SOURCE_TYPE_MEMORYPRESSURE : dispatch_source_type_t {
get { return _swift_dispatch_source_type_memorypressure() }
}
var DISPATCH_SOURCE_TYPE_READ : dispatch_source_type_t {
get { return _swift_dispatch_source_type_read() }
}
var DISPATCH_SOURCE_TYPE_PROC : dispatch_source_type_t {
get { return _swift_dispatch_source_type_proc() }
}
var DISPATCH_SOURCE_TYPE_SIGNAL : dispatch_source_type_t {
get { return _swift_dispatch_source_type_signal() }
}
var DISPATCH_SOURCE_TYPE_TIMER : dispatch_source_type_t {
get { return _swift_dispatch_source_type_timer() }
}
var DISPATCH_SOURCE_TYPE_VNODE : dispatch_source_type_t {
get { return _swift_dispatch_source_type_vnode() }
}
var DISPATCH_SOURCE_TYPE_WRITE : dispatch_source_type_t {
get { return _swift_dispatch_source_type_write() }
}
@asmname("_swift_dispatch_source_type_DATA_ADD")
func _swift_dispatch_source_type_data_add() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_DATA_OR")
func _swift_dispatch_source_type_data_or() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_MACH_SEND")
func _swift_dispatch_source_type_mach_send() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_MACH_RECV")
func _swift_dispatch_source_type_mach_recv() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_MEMORYPRESSURE")
func _swift_dispatch_source_type_memorypressure() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_PROC")
func _swift_dispatch_source_type_proc() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_READ")
func _swift_dispatch_source_type_read() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_SIGNAL")
func _swift_dispatch_source_type_signal() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_TIMER")
func _swift_dispatch_source_type_timer() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_VNODE")
func _swift_dispatch_source_type_vnode() -> dispatch_source_type_t
@asmname("_swift_dispatch_source_type_WRITE")
func _swift_dispatch_source_type_write() -> dispatch_source_type_t
// dispatch/time.h
// DISPATCH_TIME_NOW: ok
// DISPATCH_TIME_FOREVER: ok

File diff suppressed because it is too large Load Diff

View File

@@ -23,11 +23,12 @@ extension NSObject {
forKeyPath keyPath: String!,
kvoContext: KVOContext)
{
let ptr = CMutableVoidPointer(kvoContext, reinterpretCast(kvoContext))
let ptr = CMutableVoidPointer(owner: kvoContext,
value: reinterpretCast(kvoContext))
self.removeObserver(observer,
forKeyPath: keyPath,
context: ptr)
Unmanaged(kvoContext).release()
Unmanaged(_private: kvoContext).release()
}
func addObserver(observer: NSObject!,
@@ -35,8 +36,9 @@ extension NSObject {
options: NSKeyValueObservingOptions,
kvoContext: KVOContext)
{
let ptr = CMutableVoidPointer(kvoContext, reinterpretCast(kvoContext))
Unmanaged(kvoContext).retain()
let ptr = CMutableVoidPointer(owner: kvoContext,
value: reinterpretCast(kvoContext))
Unmanaged(_private: kvoContext).retain()
self.addObserver(observer,
forKeyPath: keyPath,
options: options,

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,15 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@exported
import ObjectiveC
@@ -12,6 +24,10 @@ import ObjectiveC
struct ObjCBool : ReplPrintable {
var value : Bool
init(_ value: Bool) {
self.value = value
}
/// \brief Allow use in a Boolean context.
func getLogicValue() -> Bool {
return value == true

View File

@@ -1,3 +1,15 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@exported
import ObjectiveC
@@ -10,6 +22,10 @@ import ObjectiveC
struct ObjCBool : ReplPrintable {
var value : Int8
init(_ value: Int8) {
self.value = value
}
/// \brief Allow use in a Boolean context.
func getLogicValue() -> Bool {
return value != 0

View File

@@ -1,4 +1,16 @@
import swift
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
@exported
import ObjectiveC
//===----------------------------------------------------------------------===//
@@ -7,43 +19,6 @@ import ObjectiveC
// FIXME: Objective-C types belong in a layer below the Objective-C support
// libraries, not here.
/// \brief The Objective-C BOOL type.
///
/// The Objective-C BOOL type is typically a typedef of "signed char". Clang
/// importer imports it as ObjCBool.
///
/// Note: When BOOL is a typedef of C's _Bool/C++'s bool, this struct goes away
/// and simply becomes a typealias for CBool.
///
/// The compiler has special knowledge of this type.
struct ObjCBool {
var value : UInt8
/// \brief Allow use in a Boolean context.
func getLogicValue() -> Bool {
return value != 0
}
/// \brief Implicit conversion from C Boolean type to Swift Boolean
/// type.
func [conversion] __conversion() -> Bool {
return this.getLogicValue()
}
func replPrint() {
// Dispatch to Bool.
this.getLogicValue().replPrint()
}
}
extension Bool {
/// \brief Implicit conversion from Swift Boolean type to
/// Objective-C Boolean type.
func [conversion] __conversion() -> ObjCBool {
return ObjCBool(this ? 1 : 0)
}
}
/// \brief The Objective-C SEL type.
///
/// The Objective-C SEL type is typically an opaque pointer. Swift
@@ -51,53 +26,91 @@ extension Bool {
/// convert between C strings and selectors.
///
/// The compiler has special knowledge of this type.
struct ObjCSel : StringLiteralConvertible {
struct Selector : StringLiteralConvertible, ReplPrintable {
var ptr : COpaquePointer
/// \brief Create a selector from a string.
constructor(str : String) {
var LM = LifetimeManager()
ptr = sel_registerName(LM.getCString(str)).ptr
LM.release()
init(_ str : String) {
ptr = str.withCString { sel_registerName($0).ptr }
}
typealias StringLiteralType = CString
/// \brief Construct a selector from a string literal.
static func convertFromExtendedGraphemeClusterLiteral(
value: CString) -> Selector {
return convertFromStringLiteral(value)
}
/// \brief Construct a selector from a string literal.
///
/// FIXME: Fast-path this in the compiler, so we don't end up with
/// the sel_registerName call at compile time.
static func convertFromStringLiteral(str : CString) -> ObjCSel {
return sel_registerName(str)
static func convertFromStringLiteral(value: CString) -> Selector {
return sel_registerName(value)
}
init(_: _Nil) {
ptr = nil
}
func replPrint() {
print(String(this))
print(String(self))
}
}
extension ObjCSel : Equatable, Hashable {
func __equal__ (rhs : ObjCSel) -> Bool {
return sel_isEqual(this, rhs)
}
func hashValue() -> Int {
return ptr.hashValue()
func ==(lhs: Selector, rhs: Selector) -> Bool {
return sel_isEqual(lhs, rhs)
}
extension Selector : Equatable, Hashable {
var hashValue: Int {
return ptr.hashValue
}
}
extension String {
/// \brief Construct the C string representation of an Objective-C selector.
constructor(sel : ObjCSel) {
init(_ sel: Selector) {
// FIXME: This misses the ASCII optimization.
this = String.fromCString(sel_getName(sel))
self = String.fromCString(sel_getName(sel))
}
}
// Functions used to implicitly bridge ObjCBool types to Swift's Bool type.
func convertBoolToObjCBool(x:Bool) -> ObjCBool {
func _convertBoolToObjCBool(x: Bool) -> ObjCBool {
return x
}
func convertObjCBoolToBool(x:ObjCBool) -> Bool {
func _convertObjCBoolToBool(x: ObjCBool) -> Bool {
return x
}
extension _Nil {
@conversion func __conversion() -> Selector {
return Selector(nil)
}
}
func ~=(x: NSObject, y: NSObject) -> Bool {
return x.isEqual(y)
}
//===----------------------------------------------------------------------===//
// FIXME: @autoreleasepool substitute
//===----------------------------------------------------------------------===//
@asmname("objc_autoreleasePoolPush") func __pushAutoreleasePool() -> COpaquePointer
@asmname("objc_autoreleasePoolPop") func __popAutoreleasePool(pool: COpaquePointer)
func autoreleasepool(code: () -> ()) {
var pool = __pushAutoreleasePool()
code()
__popAutoreleasePool(pool)
}
//===----------------------------------------------------------------------===//
// Mark YES and NO unavailable.
//===----------------------------------------------------------------------===//
@availability(*, unavailable, message="Use 'Bool' value 'true' instead") var YES : ObjCBool = Bool.true
@availability(*, unavailable, message="Use 'Bool' value 'false' instead") var NO : ObjCBool = Bool.false

View File

@@ -4,9 +4,194 @@
#if os(OSX)
typealias SKColor = NSColor
#else
#if os(iOS)
#elseif os(iOS)
typealias SKColor = UIColor
#endif
#if os(OSX)
// this class only exists to allow AnyObject lookup of _copyImageData
// since that method only exists in a private header in SpriteKit, the lookup
// mechanism by default fails to accept it as a valid AnyObject call
@objc class _SpriteKitMethodProvider : NSObject {
init() { fatal("don't touch me") }
@objc func _copyImageData() -> NSData! { return nil }
}
// HACK - these four mirrors do the exact same thing, they should be one and the same
// and use an AnyObject, or some T : NSObject as their ivar type, but that causes
// the compiler to crash - as a result, four mirrors it is
struct _SKShapeNodeMirror : Mirror {
var _value : SKShapeNode
init(_ _v : SKShapeNode) {
_value = _v
}
var value : Any { return (_value as Any)}
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 0 }
subscript(_: Int) -> (String,Mirror) { fatal("don't ask") }
var summary: String { return _value.description }
var quickLookObject: QuickLookObject? {
// this code comes straight from the quicklooks
if let data = (_value as AnyObject)._copyImageData?() {
// we could send a Raw, but I don't want to make a copy of the bytes for no good reason
// make an NSImage out of them and send that
let img = NSImage(data: data)
return .Some(.Sprite(img))
}
return nil
}
var disposition : MirrorDisposition { get { return .Aggregate } }
}
struct _SKSpriteNodeMirror : Mirror {
var _value : SKSpriteNode
init(_ _v : SKSpriteNode) {
_value = _v
}
var value : Any { return (_value as Any)}
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 0 }
subscript(_: Int) -> (String,Mirror) { fatal("don't ask") }
var summary: String { return _value.description }
var quickLookObject: QuickLookObject? {
// this code comes straight from the quicklooks
if let data = (_value as AnyObject)._copyImageData?() {
// we could send a Raw, but I don't want to make a copy of the bytes for no good reason
// make an NSImage out of them and send that
let img = NSImage(data: data)
return .Some(.Sprite(img))
}
return nil
}
var disposition : MirrorDisposition { get { return .Aggregate } }
}
struct _SKTextureAtlasMirror : Mirror {
var _value : SKTextureAtlas
init(_ _v : SKTextureAtlas) {
_value = _v
}
var value : Any { return (_value as Any)}
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 0 }
subscript(_: Int) -> (String,Mirror) { fatal("don't ask") }
var summary: String { return _value.description }
var quickLookObject: QuickLookObject? {
// this code comes straight from the quicklooks
if let data = (_value as AnyObject)._copyImageData?() {
// we could send a Raw, but I don't want to make a copy of the bytes for no good reason
// make an NSImage out of them and send that
let img = NSImage(data: data)
return .Some(.Sprite(img))
}
return nil
}
var disposition : MirrorDisposition { get { return .Aggregate } }
}
struct _SKTextureMirror : Mirror {
var _value : SKTexture
init(_ _v : SKTexture) {
_value = _v
}
var value : Any { return (_value as Any)}
var valueType: Any.Type { return (_value as Any).dynamicType }
var objectIdentifier: ObjectIdentifier? { return .None }
var count: Int { return 0 }
subscript(_: Int) -> (String,Mirror) { fatal("don't ask") }
var summary: String { return _value.description }
var quickLookObject: QuickLookObject? {
// this code comes straight from the quicklooks
if let data = (_value as AnyObject)._copyImageData?() {
// we could send a Raw, but I don't want to make a copy of the bytes for no good reason
// make an NSImage out of them and send that
let img = NSImage(data: data)
return .Some(.Sprite(img))
}
return nil
}
var disposition : MirrorDisposition { get { return .Aggregate } }
}
extension SKShapeNode : Reflectable {
func getMirror() -> Mirror {
return _SKShapeNodeMirror(self)
}
}
extension SKSpriteNode : Reflectable {
func getMirror() -> Mirror {
return _SKSpriteNodeMirror(self)
}
}
extension SKTextureAtlas : Reflectable {
func getMirror() -> Mirror {
return _SKTextureAtlasMirror(self)
}
}
extension SKTexture : Reflectable {
func getMirror() -> Mirror {
return _SKTextureMirror(self)
}
}
#elseif os(iOS)
// FIXME: we want to interop nicely with SpriteKit on iOS as well
#endif
extension SKNode {
subscript (name: String) -> SKNode[] {
var nodes = SKNode[]()
enumerateChildNodesWithName(name) { node, stop in
if let n = node { nodes.append(n) }
}
return nodes
}
}

View File

@@ -1,2 +1,130 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import Foundation
import [exported] UIKit
@exported import UIKit
// Overlay UIApplicationMain, which is declared with a non-const char *argv[]
// argument that gets mapped to UnsafePointer<UnsafePointer<CChar>> by the
// importer, with one that takes UnsafePointer<CString> instead, matching the
// type of C_ARGV.
@asmname("UIApplicationMain")
func UIApplicationMain(argc: CInt,
argv: UnsafePointer<CString>,
principalClassName: NSString?,
delegateClassName: NSString?) -> CInt
// These are un-imported macros in UIKit.
extension UIDeviceOrientation {
var isLandscape: Bool {
get { return self == .LandscapeLeft || self == .LandscapeRight }
}
var isPortrait: Bool {
get { return self == .Portrait || self == .PortraitUpsideDown }
}
var isFlat: Bool {
get { return self == .FaceUp || self == .FaceDown }
}
var isValidInterfaceOrientation: Bool {
get {
switch (self) {
case .Portrait, .PortraitUpsideDown, .LandscapeLeft, .LandscapeRight:
return true
default:
return false
}
}
}
}
func UIDeviceOrientationIsLandscape(orientation: UIDeviceOrientation) -> Bool {
return orientation.isLandscape
}
func UIDeviceOrientationIsPortrait(orientation: UIDeviceOrientation) -> Bool {
return orientation.isPortrait
}
func UIDeviceOrientationIsValidInterfaceOrientation(
orientation: UIDeviceOrientation) -> Bool
{
return orientation.isValidInterfaceOrientation
}
extension UIInterfaceOrientation {
var isLandscape: Bool {
get { return self == .LandscapeLeft || self == .LandscapeRight }
}
var isPortrait: Bool {
get { return self == .Portrait || self == .PortraitUpsideDown }
}
}
func UIInterfaceOrientationIsPortrait(orientation: UIInterfaceOrientation)
-> Bool
{
return orientation.isPortrait
}
func UIInterfaceOrientationIsLandscape(orientation: UIInterfaceOrientation)
-> Bool
{
return orientation.isLandscape
}
// Overlays for variadic initializers.
extension UIActionSheet {
convenience init(title: String?,
delegate: UIActionSheetDelegate?,
cancelButtonTitle: String?,
destructiveButtonTitle: String?,
// Hack around overload ambiguity with non-variadic constructor.
// <rdar://problem/16704770>
otherButtonTitles firstButtonTitle: String,
_ moreButtonTitles: String...) {
self.init(title: title,
delegate: delegate,
cancelButtonTitle: cancelButtonTitle,
destructiveButtonTitle: destructiveButtonTitle)
self.addButtonWithTitle(firstButtonTitle)
for buttonTitle in moreButtonTitles {
self.addButtonWithTitle(buttonTitle)
}
}
}
extension UIAlertView {
convenience init(title: String,
message: String,
delegate: UIAlertViewDelegate?,
cancelButtonTitle: String?,
// Hack around overload ambiguity with non-variadic constructor.
// <rdar://problem/16704770>
otherButtonTitles firstButtonTitle: String,
_ moreButtonTitles: String...) {
self.init(title: title,
message: message,
delegate: delegate,
cancelButtonTitle: cancelButtonTitle)
self.addButtonWithTitle(firstButtonTitle)
for buttonTitle in moreButtonTitles {
self.addButtonWithTitle(buttonTitle)
}
}
}

View File

@@ -10,30 +10,32 @@
//
//===----------------------------------------------------------------------===//
import XCTest
@exported import XCTest // Clang module
/// Returns the current test case, so we can use free functions instead of methods for the overlay.
@asmname("_XCTCurrentTestCase") func _XCTCurrentTestCase() -> XCTestCase
/// Register the failure, expected or unexpected, of the given test.
func _XCTRegisterFailure(test: XCTestCase, expected: Bool, condition: String, message: String, file: String, line: Int) -> Void {
/// Register the failure, expected or unexpected, of the current test case.
func _XCTRegisterFailure(expected: Bool, condition: String, message: String, file: String, line: Int) -> Void {
// Call the real _XCTFailureHandler.
let test = _XCTCurrentTestCase()
_XCTPreformattedFailureHandler(test, expected, file, line, condition, message)
}
/// Produce a failure description for the given assertion type.
func _XCTFailureDescription(assertionType: _XCTAssertionType, formatIndex: Int, expressionStrings: CVarArg...) -> String {
return String(withFormat: _XCTFailureFormat(assertionType, formatIndex), arguments: expressionStrings)
return String(format: _XCTFailureFormat(assertionType, formatIndex), arguments: expressionStrings)
}
extension XCTestCase {
// --- Supported Assertions ---
// --- Supported Assertions ---
func XCTFail(message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTFail(_ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_Fail
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, ""), message, file, line)
}
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, ""), message, file, line)
}
func XCTAssertNil(expression: @auto_closure () -> AnyObject?, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertNil(expression: @auto_closure () -> AnyObject?, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_Nil
// evaluate the expression exactly once
@@ -41,12 +43,14 @@ extension XCTestCase {
// test both Optional and value to treat .None and nil as synonymous
var passed: Bool
var expressionValueStr: String = "nil"
if let expressionValueUnwrapped: AnyObject = expressionValueOptional {
// TODO: passed = (expressionValueUnwrapped === nil)
if expressionValueUnwrapped === nil {
passed = true
} else {
passed = false
expressionValueStr = reflect(expressionValueUnwrapped).summary
}
} else {
passed = true
@@ -56,17 +60,14 @@ extension XCTestCase {
// TODO: @auto_string expression
let expressionStr = "expressionStr"
// TODO: stringify expressionValue
let expressionValueStr = "expressionValueStr"
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr, expressionValueStr), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr, expressionValueStr), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssertNotNil(expression: @auto_closure () -> AnyObject?, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertNotNil(expression: @auto_closure () -> AnyObject?, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_NotNil
// evaluate the expression exactly once
@@ -74,12 +75,14 @@ extension XCTestCase {
// test both Optional and value to treat .None and nil as synonymous
var passed: Bool
var expressionValueStr: String = "nil"
if let expressionValueUnwrapped: AnyObject = expressionValueOptional {
// TODO: passed = !(expressionValueUnwrapped === nil)
if expressionValueUnwrapped === nil {
passed = false
} else {
passed = true
expressionValueStr = reflect(expressionValueUnwrapped).summary
}
} else {
passed = false
@@ -89,19 +92,19 @@ extension XCTestCase {
// TODO: @auto_string expression
let expressionStr = "expressionStr"
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr, expressionValueStr), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssert(expression: @auto_closure () -> LogicValue, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssert(expression: @auto_closure () -> LogicValue, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
// XCTAssert is just a cover for XCTAssertTrue.
XCTAssertTrue(expression, message, file, line);
}
XCTAssertTrue(expression, message, file: file, line: line);
}
func XCTAssertTrue(expression: @auto_closure () -> LogicValue, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertTrue(expression: @auto_closure () -> LogicValue, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_True
// evaluate the expression exactly once
@@ -109,16 +112,16 @@ extension XCTestCase {
if !expressionValue {
// TODO: @auto_string expression
let expressionStr = "expressionStr"
let expressionStr = expressionValue ? "true" : "false"
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssertFalse(expression: @auto_closure () -> LogicValue, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertFalse(expression: @auto_closure () -> LogicValue, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_False
// evaluate the expression exactly once
@@ -128,64 +131,105 @@ extension XCTestCase {
// TODO: @auto_string expression
let expressionStr = expressionValue ? "true" : "false"
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssertEqualObjects(expression1: @auto_closure () -> NSObject, expression2: @auto_closure () -> NSObject, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertEqualObjects(expression1: @auto_closure () -> NSObject?, expression2: @auto_closure () -> NSObject?, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_EqualObjects
// evaluate each expression exactly once
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if (expressionValue1 == nil && expressionValue2 == nil) || !(expressionValue1.isEqual(expressionValue2)) {
var isEqualOrBothNil: Bool = false
var expressionValueStr1: String
var expressionValueStr2: String
if let expressionValue1NonOptional: NSObject = expressionValue1 {
expressionValueStr1 = "\(expressionValue1NonOptional.description)"
if let expressionValue2NonOptional: NSObject = expressionValue2 {
expressionValueStr2 = "\(expressionValue2NonOptional.description)"
isEqualOrBothNil = expressionValue1NonOptional.isEqual(expressionValue2NonOptional)
} else {
expressionValueStr2 = "nil"
}
} else {
expressionValueStr1 = "nil"
if let expressionValue2NonOptional: NSObject = expressionValue2 {
expressionValueStr2 = "\(expressionValue2NonOptional.description)"
} else {
expressionValueStr2 = "nil"
// If both are nil, also consider XCTAssertEqualObjects to pass.
isEqualOrBothNil = true
}
}
if !isEqualOrBothNil {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
// TODO: stringify expressionValue1
// TODO: stringify expressionValue2
let expressionValueStr1 = "expressionValueStr1"
let expressionValueStr2 = "expressionValueStr2"
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssertNotEqualObjects(expression1: @auto_closure () -> NSObject, expression2: @auto_closure () -> NSObject, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertNotEqualObjects(expression1: @auto_closure () -> NSObject?, expression2: @auto_closure () -> NSObject?, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_NotEqualObjects
// evaluate each expression exactly once
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if (expressionValue1 == expressionValue2) || expressionValue1.isEqual(expressionValue2) {
var isEqualAndBothNonNil: Bool = false
var expressionValueStr1: String
var expressionValueStr2: String
if let expressionValue1NonOptional = expressionValue1 {
expressionValueStr1 = "\(expressionValue1NonOptional.description)"
if let expressionValue2NonOptional = expressionValue2 {
expressionValueStr2 = "\(expressionValue2NonOptional.description)"
isEqualAndBothNonNil = expressionValue1NonOptional.isEqual(expressionValue2NonOptional)
} else {
expressionValueStr2 = "nil"
}
} else {
expressionValueStr1 = "nil"
if let expressionValue2NonOptional: NSObject = expressionValue2 {
expressionValueStr2 = "\(expressionValue2NonOptional.description)"
} else {
expressionValueStr2 = "nil"
}
}
if isEqualAndBothNonNil || (expressionValue1 == nil && expressionValue2 == nil) {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
// TODO: stringify expressionValue1
// TODO: stringify expressionValue2
let expressionValueStr1 = "expressionValueStr1"
let expressionValueStr2 = "expressionValueStr2"
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssertEqual<T: Equatable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertEqual<T: Equatable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_Equal
// evaluate each expression exactly once
@@ -198,19 +242,17 @@ extension XCTestCase {
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
// TODO: stringify expressionValue1
// TODO: stringify expressionValue2
let expressionValueStr1 = "expressionValueStr1"
let expressionValueStr2 = "expressionValueStr2"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssertNotEqual<T: Equatable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertNotEqual<T: Equatable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_NotEqual
// evaluate each expression exactly once
@@ -223,116 +265,242 @@ extension XCTestCase {
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
// TODO: stringify expressionValue1
// TODO: stringify expressionValue2
let expressionValueStr1 = "expressionValueStr1"
let expressionValueStr2 = "expressionValueStr2"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
#if XCTEST_ENABLE_EQUAL_WITH_ACCURACY_ASSERTIONS
func XCTAssertEqualWithAccuracy<T: FloatingPointNumber>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, accuracy: T, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func _XCTCheckEqualWithAccuracy_Double(value1: Double, value2: Double, accuracy: Double) -> Bool {
return (!value1.isNaN() && !value2.isNaN())
&& (abs(value1 - value2) <= accuracy)
}
func _XCTCheckEqualWithAccuracy_Float(value1: Float, value2: Float, accuracy: Float) -> Bool {
return (!value1.isNaN() && !value2.isNaN())
&& (abs(value1 - value2) <= accuracy)
}
func XCTAssertEqualWithAccuracy<T: FloatingPointNumber>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, accuracy: T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_EqualWithAccuracy
// evaluate each expression exactly once
let expressionValue1: FloatingPointNumber = expression1()
let expressionValue2: FloatingPointNumber = expression2()
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if expressionValue1.isNaN() || expressionValue2.isNaN()
|| ((max(expressionValue1, expressionValue2)
- min(expressionValue1, expressionValue2)) > accuracy) {
var equalWithAccuracy: Bool = false
switch (expressionValue1, expressionValue2, accuracy) {
case let (expressionValue1Double as Double, expressionValue2Double as Double, accuracyDouble as Double):
equalWithAccuracy = _XCTCheckEqualWithAccuracy_Double(expressionValue1Double, expressionValue2Double, accuracyDouble)
case let (expressionValue1Float as Float, expressionValue2Float as Float, accuracyFloat as Float):
equalWithAccuracy = _XCTCheckEqualWithAccuracy_Float(expressionValue1Float, expressionValue2Float, accuracyFloat)
default:
// unknown type, fail with prejudice
fatal("unsupported floating-point type passed to XCTAssertEqualWithAccuracy")
}
if !equalWithAccuracy {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
// TODO: stringify expressionValue1
// TODO: stringify expressionValue2
// TODO: stringify accuracy
let expressionValueStr1 = "expressionValueStr1"
let expressionValueStr2 = "expressionValueStr2"
let accuracyStr = "accuracyStr"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
var accuracyStr = reflect(accuracy).summary
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, accuracyStr, expressionValueStr1, expressionValueStr2, accuracyStr), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, accuracyStr, expressionValueStr1, expressionValueStr2, accuracyStr), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
}
func XCTAssertNotEqualWithAccuracy<T: FloatingPointNumber>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, accuracy: T, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func _XCTCheckNotEqualWithAccuracy_Double(value1: Double, value2: Double, accuracy: Double) -> Bool {
return (value1.isNaN() || value2.isNaN())
|| (abs(value1 - value2) > accuracy)
}
func _XCTCheckNotEqualWithAccuracy_Float(value1: Float, value2: Float, accuracy: Float) -> Bool {
return (value1.isNaN() || value2.isNaN())
|| (abs(value1 - value2) > accuracy)
}
func XCTAssertNotEqualWithAccuracy<T: FloatingPointNumber>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, accuracy: T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_NotEqualWithAccuracy
// evaluate each expression exactly once
let expressionValue1: FloatingPointNumber = expression1()
let expressionValue2: FloatingPointNumber = expression2()
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if !expressionValue1.isNaN() && !expressionValue2.isNaN()
&& ((max(expressionValue1, expressionValue2)
- min(expressionValue1, expressionValue2)) <= accuracy) {
var notEqualWithAccuracy: Bool = false
switch (expressionValue1, expressionValue2, accuracy) {
case let (expressionValue1Double as Double, expressionValue2Double as Double, accuracyDouble as Double):
notEqualWithAccuracy = _XCTCheckNotEqualWithAccuracy_Double(expressionValue1Double, expressionValue2Double, accuracyDouble)
case let (expressionValue1Float as Float, expressionValue2Float as Float, accuracyFloat as Float):
notEqualWithAccuracy = _XCTCheckNotEqualWithAccuracy_Float(expressionValue1Float, expressionValue2Float, accuracyFloat)
default:
// unknown type, fail with prejudice
fatal("unsupported floating-point type passed to XCTAssertNotEqualWithAccuracy")
}
if !notEqualWithAccuracy {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
// TODO: @auto_string accuracy
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
// TODO: stringify expressionValue1
// TODO: stringify expressionValue2
// TODO: stringify accuracy
let expressionValueStr1 = "expressionValueStr1"
let expressionValueStr2 = "expressionValueStr2"
let accuracyStr = "accuracyStr"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
var accuracyStr = reflect(accuracy).summary
_XCTRegisterFailure(self, true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, accuracyStr, expressionValueStr1, expressionValueStr2, accuracyStr), message, file, line)
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, accuracyStr, expressionValueStr1, expressionValueStr2, accuracyStr), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
func XCTAssertGreaterThan<T: Comparable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_GreaterThan
// evaluate each expression exactly once
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if !(expressionValue1 > expressionValue2) {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
#endif
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
func XCTAssertGreaterThanOrEqual<T: Comparable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__)
{
let assertionType = _XCTAssertionType.Assertion_GreaterThanOrEqual
// evaluate each expression exactly once
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if !(expressionValue1 >= expressionValue2) {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
func XCTAssertLessThan<T: Comparable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_LessThan
// evaluate each expression exactly once
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if !(expressionValue1 < expressionValue2) {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
func XCTAssertLessThanOrEqual<T: Comparable>(expression1: @auto_closure () -> T, expression2: @auto_closure () -> T, _ message: String = "", file: String = __FILE__, line: Int = __LINE__)
{
let assertionType = _XCTAssertionType.Assertion_LessThanOrEqual
// evaluate each expression exactly once
let expressionValue1 = expression1()
let expressionValue2 = expression2()
if !(expressionValue1 <= expressionValue2) {
// TODO: @auto_string expression1
// TODO: @auto_string expression2
let expressionStr1 = "expressionStr1"
let expressionStr2 = "expressionStr2"
var expressionValueStr1 = reflect(expressionValue1).summary
let expressionValueStr2 = reflect(expressionValue2).summary
_XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionStr1, expressionStr2, expressionValueStr1, expressionValueStr2), message, file, line)
}
// TODO: handle an exception for which we can get a description
// TODO: handle an exception for which we can't get a description
}
#if XCTEST_ENABLE_EXCEPTION_ASSERTIONS
// --- Currently-Unsupported Assertions ---
// --- Currently-Unsupported Assertions ---
func XCTAssertThrows(expression: @auto_closure () -> Any?, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertThrows(expression: @auto_closure () -> Any?, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_Throws
// FIXME: Unsupported
}
}
func XCTAssertThrowsSpecific(expression: @auto_closure () -> Any?, exception: Any, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertThrowsSpecific(expression: @auto_closure () -> Any?, exception: Any, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_ThrowsSpecific
// FIXME: Unsupported
}
}
func XCTAssertThrowsSpecificNamed(expression: @auto_closure () -> Any?, exception: Any, name: String, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertThrowsSpecificNamed(expression: @auto_closure () -> Any?, exception: Any, name: String, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_ThrowsSpecificNamed
// FIXME: Unsupported
}
}
func XCTAssertNoThrow(expression: @auto_closure () -> Any?, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertNoThrow(expression: @auto_closure () -> Any?, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_NoThrow
// FIXME: Unsupported
}
}
func XCTAssertNoThrowSpecific(expression: @auto_closure () -> Any?, exception: Any, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertNoThrowSpecific(expression: @auto_closure () -> Any?, exception: Any, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_NoThrowSpecific
// FIXME: Unsupported
}
}
func XCTAssertNoThrowSpecificNamed(expression: @auto_closure () -> Any?, exception: Any, name: String, message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
func XCTAssertNoThrowSpecificNamed(expression: @auto_closure () -> Any?, exception: Any, name: String, _ message: String = "", file: String = __FILE__, line: Int = __LINE__) -> Void {
let assertionType = _XCTAssertionType.Assertion_NoThrowSpecificNamed
// FIXME: Unsupported
}
#endif
}
#endif

View File

@@ -1,3 +1,4 @@
%# -*- mode: swift -*-
//===--- NSSwiftXXXBase.mm.gyb - Cocoa bases for Swift container buffers --===//
//
// This source file is part of the Swift.org open source project
@@ -43,7 +44,7 @@ extern "C" id _objc_rootAutorelease(id);
using namespace swift;
% for Class in ('Array','Dictionary'):
% for Class in ('Array','Dictionary','Enumerator'):
@interface NSSwift${Class}Base : NS${Class}
{
SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
@@ -54,9 +55,10 @@ using namespace swift;
+ (void)load {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
class_setSuperclass(
objc_getClass("NSSwift${Class}"),
[NSSwift${Class}Base class]);
char buffer[64];
snprintf(buffer, 64, "_TtCSs%d%s", (int)strlen("NSSwift${Class}"),
"NSSwift${Class}");
class_setSuperclass(objc_getClass(buffer), [NSSwift${Class}Base class]);
#pragma clang diagnostic pop
}

View File

@@ -15,17 +15,36 @@
//
//===----------------------------------------------------------------------===//
#include <Block.h>
#include <objc/NSObject.h>
#include <objc/runtime.h>
#include <objc/message.h>
#if __has_include(<objc/objc-internal.h>)
#include <objc/objc-abi.h>
#include <objc/objc-internal.h>
#else
extern "C" id _objc_rootAutorelease(id);
#endif
#include "swift/Runtime/Alloc.h"
#include "swift/Runtime/Heap.h"
#include "swift/Runtime/HeapObject.h"
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/ObjCBridge.h"
#include "llvm/ADT/DenseMap.h"
#include "Private.h"
#include "Debug.h"
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <mutex>
#include "../shims/shims.h"
// Redeclare these just we check them.
extern "C" id objc_retain(id);
extern "C" void objc_release(id);
extern "C" id _objc_rootAutorelease(id);
extern "C" void objc_moveWeak(id*, id*);
extern "C" void objc_copyWeak(id*, id*);
extern "C" id objc_initWeak(id*, id);
extern "C" id objc_storeWeak(id*, id);
extern "C" void objc_destroyWeak(id*);
extern "C" id objc_loadWeakRetained(id*);
using namespace swift;
@@ -37,38 +56,133 @@ struct SwiftObject_s {
#if __has_attribute(objc_root_class)
__attribute__((objc_root_class))
#endif
@interface SwiftObject
{
@interface SwiftObject<NSObject> {
SwiftObject_s magic;
}
- (id)retain;
- (void)release;
- (id)autorelease;
- (void)dealloc;
- (BOOL)isEqual:(id)object;
- (NSUInteger)hash;
- (Class)superclass;
- (Class)class;
- (instancetype)self;
- (struct _NSZone *)zone;
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
- (BOOL)isProxy;
+ (BOOL)isSubclassOfClass:(Class)aClass;
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
- (BOOL)respondsToSelector:(SEL)aSelector;
- (instancetype)retain;
- (oneway void)release;
- (instancetype)autorelease;
- (NSUInteger)retainCount;
- (NSString *)description;
- (NSString *)debugDescription;
@end
void reportUnrecognizedSelector(Class cls, SEL sel) {
printf("class '%s' does not recognize %s selector '%s', aborting\n",
class_getName(cls),
class_isMetaClass(cls) ? "class" : "instance",
sel_getName(sel));
abort();
static SwiftObject *_allocHelper(Class cls) {
// XXX FIXME
// When we have layout information, do precise alignment rounding
// For now, assume someone is using hardware vector types
#if defined(__x86_64__) || defined(__i386__)
const size_t mask = 32 - 1;
#else
const size_t mask = 16 - 1;
#endif
return reinterpret_cast<SwiftObject *>(swift::swift_allocObject(
reinterpret_cast<HeapMetadata const *>(cls),
class_getInstanceSize(cls), mask));
}
// Helper from the standard library for stringizing an arbitrary object.
namespace {
struct String { void *x, *y, *z; };
}
extern "C" void swift_getSummary(String *out, OpaqueValue *value,
const Metadata *T);
static NSString *_getDescription(SwiftObject *obj) {
// Cached lookup of swift_convertStringToNSString, which is in Foundation.
static NSString *(*convertStringToNSString)(void *sx, void *sy, void *sz)
= nullptr;
if (!convertStringToNSString) {
convertStringToNSString = (decltype(convertStringToNSString))(uintptr_t)
dlsym(RTLD_DEFAULT, "swift_convertStringToNSString");
// If Foundation hasn't loaded yet, fall back to returning the static string
// "SwiftObject". The likelihood of someone invoking -description without
// ObjC interop is low.
if (!convertStringToNSString)
return @"SwiftObject";
}
String tmp;
swift_retain((HeapObject*)obj);
swift_getSummary(&tmp, (OpaqueValue*)&obj,
(const Metadata*)object_getClass(obj));
return [convertStringToNSString(tmp.x, tmp.y, tmp.z) autorelease];
}
@implementation SwiftObject
+ (void)load {}
+ (void)initialize {}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
assert(zone == nullptr);
return _allocHelper(self);
}
+ (instancetype)alloc {
// we do not support "placement new" or zones,
// so there is no need to call allocWithZone
return _allocHelper(self);
}
+ (Class)class {
return self;
}
- (id)class {
return object_getClass(self);
}
+ (Class)superclass {
return class_getSuperclass(self);
}
- (Class)superclass {
return class_getSuperclass([self class]);
}
+ (BOOL)isMemberOfClass:(Class)cls {
return object_getClass((id)self) == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
return [self class] == cls;
}
- (instancetype)self {
return self;
}
- (BOOL)isProxy {
return NO;
}
- (struct _NSZone *)zone {
return (struct _NSZone *)&swift::zoneShims;
}
- (void)doesNotRecognizeSelector: (SEL) sel {
reportUnrecognizedSelector(object_getClass(self), sel);
swift::crash("Unrecognized selector");
}
- (id)retain {
@@ -83,6 +197,9 @@ void reportUnrecognizedSelector(Class cls, SEL sel) {
- (id)autorelease {
return _objc_rootAutorelease(self);
}
- (NSUInteger)retainCount {
return swift::swift_retainCount(reinterpret_cast<HeapObject *>(self));
}
- (void)dealloc {
auto SELF = reinterpret_cast<HeapObject *>(self);
@@ -97,8 +214,292 @@ void reportUnrecognizedSelector(Class cls, SEL sel) {
return NO;
}
+ (BOOL)isSubclassOfClass:(Class)someClass {
for (Class isa = self; isa != Nil; isa = class_getSuperclass(isa))
if (isa == someClass)
return YES;
return NO;
}
+ (BOOL)respondsToSelector:(SEL)sel {
if (!sel) return NO;
return class_respondsToSelector(object_getClass((id)self), sel);
}
- (BOOL)respondsToSelector:(SEL)sel {
if (!sel) return NO;
return class_respondsToSelector([self class], sel);
}
- (BOOL)conformsToProtocol:(Protocol*)proto {
if (!proto) return NO;
return class_conformsToProtocol([self class], proto);
}
- (bool) __usesNativeSwiftReferenceCounting {
return true;
}
- (NSUInteger)hash {
return (NSUInteger)self;
}
- (BOOL)isEqual:(id)object {
return self == object;
}
- (id)performSelector:(SEL)aSelector {
return ((id(*)(id, SEL))objc_msgSend)(self, aSelector);
}
- (id)performSelector:(SEL)aSelector withObject:(id)object {
return ((id(*)(id, SEL, id))objc_msgSend)(self, aSelector, object);
}
- (id)performSelector:(SEL)aSelector withObject:(id)object1
withObject:(id)object2 {
return ((id(*)(id, SEL, id, id))objc_msgSend)(self, aSelector, object1,
object2);
}
- (NSString *)description {
return _getDescription(self);
}
- (NSString *)debugDescription {
return _getDescription(self);
}
@end
// FIXME: there can be no exhaustive list of ObjC root classes; this
// really needs to be done by the runtime.
@implementation NSObject (__UsesNativeSwiftReferenceCounting)
- (bool) __usesNativeSwiftReferenceCounting {
return false;
}
@end
// FIXME: NSProxy?
/*****************************************************************************/
/****************************** WEAK REFERENCES ******************************/
/*****************************************************************************/
/// A side-table of shared weak references for use by the unowned entry.
///
/// FIXME: this needs to be integrated with the ObjC runtime so that
/// entries will actually get collected. Also, that would make this just
/// a simple manipulation of the internal structures there.
namespace {
struct UnownedRefEntry {
id Value;
size_t Count;
};
}
static llvm::DenseMap<const void*, UnownedRefEntry> UnownedRefs;
static std::mutex UnownedRefsMutex;
static void objc_rootRetainUnowned(id object) {
std::lock_guard<std::mutex> lock(UnownedRefsMutex);
auto it = UnownedRefs.find((const void*) object);
assert(it != UnownedRefs.end());
assert(it->second.Count > 0);
// Do an unbalanced retain.
id result = objc_loadWeakRetained(&it->second.Value);
// If that yielded null, abort.
if (!result) _swift_abortRetainUnowned((const void*) object);
}
static void objc_rootWeakRetain(id object) {
std::lock_guard<std::mutex> lock(UnownedRefsMutex);
auto ins = UnownedRefs.insert({ (const void*) object, UnownedRefEntry() });
if (ins.second) {
ins.first->second.Count++;
} else {
objc_initWeak(&ins.first->second.Value, object);
ins.first->second.Count = 1;
}
}
static void objc_rootWeakRelease(id object) {
std::lock_guard<std::mutex> lock(UnownedRefsMutex);
auto it = UnownedRefs.find((const void*) object);
assert(it != UnownedRefs.end());
assert(it->second.Count > 0);
if (--it->second.Count == 0) {
objc_destroyWeak(&it->second.Value);
UnownedRefs.erase(it);
}
}
/// Decide dynamically whether the given object uses native Swift
/// reference-counting.
static bool usesNativeSwiftReferenceCounting(void *object) {
// This could be *much* faster if it were integrated into the ObjC runtime.
assert(object);
return [(id) object __usesNativeSwiftReferenceCounting];
}
void *swift::swift_unknownRetain(void *object) {
if (object == nullptr) return nullptr;
if (usesNativeSwiftReferenceCounting(object))
return swift_retain((HeapObject*) object);
return objc_retain((id) object);
}
void swift::swift_unknownRelease(void *object) {
if (object == nullptr) return;
if (usesNativeSwiftReferenceCounting(object))
return swift_release((HeapObject*) object);
return objc_release((id) object);
}
void swift::swift_unknownRetainUnowned(void *object) {
if (object == nullptr) return;
if (usesNativeSwiftReferenceCounting(object))
return swift_retainUnowned((HeapObject*) object);
objc_rootRetainUnowned((id) object);
}
void swift::swift_unknownWeakRetain(void *object) {
if (object == nullptr) return;
if (usesNativeSwiftReferenceCounting(object))
return swift_weakRetain((HeapObject*) object);
objc_rootWeakRetain((id) object);
}
void swift::swift_unknownWeakRelease(void *object) {
if (object == nullptr) return;
if (usesNativeSwiftReferenceCounting(object))
return swift_weakRelease((HeapObject*) object);
objc_rootWeakRelease((id) object);
}
// FIXME: these are not really valid implementations; they assume too
// much about the implementation of ObjC weak references, and the
// loads from ->Value can race with clears by the runtime.
static void doWeakInit(WeakReference *addr, void *value, bool valueIsNative) {
assert(value != nullptr);
if (valueIsNative) {
swift_weakInit(addr, (HeapObject*) value);
} else {
objc_initWeak((id*) &addr->Value, (id) value);
}
}
static void doWeakDestroy(WeakReference *addr, bool valueIsNative) {
if (valueIsNative) {
swift_weakDestroy(addr);
} else {
objc_destroyWeak((id*) &addr->Value);
}
}
void swift::swift_unknownWeakInit(WeakReference *addr, void *value) {
if (value == nullptr) {
addr->Value = nullptr;
return;
}
doWeakInit(addr, value, usesNativeSwiftReferenceCounting(value));
}
void swift::swift_unknownWeakAssign(WeakReference *addr, void *newValue) {
// If the incoming value is null, this is just a destroy and
// re-initialize.
if (newValue == nullptr) {
swift_unknownWeakDestroy(addr);
addr->Value = nullptr;
return;
}
bool newIsNative = usesNativeSwiftReferenceCounting(newValue);
// If the existing value is null, this is just an initialize.
void *oldValue = addr->Value;
if (oldValue == nullptr)
return doWeakInit(addr, newValue, newIsNative);
bool oldIsNative = usesNativeSwiftReferenceCounting(oldValue);
// If they're both native, we can use the native function.
if (oldIsNative && newIsNative)
return swift_weakAssign(addr, (HeapObject*) newValue);
// If neither is native, we can use the ObjC function.
if (!oldIsNative && !newIsNative)
return (void) objc_storeWeak((id*) &addr->Value, (id) newValue);
// Otherwise, destroy according to one set of semantics and
// re-initialize with the other.
doWeakDestroy(addr, oldIsNative);
doWeakInit(addr, newValue, newIsNative);
}
void *swift::swift_unknownWeakLoadStrong(WeakReference *addr) {
void *value = addr->Value;
if (value == nullptr) return nullptr;
if (usesNativeSwiftReferenceCounting(value)) {
return swift_weakLoadStrong(addr);
} else {
return (void*) objc_loadWeakRetained((id*) &addr->Value);
}
}
void *swift::swift_unknownWeakTakeStrong(WeakReference *addr) {
void *value = addr->Value;
if (value == nullptr) return nullptr;
if (usesNativeSwiftReferenceCounting(value)) {
return swift_weakTakeStrong(addr);
} else {
void *result = (void*) objc_loadWeakRetained((id*) &addr->Value);
objc_destroyWeak((id*) &addr->Value);
return result;
}
}
void swift::swift_unknownWeakDestroy(WeakReference *addr) {
id object = (id) addr->Value;
if (object == nullptr) return;
doWeakDestroy(addr, usesNativeSwiftReferenceCounting(object));
}
void swift::swift_unknownWeakCopyInit(WeakReference *dest, WeakReference *src) {
id object = (id) src->Value;
if (object == nullptr) {
dest->Value = nullptr;
return;
}
if (usesNativeSwiftReferenceCounting(object))
return swift_weakCopyInit(dest, src);
objc_copyWeak((id*) &dest->Value, (id*) src);
}
void swift::swift_unknownWeakTakeInit(WeakReference *dest, WeakReference *src) {
id object = (id) src->Value;
if (object == nullptr) {
dest->Value = nullptr;
return;
}
if (usesNativeSwiftReferenceCounting(object))
return swift_weakTakeInit(dest, src);
objc_moveWeak((id*) &dest->Value, (id*) &src->Value);
}
void swift::swift_unknownWeakCopyAssign(WeakReference *dest, WeakReference *src) {
if (dest == src) return;
swift_unknownWeakDestroy(dest);
swift_unknownWeakCopyInit(dest, src);
}
void swift::swift_unknownWeakTakeAssign(WeakReference *dest, WeakReference *src) {
if (dest == src) return;
swift_unknownWeakDestroy(dest);
swift_unknownWeakTakeInit(dest, src);
}
/*****************************************************************************/
/******************************* DYNAMIC CASTS *******************************/
/*****************************************************************************/
const void *
swift::swift_dynamicCastObjCClass(const void *object,
@@ -106,9 +507,11 @@ swift::swift_dynamicCastObjCClass(const void *object,
// FIXME: We need to decide if this is really how we want to treat 'nil'.
if (object == nullptr)
return nullptr;
// FIXME: -isKindOfClass: is not a core part of the Objective-C language.
if ([(id)object isKindOfClass:(Class)targetType])
if ([(id)object isKindOfClass:(Class)targetType]) {
return object;
}
return nullptr;
}
@@ -118,67 +521,200 @@ swift::swift_dynamicCastObjCClassUnconditional(const void *object,
// FIXME: We need to decide if this is really how we want to treat 'nil'.
if (object == nullptr)
return nullptr;
// FIXME: -isKindOfClass: is not a core part of the Objective-C language.
if ([(id)object isKindOfClass:(Class)targetType])
if ([(id)object isKindOfClass:(Class)targetType]) {
return object;
}
swift::crash("Swift dynamic cast failed");
}
/// \brief Fetch the type metadata associated with the formal dynamic
/// type of the given (possibly Objective-C) object. The formal
/// dynamic type ignores dynamic subclasses such as those introduced
/// by KVO.
///
/// The object pointer may be a tagged pointer, but cannot be null.
const Metadata *swift::swift_getObjectType(id object) {
auto theClass = object_getClass(object);
auto classAsMetadata = reinterpret_cast<ClassMetadata*>(theClass);
if (classAsMetadata->isTypeMetadata()) return classAsMetadata;
return swift_getObjCClassMetadata(classAsMetadata);
}
extern "C" bool swift_objcRespondsToSelector(id object, SEL selector) {
return [object respondsToSelector:selector];
}
extern "C" id swift_dynamicCastObjCProtocolUnconditional(id object,
size_t numProtocols,
Protocol * const *protocols) {
for (size_t i = 0; i < numProtocols; ++i) {
// FIXME: More informative failure message
if (![object conformsToProtocol:protocols[i]]) {
abort();
}
}
return object;
}
extern "C"
const char *swift_getClassName(HeapMetadata *s) {
// FIXME: The class name should be available in a more Swiftish way.
// FIXME: Generic parameters of generic class instances.
return class_getName(reinterpret_cast<Class>(s));
extern "C" id swift_dynamicCastObjCProtocolConditional(id object,
size_t numProtocols,
Protocol * const *protocols) {
for (size_t i = 0; i < numProtocols; ++i) {
if (![object conformsToProtocol:protocols[i]]) {
return nil;
}
}
return object;
}
//
// Temporary block conversion shims
//
extern "C" void swift_instantiateObjCClass(Class c) {
static const objc_image_info ImageInfo = {0, 0};
// Register the class.
Class registered = objc_readClassPair(c, &ImageInfo);
assert(registered == c
&& "objc_readClassPair failed to instantiate the class in-place");
(void)registered;
// objc_readClassPair does not preserve the "is Swift" bit in the rodata, so
// set it back.
((ClassMetadata*)c)->Data |= 1;
}
namespace {
template<typename T> struct block_shim;
template<typename R, typename...A>
struct block_shim<R(A...)> {
using block_type = R (^)(A...);
using code_type = R (*)(A..., HeapObject *);
// protocol _BridgedToObjectiveC {
struct _BridgedToObjectiveCWitnessTable {
// typealias ObjectiveCType: class
const Metadata *ObjectiveCType;
// func bridgeToObjectiveC() -> ObjectiveCType
HeapObject *(*bridgeToObjectiveC)(OpaqueValue *self, const Metadata *Self);
};
// }
template<typename...U>
static void pass(U &&...) {}
// protocol _ConditionallyBridgedToObjectiveC {
struct _ConditionallyBridgedToObjectiveCWitnessTable {
// My untrained eye can't find this offset in the generated LLVM IR,
// but I do see it being applied in x86 assembly. It disappears
// when inheritance from _BridgedToObjectiveC is removed. If it
// presents any portability problems we can drop that inheritance
// relationship.
const void* const probablyPointsAtBridgedToObjectiveCWitnessTable;
template<typename U>
static void retain_if_id(U const &x) {}
static void retain_if_id(id x) { [x retain]; }
// class func isBridgedToObjectiveC() -> bool
bool (*isBridgedToObjectiveC)(const Metadata* value, const Metadata *T);
};
// }
extern "C" const ProtocolDescriptor _TMpSs20_BridgedToObjectiveC;
extern "C" const ProtocolDescriptor _TMpSs33_ConditionallyBridgedToObjectiveC;
static block_type shim(code_type code, HeapObject *context) {
// Manage non-class Swift memory in a way that blocks can understand.
SwiftRAII contextRAII{context, /*AlreadyRetained=*/true};
return Block_copy(^R (A...args) {
// Adjust the context and any id arguments to +1 retain count.
pass((retain_if_id(args), 0)...);
return code(args..., swift_retain(*contextRAII));
});
}
};
}
/// MAKE_BLOCK_SHIM(_Tmangled_name, return_type(arg_types...));
#define MAKE_BLOCK_SHIM(MANGLED_NAME, ...) \
extern "C" block_shim<__VA_ARGS__>::block_type \
MANGLED_NAME(block_shim<__VA_ARGS__>::code_type code, HeapObject *context) { \
return block_shim<__VA_ARGS__>::shim(code, context); \
static const _BridgedToObjectiveCWitnessTable*
findBridgeWitness(const Metadata *T) {
auto w = swift_conformsToProtocol(T, &_TMpSs20_BridgedToObjectiveC, nullptr);
return reinterpret_cast<const _BridgedToObjectiveCWitnessTable*>(w);
}
static const _ConditionallyBridgedToObjectiveCWitnessTable*
findConditionalBridgeWitness(const Metadata *T) {
auto w = swift_conformsToProtocol(
T, &_TMpSs33_ConditionallyBridgedToObjectiveC, nullptr);
return reinterpret_cast<
const _ConditionallyBridgedToObjectiveCWitnessTable*
>(w);
}
static inline bool swift_isClassOrObjCExistentialImpl(const Metadata *T) {
auto kind = T->getKind();
return kind == MetadataKind::Class ||
kind == MetadataKind::ObjCClassWrapper ||
(kind == MetadataKind::Existential &&
static_cast<const ExistentialTypeMetadata *>(T)->isObjC());
}
// func bridgeToObjectiveC<T>(x: T) -> AnyObject?
extern "C" HeapObject *
swift_bridgeToObjectiveC(OpaqueValue *value, const Metadata *T) {
auto const bridgeWitness = findBridgeWitness(T);
if (bridgeWitness) {
if (auto conditionalWitness = findConditionalBridgeWitness(T)) {
if (!conditionalWitness->isBridgedToObjectiveC(T, T))
return nullptr;
}
auto result = bridgeWitness->bridgeToObjectiveC(value, T);
// Witnesses take 'self' at +0, so we still need to consume the +1 argument.
T->vw_destroy(value);
return result;
}
@class NSString;
if (swift_isClassOrObjCExistentialImpl(T))
return *reinterpret_cast<HeapObject**>(value);
return nullptr;
}
/// () -> ()
MAKE_BLOCK_SHIM(_TTbbT_T_, void(void));
/// (NSString, UnsafePointer<BOOL>) -> ()
MAKE_BLOCK_SHIM(_TTbbTCSo8NSStringGVSs13UnsafePointerV10ObjectiveC8ObjCBool__T_,
void(id, BOOL *));
/// (int64_t) -> ()
MAKE_BLOCK_SHIM(_TTbbSiT_,
void(int64_t));
// (NSObject, NSObject) -> NSComparisonResult aka NSComparator
MAKE_BLOCK_SHIM(_TTbbTCSo8NSObjectS__V10Foundation18NSComparisonResult,
long(id, id));
// func isBridgedToObjectiveC<T>(x: T.Type) -> Bool
extern "C" bool
swift_isBridgedToObjectiveC(const Metadata *value, const Metadata *T) {
auto bridgeWitness = findBridgeWitness(T);
if (bridgeWitness) {
auto conditionalWitness = findConditionalBridgeWitness(T);
return !conditionalWitness
|| conditionalWitness->isBridgedToObjectiveC(value, T);
}
return swift_isClassOrObjCExistentialImpl(T);
}
// func isBridgedVerbatimToObjectiveC<T>(x: T.Type) -> Bool
extern "C" bool
swift_isBridgedVerbatimToObjectiveC(const Metadata *value, const Metadata *T) {
if (findBridgeWitness(T))
return false;
return swift_isClassOrObjCExistentialImpl(T);
}
// func _swift_isClassOrObjCExistential<T>(x: T.Type) -> Bool
extern "C" bool
swift_isClassOrObjCExistential(const Metadata *value, const Metadata *T) {
return swift_isClassOrObjCExistentialImpl(T);
}
const ClassMetadata *
swift::swift_dynamicCastObjCClassMetatype(const ClassMetadata *source,
const ClassMetadata *dest) {
if ([(Class)source isSubclassOfClass:(Class)dest])
return source;
return nil;
}
const ClassMetadata *
swift::swift_dynamicCastObjCClassMetatypeUnconditional(
const ClassMetadata *source,
const ClassMetadata *dest) {
if ([(Class)source isSubclassOfClass:(Class)dest])
return source;
swift::crash("Swift dynamic cast failed");
}
extern "C" const char *swift_getGenericClassObjCName(const ClassMetadata *clas,
const char *basename) {
// FIXME: We should use a runtime mangler to form the real mangled name of the
// generic instance. Since we don't have a runtime mangler yet, just tack the
// address of the class onto the basename, which is totally lame but at least
// gives a unique name to the ObjC runtime.
size_t baseLen = strlen(basename);
auto fullName = (char*)swift_slowAlloc(baseLen + 17, 0);
snprintf(fullName, baseLen + 17, "%s%016llX", basename,
(unsigned long long)clas);
return fullName;
}

View File

@@ -1,6 +1,6 @@
// RUN: %swift -parse %s -verify -D FOO -D BAR -target arm64-apple-ios7.0 -D FOO
#if arch(ARM64) && os(iOS)
#if arch(arm64) && os(iOS)
class C {}
var x = C()
#endif

View File

@@ -1,6 +1,6 @@
// RUN: %swift -parse %s -verify -D FOO -D BAR -target arm-apple-ios7.0 -D FOO
#if arch(ARM) && os(iOS)
#if arch(arm) && os(iOS)
class C {}
var x = C()
#endif

View File

@@ -1,5 +1,4 @@
// RUN: %swift -parse %s -verify -D FOO -D BAR
// REQUIRES: X86
// RUN: %swift -parse %s -verify -D FOO -D BAR -target x86_64-apple-darwin11.3.0
class A {}
@@ -63,3 +62,21 @@ class P : P1 {
func fFOO() -> Int { return 0; }
func fBAR() -> Int { return 0; }
}
func constants1() -> Int {
#if true
return 1
#else
return "1" // should not result in an error
#endif
}
func constants2() -> Int {
#if false
return "1" // should not result in an error
#elseif ((false || false))
return "1" // should not result in an error
#else
return 1
#endif
}

View File

@@ -1,5 +1,4 @@
// RUN: %swift -parse %s -verify -D FOO -D BAZ
// REQUIRES: X86
// RUN: %swift -parse %s -verify -D FOO -D BAZ -target x86_64-apple-darwin11.3.0
#if FOO
var a = 0
@@ -31,22 +30,22 @@ var k = 0
#endif
var l = k
#if arch(X64)
#if arch(x86_64)
var m = 0
#endif
var n = m
#if FOO && !BAR && BAZ && os(OSX) && arch(X64)
#if FOO && !BAR && BAZ && os(OSX) && arch(x86_64)
var o = 0
#endif
var p = o
#if FOO && (!BAR && BAZ && os(OSX) && arch(X64))
#if FOO && (!BAR && BAZ && os(OSX) && arch(x86_64))
var q = 0
#endif
var r = q
#if FOO && !(!BAZ && BAZ && os(OSX) && arch(X64))
#if FOO && !(!BAZ && BAZ && os(OSX) && arch(x86_64))
var s = 0
#endif
var t = s

View File

@@ -1,15 +1,58 @@
// RUN: %swift -parse %s -verify -D FOO -D BAZ
// REQUIRES: X86
// RUN: %swift -parse %s -verify -D FOO -D BAZ -target x86_64-apple-darwin11.3.0
#if FOO == BAZ // expected-error{{expected '&&' or '||' expression}}
var x = 0
#endif
#if ^FOO // expected-error{{expected unary '!' expression}}
#if ^FOO // expected-error {{expected unary '!' expression}}
var y = 0
#endif
#if swift(FOO) // expected-error{{unexpected target configuration expression (expected 'os' or 'arch')}}
#if swift(FOO) // expected-error {{unexpected target configuration expression (expected 'os' or 'arch')}}
var z = 0
#endif
#if FOO || !FOO
func f() {}
#endif ; f() // expected-error {{extra tokens at the end of the build configuration directive}}
#if FOO || !FOO
func g() {}
#else g() // expected-error {{extra tokens at the end of the build configuration directive}}
#endif
#if FOO || !FOO
func h() {}
#else /* aaa */
#endif /* bbb */
#if foo.bar()
.baz() // expected-error {{unexpected target configuration expression argument type}}
#endif
struct S {
#if FOO
#else
#else // expected-error {{further conditions after #else are unreachable}}
#endif
#if FOO
#elseif BAR
#elseif BAZ
#else
#endif
}
#if FOO
#else
#else // expected-error {{further conditions after #else are unreachable}}
#endif
#if FOO
#elseif BAR
#elseif BAZ
#else
#endif

View File

@@ -8,6 +8,6 @@ class C {
#else
func bar() {}
func baz() {}
} // expected-error{{expected declaration}}
} // expected-error{{expected #else or #endif at end of configuration block}} expected-error {{expected declaration}}
#endif
// expected-error@+1{{expected declaration}}

View File

@@ -1,6 +1,6 @@
// RUN: %swift -parse %s -verify -D FOO -D BAR -target i386-apple-ios7.0 -D FOO
#if arch(I386) && os(iOS)
#if arch(i386) && os(iOS)
class C {}
var x = C()
#endif

View File

@@ -1,7 +1,6 @@
// RUN: %swift -parse %s -verify
// With a space next to the '#if'
#if
class C {} // expected-error{{expected #else or #endif at end of configuration block}}
#endif
#if // expected-error {{expected a build configuration expression to follow the #if clause}}
class C {} //expected-error {{expected #else or #endif at end of configuration block}}
#endif // expected-error {{unexpected configuration block terminator}}

View File

@@ -2,7 +2,7 @@
// No space next to the '#if'
// expected-error@+1{{expected expression, var, or let in 'if' condition}}
#if// expected-error 2{{invalid character in source file}}
class D {}
#if // expected-error {{expected a build configuration expression to follow the #if clause}}
class D {} // expected-error {{expected #else or #endif at end of configuration block}}
#endif
// expected-error @-1{{unexpected configuration block terminator}}

View File

@@ -1,5 +1,5 @@
// RUN: %swift -parse %s -verify -D FOO -D BAZ -target x86_64-apple-darwin11.3.0
#if arch(X64) && os(OSX)
#if arch(x86_64) && os(OSX)
println("Mac") // This should not be parsed as a trailing closure
#endif

View File

@@ -1,6 +1,6 @@
// RUN: %swift -parse %s -verify -D FOO -D BAR -target x86_64-apple-ios7.0 -D FOO
#if arch(X64) && os(iOS)
#if arch(x86_64) && os(iOS)
class C {}
var x = C()
#endif

View File

@@ -1,6 +1,22 @@
// RUN: %target-swift-frontend %s -verify
import Darwin
import ObjectiveC
errno = 0
assert(errno == 0)
fork() // expected-error{{'fork' is unavailable}}
vfork() // expected-error{{'vfork' is unavailable}}
// Test YES and NO.
let x_YES = YES // expected-error {{'YES' is unavailable: Use 'Bool' value 'true' instead}}
let x_NO = NO // expected-error {{'NO' is unavailable: Use 'Bool' value 'false' instead}}
func test_shadow(flag: Bool) -> Bool {
let YES = true
let NO = false
return flag ? YES : NO
}

View File

@@ -1,5 +1,5 @@
@exported import ProtoWithInitializer
class Impl : InitProto {
init withInt(i: CInt) {}
init(int i: CInt) {}
}

View File

@@ -1 +1,34 @@
// empty (for now)
@objc class ForwardClass : NSObject {
}
@objc protocol ForwardProto : NSObjectProtocol {
}
@objc class ForwardProtoAdopter : NSObject, ForwardProto {
}
@objc class PartialBaseClass {
}
@objc class PartialSubClass : NSObject {
}
class ProtoConformer : ForwardClassUser {
func consumeForwardClass(arg: ForwardClass) {}
var forward = ForwardClass()
}
func testProtocolWrapper(conformer: ForwardClassUser) {
conformer.consumeForwardClass(conformer.forward)
}
func testStruct(p: Point) -> Point {
var result = p
result.y += 5
return result
}
class Derived : Base {
override func safeOverride(arg: NSObject) -> ForwardClass {
return ForwardClass()
}
}

View File

@@ -10,3 +10,12 @@ func testReexportedClangModules(foo : FooProto) {
let _: CInt = foo.bar
let _: CInt = ExternIntX.x
}
func testCrossReferences(derived: Derived) {
let obj: Base = derived
let _: NSObject = obj.safeOverride(ForwardClass())
let _: NSObject = obj.safeOverrideProto(ForwardProtoAdopter())
testProtocolWrapper(ProtoConformer())
testStruct(Point(x: 2,y: 3))
}

View File

@@ -7,5 +7,5 @@ import AppKit
let encoding: UInt = NSUTF8StringEncoding
let point: Redeclaration.NSPoint = AppKit.NSPoint(0, 0)
let point: Redeclaration.NSPoint = AppKit.NSPoint(x: 0, y: 0)
Redeclaration.NSStringToNSString(AppKit.NSStringToNSString("abc"))

View File

@@ -1,13 +1,31 @@
// RUN: %swift -sdk=%S/Inputs -I=%S/Inputs/custom-modules %s -emit-llvm -o - | FileCheck %s
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %swift %s -target x86_64-apple-darwin13 -sdk %S/Inputs -I=%S/Inputs/custom-modules -module-cache-path %t/clang-module-cache -emit-ir -o %t/without-adapter.ll
// RUN: FileCheck %s < %t/without-adapter.ll
// RUN: %swift -emit-module %S/Inputs/adapter.swift -sdk %S/Inputs -module-link-name SwiftAdapter -module-name ClangModuleWithAdapter -I=%S/Inputs/custom-modules -o %t
// RUN: %swift %s -target x86_64-apple-darwin13 -sdk %S/Inputs -I=%S/Inputs/custom-modules -I %t -module-cache-path %t/clang-module-cache -emit-ir -o %t/with-adapter.ll
// RUN: FileCheck %s < %t/with-adapter.ll
// RUN: FileCheck --check-prefix=CHECK-WITH-SWIFT %s < %t/with-adapter.ll
import LinkMusket
import LinkFramework
import ClangModuleUser
import IndirectFrameworkImporter
import UsesSubmodule
var _ = LinkFramework.IComeFromLinkFramework
UsesSubmodule.useSomethingFromSubmodule()
// CHECK: !{{[0-9]+}} = metadata !{i32 6, metadata !"Linker Options", metadata ![[LINK_LIST:[0-9]+]]}
// CHECK: ![[LINK_LIST]] = metadata !{
// CHECK-DAG: !{{[0-9]+}} = metadata !{metadata !"-lLock"}
// CHECK-DAG: !{{[0-9]+}} = metadata !{metadata !"-lStock"}
// CHECK-DAG: !{{[0-9]+}} = metadata !{metadata !"-framework", metadata !"Barrel"}
// CHECK-DAG: !{{[0-9]+}} = metadata !{metadata !"-framework", metadata !"LinkFramework"}
// CHECK-DAG: !{{[0-9]+}} = metadata !{metadata !"-lUnderlyingClangLibrary"}
// CHECK-DAG: !{{[0-9]+}} = metadata !{metadata !"-framework", metadata !"Indirect"}
// CHECK-DAG: !{{[0-9]+}} = metadata !{metadata !"-framework", metadata !"HasSubmodule"}
// CHECK-WITH-SWIFT: !{{[0-9]+}} = metadata !{metadata !"-lSwiftAdapter"}

View File

@@ -2,6 +2,7 @@
// RUN: %swift %clang-importer-sdk -parse -verify -module-cache-path %t/clang-module-cache -target x86_64-apple-darwin13 %s
import Foundation
import stdio
// Test if an instance method marked __attribute__((unavailable)) on
// the *class* NSObject can be used.
@@ -9,7 +10,24 @@ func test_unavailable_instance_method(x : NSObject) -> Bool {
return x.allowsWeakReference() // expected-error {{'allowsWeakReference' is unavailable}}
}
func test_unavailable_method_in_protocol(x : NSObjectProtocol) {
x.retain() // expected-error {{'retain' is unavailable}}
}
func test_unavailable_method_in_protocol_use_class_instance(x : NSObject) {
x.retain() // expected-error {{'retain' is unavailable}}
}
func test_unavailable_func(x : NSObject) {
NSDeallocateObject(x) // expected-error {{'NSDeallocateObject' is unavailable}}
}
func test_deprecated_imported_as_unavailable(s:CMutablePointer<CChar>) {
let x = tmpnam(s) // expected-error {{'tmpnam' is unavailable: Due to security concerns inherent in the design of tmpnam(3), it is highly recommended that you use mkstemp(3) instead.}}
}
func test_NSInvocation(x:NSInvocation) {} // expected-error {{'NSInvocation' is unavailable}}
func test_class_avail(x:NSObject) {
x.`class`() // expected-error {{'class' is unavailable: use 'dynamicType' instead}}
NSObject.`class`() // expected-error {{'class' is unavailable: use 'self' instead}}
}

View File

@@ -1,13 +1,18 @@
// RUN: rm -rf %t/clang-module-cache
// RUN: %swift -constraint-checker -parse -verify -module-cache-path=%t/clang-module-cache -sdk=%S/Inputs %s
// RUN: ls -lR %t/clang-module-cache | grep blocks.pcm
// RUN: %swift %clang-importer-sdk -parse -verify -module-cache-path %t/clang-module-cache -target x86_64-apple-darwin13 %s
// RUN: ls -lR %t/clang-module-cache | FileCheck %s
// CHECK: blocks{{.*}}.pcm
import blocks
import Foundation
var someNSString : NSString
func useNSString(s:NSString) {}
func useString(s: String) {}
dispatch_async(dispatch_get_current_queue()) { }
someNSString.enumerateLinesUsingBlock {(s:String?) in }
someNSString.enumerateLinesUsingBlock {s in }
someNSString.enumerateLinesUsingBlock({ useString($0) })
dispatch_async(dispatch_get_current_queue(), /*not a block=*/()) // expected-error{{'()' is not convertible to 'dispatch_block_t'}}
dispatch_async(dispatch_get_current_queue(), func() { })
someNSString.enumerateLinesUsingBlock(func(s:NSString) { })
someNSString.enumerateLinesUsingBlock(func(s) { })
someNSString.enumerateLinesUsingBlock({ useNSString($0) })

View File

@@ -3,15 +3,16 @@
import CoreCooling
func assertUnmanaged<T:AnyObject>(t: Unmanaged<T>) {}
func assertUnmanaged<T: AnyObject>(t: Unmanaged<T>) {}
func assertManaged<T: AnyObject>(t: T) {}
func test0(fridge: CCRefrigeratorRef) {
assertUnmanaged(fridge)
assertManaged(fridge)
}
func test1(power: CCPowerSupplyRef) {
func test1(power: Unmanaged<CCPowerSupplyRef>) {
assertUnmanaged(power)
let fridge = CCRefrigeratorCreate(power)
let fridge = CCRefrigeratorCreate(power) // expected-error {{'Unmanaged<CCPowerSupplyRef>' is not convertible to 'CCPowerSupply'}}
assertUnmanaged(fridge)
}
@@ -20,3 +21,46 @@ func test2() {
assertUnmanaged(fridge)
}
func test3(fridge: CCRefrigerator) {
assertManaged(fridge)
}
func test4() {
// FIXME: this should not require a type annotation
let power: CCPowerSupply = kCCPowerStandard
assertManaged(power)
let fridge = CCRefrigeratorCreate(power)
assertUnmanaged(fridge)
}
func test5() {
let power: Unmanaged<CCPowerSupply> = .passUnretained(kCCPowerStandard)
assertUnmanaged(power)
let fridge = CCRefrigeratorCreate(power.takeUnretainedValue())
}
func test6() {
let fridge = CCRefrigeratorCreate(nil)
fridge?.release()
}
func test7() {
let value = CFBottom()
assertUnmanaged(value)
}
func test8(f: CCRefrigerator) {
let v1: CFTypeRef = f
let v2: AnyObject = f
}
func test9() {
let fridge = CCRefrigeratorCreateMutable(kCCPowerStandard).takeRetainedValue()
let constFridge: CCRefrigerator = fridge
CCRefrigeratorOpen(fridge)
let item = CCRefrigeratorGet(fridge, 0).takeUnretainedValue()
CCRefrigeratorInsert(item, fridge) // expected-error {{'CCItem' is not convertible to 'CCMutableRefrigerator'}}
CCRefrigeratorInsert(constFridge, item) // expected-error {{'CCRefrigerator' is not convertible to 'CCMutableRefrigerator'}}
CCRefrigeratorInsert(fridge, item)
CCRefrigeratorClose(fridge)
}

View File

@@ -1,7 +1,17 @@
// RUN: rm -rf %t/clang-module-cache
// RUN: %swift -module-cache-path=%t/clang-module-cache -sdk=%S/Inputs %s -emit-llvm -o - | FileCheck %s
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -target x86_64-apple-darwin13 %s -emit-ir -o - | FileCheck %s
import cfuncs
// CHECK: call void @cfunc1
cfunc1()
// CHECK: call double @pow(double 3.141590e+00, double 2.718280e+00)
var d = pow(3.14159, 2.71828)
// CHECK: call i32 @"\01_something_else"(i32 17)
renamed(17)
// CHECK: call void @exit(i32 17)
exit(17)

View File

@@ -1,22 +1,121 @@
// RUN: rm -rf %t/clang-module-cache
// RUN: %swift -parse -verify -module-cache-path=%t/clang-module-cache -sdk=%S/Inputs %s
// RUN: ls -lR %t/clang-module-cache | grep cfuncs.pcm
// RUN: rm -rf %t
// RUN: mkdir -p %t
// RUN: %swift %clang-importer-sdk -parse -verify -module-cache-path %t/clang-module-cache -target x86_64-apple-darwin13 -I %S/Inputs %s
// RUN: ls -lR %t/clang-module-cache | FileCheck %s
// CHECK: cfuncs{{.*}}.pcm
import cfuncs
func test_cfunc1(i : Int) {
func test_cfunc1(i: Int) {
cfunc1() // okay
cfunc1(i) // expected-error{{invalid conversion from type 'Int' to '()'}} expected-note{{while converting}}
cfunc1(i) // expected-error{{cannot convert the expression's type '$T2' to type '() -> Void'}}
}
func test_cfunc2(i : Int) {
func test_cfunc2(i: Int) {
var f = cfunc2(i, 17)
var f2 : Float = f
cfunc2(b=17, a=i)
cfunc2(b:17, a:i) // expected-error{{cannot convert the expression's type '$T3' to type 'CLong'}}
}
func test_cfunc3() {
// FIXME: Breaks with an explicit closure, but I'm not sure why.
var b = cfunc3( func(a : Double, b : Double) -> Double { return a + b } )
func test_cfunc3_a() {
var b = cfunc3( { (a : Double, b : Double) -> Double in a + b } )
var d : Double = b(1.5, 2.5)
var d1 : Double = b // expected-error{{invalid conversion from type 'double_bin_op_block' to 'Double'}} expected-note{{while converting}}
var d1 : Double = b // expected-error{{'double_bin_op_block' is not convertible to 'Double'}}
}
func test_cfunc3_b() {
var b = cfunc3( { a, b in a + b } )
var d : Double = b(1.5, 2.5)
var d1 : Double = b // expected-error{{'double_bin_op_block' is not convertible to 'Double'}}
}
func test_cfunc3_c() {
var b = cfunc3({ $0 + $1 })
var d : Double = b(1.5, 2.5)
var d1 : Double = b // expected-error{{'double_bin_op_block' is not convertible to 'Double'}}
}
func test_cfunc3_d() {
var x: Double = 0
var y: Double = 0
var z: Double? = cfunc3(nil)?(x, y)
var w: Double = cfunc3(nil)!(x, y)
}
func test_cfunc4() {
// Okay: has no prototype, so assume no parameters.
cfunc4()
}
func test_pow() {
pow(1.5, 2.5)
}
func test_puts(s: String) {
var i = s.withCString { puts($0) + 32 };
}
func test_fopen(filename: String) -> CInt {
var file = filename.withCString { fopen($0, "r") }
return file.get().inode
}
func test_cfunc_in_swift() -> Int {
return cfunc_in_swift(5)
}
func test_inline_available() {
createSomething()
}
func test_pointer() {
var i: CInt = 0
var ia: CInt[] = [1, 2, 3]
var f: CFloat = 0
var fa: CFloat[] = [1, 2, 3]
param_pointer(UnsafePointer<CInt>())
param_pointer(&i)
param_pointer(&ia)
param_const_pointer(UnsafePointer<CInt>())
param_const_pointer(&i)
param_const_pointer(ia)
param_const_pointer([1, 2, 3])
param_void_pointer(COpaquePointer())
param_void_pointer(UnsafePointer<CInt>())
param_void_pointer(UnsafePointer<CFloat>())
param_void_pointer(&i)
param_void_pointer(&ia)
param_void_pointer(&f)
param_void_pointer(&fa)
param_const_void_pointer(COpaquePointer())
param_const_void_pointer(UnsafePointer<CInt>())
param_const_void_pointer(UnsafePointer<CFloat>())
param_const_void_pointer(&i)
param_const_void_pointer(ia)
param_const_void_pointer([1, 2, 3])
param_const_void_pointer(&f)
param_const_void_pointer(fa)
param_const_void_pointer([1.0, 2.0, 3.0])
}
func test_decay() {
decay_param_array(UnsafePointer<CInt>())
var i: CInt = 0
var a: CInt[] = [1, 2, 3]
decay_param_array(&i)
decay_param_array(&a)
decay_param_const_array(UnsafePointer<CInt>())
decay_param_const_array(&i)
decay_param_const_array(a)
decay_param_const_array([1, 2, 3])
}
func exit(_: Float) {} // expected-note {{found this candidate}}
func test_ambiguous() {
exit(5) // expected-error {{ambiguous use of 'exit'}}
}

Some files were not shown because too many files have changed in this diff Show More