Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fold compound expressions with literal arguments into literals #5279

Merged
merged 5 commits into from
Sep 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions flow-typed/visitor.js

This file was deleted.

36 changes: 4 additions & 32 deletions src/style-spec/function/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ const {
CompilationContext
} = require('./expression');
const parseExpression = require('./parse_expression');
const { CompoundExpression } = require('./compound_expression');
const definitions = require('./definitions');
const evaluationContext = require('./evaluation_context');
const {
isFeatureConstant,
isZoomConstant
} = require('./is_constant');

import type { Type } from './types.js';
import type { Expression, ParsingError } from './expression.js';
Expand Down Expand Up @@ -78,34 +81,3 @@ function compileExpression(
};
}

function isFeatureConstant(e: Expression) {
let result = true;
e.accept({
visit: (expression) => {
if (expression instanceof CompoundExpression) {
if (expression.name === 'get') {
result = result && (expression.args.length > 1);
} else if (expression.name === 'has') {
result = result && (expression.args.length > 1);
} else {
result = result && !(
expression.name === 'properties' ||
expression.name === 'geometry-type' ||
expression.name === 'id'
);
}
}
}
});
return result;
}

function isZoomConstant(e: Expression) {
let result = true;
e.accept({
visit: (expression) => {
if (expression.name === 'zoom') result = false;
}
});
return result;
}
5 changes: 2 additions & 3 deletions src/style-spec/function/compound_expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ class CompoundExpression implements Expression {
return [ name ].concat(args);
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.args.forEach(a => a.accept(visitor));
eachChild(fn: (Expression) => void) {
this.args.forEach(fn);
}

static parse(args: Array<mixed>, context: ParsingContext): ?Expression {
Expand Down
5 changes: 2 additions & 3 deletions src/style-spec/function/definitions/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,8 @@ class ArrayAssertion implements Expression {
}
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.input.accept(visitor);
eachChild(fn: (Expression) => void) {
fn(this.input);
}
}

Expand Down
27 changes: 13 additions & 14 deletions src/style-spec/function/definitions/assertion.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ const types = {
class Assertion implements Expression {
key: string;
type: Type;
inputs: Array<Expression>;
args: Array<Expression>;

constructor(key: string, type: Type, inputs: Array<Expression>) {
constructor(key: string, type: Type, args: Array<Expression>) {
this.key = key;
this.type = type;
this.inputs = inputs;
this.args = args;
}

static parse(args: Array<mixed>, context: ParsingContext): ?Expression {
Expand All @@ -40,33 +40,32 @@ class Assertion implements Expression {

const type = types[name];

const inputs = [];
const parsed = [];
for (let i = 1; i < args.length; i++) {
const input = parseExpression(args[i], context.concat(i, ValueType));
if (!input) return null;
inputs.push(input);
parsed.push(input);
}

return new Assertion(context.key, type, inputs);
return new Assertion(context.key, type, parsed);
}

compile(ctx: CompilationContext) {
const jsType = JSON.stringify(this.type.kind.toLowerCase());
const inputs = [];
for (const input of this.inputs) {
inputs.push(ctx.addExpression(input.compile(ctx)));
const args = [];
for (const input of this.args) {
args.push(ctx.addExpression(input.compile(ctx)));
}
const inputsVar = ctx.addVariable(`[${inputs.join(',')}]`);
const inputsVar = ctx.addVariable(`[${args.join(',')}]`);
return `$this.asJSType(${jsType}, ${inputsVar})`;
}

serialize() {
return [ this.type.kind.toLowerCase() ].concat(this.inputs.map(i => i.serialize()));
return [ this.type.kind.toLowerCase() ].concat(this.args.map(i => i.serialize()));
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.inputs.forEach(input => input.accept(visitor));
eachChild(fn: (Expression) => void) {
this.args.forEach(fn);
}
}

Expand Down
7 changes: 3 additions & 4 deletions src/style-spec/function/definitions/at.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ class At implements Expression {
return [ 'at', this.index.serialize(), this.input.serialize() ];
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.index.accept(visitor);
this.input.accept(visitor);
eachChild(fn: (Expression) => void) {
fn(this.index);
fn(this.input);
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/style-spec/function/definitions/case.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,12 @@ class Case implements Expression {
return result;
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
eachChild(fn: (Expression) => void) {
for (const [test, expression] of this.branches) {
test.accept(visitor);
expression.accept(visitor);
fn(test);
fn(expression);
}
this.otherwise.accept(visitor);
fn(this.otherwise);
}
}

Expand Down
7 changes: 2 additions & 5 deletions src/style-spec/function/definitions/coalesce.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,8 @@ class Coalesce implements Expression {
return ['coalesce'].concat(this.args.map(a => a.serialize()));
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
for (const arg of this.args) {
arg.accept(visitor);
}
eachChild(fn: (Expression) => void) {
this.args.forEach(fn);
}
}

Expand Down
27 changes: 13 additions & 14 deletions src/style-spec/function/definitions/coercion.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ const types = {
class Coercion implements Expression {
key: string;
type: Type;
inputs: Array<Expression>;
args: Array<Expression>;

constructor(key: string, type: Type, inputs: Array<Expression>) {
constructor(key: string, type: Type, args: Array<Expression>) {
this.key = key;
this.type = type;
this.inputs = inputs;
this.args = args;
}

static parse(args: Array<mixed>, context: ParsingContext): ?Expression {
Expand All @@ -43,32 +43,31 @@ class Coercion implements Expression {

const type = types[name];

const inputs = [];
const parsed = [];
for (let i = 1; i < args.length; i++) {
const input = parseExpression(args[i], context.concat(i, ValueType));
if (!input) return null;
inputs.push(input);
parsed.push(input);
}

return new Coercion(context.key, type, inputs);
return new Coercion(context.key, type, parsed);
}

compile(ctx: CompilationContext) {
const inputs = [];
for (const input of this.inputs) {
inputs.push(ctx.addExpression(input.compile(ctx)));
const args = [];
for (const input of this.args) {
args.push(ctx.addExpression(input.compile(ctx)));
}
const inputsVar = ctx.addVariable(`[${inputs.join(',')}]`);
const inputsVar = ctx.addVariable(`[${args.join(',')}]`);
return `$this.to${this.type.kind}(${inputsVar})`;
}

serialize() {
return [ `to-${this.type.kind.toLowerCase()}` ].concat(this.inputs.map(i => i.serialize()));
return [ `to-${this.type.kind.toLowerCase()}` ].concat(this.args.map(i => i.serialize()));
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.inputs.forEach(input => input.accept(visitor));
eachChild(fn: (Expression) => void) {
this.args.forEach(fn);
}
}

Expand Down
7 changes: 3 additions & 4 deletions src/style-spec/function/definitions/contains.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ class Contains implements Expression {
return [ 'contains', this.value.serialize(), this.array.serialize() ];
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.array.accept(visitor);
this.value.accept(visitor);
eachChild(fn: (Expression) => void) {
fn(this.array);
fn(this.value);
}
}

Expand Down
11 changes: 5 additions & 6 deletions src/style-spec/function/definitions/curve.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ class Curve implements Expression {
const label = rest[i];
const value = rest[i + 1];

const labelKey = isStep ? i + 4 : i + 3;
const valueKey = isStep ? i + 5 : i + 4;
const labelKey = isStep ? i + 2 : i + 3;
const valueKey = isStep ? i + 3 : i + 4;

if (typeof label !== 'number') {
return context.error('Input/output pairs for "curve" expressions must be defined using literal numeric values (not computed expressions) for the input values.', labelKey);
Expand Down Expand Up @@ -176,11 +176,10 @@ class Curve implements Expression {
return result;
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.input.accept(visitor);
eachChild(fn: (Expression) => void) {
fn(this.input);
for (const [ , expression] of this.stops) {
expression.accept(visitor);
fn(expression);
}
}
}
Expand Down
7 changes: 3 additions & 4 deletions src/style-spec/function/definitions/let.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ class Let implements Expression {
return serialized;
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
eachChild(fn: (Expression) => void) {
for (const binding of this.bindings) {
binding[1].accept(visitor);
fn(binding[1]);
}
this.result.accept(visitor);
fn(this.result);
}

static parse(args: Array<mixed>, context: ParsingContext) {
Expand Down
20 changes: 15 additions & 5 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,19 @@ 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) {
return ctx.addVariable(value);
} else {
return value;
}
}

static compile(value: Value) {
Expand All @@ -72,7 +82,7 @@ class Literal implements Expression {
}
}

accept(visitor: Visitor<Expression>) { visitor.visit(this); }
eachChild() {}
}

module.exports = Literal;
11 changes: 4 additions & 7 deletions src/style-spec/function/definitions/match.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,10 @@ class Match implements Expression {
return result;
}

accept(visitor: Visitor<Expression>) {
visitor.visit(this);
this.input.accept(visitor);
for (const output of this.outputs) {
output.accept(visitor);
}
this.otherwise.accept(visitor);
eachChild(fn: (Expression) => void) {
fn(this.input);
this.outputs.forEach(fn);
fn(this.otherwise);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/style-spec/function/definitions/var.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Var implements Expression {
return [this.name];
}

accept(visitor: Visitor<Expression>) { visitor.visit(this); }
eachChild() {}
}


Expand Down
1 change: 1 addition & 0 deletions src/style-spec/function/evaluation_context.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function ensure(condition: any, message: string) {
module.exports = () => ({
types: types,

Color: Color, // used for compiling color literals
ensure: ensure,
error: (msg: string) => ensure(false, msg),

Expand Down
2 changes: 1 addition & 1 deletion src/style-spec/function/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface Expression {
compile(CompilationContext): string; // eslint-disable-line no-use-before-define

serialize(): any;
accept(Visitor<Expression>): void;
eachChild(fn: Expression => void): void;
}

class ParsingError extends Error {
Expand Down
Loading