summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra <fabian.guerra@mapbox.com>2018-03-27 23:02:21 -0400
committerFabian Guerra <fabian.guerra@mapbox.com>2018-03-28 19:40:09 -0400
commit74b425f4c2d1acec0abf2d2eeea0b6652ebf87e4 (patch)
tree73f537b92e56b4dfb84b3d867a36e8b39e22dc3f
parentc06655e404f9d5190279b56c2df8b8c0272192be (diff)
downloadqtlocation-mapboxgl-74b425f4c2d1acec0abf2d2eeea0b6652ebf87e4.tar.gz
[ios, macos] Add conventional custom function support.
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm85
-rw-r--r--platform/darwin/src/NSPredicate+MGLAdditions.h4
-rw-r--r--platform/darwin/src/NSPredicate+MGLAdditions.mm31
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm13
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"]],