-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[ios, macos] Add lookup and feature operators. #11528
Conversation
3167c94
to
9b08744
Compare
By the way, I’ve been using this header as a guide to which built-in syntaxes (like subscripting) correspond to which built-in expression functions ( |
@@ -639,6 +663,9 @@ - (id)mgl_jsonExpressionObject { | |||
} else if ([function isEqualToString:@"stringByAppendingString:"]) { | |||
NSArray *arguments = self.arguments.mgl_jsonExpressionObject; | |||
return [@[@"concat", self.operand.mgl_jsonExpressionObject] arrayByAddingObjectsFromArray:arguments]; | |||
} else if ([function isEqualToString:@"objectAtIndex:"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[NSExpression expressionWithFormat:@"{1, 2, 3}[index]"]
has a function
of objectFrom:withIndex:
and an arguments
consisting of the expression index
.
@@ -456,6 +465,12 @@ + (instancetype)mgl_expressionWithJSONObject:(id)object { | |||
return [NSExpression expressionForVariable:@"zoomLevel"]; | |||
} else if ([op isEqualToString:@"heatmap-density"]) { | |||
return [NSExpression expressionForVariable:@"heatmapDensity"]; | |||
} else if ([op isEqualToString:@"geometry-type"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conventional custom functions should be prefixed with mgl_
to avoid conflicting with functions that Apple may add to NSExpression in the future.
@@ -544,6 +559,15 @@ - (id)mgl_jsonExpressionObject { | |||
if ([self.variable isEqualToString:@"zoomLevel"]) { | |||
return @[@"zoom"]; | |||
} | |||
if ([self.variable isEqualToString:@"geometryType"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This SDK is using the $variable
syntax both for these special built-in values that vary based on the execution context and also for user-defined variables. The assumption with zoomLevel
and the like is that developers will be less likely to need a variable by that exact name.
if ([self.variable isEqualToString:@"geometryType"]) { | ||
return @[@"geometry-type"]; | ||
} | ||
if ([self.variable isEqualToString:@"featureId"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency with Cocoa and this SDK, either spell this function featureID
or, better yet, featureIdentifier
.
XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression); | ||
} | ||
{ | ||
NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION('x', 'has')"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The has
operator has two forms. You can think of the ["has", "something"]
form as shorthand for ["has", "something", ["properties"]]
. This PR only implements one of the two forms.
["has", "something"]
should translate to FUNCTION(self, 'mgl_has:', 'something')
, and ["has", "something", object]
should translate to FUNCTION(object, 'mgl_has:', 'something')
.
441a524
to
ae3df5c
Compare
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects); | ||
NSExpression *operand = argumentObjects.count > 1 ? subexpressions[1] : [NSExpression expressionWithFormat:@"self"]; | ||
NSExpression *property = subexpressions.firstObject; | ||
return [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_has:', %@)", operand, property]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way, a preexisting way to write this in an expression would be FUNCTION(%@, 'valueForKey:', %@) != nil
. That seems a bit more natural, although I guess mgl_has:
will be slightly more ergonomic once we implement an aftermarket function for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this case mgl_has:
seems like the most ergonomic option as its closer to our spec.
if ([self.variable isEqualToString:@"mgl_geometryType"]) { | ||
return @[@"geometry-type"]; | ||
} | ||
if ([self.variable isEqualToString:@"featureIdentifier"]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mgl_geometryType
is prefixed with the class prefix, but featureIdentifier
and featureProperties
are not.
@@ -651,6 +690,12 @@ - (id)mgl_jsonExpressionObject { | |||
return @[@"to-string", self.operand.mgl_jsonExpressionObject]; | |||
} else if ([function isEqualToString:@"noindex:"]) { | |||
return self.arguments.firstObject.mgl_jsonExpressionObject; | |||
} else if ([function isEqualToString:@"mgl_has:"]) { | |||
NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"has", self.arguments[0].mgl_jsonExpressionObject, nil]; | |||
if (self.operand.expressionType == NSConstantValueExpressionType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FUNCTION($featureProperties, 'mgl_has:', 'property')
should be translated as ["has", ["properties"], "property"]
, so we need to check here that the operand isn’t an NSEvaluatedObjectExpressionType
(i.e., SELF
).
Fixes #11006
Add operators