Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Property behaviors prototype #1297

Closed
wants to merge 5 commits into from

Conversation

jckarter
Copy link
Member

Parse 'var [behavior] x: T', and when we see it, try to instantiate the property's
implementation in terms of the given behavior. To start out, behaviors are modeled
as protocols. If the protocol follows this pattern:

  protocol behavior {
    associatedtype Value
  }
  extension behavior {
    var value: Value { ... }
  }

then the property is instantiated by forming a conformance to behavior where
Self is bound to the enclosing type and Value is bound to the property's
declared type, and invoking the accessors of the value implementation:

  struct Foo {
    var [behavior] foo: Int
  }

  /* behaves like */

  extension Foo: private behavior {
    @implements(behavior.Value)
    private typealias `[behavior].Value` = Int

    var foo: Int {
      get { return value }
      set { value = newValue }
    }
  }

If the protocol requires a storage member, and provides an initStorage method
to provide an initial value to the storage:

  protocol storageBehavior {
    associatedtype Value

    var storage: Something<Value> { ... }
  }
  extension storageBehavior {
    var value: Value { ... }

    static func initStorage() -> Something<Value> { ... }
  }

then a stored property of the appropriate type is instantiated to witness the
requirement, using initStorage to initialize:

  struct Foo {
    var [storageBehavior] foo: Int
  }

  /* behaves like */

  extension Foo: private storageBehavior {
    @implements(storageBehavior.Value)
    private typealias `[storageBehavior].Value` = Int
    @implements(storageBehavior.storage)
    private var `[storageBehavior].storage`: Something<Int> = initStorage()

    var foo: Int {
      get { return value }
      set { value = newValue }
    }
  }

In either case, the value and storage properties should support any combination
of get-only/settable and mutating/nonmutating modifiers. The instantiated property
follows the settability and mutating-ness of the value implementation. The
protocol can also impose requirements on the Self and Value types.

Bells and whistles such as initializer expressions, accessors,
out-of-line initialization, etc. are not implemented. Additionally, behaviors
that instantiate storage are currently only supported on instance properties.
This also hasn't been tested past sema yet; SIL and IRGen will likely expose
additional issues.

@jckarter
Copy link
Member Author

@swift-ci Please test

@jckarter
Copy link
Member Author

@swift-ci Please test

@@ -3626,7 +3647,7 @@ class AbstractStorageDecl : public ValueDecl {
}
};
void configureAddressorRecord(AddressorRecord *record,
FuncDecl *addressor, FuncDecl *mutableAddressor);
FuncDecl *addressor, FuncDecl *mutableAddressor);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pointless edit here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing an 80-column violation.

@slavapestov
Copy link
Member

@jckarter This looks awesome. I just have a few nitpicks that you're free to ignore.

@jckarter
Copy link
Member Author

@swift-ci Please test

@jckarter
Copy link
Member Author

@swift-ci Please test

Parse 'var [behavior] x: T', and when we see it, try to instantiate the property's
implementation in terms of the given behavior. To start out, behaviors are modeled
as protocols. If the protocol follows this pattern:

  ```
  protocol behavior {
    associatedtype Value
  }
  extension behavior {
    var value: Value { ... }
  }
  ```

then the property is instantiated by forming a conformance to `behavior` where
`Self` is bound to the enclosing type and `Value` is bound to the property's
declared type, and invoking the accessors of the `value` implementation:

  ```
  struct Foo {
    var [behavior] foo: Int
  }

  /* behaves like */

  extension Foo: private behavior {
    @implements(behavior.Value)
    private typealias `[behavior].Value` = Int

    var foo: Int {
      get { return value }
      set { value = newValue }
    }
  }
  ```

If the protocol requires a `storage` member, and provides an `initStorage` method
to provide an initial value to the storage:

  ```
  protocol storageBehavior {
    associatedtype Value

    var storage: Something<Value> { ... }
  }
  extension storageBehavior {
    var value: Value { ... }

    static func initStorage() -> Something<Value> { ... }
  }
  ```

then a stored property of the appropriate type is instantiated to witness the
requirement, using `initStorage` to initialize:

  ```
  struct Foo {
    var [storageBehavior] foo: Int
  }

  /* behaves like */

  extension Foo: private storageBehavior {
    @implements(storageBehavior.Value)
    private typealias `[storageBehavior].Value` = Int
    @implements(storageBehavior.storage)
    private var `[storageBehavior].storage`: Something<Int> = initStorage()

    var foo: Int {
      get { return value }
      set { value = newValue }
    }
  }
  ```

In either case, the `value` and `storage` properties should support any combination
of get-only/settable and mutating/nonmutating modifiers. The instantiated property
follows the settability and mutating-ness of the `value` implementation. The
protocol can also impose requirements on the `Self` and `Value` types.

Bells and whistles such as initializer expressions, accessors,
out-of-line initialization, etc. are not implemented. Additionally, behaviors
that instantiate storage are currently only supported on instance properties.
This also hasn't been tested past sema yet; SIL and IRGen will likely expose
additional issues.
Fix some interface type/context type confusion in the AST synthesis from the previous patch, add a unique private mangling for behavior protocol conformances, and set up SILGen to emit the conformances when property declarations with behaviors are visited. Disable synthesis of the struct memberwise initializer if any instance properties use behaviors; codegen will need to be redesigned here.
We have enough implementation to do "delayed" now.
@jckarter jckarter changed the title Sema: Initial parsing and synthesis for properties with behaviors. Property behaviors prototype Feb 19, 2016
@jckarter
Copy link
Member Author

@swift-ci Please test

…rement.

Would be nice to have `guard` in C++...
Since the feature is incomplete and yet to be accepted or implemented as proposed, hide it behind an -enable-experimental-property-behaviors frontend flag.
@jckarter
Copy link
Member Author

@swift-ci Please test

@jckarter
Copy link
Member Author

I've merged this into master, hidden behind a frontend flag, -enable-experimental-property-behaviors.

@jckarter jckarter closed this Feb 21, 2016
@jckarter jckarter deleted the property-behaviors branch February 21, 2016 03:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants