@mapwhit/style-expressions
Version:
Process expressions in map style.
68 lines (57 loc) • 1.77 kB
JavaScript
import assert from 'assert';
import { Formatted } from '../types/formatted.js';
import { Color, isValue, typeOf } from '../values.js';
export default class Literal {
constructor(type, value) {
this.type = type;
this.value = value;
}
static parse(args, context) {
if (args.length !== 2)
return context.error(`'literal' expression requires exactly one argument, but found ${args.length - 1} instead.`);
if (!isValue(args[1])) return context.error('invalid value');
const value = args[1];
let type = typeOf(value);
// special case: infer the item type if possible for zero-length arrays
const expected = context.expectedType;
if (
type.kind === 'array' &&
type.N === 0 &&
expected &&
expected.kind === 'array' &&
(typeof expected.N !== 'number' || expected.N === 0)
) {
type = expected;
}
return new Literal(type, value);
}
evaluate() {
return this.value;
}
eachChild() {}
possibleOutputs() {
return [this.value];
}
serialize() {
if (this.type.kind === 'array' || this.type.kind === 'object') {
return ['literal', this.value];
}
if (this.value instanceof Color) {
// Constant-folding can generate Literal expressions that you
// couldn't actually generate with a "literal" expression,
// so we have to implement an equivalent serialization here
return ['rgba'].concat(this.value.toArray());
}
if (this.value instanceof Formatted) {
// Same as Color
return this.value.serialize();
}
assert(
this.value === null ||
typeof this.value === 'string' ||
typeof this.value === 'number' ||
typeof this.value === 'boolean'
);
return this.value;
}
}