Skip to content

Commit

Permalink
Fold compound expressions with literal arguments into literals
Browse files Browse the repository at this point in the history
  • Loading branch information
Anand Thakker committed Sep 15, 2017
1 parent 50243f7 commit 0567a8f
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 6 deletions.
19 changes: 15 additions & 4 deletions src/style-spec/function/definitions/literal.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { Color, isValue, typeOf } = require('../values');

import type { Type } from '../types';
import type { Value } from '../values';
import type { Expression, ParsingContext } from '../expression';
import type { Expression, ParsingContext, CompilationContext } from '../expression';

const u2028 = /\u2028/g;
const u2029 = /\u2029/g;
Expand Down Expand Up @@ -45,9 +45,20 @@ class Literal implements Expression {
return new Literal(context.key, type, value);
}

compile() {
const value = Literal.compile(this.value);
return typeof this.value === 'object' ? `(${value})` : value;
compile(ctx: CompilationContext) {
let value;
if (this.type.kind === 'Color') {
value = `(new $this.Color(${(this.value: any).join(', ')}))`;
} else {
value = Literal.compile(this.value);
}

if (typeof this.value === 'object' && this.value !== null) {
const v = ctx.addVariable(value);
return v;
} else {
return value;
}
}

static compile(value: Value) {
Expand Down
5 changes: 3 additions & 2 deletions src/style-spec/function/evaluation_context.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const {
toString,
checkSubtype} = require('./types');
const {Color, typeOf} = require('./values');
const Curve = require('./definitions/curve');

import type { ArrayType } from './types';
import type { Value } from './values';
Expand Down Expand Up @@ -59,8 +58,9 @@ function ensure(condition: any, message: string) {
}


module.exports = () => ({
const createContext = (Curve) => ({
types: types,
Color: Color,

ensure: ensure,
error: (msg: string) => ensure(false, msg),
Expand Down Expand Up @@ -280,3 +280,4 @@ function findStopLessThanOrEqualTo(stops, input) {
return Math.max(currentIndex - 1, 0);
}

module.exports = () => createContext(require('./definitions/curve'));
36 changes: 36 additions & 0 deletions src/style-spec/function/parse_expression.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// @flow

const Literal = require('./definitions/literal');
const {CompilationContext} = require('./expression');
const evaluationContext = require('./evaluation_context');
import type {ParsingContext, Expression} from './expression';

/**
Expand Down Expand Up @@ -55,6 +58,22 @@ function parseExpression(expr: mixed, context: ParsingContext): ?Expression {
}
}

// If an expression's arguments are all literals, we can evaluate
// it immediately and replace it with a literal value in the
// parsed/compiled result.
if (isConstant(parsed)) {
const cc = new CompilationContext();
const ec = evaluationContext();
const compiled = cc.compileToFunction(parsed, ec);
try {
const value = compiled({}, {});
parsed = new Literal(parsed.key, parsed.type, value);
} catch (e) {
context.error(e.message);
return null;
}
}

return parsed;
}

Expand All @@ -68,4 +87,21 @@ function parseExpression(expr: mixed, context: ParsingContext): ?Expression {
}
}

const nonConstantExpressions = [ 'error', 'get', 'has', 'properties', 'id', 'geometry-type', 'zoom' ];
function isConstant(expression: Expression) {
const {CompoundExpression} = require('./compound_expression');
const Var = require('./definitions/var');
if (expression instanceof CompoundExpression && nonConstantExpressions.indexOf(expression.name) >= 0) {
return false;
} else if (expression instanceof Var) {
return false;
}

let constant = true;
expression.eachChild(arg => {
constant = constant && (arg instanceof Literal);
});
return constant;
}

module.exports = parseExpression;
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"expectExpressionType": {"kind": "Color"},
"expression": [
"curve",
["step"],
["get", "x"],
"black",
0,
"invalid",
10,
"blue"
],
"inputs": [
[{}, {"properties": {"x": -1}}],
[{}, {"properties": {"x": 0}}],
[{}, {"properties": {"x": 5}}],
[{}, {"properties": {"x": 10}}],
[{}, {"properties": {"x": 11}}]
],
"expected": {
"compiled": {
"result": "error",
"errors": [
{"key": "[5]", "error": "Could not parse color from value 'invalid'"}
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"expectExpressionType": null,
"expression": ["to-color", "red"],
"inputs": [[{}, {}]],
"expected": {
"compiled": {
"result": "success",
"isFeatureConstant": true,
"isZoomConstant": true,
"type": "Color"
},
"outputs": [
[1, 0, 0, 1]
]
}
}

0 comments on commit 0567a8f

Please sign in to comment.