vega-expression
Version:
Vega expression parser and code generator.
106 lines (94 loc) • 3.29 kB
JavaScript
import {error} from 'vega-util';
export default function(codegen) {
function fncall(name, args, cast, type) {
let obj = codegen(args[0]);
if (cast) {
obj = cast + '(' + obj + ')';
if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
}
return obj + '.' + name + (type < 0 ? '' : type === 0 ?
'()' :
'(' + args.slice(1).map(codegen).join(',') + ')');
}
function fn(name, cast, type) {
return args => fncall(name, args, cast, type);
}
const DATE = 'new Date',
STRING = 'String',
REGEXP = 'RegExp';
return {
// MATH functions
isNaN: 'Number.isNaN',
isFinite: 'Number.isFinite',
abs: 'Math.abs',
acos: 'Math.acos',
asin: 'Math.asin',
atan: 'Math.atan',
atan2: 'Math.atan2',
ceil: 'Math.ceil',
cos: 'Math.cos',
exp: 'Math.exp',
floor: 'Math.floor',
hypot: 'Math.hypot',
log: 'Math.log',
max: 'Math.max',
min: 'Math.min',
pow: 'Math.pow',
random: 'Math.random',
round: 'Math.round',
sin: 'Math.sin',
sqrt: 'Math.sqrt',
tan: 'Math.tan',
clamp: function(args) {
if (args.length < 3) error('Missing arguments to clamp function.');
if (args.length > 3) error('Too many arguments to clamp function.');
const a = args.map(codegen);
return 'Math.max('+a[1]+', Math.min('+a[2]+','+a[0]+'))';
},
// DATE functions
now: 'Date.now',
utc: 'Date.UTC',
datetime: DATE,
date: fn('getDate', DATE, 0),
day: fn('getDay', DATE, 0),
year: fn('getFullYear', DATE, 0),
month: fn('getMonth', DATE, 0),
hours: fn('getHours', DATE, 0),
minutes: fn('getMinutes', DATE, 0),
seconds: fn('getSeconds', DATE, 0),
milliseconds: fn('getMilliseconds', DATE, 0),
time: fn('getTime', DATE, 0),
timezoneoffset: fn('getTimezoneOffset', DATE, 0),
utcdate: fn('getUTCDate', DATE, 0),
utcday: fn('getUTCDay', DATE, 0),
utcyear: fn('getUTCFullYear', DATE, 0),
utcmonth: fn('getUTCMonth', DATE, 0),
utchours: fn('getUTCHours', DATE, 0),
utcminutes: fn('getUTCMinutes', DATE, 0),
utcseconds: fn('getUTCSeconds', DATE, 0),
utcmilliseconds: fn('getUTCMilliseconds', DATE, 0),
// sequence functions
length: fn('length', null, -1),
// STRING functions
parseFloat: 'parseFloat',
parseInt: 'parseInt',
upper: fn('toUpperCase', STRING, 0),
lower: fn('toLowerCase', STRING, 0),
substring: fn('substring', STRING),
split: fn('split', STRING),
trim: fn('trim', STRING, 0),
// base64 encode/decode
btoa: 'btoa',
atob: 'atob',
// REGEXP functions
regexp: REGEXP,
test: fn('test', REGEXP),
// Control Flow functions
if: function(args) {
if (args.length < 3) error('Missing arguments to if function.');
if (args.length > 3) error('Too many arguments to if function.');
const a = args.map(codegen);
return '('+a[0]+'?'+a[1]+':'+a[2]+')';
}
};
}