Skip to content
This repository has been archived by the owner on May 19, 2018. It is now read-only.

Commit

Permalink
Implement destructuring pattern matching.
Browse files Browse the repository at this point in the history
  • Loading branch information
robrix committed Apr 13, 2014
1 parent 4167cf2 commit 2e07003
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
14 changes: 14 additions & 0 deletions Hammer.xcodeproj/project.pbxproj
Expand Up @@ -12,6 +12,9 @@
D40D7B1C18E27E070065BB70 /* HammerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D40D7B1B18E27E070065BB70 /* HammerTests.m */; };
D40D7B2318E27E1E0065BB70 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4ACA5CB18DD188A00EBD899 /* XCTest.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
D40D7B2418E27F070065BB70 /* Lagrangian.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4ACA5F118DD19FE00EBD899 /* Lagrangian.framework */; };
D42ED3B818FA1480005BEC10 /* HMRCase.h in Headers */ = {isa = PBXBuildFile; fileRef = D42ED3B618FA1480005BEC10 /* HMRCase.h */; };
D42ED3B918FA1480005BEC10 /* HMRCase.m in Sources */ = {isa = PBXBuildFile; fileRef = D42ED3B718FA1480005BEC10 /* HMRCase.m */; };
D42ED40718FA65FE005BEC10 /* Obstruct.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D42ED40618FA65FE005BEC10 /* Obstruct.framework */; };
D499A49218EFEDF1004DF7E3 /* HMRTerminal.h in Headers */ = {isa = PBXBuildFile; fileRef = D499A49018EFEDF1004DF7E3 /* HMRTerminal.h */; };
D499A49318EFEDF1004DF7E3 /* HMRTerminal.m in Sources */ = {isa = PBXBuildFile; fileRef = D499A49118EFEDF1004DF7E3 /* HMRTerminal.m */; };
D499A49618F067D4004DF7E3 /* HMRParsing.h in Headers */ = {isa = PBXBuildFile; fileRef = D499A49418F067D4004DF7E3 /* HMRParsing.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -67,6 +70,9 @@
D40D7B1718E27E070065BB70 /* Hammer Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Hammer Tests-Info.plist"; sourceTree = "<group>"; };
D40D7B1918E27E070065BB70 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D40D7B1B18E27E070065BB70 /* HammerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HammerTests.m; sourceTree = "<group>"; };
D42ED3B618FA1480005BEC10 /* HMRCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMRCase.h; sourceTree = "<group>"; };
D42ED3B718FA1480005BEC10 /* HMRCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HMRCase.m; sourceTree = "<group>"; };
D42ED40618FA65FE005BEC10 /* Obstruct.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Obstruct.framework; path = External/Obstruct/build/Debug/Obstruct.framework; sourceTree = "<group>"; };
D499A49018EFEDF1004DF7E3 /* HMRTerminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMRTerminal.h; sourceTree = "<group>"; };
D499A49118EFEDF1004DF7E3 /* HMRTerminal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HMRTerminal.m; sourceTree = "<group>"; };
D499A49418F067D4004DF7E3 /* HMRParsing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HMRParsing.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -124,6 +130,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D42ED40718FA65FE005BEC10 /* Obstruct.framework in Frameworks */,
D40D7B2318E27E1E0065BB70 /* XCTest.framework in Frameworks */,
D4ACA5F218DD19FE00EBD899 /* Lagrangian.framework in Frameworks */,
D40D7B0E18E27C960065BB70 /* Reducers.framework in Frameworks */,
Expand Down Expand Up @@ -173,6 +180,7 @@
D4ACA5B518DD188A00EBD899 /* Frameworks */ = {
isa = PBXGroup;
children = (
D42ED40618FA65FE005BEC10 /* Obstruct.framework */,
D40D7B0D18E27C960065BB70 /* Reducers.framework */,
D4ACA5F118DD19FE00EBD899 /* Lagrangian.framework */,
D4ACA5B918DD188A00EBD899 /* Foundation.framework */,
Expand Down Expand Up @@ -206,6 +214,8 @@
D4C87CD418EB79E400567D57 /* HMRDelay.m */,
D499A5FC18F4D848004DF7E3 /* HMRPair.h */,
D499A5FD18F4D848004DF7E3 /* HMRPair.m */,
D42ED3B618FA1480005BEC10 /* HMRCase.h */,
D42ED3B718FA1480005BEC10 /* HMRCase.m */,
);
name = "Supporting Files";
sourceTree = "<group>";
Expand Down Expand Up @@ -279,6 +289,7 @@
D4ACA5FE18DD32CB00EBD899 /* HMROnce.h in Headers */,
D4ACA5E118DD19A400EBD899 /* Hammer.h in Headers */,
D4ACA5F518DD22F800EBD899 /* HMRNonterminal.h in Headers */,
D42ED3B818FA1480005BEC10 /* HMRCase.h in Headers */,
D4ACA61718DD3CDB00EBD899 /* HMRReduction.h in Headers */,
D4ACA5F918DD258E00EBD899 /* HMRNull.h in Headers */,
D4ACA62318DD4F5200EBD899 /* HMRRepetition.h in Headers */,
Expand Down Expand Up @@ -409,6 +420,7 @@
D499A5FF18F4D848004DF7E3 /* HMRPair.m in Sources */,
D499A49718F067D4004DF7E3 /* HMRParsing.m in Sources */,
D4ACA62418DD4F5200EBD899 /* HMRRepetition.m in Sources */,
D42ED3B918FA1480005BEC10 /* HMRCase.m in Sources */,
D4C87CEE18ED3D5F00567D57 /* HMRCharacterSetCombinator.m in Sources */,
D4C87CE218ED356E00567D57 /* HMRDelayCombinator.m in Sources */,
D4ACA5FF18DD33DC00EBD899 /* HMRNonterminal.m in Sources */,
Expand Down Expand Up @@ -567,6 +579,7 @@
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Hammer/Hammer-Info.plist";
INSTALL_PATH = "@rpath";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = framework;
};
Expand All @@ -583,6 +596,7 @@
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Hammer/Hammer-Info.plist";
INSTALL_PATH = "@rpath";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = framework;
};
Expand Down
3 changes: 3 additions & 0 deletions Hammer.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions Hammer/HMRCase.h
@@ -0,0 +1,14 @@
// Copyright (c) 2014 Rob Rix. All rights reserved.

