Skip to content

Instantly share code, notes, and snippets.

@jeremy-w
Created August 27, 2012 23:50
Show Gist options
  • Save jeremy-w/3493503 to your computer and use it in GitHub Desktop.
Save jeremy-w/3493503 to your computer and use it in GitHub Desktop.
Tops script to convert code to use Obj-C literals
// clang -g -Weverything -framework Foundation literals.m -o literals
/* @file literals.m
* @author Jeremy W. Sherman
* @url http://jeremywsherman.com/
* @date 2012-08-27 */
#import <Foundation/Foundation.h>
int
main(void)
{
@autoreleasepool {
NSString *string = @"string";
/* Array Literals */
NSArray *array = [[NSArray alloc] init];
array = [NSArray array];
array = [[NSArray alloc] initWithObjects:@"0", @"1", @"2", (void *)nil];
array = [NSArray arrayWithObjects:@"0", @"1", @"2", nil];
/* Don't rewrite mutable creation, since container literals
* create immutable containers. */
NSMutableArray *marray = [NSMutableArray arrayWithObjects:@"NO", nil];
[marray replaceObjectAtIndex:0 withObject:string];
string = [array objectAtIndex:0];
array = [[NSMutableArray alloc] initWithObjects:
@"1", @"2", @"3", nil];
/* Dictionary Literals */
NSDictionary *dict = [[NSDictionary alloc] init];
dict = [NSDictionary dictionary];
dict = [[NSDictionary alloc]
initWithObjectsAndKeys:@"obj", @"key", @"v", @"k", (void *)nil];
dict = [NSDictionary dictionaryWithObjectsAndKeys:
@"bar", @"key", (void *)nil];
NSMutableDictionary *mdict = [[NSMutableDictionary alloc]
init];
[mdict setObject:@"foo" forKey:@"key"];
/* Trickier? */
NSArray *arrays[] = {array, array};
id obj = [*arrays objectAtIndex:0];
obj = [*(arrays + 1) objectAtIndex:0];
NSLog(@"%@", obj);
}
}
/*tops -semiverbose -scriptfile literals.tops Project/_**_/*.(h|m|hpp|mm)
* Drop the underscores around the **, needed to avoid closing the comment. */
/* @file literals.tops
* @author Jeremy W. Sherman
* @url http://jeremywsherman.com/
* @date 2012-08-27 */
/* Dictionary Creation
* Literals create immutable dicts, so only replace NSDictionary not
* NSMutableDictionary. */
replace "[NSDictionary dictionary]" with "@{}"
replace "[[NSDictionary alloc] init]" with "@{}"
replace "[NSDictionary new]" with "@{}"
replace "[NSDictionary dictionaryWithObjectsAndKeys:<a args>]"
with "@{<args>}"
within ("<args>") {
replace ", nil" with ""
replace ", (<b cast>)nil" with ""
replace "<val>, <key>" with "<key> : <val>!!!"
replace "!!!" with ""
}
replace "[[NSDictionary alloc] initWithObjectsAndKeys:<a args>]"
with "@{<args>}"
within ("<args>") {
replace ", nil" with ""
replace ", (<b cast>)nil" with ""
replace "<val>, <key>" with "<key> : <val>!!!"
replace "!!!" with ""
}
/* Dictionary Access */
/* We distinguish between simple tokens and entire expressions, and wrap
* expressions with parens in the substitution.
* We do the same for arrays later. */
replace "[<t dict> objectForKey:<key>]" with "<dict>[<key>]"
replace "[<expr> objectForKey:<key>]" with "(<expr>)[<key>]"
/* Dictionary Mutation */
replace "[<t dict> setObject:<obj> forKey:<key>]" with "<dict>[<key>] = <obj>"
replace "[<expr> setObject:<obj> forKey:<key>]" with "(<expr>)[<key>] = <obj>"
/* Array Creation */
replace "[NSArray array]" with "@[]"
replace "[[NSArray alloc] init]" with "@[]"
replace "[NSArray new]" with "@[]"
replace "[[NSArray alloc] initWithObjects:<a objs>]" with "@[<objs>]"
within ("<objs>") {
replace ", nil" with ""
replace ", (<b cast>)nil" with ""
}
replace "[NSArray arrayWithObjects:<a objs>]" with "@[<objs>]"
within ("<objs>") {
replace ", nil" with ""
replace ", (<b cast>)nil" with ""
}
/* Array Access */
replace "[<t arr> objectAtIndex:<i>]" with "<arr>[<i>]"
replace "[<expr> objectAtIndex:<i>]" with "(<expr>)[<i>]"
/* Array Mutation */
replace "[<t arr> replaceObjectAtIndex:<i> withObject:<obj>]"
with "<arr>[<i>] = <obj>"
replace "[<expr> replaceObjectAtIndex:<i> withObject:<obj>]"
with "(expr)[<i>] = <obj>"
/* Number Literals */
/* Not handled, because Apple releases don't yet support boxed expressions,
* many numbers are likely to be created with boxed expressions, and tops
* can't distinguish type well enough to restrict transformations to
* those involving only numeric literals. */
@jeremy-w
Copy link
Author

Thank you to Konstantin Dorodov for correcting the array literal notation in the rewrite rules.

NeXT plaintext plists used ()s for arrays. Objective-C literals use @[]. @() will eventually be used for boxed expressions, which are really cool, so I hope they hit Apple's clang soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment