|
119 | 119 | }
|
120 | 120 |
|
121 | 121 |
|
| 122 | + // Type constants used to define functions. |
| 123 | + var TYPE_NUMBER = 0; |
| 124 | + var TYPE_ANY = 1; |
| 125 | + var TYPE_STRING = 2; |
| 126 | + var TYPE_ARRAY = 3; |
| 127 | + var TYPE_OBJECT = 4; |
| 128 | + var TYPE_BOOLEAN = 5; |
| 129 | + var TYPE_EXPREF = 6; |
| 130 | + var TYPE_NULL = 7; |
| 131 | + var TYPE_ARRAY_NUMBER = 8; |
| 132 | + var TYPE_ARRAY_STRING = 9; |
| 133 | + |
| 134 | + |
122 | 135 | // The "&", "[", "<", ">" tokens
|
123 | 136 | // are not in basicToken because
|
124 | 137 | // there are two token variants
|
|
1139 | 1152 | // types. If the type is "any" then no type checking
|
1140 | 1153 | // occurs on the argument. Variadic is optional
|
1141 | 1154 | // and if not provided is assumed to be false.
|
1142 |
| - abs: {func: this.functionAbs, signature: [{types: ["number"]}]}, |
1143 |
| - avg: {func: this.functionAvg, signature: [{types: ["array-number"]}]}, |
1144 |
| - ceil: {func: this.functionCeil, signature: [{types: ["number"]}]}, |
| 1155 | + abs: {func: this.functionAbs, signature: [{types: [TYPE_NUMBER]}]}, |
| 1156 | + avg: {func: this.functionAvg, signature: [{types: [TYPE_ARRAY_NUMBER]}]}, |
| 1157 | + ceil: {func: this.functionCeil, signature: [{types: [TYPE_NUMBER]}]}, |
1145 | 1158 | contains: {
|
1146 | 1159 | func: this.functionContains,
|
1147 |
| - signature: [{types: ["string", "array"]}, {types: ["any"]}]}, |
| 1160 | + signature: [{types: [TYPE_STRING, TYPE_ARRAY]}, |
| 1161 | + {types: [TYPE_ANY]}]}, |
1148 | 1162 | "ends_with": {
|
1149 | 1163 | func: this.functionEndsWith,
|
1150 |
| - signature: [{types: ["string"]}, {types: ["string"]}]}, |
1151 |
| - floor: {func: this.functionFloor, signature: [{types: ["number"]}]}, |
| 1164 | + signature: [{types: [TYPE_STRING]}, {types: [TYPE_STRING]}]}, |
| 1165 | + floor: {func: this.functionFloor, signature: [{types: [TYPE_NUMBER]}]}, |
1152 | 1166 | length: {
|
1153 | 1167 | func: this.functionLength,
|
1154 |
| - signature: [{types: ["string", "array", "object"]}]}, |
| 1168 | + signature: [{types: [TYPE_STRING, TYPE_ARRAY, TYPE_OBJECT]}]}, |
1155 | 1169 | map: {
|
1156 | 1170 | func: this.functionMap,
|
1157 |
| - signature: [{types: ["expref"]}, {types: ["array"]}]}, |
| 1171 | + signature: [{types: [TYPE_EXPREF]}, {types: [TYPE_ARRAY]}]}, |
1158 | 1172 | max: {
|
1159 | 1173 | func: this.functionMax,
|
1160 |
| - signature: [{types: ["array-number", "array-string"]}]}, |
| 1174 | + signature: [{types: [TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING]}]}, |
1161 | 1175 | "merge": {
|
1162 | 1176 | func: this.functionMerge,
|
1163 |
| - signature: [{types: ["object"], variadic: true}] |
| 1177 | + signature: [{types: [TYPE_OBJECT], variadic: true}] |
1164 | 1178 | },
|
1165 | 1179 | "max_by": {
|
1166 | 1180 | func: this.functionMaxBy,
|
1167 |
| - signature: [{types: ["array"]}, {types: ["expref"]}] |
| 1181 | + signature: [{types: [TYPE_ARRAY]}, {types: [TYPE_EXPREF]}] |
1168 | 1182 | },
|
1169 |
| - sum: {func: this.functionSum, signature: [{types: ["array-number"]}]}, |
| 1183 | + sum: {func: this.functionSum, signature: [{types: [TYPE_ARRAY_NUMBER]}]}, |
1170 | 1184 | "starts_with": {
|
1171 | 1185 | func: this.functionStartsWith,
|
1172 |
| - signature: [{types: ["string"]}, {types: ["string"]}]}, |
| 1186 | + signature: [{types: [TYPE_STRING]}, {types: [TYPE_STRING]}]}, |
1173 | 1187 | min: {
|
1174 | 1188 | func: this.functionMin,
|
1175 |
| - signature: [{types: ["array-number", "array-string"]}]}, |
| 1189 | + signature: [{types: [TYPE_ARRAY_NUMBER, TYPE_ARRAY_STRING]}]}, |
1176 | 1190 | "min_by": {
|
1177 | 1191 | func: this.functionMinBy,
|
1178 |
| - signature: [{types: ["array"]}, {types: ["expref"]}] |
| 1192 | + signature: [{types: [TYPE_ARRAY]}, {types: [TYPE_EXPREF]}] |
1179 | 1193 | },
|
1180 |
| - type: {func: this.functionType, signature: [{types: ["any"]}]}, |
1181 |
| - keys: {func: this.functionKeys, signature: [{types: ["object"]}]}, |
1182 |
| - values: {func: this.functionValues, signature: [{types: ["object"]}]}, |
1183 |
| - sort: {func: this.functionSort, signature: [{types: ["array-string", "array-number"]}]}, |
| 1194 | + type: {func: this.functionType, signature: [{types: [TYPE_ANY]}]}, |
| 1195 | + keys: {func: this.functionKeys, signature: [{types: [TYPE_OBJECT]}]}, |
| 1196 | + values: {func: this.functionValues, signature: [{types: [TYPE_OBJECT]}]}, |
| 1197 | + sort: {func: this.functionSort, signature: [{types: [TYPE_ARRAY_STRING, TYPE_ARRAY_NUMBER]}]}, |
1184 | 1198 | "sort_by": {
|
1185 | 1199 | func: this.functionSortBy,
|
1186 |
| - signature: [{types: ["array"]}, {types: ["expref"]}] |
| 1200 | + signature: [{types: [TYPE_ARRAY]}, {types: [TYPE_EXPREF]}] |
1187 | 1201 | },
|
1188 | 1202 | join: {
|
1189 | 1203 | func: this.functionJoin,
|
1190 | 1204 | signature: [
|
1191 |
| - {types: ["string"]}, |
1192 |
| - {types: ["array-string"]} |
| 1205 | + {types: [TYPE_STRING]}, |
| 1206 | + {types: [TYPE_ARRAY_STRING]} |
1193 | 1207 | ]
|
1194 | 1208 | },
|
1195 | 1209 | reverse: {
|
1196 | 1210 | func: this.functionReverse,
|
1197 |
| - signature: [{types: ["string", "array"]}]}, |
1198 |
| - "to_array": {func: this.functionToArray, signature: [{types: ["any"]}]}, |
1199 |
| - "to_string": {func: this.functionToString, signature: [{types: ["any"]}]}, |
1200 |
| - "to_number": {func: this.functionToNumber, signature: [{types: ["any"]}]}, |
| 1211 | + signature: [{types: [TYPE_STRING, TYPE_ARRAY]}]}, |
| 1212 | + "to_array": {func: this.functionToArray, signature: [{types: [TYPE_ANY]}]}, |
| 1213 | + "to_string": {func: this.functionToString, signature: [{types: [TYPE_ANY]}]}, |
| 1214 | + "to_number": {func: this.functionToNumber, signature: [{types: [TYPE_ANY]}]}, |
1201 | 1215 | "not_null": {
|
1202 | 1216 | func: this.functionNotNull,
|
1203 |
| - signature: [{types: ["any"], variadic: true}] |
| 1217 | + signature: [{types: [TYPE_ANY], variadic: true}] |
1204 | 1218 | }
|
1205 | 1219 | };
|
1206 | 1220 | }
|
|
1259 | 1273 | },
|
1260 | 1274 |
|
1261 | 1275 | typeMatches: function(actual, expected, argValue) {
|
1262 |
| - if (expected === "any") { |
| 1276 | + if (expected === TYPE_ANY) { |
1263 | 1277 | return true;
|
1264 | 1278 | }
|
1265 |
| - if (expected.indexOf("array") === 0) { |
| 1279 | + if (expected === TYPE_ARRAY_STRING || |
| 1280 | + expected === TYPE_ARRAY_NUMBER || |
| 1281 | + expected === TYPE_ARRAY) { |
1266 | 1282 | // The expected type can either just be array,
|
1267 | 1283 | // or it can require a specific subtype (array of numbers).
|
1268 | 1284 | //
|
1269 | 1285 | // The simplest case is if "array" with no subtype is specified.
|
1270 |
| - if (expected === "array") { |
1271 |
| - return actual.indexOf("array") === 0; |
1272 |
| - } else if (actual.indexOf("array") === 0) { |
| 1286 | + if (expected === TYPE_ARRAY) { |
| 1287 | + return actual === TYPE_ARRAY; |
| 1288 | + } else if (actual === TYPE_ARRAY) { |
1273 | 1289 | // Otherwise we need to check subtypes.
|
1274 | 1290 | // I think this has potential to be improved.
|
1275 |
| - var subtype = expected.split("-")[1]; |
| 1291 | + var subtype; |
| 1292 | + if (expected === TYPE_ARRAY_NUMBER) { |
| 1293 | + subtype = TYPE_NUMBER; |
| 1294 | + } else if (expected === TYPE_ARRAY_STRING) { |
| 1295 | + subtype = TYPE_STRING; |
| 1296 | + } |
1276 | 1297 | for (var i = 0; i < argValue.length; i++) {
|
1277 | 1298 | if (!this.typeMatches(
|
1278 | 1299 | this.getTypeName(argValue[i]), subtype,
|
|
1289 | 1310 | getTypeName: function(obj) {
|
1290 | 1311 | switch (Object.prototype.toString.call(obj)) {
|
1291 | 1312 | case "[object String]":
|
1292 |
| - return "string"; |
| 1313 | + return TYPE_STRING; |
1293 | 1314 | case "[object Number]":
|
1294 |
| - return "number"; |
| 1315 | + return TYPE_NUMBER; |
1295 | 1316 | case "[object Array]":
|
1296 |
| - return "array"; |
| 1317 | + return TYPE_ARRAY; |
1297 | 1318 | case "[object Boolean]":
|
1298 |
| - return "boolean"; |
| 1319 | + return TYPE_BOOLEAN; |
1299 | 1320 | case "[object Null]":
|
1300 |
| - return "null"; |
| 1321 | + return TYPE_NULL; |
1301 | 1322 | case "[object Object]":
|
1302 | 1323 | // Check if it's an expref. If it has, it's been
|
1303 | 1324 | // tagged with a jmespathType attr of 'Expref';
|
1304 | 1325 | if (obj.jmespathType === "Expref") {
|
1305 |
| - return "expref"; |
| 1326 | + return TYPE_EXPREF; |
1306 | 1327 | } else {
|
1307 |
| - return "object"; |
| 1328 | + return TYPE_OBJECT; |
1308 | 1329 | }
|
1309 | 1330 | }
|
1310 | 1331 | },
|
|
1321 | 1342 |
|
1322 | 1343 | functionReverse: function(resolvedArgs) {
|
1323 | 1344 | var typeName = this.getTypeName(resolvedArgs[0]);
|
1324 |
| - if (typeName === "string") { |
| 1345 | + if (typeName === TYPE_STRING) { |
1325 | 1346 | var originalStr = resolvedArgs[0];
|
1326 | 1347 | var reversedStr = "";
|
1327 | 1348 | for (var i = originalStr.length - 1; i >= 0; i--) {
|
|
1395 | 1416 | functionMax: function(resolvedArgs) {
|
1396 | 1417 | if (resolvedArgs[0].length > 0) {
|
1397 | 1418 | var typeName = this.getTypeName(resolvedArgs[0][0]);
|
1398 |
| - if (typeName === "number") { |
| 1419 | + if (typeName === TYPE_NUMBER) { |
1399 | 1420 | return Math.max.apply(Math, resolvedArgs[0]);
|
1400 | 1421 | } else {
|
1401 | 1422 | var elements = resolvedArgs[0];
|
|
1415 | 1436 | functionMin: function(resolvedArgs) {
|
1416 | 1437 | if (resolvedArgs[0].length > 0) {
|
1417 | 1438 | var typeName = this.getTypeName(resolvedArgs[0][0]);
|
1418 |
| - if (typeName === "number") { |
| 1439 | + if (typeName === TYPE_NUMBER) { |
1419 | 1440 | return Math.min.apply(Math, resolvedArgs[0]);
|
1420 | 1441 | } else {
|
1421 | 1442 | var elements = resolvedArgs[0];
|
|
1442 | 1463 | },
|
1443 | 1464 |
|
1444 | 1465 | functionType: function(resolvedArgs) {
|
1445 |
| - return this.getTypeName(resolvedArgs[0]); |
| 1466 | + switch (this.getTypeName(resolvedArgs[0])) { |
| 1467 | + case TYPE_NUMBER: |
| 1468 | + return "number"; |
| 1469 | + case TYPE_STRING: |
| 1470 | + return "string"; |
| 1471 | + case TYPE_ARRAY: |
| 1472 | + return "array"; |
| 1473 | + case TYPE_OBJECT: |
| 1474 | + return "object"; |
| 1475 | + case TYPE_BOOLEAN: |
| 1476 | + return "boolean"; |
| 1477 | + case TYPE_EXPREF: |
| 1478 | + return "expref"; |
| 1479 | + case TYPE_NULL: |
| 1480 | + return "null"; |
| 1481 | + } |
1446 | 1482 | },
|
1447 | 1483 |
|
1448 | 1484 | functionKeys: function(resolvedArgs) {
|
|
1466 | 1502 | },
|
1467 | 1503 |
|
1468 | 1504 | functionToArray: function(resolvedArgs) {
|
1469 |
| - if (this.getTypeName(resolvedArgs[0]) === "array") { |
| 1505 | + if (this.getTypeName(resolvedArgs[0]) === TYPE_ARRAY) { |
1470 | 1506 | return resolvedArgs[0];
|
1471 | 1507 | } else {
|
1472 | 1508 | return [resolvedArgs[0]];
|
1473 | 1509 | }
|
1474 | 1510 | },
|
1475 | 1511 |
|
1476 | 1512 | functionToString: function(resolvedArgs) {
|
1477 |
| - if (this.getTypeName(resolvedArgs[0]) === "string") { |
| 1513 | + if (this.getTypeName(resolvedArgs[0]) === TYPE_STRING) { |
1478 | 1514 | return resolvedArgs[0];
|
1479 | 1515 | } else {
|
1480 | 1516 | return JSON.stringify(resolvedArgs[0]);
|
|
1484 | 1520 | functionToNumber: function(resolvedArgs) {
|
1485 | 1521 | var typeName = this.getTypeName(resolvedArgs[0]);
|
1486 | 1522 | var convertedValue;
|
1487 |
| - if (typeName === "number") { |
| 1523 | + if (typeName === TYPE_NUMBER) { |
1488 | 1524 | return resolvedArgs[0];
|
1489 |
| - } else if (typeName === "string") { |
| 1525 | + } else if (typeName === TYPE_STRING) { |
1490 | 1526 | convertedValue = +resolvedArgs[0];
|
1491 | 1527 | if (!isNaN(convertedValue)) {
|
1492 | 1528 | return convertedValue;
|
|
1497 | 1533 |
|
1498 | 1534 | functionNotNull: function(resolvedArgs) {
|
1499 | 1535 | for (var i = 0; i < resolvedArgs.length; i++) {
|
1500 |
| - if (this.getTypeName(resolvedArgs[i]) !== "null") { |
| 1536 | + if (this.getTypeName(resolvedArgs[i]) !== TYPE_NULL) { |
1501 | 1537 | return resolvedArgs[i];
|
1502 | 1538 | }
|
1503 | 1539 | }
|
|
1519 | 1555 | var exprefNode = resolvedArgs[1];
|
1520 | 1556 | var requiredType = this.getTypeName(
|
1521 | 1557 | interpreter.visit(exprefNode, sortedArray[0]));
|
1522 |
| - if (["number", "string"].indexOf(requiredType) < 0) { |
| 1558 | + if ([TYPE_NUMBER, TYPE_STRING].indexOf(requiredType) < 0) { |
1523 | 1559 | throw new Error("TypeError");
|
1524 | 1560 | }
|
1525 | 1561 | var that = this;
|
|
1567 | 1603 | functionMaxBy: function(resolvedArgs) {
|
1568 | 1604 | var exprefNode = resolvedArgs[1];
|
1569 | 1605 | var resolvedArray = resolvedArgs[0];
|
1570 |
| - var keyFunction = this.createKeyFunction(exprefNode, ["number", "string"]); |
| 1606 | + var keyFunction = this.createKeyFunction(exprefNode, [TYPE_NUMBER, TYPE_STRING]); |
1571 | 1607 | var maxNumber = -Infinity;
|
1572 | 1608 | var maxRecord;
|
1573 | 1609 | var current;
|
|
1584 | 1620 | functionMinBy: function(resolvedArgs) {
|
1585 | 1621 | var exprefNode = resolvedArgs[1];
|
1586 | 1622 | var resolvedArray = resolvedArgs[0];
|
1587 |
| - var keyFunction = this.createKeyFunction(exprefNode, ["number", "string"]); |
| 1623 | + var keyFunction = this.createKeyFunction(exprefNode, [TYPE_NUMBER, TYPE_STRING]); |
1588 | 1624 | var minNumber = Infinity;
|
1589 | 1625 | var minRecord;
|
1590 | 1626 | var current;
|
|
0 commit comments