Skip to content
This repository has been archived by the owner on Dec 5, 2019. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Super work-in-progress on an exception handling system similar to Com…
…mon Lisp conditions and restarts
  • Loading branch information
jspahrsummers committed Jan 9, 2012
1 parent 9d13782 commit bb3c24e
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 1 deletion.
10 changes: 10 additions & 0 deletions extobjc/Modules/EXTCondition.h
@@ -0,0 +1,10 @@
//
// EXTCondition.h
// extobjc
//
// Created by Justin Spahr-Summers on 08.01.12.
// Released into the public domain.
//

#import <Foundation/Foundation.h>

10 changes: 10 additions & 0 deletions extobjc/Modules/EXTCondition.m
@@ -0,0 +1,10 @@
//
// EXTCondition.m
// extobjc
//
// Created by Justin Spahr-Summers on 08.01.12.
// Released into the public domain.
//

#import "EXTCondition.h"

16 changes: 16 additions & 0 deletions extobjc/Tests/EXTConditionTest.h
@@ -0,0 +1,16 @@

//
// EXTConditionTest.h
// extobjc
//
// Created by Justin Spahr-Summers on 08.01.12.
// Released into the public domain.
//

// Logic unit tests contain unit test code that is designed to be linked into an independent test executable.

#import <SenTestingKit/SenTestingKit.h>

@interface EXTConditionTest : SenTestCase

@end
117 changes: 117 additions & 0 deletions extobjc/Tests/EXTConditionTest.m
@@ -0,0 +1,117 @@
//
// EXTConditionTest.m
// extobjc
//
// Created by Justin Spahr-Summers on 08.01.12.
// Released into the public domain.
//

#import "EXTConditionTest.h"
#import "EXTCondition.h"
#import "EXTSafeCategory.h"

NSMutableArray *handlers;
NSMutableDictionary *restarts;
jmp_buf context;

typedef enum {
EXTHandlerStatusInstallingHandlers = 0,
EXTHandlerStatusRunning,
EXTHandlerStatusDone
} EXTHandlerStatus;

typedef enum {
EXTConditionStatusNoException = 0,
EXTConditionStatusExceptionThrown
} EXTConditionStatus;

#define handle \
for (EXTHandlerStatus handlerStatus_ = EXTHandlerStatusInstallingHandlers; handlerStatus_ != EXTHandlerStatusDone; ++handlerStatus_) \
switch (handlerStatus_) \
for (BOOL loop2Done_ = NO; !loop2Done_; loop2Done_ = YES) \
default: \
if (handlerStatus_ == EXTHandlerStatusRunning)
/* @handle block begins with user code */

#define rescue(TYPE, VAR) \
else if (handlerStatus_ == EXTHandlerStatusInstallingHandlers) \
for (id handler_ = nil; !handler_; (handler_ && ([handlers addObject:handler_], YES))) \
handler_ = ^(TYPE *VAR)

#define restart(...) \
if (!setjmp(context) && ((restarts = [NSDictionary dictionaryWithKeysAndCopiedObjects:__VA_ARGS__, nil]) || YES))

#define invoke(RESTART, ...) \
NSLog(@"%@", RESTART) \

@interface NSDictionary (ConditionExtensions)
+ (id)dictionaryWithKeysAndCopiedObjects:(id)firstKey, ... NS_REQUIRES_NIL_TERMINATION;
@end

@interface TestCondition : NSObject
+ (void)raise;
@end

@implementation TestCondition
+ (void)raise; {
NSLog(@"jumping");
longjmp(context, 1);
}

@end

@implementation EXTConditionTest

- (void)testRestart {
handlers = [[NSMutableArray alloc] init];

handle {
__block NSString *str = @"foobar";

restart(
@"invalid-string", ^(NSString *newString){ str = newString; }
) {
if ([str isEqualToString:@"foobar"])
[TestCondition raise];
}

NSLog(@"restarts: %@", restarts);

STAssertEqualObjects(str, @"fizzbuzz", @"");
} rescue (TestCondition, condition) {
invoke(@"invalid-string", @"fizzbuzz");
};

void (^testHandler)(TestCondition *) = [handlers objectAtIndex:0];
testHandler(nil);
}

@end

