diff options
author | Fabian Guerra <fabian.guerra@mapbox.com> | 2018-03-27 23:02:21 -0400 |
---|---|---|
committer | Fabian Guerra <fabian.guerra@mapbox.com> | 2018-03-28 19:40:09 -0400 |
commit | 74b425f4c2d1acec0abf2d2eeea0b6652ebf87e4 (patch) | |
tree | 73f537b92e56b4dfb84b3d867a36e8b39e22dc3f | |
parent | c06655e404f9d5190279b56c2df8b8c0272192be (diff) | |
download | qtlocation-mapboxgl-74b425f4c2d1acec0abf2d2eeea0b6652ebf87e4.tar.gz |
[ios, macos] Add conventional custom function support.
-rw-r--r-- | platform/darwin/src/NSExpression+MGLAdditions.mm | 85 | ||||
-rw-r--r-- | platform/darwin/src/NSPredicate+MGLAdditions.h | 4 | ||||
-rw-r--r-- | platform/darwin/src/NSPredicate+MGLAdditions.mm | 31 | ||||
-rw-r--r-- | platform/darwin/test/MGLExpressionTests.mm | 13 |
4 files changed, 106 insertions, 27 deletions
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 2ff0d100f6..2af636516e 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -67,7 +67,7 @@ // with an explicit and implicit first argument. INSTALL_CONTROL_STRUCTURE(MGL_LET); INSTALL_CONTROL_STRUCTURE(MGL_MATCH); - INSTALL_CONTROL_STRUCTURE(MGL_SWITCH); + INSTALL_CONTROL_STRUCTURE(MGL_IF); INSTALL_CONTROL_STRUCTURE(MGL_FUNCTION); #undef INSTALL_AFTERMARKET_FN @@ -100,6 +100,9 @@ return nil; } +/** + A placeholder for a method that evaluates a coalesce expression. + */ - (id)mgl_coalesce:(NSArray<NSExpression *> *)elements { [NSException raise:NSInvalidArgumentException format:@"Coalesce expressions lack underlying Objective-C implementations."]; @@ -128,7 +131,7 @@ /** A placeholder for a method that evaluates an expression and returns the matching element. */ -- (id)MGL_SWITCH:(id)firstCondition, ... { +- (id)MGL_IF:(id)firstCondition, ... { va_list argumentList; va_start(argumentList, firstCondition); @@ -647,7 +650,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { } } - return [NSExpression expressionForFunction:@"MGL_SWITCH" arguments:arguments]; + return [NSExpression expressionForFunction:@"MGL_IF" arguments:arguments]; } else if ([op isEqualToString:@"match"]) { NSMutableArray *optionsArray = [NSMutableArray array]; NSEnumerator *optionsEnumerator = argumentObjects.objectEnumerator; @@ -852,28 +855,12 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { }]; [expressionObject addObject:self.operand.mgl_jsonExpressionObject]; return expressionObject; - } else if ([function isEqualToString:@"MGL_SWITCH"]) { - NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"case", nil]; - - for (NSExpression *option in self.arguments) { - if ([option respondsToSelector:@selector(constantValue)] && [option.constantValue isKindOfClass:[NSComparisonPredicate class]]) { - NSPredicate *predicate = (NSPredicate *)option.constantValue; - [expressionObject addObject:predicate.mgl_jsonExpressionObject]; - } else { - [expressionObject addObject:option.mgl_jsonExpressionObject]; - } - } - - return expressionObject; - } else if ([function isEqualToString:@"MGL_MATCH"]) { - NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"match", nil]; - - - for (NSExpression *option in self.arguments) { - [expressionObject addObject:option.mgl_jsonExpressionObject]; - } - - return expressionObject; + } else if ([function isEqualToString:@"MGL_IF"] || + [function isEqualToString:@"mgl_if:"]) { + return self.mgl_jsonIfExpressionObject; + } else if ([function isEqualToString:@"MGL_MATCH"] || + [function isEqualToString:@"mgl_match:"]) { + return self.mgl_jsonMatchExpressionObject; } else if ([function isEqualToString:@"mgl_coalesce:"]) { NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"coalesce", nil]; @@ -1018,4 +1005,52 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { return expressionObject; } +- (id)mgl_jsonMatchExpressionObject { + BOOL isAftermarketFunction = [self.function isEqualToString:@"MGL_MATCH"]; + NSUInteger minimumIndex = isAftermarketFunction ? 1 : 0; + + NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"match", (isAftermarketFunction ? self.arguments.firstObject : self.operand).mgl_jsonExpressionObject, nil]; + NSArray<NSExpression *> *arguments = isAftermarketFunction ? self.arguments : self.arguments[minimumIndex].constantValue; + + for (NSUInteger index = minimumIndex; index < arguments.count; index++) { + [expressionObject addObject:arguments[index].mgl_jsonExpressionObject]; + } + + return expressionObject; +} + +- (id)mgl_jsonIfExpressionObject { + BOOL isAftermarketFunction = [self.function isEqualToString:@"MGL_IF"]; + NSUInteger minimumIndex = isAftermarketFunction ? 1 : 0; + NSExpression *firstCondition; + id condition; + + if (isAftermarketFunction) { + firstCondition = self.arguments.firstObject; + } else { + firstCondition = self.operand; + } + + if ([firstCondition respondsToSelector:@selector(constantValue)] && [firstCondition.constantValue isKindOfClass:[NSComparisonPredicate class]]) { + NSPredicate *predicate = (NSPredicate *)firstCondition.constantValue; + condition = predicate.mgl_jsonExpressionObject; + } else { + condition = firstCondition.mgl_jsonExpressionObject; + } + + NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"case", condition, nil]; + NSArray<NSExpression *> *arguments = isAftermarketFunction ? self.arguments : self.arguments[minimumIndex].constantValue; + + for (NSUInteger index = minimumIndex; index < arguments.count; index++) { + if ([arguments[index] respondsToSelector:@selector(constantValue)] && [arguments[index].constantValue isKindOfClass:[NSComparisonPredicate class]]) { + NSPredicate *predicate = (NSPredicate *)arguments[index].constantValue; + [expressionObject addObject:predicate.mgl_jsonExpressionObject]; + } else { + [expressionObject addObject:arguments[index].mgl_jsonExpressionObject]; + } + } + + return expressionObject; +} + @end diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.h b/platform/darwin/src/NSPredicate+MGLAdditions.h index 89e9e65c64..a73b1a61ba 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.h +++ b/platform/darwin/src/NSPredicate+MGLAdditions.h @@ -16,4 +16,8 @@ @property (nonatomic, readonly) id mgl_jsonExpressionObject; +- (id)mgl_if:(id)firstValue, ...; + +- (id)mgl_match:(NSExpression *)firstCase, ...; + @end diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm index 63c8307803..8fe5735bf9 100644 --- a/platform/darwin/src/NSPredicate+MGLAdditions.mm +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -324,4 +324,35 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) { return nil; } +- (id)mgl_if:(id)firstValue, ... { + + if ([self evaluateWithObject:nil]) { + return firstValue; + } + + id eachExpression; + va_list argumentList; + va_start(argumentList, firstValue); + + while ((eachExpression = va_arg(argumentList, id))) { + if ([eachExpression isKindOfClass:[NSComparisonPredicate class]]) { + id valueExpression = va_arg(argumentList, id); + if ([eachExpression evaluateWithObject:nil]) { + return valueExpression; + } + } else { + return eachExpression; + } + } + va_end(argumentList); + + return nil; +} + +- (id)mgl_match:(NSExpression *)firstCase, ... { + [NSException raise:NSInvalidArgumentException + format:@"Match expressions lack underlying Objective-C implementations."]; + return nil; +} + @end diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm index f00ea690f5..17c48af226 100644 --- a/platform/darwin/test/MGLExpressionTests.mm +++ b/platform/darwin/test/MGLExpressionTests.mm @@ -632,8 +632,15 @@ using namespace std::string_literals; MGLConstantExpression(@"one"), MGLConstantExpression(@0), MGLConstantExpression(@"zero")]; + NSExpression *predicate = [NSExpression expressionWithFormat:@"2 - 1"]; + NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_match:', %@)", predicate, @[MGLConstantExpression(@1), + MGLConstantExpression(@"one"), + MGLConstantExpression(@0), + MGLConstantExpression(@"zero"), + MGLConstantExpression(@"default")]]; NSArray *jsonExpression = @[@"match", @[@"-", @2, @1], @1, @"one", @0, @"zero", @"default"]; XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); + XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression); XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); } { @@ -660,17 +667,19 @@ using namespace std::string_literals; - (void)testConditionalExpressionObject { { - NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_SWITCH(%@, %@, %@)", + NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, %@, %@)", [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]], MGLConstantExpression(@YES), MGLConstantExpression(@NO)]; + NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_if:', %@)", [NSPredicate predicateWithFormat:@"1 = 2"], @[MGLConstantExpression(@YES), MGLConstantExpression(@NO)]]; NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO]; XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); + XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression); XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO); } { - NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_SWITCH(%@, %@, %@, %@, %@)", + NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, %@, %@, %@, %@)", [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]], MGLConstantExpression(@YES), [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 1"]], |