#import <Reducers/REDFilter.h>

@interface HMRCase : NSObject

+(id)match:(id)object withCases:(NSArray *)cases;

+(instancetype)case:(REDPredicateBlock)predicate then:(id(^)())block;

-(id)evaluateWithObject:(id)object;

@end

71 changes: 71 additions & 0 deletions Hammer/HMRCase.m
@@ -0,0 +1,71 @@
// Copyright (c) 2014 Rob Rix. All rights reserved.

#import "HMRCase.h"
#import "HMRCombinator.h"
#import <Obstruct/apply.h>

@implementation HMRCase {
REDPredicateBlock _predicate;
id (^_block)();
}

+(id)match:(id)object withCases:(NSArray *)cases {
id result;

for (HMRCase *each in cases) {
result = [each evaluateWithObject:object];

if (result != nil) break;
}

return result;
}

l3_test(@selector(match:withCases:)) {
id object = [NSObject new];
l3_expect([HMRCase match:object withCases:@[ [HMRCase case:REDTruePredicateBlock then:^{ return @YES; }] ]]).to.equal(@YES);
l3_expect([HMRCase match:object withCases:@[ [HMRCase case:HMRBind then:REDIdentityMapBlock] ]]).to.equal(object);
l3_expect([HMRCase match:HMRConcatenate(HMRLiteral(@"x"), HMRLiteral(@"y")) withCases:@[ [HMRCase case:HMRConcatenationPredicate(nil, HMRBind) then:REDIdentityMapBlock] ]]).to.equal(HMRLiteral(@"y"));
}


+(instancetype)case:(REDPredicateBlock)predicate then:(id(^)())block {
return [[self alloc] initWithPredicate:predicate thenBlock:block];
}

-(instancetype)initWithPredicate:(REDPredicateBlock)predicate thenBlock:(id(^)())block {
NSParameterAssert(block != nil);

if ((self = [super init])) {
_predicate = [predicate ?: REDTruePredicateBlock copy];
_block = [block copy];
}
return self;
}


static _Thread_local CFMutableArrayRef variables;

-(id)evaluateWithObject:(id)object {
CFMutableArrayRef previous = variables;
NSMutableArray *bindings = [NSMutableArray new];
variables = (CFMutableArrayRef)CFBridgingRetain(bindings);

id result;

if (_predicate(object)) {
result = obstruct_apply_array(_block, bindings);
}

variables = previous;

return result;
}

@end


REDPredicateBlock const HMRBind = ^bool (id object) {
[(NSMutableArray *)CFBridgingRelease(variables) addObject:object];
return YES;
};

0 comments on commit 2e07003

Please sign in to comment.