Permalink
Browse files

operator cleanup

The (ivars) and (ivar-accessor) operators now do nothing and should
be removed. Instance variables are now implicitly created and
stored using associated objects, so there is no overhead for their
potential use.

The (cmethod) and (imethod) operators are still available but with
a deprecation warning in the log. They should be replaced by (+) and
(-), which are more consistent with Objective-C usage.

The (def) operator is gone. It was carried over from Ruby and in
practice, the equivalent (function) is preferred.
  • Loading branch information...
1 parent 3b1e414 commit aa31bfb1310ab1282da43ad4ee7661611b2743f5 @timburks timburks committed Jun 19, 2011
Showing with 183 additions and 148 deletions.
  1. +1 −2 nu/test.nu
  2. +2 −5 objc/Nu.m
  3. +3 −0 objc/NuHandler.m
  4. +2 −0 objc/NuObject.h
  5. +51 −5 objc/NuObject.m
  6. +6 −9 objc/NuOperator.m
  7. +27 −29 test/test_comparison.nu
  8. +1 −3 test/test_memory.nu
  9. +5 −7 test/test_structs.nu
  10. +85 −88 test/test_undo.nu
View
@@ -38,8 +38,7 @@
;;
;; <code>% nutest test/test_*.nu</code>
;;
-(class NuTestCase is NSObject
- (ivar (id) failures (id) assertions (id) errors)
+(class NuTestCase is NSObject
;; By overriding this method, we detect each time a class is defined in Nu that inherits from this class.
(+ (id) inheritedByClass:(id) testClass is
View
@@ -245,15 +245,15 @@ void NuInit()
[NSString include: [NuClass classWithClass:[NuEnumerable class]]];
[pool drain];
-#ifndef IPHONE
// Copy some useful methods from NSObject to NSProxy.
// Their implementations are identical; this avoids code duplication.
transplant_nu_methods([NSProxy class], [NSObject class]);
+ // swizzle container classes to allow us to add nil to collections (as NSNull).
void nu_swizzleContainerClasses();
nu_swizzleContainerClasses();
-#ifndef MININUSH
+#if !defined(MININUSH) && !defined(IPHONE)
// Load some standard files
// Warning: since these loads are performed without a context, the non-global symbols defined in them
// will not be available to other Nu scripts or at the console. These loads should only be used
@@ -263,9 +263,6 @@ void NuInit()
[Nu loadNuFile:@"cocoa" fromBundleWithIdentifier:@"nu.programming.framework" withContext:nil];
[Nu loadNuFile:@"help" fromBundleWithIdentifier:@"nu.programming.framework" withContext:nil];
#endif
-#endif
-
-
}
}
View
@@ -230,7 +230,10 @@ + (IMP) handlerWithSelector:(SEL)sel block:(NuBlock *)block signature:(const cha
}
#endif
else {
+#ifdef IPHONE
+ // this is only a problem on iOS.
NSLog(@"UNKNOWN RETURN TYPE %@", returnType);
+#endif
}
// the following is deprecated. Now that we can create IMPs from blocks, we don't need handler pools.
if (!handlerWarehouse) {
View
@@ -96,4 +96,6 @@
/*! Remove all associated objects. */
- (void) removeAssociatedObjects;
+- (id) attemptAutomaticIvarAccess:(id) message withContext:(NSMutableDictionary *) context returningSuccess:(BOOL *) success;
+
@end
View
@@ -272,14 +272,15 @@ + (id) handleUnknownMessage:(id) cdr withContext:(NSMutableDictionary *) context
return Nu__null;
}
-- (id) handleUnknownMessage:(id) cdr withContext:(NSMutableDictionary *) context
+
+- (id) handleUnknownMessage:(id) message withContext:(NSMutableDictionary *) context
{
// Collect the method selector and arguments.
// This seems like a bottleneck, and it also lacks flexibility.
// Replacing explicit string building with the selector cache reduced runtimes by around 20%.
// Methods with variadic arguments (NSArray arrayWithObjects:...) are not supported.
NSMutableArray *args = [NSMutableArray array];
- id cursor = cdr;
+ id cursor = message;
SEL sel = 0;
id nextSymbol = [cursor car];
if (nu_objectIsKindOfClass(nextSymbol, [NuSymbol class])) {
@@ -336,9 +337,48 @@ - (id) handleUnknownMessage:(id) cdr withContext:(NSMutableDictionary *) context
return result;
}
+#define AUTOMATIC_IVAR_ACCESSORS
+#ifdef AUTOMATIC_IVAR_ACCESSORS
+ //NSLog(@"attempting to access ivar %@", [message stringValue]);
+ int message_length = [message length];
+ if (message_length == 1) {
+ // try to automatically get an ivar
+ @try
+ {
+ NSString *ivarName = [[message car] stringValue];
+ //NSLog(@"looking for ivar %@", ivarName);
+ // ivar name is the first (only) token of the message
+ id result = [self valueForIvar:ivarName];
+ // NSLog(@"returning %@ = %@", ivarName, [result description]);
+ return result;
+ }
+ @catch (id error) {
+ //NSLog(@"skipping this error: %@", [error description]);
+ // no ivar, keep going
+ }
+ }
+ else if (message_length == 2) {
+ // try to automatically set an ivar
+ if ([[[[message car] stringValue] substringWithRange:NSMakeRange(0,3)] isEqualToString:@"set"]) {
+ @try
+ {
+ id firstArgument = [[message car] stringValue];
+ id variableName0 = [[firstArgument substringWithRange:NSMakeRange(3,1)] lowercaseString];
+ id variableName1 = [firstArgument substringWithRange:NSMakeRange(4, [firstArgument length] - 5)];
+ [self setValue:[[[message cdr] car] evalWithContext:context]
+ forIvar:[NSString stringWithFormat:@"%@%@", variableName0, variableName1]];
+ return Nu__null;
+ }
+ @catch (id error) {
+ // NSLog(@"skipping this error: %@", [error description]);
+ // no ivar, keep going
+ }
+ }
+ }
+#endif
NuCell *cell = [[[NuCell alloc] init] autorelease];
- [cell setCar: self];
- [cell setCdr: cdr];
+ [cell setCar:self];
+ [cell setCdr:message];
[NSException raise:@"NuUnknownMessage"
format:@"unable to find message handler for %@",
[cell stringValue]];
@@ -352,7 +392,13 @@ - (id) valueForIvar:(NSString *) name
// look for sparse ivar storage
NSMutableDictionary *sparseIvars = [self associatedObjectForKey:@"__nuivars"];
if (sparseIvars) {
- return [sparseIvars objectForKey:name];
+ // NSLog(@"sparse %@", [sparseIvars description]);
+ id result = [sparseIvars objectForKey:name];
+ if (result) {
+ return result;
+ } else {
+ NSLog(@"NO VALUE");
+ }
}
[NSException raise:@"NuNoInstanceVariable"
format:@"Unable to get ivar named %@ for object %@",
View
@@ -1731,6 +1731,7 @@ @interface Nu_cmethod_operator : NuOperator {}
@implementation Nu_cmethod_operator
- (id) callWithArguments:(id)cdr context:(NSMutableDictionary *)context
{
+ NSLog(@"The cmethod operator is deprecated. Please replace it with '+' in your code.");
NuSymbolTable *symbolTable = [context objectForKey:SYMBOLS_KEY];
NuClass *classWrapper = [context objectForKey:[symbolTable symbolWithCString:"_class"]];
[classWrapper registerClass];
@@ -1748,6 +1749,7 @@ @interface Nu_imethod_operator : NuOperator {}
@implementation Nu_imethod_operator
- (id) callWithArguments:(id)cdr context:(NSMutableDictionary *)context
{
+ NSLog(@"The imethod operator is deprecated. Please replace it with '-' in your code.");
NuSymbolTable *symbolTable = [context objectForKey:SYMBOLS_KEY];
NuClass *classWrapper = [context objectForKey:[symbolTable symbolWithCString:"_class"]];
[classWrapper registerClass];
@@ -1767,12 +1769,10 @@ - (id) callWithArguments:(id)cdr context:(NSMutableDictionary *)context
{
NuSymbolTable *symbolTable = [context objectForKey:SYMBOLS_KEY];
NuClass *classWrapper = [context objectForKey:[symbolTable symbolWithCString:"_class"]];
-#if defined(__x86_64__) || defined(IPHONE)
// this will only work if the class is unregistered...
if ([classWrapper isRegistered]) {
- [NSException raise:@"NuIvarAddedTooLate" format:@"instance variables must be added when a class is created and before any method declarations"];
+ [NSException raise:@"NuIvarAddedTooLate" format:@"explicit instance variables must be added when a class is created and before any method declarations"];
}
-#endif
Class classToExtend = [classWrapper wrappedClass];
if (!classToExtend)
[NSException raise:@"NuMisplacedDeclaration" format:@"instance variable declaration with no enclosing class declaration"];
@@ -1799,6 +1799,7 @@ @interface Nu_ivars_operator : NuOperator {}
@implementation Nu_ivars_operator
- (id) callWithArguments:(id)cdr context:(NSMutableDictionary *)context
{
+ NSLog(@"The ivars operator is unnecessary. Please remove it from your source.");
return Nu__null;
}
@@ -1810,11 +1811,7 @@ @interface Nu_ivar_accessors_operator : NuOperator {}
@implementation Nu_ivar_accessors_operator
- (id) callWithArguments:(id)cdr context:(NSMutableDictionary *)context
{
- NuSymbolTable *symbolTable = [context objectForKey:SYMBOLS_KEY];
- NuClass *classWrapper = [context objectForKey:[symbolTable symbolWithCString:"_class"]];
- [classWrapper registerClass];
- Class classToExtend = [classWrapper wrappedClass];
- [classToExtend include:[NuClass classWithClass:[NuAutomaticIvars class]]];
+ NSLog(@"The ivar-accessors operator is unnecessary. Please remove it from your source.");
return Nu__null;
}
@@ -2160,7 +2157,7 @@ void load_builtins(NuSymbolTable *symbolTable)
install("regex", Nu_regex_operator);
- install("def", Nu_function_operator);
+ // install("def", Nu_function_operator); // did anyone use this?
install("function", Nu_function_operator);
install("progn", Nu_progn_operator);
install("then", Nu_progn_operator);
View
@@ -29,32 +29,30 @@
(assert_equal nil (>= 3 2 1 2))
(assert_equal nil (>= "a" "b")))
- (if (eq (uname) "Darwin") ;; I think the problem here is with method declaration
- (- testCustomComparison is
-
- (class NumericString is NSObject
- (ivar (id) string)
- (+ stringWithString:s is ((self alloc) initWithString:s))
- (- initWithString:s is
- (self init)
- (set @string s)
- self)
- (- stringValue is @string)
- (- description is @string)
- (- (int) compare:(id) other is
- ((@string intValue) compare:((other stringValue) intValue))))
-
- (set x (NumericString stringWithString:"123"))
- (set y (NumericString stringWithString:"45"))
- (set z (NumericString stringWithString:"12"))
-
- (set a ((array x y z) sort))
-
- (assert_equal "12" ((a 0) stringValue))
- (assert_equal "45" ((a 1) stringValue))
- (assert_equal "123" ((a 2) stringValue))
-
- (assert_equal nil (<= x y))
- (assert_equal nil (< x y))
- (assert_equal t (>= x y))
- (assert_equal t (> x y)))))
+ (- testCustomComparison is
+
+ (class NumericString is NSObject
+ (+ stringWithString:s is ((self alloc) initWithString:s))
+ (- initWithString:s is
+ (self init)
+ (set @string s)
+ self)
+ (- stringValue is @string)
+ (- description is @string)
+ (- (int) compare:(id) other is
+ ((@string intValue) compare:((other stringValue) intValue))))
+
+ (set x (NumericString stringWithString:"123"))
+ (set y (NumericString stringWithString:"45"))
+ (set z (NumericString stringWithString:"12"))
+
+ (set a ((array x y z) sort))
+
+ (assert_equal "12" ((a 0) stringValue))
+ (assert_equal "45" ((a 1) stringValue))
+ (assert_equal "123" ((a 2) stringValue))
+
+ (assert_equal nil (<= x y))
+ (assert_equal nil (< x y))
+ (assert_equal t (>= x y))
+ (assert_equal t (> x y))))
View
@@ -43,9 +43,7 @@
(- testIvarReleaseOnDealloc is
(class IvarReleaseHelper is NuTestHelper
- ;;(ivar (id) x) ;; currently declared ivars are not released, this is consistent with unretained outlets
- (ivars)
- (ivar-accessors)
+ ;;(ivar (id) x) ;; currently declared ivars are not released, this is consistent with unretained outlets
(set myDeallocationCount 0) ;; closure gives this variable class scope.
(+ (int) myDeallocationCount is myDeallocationCount)
(- (void) dealloc is
View
@@ -34,6 +34,10 @@
(assert_equal '(3 4) (v frameOrigin)))
(- (id) testRange is
+ ;; I couldn't find a class that stored ranges inside it
+ ;; (the way that NSView has internal NSRects), so I made one.
+ (class ThingWithRange is NSObject
+ (ivar (NSRange) range))
(set rangeThing ((ThingWithRange alloc) init))
(assert_equal '(0 0) (rangeThing range))
(rangeThing setRange:'(1 2))
@@ -46,10 +50,4 @@
(- (NSSize) frameSize is
(list ((self frame) third) ((self frame) fourth)))
(- (NSPoint) frameOrigin is
- (list ((self frame) first) ((self frame) second))))
-
- ;; I couldn't find a class that stored ranges inside it
- ;; (the way that NSView has internal NSRects), so I made one.
- (class ThingWithRange is NSObject
- (ivar (NSRange) range)
- (ivar-accessors)))
+ (list ((self frame) first) ((self frame) second)))))
Oops, something went wrong.

0 comments on commit aa31bfb

Please sign in to comment.