Skip to content

Commit

Permalink
Split 'type' keyword into 'static' and 'class'
Browse files Browse the repository at this point in the history
rdar://15911697


Swift SVN r13908
  • Loading branch information
gribozavr committed Feb 14, 2014
1 parent efe54a1 commit 571c9b3
Show file tree
Hide file tree
Showing 42 changed files with 765 additions and 284 deletions.
2 changes: 1 addition & 1 deletion docs/Import.rst
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fails, we fall back to qualified lookup into the module::
import Foo // exports bas

class Foo {
type func bar()
class func bar()
}

Foo.bar() // bar method from Foo class
Expand Down
28 changes: 18 additions & 10 deletions docs/LangRef.html
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ <h3 id="decl-var">var Declarations</h3>
<!-- ===================================================================== -->

<pre class="grammar">
decl-var ::= <a href="#attribute-list">attribute-list</a> 'type'? var' <a href="#pattern">pattern</a> initializer? (',' pattern initializer?)*
decl-var ::= <a href="#attribute-list">attribute-list</a> ('static' | 'class')? var' <a href="#pattern">pattern</a> initializer? (',' pattern initializer?)*

decl-var ::= <a href="#attribute-list">attribute-list</a> 'var' <a href="#identifier">identifier</a> ':' <a href="#type">type-annotation</a> <a href="#brace-item-list">brace-item-list</a>

Expand Down Expand Up @@ -869,13 +869,17 @@ <h3 id="decl-var">var Declarations</h3>
</pre>

<p>Note that both 'get' and 'set' are context-sensitive keywords.</p>


<p>'static' keyword is allowed inside structs and enums, and extensions of those.</p>

<p>'class' keyword is allowed inside classes, class extensions, and protocols.</p>

<!-- ===================================================================== -->
<h3 id="decl-func">func Declarations</h3>
<!-- ===================================================================== -->

<pre class="grammar">
decl-func ::= <a href="#attribute-list">attribute-list</a> 'type'? 'func' <a href="#any-identifier">any-identifier</a> <a href="#generic-params">generic-params</a>? <a href="#func-signature">func-signature</a> <a href="#brace-item-list">brace-item-list</a>?
decl-func ::= <a href="#attribute-list">attribute-list</a> ('static' | 'class')? 'func' <a href="#any-identifier">any-identifier</a> <a href="#generic-params">generic-params</a>? <a href="#func-signature">func-signature</a> <a href="#brace-item-list">brace-item-list</a>?
</pre>

<p>'func' is a declaration for a function. The argument list and
Expand All @@ -892,13 +896,17 @@ <h3 id="decl-func">func Declarations</h3>
in other places that are semantically equivalent to an extension) implicitly
get a 'self' argument with these rules ... [todo]</p>

<p>'type' functions are only allowed in an <a
<p>'static' and 'class' functions are only allowed in an <a
href="#decl-extension">extension</a> of some type (or in other places
that are semantically equivalent to an extension). They indicate that
the function is actually defined on the <a href="#metatype">metatype</a>
for the type, not on the
type itself. Thus its implicit 'self' argument is actually of
metatype type.</p>

<p>'static' keyword is allowed inside structs and enums, and extensions of those.</p>

<p>'class' keyword is allowed inside classes, class extensions, and protocols.</p>

<p>TODO: Func should be an immutable name binding, it should implicitly add
an attribute immutable when it exists.</p>
Expand Down Expand Up @@ -987,14 +995,14 @@ <h4 id="func-signature">Function signatures</h4>
struct bankaccount {
amount : Int

type func bankaccount() -> bankaccount {
static func bankaccount() -> bankaccount {
// Custom 'constructor' logic goes here.
}
func deposit(arg : Int) {
amount = amount + arg
}

type func someMetatypeMethod() {}
static func someMetatypeMethod() {}
}

<i>// Dot syntax on metatype.</i>
Expand Down Expand Up @@ -1692,19 +1700,19 @@ <h3>Metatypes</h3>
<p id="metatype">Each type has a corresponding <i>metatype</i>, with the same
name as the type, that is injected into the standard name lookup scope when
a type is <a href="#decl">declared</a>. This allows access to '<a
href="#decl-func">type functions</a>' through dot syntax. For example:</p>
href="#decl-func">static functions</a>' through dot syntax. For example:</p>

<pre class="example">
// Declares a type 'foo' as well as its metatype.
struct foo {
type func bar() {}
static func bar() {}
}

// Declares x to be of type foo. A reference to a name in type context
// refers to the type itself.
var x : foo

// Accesses a type function on the foo metatype. In a value context, the
// Accesses a static function on the foo metatype. In a value context, the
// name of its type refers to its metatype.
foo.bar()
</pre>
Expand Down Expand Up @@ -2824,7 +2832,7 @@ <h3 id="expr-identifier">Identifiers</h3>
<i>// A generic struct.</i>
struct Dict&lt;K,V&gt; {
init() {}
type func fromKeysAndValues(keys:K[], values:T[]) -&gt; Dict&lt;K,V&gt; {}
static func fromKeysAndValues(keys:K[], values:T[]) -&gt; Dict&lt;K,V&gt; {}
}

<i>// Construct an instance of the generic struct.</i>
Expand Down
8 changes: 4 additions & 4 deletions docs/Literals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ library's Policy.swift::
// NOTE: the compiler has builtin knowledge of this protocol
protocol StringLiteralConvertible {
typealias StringLiteralType : BuiltinStringLiteralConvertible
type func convertFromStringLiteral(value : StringLiteralType) -> Self
class func convertFromStringLiteral(value : StringLiteralType) -> Self
}

Curiously, the protocol is not defined in terms of primitive types, but in
Expand All @@ -62,9 +62,9 @@ Policy.swift contains a second protocol::

// NOTE: the compiler has builtin knowledge of this protocol
protocol BuiltinStringLiteralConvertible {
type func _convertFromBuiltinStringLiteral(value : Builtin.RawPointer,
byteSize : Builtin.Int64,
isASCII: Builtin.Int1) -> Self
class func _convertFromBuiltinStringLiteral(value : Builtin.RawPointer,
byteSize : Builtin.Int64,
isASCII: Builtin.Int1) -> Self
}

The use of builtin types makes it clear that this is *only* for use in the
Expand Down
2 changes: 1 addition & 1 deletion docs/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Syntax overview
func f(x : Int) -> Int {
return MyVar + x
}
type func getAMyclass() -> MyClass {
class func getAMyclass() -> MyClass {
return new MyClass
}
constructor() {
Expand Down
4 changes: 2 additions & 2 deletions docs/proposals/Enums.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ models the traditional relationship between a C enum and its raw type::
/// conforming type.
/// Returns None if the raw value has no corresponding conforming type
/// value.
type func fromRaw(_:RawType) -> Self?
class func fromRaw(_:RawType) -> Self?
}

Any type may manually conform to the RawRepresentable protocol following the above
Expand Down Expand Up @@ -330,7 +330,7 @@ methods. The NSChangeDictionaryKey definition behaves as if defined::
}
}

