Add support for Objective-C class implementation #5064
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Add support for Objective-C class implementation
The purpose of this work is to add full Odin-native support for creating Objective-C classes, not just consuming them.
Doing so without modifying syntax, only leveraging attributes and new compiler intrinsics. I also attempt to leverage existing attributes and augment them when necessarry to add the desired new functionality.
This facilitates creating new classes where needed, for things like delegates, event handlers, etc. without ugly runtime workarounds, or leaving Odin to provide it in a different language.
This PR has the following requirements:
What it does not aim to do (at least not this PR):
Requirements
Implement
@objc_implement
attribute for structsImplement
@objc_superclass
attribute for procsImplement
@objc_ivar
attributeLimit generating the global ivar offset to intrinsic usage?
Implement
@objc_selector
attributeApply a legitimate strategy for export/linkage
@export
attribute is applied to an Objective-C class, then all methods are exported. Currently all are exported unconditionally (@export
is implied)Checker:
Proper, understandable error messages
Resolve all pending TODOs
State and discussion
At the time of this writing the full example below works as all the main requirements have been implemented. It will only work with a single module as there's still issues with the changes. Due to lack of experience with the codebase there needs to be some guidance from the team to get this to a proper shippable state.
I'd like to get feedback on attribute and intrinsic naming in addition to the code changes itself.
Practical Explanation & Usage
Creating a new Objective-C class looks like it does when consuming an existing one, except we add the
@objc_implement
attribute:Typically you also want to specify a super/base class as well:
Finally you may want to associate a type to serve as the class' Ivar:
You can add methods to it the same way you do when consuming existing Objective-C methods, simply add the same
@objc_implement
attribute:The compiler will generate a hidden function that conforms to the signature that the Objective-C runtime expects, which simply forwards the call to our method
proc
:Any arguments will be forwarded:
Notice the use of the new intrinsic
intrinsics.ivar_get
. This intrinsic will obtain a pointer to the Type's data of the Ivar from an instance, if one is associated with the class. This is implemented by recording the offset to the ivar at startup, then it simply offsets from the instance pointer during the call to the intrinsic.You can also specify the selector name to be used for a method. By default the value of
@objc_name
will be used, if one is not specified. But there will be many cases when you may want to specify one manually, as it is when implementing a protocol. Specify it via the@objc_selector
attribute:Full working example of an
NSAppDelegate
(partially) implemented in Odin: