diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2018-03-26 10:19:41 -0700 |
---|---|---|
committer | Fabian Guerra <fabian.guerra@mapbox.com> | 2018-03-28 19:37:12 -0400 |
commit | 1dcc93d9213a7aee2f049ec3cb52b04d7a244373 (patch) | |
tree | 73d8f9663a59b944ccf0870a6a0c4fa3bc8d58d1 | |
parent | 66648e5ac25f86a0c643d2837163b143bc63b2e0 (diff) | |
download | qtlocation-mapboxgl-1dcc93d9213a7aee2f049ec3cb52b04d7a244373.tar.gz |
[ios, macos] Aftermarket let expressions
-rw-r--r-- | platform/darwin/docs/guides/Predicates and Expressions.md | 17 | ||||
-rw-r--r-- | platform/darwin/src/NSExpression+MGLAdditions.mm | 29 | ||||
-rw-r--r-- | platform/darwin/test/MGLExpressionTests.mm | 13 |
3 files changed, 31 insertions, 28 deletions
diff --git a/platform/darwin/docs/guides/Predicates and Expressions.md b/platform/darwin/docs/guides/Predicates and Expressions.md index 97834b4f71..5e6af06dc4 100644 --- a/platform/darwin/docs/guides/Predicates and Expressions.md +++ b/platform/darwin/docs/guides/Predicates and Expressions.md @@ -193,6 +193,7 @@ string syntax: Initializer parameter | Format string syntax | Arguments | Returns ----------------------|----------------------|-----------|-------- `mgl_join:` | `mgl_join({'Old', 'MacDonald'})` | An aggregate expression or `NSArray` constant value expression containing one or more `NSExpression`s, each evaluating to a string. | An `NSString` object (the result of concatenating together all the elements of an array in order). +`MGL_LET` | `MGL_LET('age', uppercase('old'), 'name', uppercase('MacDonald'), mgl_join({$age, $name}))` | Any number of variable names interspersed with their assigned `NSExpression` values, followed by an `NSExpression` that may contain references to those variables. The following custom functions are also available with the `+[NSExpression expressionForFunction:selectorName:arguments:]` method or the @@ -215,22 +216,6 @@ The following custom functions are also available with the </td> </tr> <tr> - <td><code>mgl_expressionWithContext:</code></td> - <td> - An `NSExpression` that may contain references to the variables defined in - the context dictionary. - </td> - <td> - An `NSDictionary` with `NSString`s as keys and `NSExpression`s as values. - Each key is a variable name and each value is the variable’s value within - the target expression. - </td> - <td> - The target expression with variable subexpressions replaced with the - values defined in the context dictionary. - </td> -</tr> -<tr> <td><code>mgl_interpolateWithCurveType:parameters:stops:</code></td> <td> An `NSExpression` that evaluates to a number and contains a variable or diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm index 43661a5502..16c1656fb8 100644 --- a/platform/darwin/src/NSExpression+MGLAdditions.mm +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -24,6 +24,16 @@ NSString *MGLJoinComponents(Class self, SEL _cmd, NSArray<NSString *> *component } /** + A placeholder for a method that evaluates an expression based on an arbitrary + number of variable names and assigned expressions. + */ +id MGLEvaluateWithContext(Class self, SEL _cmd, NSString *firstVariableName, ...) { + [NSException raise:NSInvalidArgumentException + format:@"Assignment expressions lack underlying Objective-C implementations."]; + return nil; +}; + +/** Adds to NSExpression’s built-in repertoire of functions. */ void MGLInstallAftermarketExpressionFunctions() { @@ -38,6 +48,10 @@ void MGLInstallAftermarketExpressionFunctions() { #pragma clang push #pragma clang diagnostic ignored "-Wundeclared-selector" class_addMethod(NSPredicateUtilities, @selector(mgl_join:), (IMP)MGLJoinComponents, "@@:@"); + + // Vararg aftermarket expressions need to be declared with an explicit and implicit first argument. + class_addMethod(NSPredicateUtilities, @selector(MGL_LET), (IMP)MGLEvaluateWithContext, "@@:@"); + class_addMethod(NSPredicateUtilities, @selector(MGL_LET:), (IMP)MGLEvaluateWithContext, "@@:@"); #pragma clang pop } @@ -369,6 +383,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { @"^": @"raise:toPower:", @"upcase": @"uppercase:", @"downcase": @"lowercase:", + @"let": @"MGL_LET", }; }); @@ -530,17 +545,6 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { return [NSExpression expressionForVariable:@"mgl_featureIdentifier"]; } else if ([op isEqualToString:@"properties"]) { return [NSExpression expressionForVariable:@"mgl_featureProperties"]; - } else if ([op isEqualToString:@"let"]) { - NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.lastObject]; - NSArray *bindingObjects = [argumentObjects subarrayWithRange:NSMakeRange(0, argumentObjects.count - 1)]; - NSMutableDictionary *context = [NSMutableDictionary dictionaryWithCapacity:bindingObjects.count / 2]; - NSEnumerator *bindingEnumerator = bindingObjects.objectEnumerator; - while (NSString *key = bindingEnumerator.nextObject) { - context[key] = [NSExpression mgl_expressionWithJSONObject:bindingEnumerator.nextObject]; - } - return [NSExpression expressionForFunction:operand - selectorName:@"mgl_expressionWithContext:" - arguments:@[[NSExpression expressionForConstantValue:context]]]; } else if ([op isEqualToString:@"var"]) { return [NSExpression expressionForVariable:argumentObjects.firstObject]; } else if ([op isEqualToString:@"case"]) { @@ -608,6 +612,9 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) { @"uppercase:": @"upcase", @"lowercase:": @"downcase", @"length:": @"length", + // Vararg aftermarket expressions need to be declared with an explicit and implicit first argument. + @"MGL_LET": @"let", + @"MGL_LET:": @"let", }; }); diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm index 5451174e24..94c9410892 100644 --- a/platform/darwin/test/MGLExpressionTests.mm +++ b/platform/darwin/test/MGLExpressionTests.mm @@ -199,9 +199,11 @@ using namespace std::string_literals; } { NSDictionary *context = @{@"loremIpsum": MGLConstantExpression(@"Lorem ipsum dolor sit amet")}; - NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(uppercase($loremIpsum), 'mgl_expressionWithContext:', %@)", context]; + NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_LET('loremIpsum', 'Lorem ipsum dolor sit amet', uppercase($loremIpsum))", context]; + NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(uppercase($loremIpsum), 'mgl_expressionWithContext:', %@)", context]; NSArray *jsonExpression = @[@"let", @"loremIpsum", @"Lorem ipsum dolor sit amet", @[@"upcase", @[@"var", @"loremIpsum"]]]; XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); + XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression); XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); } } @@ -353,6 +355,15 @@ using namespace std::string_literals; XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); } { + NSArray *arguments = @[MGLConstantExpression(@1), MGLConstantExpression(@1), MGLConstantExpression(@1)]; + NSExpression *expression = [NSExpression expressionForFunction:@"add:to:" arguments:arguments]; + NSArray *jsonExpression = @[@"+", @1, @1, @1]; + XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); + jsonExpression = @[@"+", @[@"+", @1, @1], @1]; + XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 + 1 + 1"].mgl_jsonExpressionObject, jsonExpression); + XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], [NSExpression expressionWithFormat:@"1 + 1 + 1"]); + } + { NSExpression *expression = [NSExpression expressionForFunction:@"from:subtract:" arguments:arguments]; NSArray *jsonExpression = @[@"-", @1, @1]; XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression); |