@safecategory (NSDictionary, ConditionExtensions)
+ (id)dictionaryWithKeysAndCopiedObjects:(id)firstKey, ... {
if (!firstKey)
return [NSDictionary dictionary];

va_list args;
va_start(args, firstKey);

id firstObject = va_arg(args, id);

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:[firstObject copy] forKey:firstKey];

for (;;) {
id nextKey = va_arg(args, id);
if (!nextKey)
break;

id nextObject = va_arg(args, id);
[dictionary setObject:[nextObject copy] forKey:nextKey];
}

va_end(args);

return [dictionary copy];
}
@end
22 changes: 21 additions & 1 deletion extobjc/extobjc.xcodeproj/project.pbxproj
Expand Up @@ -56,6 +56,12 @@
D0A8B313128A4BDE004AACE0 /* extobjc.h in Headers */ = {isa = PBXBuildFile; fileRef = D0A8B311128A4BDE004AACE0 /* extobjc.h */; };
D0A8B338128A5185004AACE0 /* EXTConcreteProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D0A8B336128A5185004AACE0 /* EXTConcreteProtocol.h */; };
D0A8B33A128A5185004AACE0 /* EXTConcreteProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D0A8B336128A5185004AACE0 /* EXTConcreteProtocol.h */; };
D0A93EAE14BACFE400CAAF36 /* EXTCondition.h in Headers */ = {isa = PBXBuildFile; fileRef = D0A93EAC14BACFE400CAAF36 /* EXTCondition.h */; };
D0A93EAF14BACFE400CAAF36 /* EXTCondition.h in Headers */ = {isa = PBXBuildFile; fileRef = D0A93EAC14BACFE400CAAF36 /* EXTCondition.h */; };
D0A93EB014BACFE400CAAF36 /* EXTCondition.m in Sources */ = {isa = PBXBuildFile; fileRef = D0A93EAD14BACFE400CAAF36 /* EXTCondition.m */; };
D0A93EB114BACFE400CAAF36 /* EXTCondition.m in Sources */ = {isa = PBXBuildFile; fileRef = D0A93EAD14BACFE400CAAF36 /* EXTCondition.m */; };
D0A93EB414BAD01600CAAF36 /* EXTConditionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0A93EB314BAD01600CAAF36 /* EXTConditionTest.m */; };
D0A93EB514BAD01600CAAF36 /* EXTConditionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = D0A93EB314BAD01600CAAF36 /* EXTConditionTest.m */; };
D0ACF896132B417100900962 /* EXTDispatchObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D0ACF894132B417100900962 /* EXTDispatchObject.h */; };
D0ACF897132B417100900962 /* EXTDispatchObject.h in Headers */ = {isa = PBXBuildFile; fileRef = D0ACF894132B417100900962 /* EXTDispatchObject.h */; };
D0ACF898132B417100900962 /* EXTDispatchObject.m in Sources */ = {isa = PBXBuildFile; fileRef = D0ACF895132B417100900962 /* EXTDispatchObject.m */; };
Expand Down Expand Up @@ -197,6 +203,10 @@
D0A8B30D128A4B56004AACE0 /* EXTSwizzleTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTSwizzleTest.m; sourceTree = "<group>"; };
D0A8B311128A4BDE004AACE0 /* extobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extobjc.h; sourceTree = "<group>"; };
D0A8B336128A5185004AACE0 /* EXTConcreteProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTConcreteProtocol.h; sourceTree = "<group>"; };
D0A93EAC14BACFE400CAAF36 /* EXTCondition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTCondition.h; sourceTree = "<group>"; };
D0A93EAD14BACFE400CAAF36 /* EXTCondition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTCondition.m; sourceTree = "<group>"; };
D0A93EB214BAD01600CAAF36 /* EXTConditionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTConditionTest.h; sourceTree = "<group>"; };
D0A93EB314BAD01600CAAF36 /* EXTConditionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTConditionTest.m; sourceTree = "<group>"; };
D0ACF894132B417100900962 /* EXTDispatchObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTDispatchObject.h; sourceTree = "<group>"; };
D0ACF895132B417100900962 /* EXTDispatchObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTDispatchObject.m; sourceTree = "<group>"; };
D0ACF8AE132B506300900962 /* EXTBlockMethod.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EXTBlockMethod.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -426,6 +436,8 @@
D07F83B1135D50E9008B9D6D /* EXTBlockTargetTest.m */,
D0C1D916128A57B600E96C0F /* EXTConcreteProtocolTest.h */,
D0C1D917128A57B600E96C0F /* EXTConcreteProtocolTest.m */,
D0A93EB214BAD01600CAAF36 /* EXTConditionTest.h */,
D0A93EB314BAD01600CAAF36 /* EXTConditionTest.m */,
D03EC9A1138A25F100559080 /* EXTCoroutineTest.h */,
D03EC9A2138A25F100559080 /* EXTCoroutineTest.m */,
D0337665131E54960039ACFD /* EXTFinalMethodTest.h */,
Expand All @@ -444,8 +456,8 @@
D0B9B0B413727EF800EC1224 /* EXTScopeTest.m */,
D0A8B30C128A4B56004AACE0 /* EXTSwizzleTest.h */,
D0A8B30D128A4B56004AACE0 /* EXTSwizzleTest.m */,
D0A8B2DD128A495D004AACE0 /* OSX-Info.plist */,
D0CFB610128A8EEE006DC377 /* iOS-Info.plist */,
D0A8B2DD128A495D004AACE0 /* OSX-Info.plist */,
);
path = Tests;
sourceTree = "<group>";
Expand All @@ -459,6 +471,8 @@
D0ACF8AE132B506300900962 /* EXTBlockMethod.m */,
D0A8B336128A5185004AACE0 /* EXTConcreteProtocol.h */,
D0B6C99C128B121B00137E97 /* EXTConcreteProtocol.m */,
D0A93EAC14BACFE400CAAF36 /* EXTCondition.h */,
D0A93EAD14BACFE400CAAF36 /* EXTCondition.m */,
D0D0CE2B1389F57D003ECD3D /* EXTCoroutine.h */,
D0337660131E547C0039ACFD /* EXTFinalMethod.h */,
D033765F131E547C0039ACFD /* EXTFinalMethod.m */,
Expand Down Expand Up @@ -524,6 +538,7 @@
D0B9B0B213727A6600EC1224 /* EXTScope.h in Headers */,
D0D0CE2F1389F57D003ECD3D /* EXTCoroutine.h in Headers */,
D0E4D57C147F477C002C3C9F /* EXTAspect.h in Headers */,
D0A93EAF14BACFE400CAAF36 /* EXTCondition.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -551,6 +566,7 @@
D0B9B0B113727A6600EC1224 /* EXTScope.h in Headers */,
D0D0CE2E1389F57D003ECD3D /* EXTCoroutine.h in Headers */,
D0E4D57B147F477C002C3C9F /* EXTAspect.h in Headers */,
D0A93EAE14BACFE400CAAF36 /* EXTCondition.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -745,6 +761,7 @@
D002DAF41365694C005348A5 /* EXTNil.m in Sources */,
D0B9B0B013727A6600EC1224 /* EXTScope.m in Sources */,
D0E4D57E147F477C002C3C9F /* EXTAspect.m in Sources */,
D0A93EB114BACFE400CAAF36 /* EXTCondition.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -765,6 +782,7 @@
D0B9B0B513727EF800EC1224 /* EXTScopeTest.m in Sources */,
D03EC9A3138A25F100559080 /* EXTCoroutineTest.m in Sources */,
D035A5BB148022B9006C1001 /* EXTAspectTest.m in Sources */,
D0A93EB414BAD01600CAAF36 /* EXTConditionTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -785,6 +803,7 @@
D0B9B0B613727EF800EC1224 /* EXTScopeTest.m in Sources */,
D03EC9A4138A25F100559080 /* EXTCoroutineTest.m in Sources */,
D035A5BC148022B9006C1001 /* EXTAspectTest.m in Sources */,
D0A93EB514BAD01600CAAF36 /* EXTConditionTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -807,6 +826,7 @@
D002DAF31365694C005348A5 /* EXTNil.m in Sources */,
D0B9B0AF13727A6600EC1224 /* EXTScope.m in Sources */,
D0E4D57D147F477C002C3C9F /* EXTAspect.m in Sources */,
D0A93EB014BACFE400CAAF36 /* EXTCondition.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down

0 comments on commit bb3c24e

Please sign in to comment.