type func fromRaw(s:String) -> NSChangeDictionaryKey? {
static func fromRaw(s:String) -> NSChangeDictionaryKey? {
switch s {
case "NSKeyValueChangeKindKey":
return .NSKeyValueChangeKindKey
Expand Down
12 changes: 6 additions & 6 deletions docs/proposals/OptionSets.rst
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ For example::
AlignHeightInward : Bool = false

// convenience combinations
type func NSAlignAllEdgesInward() {
static func NSAlignAllEdgesInward() {
return NSAlignmentOptions(AlignMinXInward: true,
AlignMaxXInward: true,
AlignMinYInward: true,
Expand Down Expand Up @@ -265,7 +265,7 @@ bitwise operations can be applied to them.
struct MyOptions : OptionSet {
var Foo, Bar, Bas : Bool = false
type func Foobar() -> MyOptions {
static func Foobar() -> MyOptions {
return MyOptions(Foo: true, Bar: true)
}
}
Expand All @@ -281,14 +281,14 @@ individual option::
// Stored properties of instances
var Foo, Bar, Bas : Bool = false

type func Foobar() -> MyOptions {
static func Foobar() -> MyOptions {
return MyOptions(Foo: true, Bar: true)
}

// Implicitly-generated static properties?
type func Foo() -> MyOptions { return MyOptions(Foo: true) }
type func Bar() -> MyOptions { return MyOptions(Bar: true) }
type func Bas() -> MyOptions { return MyOptions(Bas: true) }
static func Foo() -> MyOptions { return MyOptions(Foo: true) }
static func Bar() -> MyOptions { return MyOptions(Bar: true) }
static func Bas() -> MyOptions { return MyOptions(Bas: true) }
}

var x: MyOptions = .Foobar() | .Bas()
Expand Down
71 changes: 56 additions & 15 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ enum class CircularityCheck {
Checked
};

/// Describes which spelling was used in the source for the 'static' or 'class'
/// keyword.
enum class StaticSpellingKind : uint8_t {
None,
KeywordStatic,
KeywordClass,
};

/// Diagnostic printing of \c StaticSpellingKind.
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, StaticSpellingKind SSK);

/// Decl - Base class for all declarations in Swift.
class alignas(8) Decl {
// alignas(8) because we use three tag bits on Decl*.
Expand Down Expand Up @@ -142,13 +153,16 @@ class alignas(8) Decl {
/// \brief Whether this pattern binding declares static variables.
unsigned IsStatic : 1;

/// \brief Whether 'static' or 'class' was used.
unsigned StaticSpelling : 2;

/// \brief Whether this pattern binding declares a variable with storage.
unsigned HasStorage : 1;

/// \brief Whether this pattern binding appears in a conditional statement.
unsigned Conditional : 1;
};
enum { NumPatternBindingDeclBits = NumDeclBits + 3 };
enum { NumPatternBindingDeclBits = NumDeclBits + 5 };
static_assert(NumPatternBindingDeclBits <= 32, "fits in an unsigned");

class ValueDeclBitfields {
Expand All @@ -165,8 +179,8 @@ class alignas(8) Decl {

/// \brief Whether this property is a type property (currently unfortunately
/// called 'static').
unsigned Static : 1;
unsigned IsStatic : 1;

/// \brief Whether this is a 'let' property, which can only be initialized
/// in its declaration, and never assigned to, making it immutable.
unsigned IsLet : 1;
Expand Down Expand Up @@ -200,13 +214,17 @@ class alignas(8) Decl {
unsigned : NumAbstractFunctionDeclBits;

/// Whether this function is a 'static' method.
unsigned Static : 1;
unsigned IsStatic : 1;

/// \brief Whether 'static' or 'class' was used.
unsigned StaticSpelling : 2;

/// Whether this function is a 'mutating' method.
unsigned Mutating : 1;
/// Whether this function has a \c DynamicSelf return type.
unsigned HasDynamicSelf : 1;
};
enum { NumFuncDeclBits = NumAbstractFunctionDeclBits + 3 };
enum { NumFuncDeclBits = NumAbstractFunctionDeclBits + 5 };
static_assert(NumFuncDeclBits <= 32, "fits in an unsigned");

class ConstructorDeclBitfields {
Expand Down Expand Up @@ -1252,15 +1270,18 @@ class PatternBindingDecl : public Decl {
friend class Decl;

public:
PatternBindingDecl(SourceLoc StaticLoc,
SourceLoc VarLoc, Pattern *Pat, Expr *E,
PatternBindingDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
SourceLoc VarLoc,
Pattern *Pat, Expr *E,
bool hasStorage,
bool isConditional,
DeclContext *Parent)
: Decl(DeclKind::PatternBinding, Parent),
StaticLoc(StaticLoc), VarLoc(VarLoc), Pat(Pat),
InitAndChecked(E, false) {
PatternBindingDeclBits.IsStatic = StaticLoc.isValid();
PatternBindingDeclBits.StaticSpelling =
static_cast<unsigned>(StaticSpelling);
PatternBindingDeclBits.HasStorage = hasStorage;
PatternBindingDeclBits.Conditional = isConditional;
}
Expand Down Expand Up @@ -1292,6 +1313,13 @@ class PatternBindingDecl : public Decl {
bool isStatic() const { return PatternBindingDeclBits.IsStatic; }
void setStatic(bool s) { PatternBindingDeclBits.IsStatic = s; }
SourceLoc getStaticLoc() const { return StaticLoc; }
/// \returns the way 'static'/'class' was spelled in the source.
StaticSpellingKind getStaticSpelling() const {
return static_cast<StaticSpellingKind>(
PatternBindingDeclBits.StaticSpelling);
}
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;

static bool classof(const Decl *D) {
return D->getKind() == DeclKind::PatternBinding;
Expand Down Expand Up @@ -2633,7 +2661,7 @@ class VarDecl : public AbstractStorageDecl {
VarDecl(bool IsStatic, bool IsLet, SourceLoc NameLoc, Identifier Name,
Type Ty, DeclContext *DC)
: AbstractStorageDecl(DeclKind::Var, DC, Name, NameLoc) {
VarDeclBits.Static = IsStatic;
VarDeclBits.IsStatic = IsStatic;
VarDeclBits.IsLet = IsLet;
VarDeclBits.IsDebuggerVar = false;
setType(Ty);
Expand Down Expand Up @@ -2670,8 +2698,11 @@ class VarDecl : public AbstractStorageDecl {
bool isAnonClosureParam() const;

/// Is this a type ('static') variable?
bool isStatic() const { return VarDeclBits.Static; }
void setStatic(bool IsStatic) { VarDeclBits.Static = IsStatic; }
bool isStatic() const { return VarDeclBits.IsStatic; }
void setStatic(bool IsStatic) { VarDeclBits.IsStatic = IsStatic; }

/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;

/// Is this an immutable 'let' property?
bool isLet() const { return VarDeclBits.IsLet; }
Expand Down Expand Up @@ -3053,14 +3084,16 @@ class FuncDecl : public AbstractFunctionDecl {
FuncDecl *OverriddenDecl;
OperatorDecl *Operator;

FuncDecl(SourceLoc StaticLoc, SourceLoc FuncLoc, Identifier Name,
FuncDecl(SourceLoc StaticLoc, StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc, Identifier Name,
SourceLoc NameLoc, unsigned NumParamPatterns,
GenericParamList *GenericParams, Type Ty, DeclContext *Parent)
: AbstractFunctionDecl(DeclKind::Func, Parent, Name, NameLoc,
NumParamPatterns, GenericParams),
StaticLoc(StaticLoc), FuncLoc(FuncLoc),
OverriddenDecl(nullptr), Operator(nullptr) {
FuncDeclBits.Static = StaticLoc.isValid() || getName().isOperator();
FuncDeclBits.IsStatic = StaticLoc.isValid() || getName().isOperator();
FuncDeclBits.StaticSpelling = static_cast<unsigned>(StaticSpelling);
assert(NumParamPatterns > 0 && "Must have at least an empty tuple arg");
setType(Ty);
FuncDeclBits.Mutating = false;
Expand All @@ -3070,27 +3103,35 @@ class FuncDecl : public AbstractFunctionDecl {
public:
/// Factory function only for use by deserialization.
static FuncDecl *createDeserialized(ASTContext &Context, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc, Identifier Name,
SourceLoc NameLoc,
GenericParamList *GenericParams, Type Ty,
unsigned NumParamPatterns,
DeclContext *Parent);

static FuncDecl *create(ASTContext &Context, SourceLoc StaticLoc,
StaticSpellingKind StaticSpelling,
SourceLoc FuncLoc, Identifier Name, SourceLoc NameLoc,
GenericParamList *GenericParams, Type Ty,
ArrayRef<Pattern *> ArgParams,
ArrayRef<Pattern *> BodyParams,
TypeLoc FnRetType, DeclContext *Parent);

bool isStatic() const {
return FuncDeclBits.Static;
return FuncDeclBits.IsStatic;
}
/// \returns the way 'static'/'class' was spelled in the source.
StaticSpellingKind getStaticSpelling() const {
return static_cast<StaticSpellingKind>(FuncDeclBits.StaticSpelling);
}
/// \returns the way 'static'/'class' should be spelled for this declaration.
StaticSpellingKind getCorrectStaticSpelling() const;
bool isMutating() const {
return FuncDeclBits.Mutating;
}
void setStatic(bool Static = true) {
FuncDeclBits.Static = Static;
void setStatic(bool IsStatic = true) {
FuncDeclBits.IsStatic = IsStatic;
}
void setMutating(bool Mutating = true) {
FuncDeclBits.Mutating = Mutating;
Expand Down
Loading

0 comments on commit 571c9b3

Please sign in to comment.