├── .babelrc ├── .eslintrc ├── .gitignore ├── README.md ├── lib └── tailored.js ├── package.json ├── rollup.config.js ├── src ├── index.js └── tailored │ ├── checks.js │ ├── comprehensions.js │ ├── defmatch.js │ ├── match.js │ ├── resolvers.js │ ├── types.js │ └── utils.js ├── test ├── comprehension.spec.js ├── defmatch.spec.js ├── match.spec.js └── tailcall.spec.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ] 11 | ] 12 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [ 4 | 2, 5 | 2 6 | ], 7 | "quotes": [ 8 | 0, 9 | "double" 10 | ], 11 | "linebreak-style": [ 12 | 2, 13 | "unix" 14 | ], 15 | "semi": [ 16 | 2, 17 | "always" 18 | ], 19 | "no-unused-vars": [2, {"vars": "all", "args": "none"}], 20 | "no-console": [ 21 | 0 22 | ], 23 | "comma-dangle":[0] 24 | }, 25 | "env": { 26 | "es6": true, 27 | "browser": true, 28 | "mocha": true, 29 | "node": true 30 | }, 31 | "ecmaFeatures": { modules: true }, 32 | "extends": "eslint:recommended", 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | .DS_Store 4 | test_build/ 5 | *.log 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tailored 2 | 3 | ## A pattern matching library 4 | 5 | This is the pattern matching library ported from elixirscript. It allows you to 6 | create functions that will perform pattern matching on the input and either execute 7 | the corresponding function or throw a `tailored.MatchError`. 8 | 9 | ```js 10 | const tailored = require('tailored'); 11 | const _ = tailored.wildcard(); 12 | const $ = tailored.parameter(); 13 | 14 | let fact = tailored.defmatch( 15 | tailored.clause([0], () => 1), 16 | tailored.clause([$], (n) => n * fact(n - 1)) 17 | ); 18 | 19 | let response = fact(0); //1 20 | response = fact(10); //3628800 21 | ``` 22 | 23 | ### API 24 | 25 | * `tailored.defmatch(...clauses): Function` - Takes one or more `tailored.Clause` objects and returns 26 | a pattern match function. It cycles through the clauses and if a corresponding pattern matches, and the guard is true, 27 | then the matching parameters are passed to the corresponding function that will execute. If no matching clause is found, a `tailored.MatchError` is thrown. 28 | 29 | * `tailored.clause(patterns: Array[any], fn: Function, guard: Function = () => true): tailored.Clause` - A helper function for creating `tailored.Clause` objects. It takes an array of patterns, the function to execute if the pattern matches, and a guard function. 30 | 31 | 32 | * `tailored.match(pattern: any, expression: any): [any]` - Tries to match the pattern with the given expression 33 | 34 | 35 | * `tailored.wildcard()` - Returns a wildcard pattern. Matches on anything. 36 | 37 | * `tailored.variable()` - Returns a variable pattern. Matches on a value and uses it as a parameter for the clause functions 38 | 39 | * `tailored.startsWith(prefix: String)` - Returns a startsWith pattern. Matches on strings with the given string as a prefix 40 | 41 | * `tailored.headTail()` - Returns a headTail pattern. Matches arrays and returns both the head element and the tail elements as parameters 42 | 43 | * `tailored.type(type: any, properties: Object = {})` - Returns a type pattern. Match on the type and it's properties for matching patterns. 44 | 45 | * `tailored.capture(pattern: any)` - Returns a capture pattern. Matches on it's patterns, and then returns the pattern as a parameter 46 | 47 | 48 | ### Examples 49 | 50 | * Matches on anything, returning one 51 | ```js 52 | var fn = tailored.defmatch(tailored.clause([_], function () { 53 | return 1; 54 | })); 55 | 56 | fn("ABC") // 1 57 | ``` 58 | 59 | * Using a guard 60 | ```js 61 | let fn = tailored.defmatch( 62 | tailored.clause([$], (number) => number, (number) => number > 0) 63 | ); 64 | 65 | fn(0); //throws MatchError 66 | fn(3); //returns 3; 67 | ``` 68 | 69 | * Match values in an object 70 | ```js 71 | var fn = tailored.defmatch( 72 | tailored.clause([{ value: $ }], function (val) { return 1 + val; }), 73 | tailored.clause([{ a: { b: { c: $ } } }], function (val) { return 1 - val; }) 74 | ); 75 | 76 | fn({value: 20}) //21; 77 | fn({a: {b: {c: 20}, d: 10 } }) // 19 78 | ``` 79 | 80 | 81 | More examples can be found in the tests 82 | -------------------------------------------------------------------------------- /lib/tailored.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } 4 | 5 | var ErlangTypes = _interopDefault(require('erlang-types')); 6 | 7 | /* @flow */ 8 | 9 | class Variable { 10 | constructor(name = null, default_value = Symbol.for('tailored.no_value')) { 11 | this.name = name; 12 | this.default_value = default_value; 13 | } 14 | } 15 | 16 | class Wildcard { 17 | constructor() {} 18 | } 19 | 20 | class StartsWith { 21 | constructor(prefix) { 22 | this.prefix = prefix; 23 | } 24 | } 25 | 26 | class Capture { 27 | constructor(value) { 28 | this.value = value; 29 | } 30 | } 31 | 32 | class HeadTail { 33 | constructor(head, tail) { 34 | this.head = head; 35 | this.tail = tail; 36 | } 37 | } 38 | 39 | class Type { 40 | constructor(type, objPattern = {}) { 41 | this.type = type; 42 | this.objPattern = objPattern; 43 | } 44 | } 45 | 46 | class Bound { 47 | constructor(value) { 48 | this.value = value; 49 | } 50 | } 51 | 52 | class BitStringMatch { 53 | constructor(...values) { 54 | this.values = values; 55 | } 56 | 57 | length() { 58 | return values.length; 59 | } 60 | 61 | bit_size() { 62 | return this.byte_size() * 8; 63 | } 64 | 65 | byte_size() { 66 | let s = 0; 67 | 68 | for (let val of this.values) { 69 | s = s + val.unit * val.size / 8; 70 | } 71 | 72 | return s; 73 | } 74 | 75 | getValue(index) { 76 | return this.values(index); 77 | } 78 | 79 | getSizeOfValue(index) { 80 | let val = this.getValue(index); 81 | return val.unit * val.size; 82 | } 83 | 84 | getTypeOfValue(index) { 85 | return this.getValue(index).type; 86 | } 87 | } 88 | 89 | class NamedVariableResult { 90 | constructor(name, value) { 91 | this.name = name; 92 | this.value = value; 93 | } 94 | } 95 | 96 | function variable(name = null, default_value = Symbol.for('tailored.no_value')) { 97 | return new Variable(name, default_value); 98 | } 99 | 100 | function wildcard() { 101 | return new Wildcard(); 102 | } 103 | 104 | function startsWith(prefix) { 105 | return new StartsWith(prefix); 106 | } 107 | 108 | function capture(value) { 109 | return new Capture(value); 110 | } 111 | 112 | function headTail(head, tail) { 113 | return new HeadTail(head, tail); 114 | } 115 | 116 | function type(type, objPattern = {}) { 117 | return new Type(type, objPattern); 118 | } 119 | 120 | function bound(value) { 121 | return new Bound(value); 122 | } 123 | 124 | function bitStringMatch(...values) { 125 | return new BitStringMatch(...values); 126 | } 127 | 128 | function namedVariableResult(name, value) { 129 | return new NamedVariableResult(name, value); 130 | } 131 | 132 | /* @flow */ 133 | 134 | function is_number(value) { 135 | return typeof value === 'number'; 136 | } 137 | 138 | function is_string(value) { 139 | return typeof value === 'string'; 140 | } 141 | 142 | function is_boolean(value) { 143 | return typeof value === 'boolean'; 144 | } 145 | 146 | function is_symbol(value) { 147 | return typeof value === 'symbol'; 148 | } 149 | 150 | function is_object(value) { 151 | return typeof value === 'object'; 152 | } 153 | 154 | function is_variable(value) { 155 | return value instanceof Variable; 156 | } 157 | 158 | function is_bitstring(value) { 159 | return value instanceof BitStringMatch; 160 | } 161 | 162 | function is_null(value) { 163 | return value === null; 164 | } 165 | 166 | function is_array(value) { 167 | return Array.isArray(value); 168 | } 169 | 170 | function is_function(value) { 171 | return typeof value === 'function' || value instanceof Function; 172 | } 173 | 174 | function is_map(value) { 175 | return value instanceof Map; 176 | } 177 | 178 | function is_pid(value) { 179 | return value instanceof ErlangTypes.PID; 180 | } 181 | 182 | function is_tuple(value) { 183 | return value instanceof ErlangTypes.Tuple; 184 | } 185 | 186 | function is_reference(value) { 187 | return value instanceof ErlangTypes.Reference; 188 | } 189 | 190 | function arrayEquals(left, right) { 191 | if (!Array.isArray(right)) { 192 | return false; 193 | } 194 | 195 | if (left.length !== right.length) { 196 | return false; 197 | } 198 | 199 | for (let i = 0; i < left.length; i++) { 200 | if (equals(left[i], right[i]) === false) { 201 | return false; 202 | } 203 | } 204 | 205 | return true; 206 | } 207 | 208 | function tupleEquals(left, right) { 209 | if (right instanceof ErlangTypes.Tuple === false) { 210 | return false; 211 | } 212 | 213 | if (left.length !== right.length) { 214 | return false; 215 | } 216 | 217 | return arrayEquals(left.values, right.values); 218 | } 219 | 220 | function bitstringEquals(left, right) { 221 | if (right instanceof ErlangTypes.BitString === false) { 222 | return false; 223 | } 224 | 225 | if (left.length !== right.length) { 226 | return false; 227 | } 228 | 229 | return arrayEquals(left.value, right.value); 230 | } 231 | 232 | function pidEquals(left, right) { 233 | if (right instanceof ErlangTypes.PID === false) { 234 | return false; 235 | } 236 | 237 | return left.id === right.id; 238 | } 239 | 240 | function referenceEquals(left, right) { 241 | if (right instanceof ErlangTypes.Reference === false) { 242 | return false; 243 | } 244 | 245 | return left.id === right.id; 246 | } 247 | 248 | function mapEquals(left, right) { 249 | if (right instanceof Map === false) { 250 | return false; 251 | } 252 | 253 | const leftEntries = Array.from(left.entries()); 254 | const rightEntries = Array.from(right.entries()); 255 | 256 | return arrayEquals(leftEntries, rightEntries); 257 | } 258 | 259 | function equals(left, right) { 260 | if (Array.isArray(left)) { 261 | return arrayEquals(left, right); 262 | } 263 | 264 | if (left instanceof ErlangTypes.Tuple) { 265 | return tupleEquals(left, right); 266 | } 267 | 268 | if (left instanceof ErlangTypes.PID) { 269 | return pidEquals(left, right); 270 | } 271 | 272 | if (left instanceof ErlangTypes.BitString) { 273 | return bitstringEquals(left, right); 274 | } 275 | 276 | if (left instanceof ErlangTypes.Reference) { 277 | return referenceEquals(left, right); 278 | } 279 | 280 | if (left instanceof Map) { 281 | return mapEquals(left, right); 282 | } 283 | 284 | return left === right; 285 | } 286 | 287 | function is_non_primitive(key) { 288 | return is_array(key) || is_map(key) || is_pid(key) || is_reference(key) || is_bitstring(key) || is_tuple(key); 289 | } 290 | 291 | function has(map, key) { 292 | if (is_non_primitive(key)) { 293 | for (const map_key of map.keys()) { 294 | if (equals(map_key, key)) { 295 | return true; 296 | } 297 | } 298 | 299 | return false; 300 | } 301 | 302 | return map.has(key); 303 | } 304 | 305 | function get(map, key) { 306 | if (is_non_primitive(key)) { 307 | for (const map_key of map.keys()) { 308 | if (equals(map_key, key)) { 309 | return map.get(map_key); 310 | } 311 | } 312 | 313 | return null; 314 | } 315 | 316 | return map.get(key); 317 | } 318 | 319 | var Utils = { 320 | get, 321 | has, 322 | equals 323 | }; 324 | 325 | /* @flow */ 326 | 327 | const BitString = ErlangTypes.BitString; 328 | function resolveSymbol(pattern) { 329 | return function (value) { 330 | return is_symbol(value) && value === pattern; 331 | }; 332 | } 333 | 334 | function resolveString(pattern) { 335 | return function (value) { 336 | return is_string(value) && value === pattern; 337 | }; 338 | } 339 | 340 | function resolveNumber(pattern) { 341 | return function (value) { 342 | return is_number(value) && value === pattern; 343 | }; 344 | } 345 | 346 | function resolveBoolean(pattern) { 347 | return function (value) { 348 | return is_boolean(value) && value === pattern; 349 | }; 350 | } 351 | 352 | function resolveFunction(pattern) { 353 | return function (value) { 354 | return is_function(value) && value === pattern; 355 | }; 356 | } 357 | 358 | function resolveNull(pattern) { 359 | return function (value) { 360 | return is_null(value); 361 | }; 362 | } 363 | 364 | function resolveBound(pattern) { 365 | return function (value, args) { 366 | if (typeof value === typeof pattern.value && value === pattern.value) { 367 | return true; 368 | } 369 | 370 | return false; 371 | }; 372 | } 373 | 374 | function resolveWildcard() { 375 | return function () { 376 | return true; 377 | }; 378 | } 379 | 380 | function resolveVariable(pattern) { 381 | return function (value, args) { 382 | if (pattern.name === null) { 383 | args.push(value); 384 | } else if (pattern.name !== '_') { 385 | args.push(namedVariableResult(pattern.name, value)); 386 | } 387 | 388 | return true; 389 | }; 390 | } 391 | 392 | function resolveHeadTail(pattern) { 393 | const headMatches = buildMatch(pattern.head); 394 | const tailMatches = buildMatch(pattern.tail); 395 | 396 | return function (value, args) { 397 | if (!is_array(value) || value.length === 0) { 398 | return false; 399 | } 400 | 401 | const head = value[0]; 402 | const tail = value.slice(1); 403 | 404 | if (headMatches(head, args) && tailMatches(tail, args)) { 405 | return true; 406 | } 407 | 408 | return false; 409 | }; 410 | } 411 | 412 | function resolveCapture(pattern) { 413 | const matches = buildMatch(pattern.value); 414 | 415 | return function (value, args) { 416 | if (matches(value, args)) { 417 | args.push(value); 418 | return true; 419 | } 420 | 421 | return false; 422 | }; 423 | } 424 | 425 | function resolveStartsWith(pattern) { 426 | const prefix = pattern.prefix; 427 | 428 | return function (value, args) { 429 | if (is_string(value) && value.startsWith(prefix)) { 430 | args.push(value.substring(prefix.length)); 431 | return true; 432 | } 433 | 434 | return false; 435 | }; 436 | } 437 | 438 | function resolveType(pattern) { 439 | return function (value, args) { 440 | if (value instanceof pattern.type) { 441 | const matches = buildMatch(pattern.objPattern); 442 | return matches(value, args); 443 | } 444 | 445 | return false; 446 | }; 447 | } 448 | 449 | function resolveArray(pattern) { 450 | const matches = pattern.map(x => buildMatch(x)); 451 | 452 | return function (value, args) { 453 | if (!is_array(value) || value.length != pattern.length) { 454 | return false; 455 | } 456 | 457 | return value.every(function (v, i) { 458 | return matches[i](value[i], args); 459 | }); 460 | }; 461 | } 462 | 463 | function resolveMap(pattern) { 464 | let matches = new Map(); 465 | 466 | const keys = Array.from(pattern.keys()); 467 | 468 | for (let key of keys) { 469 | matches.set(key, buildMatch(pattern.get(key))); 470 | } 471 | 472 | return function (value, args) { 473 | if (!is_map(value) || pattern.size > value.size) { 474 | return false; 475 | } 476 | 477 | for (const key of keys) { 478 | if (!Utils.has(value, key) || !Utils.get(matches, key)(Utils.get(value, key), args)) { 479 | return false; 480 | } 481 | } 482 | 483 | return true; 484 | }; 485 | } 486 | 487 | function resolveObject(pattern) { 488 | let matches = {}; 489 | 490 | const keys = Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern)); 491 | 492 | for (let key of keys) { 493 | matches[key] = buildMatch(pattern[key]); 494 | } 495 | 496 | return function (value, args) { 497 | if (!is_object(value) || pattern.length > value.length) { 498 | return false; 499 | } 500 | 501 | for (let key of keys) { 502 | if (!(key in value) || !matches[key](value[key], args)) { 503 | return false; 504 | } 505 | } 506 | 507 | return true; 508 | }; 509 | } 510 | 511 | function resolveBitString(pattern) { 512 | let patternBitString = []; 513 | 514 | for (let bitstringMatchPart of pattern.values) { 515 | if (is_variable(bitstringMatchPart.value)) { 516 | let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); 517 | fillArray(patternBitString, size); 518 | } else { 519 | patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); 520 | } 521 | } 522 | 523 | let patternValues = pattern.values; 524 | 525 | return function (value, args) { 526 | let bsValue = null; 527 | 528 | if (!is_string(value) && !(value instanceof BitString)) { 529 | return false; 530 | } 531 | 532 | if (is_string(value)) { 533 | bsValue = new BitString(BitString.binary(value)); 534 | } else { 535 | bsValue = value; 536 | } 537 | 538 | let beginningIndex = 0; 539 | 540 | for (let i = 0; i < patternValues.length; i++) { 541 | let bitstringMatchPart = patternValues[i]; 542 | 543 | if (is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { 544 | throw new Error('a binary field without size is only allowed at the end of a binary pattern'); 545 | } 546 | 547 | let size = 0; 548 | let bsValueArrayPart = []; 549 | let patternBitStringArrayPart = []; 550 | size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); 551 | 552 | if (i === patternValues.length - 1) { 553 | bsValueArrayPart = bsValue.value.slice(beginningIndex); 554 | patternBitStringArrayPart = patternBitString.slice(beginningIndex); 555 | } else { 556 | bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); 557 | patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); 558 | } 559 | 560 | if (is_variable(bitstringMatchPart.value)) { 561 | switch (bitstringMatchPart.type) { 562 | case 'integer': 563 | if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf('signed') != -1) { 564 | args.push(new Int8Array([bsValueArrayPart[0]])[0]); 565 | } else { 566 | args.push(new Uint8Array([bsValueArrayPart[0]])[0]); 567 | } 568 | break; 569 | 570 | case 'float': 571 | if (size === 64) { 572 | args.push(Float64Array.from(bsValueArrayPart)[0]); 573 | } else if (size === 32) { 574 | args.push(Float32Array.from(bsValueArrayPart)[0]); 575 | } else { 576 | return false; 577 | } 578 | break; 579 | 580 | case 'bitstring': 581 | args.push(createBitString(bsValueArrayPart)); 582 | break; 583 | 584 | case 'binary': 585 | args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); 586 | break; 587 | 588 | case 'utf8': 589 | args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); 590 | break; 591 | 592 | case 'utf16': 593 | args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); 594 | break; 595 | 596 | case 'utf32': 597 | args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); 598 | break; 599 | 600 | default: 601 | return false; 602 | } 603 | } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { 604 | return false; 605 | } 606 | 607 | beginningIndex = beginningIndex + size; 608 | } 609 | 610 | return true; 611 | }; 612 | } 613 | 614 | function getSize(unit, size) { 615 | return unit * size / 8; 616 | } 617 | 618 | function arraysEqual(a, b) { 619 | if (a === b) return true; 620 | if (a == null || b == null) return false; 621 | if (a.length != b.length) return false; 622 | 623 | for (var i = 0; i < a.length; ++i) { 624 | if (a[i] !== b[i]) return false; 625 | } 626 | 627 | return true; 628 | } 629 | 630 | function fillArray(arr, num) { 631 | for (let i = 0; i < num; i++) { 632 | arr.push(0); 633 | } 634 | } 635 | 636 | function createBitString(arr) { 637 | let integerParts = arr.map(elem => BitString.integer(elem)); 638 | return new BitString(...integerParts); 639 | } 640 | 641 | function resolveNoMatch() { 642 | return function () { 643 | return false; 644 | }; 645 | } 646 | 647 | const patternMap = new Map(); 648 | patternMap.set(Variable.prototype, resolveVariable); 649 | patternMap.set(Wildcard.prototype, resolveWildcard); 650 | patternMap.set(HeadTail.prototype, resolveHeadTail); 651 | patternMap.set(StartsWith.prototype, resolveStartsWith); 652 | patternMap.set(Capture.prototype, resolveCapture); 653 | patternMap.set(Bound.prototype, resolveBound); 654 | patternMap.set(Type.prototype, resolveType); 655 | patternMap.set(BitStringMatch.prototype, resolveBitString); 656 | patternMap.set(Number.prototype, resolveNumber); 657 | patternMap.set(Symbol.prototype, resolveSymbol); 658 | patternMap.set(Map.prototype, resolveMap); 659 | patternMap.set(Array.prototype, resolveArray); 660 | patternMap.set(String.prototype, resolveString); 661 | patternMap.set(Boolean.prototype, resolveBoolean); 662 | patternMap.set(Function.prototype, resolveFunction); 663 | patternMap.set(Object.prototype, resolveObject); 664 | 665 | function buildMatch(pattern) { 666 | if (pattern === null) { 667 | return resolveNull(pattern); 668 | } 669 | 670 | if (typeof pattern === 'undefined') { 671 | return resolveWildcard(pattern); 672 | } 673 | 674 | if (typeof pattern === 'function') { 675 | return resolveFunction(pattern); 676 | } 677 | 678 | const type$$1 = pattern.constructor.prototype; 679 | const resolver = patternMap.get(type$$1); 680 | 681 | if (resolver) { 682 | return resolver(pattern); 683 | } 684 | 685 | if (typeof pattern === 'object') { 686 | return resolveObject(pattern); 687 | } 688 | 689 | return resolveNoMatch(); 690 | } 691 | 692 | class MatchError extends Error { 693 | constructor(arg) { 694 | super(); 695 | 696 | if (typeof arg === 'symbol') { 697 | this.message = 'No match for: ' + arg.toString(); 698 | } else if (Array.isArray(arg)) { 699 | let mappedValues = arg.map(x => { 700 | if (x === null) { 701 | return 'null'; 702 | } else if (typeof x === 'undefined') { 703 | return 'undefined'; 704 | } 705 | 706 | return x.toString(); 707 | }); 708 | 709 | this.message = 'No match for: ' + mappedValues; 710 | } else { 711 | this.message = 'No match for: ' + arg; 712 | } 713 | 714 | this.name = this.constructor.name; 715 | } 716 | } 717 | 718 | class Clause { 719 | constructor(pattern, fn, guard = () => true) { 720 | this.pattern = buildMatch(pattern); 721 | this.arity = pattern.length; 722 | this.optionals = getOptionalValues(pattern); 723 | this.fn = fn; 724 | this.guard = guard; 725 | } 726 | } 727 | 728 | function clause(pattern, fn, guard = () => true) { 729 | return new Clause(pattern, fn, guard); 730 | } 731 | 732 | 733 | 734 | function defmatch(...clauses) { 735 | const arities = getArityMap(clauses); 736 | 737 | return function (...args) { 738 | let [funcToCall, params] = findMatchingFunction(args, arities); 739 | return funcToCall.apply(this, params); 740 | }; 741 | } 742 | 743 | function defmatchgen(...clauses) { 744 | const arities = getArityMap(clauses); 745 | 746 | return function* (...args) { 747 | if (arities.has(args.length)) { 748 | const arityClauses = arities.get(args.length); 749 | 750 | let funcToCall = null; 751 | let params = null; 752 | for (let processedClause of arityClauses) { 753 | let result = []; 754 | args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); 755 | 756 | const doesMatch = processedClause.pattern(args, result); 757 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 758 | 759 | if (doesMatch && allNamesMatch && (yield* processedClause.guard.apply(this, filteredResult))) { 760 | funcToCall = processedClause.fn; 761 | params = filteredResult; 762 | break; 763 | } 764 | } 765 | 766 | if (!funcToCall) { 767 | console.error('No match for:', args); 768 | throw new MatchError(args); 769 | } 770 | 771 | return yield* funcToCall.apply(this, params); 772 | } else { 773 | console.error('Arity of', args.length, 'not found. No match for:', args); 774 | throw new MatchError(args); 775 | } 776 | }; 777 | } 778 | 779 | function defmatchGen(...args) { 780 | return defmatchgen(...args); 781 | } 782 | 783 | function defmatchAsync(...clauses) { 784 | const arities = getArityMap(clauses); 785 | 786 | return async function (...args) { 787 | if (arities.has(args.length)) { 788 | const arityClauses = arities.get(args.length); 789 | 790 | let funcToCall = null; 791 | let params = null; 792 | for (let processedClause of arityClauses) { 793 | let result = []; 794 | args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); 795 | 796 | const doesMatch = processedClause.pattern(args, result); 797 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 798 | 799 | if (doesMatch && allNamesMatch && (await processedClause.guard.apply(this, filteredResult))) { 800 | funcToCall = processedClause.fn; 801 | params = filteredResult; 802 | break; 803 | } 804 | } 805 | 806 | if (!funcToCall) { 807 | console.error('No match for:', args); 808 | throw new MatchError(args); 809 | } 810 | 811 | return funcToCall.apply(this, params); 812 | } else { 813 | console.error('Arity of', args.length, 'not found. No match for:', args); 814 | throw new MatchError(args); 815 | } 816 | }; 817 | } 818 | 819 | function findMatchingFunction(args, arities) { 820 | if (arities.has(args.length)) { 821 | const arityClauses = arities.get(args.length); 822 | 823 | let funcToCall = null; 824 | let params = null; 825 | for (let processedClause of arityClauses) { 826 | let result = []; 827 | args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); 828 | 829 | const doesMatch = processedClause.pattern(args, result); 830 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 831 | 832 | if (doesMatch && allNamesMatch && processedClause.guard.apply(this, filteredResult)) { 833 | funcToCall = processedClause.fn; 834 | params = filteredResult; 835 | break; 836 | } 837 | } 838 | 839 | if (!funcToCall) { 840 | console.error('No match for:', args); 841 | throw new MatchError(args); 842 | } 843 | 844 | return [funcToCall, params]; 845 | } else { 846 | console.error('Arity of', args.length, 'not found. No match for:', args); 847 | throw new MatchError(args); 848 | } 849 | } 850 | 851 | function getArityMap(clauses) { 852 | let map = new Map(); 853 | 854 | for (const clause of clauses) { 855 | const range = getArityRange(clause); 856 | 857 | for (const arity of range) { 858 | let arityClauses = []; 859 | 860 | if (map.has(arity)) { 861 | arityClauses = map.get(arity); 862 | } 863 | 864 | arityClauses.push(clause); 865 | map.set(arity, arityClauses); 866 | } 867 | } 868 | 869 | return map; 870 | } 871 | 872 | function getArityRange(clause) { 873 | const min = clause.arity - clause.optionals.length; 874 | const max = clause.arity; 875 | 876 | let range = [min]; 877 | 878 | while (range[range.length - 1] != max) { 879 | range.push(range[range.length - 1] + 1); 880 | } 881 | 882 | return range; 883 | } 884 | 885 | function getOptionalValues(pattern) { 886 | let optionals = []; 887 | 888 | for (let i = 0; i < pattern.length; i++) { 889 | if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for('tailored.no_value')) { 890 | optionals.push([i, pattern[i].default_value]); 891 | } 892 | } 893 | 894 | return optionals; 895 | } 896 | 897 | function fillInOptionalValues(args, arity, optionals) { 898 | if (args.length === arity || optionals.length === 0) { 899 | return args; 900 | } 901 | 902 | if (args.length + optionals.length < arity) { 903 | return args; 904 | } 905 | 906 | let numberOfOptionalsToFill = arity - args.length; 907 | let optionalsToRemove = optionals.length - numberOfOptionalsToFill; 908 | 909 | let optionalsToUse = optionals.slice(optionalsToRemove); 910 | 911 | for (let [index, value] of optionalsToUse) { 912 | args.splice(index, 0, value); 913 | if (args.length === arity) { 914 | break; 915 | } 916 | } 917 | 918 | return args; 919 | } 920 | 921 | function match(pattern, expr, guard = () => true) { 922 | let result = []; 923 | let processedPattern = buildMatch(pattern); 924 | const doesMatch = processedPattern(expr, result); 925 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 926 | 927 | if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { 928 | return filteredResult; 929 | } else { 930 | console.error('No match for:', expr); 931 | throw new MatchError(expr); 932 | } 933 | } 934 | 935 | function* match_gen(pattern, expr, guard = function* () { 936 | return true; 937 | }) { 938 | let result = []; 939 | let processedPattern = buildMatch(pattern); 940 | const doesMatch = processedPattern(expr, result); 941 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 942 | const matches = doesMatch && allNamesMatch; 943 | 944 | if (matches && (yield* guard.apply(this, filteredResult))) { 945 | return filteredResult; 946 | } else { 947 | console.error('No match for:', expr); 948 | throw new MatchError(expr); 949 | } 950 | } 951 | 952 | function checkNamedVariables(results) { 953 | const namesMap = {}; 954 | const filteredResults = []; 955 | 956 | for (let i = 0; i < results.length; i++) { 957 | const current = results[i]; 958 | if (current instanceof NamedVariableResult) { 959 | if (namesMap[current.name] && namesMap[current.name] !== current.value) { 960 | return [results, false]; 961 | } else if (namesMap[current.name] && namesMap[current.name] === current.value) { 962 | filteredResults.push(current.value); 963 | } else { 964 | namesMap[current.name] = current.value; 965 | filteredResults.push(current.value); 966 | } 967 | } else { 968 | filteredResults.push(current); 969 | } 970 | } 971 | 972 | return [filteredResults, true]; 973 | } 974 | 975 | function match_or_default(pattern, expr, guard = () => true, default_value = null) { 976 | let result = []; 977 | let processedPattern = buildMatch(pattern); 978 | const doesMatch = processedPattern(expr, result); 979 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 980 | 981 | if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { 982 | return filteredResult; 983 | } else { 984 | return default_value; 985 | } 986 | } 987 | 988 | function* match_or_default_gen(pattern, expr, guard = function* () { 989 | return true; 990 | }, default_value = null) { 991 | let result = []; 992 | let processedPattern = buildMatch(pattern); 993 | const doesMatch = processedPattern(expr, result); 994 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 995 | const matches = doesMatch && allNamesMatch; 996 | 997 | if (matches && (yield* guard.apply(this, filteredResult))) { 998 | return filteredResult; 999 | } else { 1000 | return default_value; 1001 | } 1002 | } 1003 | 1004 | async function match_or_default_async(pattern, expr, guard = async () => true, default_value = null) { 1005 | let result = []; 1006 | let processedPattern = buildMatch(pattern); 1007 | const doesMatch = processedPattern(expr, result); 1008 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 1009 | const matches = doesMatch && allNamesMatch; 1010 | 1011 | if (matches && (await guard.apply(this, filteredResult))) { 1012 | return filteredResult; 1013 | } else { 1014 | return default_value; 1015 | } 1016 | } 1017 | 1018 | const NO_MATCH = Symbol(); 1019 | 1020 | function bitstring_generator(pattern, bitstring) { 1021 | return function () { 1022 | let returnResult = []; 1023 | let bsSlice = bitstring.slice(0, pattern.byte_size()); 1024 | let i = 1; 1025 | 1026 | while (bsSlice.byte_size == pattern.byte_size()) { 1027 | const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); 1028 | 1029 | if (result != NO_MATCH) { 1030 | const [value] = result; 1031 | returnResult.push(result); 1032 | } 1033 | 1034 | bsSlice = bitstring.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); 1035 | 1036 | i++; 1037 | } 1038 | 1039 | return returnResult; 1040 | }; 1041 | } 1042 | 1043 | function list_generator(pattern, list) { 1044 | return function () { 1045 | let returnResult = []; 1046 | for (let i of list) { 1047 | const result = match_or_default(pattern, i, () => true, NO_MATCH); 1048 | if (result != NO_MATCH) { 1049 | const [value] = result; 1050 | returnResult.push(value); 1051 | } 1052 | } 1053 | 1054 | return returnResult; 1055 | }; 1056 | } 1057 | 1058 | function list_comprehension(expression, generators) { 1059 | const generatedValues = run_generators(generators.pop()(), generators); 1060 | 1061 | let result = []; 1062 | 1063 | for (let value of generatedValues) { 1064 | if (expression.guard.apply(this, value)) { 1065 | result.push(expression.fn.apply(this, value)); 1066 | } 1067 | } 1068 | 1069 | return result; 1070 | } 1071 | 1072 | function run_generators(generator, generators) { 1073 | if (generators.length == 0) { 1074 | return generator.map(x => { 1075 | if (Array.isArray(x)) { 1076 | return x; 1077 | } else { 1078 | return [x]; 1079 | } 1080 | }); 1081 | } else { 1082 | const list = generators.pop(); 1083 | 1084 | let next_gen = []; 1085 | for (let j of list()) { 1086 | for (let i of generator) { 1087 | next_gen.push([j].concat(i)); 1088 | } 1089 | } 1090 | 1091 | return run_generators(next_gen, generators); 1092 | } 1093 | } 1094 | 1095 | function bitstring_comprehension(expression, generators) { 1096 | const generatedValues = run_generators(generators.pop()(), generators); 1097 | 1098 | let result = []; 1099 | 1100 | for (let value of generatedValues) { 1101 | if (expression.guard.apply(this, value)) { 1102 | result.push(expression.fn.apply(this, value)); 1103 | } 1104 | } 1105 | 1106 | result = result.map(x => ErlangTypes.BitString.integer(x)); 1107 | return new ErlangTypes.BitString(...result); 1108 | } 1109 | 1110 | var index = { 1111 | defmatch, 1112 | match, 1113 | match_gen, 1114 | MatchError, 1115 | variable, 1116 | wildcard, 1117 | startsWith, 1118 | capture, 1119 | headTail, 1120 | type, 1121 | bound, 1122 | Clause, 1123 | clause, 1124 | bitStringMatch, 1125 | match_or_default, 1126 | match_or_default_gen, 1127 | match_or_default_async, 1128 | defmatchgen, 1129 | list_comprehension, 1130 | list_generator, 1131 | bitstring_generator, 1132 | bitstring_comprehension, 1133 | defmatchGen, 1134 | defmatchAsync 1135 | }; 1136 | 1137 | module.exports = index; 1138 | //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFpbG9yZWQuanMiLCJzb3VyY2VzIjpbIi4uL3NyYy90YWlsb3JlZC90eXBlcy5qcyIsIi4uL3NyYy90YWlsb3JlZC9jaGVja3MuanMiLCIuLi9zcmMvdGFpbG9yZWQvdXRpbHMuanMiLCIuLi9zcmMvdGFpbG9yZWQvcmVzb2x2ZXJzLmpzIiwiLi4vc3JjL3RhaWxvcmVkL21hdGNoLmpzIiwiLi4vc3JjL3RhaWxvcmVkL2RlZm1hdGNoLmpzIiwiLi4vc3JjL3RhaWxvcmVkL2NvbXByZWhlbnNpb25zLmpzIiwiLi4vc3JjL2luZGV4LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwsIGRlZmF1bHRfdmFsdWUgPSBTeW1ib2wuZm9yKCd0YWlsb3JlZC5ub192YWx1ZScpKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICB0aGlzLmRlZmF1bHRfdmFsdWUgPSBkZWZhdWx0X3ZhbHVlO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoaGVhZCwgdGFpbCkge1xuICAgIHRoaXMuaGVhZCA9IGhlYWQ7XG4gICAgdGhpcy50YWlsID0gdGFpbDtcbiAgfVxufVxuXG5jbGFzcyBUeXBlIHtcbiAgY29uc3RydWN0b3IodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLm9ialBhdHRlcm4gPSBvYmpQYXR0ZXJuO1xuICB9XG59XG5cbmNsYXNzIEJvdW5kIHtcbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nTWF0Y2gge1xuICBjb25zdHJ1Y3RvciguLi52YWx1ZXMpIHtcbiAgICB0aGlzLnZhbHVlcyA9IHZhbHVlcztcbiAgfVxuXG4gIGxlbmd0aCgpIHtcbiAgICByZXR1cm4gdmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIGJpdF9zaXplKCkge1xuICAgIHJldHVybiB0aGlzLmJ5dGVfc2l6ZSgpICogODtcbiAgfVxuXG4gIGJ5dGVfc2l6ZSgpIHtcbiAgICBsZXQgcyA9IDA7XG5cbiAgICBmb3IgKGxldCB2YWwgb2YgdGhpcy52YWx1ZXMpIHtcbiAgICAgIHMgPSBzICsgdmFsLnVuaXQgKiB2YWwuc2l6ZSAvIDg7XG4gICAgfVxuXG4gICAgcmV0dXJuIHM7XG4gIH1cblxuICBnZXRWYWx1ZShpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcyhpbmRleCk7XG4gIH1cblxuICBnZXRTaXplT2ZWYWx1ZShpbmRleCkge1xuICAgIGxldCB2YWwgPSB0aGlzLmdldFZhbHVlKGluZGV4KTtcbiAgICByZXR1cm4gdmFsLnVuaXQgKiB2YWwuc2l6ZTtcbiAgfVxuXG4gIGdldFR5cGVPZlZhbHVlKGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VmFsdWUoaW5kZXgpLnR5cGU7XG4gIH1cbn1cblxuY2xhc3MgTmFtZWRWYXJpYWJsZVJlc3VsdCB7XG4gIGNvbnN0cnVjdG9yKG5hbWUsIHZhbHVlKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUoXG4gIG5hbWUgPSBudWxsLFxuICBkZWZhdWx0X3ZhbHVlID0gU3ltYm9sLmZvcigndGFpbG9yZWQubm9fdmFsdWUnKVxuKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSwgZGVmYXVsdF92YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKGhlYWQsIHRhaWwpIHtcbiAgcmV0dXJuIG5ldyBIZWFkVGFpbChoZWFkLCB0YWlsKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gYml0U3RyaW5nTWF0Y2goLi4udmFsdWVzKSB7XG4gIHJldHVybiBuZXcgQml0U3RyaW5nTWF0Y2goLi4udmFsdWVzKTtcbn1cblxuZnVuY3Rpb24gbmFtZWRWYXJpYWJsZVJlc3VsdChuYW1lLCB2YWx1ZSkge1xuICByZXR1cm4gbmV3IE5hbWVkVmFyaWFibGVSZXN1bHQobmFtZSwgdmFsdWUpO1xufVxuXG5leHBvcnQge1xuICBWYXJpYWJsZSxcbiAgV2lsZGNhcmQsXG4gIFN0YXJ0c1dpdGgsXG4gIENhcHR1cmUsXG4gIEhlYWRUYWlsLFxuICBUeXBlLFxuICBCb3VuZCxcbiAgQml0U3RyaW5nTWF0Y2gsXG4gIHZhcmlhYmxlLFxuICB3aWxkY2FyZCxcbiAgc3RhcnRzV2l0aCxcbiAgY2FwdHVyZSxcbiAgaGVhZFRhaWwsXG4gIHR5cGUsXG4gIGJvdW5kLFxuICBiaXRTdHJpbmdNYXRjaCxcbiAgTmFtZWRWYXJpYWJsZVJlc3VsdCxcbiAgbmFtZWRWYXJpYWJsZVJlc3VsdFxufTtcbiIsIi8qIEBmbG93ICovXG5cbmltcG9ydCB7XG4gIFZhcmlhYmxlLFxuICBXaWxkY2FyZCxcbiAgSGVhZFRhaWwsXG4gIENhcHR1cmUsXG4gIFR5cGUsXG4gIFN0YXJ0c1dpdGgsXG4gIEJvdW5kLFxuICBCaXRTdHJpbmdNYXRjaFxufSBmcm9tICcuL3R5cGVzJztcblxuaW1wb3J0IEVybGFuZ1R5cGVzIGZyb20gJ2VybGFuZy10eXBlcyc7XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCaXRTdHJpbmdNYXRjaDtcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJyB8fCB2YWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19tYXAodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgTWFwO1xufVxuXG5mdW5jdGlvbiBpc19waWQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgRXJsYW5nVHlwZXMuUElEO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBFcmxhbmdUeXBlcy5UdXBsZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEVybGFuZ1R5cGVzLlJlZmVyZW5jZTtcbn1cblxuZXhwb3J0IHtcbiAgaXNfbnVtYmVyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXksXG4gIGlzX2JpdHN0cmluZyxcbiAgaXNfbWFwLFxuICBpc190dXBsZSxcbiAgaXNfcGlkLFxuICBpc19yZWZlcmVuY2UsXG59O1xuIiwiaW1wb3J0ICogYXMgQ2hlY2tzIGZyb20gJy4vY2hlY2tzJztcbmltcG9ydCBFcmxhbmdUeXBlcyBmcm9tICdlcmxhbmctdHlwZXMnO1xuXG5mdW5jdGlvbiBhcnJheUVxdWFscyhsZWZ0LCByaWdodCkge1xuICBpZiAoIUFycmF5LmlzQXJyYXkocmlnaHQpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGxlZnQubGVuZ3RoICE9PSByaWdodC5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxlZnQubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoZXF1YWxzKGxlZnRbaV0sIHJpZ2h0W2ldKSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gdHVwbGVFcXVhbHMobGVmdCwgcmlnaHQpIHtcbiAgaWYgKHJpZ2h0IGluc3RhbmNlb2YgRXJsYW5nVHlwZXMuVHVwbGUgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGxlZnQubGVuZ3RoICE9PSByaWdodC5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gYXJyYXlFcXVhbHMobGVmdC52YWx1ZXMsIHJpZ2h0LnZhbHVlcyk7XG59XG5cbmZ1bmN0aW9uIGJpdHN0cmluZ0VxdWFscyhsZWZ0LCByaWdodCkge1xuICBpZiAocmlnaHQgaW5zdGFuY2VvZiBFcmxhbmdUeXBlcy5CaXRTdHJpbmcgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgaWYgKGxlZnQubGVuZ3RoICE9PSByaWdodC5sZW5ndGgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gYXJyYXlFcXVhbHMobGVmdC52YWx1ZSwgcmlnaHQudmFsdWUpO1xufVxuXG5mdW5jdGlvbiBwaWRFcXVhbHMobGVmdCwgcmlnaHQpIHtcbiAgaWYgKHJpZ2h0IGluc3RhbmNlb2YgRXJsYW5nVHlwZXMuUElEID09PSBmYWxzZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBsZWZ0LmlkID09PSByaWdodC5pZDtcbn1cblxuZnVuY3Rpb24gcmVmZXJlbmNlRXF1YWxzKGxlZnQsIHJpZ2h0KSB7XG4gIGlmIChyaWdodCBpbnN0YW5jZW9mIEVybGFuZ1R5cGVzLlJlZmVyZW5jZSA9PT0gZmFsc2UpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gbGVmdC5pZCA9PT0gcmlnaHQuaWQ7XG59XG5cbmZ1bmN0aW9uIG1hcEVxdWFscyhsZWZ0LCByaWdodCkge1xuICBpZiAocmlnaHQgaW5zdGFuY2VvZiBNYXAgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3QgbGVmdEVudHJpZXMgPSBBcnJheS5mcm9tKGxlZnQuZW50cmllcygpKTtcbiAgY29uc3QgcmlnaHRFbnRyaWVzID0gQXJyYXkuZnJvbShyaWdodC5lbnRyaWVzKCkpO1xuXG4gIHJldHVybiBhcnJheUVxdWFscyhsZWZ0RW50cmllcywgcmlnaHRFbnRyaWVzKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxzKGxlZnQsIHJpZ2h0KSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGxlZnQpKSB7XG4gICAgcmV0dXJuIGFycmF5RXF1YWxzKGxlZnQsIHJpZ2h0KTtcbiAgfVxuXG4gIGlmIChsZWZ0IGluc3RhbmNlb2YgRXJsYW5nVHlwZXMuVHVwbGUpIHtcbiAgICByZXR1cm4gdHVwbGVFcXVhbHMobGVmdCwgcmlnaHQpO1xuICB9XG5cbiAgaWYgKGxlZnQgaW5zdGFuY2VvZiBFcmxhbmdUeXBlcy5QSUQpIHtcbiAgICByZXR1cm4gcGlkRXF1YWxzKGxlZnQsIHJpZ2h0KTtcbiAgfVxuXG4gIGlmIChsZWZ0IGluc3RhbmNlb2YgRXJsYW5nVHlwZXMuQml0U3RyaW5nKSB7XG4gICAgcmV0dXJuIGJpdHN0cmluZ0VxdWFscyhsZWZ0LCByaWdodCk7XG4gIH1cblxuICBpZiAobGVmdCBpbnN0YW5jZW9mIEVybGFuZ1R5cGVzLlJlZmVyZW5jZSkge1xuICAgIHJldHVybiByZWZlcmVuY2VFcXVhbHMobGVmdCwgcmlnaHQpO1xuICB9XG5cbiAgaWYgKGxlZnQgaW5zdGFuY2VvZiBNYXApIHtcbiAgICByZXR1cm4gbWFwRXF1YWxzKGxlZnQsIHJpZ2h0KTtcbiAgfVxuXG4gIHJldHVybiBsZWZ0ID09PSByaWdodDtcbn1cblxuZnVuY3Rpb24gaXNfbm9uX3ByaW1pdGl2ZShrZXkpIHtcbiAgcmV0dXJuIChcbiAgICBDaGVja3MuaXNfYXJyYXkoa2V5KSB8fFxuICAgIENoZWNrcy5pc19tYXAoa2V5KSB8fFxuICAgIENoZWNrcy5pc19waWQoa2V5KSB8fFxuICAgIENoZWNrcy5pc19yZWZlcmVuY2Uoa2V5KSB8fFxuICAgIENoZWNrcy5pc19iaXRzdHJpbmcoa2V5KSB8fFxuICAgIENoZWNrcy5pc190dXBsZShrZXkpXG4gICk7XG59XG5cbmZ1bmN0aW9uIGhhcyhtYXAsIGtleSkge1xuICBpZiAoaXNfbm9uX3ByaW1pdGl2ZShrZXkpKSB7XG4gICAgZm9yIChjb25zdCBtYXBfa2V5IG9mIG1hcC5rZXlzKCkpIHtcbiAgICAgIGlmIChlcXVhbHMobWFwX2tleSwga2V5KSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gbWFwLmhhcyhrZXkpO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXkpIHtcbiAgaWYgKGlzX25vbl9wcmltaXRpdmUoa2V5KSkge1xuICAgIGZvciAoY29uc3QgbWFwX2tleSBvZiBtYXAua2V5cygpKSB7XG4gICAgICBpZiAoZXF1YWxzKG1hcF9rZXksIGtleSkpIHtcbiAgICAgICAgcmV0dXJuIG1hcC5nZXQobWFwX2tleSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gbWFwLmdldChrZXkpO1xufVxuXG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZ2V0LFxuICBoYXMsXG4gIGVxdWFscyxcbn1cbiIsIi8qIEBmbG93ICovXG5cbmltcG9ydCAqIGFzIENoZWNrcyBmcm9tICcuL2NoZWNrcyc7XG5pbXBvcnQgKiBhcyBUeXBlcyBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IGJ1aWxkTWF0Y2ggfSBmcm9tICcuL21hdGNoJztcbmltcG9ydCBFcmxhbmdUeXBlcyBmcm9tICdlcmxhbmctdHlwZXMnO1xuY29uc3QgQml0U3RyaW5nID0gRXJsYW5nVHlwZXMuQml0U3RyaW5nO1xuaW1wb3J0IFV0aWxzIGZyb20gJy4vdXRpbHMnXG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbih2YWx1ZSwgYXJncykge1xuICAgIGlmIChwYXR0ZXJuLm5hbWUgPT09IG51bGwpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIGlmIChwYXR0ZXJuLm5hbWUgIT09ICdfJykge1xuICAgICAgYXJncy5wdXNoKFR5cGVzLm5hbWVkVmFyaWFibGVSZXN1bHQocGF0dGVybi5uYW1lLCB2YWx1ZSkpO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwocGF0dGVybikge1xuICBjb25zdCBoZWFkTWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5oZWFkKTtcbiAgY29uc3QgdGFpbE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udGFpbCk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoaGVhZE1hdGNoZXMoaGVhZCwgYXJncykgJiYgdGFpbE1hdGNoZXModGFpbCwgYXJncykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24odmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbih2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVNYXAocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IG5ldyBNYXAoKTtcblxuICBjb25zdCBrZXlzID0gQXJyYXkuZnJvbShwYXR0ZXJuLmtleXMoKSk7XG5cbiAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICBtYXRjaGVzLnNldChrZXksIGJ1aWxkTWF0Y2gocGF0dGVybi5nZXQoa2V5KSkpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfbWFwKHZhbHVlKSB8fCBwYXR0ZXJuLnNpemUgPiB2YWx1ZS5zaXplKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgaWYgKCFVdGlscy5oYXModmFsdWUsIGtleSkgfHwgIVV0aWxzLmdldChtYXRjaGVzLCBrZXkpKFV0aWxzLmdldCh2YWx1ZSwga2V5KSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBjb25zdCBrZXlzID0gT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KFxuICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybilcbiAgKTtcblxuICBmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbih2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJpdFN0cmluZyhwYXR0ZXJuKSB7XG4gIGxldCBwYXR0ZXJuQml0U3RyaW5nID0gW107XG5cbiAgZm9yIChsZXQgYml0c3RyaW5nTWF0Y2hQYXJ0IG9mIHBhdHRlcm4udmFsdWVzKSB7XG4gICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICBsZXQgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcbiAgICAgIGZpbGxBcnJheShwYXR0ZXJuQml0U3RyaW5nLCBzaXplKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0dGVybkJpdFN0cmluZyA9IHBhdHRlcm5CaXRTdHJpbmcuY29uY2F0KFxuICAgICAgICBuZXcgQml0U3RyaW5nKGJpdHN0cmluZ01hdGNoUGFydCkudmFsdWVcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgbGV0IHBhdHRlcm5WYWx1ZXMgPSBwYXR0ZXJuLnZhbHVlcztcblxuICByZXR1cm4gZnVuY3Rpb24odmFsdWUsIGFyZ3MpIHtcbiAgICBsZXQgYnNWYWx1ZSA9IG51bGw7XG5cbiAgICBpZiAoIUNoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmICEodmFsdWUgaW5zdGFuY2VvZiBCaXRTdHJpbmcpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpKSB7XG4gICAgICBic1ZhbHVlID0gbmV3IEJpdFN0cmluZyhCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJzVmFsdWUgPSB2YWx1ZTtcbiAgICB9XG5cbiAgICBsZXQgYmVnaW5uaW5nSW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwYXR0ZXJuVmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgYml0c3RyaW5nTWF0Y2hQYXJ0ID0gcGF0dGVyblZhbHVlc1tpXTtcblxuICAgICAgaWYgKFxuICAgICAgICBDaGVja3MuaXNfdmFyaWFibGUoYml0c3RyaW5nTWF0Y2hQYXJ0LnZhbHVlKSAmJlxuICAgICAgICBiaXRzdHJpbmdNYXRjaFBhcnQudHlwZSA9PSAnYmluYXJ5JyAmJlxuICAgICAgICBiaXRzdHJpbmdNYXRjaFBhcnQuc2l6ZSA9PT0gdW5kZWZpbmVkICYmXG4gICAgICAgIGkgPCBwYXR0ZXJuVmFsdWVzLmxlbmd0aCAtIDFcbiAgICAgICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgJ2EgYmluYXJ5IGZpZWxkIHdpdGhvdXQgc2l6ZSBpcyBvbmx5IGFsbG93ZWQgYXQgdGhlIGVuZCBvZiBhIGJpbmFyeSBwYXR0ZXJuJ1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBsZXQgc2l6ZSA9IDA7XG4gICAgICBsZXQgYnNWYWx1ZUFycmF5UGFydCA9IFtdO1xuICAgICAgbGV0IHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQgPSBbXTtcbiAgICAgIHNpemUgPSBnZXRTaXplKGJpdHN0cmluZ01hdGNoUGFydC51bml0LCBiaXRzdHJpbmdNYXRjaFBhcnQuc2l6ZSk7XG5cbiAgICAgIGlmIChpID09PSBwYXR0ZXJuVmFsdWVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgYnNWYWx1ZUFycmF5UGFydCA9IGJzVmFsdWUudmFsdWUuc2xpY2UoYmVnaW5uaW5nSW5kZXgpO1xuICAgICAgICBwYXR0ZXJuQml0U3RyaW5nQXJyYXlQYXJ0ID0gcGF0dGVybkJpdFN0cmluZy5zbGljZShiZWdpbm5pbmdJbmRleCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBic1ZhbHVlQXJyYXlQYXJ0ID0gYnNWYWx1ZS52YWx1ZS5zbGljZShcbiAgICAgICAgICBiZWdpbm5pbmdJbmRleCxcbiAgICAgICAgICBiZWdpbm5pbmdJbmRleCArIHNpemVcbiAgICAgICAgKTtcbiAgICAgICAgcGF0dGVybkJpdFN0cmluZ0FycmF5UGFydCA9IHBhdHRlcm5CaXRTdHJpbmcuc2xpY2UoXG4gICAgICAgICAgYmVnaW5uaW5nSW5kZXgsXG4gICAgICAgICAgYmVnaW5uaW5nSW5kZXggKyBzaXplXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChDaGVja3MuaXNfdmFyaWFibGUoYml0c3RyaW5nTWF0Y2hQYXJ0LnZhbHVlKSkge1xuICAgICAgICBzd2l0Y2ggKGJpdHN0cmluZ01hdGNoUGFydC50eXBlKSB7XG4gICAgICAgICAgY2FzZSAnaW50ZWdlcic6XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgIGJpdHN0cmluZ01hdGNoUGFydC5hdHRyaWJ1dGVzICYmXG4gICAgICAgICAgICAgIGJpdHN0cmluZ01hdGNoUGFydC5hdHRyaWJ1dGVzLmluZGV4T2YoJ3NpZ25lZCcpICE9IC0xXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKG5ldyBJbnQ4QXJyYXkoW2JzVmFsdWVBcnJheVBhcnRbMF1dKVswXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBhcmdzLnB1c2gobmV3IFVpbnQ4QXJyYXkoW2JzVmFsdWVBcnJheVBhcnRbMF1dKVswXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgJ2Zsb2F0JzpcbiAgICAgICAgICAgIGlmIChzaXplID09PSA2NCkge1xuICAgICAgICAgICAgICBhcmdzLnB1c2goRmxvYXQ2NEFycmF5LmZyb20oYnNWYWx1ZUFycmF5UGFydClbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChzaXplID09PSAzMikge1xuICAgICAgICAgICAgICBhcmdzLnB1c2goRmxvYXQzMkFycmF5LmZyb20oYnNWYWx1ZUFycmF5UGFydClbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdiaXRzdHJpbmcnOlxuICAgICAgICAgICAgYXJncy5wdXNoKGNyZWF0ZUJpdFN0cmluZyhic1ZhbHVlQXJyYXlQYXJ0KSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgICAgICBhcmdzLnB1c2goXG4gICAgICAgICAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICd1dGY4JzpcbiAgICAgICAgICAgIGFyZ3MucHVzaChcbiAgICAgICAgICAgICAgU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDhBcnJheShic1ZhbHVlQXJyYXlQYXJ0KSlcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGNhc2UgJ3V0ZjE2JzpcbiAgICAgICAgICAgIGFyZ3MucHVzaChcbiAgICAgICAgICAgICAgU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDE2QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICd1dGYzMic6XG4gICAgICAgICAgICBhcmdzLnB1c2goXG4gICAgICAgICAgICAgIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQzMkFycmF5KGJzVmFsdWVBcnJheVBhcnQpKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICghYXJyYXlzRXF1YWwoYnNWYWx1ZUFycmF5UGFydCwgcGF0dGVybkJpdFN0cmluZ0FycmF5UGFydCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBiZWdpbm5pbmdJbmRleCA9IGJlZ2lubmluZ0luZGV4ICsgc2l6ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0U2l6ZSh1bml0LCBzaXplKSB7XG4gIHJldHVybiB1bml0ICogc2l6ZSAvIDg7XG59XG5cbmZ1bmN0aW9uIGFycmF5c0VxdWFsKGEsIGIpIHtcbiAgaWYgKGEgPT09IGIpIHJldHVybiB0cnVlO1xuICBpZiAoYSA9PSBudWxsIHx8IGIgPT0gbnVsbCkgcmV0dXJuIGZhbHNlO1xuICBpZiAoYS5sZW5ndGggIT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGEubGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoYVtpXSAhPT0gYltpXSkgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGZpbGxBcnJheShhcnIsIG51bSkge1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG51bTsgaSsrKSB7XG4gICAgYXJyLnB1c2goMCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlQml0U3RyaW5nKGFycikge1xuICBsZXQgaW50ZWdlclBhcnRzID0gYXJyLm1hcChlbGVtID0+IEJpdFN0cmluZy5pbnRlZ2VyKGVsZW0pKTtcbiAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uaW50ZWdlclBhcnRzKTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmV4cG9ydCB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGwsXG4gIHJlc29sdmVCaXRTdHJpbmcsXG4gIHJlc29sdmVNYXBcbn07XG4iLCJpbXBvcnQgKiBhcyBSZXNvbHZlcnMgZnJvbSAnLi9yZXNvbHZlcnMnO1xuaW1wb3J0IHtcbiAgVmFyaWFibGUsXG4gIFdpbGRjYXJkLFxuICBIZWFkVGFpbCxcbiAgQ2FwdHVyZSxcbiAgVHlwZSxcbiAgU3RhcnRzV2l0aCxcbiAgQm91bmQsXG4gIEJpdFN0cmluZ01hdGNoXG59IGZyb20gJy4vdHlwZXMnO1xuXG5jb25zdCBwYXR0ZXJuTWFwID0gbmV3IE1hcCgpO1xucGF0dGVybk1hcC5zZXQoVmFyaWFibGUucHJvdG90eXBlLCBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKTtcbnBhdHRlcm5NYXAuc2V0KFdpbGRjYXJkLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZCk7XG5wYXR0ZXJuTWFwLnNldChIZWFkVGFpbC5wcm90b3R5cGUsIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwpO1xucGF0dGVybk1hcC5zZXQoU3RhcnRzV2l0aC5wcm90b3R5cGUsIFJlc29sdmVycy5yZXNvbHZlU3RhcnRzV2l0aCk7XG5wYXR0ZXJuTWFwLnNldChDYXB0dXJlLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKTtcbnBhdHRlcm5NYXAuc2V0KEJvdW5kLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVCb3VuZCk7XG5wYXR0ZXJuTWFwLnNldChUeXBlLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVUeXBlKTtcbnBhdHRlcm5NYXAuc2V0KEJpdFN0cmluZ01hdGNoLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVCaXRTdHJpbmcpO1xucGF0dGVybk1hcC5zZXQoTnVtYmVyLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVOdW1iZXIpO1xucGF0dGVybk1hcC5zZXQoU3ltYm9sLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wpO1xucGF0dGVybk1hcC5zZXQoTWFwLnByb3RvdHlwZSwgUmVzb2x2ZXJzLnJlc29sdmVNYXApO1xucGF0dGVybk1hcC5zZXQoQXJyYXkucHJvdG90eXBlLCBSZXNvbHZlcnMucmVzb2x2ZUFycmF5KTtcbnBhdHRlcm5NYXAuc2V0KFN0cmluZy5wcm90b3R5cGUsIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKTtcbnBhdHRlcm5NYXAuc2V0KEJvb2xlYW4ucHJvdG90eXBlLCBSZXNvbHZlcnMucmVzb2x2ZUJvb2xlYW4pO1xucGF0dGVybk1hcC5zZXQoRnVuY3Rpb24ucHJvdG90eXBlLCBSZXNvbHZlcnMucmVzb2x2ZUZ1bmN0aW9uKTtcbnBhdHRlcm5NYXAuc2V0KE9iamVjdC5wcm90b3R5cGUsIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KTtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuICBpZiAocGF0dGVybiA9PT0gbnVsbCkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bGwocGF0dGVybik7XG4gIH1cblxuICBpZiAodHlwZW9mIHBhdHRlcm4gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAodHlwZW9mIHBhdHRlcm4gPT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGNvbnN0IHR5cGUgPSBwYXR0ZXJuLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgY29uc3QgcmVzb2x2ZXIgPSBwYXR0ZXJuTWFwLmdldCh0eXBlKTtcblxuICBpZiAocmVzb2x2ZXIpIHtcbiAgICByZXR1cm4gcmVzb2x2ZXIocGF0dGVybik7XG4gIH1cblxuICBpZiAodHlwZW9mIHBhdHRlcm4gPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuIiwiaW1wb3J0IHsgYnVpbGRNYXRjaCB9IGZyb20gJy4vbWF0Y2gnO1xuaW1wb3J0ICogYXMgVHlwZXMgZnJvbSAnLi90eXBlcyc7XG5cbmNvbnN0IEZVTkMgPSBTeW1ib2woKTtcblxuZXhwb3J0IGNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB7XG4gICAgICAgIGlmICh4ID09PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuICdudWxsJztcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgeCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICByZXR1cm4gJ3VuZGVmaW5lZCc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geC50b1N0cmluZygpO1xuICAgICAgfSk7XG5cbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBDbGF1c2Uge1xuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmFyaXR5ID0gcGF0dGVybi5sZW5ndGg7XG4gICAgdGhpcy5vcHRpb25hbHMgPSBnZXRPcHRpb25hbFZhbHVlcyhwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjbGF1c2UocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gbmV3IENsYXVzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHJhbXBvbGluZShmbikge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgbGV0IHJlcyA9IGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgd2hpbGUgKHJlcyBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXMgPSByZXMoKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNsYXVzZXMpIHtcbiAgY29uc3QgYXJpdGllcyA9IGdldEFyaXR5TWFwKGNsYXVzZXMpO1xuXG4gIHJldHVybiBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgbGV0IFtmdW5jVG9DYWxsLCBwYXJhbXNdID0gZmluZE1hdGNoaW5nRnVuY3Rpb24oYXJncywgYXJpdGllcyk7XG4gICAgcmV0dXJuIGZ1bmNUb0NhbGwuYXBwbHkodGhpcywgcGFyYW1zKTtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlZm1hdGNoZ2VuKC4uLmNsYXVzZXMpIHtcbiAgY29uc3QgYXJpdGllcyA9IGdldEFyaXR5TWFwKGNsYXVzZXMpO1xuXG4gIHJldHVybiBmdW5jdGlvbiooLi4uYXJncykge1xuICAgIGlmIChhcml0aWVzLmhhcyhhcmdzLmxlbmd0aCkpIHtcbiAgICAgIGNvbnN0IGFyaXR5Q2xhdXNlcyA9IGFyaXRpZXMuZ2V0KGFyZ3MubGVuZ3RoKTtcblxuICAgICAgbGV0IGZ1bmNUb0NhbGwgPSBudWxsO1xuICAgICAgbGV0IHBhcmFtcyA9IG51bGw7XG4gICAgICBmb3IgKGxldCBwcm9jZXNzZWRDbGF1c2Ugb2YgYXJpdHlDbGF1c2VzKSB7XG4gICAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgICAgYXJncyA9IGZpbGxJbk9wdGlvbmFsVmFsdWVzKFxuICAgICAgICAgIGFyZ3MsXG4gICAgICAgICAgcHJvY2Vzc2VkQ2xhdXNlLmFyaXR5LFxuICAgICAgICAgIHByb2Nlc3NlZENsYXVzZS5vcHRpb25hbHNcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBkb2VzTWF0Y2ggPSBwcm9jZXNzZWRDbGF1c2UucGF0dGVybihhcmdzLCByZXN1bHQpO1xuICAgICAgICBjb25zdCBbZmlsdGVyZWRSZXN1bHQsIGFsbE5hbWVzTWF0Y2hdID0gY2hlY2tOYW1lZFZhcmlhYmxlcyhyZXN1bHQpO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICBkb2VzTWF0Y2ggJiZcbiAgICAgICAgICBhbGxOYW1lc01hdGNoICYmXG4gICAgICAgICAgKHlpZWxkKiBwcm9jZXNzZWRDbGF1c2UuZ3VhcmQuYXBwbHkodGhpcywgZmlsdGVyZWRSZXN1bHQpKVxuICAgICAgICApIHtcbiAgICAgICAgICBmdW5jVG9DYWxsID0gcHJvY2Vzc2VkQ2xhdXNlLmZuO1xuICAgICAgICAgIHBhcmFtcyA9IGZpbHRlcmVkUmVzdWx0O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghZnVuY1RvQ2FsbCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdObyBtYXRjaCBmb3I6JywgYXJncyk7XG4gICAgICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4geWllbGQqIGZ1bmNUb0NhbGwuYXBwbHkodGhpcywgcGFyYW1zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignQXJpdHkgb2YnLCBhcmdzLmxlbmd0aCwgJ25vdCBmb3VuZC4gTm8gbWF0Y2ggZm9yOicsIGFyZ3MpO1xuICAgICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gICAgfVxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmbWF0Y2hHZW4oLi4uYXJncykge1xuICByZXR1cm4gZGVmbWF0Y2hnZW4oLi4uYXJncyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZtYXRjaEFzeW5jKC4uLmNsYXVzZXMpIHtcbiAgY29uc3QgYXJpdGllcyA9IGdldEFyaXR5TWFwKGNsYXVzZXMpO1xuXG4gIHJldHVybiBhc3luYyBmdW5jdGlvbiguLi5hcmdzKSB7XG4gICAgaWYgKGFyaXRpZXMuaGFzKGFyZ3MubGVuZ3RoKSkge1xuICAgICAgY29uc3QgYXJpdHlDbGF1c2VzID0gYXJpdGllcy5nZXQoYXJncy5sZW5ndGgpO1xuXG4gICAgICBsZXQgZnVuY1RvQ2FsbCA9IG51bGw7XG4gICAgICBsZXQgcGFyYW1zID0gbnVsbDtcbiAgICAgIGZvciAobGV0IHByb2Nlc3NlZENsYXVzZSBvZiBhcml0eUNsYXVzZXMpIHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgICBhcmdzID0gZmlsbEluT3B0aW9uYWxWYWx1ZXMoXG4gICAgICAgICAgYXJncyxcbiAgICAgICAgICBwcm9jZXNzZWRDbGF1c2UuYXJpdHksXG4gICAgICAgICAgcHJvY2Vzc2VkQ2xhdXNlLm9wdGlvbmFsc1xuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGRvZXNNYXRjaCA9IHByb2Nlc3NlZENsYXVzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCk7XG4gICAgICAgIGNvbnN0IFtmaWx0ZXJlZFJlc3VsdCwgYWxsTmFtZXNNYXRjaF0gPSBjaGVja05hbWVkVmFyaWFibGVzKHJlc3VsdCk7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgIGRvZXNNYXRjaCAmJlxuICAgICAgICAgIGFsbE5hbWVzTWF0Y2ggJiZcbiAgICAgICAgICAoYXdhaXQgcHJvY2Vzc2VkQ2xhdXNlLmd1YXJkLmFwcGx5KHRoaXMsIGZpbHRlcmVkUmVzdWx0KSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgZnVuY1RvQ2FsbCA9IHByb2Nlc3NlZENsYXVzZS5mbjtcbiAgICAgICAgICBwYXJhbXMgPSBmaWx0ZXJlZFJlc3VsdDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIWZ1bmNUb0NhbGwpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignTm8gbWF0Y2ggZm9yOicsIGFyZ3MpO1xuICAgICAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZ1bmNUb0NhbGwuYXBwbHkodGhpcywgcGFyYW1zKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignQXJpdHkgb2YnLCBhcmdzLmxlbmd0aCwgJ25vdCBmb3VuZC4gTm8gbWF0Y2ggZm9yOicsIGFyZ3MpO1xuICAgICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBmaW5kTWF0Y2hpbmdGdW5jdGlvbihhcmdzLCBhcml0aWVzKSB7XG4gIGlmIChhcml0aWVzLmhhcyhhcmdzLmxlbmd0aCkpIHtcbiAgICBjb25zdCBhcml0eUNsYXVzZXMgPSBhcml0aWVzLmdldChhcmdzLmxlbmd0aCk7XG5cbiAgICBsZXQgZnVuY1RvQ2FsbCA9IG51bGw7XG4gICAgbGV0IHBhcmFtcyA9IG51bGw7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2xhdXNlIG9mIGFyaXR5Q2xhdXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgYXJncyA9IGZpbGxJbk9wdGlvbmFsVmFsdWVzKFxuICAgICAgICBhcmdzLFxuICAgICAgICBwcm9jZXNzZWRDbGF1c2UuYXJpdHksXG4gICAgICAgIHByb2Nlc3NlZENsYXVzZS5vcHRpb25hbHNcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IGRvZXNNYXRjaCA9IHByb2Nlc3NlZENsYXVzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCk7XG4gICAgICBjb25zdCBbZmlsdGVyZWRSZXN1bHQsIGFsbE5hbWVzTWF0Y2hdID0gY2hlY2tOYW1lZFZhcmlhYmxlcyhyZXN1bHQpO1xuXG4gICAgICBpZiAoXG4gICAgICAgIGRvZXNNYXRjaCAmJlxuICAgICAgICBhbGxOYW1lc01hdGNoICYmXG4gICAgICAgIHByb2Nlc3NlZENsYXVzZS5ndWFyZC5hcHBseSh0aGlzLCBmaWx0ZXJlZFJlc3VsdClcbiAgICAgICkge1xuICAgICAgICBmdW5jVG9DYWxsID0gcHJvY2Vzc2VkQ2xhdXNlLmZuO1xuICAgICAgICBwYXJhbXMgPSBmaWx0ZXJlZFJlc3VsdDtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFmdW5jVG9DYWxsKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdObyBtYXRjaCBmb3I6JywgYXJncyk7XG4gICAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW2Z1bmNUb0NhbGwsIHBhcmFtc107XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcignQXJpdHkgb2YnLCBhcmdzLmxlbmd0aCwgJ25vdCBmb3VuZC4gTm8gbWF0Y2ggZm9yOicsIGFyZ3MpO1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldEFyaXR5TWFwKGNsYXVzZXMpIHtcbiAgbGV0IG1hcCA9IG5ldyBNYXAoKTtcblxuICBmb3IgKGNvbnN0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgY29uc3QgcmFuZ2UgPSBnZXRBcml0eVJhbmdlKGNsYXVzZSk7XG5cbiAgICBmb3IgKGNvbnN0IGFyaXR5IG9mIHJhbmdlKSB7XG4gICAgICBsZXQgYXJpdHlDbGF1c2VzID0gW107XG5cbiAgICAgIGlmIChtYXAuaGFzKGFyaXR5KSkge1xuICAgICAgICBhcml0eUNsYXVzZXMgPSBtYXAuZ2V0KGFyaXR5KTtcbiAgICAgIH1cblxuICAgICAgYXJpdHlDbGF1c2VzLnB1c2goY2xhdXNlKTtcbiAgICAgIG1hcC5zZXQoYXJpdHksIGFyaXR5Q2xhdXNlcyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1hcDtcbn1cblxuZnVuY3Rpb24gZ2V0QXJpdHlSYW5nZShjbGF1c2UpIHtcbiAgY29uc3QgbWluID0gY2xhdXNlLmFyaXR5IC0gY2xhdXNlLm9wdGlvbmFscy5sZW5ndGg7XG4gIGNvbnN0IG1heCA9IGNsYXVzZS5hcml0eTtcblxuICBsZXQgcmFuZ2UgPSBbbWluXTtcblxuICB3aGlsZSAocmFuZ2VbcmFuZ2UubGVuZ3RoIC0gMV0gIT0gbWF4KSB7XG4gICAgcmFuZ2UucHVzaChyYW5nZVtyYW5nZS5sZW5ndGggLSAxXSArIDEpO1xuICB9XG5cbiAgcmV0dXJuIHJhbmdlO1xufVxuXG5mdW5jdGlvbiBnZXRPcHRpb25hbFZhbHVlcyhwYXR0ZXJuKSB7XG4gIGxldCBvcHRpb25hbHMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm4ubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoXG4gICAgICBwYXR0ZXJuW2ldIGluc3RhbmNlb2YgVHlwZXMuVmFyaWFibGUgJiZcbiAgICAgIHBhdHRlcm5baV0uZGVmYXVsdF92YWx1ZSAhPSBTeW1ib2wuZm9yKCd0YWlsb3JlZC5ub192YWx1ZScpXG4gICAgKSB7XG4gICAgICBvcHRpb25hbHMucHVzaChbaSwgcGF0dGVybltpXS5kZWZhdWx0X3ZhbHVlXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9wdGlvbmFscztcbn1cblxuZnVuY3Rpb24gZmlsbEluT3B0aW9uYWxWYWx1ZXMoYXJncywgYXJpdHksIG9wdGlvbmFscykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IGFyaXR5IHx8IG9wdGlvbmFscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gYXJncztcbiAgfVxuXG4gIGlmIChhcmdzLmxlbmd0aCArIG9wdGlvbmFscy5sZW5ndGggPCBhcml0eSkge1xuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgbGV0IG51bWJlck9mT3B0aW9uYWxzVG9GaWxsID0gYXJpdHkgLSBhcmdzLmxlbmd0aDtcbiAgbGV0IG9wdGlvbmFsc1RvUmVtb3ZlID0gb3B0aW9uYWxzLmxlbmd0aCAtIG51bWJlck9mT3B0aW9uYWxzVG9GaWxsO1xuXG4gIGxldCBvcHRpb25hbHNUb1VzZSA9IG9wdGlvbmFscy5zbGljZShvcHRpb25hbHNUb1JlbW92ZSk7XG5cbiAgZm9yIChsZXQgW2luZGV4LCB2YWx1ZV0gb2Ygb3B0aW9uYWxzVG9Vc2UpIHtcbiAgICBhcmdzLnNwbGljZShpbmRleCwgMCwgdmFsdWUpO1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gYXJpdHkpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBhcmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBjb25zdCBkb2VzTWF0Y2ggPSBwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCk7XG4gIGNvbnN0IFtmaWx0ZXJlZFJlc3VsdCwgYWxsTmFtZXNNYXRjaF0gPSBjaGVja05hbWVkVmFyaWFibGVzKHJlc3VsdCk7XG5cbiAgaWYgKGRvZXNNYXRjaCAmJiBhbGxOYW1lc01hdGNoICYmIGd1YXJkLmFwcGx5KHRoaXMsIGZpbHRlcmVkUmVzdWx0KSkge1xuICAgIHJldHVybiBmaWx0ZXJlZFJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmVycm9yKCdObyBtYXRjaCBmb3I6JywgZXhwcik7XG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoZXhwcik7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uKiBtYXRjaF9nZW4oXG4gIHBhdHRlcm4sXG4gIGV4cHIsXG4gIGd1YXJkID0gZnVuY3Rpb24qICgpIHsgcmV0dXJuIHRydWUgfVxuKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBjb25zdCBkb2VzTWF0Y2ggPSBwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCk7XG4gIGNvbnN0IFtmaWx0ZXJlZFJlc3VsdCwgYWxsTmFtZXNNYXRjaF0gPSBjaGVja05hbWVkVmFyaWFibGVzKHJlc3VsdCk7XG4gIGNvbnN0IG1hdGNoZXMgPSBkb2VzTWF0Y2ggJiYgYWxsTmFtZXNNYXRjaDtcblxuICBpZiAobWF0Y2hlcyAmJiAoeWllbGQqIGd1YXJkLmFwcGx5KHRoaXMsIGZpbHRlcmVkUmVzdWx0KSkpIHtcbiAgICByZXR1cm4gZmlsdGVyZWRSZXN1bHQ7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcignTm8gbWF0Y2ggZm9yOicsIGV4cHIpO1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNoZWNrTmFtZWRWYXJpYWJsZXMocmVzdWx0cykge1xuICBjb25zdCBuYW1lc01hcCA9IHt9O1xuICBjb25zdCBmaWx0ZXJlZFJlc3VsdHMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHJlc3VsdHMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjdXJyZW50ID0gcmVzdWx0c1tpXTtcbiAgICBpZiAoY3VycmVudCBpbnN0YW5jZW9mIFR5cGVzLk5hbWVkVmFyaWFibGVSZXN1bHQpIHtcbiAgICAgIGlmIChuYW1lc01hcFtjdXJyZW50Lm5hbWVdICYmIG5hbWVzTWFwW2N1cnJlbnQubmFtZV0gIT09IGN1cnJlbnQudmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIFtyZXN1bHRzLCBmYWxzZV07XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBuYW1lc01hcFtjdXJyZW50Lm5hbWVdICYmXG4gICAgICAgIG5hbWVzTWFwW2N1cnJlbnQubmFtZV0gPT09IGN1cnJlbnQudmFsdWVcbiAgICAgICkge1xuICAgICAgICBmaWx0ZXJlZFJlc3VsdHMucHVzaChjdXJyZW50LnZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5hbWVzTWFwW2N1cnJlbnQubmFtZV0gPSBjdXJyZW50LnZhbHVlO1xuICAgICAgICBmaWx0ZXJlZFJlc3VsdHMucHVzaChjdXJyZW50LnZhbHVlKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZmlsdGVyZWRSZXN1bHRzLnB1c2goY3VycmVudCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFtmaWx0ZXJlZFJlc3VsdHMsIHRydWVdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2hfb3JfZGVmYXVsdChcbiAgcGF0dGVybixcbiAgZXhwcixcbiAgZ3VhcmQgPSAoKSA9PiB0cnVlLFxuICBkZWZhdWx0X3ZhbHVlID0gbnVsbFxuKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBjb25zdCBkb2VzTWF0Y2ggPSBwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCk7XG4gIGNvbnN0IFtmaWx0ZXJlZFJlc3VsdCwgYWxsTmFtZXNNYXRjaF0gPSBjaGVja05hbWVkVmFyaWFibGVzKHJlc3VsdCk7XG5cbiAgaWYgKGRvZXNNYXRjaCAmJiBhbGxOYW1lc01hdGNoICYmIGd1YXJkLmFwcGx5KHRoaXMsIGZpbHRlcmVkUmVzdWx0KSkge1xuICAgIHJldHVybiBmaWx0ZXJlZFJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZGVmYXVsdF92YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24qIG1hdGNoX29yX2RlZmF1bHRfZ2VuKFxuICBwYXR0ZXJuLFxuICBleHByLFxuICBndWFyZCA9IGZ1bmN0aW9uKiAoKSB7IHJldHVybiB0cnVlIH0sXG4gIGRlZmF1bHRfdmFsdWUgPSBudWxsXG4pIHtcbiAgbGV0IHJlc3VsdCA9IFtdO1xuICBsZXQgcHJvY2Vzc2VkUGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gIGNvbnN0IGRvZXNNYXRjaCA9IHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KTtcbiAgY29uc3QgW2ZpbHRlcmVkUmVzdWx0LCBhbGxOYW1lc01hdGNoXSA9IGNoZWNrTmFtZWRWYXJpYWJsZXMocmVzdWx0KTtcbiAgY29uc3QgbWF0Y2hlcyA9IGRvZXNNYXRjaCAmJiBhbGxOYW1lc01hdGNoO1xuXG4gIGlmIChtYXRjaGVzICYmICh5aWVsZCogZ3VhcmQuYXBwbHkodGhpcywgZmlsdGVyZWRSZXN1bHQpKSkge1xuICAgIHJldHVybiBmaWx0ZXJlZFJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZGVmYXVsdF92YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbWF0Y2hfb3JfZGVmYXVsdF9hc3luYyhcbiAgcGF0dGVybixcbiAgZXhwcixcbiAgZ3VhcmQgPSBhc3luYyAoKSA9PiB0cnVlLFxuICBkZWZhdWx0X3ZhbHVlID0gbnVsbFxuKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBjb25zdCBkb2VzTWF0Y2ggPSBwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCk7XG4gIGNvbnN0IFtmaWx0ZXJlZFJlc3VsdCwgYWxsTmFtZXNNYXRjaF0gPSBjaGVja05hbWVkVmFyaWFibGVzKHJlc3VsdCk7XG4gIGNvbnN0IG1hdGNoZXMgPSBkb2VzTWF0Y2ggJiYgYWxsTmFtZXNNYXRjaDtcblxuICBpZiAobWF0Y2hlcyAmJiAoYXdhaXQgZ3VhcmQuYXBwbHkodGhpcywgZmlsdGVyZWRSZXN1bHQpKSkge1xuICAgIHJldHVybiBmaWx0ZXJlZFJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZGVmYXVsdF92YWx1ZTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgbWF0Y2hfb3JfZGVmYXVsdCB9IGZyb20gXCIuL2RlZm1hdGNoXCI7XG5pbXBvcnQgRXJsYW5nVHlwZXMgZnJvbSBcImVybGFuZy10eXBlc1wiO1xuXG5jb25zdCBOT19NQVRDSCA9IFN5bWJvbCgpO1xuXG5leHBvcnQgZnVuY3Rpb24gYml0c3RyaW5nX2dlbmVyYXRvcihwYXR0ZXJuLCBiaXRzdHJpbmcpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIGxldCByZXR1cm5SZXN1bHQgPSBbXTtcbiAgICBsZXQgYnNTbGljZSA9IGJpdHN0cmluZy5zbGljZSgwLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKTtcbiAgICBsZXQgaSA9IDE7XG5cbiAgICB3aGlsZSAoYnNTbGljZS5ieXRlX3NpemUgPT0gcGF0dGVybi5ieXRlX3NpemUoKSkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gbWF0Y2hfb3JfZGVmYXVsdChwYXR0ZXJuLCBic1NsaWNlLCAoKSA9PiB0cnVlLCBOT19NQVRDSCk7XG5cbiAgICAgIGlmIChyZXN1bHQgIT0gTk9fTUFUQ0gpIHtcbiAgICAgICAgY29uc3QgW3ZhbHVlXSA9IHJlc3VsdDtcbiAgICAgICAgcmV0dXJuUmVzdWx0LnB1c2gocmVzdWx0KTtcbiAgICAgIH1cblxuICAgICAgYnNTbGljZSA9IGJpdHN0cmluZy5zbGljZShcbiAgICAgICAgcGF0dGVybi5ieXRlX3NpemUoKSAqIGksXG4gICAgICAgIHBhdHRlcm4uYnl0ZV9zaXplKCkgKiAoaSArIDEpXG4gICAgICApO1xuXG4gICAgICBpKys7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldHVyblJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RfZ2VuZXJhdG9yKHBhdHRlcm4sIGxpc3QpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIGxldCByZXR1cm5SZXN1bHQgPSBbXTtcbiAgICBmb3IgKGxldCBpIG9mIGxpc3QpIHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IG1hdGNoX29yX2RlZmF1bHQocGF0dGVybiwgaSwgKCkgPT4gdHJ1ZSwgTk9fTUFUQ0gpO1xuICAgICAgaWYgKHJlc3VsdCAhPSBOT19NQVRDSCkge1xuICAgICAgICBjb25zdCBbdmFsdWVdID0gcmVzdWx0O1xuICAgICAgICByZXR1cm5SZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldHVyblJlc3VsdDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RfY29tcHJlaGVuc2lvbihleHByZXNzaW9uLCBnZW5lcmF0b3JzKSB7XG4gIGNvbnN0IGdlbmVyYXRlZFZhbHVlcyA9IHJ1bl9nZW5lcmF0b3JzKGdlbmVyYXRvcnMucG9wKCkoKSwgZ2VuZXJhdG9ycyk7XG5cbiAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gIGZvciAobGV0IHZhbHVlIG9mIGdlbmVyYXRlZFZhbHVlcykge1xuICAgIGlmIChleHByZXNzaW9uLmd1YXJkLmFwcGx5KHRoaXMsIHZhbHVlKSkge1xuICAgICAgcmVzdWx0LnB1c2goZXhwcmVzc2lvbi5mbi5hcHBseSh0aGlzLCB2YWx1ZSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIHJ1bl9nZW5lcmF0b3JzKGdlbmVyYXRvciwgZ2VuZXJhdG9ycykge1xuICBpZiAoZ2VuZXJhdG9ycy5sZW5ndGggPT0gMCkge1xuICAgIHJldHVybiBnZW5lcmF0b3IubWFwKHggPT4ge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoeCkpIHtcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gW3hdO1xuICAgICAgfVxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IGxpc3QgPSBnZW5lcmF0b3JzLnBvcCgpO1xuXG4gICAgbGV0IG5leHRfZ2VuID0gW107XG4gICAgZm9yIChsZXQgaiBvZiBsaXN0KCkpIHtcbiAgICAgIGZvciAobGV0IGkgb2YgZ2VuZXJhdG9yKSB7XG4gICAgICAgIG5leHRfZ2VuLnB1c2goW2pdLmNvbmNhdChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJ1bl9nZW5lcmF0b3JzKG5leHRfZ2VuLCBnZW5lcmF0b3JzKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gYml0c3RyaW5nX2NvbXByZWhlbnNpb24oZXhwcmVzc2lvbiwgZ2VuZXJhdG9ycykge1xuICBjb25zdCBnZW5lcmF0ZWRWYWx1ZXMgPSBydW5fZ2VuZXJhdG9ycyhnZW5lcmF0b3JzLnBvcCgpKCksIGdlbmVyYXRvcnMpO1xuXG4gIGxldCByZXN1bHQgPSBbXTtcblxuICBmb3IgKGxldCB2YWx1ZSBvZiBnZW5lcmF0ZWRWYWx1ZXMpIHtcbiAgICBpZiAoZXhwcmVzc2lvbi5ndWFyZC5hcHBseSh0aGlzLCB2YWx1ZSkpIHtcbiAgICAgIHJlc3VsdC5wdXNoKGV4cHJlc3Npb24uZm4uYXBwbHkodGhpcywgdmFsdWUpKTtcbiAgICB9XG4gIH1cblxuICByZXN1bHQgPSByZXN1bHQubWFwKHggPT4gRXJsYW5nVHlwZXMuQml0U3RyaW5nLmludGVnZXIoeCkpO1xuICByZXR1cm4gbmV3IEVybGFuZ1R5cGVzLkJpdFN0cmluZyguLi5yZXN1bHQpO1xufVxuIiwiaW1wb3J0IHtcbiAgZGVmbWF0Y2gsXG4gIG1hdGNoLFxuICBtYXRjaF9nZW4sXG4gIE1hdGNoRXJyb3IsXG4gIENsYXVzZSxcbiAgY2xhdXNlLFxuICBtYXRjaF9vcl9kZWZhdWx0LFxuICBtYXRjaF9vcl9kZWZhdWx0X2dlbixcbiAgbWF0Y2hfb3JfZGVmYXVsdF9hc3luYyxcbiAgZGVmbWF0Y2hnZW4sXG4gIGRlZm1hdGNoR2VuLFxuICBkZWZtYXRjaEFzeW5jXG59IGZyb20gJy4vdGFpbG9yZWQvZGVmbWF0Y2gnO1xuaW1wb3J0IHtcbiAgdmFyaWFibGUsXG4gIHdpbGRjYXJkLFxuICBzdGFydHNXaXRoLFxuICBjYXB0dXJlLFxuICBoZWFkVGFpbCxcbiAgdHlwZSxcbiAgYm91bmQsXG4gIGJpdFN0cmluZ01hdGNoXG59IGZyb20gJy4vdGFpbG9yZWQvdHlwZXMnO1xuXG5pbXBvcnQge1xuICBsaXN0X2dlbmVyYXRvcixcbiAgbGlzdF9jb21wcmVoZW5zaW9uLFxuICBiaXRzdHJpbmdfZ2VuZXJhdG9yLFxuICBiaXRzdHJpbmdfY29tcHJlaGVuc2lvblxufSBmcm9tICcuL3RhaWxvcmVkL2NvbXByZWhlbnNpb25zJztcblxuZXhwb3J0IGRlZmF1bHQge1xuICBkZWZtYXRjaCxcbiAgbWF0Y2gsXG4gIG1hdGNoX2dlbixcbiAgTWF0Y2hFcnJvcixcbiAgdmFyaWFibGUsXG4gIHdpbGRjYXJkLFxuICBzdGFydHNXaXRoLFxuICBjYXB0dXJlLFxuICBoZWFkVGFpbCxcbiAgdHlwZSxcbiAgYm91bmQsXG4gIENsYXVzZSxcbiAgY2xhdXNlLFxuICBiaXRTdHJpbmdNYXRjaCxcbiAgbWF0Y2hfb3JfZGVmYXVsdCxcbiAgbWF0Y2hfb3JfZGVmYXVsdF9nZW4sXG4gIG1hdGNoX29yX2RlZmF1bHRfYXN5bmMsXG4gIGRlZm1hdGNoZ2VuLFxuICBsaXN0X2NvbXByZWhlbnNpb24sXG4gIGxpc3RfZ2VuZXJhdG9yLFxuICBiaXRzdHJpbmdfZ2VuZXJhdG9yLFxuICBiaXRzdHJpbmdfY29tcHJlaGVuc2lvbixcbiAgZGVmbWF0Y2hHZW4sXG4gIGRlZm1hdGNoQXN5bmNcbn07XG4iXSwibmFtZXMiOlsiVmFyaWFibGUiLCJuYW1lIiwiZGVmYXVsdF92YWx1ZSIsIlN5bWJvbCIsImZvciIsIldpbGRjYXJkIiwiU3RhcnRzV2l0aCIsInByZWZpeCIsIkNhcHR1cmUiLCJ2YWx1ZSIsIkhlYWRUYWlsIiwiaGVhZCIsInRhaWwiLCJUeXBlIiwidHlwZSIsIm9ialBhdHRlcm4iLCJCb3VuZCIsIkJpdFN0cmluZ01hdGNoIiwidmFsdWVzIiwibGVuZ3RoIiwiYnl0ZV9zaXplIiwicyIsInZhbCIsInVuaXQiLCJzaXplIiwiaW5kZXgiLCJnZXRWYWx1ZSIsIk5hbWVkVmFyaWFibGVSZXN1bHQiLCJ2YXJpYWJsZSIsIndpbGRjYXJkIiwic3RhcnRzV2l0aCIsImNhcHR1cmUiLCJoZWFkVGFpbCIsImJvdW5kIiwiYml0U3RyaW5nTWF0Y2giLCJuYW1lZFZhcmlhYmxlUmVzdWx0IiwiaXNfbnVtYmVyIiwiaXNfc3RyaW5nIiwiaXNfYm9vbGVhbiIsImlzX3N5bWJvbCIsImlzX29iamVjdCIsImlzX3ZhcmlhYmxlIiwiaXNfYml0c3RyaW5nIiwiaXNfbnVsbCIsImlzX2FycmF5IiwiQXJyYXkiLCJpc0FycmF5IiwiaXNfZnVuY3Rpb24iLCJGdW5jdGlvbiIsImlzX21hcCIsIk1hcCIsImlzX3BpZCIsIkVybGFuZ1R5cGVzIiwiUElEIiwiaXNfdHVwbGUiLCJUdXBsZSIsImlzX3JlZmVyZW5jZSIsIlJlZmVyZW5jZSIsImFycmF5RXF1YWxzIiwibGVmdCIsInJpZ2h0IiwiaSIsImVxdWFscyIsInR1cGxlRXF1YWxzIiwiYml0c3RyaW5nRXF1YWxzIiwiQml0U3RyaW5nIiwicGlkRXF1YWxzIiwiaWQiLCJyZWZlcmVuY2VFcXVhbHMiLCJtYXBFcXVhbHMiLCJsZWZ0RW50cmllcyIsImZyb20iLCJlbnRyaWVzIiwicmlnaHRFbnRyaWVzIiwiaXNfbm9uX3ByaW1pdGl2ZSIsImtleSIsIkNoZWNrcyIsImhhcyIsIm1hcCIsIm1hcF9rZXkiLCJrZXlzIiwiZ2V0IiwicmVzb2x2ZVN5bWJvbCIsInBhdHRlcm4iLCJyZXNvbHZlU3RyaW5nIiwicmVzb2x2ZU51bWJlciIsInJlc29sdmVCb29sZWFuIiwicmVzb2x2ZUZ1bmN0aW9uIiwicmVzb2x2ZU51bGwiLCJyZXNvbHZlQm91bmQiLCJhcmdzIiwicmVzb2x2ZVdpbGRjYXJkIiwicmVzb2x2ZVZhcmlhYmxlIiwicHVzaCIsIlR5cGVzIiwicmVzb2x2ZUhlYWRUYWlsIiwiaGVhZE1hdGNoZXMiLCJidWlsZE1hdGNoIiwidGFpbE1hdGNoZXMiLCJzbGljZSIsInJlc29sdmVDYXB0dXJlIiwibWF0Y2hlcyIsInJlc29sdmVTdGFydHNXaXRoIiwic3Vic3RyaW5nIiwicmVzb2x2ZVR5cGUiLCJyZXNvbHZlQXJyYXkiLCJ4IiwiZXZlcnkiLCJ2IiwicmVzb2x2ZU1hcCIsInNldCIsIlV0aWxzIiwicmVzb2x2ZU9iamVjdCIsIk9iamVjdCIsImNvbmNhdCIsImdldE93blByb3BlcnR5U3ltYm9scyIsInJlc29sdmVCaXRTdHJpbmciLCJwYXR0ZXJuQml0U3RyaW5nIiwiYml0c3RyaW5nTWF0Y2hQYXJ0IiwiZ2V0U2l6ZSIsInBhdHRlcm5WYWx1ZXMiLCJic1ZhbHVlIiwiYmluYXJ5IiwiYmVnaW5uaW5nSW5kZXgiLCJ1bmRlZmluZWQiLCJFcnJvciIsImJzVmFsdWVBcnJheVBhcnQiLCJwYXR0ZXJuQml0U3RyaW5nQXJyYXlQYXJ0IiwiYXR0cmlidXRlcyIsImluZGV4T2YiLCJJbnQ4QXJyYXkiLCJVaW50OEFycmF5IiwiRmxvYXQ2NEFycmF5IiwiRmxvYXQzMkFycmF5IiwiY3JlYXRlQml0U3RyaW5nIiwiU3RyaW5nIiwiZnJvbUNoYXJDb2RlIiwiYXBwbHkiLCJVaW50MTZBcnJheSIsIlVpbnQzMkFycmF5IiwiYXJyYXlzRXF1YWwiLCJhIiwiYiIsImZpbGxBcnJheSIsImFyciIsIm51bSIsImludGVnZXJQYXJ0cyIsImVsZW0iLCJpbnRlZ2VyIiwicmVzb2x2ZU5vTWF0Y2giLCJwYXR0ZXJuTWFwIiwicHJvdG90eXBlIiwiUmVzb2x2ZXJzIiwiTnVtYmVyIiwiQm9vbGVhbiIsImNvbnN0cnVjdG9yIiwicmVzb2x2ZXIiLCJNYXRjaEVycm9yIiwiYXJnIiwibWVzc2FnZSIsInRvU3RyaW5nIiwibWFwcGVkVmFsdWVzIiwiQ2xhdXNlIiwiZm4iLCJndWFyZCIsImFyaXR5Iiwib3B0aW9uYWxzIiwiZ2V0T3B0aW9uYWxWYWx1ZXMiLCJjbGF1c2UiLCJkZWZtYXRjaCIsImNsYXVzZXMiLCJhcml0aWVzIiwiZ2V0QXJpdHlNYXAiLCJmdW5jVG9DYWxsIiwicGFyYW1zIiwiZmluZE1hdGNoaW5nRnVuY3Rpb24iLCJkZWZtYXRjaGdlbiIsImFyaXR5Q2xhdXNlcyIsInByb2Nlc3NlZENsYXVzZSIsInJlc3VsdCIsImZpbGxJbk9wdGlvbmFsVmFsdWVzIiwiZG9lc01hdGNoIiwiZmlsdGVyZWRSZXN1bHQiLCJhbGxOYW1lc01hdGNoIiwiY2hlY2tOYW1lZFZhcmlhYmxlcyIsImVycm9yIiwiZGVmbWF0Y2hHZW4iLCJkZWZtYXRjaEFzeW5jIiwicmFuZ2UiLCJnZXRBcml0eVJhbmdlIiwibWluIiwibWF4IiwibnVtYmVyT2ZPcHRpb25hbHNUb0ZpbGwiLCJvcHRpb25hbHNUb1JlbW92ZSIsIm9wdGlvbmFsc1RvVXNlIiwic3BsaWNlIiwibWF0Y2giLCJleHByIiwicHJvY2Vzc2VkUGF0dGVybiIsIm1hdGNoX2dlbiIsInJlc3VsdHMiLCJuYW1lc01hcCIsImZpbHRlcmVkUmVzdWx0cyIsImN1cnJlbnQiLCJtYXRjaF9vcl9kZWZhdWx0IiwibWF0Y2hfb3JfZGVmYXVsdF9nZW4iLCJtYXRjaF9vcl9kZWZhdWx0X2FzeW5jIiwiTk9fTUFUQ0giLCJiaXRzdHJpbmdfZ2VuZXJhdG9yIiwiYml0c3RyaW5nIiwicmV0dXJuUmVzdWx0IiwiYnNTbGljZSIsImxpc3RfZ2VuZXJhdG9yIiwibGlzdCIsImxpc3RfY29tcHJlaGVuc2lvbiIsImV4cHJlc3Npb24iLCJnZW5lcmF0b3JzIiwiZ2VuZXJhdGVkVmFsdWVzIiwicnVuX2dlbmVyYXRvcnMiLCJwb3AiLCJnZW5lcmF0b3IiLCJuZXh0X2dlbiIsImoiLCJiaXRzdHJpbmdfY29tcHJlaGVuc2lvbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7O0FBRUEsTUFBTUEsUUFBTixDQUFlO2NBQ0RDLE9BQU8sSUFBbkIsRUFBeUJDLGdCQUFnQkMsT0FBT0MsR0FBUCxDQUFXLG1CQUFYLENBQXpDLEVBQTBFO1NBQ25FSCxJQUFMLEdBQVlBLElBQVo7U0FDS0MsYUFBTCxHQUFxQkEsYUFBckI7Ozs7QUFJSixNQUFNRyxRQUFOLENBQWU7Z0JB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 1139 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tailored", 3 | "version": "2.7.5", 4 | "description": "Pattern matching library", 5 | "main": "lib/tailored.js", 6 | "jsnext:main": "src/index.js", 7 | "scripts": { 8 | "build": "rollup -c rollup.config.js", 9 | "test": "mocha test --recursive --compilers js:babel-register" 10 | }, 11 | "keywords": ["pattern-matching", "functional"], 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/elixirscript/tailored.git" 15 | }, 16 | "author": "Bryan Joseph ", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "babel-core": "^6.25.0", 20 | "babel-preset-env": "^1.6.0", 21 | "babel-register": "^6.24.1", 22 | "chai": "^4.1.0", 23 | "mocha": "^6.0.2", 24 | "rollup": "^1.12.4", 25 | "rollup-plugin-babel": "^3.0.7" 26 | }, 27 | "dependencies": { 28 | "erlang-types": "^1.0.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import { rollup } from 'rollup'; 2 | import babel from 'rollup-plugin-babel'; 3 | 4 | export default { 5 | entry: 'src/index.js', 6 | dest: 'lib/tailored.js', 7 | sourceMap: 'inline', 8 | format: 'cjs', 9 | plugins: [ 10 | babel({ 11 | babelrc: false, 12 | presets: [ 13 | [ 14 | 'env', 15 | { 16 | targets: { 17 | node: 'current', 18 | }, 19 | modules: false, 20 | loose: true, 21 | }, 22 | ], 23 | ], 24 | }), 25 | ], 26 | external: ['erlang-types'], 27 | }; 28 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | defmatch, 3 | match, 4 | match_gen, 5 | MatchError, 6 | Clause, 7 | clause, 8 | match_or_default, 9 | match_or_default_gen, 10 | match_or_default_async, 11 | defmatchgen, 12 | defmatchGen, 13 | defmatchAsync 14 | } from './tailored/defmatch'; 15 | import { 16 | variable, 17 | wildcard, 18 | startsWith, 19 | capture, 20 | headTail, 21 | type, 22 | bound, 23 | bitStringMatch 24 | } from './tailored/types'; 25 | 26 | import { 27 | list_generator, 28 | list_comprehension, 29 | bitstring_generator, 30 | bitstring_comprehension 31 | } from './tailored/comprehensions'; 32 | 33 | export default { 34 | defmatch, 35 | match, 36 | match_gen, 37 | MatchError, 38 | variable, 39 | wildcard, 40 | startsWith, 41 | capture, 42 | headTail, 43 | type, 44 | bound, 45 | Clause, 46 | clause, 47 | bitStringMatch, 48 | match_or_default, 49 | match_or_default_gen, 50 | match_or_default_async, 51 | defmatchgen, 52 | list_comprehension, 53 | list_generator, 54 | bitstring_generator, 55 | bitstring_comprehension, 56 | defmatchGen, 57 | defmatchAsync 58 | }; 59 | -------------------------------------------------------------------------------- /src/tailored/checks.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import { 4 | Variable, 5 | Wildcard, 6 | HeadTail, 7 | Capture, 8 | Type, 9 | StartsWith, 10 | Bound, 11 | BitStringMatch 12 | } from './types'; 13 | 14 | import ErlangTypes from 'erlang-types'; 15 | 16 | function is_number(value) { 17 | return typeof value === 'number'; 18 | } 19 | 20 | function is_string(value) { 21 | return typeof value === 'string'; 22 | } 23 | 24 | function is_boolean(value) { 25 | return typeof value === 'boolean'; 26 | } 27 | 28 | function is_symbol(value) { 29 | return typeof value === 'symbol'; 30 | } 31 | 32 | function is_undefined(value) { 33 | return typeof value === 'undefined'; 34 | } 35 | 36 | function is_object(value) { 37 | return typeof value === 'object'; 38 | } 39 | 40 | function is_variable(value) { 41 | return value instanceof Variable; 42 | } 43 | 44 | function is_wildcard(value) { 45 | return value instanceof Wildcard; 46 | } 47 | 48 | function is_headTail(value) { 49 | return value instanceof HeadTail; 50 | } 51 | 52 | function is_capture(value) { 53 | return value instanceof Capture; 54 | } 55 | 56 | function is_type(value) { 57 | return value instanceof Type; 58 | } 59 | 60 | function is_startsWith(value) { 61 | return value instanceof StartsWith; 62 | } 63 | 64 | function is_bound(value) { 65 | return value instanceof Bound; 66 | } 67 | 68 | function is_bitstring(value) { 69 | return value instanceof BitStringMatch; 70 | } 71 | 72 | function is_null(value) { 73 | return value === null; 74 | } 75 | 76 | function is_array(value) { 77 | return Array.isArray(value); 78 | } 79 | 80 | function is_function(value) { 81 | return typeof value === 'function' || value instanceof Function; 82 | } 83 | 84 | function is_map(value) { 85 | return value instanceof Map; 86 | } 87 | 88 | function is_pid(value) { 89 | return value instanceof ErlangTypes.PID; 90 | } 91 | 92 | function is_tuple(value) { 93 | return value instanceof ErlangTypes.Tuple; 94 | } 95 | 96 | function is_reference(value) { 97 | return value instanceof ErlangTypes.Reference; 98 | } 99 | 100 | export { 101 | is_number, 102 | is_string, 103 | is_boolean, 104 | is_symbol, 105 | is_null, 106 | is_undefined, 107 | is_function, 108 | is_variable, 109 | is_wildcard, 110 | is_headTail, 111 | is_capture, 112 | is_type, 113 | is_startsWith, 114 | is_bound, 115 | is_object, 116 | is_array, 117 | is_bitstring, 118 | is_map, 119 | is_tuple, 120 | is_pid, 121 | is_reference, 122 | }; 123 | -------------------------------------------------------------------------------- /src/tailored/comprehensions.js: -------------------------------------------------------------------------------- 1 | import { match_or_default } from "./defmatch"; 2 | import ErlangTypes from "erlang-types"; 3 | 4 | const NO_MATCH = Symbol(); 5 | 6 | export function bitstring_generator(pattern, bitstring) { 7 | return function() { 8 | let returnResult = []; 9 | let bsSlice = bitstring.slice(0, pattern.byte_size()); 10 | let i = 1; 11 | 12 | while (bsSlice.byte_size == pattern.byte_size()) { 13 | const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); 14 | 15 | if (result != NO_MATCH) { 16 | const [value] = result; 17 | returnResult.push(result); 18 | } 19 | 20 | bsSlice = bitstring.slice( 21 | pattern.byte_size() * i, 22 | pattern.byte_size() * (i + 1) 23 | ); 24 | 25 | i++; 26 | } 27 | 28 | return returnResult; 29 | }; 30 | } 31 | 32 | export function list_generator(pattern, list) { 33 | return function() { 34 | let returnResult = []; 35 | for (let i of list) { 36 | const result = match_or_default(pattern, i, () => true, NO_MATCH); 37 | if (result != NO_MATCH) { 38 | const [value] = result; 39 | returnResult.push(value); 40 | } 41 | } 42 | 43 | return returnResult; 44 | }; 45 | } 46 | 47 | export function list_comprehension(expression, generators) { 48 | const generatedValues = run_generators(generators.pop()(), generators); 49 | 50 | let result = []; 51 | 52 | for (let value of generatedValues) { 53 | if (expression.guard.apply(this, value)) { 54 | result.push(expression.fn.apply(this, value)); 55 | } 56 | } 57 | 58 | return result; 59 | } 60 | 61 | function run_generators(generator, generators) { 62 | if (generators.length == 0) { 63 | return generator.map(x => { 64 | if (Array.isArray(x)) { 65 | return x; 66 | } else { 67 | return [x]; 68 | } 69 | }); 70 | } else { 71 | const list = generators.pop(); 72 | 73 | let next_gen = []; 74 | for (let j of list()) { 75 | for (let i of generator) { 76 | next_gen.push([j].concat(i)); 77 | } 78 | } 79 | 80 | return run_generators(next_gen, generators); 81 | } 82 | } 83 | 84 | export function bitstring_comprehension(expression, generators) { 85 | const generatedValues = run_generators(generators.pop()(), generators); 86 | 87 | let result = []; 88 | 89 | for (let value of generatedValues) { 90 | if (expression.guard.apply(this, value)) { 91 | result.push(expression.fn.apply(this, value)); 92 | } 93 | } 94 | 95 | result = result.map(x => ErlangTypes.BitString.integer(x)); 96 | return new ErlangTypes.BitString(...result); 97 | } 98 | -------------------------------------------------------------------------------- /src/tailored/defmatch.js: -------------------------------------------------------------------------------- 1 | import { buildMatch } from './match'; 2 | import * as Types from './types'; 3 | 4 | const FUNC = Symbol(); 5 | 6 | export class MatchError extends Error { 7 | constructor(arg) { 8 | super(); 9 | 10 | if (typeof arg === 'symbol') { 11 | this.message = 'No match for: ' + arg.toString(); 12 | } else if (Array.isArray(arg)) { 13 | let mappedValues = arg.map(x => { 14 | if (x === null) { 15 | return 'null'; 16 | } else if (typeof x === 'undefined') { 17 | return 'undefined'; 18 | } 19 | 20 | return x.toString(); 21 | }); 22 | 23 | this.message = 'No match for: ' + mappedValues; 24 | } else { 25 | this.message = 'No match for: ' + arg; 26 | } 27 | 28 | this.name = this.constructor.name; 29 | } 30 | } 31 | 32 | export class Clause { 33 | constructor(pattern, fn, guard = () => true) { 34 | this.pattern = buildMatch(pattern); 35 | this.arity = pattern.length; 36 | this.optionals = getOptionalValues(pattern); 37 | this.fn = fn; 38 | this.guard = guard; 39 | } 40 | } 41 | 42 | export function clause(pattern, fn, guard = () => true) { 43 | return new Clause(pattern, fn, guard); 44 | } 45 | 46 | export function trampoline(fn) { 47 | return function() { 48 | let res = fn.apply(this, arguments); 49 | while (res instanceof Function) { 50 | res = res(); 51 | } 52 | return res; 53 | }; 54 | } 55 | 56 | export function defmatch(...clauses) { 57 | const arities = getArityMap(clauses); 58 | 59 | return function(...args) { 60 | let [funcToCall, params] = findMatchingFunction(args, arities); 61 | return funcToCall.apply(this, params); 62 | }; 63 | } 64 | 65 | export function defmatchgen(...clauses) { 66 | const arities = getArityMap(clauses); 67 | 68 | return function*(...args) { 69 | if (arities.has(args.length)) { 70 | const arityClauses = arities.get(args.length); 71 | 72 | let funcToCall = null; 73 | let params = null; 74 | for (let processedClause of arityClauses) { 75 | let result = []; 76 | args = fillInOptionalValues( 77 | args, 78 | processedClause.arity, 79 | processedClause.optionals 80 | ); 81 | 82 | const doesMatch = processedClause.pattern(args, result); 83 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 84 | 85 | if ( 86 | doesMatch && 87 | allNamesMatch && 88 | (yield* processedClause.guard.apply(this, filteredResult)) 89 | ) { 90 | funcToCall = processedClause.fn; 91 | params = filteredResult; 92 | break; 93 | } 94 | } 95 | 96 | if (!funcToCall) { 97 | console.error('No match for:', args); 98 | throw new MatchError(args); 99 | } 100 | 101 | return yield* funcToCall.apply(this, params); 102 | } else { 103 | console.error('Arity of', args.length, 'not found. No match for:', args); 104 | throw new MatchError(args); 105 | } 106 | }; 107 | } 108 | 109 | export function defmatchGen(...args) { 110 | return defmatchgen(...args); 111 | } 112 | 113 | export function defmatchAsync(...clauses) { 114 | const arities = getArityMap(clauses); 115 | 116 | return async function(...args) { 117 | if (arities.has(args.length)) { 118 | const arityClauses = arities.get(args.length); 119 | 120 | let funcToCall = null; 121 | let params = null; 122 | for (let processedClause of arityClauses) { 123 | let result = []; 124 | args = fillInOptionalValues( 125 | args, 126 | processedClause.arity, 127 | processedClause.optionals 128 | ); 129 | 130 | const doesMatch = processedClause.pattern(args, result); 131 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 132 | 133 | if ( 134 | doesMatch && 135 | allNamesMatch && 136 | (await processedClause.guard.apply(this, filteredResult)) 137 | ) { 138 | funcToCall = processedClause.fn; 139 | params = filteredResult; 140 | break; 141 | } 142 | } 143 | 144 | if (!funcToCall) { 145 | console.error('No match for:', args); 146 | throw new MatchError(args); 147 | } 148 | 149 | return funcToCall.apply(this, params); 150 | } else { 151 | console.error('Arity of', args.length, 'not found. No match for:', args); 152 | throw new MatchError(args); 153 | } 154 | }; 155 | } 156 | 157 | function findMatchingFunction(args, arities) { 158 | if (arities.has(args.length)) { 159 | const arityClauses = arities.get(args.length); 160 | 161 | let funcToCall = null; 162 | let params = null; 163 | for (let processedClause of arityClauses) { 164 | let result = []; 165 | args = fillInOptionalValues( 166 | args, 167 | processedClause.arity, 168 | processedClause.optionals 169 | ); 170 | 171 | const doesMatch = processedClause.pattern(args, result); 172 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 173 | 174 | if ( 175 | doesMatch && 176 | allNamesMatch && 177 | processedClause.guard.apply(this, filteredResult) 178 | ) { 179 | funcToCall = processedClause.fn; 180 | params = filteredResult; 181 | break; 182 | } 183 | } 184 | 185 | if (!funcToCall) { 186 | console.error('No match for:', args); 187 | throw new MatchError(args); 188 | } 189 | 190 | return [funcToCall, params]; 191 | } else { 192 | console.error('Arity of', args.length, 'not found. No match for:', args); 193 | throw new MatchError(args); 194 | } 195 | } 196 | 197 | function getArityMap(clauses) { 198 | let map = new Map(); 199 | 200 | for (const clause of clauses) { 201 | const range = getArityRange(clause); 202 | 203 | for (const arity of range) { 204 | let arityClauses = []; 205 | 206 | if (map.has(arity)) { 207 | arityClauses = map.get(arity); 208 | } 209 | 210 | arityClauses.push(clause); 211 | map.set(arity, arityClauses); 212 | } 213 | } 214 | 215 | return map; 216 | } 217 | 218 | function getArityRange(clause) { 219 | const min = clause.arity - clause.optionals.length; 220 | const max = clause.arity; 221 | 222 | let range = [min]; 223 | 224 | while (range[range.length - 1] != max) { 225 | range.push(range[range.length - 1] + 1); 226 | } 227 | 228 | return range; 229 | } 230 | 231 | function getOptionalValues(pattern) { 232 | let optionals = []; 233 | 234 | for (let i = 0; i < pattern.length; i++) { 235 | if ( 236 | pattern[i] instanceof Types.Variable && 237 | pattern[i].default_value != Symbol.for('tailored.no_value') 238 | ) { 239 | optionals.push([i, pattern[i].default_value]); 240 | } 241 | } 242 | 243 | return optionals; 244 | } 245 | 246 | function fillInOptionalValues(args, arity, optionals) { 247 | if (args.length === arity || optionals.length === 0) { 248 | return args; 249 | } 250 | 251 | if (args.length + optionals.length < arity) { 252 | return args; 253 | } 254 | 255 | let numberOfOptionalsToFill = arity - args.length; 256 | let optionalsToRemove = optionals.length - numberOfOptionalsToFill; 257 | 258 | let optionalsToUse = optionals.slice(optionalsToRemove); 259 | 260 | for (let [index, value] of optionalsToUse) { 261 | args.splice(index, 0, value); 262 | if (args.length === arity) { 263 | break; 264 | } 265 | } 266 | 267 | return args; 268 | } 269 | 270 | export function match(pattern, expr, guard = () => true) { 271 | let result = []; 272 | let processedPattern = buildMatch(pattern); 273 | const doesMatch = processedPattern(expr, result); 274 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 275 | 276 | if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { 277 | return filteredResult; 278 | } else { 279 | console.error('No match for:', expr); 280 | throw new MatchError(expr); 281 | } 282 | } 283 | 284 | export function* match_gen( 285 | pattern, 286 | expr, 287 | guard = function* () { return true } 288 | ) { 289 | let result = []; 290 | let processedPattern = buildMatch(pattern); 291 | const doesMatch = processedPattern(expr, result); 292 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 293 | const matches = doesMatch && allNamesMatch; 294 | 295 | if (matches && (yield* guard.apply(this, filteredResult))) { 296 | return filteredResult; 297 | } else { 298 | console.error('No match for:', expr); 299 | throw new MatchError(expr); 300 | } 301 | } 302 | 303 | function checkNamedVariables(results) { 304 | const namesMap = {}; 305 | const filteredResults = []; 306 | 307 | for (let i = 0; i < results.length; i++) { 308 | const current = results[i]; 309 | if (current instanceof Types.NamedVariableResult) { 310 | if (namesMap[current.name] && namesMap[current.name] !== current.value) { 311 | return [results, false]; 312 | } else if ( 313 | namesMap[current.name] && 314 | namesMap[current.name] === current.value 315 | ) { 316 | filteredResults.push(current.value); 317 | } else { 318 | namesMap[current.name] = current.value; 319 | filteredResults.push(current.value); 320 | } 321 | } else { 322 | filteredResults.push(current); 323 | } 324 | } 325 | 326 | return [filteredResults, true]; 327 | } 328 | 329 | export function match_or_default( 330 | pattern, 331 | expr, 332 | guard = () => true, 333 | default_value = null 334 | ) { 335 | let result = []; 336 | let processedPattern = buildMatch(pattern); 337 | const doesMatch = processedPattern(expr, result); 338 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 339 | 340 | if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { 341 | return filteredResult; 342 | } else { 343 | return default_value; 344 | } 345 | } 346 | 347 | export function* match_or_default_gen( 348 | pattern, 349 | expr, 350 | guard = function* () { return true }, 351 | default_value = null 352 | ) { 353 | let result = []; 354 | let processedPattern = buildMatch(pattern); 355 | const doesMatch = processedPattern(expr, result); 356 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 357 | const matches = doesMatch && allNamesMatch; 358 | 359 | if (matches && (yield* guard.apply(this, filteredResult))) { 360 | return filteredResult; 361 | } else { 362 | return default_value; 363 | } 364 | } 365 | 366 | export async function match_or_default_async( 367 | pattern, 368 | expr, 369 | guard = async () => true, 370 | default_value = null 371 | ) { 372 | let result = []; 373 | let processedPattern = buildMatch(pattern); 374 | const doesMatch = processedPattern(expr, result); 375 | const [filteredResult, allNamesMatch] = checkNamedVariables(result); 376 | const matches = doesMatch && allNamesMatch; 377 | 378 | if (matches && (await guard.apply(this, filteredResult))) { 379 | return filteredResult; 380 | } else { 381 | return default_value; 382 | } 383 | } 384 | -------------------------------------------------------------------------------- /src/tailored/match.js: -------------------------------------------------------------------------------- 1 | import * as Resolvers from './resolvers'; 2 | import { 3 | Variable, 4 | Wildcard, 5 | HeadTail, 6 | Capture, 7 | Type, 8 | StartsWith, 9 | Bound, 10 | BitStringMatch 11 | } from './types'; 12 | 13 | const patternMap = new Map(); 14 | patternMap.set(Variable.prototype, Resolvers.resolveVariable); 15 | patternMap.set(Wildcard.prototype, Resolvers.resolveWildcard); 16 | patternMap.set(HeadTail.prototype, Resolvers.resolveHeadTail); 17 | patternMap.set(StartsWith.prototype, Resolvers.resolveStartsWith); 18 | patternMap.set(Capture.prototype, Resolvers.resolveCapture); 19 | patternMap.set(Bound.prototype, Resolvers.resolveBound); 20 | patternMap.set(Type.prototype, Resolvers.resolveType); 21 | patternMap.set(BitStringMatch.prototype, Resolvers.resolveBitString); 22 | patternMap.set(Number.prototype, Resolvers.resolveNumber); 23 | patternMap.set(Symbol.prototype, Resolvers.resolveSymbol); 24 | patternMap.set(Map.prototype, Resolvers.resolveMap); 25 | patternMap.set(Array.prototype, Resolvers.resolveArray); 26 | patternMap.set(String.prototype, Resolvers.resolveString); 27 | patternMap.set(Boolean.prototype, Resolvers.resolveBoolean); 28 | patternMap.set(Function.prototype, Resolvers.resolveFunction); 29 | patternMap.set(Object.prototype, Resolvers.resolveObject); 30 | 31 | export function buildMatch(pattern) { 32 | if (pattern === null) { 33 | return Resolvers.resolveNull(pattern); 34 | } 35 | 36 | if (typeof pattern === 'undefined') { 37 | return Resolvers.resolveWildcard(pattern); 38 | } 39 | 40 | if (typeof pattern === 'function') { 41 | return Resolvers.resolveFunction(pattern); 42 | } 43 | 44 | const type = pattern.constructor.prototype; 45 | const resolver = patternMap.get(type); 46 | 47 | if (resolver) { 48 | return resolver(pattern); 49 | } 50 | 51 | if (typeof pattern === 'object') { 52 | return Resolvers.resolveObject(pattern); 53 | } 54 | 55 | return Resolvers.resolveNoMatch(); 56 | } 57 | -------------------------------------------------------------------------------- /src/tailored/resolvers.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import * as Checks from './checks'; 4 | import * as Types from './types'; 5 | import { buildMatch } from './match'; 6 | import ErlangTypes from 'erlang-types'; 7 | const BitString = ErlangTypes.BitString; 8 | import Utils from './utils' 9 | 10 | function resolveSymbol(pattern) { 11 | return function(value) { 12 | return Checks.is_symbol(value) && value === pattern; 13 | }; 14 | } 15 | 16 | function resolveString(pattern) { 17 | return function(value) { 18 | return Checks.is_string(value) && value === pattern; 19 | }; 20 | } 21 | 22 | function resolveNumber(pattern) { 23 | return function(value) { 24 | return Checks.is_number(value) && value === pattern; 25 | }; 26 | } 27 | 28 | function resolveBoolean(pattern) { 29 | return function(value) { 30 | return Checks.is_boolean(value) && value === pattern; 31 | }; 32 | } 33 | 34 | function resolveFunction(pattern) { 35 | return function(value) { 36 | return Checks.is_function(value) && value === pattern; 37 | }; 38 | } 39 | 40 | function resolveNull(pattern) { 41 | return function(value) { 42 | return Checks.is_null(value); 43 | }; 44 | } 45 | 46 | function resolveBound(pattern) { 47 | return function(value, args) { 48 | if (typeof value === typeof pattern.value && value === pattern.value) { 49 | return true; 50 | } 51 | 52 | return false; 53 | }; 54 | } 55 | 56 | function resolveWildcard() { 57 | return function() { 58 | return true; 59 | }; 60 | } 61 | 62 | function resolveVariable(pattern) { 63 | return function(value, args) { 64 | if (pattern.name === null) { 65 | args.push(value); 66 | } else if (pattern.name !== '_') { 67 | args.push(Types.namedVariableResult(pattern.name, value)); 68 | } 69 | 70 | return true; 71 | }; 72 | } 73 | 74 | function resolveHeadTail(pattern) { 75 | const headMatches = buildMatch(pattern.head); 76 | const tailMatches = buildMatch(pattern.tail); 77 | 78 | return function(value, args) { 79 | if (!Checks.is_array(value) || value.length === 0) { 80 | return false; 81 | } 82 | 83 | const head = value[0]; 84 | const tail = value.slice(1); 85 | 86 | if (headMatches(head, args) && tailMatches(tail, args)) { 87 | return true; 88 | } 89 | 90 | return false; 91 | }; 92 | } 93 | 94 | function resolveCapture(pattern) { 95 | const matches = buildMatch(pattern.value); 96 | 97 | return function(value, args) { 98 | if (matches(value, args)) { 99 | args.push(value); 100 | return true; 101 | } 102 | 103 | return false; 104 | }; 105 | } 106 | 107 | function resolveStartsWith(pattern) { 108 | const prefix = pattern.prefix; 109 | 110 | return function(value, args) { 111 | if (Checks.is_string(value) && value.startsWith(prefix)) { 112 | args.push(value.substring(prefix.length)); 113 | return true; 114 | } 115 | 116 | return false; 117 | }; 118 | } 119 | 120 | function resolveType(pattern) { 121 | return function(value, args) { 122 | if (value instanceof pattern.type) { 123 | const matches = buildMatch(pattern.objPattern); 124 | return matches(value, args); 125 | } 126 | 127 | return false; 128 | }; 129 | } 130 | 131 | function resolveArray(pattern) { 132 | const matches = pattern.map(x => buildMatch(x)); 133 | 134 | return function(value, args) { 135 | if (!Checks.is_array(value) || value.length != pattern.length) { 136 | return false; 137 | } 138 | 139 | return value.every(function(v, i) { 140 | return matches[i](value[i], args); 141 | }); 142 | }; 143 | } 144 | 145 | function resolveMap(pattern) { 146 | let matches = new Map(); 147 | 148 | const keys = Array.from(pattern.keys()); 149 | 150 | for (let key of keys) { 151 | matches.set(key, buildMatch(pattern.get(key))); 152 | } 153 | 154 | return function(value, args) { 155 | if (!Checks.is_map(value) || pattern.size > value.size) { 156 | return false; 157 | } 158 | 159 | for (const key of keys) { 160 | if (!Utils.has(value, key) || !Utils.get(matches, key)(Utils.get(value, key), args)) { 161 | return false; 162 | } 163 | } 164 | 165 | return true; 166 | }; 167 | } 168 | 169 | function resolveObject(pattern) { 170 | let matches = {}; 171 | 172 | const keys = Object.keys(pattern).concat( 173 | Object.getOwnPropertySymbols(pattern) 174 | ); 175 | 176 | for (let key of keys) { 177 | matches[key] = buildMatch(pattern[key]); 178 | } 179 | 180 | return function(value, args) { 181 | if (!Checks.is_object(value) || pattern.length > value.length) { 182 | return false; 183 | } 184 | 185 | for (let key of keys) { 186 | if (!(key in value) || !matches[key](value[key], args)) { 187 | return false; 188 | } 189 | } 190 | 191 | return true; 192 | }; 193 | } 194 | 195 | function resolveBitString(pattern) { 196 | let patternBitString = []; 197 | 198 | for (let bitstringMatchPart of pattern.values) { 199 | if (Checks.is_variable(bitstringMatchPart.value)) { 200 | let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); 201 | fillArray(patternBitString, size); 202 | } else { 203 | patternBitString = patternBitString.concat( 204 | new BitString(bitstringMatchPart).value 205 | ); 206 | } 207 | } 208 | 209 | let patternValues = pattern.values; 210 | 211 | return function(value, args) { 212 | let bsValue = null; 213 | 214 | if (!Checks.is_string(value) && !(value instanceof BitString)) { 215 | return false; 216 | } 217 | 218 | if (Checks.is_string(value)) { 219 | bsValue = new BitString(BitString.binary(value)); 220 | } else { 221 | bsValue = value; 222 | } 223 | 224 | let beginningIndex = 0; 225 | 226 | for (let i = 0; i < patternValues.length; i++) { 227 | let bitstringMatchPart = patternValues[i]; 228 | 229 | if ( 230 | Checks.is_variable(bitstringMatchPart.value) && 231 | bitstringMatchPart.type == 'binary' && 232 | bitstringMatchPart.size === undefined && 233 | i < patternValues.length - 1 234 | ) { 235 | throw new Error( 236 | 'a binary field without size is only allowed at the end of a binary pattern' 237 | ); 238 | } 239 | 240 | let size = 0; 241 | let bsValueArrayPart = []; 242 | let patternBitStringArrayPart = []; 243 | size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); 244 | 245 | if (i === patternValues.length - 1) { 246 | bsValueArrayPart = bsValue.value.slice(beginningIndex); 247 | patternBitStringArrayPart = patternBitString.slice(beginningIndex); 248 | } else { 249 | bsValueArrayPart = bsValue.value.slice( 250 | beginningIndex, 251 | beginningIndex + size 252 | ); 253 | patternBitStringArrayPart = patternBitString.slice( 254 | beginningIndex, 255 | beginningIndex + size 256 | ); 257 | } 258 | 259 | if (Checks.is_variable(bitstringMatchPart.value)) { 260 | switch (bitstringMatchPart.type) { 261 | case 'integer': 262 | if ( 263 | bitstringMatchPart.attributes && 264 | bitstringMatchPart.attributes.indexOf('signed') != -1 265 | ) { 266 | args.push(new Int8Array([bsValueArrayPart[0]])[0]); 267 | } else { 268 | args.push(new Uint8Array([bsValueArrayPart[0]])[0]); 269 | } 270 | break; 271 | 272 | case 'float': 273 | if (size === 64) { 274 | args.push(Float64Array.from(bsValueArrayPart)[0]); 275 | } else if (size === 32) { 276 | args.push(Float32Array.from(bsValueArrayPart)[0]); 277 | } else { 278 | return false; 279 | } 280 | break; 281 | 282 | case 'bitstring': 283 | args.push(createBitString(bsValueArrayPart)); 284 | break; 285 | 286 | case 'binary': 287 | args.push( 288 | String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart)) 289 | ); 290 | break; 291 | 292 | case 'utf8': 293 | args.push( 294 | String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart)) 295 | ); 296 | break; 297 | 298 | case 'utf16': 299 | args.push( 300 | String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart)) 301 | ); 302 | break; 303 | 304 | case 'utf32': 305 | args.push( 306 | String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart)) 307 | ); 308 | break; 309 | 310 | default: 311 | return false; 312 | } 313 | } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { 314 | return false; 315 | } 316 | 317 | beginningIndex = beginningIndex + size; 318 | } 319 | 320 | return true; 321 | }; 322 | } 323 | 324 | function getSize(unit, size) { 325 | return unit * size / 8; 326 | } 327 | 328 | function arraysEqual(a, b) { 329 | if (a === b) return true; 330 | if (a == null || b == null) return false; 331 | if (a.length != b.length) return false; 332 | 333 | for (var i = 0; i < a.length; ++i) { 334 | if (a[i] !== b[i]) return false; 335 | } 336 | 337 | return true; 338 | } 339 | 340 | function fillArray(arr, num) { 341 | for (let i = 0; i < num; i++) { 342 | arr.push(0); 343 | } 344 | } 345 | 346 | function createBitString(arr) { 347 | let integerParts = arr.map(elem => BitString.integer(elem)); 348 | return new BitString(...integerParts); 349 | } 350 | 351 | function resolveNoMatch() { 352 | return function() { 353 | return false; 354 | }; 355 | } 356 | 357 | export { 358 | resolveBound, 359 | resolveWildcard, 360 | resolveVariable, 361 | resolveHeadTail, 362 | resolveCapture, 363 | resolveStartsWith, 364 | resolveType, 365 | resolveArray, 366 | resolveObject, 367 | resolveNoMatch, 368 | resolveSymbol, 369 | resolveString, 370 | resolveNumber, 371 | resolveBoolean, 372 | resolveFunction, 373 | resolveNull, 374 | resolveBitString, 375 | resolveMap 376 | }; 377 | -------------------------------------------------------------------------------- /src/tailored/types.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | class Variable { 4 | constructor(name = null, default_value = Symbol.for('tailored.no_value')) { 5 | this.name = name; 6 | this.default_value = default_value; 7 | } 8 | } 9 | 10 | class Wildcard { 11 | constructor() {} 12 | } 13 | 14 | class StartsWith { 15 | constructor(prefix) { 16 | this.prefix = prefix; 17 | } 18 | } 19 | 20 | class Capture { 21 | constructor(value) { 22 | this.value = value; 23 | } 24 | } 25 | 26 | class HeadTail { 27 | constructor(head, tail) { 28 | this.head = head; 29 | this.tail = tail; 30 | } 31 | } 32 | 33 | class Type { 34 | constructor(type, objPattern = {}) { 35 | this.type = type; 36 | this.objPattern = objPattern; 37 | } 38 | } 39 | 40 | class Bound { 41 | constructor(value) { 42 | this.value = value; 43 | } 44 | } 45 | 46 | class BitStringMatch { 47 | constructor(...values) { 48 | this.values = values; 49 | } 50 | 51 | length() { 52 | return values.length; 53 | } 54 | 55 | bit_size() { 56 | return this.byte_size() * 8; 57 | } 58 | 59 | byte_size() { 60 | let s = 0; 61 | 62 | for (let val of this.values) { 63 | s = s + val.unit * val.size / 8; 64 | } 65 | 66 | return s; 67 | } 68 | 69 | getValue(index) { 70 | return this.values(index); 71 | } 72 | 73 | getSizeOfValue(index) { 74 | let val = this.getValue(index); 75 | return val.unit * val.size; 76 | } 77 | 78 | getTypeOfValue(index) { 79 | return this.getValue(index).type; 80 | } 81 | } 82 | 83 | class NamedVariableResult { 84 | constructor(name, value) { 85 | this.name = name; 86 | this.value = value; 87 | } 88 | } 89 | 90 | function variable( 91 | name = null, 92 | default_value = Symbol.for('tailored.no_value') 93 | ) { 94 | return new Variable(name, default_value); 95 | } 96 | 97 | function wildcard() { 98 | return new Wildcard(); 99 | } 100 | 101 | function startsWith(prefix) { 102 | return new StartsWith(prefix); 103 | } 104 | 105 | function capture(value) { 106 | return new Capture(value); 107 | } 108 | 109 | function headTail(head, tail) { 110 | return new HeadTail(head, tail); 111 | } 112 | 113 | function type(type, objPattern = {}) { 114 | return new Type(type, objPattern); 115 | } 116 | 117 | function bound(value) { 118 | return new Bound(value); 119 | } 120 | 121 | function bitStringMatch(...values) { 122 | return new BitStringMatch(...values); 123 | } 124 | 125 | function namedVariableResult(name, value) { 126 | return new NamedVariableResult(name, value); 127 | } 128 | 129 | export { 130 | Variable, 131 | Wildcard, 132 | StartsWith, 133 | Capture, 134 | HeadTail, 135 | Type, 136 | Bound, 137 | BitStringMatch, 138 | variable, 139 | wildcard, 140 | startsWith, 141 | capture, 142 | headTail, 143 | type, 144 | bound, 145 | bitStringMatch, 146 | NamedVariableResult, 147 | namedVariableResult 148 | }; 149 | -------------------------------------------------------------------------------- /src/tailored/utils.js: -------------------------------------------------------------------------------- 1 | import * as Checks from './checks'; 2 | import ErlangTypes from 'erlang-types'; 3 | 4 | function arrayEquals(left, right) { 5 | if (!Array.isArray(right)) { 6 | return false; 7 | } 8 | 9 | if (left.length !== right.length) { 10 | return false; 11 | } 12 | 13 | for (let i = 0; i < left.length; i++) { 14 | if (equals(left[i], right[i]) === false) { 15 | return false; 16 | } 17 | } 18 | 19 | return true; 20 | } 21 | 22 | function tupleEquals(left, right) { 23 | if (right instanceof ErlangTypes.Tuple === false) { 24 | return false; 25 | } 26 | 27 | if (left.length !== right.length) { 28 | return false; 29 | } 30 | 31 | return arrayEquals(left.values, right.values); 32 | } 33 | 34 | function bitstringEquals(left, right) { 35 | if (right instanceof ErlangTypes.BitString === false) { 36 | return false; 37 | } 38 | 39 | if (left.length !== right.length) { 40 | return false; 41 | } 42 | 43 | return arrayEquals(left.value, right.value); 44 | } 45 | 46 | function pidEquals(left, right) { 47 | if (right instanceof ErlangTypes.PID === false) { 48 | return false; 49 | } 50 | 51 | return left.id === right.id; 52 | } 53 | 54 | function referenceEquals(left, right) { 55 | if (right instanceof ErlangTypes.Reference === false) { 56 | return false; 57 | } 58 | 59 | return left.id === right.id; 60 | } 61 | 62 | function mapEquals(left, right) { 63 | if (right instanceof Map === false) { 64 | return false; 65 | } 66 | 67 | const leftEntries = Array.from(left.entries()); 68 | const rightEntries = Array.from(right.entries()); 69 | 70 | return arrayEquals(leftEntries, rightEntries); 71 | } 72 | 73 | function equals(left, right) { 74 | if (Array.isArray(left)) { 75 | return arrayEquals(left, right); 76 | } 77 | 78 | if (left instanceof ErlangTypes.Tuple) { 79 | return tupleEquals(left, right); 80 | } 81 | 82 | if (left instanceof ErlangTypes.PID) { 83 | return pidEquals(left, right); 84 | } 85 | 86 | if (left instanceof ErlangTypes.BitString) { 87 | return bitstringEquals(left, right); 88 | } 89 | 90 | if (left instanceof ErlangTypes.Reference) { 91 | return referenceEquals(left, right); 92 | } 93 | 94 | if (left instanceof Map) { 95 | return mapEquals(left, right); 96 | } 97 | 98 | return left === right; 99 | } 100 | 101 | function is_non_primitive(key) { 102 | return ( 103 | Checks.is_array(key) || 104 | Checks.is_map(key) || 105 | Checks.is_pid(key) || 106 | Checks.is_reference(key) || 107 | Checks.is_bitstring(key) || 108 | Checks.is_tuple(key) 109 | ); 110 | } 111 | 112 | function has(map, key) { 113 | if (is_non_primitive(key)) { 114 | for (const map_key of map.keys()) { 115 | if (equals(map_key, key)) { 116 | return true; 117 | } 118 | } 119 | 120 | return false; 121 | } 122 | 123 | return map.has(key); 124 | } 125 | 126 | function get(map, key) { 127 | if (is_non_primitive(key)) { 128 | for (const map_key of map.keys()) { 129 | if (equals(map_key, key)) { 130 | return map.get(map_key); 131 | } 132 | } 133 | 134 | return null; 135 | } 136 | 137 | return map.get(key); 138 | } 139 | 140 | 141 | export default { 142 | get, 143 | has, 144 | equals, 145 | } 146 | -------------------------------------------------------------------------------- /test/comprehension.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import chai from 'chai'; 4 | var expect = chai.expect; 5 | 6 | import Tailored from '../src/index.js'; 7 | import ErlangTypes from 'erlang-types'; 8 | const Tuple = ErlangTypes.Tuple; 9 | const BitString = ErlangTypes.BitString; 10 | 11 | const _ = Tailored.wildcard(); 12 | const $ = Tailored.variable(); 13 | 14 | describe('list generator', () => { 15 | it('must work on simple case', () => { 16 | let gen = Tailored.list_generator($, [1, 2, 3, 4]); 17 | 18 | let result = []; 19 | 20 | for (let a of gen()) { 21 | result.push(a); 22 | } 23 | 24 | expect(result).to.eql([1, 2, 3, 4]); 25 | }); 26 | 27 | it('must only result matching values', () => { 28 | let gen = Tailored.list_generator( 29 | Tailored.capture(Tailored.type(Tuple, { values: [1, 2, 3] })), 30 | [new Tuple(1, 2, 3), 2, 3, 4] 31 | ); 32 | 33 | let result = []; 34 | 35 | for (let a of gen()) { 36 | result.push(a); 37 | } 38 | 39 | expect(result).to.eql([new Tuple(1, 2, 3)]); 40 | }); 41 | }); 42 | 43 | describe('list comprehension', () => { 44 | it('must work on simple case', () => { 45 | let gen = Tailored.list_generator($, [1, 2, 3, 4]); 46 | let comp = Tailored.list_comprehension(Tailored.clause([$], x => x), [gen]); 47 | 48 | expect(comp).to.eql([1, 2, 3, 4]); 49 | }); 50 | 51 | it('must work on two generators', () => { 52 | let gen = Tailored.list_generator($, [1, 2]); 53 | let gen2 = Tailored.list_generator($, [3, 4]); 54 | let comp = Tailored.list_comprehension( 55 | Tailored.clause([$, $], (x, y) => x * y), 56 | [gen, gen2] 57 | ); 58 | 59 | expect(comp).to.eql([3, 4, 6, 8]); 60 | }); 61 | 62 | it('must work on three generators', () => { 63 | let gen = Tailored.list_generator($, [1, 2]); 64 | let gen2 = Tailored.list_generator($, [3, 4]); 65 | let gen3 = Tailored.list_generator($, [5, 6]); 66 | 67 | let comp = Tailored.list_comprehension( 68 | Tailored.clause([$, $, $], (x, y, z) => x * y * z), 69 | [gen, gen2, gen3] 70 | ); 71 | 72 | expect(comp).to.eql([15, 18, 20, 24, 30, 36, 40, 48]); 73 | }); 74 | 75 | it('must work with guards', () => { 76 | let gen = Tailored.list_generator($, [1, 2]); 77 | let gen2 = Tailored.list_generator($, [3, 4]); 78 | let comp = Tailored.list_comprehension( 79 | Tailored.clause([$, $], (x, y) => x * y, x => x > 1), 80 | [gen, gen2] 81 | ); 82 | 83 | expect(comp).to.eql([6, 8]); 84 | }); 85 | }); 86 | 87 | describe('binary comprehension', () => { 88 | it('must work on simple case', () => { 89 | let gen = Tailored.bitstring_generator( 90 | Tailored.bitStringMatch(BitString.integer({ value: $ })), 91 | new BitString( 92 | BitString.integer(1), 93 | BitString.integer(2), 94 | BitString.integer(3) 95 | ) 96 | ); 97 | let comp = Tailored.bitstring_comprehension( 98 | Tailored.clause( 99 | [Tailored.bitStringMatch(BitString.integer({ value: $ }))], 100 | x => x * 2 101 | ), 102 | [gen] 103 | ); 104 | 105 | expect(comp).to.eql( 106 | new BitString( 107 | BitString.integer(2), 108 | BitString.integer(4), 109 | BitString.integer(6) 110 | ) 111 | ); 112 | }); 113 | }); 114 | -------------------------------------------------------------------------------- /test/defmatch.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import chai from 'chai'; 4 | var expect = chai.expect; 5 | 6 | import Tailored from '../src/index.js'; 7 | import ErlangTypes from 'erlang-types'; 8 | const Tuple = ErlangTypes.Tuple; 9 | const BitString = ErlangTypes.BitString; 10 | 11 | const _ = Tailored.wildcard(); 12 | const $ = Tailored.variable(); 13 | 14 | describe('defmatch', () => { 15 | it('must throw error when no match is found', () => { 16 | let fn = Tailored.defmatch(Tailored.clause([0], () => 1)); 17 | 18 | expect(fn.bind(fn, 1)).to.throw('No match for: 1'); 19 | }); 20 | 21 | it('must have wildcard except everything', () => { 22 | let fn = Tailored.defmatch(Tailored.clause([_], () => 1)); 23 | 24 | expect(fn(1)).to.equal(1); 25 | expect(fn('1')).to.equal(1); 26 | expect(fn('ABC')).to.equal(1); 27 | expect(fn(() => 34)).to.equal(1); 28 | }); 29 | 30 | it('must work symbols', () => { 31 | let fn = Tailored.defmatch( 32 | Tailored.clause([Symbol.for('infinity')], () => 1) 33 | ); 34 | 35 | expect(fn(Symbol.for('infinity'))).to.equal(1); 36 | expect(fn.bind(fn, Symbol('infinity'))).to.throw( 37 | 'No match for: Symbol(infinity)' 38 | ); 39 | }); 40 | 41 | it('must match on values in object', () => { 42 | let fn = Tailored.defmatch( 43 | Tailored.clause([{ value: $ }], val => 1 + val), 44 | Tailored.clause([{ a: { b: { c: $ } } }], val => 1 - val) 45 | ); 46 | 47 | expect(fn({ value: 20 })).to.equal(21); 48 | expect(fn({ a: { b: { c: 20 } } })).to.equal(-19); 49 | }); 50 | 51 | it('must match on objects even when value has more keys', () => { 52 | let fn = Tailored.defmatch( 53 | Tailored.clause([{ value: $ }], val => 1 + val), 54 | Tailored.clause([{ a: { b: { c: $ } } }], val => 1 - val) 55 | ); 56 | 57 | expect(fn({ value: 20 })).to.equal(21); 58 | expect(fn({ a: { b: { c: 20 }, d: 10 } })).to.equal(-19); 59 | }); 60 | 61 | it('must match on substrings', () => { 62 | let fn = Tailored.defmatch( 63 | Tailored.clause([Tailored.startsWith('Bearer ')], token => token) 64 | ); 65 | 66 | expect(fn('Bearer 1234')).to.equal('1234'); 67 | }); 68 | 69 | it('must work with guards', () => { 70 | let fn = Tailored.defmatch( 71 | Tailored.clause([$], number => number, number => number > 0) 72 | ); 73 | 74 | expect(fn(3)).to.equal(3); 75 | expect(fn.bind(fn, -1)).to.throw('No match for: -1'); 76 | }); 77 | 78 | it('must capture entire match as parameter', () => { 79 | let fn = Tailored.defmatch( 80 | Tailored.clause( 81 | [Tailored.capture({ a: { b: { c: $ } } })], 82 | (val, bound_value) => bound_value['a']['b']['c'] 83 | ) 84 | ); 85 | 86 | expect(fn({ a: { b: { c: 20 } } })).to.equal(20); 87 | 88 | fn = Tailored.defmatch( 89 | Tailored.clause( 90 | [Tailored.capture([1, $, 3, $])], 91 | (a, b, bound_value) => bound_value.length 92 | ) 93 | ); 94 | 95 | expect(fn([1, 2, 3, 4])).to.equal(4); 96 | 97 | fn = Tailored.defmatch( 98 | Tailored.clause( 99 | [Tailored.capture([1, Tailored.capture({ a: { b: { c: $ } } }), 3, $])], 100 | (c, two, four, arg) => two['a']['b']['c'] 101 | ) 102 | ); 103 | 104 | expect(fn([1, { a: { b: { c: 20 } } }, 3, 4])).to.equal(20); 105 | }); 106 | 107 | it('must produce a head and a tail', () => { 108 | let fn = Tailored.defmatch( 109 | Tailored.clause([Tailored.headTail($, $)], (head, tail) => tail) 110 | ); 111 | 112 | expect(fn([3, 1, 2, 4]).length).to.equal(3); 113 | }); 114 | 115 | it('must produce a head and a tail with one element array', () => { 116 | let fn = Tailored.defmatch( 117 | Tailored.clause([Tailored.headTail($, $)], (head, tail) => tail) 118 | ); 119 | 120 | expect(fn([3]).length).to.equal(0); 121 | }); 122 | 123 | it('must match on tuple', () => { 124 | let fn = Tailored.defmatch( 125 | Tailored.clause([Tailored.type(Tuple, { values: [1, 2, 3] })], () => 3) 126 | ); 127 | 128 | expect(fn(new Tuple(1, 2, 3))).to.equal(3); 129 | expect(fn.bind(fn, new Tuple(1, 2, 4))).to.throw('No match for: {1, 2, 4}'); 130 | }); 131 | 132 | describe('BitString', () => { 133 | it('must match on a string', () => { 134 | let fn = Tailored.defmatch( 135 | Tailored.clause( 136 | [ 137 | Tailored.bitStringMatch( 138 | BitString.integer(102), 139 | BitString.integer(111), 140 | BitString.integer(111) 141 | ) 142 | ], 143 | () => 3 144 | ) 145 | ); 146 | 147 | expect(fn('foo')).to.equal(3); 148 | expect(fn.bind(fn, 'bar')).to.throw('No match for: bar'); 149 | }); 150 | 151 | it('must match on a bitstring', () => { 152 | let fn = Tailored.defmatch( 153 | Tailored.clause( 154 | [ 155 | Tailored.bitStringMatch( 156 | BitString.integer(102), 157 | BitString.integer(111), 158 | BitString.integer(111) 159 | ) 160 | ], 161 | () => 3 162 | ) 163 | ); 164 | 165 | expect( 166 | fn( 167 | new BitString( 168 | BitString.integer(102), 169 | BitString.integer(111), 170 | BitString.integer(111) 171 | ) 172 | ) 173 | ).to.equal(3); 174 | }); 175 | 176 | it('must allow for variables', () => { 177 | let fn = Tailored.defmatch( 178 | Tailored.clause( 179 | [ 180 | Tailored.bitStringMatch( 181 | BitString.integer({ value: $ }), 182 | BitString.integer(111), 183 | BitString.integer(111) 184 | ) 185 | ], 186 | pattern => pattern 187 | ) 188 | ); 189 | 190 | expect( 191 | fn( 192 | new BitString( 193 | BitString.integer(102), 194 | BitString.integer(111), 195 | BitString.integer(111) 196 | ) 197 | ) 198 | ).to.equal(102); 199 | }); 200 | 201 | it('must match on variable and convert to type', () => { 202 | let fn = Tailored.defmatch( 203 | Tailored.clause( 204 | [ 205 | Tailored.bitStringMatch( 206 | BitString.integer(102), 207 | BitString.binary({ value: $ }) 208 | ) 209 | ], 210 | b => b 211 | ) 212 | ); 213 | 214 | expect( 215 | fn( 216 | new BitString( 217 | BitString.integer(102), 218 | BitString.integer(111), 219 | BitString.integer(111) 220 | ) 221 | ) 222 | ).to.equal('oo'); 223 | }); 224 | 225 | it('throw error when binary is used without size', () => { 226 | let fn = Tailored.defmatch( 227 | Tailored.clause( 228 | [ 229 | Tailored.bitStringMatch( 230 | BitString.binary({ value: $ }), 231 | BitString.binary(' the '), 232 | BitString.binary({ value: $ }) 233 | ) 234 | ], 235 | (name, species) => name 236 | ) 237 | ); 238 | 239 | expect(fn.bind(fn, 'Frank the Walrus')).to.throw( 240 | 'a binary field without size is only allowed at the end of a binary pattern' 241 | ); 242 | }); 243 | 244 | it('allow binary pattern with size', () => { 245 | let fn = Tailored.defmatch( 246 | Tailored.clause( 247 | [ 248 | Tailored.bitStringMatch( 249 | BitString.size(BitString.binary({ value: $ }), 5), 250 | BitString.binary(' the '), 251 | BitString.binary({ value: $ }) 252 | ) 253 | ], 254 | (name, species) => name 255 | ) 256 | ); 257 | 258 | expect(fn('Frank the Walrus')).to.equal('Frank'); 259 | }); 260 | 261 | it('allow unsigned integer', () => { 262 | let fn = Tailored.defmatch( 263 | Tailored.clause( 264 | [Tailored.bitStringMatch(BitString.integer({ value: $ }))], 265 | int => int 266 | ) 267 | ); 268 | 269 | expect(fn(new BitString(BitString.integer(-100)))).to.equal(156); 270 | }); 271 | }); 272 | 273 | describe('Optional Arguments', () => { 274 | it('single optional argument', () => { 275 | let fn = Tailored.defmatch( 276 | Tailored.clause([Tailored.variable(null, 2)], arg => arg) 277 | ); 278 | 279 | expect(fn()).to.equal(2); 280 | expect(fn(3)).to.equal(3); 281 | }); 282 | 283 | it('single optional argument and one required argument', () => { 284 | let fn = Tailored.defmatch( 285 | Tailored.clause( 286 | [Tailored.variable(), Tailored.variable(null, 2)], 287 | (arg1, arg2) => arg1 + arg2 288 | ) 289 | ); 290 | 291 | expect(fn.bind(fn)).to.throw('No match for:'); 292 | expect(fn(1)).to.equal(3); 293 | expect(fn(3, 4)).to.equal(7); 294 | }); 295 | 296 | it('two optional arguments and one required argument', () => { 297 | let fn = Tailored.defmatch( 298 | Tailored.clause( 299 | [ 300 | Tailored.variable(null, 3), 301 | Tailored.variable(), 302 | Tailored.variable(null, 2) 303 | ], 304 | (arg1, arg2, arg3) => arg1 + arg2 + arg3 305 | ) 306 | ); 307 | 308 | expect(fn(1)).to.equal(6); 309 | expect(fn(3, 4)).to.equal(9); 310 | }); 311 | 312 | it('two optional arguments in between 2 required', () => { 313 | let fn = Tailored.defmatch( 314 | Tailored.clause( 315 | [ 316 | Tailored.variable(), 317 | Tailored.variable(null, 2), 318 | Tailored.variable(null, 3), 319 | Tailored.variable() 320 | ], 321 | (arg1, arg2, arg3, arg4) => arg1 + arg2 + arg3 + arg4 322 | ) 323 | ); 324 | 325 | expect(fn(1, 4)).to.equal(10); 326 | expect(fn(1, 5, 4)).to.equal(13); 327 | expect(fn(1, 5, 7, 4)).to.equal(17); 328 | }); 329 | 330 | it('must match on objects with symbol keys', () => { 331 | const bound_value = { 332 | [Symbol.for('__struct__')]: Symbol.for('Elixir.Blueprint.AssertError') 333 | }; 334 | 335 | const value = { 336 | [Symbol.for('__struct__')]: Symbol.for('Elixir.Blueprint.AssertError'), 337 | [Symbol.for('msg')]: 'somthing' 338 | }; 339 | 340 | let fn = Tailored.defmatch( 341 | Tailored.clause([Tailored.capture(bound_value)], val => true) 342 | ); 343 | 344 | expect(fn(value)).to.equal(true); 345 | }); 346 | 347 | it('must match on maps with symbol keys', () => { 348 | const bound_value = new Map([ 349 | [Symbol.for('__struct__'), Symbol.for('Elixir.Blueprint.AssertError')] 350 | ]); 351 | 352 | const value = new Map([ 353 | [Symbol.for('__struct__'), Symbol.for('Elixir.Blueprint.AssertError')], 354 | [Symbol.for('msg'), 'something'] 355 | ]); 356 | 357 | let fn = Tailored.defmatch( 358 | Tailored.clause([Tailored.capture(bound_value)], val => true) 359 | ); 360 | 361 | expect(fn(value)).to.equal(true); 362 | }); 363 | 364 | it('must work with maps', () => { 365 | const pattern = [ 366 | new Map([ 367 | [Symbol.for('a'), 1], 368 | [Symbol.for('b'), Tailored.variable('b')], 369 | [Symbol.for('c'), Tailored.variable('c')] 370 | ]) 371 | ]; 372 | 373 | const value = new Map([ 374 | [Symbol.for('a'), 1], 375 | [Symbol.for('b'), 2], 376 | [Symbol.for('c'), 3] 377 | ]); 378 | 379 | let fn = Tailored.defmatch(Tailored.clause(pattern, (b, c) => b + c)); 380 | 381 | expect(fn(value)).to.equal(5); 382 | }); 383 | 384 | it('works with bound keys', () => { 385 | const key0 = new Tuple(1) 386 | 387 | const map0 = new Map([ 388 | [new Tuple(1), "pie"] 389 | ]) 390 | 391 | const map = new Map([ 392 | [key0, Tailored.variable('value')] 393 | ]) 394 | 395 | const v = Tailored.defmatch(Tailored.clause([map], (value0) => { 396 | return value0; 397 | }, (value0) => { 398 | return true; 399 | })).call(this, map0) 400 | 401 | expect(v).to.equal('pie') 402 | }) 403 | }); 404 | }); 405 | -------------------------------------------------------------------------------- /test/match.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Tailored from '../src/index.js'; 4 | const expect = require('chai').expect; 5 | const ErlangTypes = require('erlang-types'); 6 | const Tuple = ErlangTypes.Tuple; 7 | 8 | const _ = Tailored.wildcard(); 9 | const $ = Tailored.variable(); 10 | 11 | describe('match', () => { 12 | it('must return value on parameter', () => { 13 | let [a] = Tailored.match($, 1); 14 | expect(a).to.equal(1); 15 | }); 16 | 17 | it('must ignore value when wildcard given', () => { 18 | let [a] = Tailored.match(_, 1); 19 | expect(a).to.equal(undefined); 20 | }); 21 | 22 | it('must match on multiple values when an array is given', () => { 23 | let [a] = Tailored.match([$, 2, _, 4], [1, 2, 3, 4]); 24 | expect(a).to.equal(1); 25 | }); 26 | 27 | it('must throw an error when there is no match', () => { 28 | expect(Tailored.match.bind(Tailored.match, [$, 2, _, 4], 1)).to.throw( 29 | 'No match for: 1' 30 | ); 31 | }); 32 | 33 | it('must match values in object', () => { 34 | let [a] = Tailored.match({ a: [1, $, 3] }, { a: [1, 2, 3] }); 35 | expect(a).to.equal(2); 36 | }); 37 | 38 | it('must match on capture variables', () => { 39 | let a = 1; 40 | 41 | let [b] = Tailored.match(Tailored.capture(a), 1); 42 | expect(b).to.equal(1); 43 | 44 | let c = { a: 1 }; 45 | 46 | let [d] = Tailored.match(Tailored.capture(c), { a: 1 }); 47 | expect(d['a']).to.equal(1); 48 | }); 49 | 50 | it('must throw an error when capture value does not match', () => { 51 | let a = 1; 52 | expect( 53 | Tailored.match.bind(Tailored.match, Tailored.capture(a), 2) 54 | ).to.throw('No match for: 2'); 55 | }); 56 | 57 | it('must work with type values', () => { 58 | let matches = Tailored.match_or_default( 59 | new Tuple(Symbol.for('ok'), $), 60 | new Tuple(Symbol.for('ok'), 1) 61 | ); 62 | 63 | expect(matches.length).to.equal(1); 64 | expect(matches[0]).to.equal(1); 65 | }); 66 | 67 | it('must match variable names when values are the same', () => { 68 | let matches = Tailored.match_or_default( 69 | [Tailored.variable('name'), Tailored.variable('name')], 70 | [3, 3] 71 | ); 72 | 73 | expect(matches.length).to.equal(2); 74 | expect(matches[0]).to.equal(3); 75 | }); 76 | 77 | it('must not match variable names with values are different', () => { 78 | let matches = Tailored.match_or_default( 79 | [Tailored.variable('name'), Tailored.variable('name')], 80 | [3, 4] 81 | ); 82 | 83 | expect(matches).to.equal(null); 84 | }); 85 | 86 | it('matches async function', () => { 87 | const f = async function() {}; 88 | let matches = Tailored.match_or_default(f, f); 89 | expect(matches.length).to.equal(0); 90 | }); 91 | }); 92 | -------------------------------------------------------------------------------- /test/tailcall.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import chai from 'chai'; 4 | var expect = chai.expect; 5 | 6 | import Tailored from '../src/index.js'; 7 | import ErlangTypes from 'erlang-types'; 8 | 9 | const _ = Tailored.wildcard(); 10 | const $ = Tailored.variable(); 11 | 12 | describe('tailcall', () => { 13 | it('factorial must work correctly', () => { 14 | let fact = Tailored.defmatch( 15 | Tailored.clause([0], () => 1), 16 | Tailored.clause([$], n => n * fact(n - 1)), 17 | ); 18 | 19 | //let response = fact(32768); 20 | //expect(response).to.equal(Infinity); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/estree@0.0.39": 6 | version "0.0.39" 7 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" 8 | 9 | "@types/node@^12.6.9": 10 | version "12.7.1" 11 | resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.1.tgz#3b5c3a26393c19b400844ac422bd0f631a94d69d" 12 | 13 | acorn@^6.2.1: 14 | version "6.2.1" 15 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.2.1.tgz#3ed8422d6dec09e6121cc7a843ca86a330a86b51" 16 | 17 | ansi-colors@3.2.3: 18 | version "3.2.3" 19 | resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" 20 | 21 | ansi-regex@^2.0.0: 22 | version "2.1.1" 23 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 24 | 25 | ansi-regex@^3.0.0: 26 | version "3.0.0" 27 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 28 | 29 | ansi-regex@^4.1.0: 30 | version "4.1.0" 31 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" 32 | 33 | ansi-styles@^2.2.1: 34 | version "2.2.1" 35 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 36 | 37 | ansi-styles@^3.2.1: 38 | version "3.2.1" 39 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 40 | dependencies: 41 | color-convert "^1.9.0" 42 | 43 | argparse@^1.0.7: 44 | version "1.0.10" 45 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 46 | dependencies: 47 | sprintf-js "~1.0.2" 48 | 49 | assertion-error@^1.1.0: 50 | version "1.1.0" 51 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" 52 | 53 | babel-code-frame@^6.26.0: 54 | version "6.26.0" 55 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" 56 | dependencies: 57 | chalk "^1.1.3" 58 | esutils "^2.0.2" 59 | js-tokens "^3.0.2" 60 | 61 | babel-core@^6.25.0, babel-core@^6.26.0: 62 | version "6.26.3" 63 | resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" 64 | dependencies: 65 | babel-code-frame "^6.26.0" 66 | babel-generator "^6.26.0" 67 | babel-helpers "^6.24.1" 68 | babel-messages "^6.23.0" 69 | babel-register "^6.26.0" 70 | babel-runtime "^6.26.0" 71 | babel-template "^6.26.0" 72 | babel-traverse "^6.26.0" 73 | babel-types "^6.26.0" 74 | babylon "^6.18.0" 75 | convert-source-map "^1.5.1" 76 | debug "^2.6.9" 77 | json5 "^0.5.1" 78 | lodash "^4.17.4" 79 | minimatch "^3.0.4" 80 | path-is-absolute "^1.0.1" 81 | private "^0.1.8" 82 | slash "^1.0.0" 83 | source-map "^0.5.7" 84 | 85 | babel-generator@^6.26.0: 86 | version "6.26.1" 87 | resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" 88 | dependencies: 89 | babel-messages "^6.23.0" 90 | babel-runtime "^6.26.0" 91 | babel-types "^6.26.0" 92 | detect-indent "^4.0.0" 93 | jsesc "^1.3.0" 94 | lodash "^4.17.4" 95 | source-map "^0.5.7" 96 | trim-right "^1.0.1" 97 | 98 | babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: 99 | version "6.22.0" 100 | resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.22.0.tgz#29df56be144d81bdeac08262bfa41d2c5e91cdcd" 101 | dependencies: 102 | babel-helper-explode-assignable-expression "^6.22.0" 103 | babel-runtime "^6.22.0" 104 | babel-types "^6.22.0" 105 | 106 | babel-helper-call-delegate@^6.22.0: 107 | version "6.22.0" 108 | resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef" 109 | dependencies: 110 | babel-helper-hoist-variables "^6.22.0" 111 | babel-runtime "^6.22.0" 112 | babel-traverse "^6.22.0" 113 | babel-types "^6.22.0" 114 | 115 | babel-helper-define-map@^6.23.0: 116 | version "6.23.0" 117 | resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz#1444f960c9691d69a2ced6a205315f8fd00804e7" 118 | dependencies: 119 | babel-helper-function-name "^6.23.0" 120 | babel-runtime "^6.22.0" 121 | babel-types "^6.23.0" 122 | lodash "^4.2.0" 123 | 124 | babel-helper-explode-assignable-expression@^6.22.0: 125 | version "6.22.0" 126 | resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.22.0.tgz#c97bf76eed3e0bae4048121f2b9dae1a4e7d0478" 127 | dependencies: 128 | babel-runtime "^6.22.0" 129 | babel-traverse "^6.22.0" 130 | babel-types "^6.22.0" 131 | 132 | babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.23.0: 133 | version "6.23.0" 134 | resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz#25742d67175c8903dbe4b6cb9d9e1fcb8dcf23a6" 135 | dependencies: 136 | babel-helper-get-function-arity "^6.22.0" 137 | babel-runtime "^6.22.0" 138 | babel-template "^6.23.0" 139 | babel-traverse "^6.23.0" 140 | babel-types "^6.23.0" 141 | 142 | babel-helper-get-function-arity@^6.22.0: 143 | version "6.22.0" 144 | resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce" 145 | dependencies: 146 | babel-runtime "^6.22.0" 147 | babel-types "^6.22.0" 148 | 149 | babel-helper-hoist-variables@^6.22.0: 150 | version "6.22.0" 151 | resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz#3eacbf731d80705845dd2e9718f600cfb9b4ba72" 152 | dependencies: 153 | babel-runtime "^6.22.0" 154 | babel-types "^6.22.0" 155 | 156 | babel-helper-optimise-call-expression@^6.23.0: 157 | version "6.23.0" 158 | resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz#f3ee7eed355b4282138b33d02b78369e470622f5" 159 | dependencies: 160 | babel-runtime "^6.22.0" 161 | babel-types "^6.23.0" 162 | 163 | babel-helper-regex@^6.22.0: 164 | version "6.22.0" 165 | resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz#79f532be1647b1f0ee3474b5f5c3da58001d247d" 166 | dependencies: 167 | babel-runtime "^6.22.0" 168 | babel-types "^6.22.0" 169 | lodash "^4.2.0" 170 | 171 | babel-helper-remap-async-to-generator@^6.22.0: 172 | version "6.22.0" 173 | resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.22.0.tgz#2186ae73278ed03b8b15ced089609da981053383" 174 | dependencies: 175 | babel-helper-function-name "^6.22.0" 176 | babel-runtime "^6.22.0" 177 | babel-template "^6.22.0" 178 | babel-traverse "^6.22.0" 179 | babel-types "^6.22.0" 180 | 181 | babel-helper-replace-supers@^6.22.0, babel-helper-replace-supers@^6.23.0: 182 | version "6.23.0" 183 | resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz#eeaf8ad9b58ec4337ca94223bacdca1f8d9b4bfd" 184 | dependencies: 185 | babel-helper-optimise-call-expression "^6.23.0" 186 | babel-messages "^6.23.0" 187 | babel-runtime "^6.22.0" 188 | babel-template "^6.23.0" 189 | babel-traverse "^6.23.0" 190 | babel-types "^6.23.0" 191 | 192 | babel-helpers@^6.24.1: 193 | version "6.24.1" 194 | resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" 195 | dependencies: 196 | babel-runtime "^6.22.0" 197 | babel-template "^6.24.1" 198 | 199 | babel-messages@^6.23.0: 200 | version "6.23.0" 201 | resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" 202 | dependencies: 203 | babel-runtime "^6.22.0" 204 | 205 | babel-plugin-check-es2015-constants@^6.22.0: 206 | version "6.22.0" 207 | resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" 208 | dependencies: 209 | babel-runtime "^6.22.0" 210 | 211 | babel-plugin-syntax-async-functions@^6.8.0: 212 | version "6.13.0" 213 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" 214 | 215 | babel-plugin-syntax-exponentiation-operator@^6.8.0: 216 | version "6.13.0" 217 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" 218 | 219 | babel-plugin-syntax-trailing-function-commas@^6.22.0: 220 | version "6.22.0" 221 | resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" 222 | 223 | babel-plugin-transform-async-to-generator@^6.22.0: 224 | version "6.22.0" 225 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e" 226 | dependencies: 227 | babel-helper-remap-async-to-generator "^6.22.0" 228 | babel-plugin-syntax-async-functions "^6.8.0" 229 | babel-runtime "^6.22.0" 230 | 231 | babel-plugin-transform-es2015-arrow-functions@^6.22.0: 232 | version "6.22.0" 233 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" 234 | dependencies: 235 | babel-runtime "^6.22.0" 236 | 237 | babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: 238 | version "6.22.0" 239 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" 240 | dependencies: 241 | babel-runtime "^6.22.0" 242 | 243 | babel-plugin-transform-es2015-block-scoping@^6.23.0: 244 | version "6.23.0" 245 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51" 246 | dependencies: 247 | babel-runtime "^6.22.0" 248 | babel-template "^6.23.0" 249 | babel-traverse "^6.23.0" 250 | babel-types "^6.23.0" 251 | lodash "^4.2.0" 252 | 253 | babel-plugin-transform-es2015-classes@^6.23.0: 254 | version "6.23.0" 255 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1" 256 | dependencies: 257 | babel-helper-define-map "^6.23.0" 258 | babel-helper-function-name "^6.23.0" 259 | babel-helper-optimise-call-expression "^6.23.0" 260 | babel-helper-replace-supers "^6.23.0" 261 | babel-messages "^6.23.0" 262 | babel-runtime "^6.22.0" 263 | babel-template "^6.23.0" 264 | babel-traverse "^6.23.0" 265 | babel-types "^6.23.0" 266 | 267 | babel-plugin-transform-es2015-computed-properties@^6.22.0: 268 | version "6.22.0" 269 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz#7c383e9629bba4820c11b0425bdd6290f7f057e7" 270 | dependencies: 271 | babel-runtime "^6.22.0" 272 | babel-template "^6.22.0" 273 | 274 | babel-plugin-transform-es2015-destructuring@^6.23.0: 275 | version "6.23.0" 276 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" 277 | dependencies: 278 | babel-runtime "^6.22.0" 279 | 280 | babel-plugin-transform-es2015-duplicate-keys@^6.22.0: 281 | version "6.22.0" 282 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.22.0.tgz#672397031c21610d72dd2bbb0ba9fb6277e1c36b" 283 | dependencies: 284 | babel-runtime "^6.22.0" 285 | babel-types "^6.22.0" 286 | 287 | babel-plugin-transform-es2015-for-of@^6.23.0: 288 | version "6.23.0" 289 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" 290 | dependencies: 291 | babel-runtime "^6.22.0" 292 | 293 | babel-plugin-transform-es2015-function-name@^6.22.0: 294 | version "6.22.0" 295 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.22.0.tgz#f5fcc8b09093f9a23c76ac3d9e392c3ec4b77104" 296 | dependencies: 297 | babel-helper-function-name "^6.22.0" 298 | babel-runtime "^6.22.0" 299 | babel-types "^6.22.0" 300 | 301 | babel-plugin-transform-es2015-literals@^6.22.0: 302 | version "6.22.0" 303 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" 304 | dependencies: 305 | babel-runtime "^6.22.0" 306 | 307 | babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.0: 308 | version "6.24.0" 309 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.0.tgz#a1911fb9b7ec7e05a43a63c5995007557bcf6a2e" 310 | dependencies: 311 | babel-plugin-transform-es2015-modules-commonjs "^6.24.0" 312 | babel-runtime "^6.22.0" 313 | babel-template "^6.22.0" 314 | 315 | babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.0: 316 | version "6.24.0" 317 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz#e921aefb72c2cc26cb03d107626156413222134f" 318 | dependencies: 319 | babel-plugin-transform-strict-mode "^6.22.0" 320 | babel-runtime "^6.22.0" 321 | babel-template "^6.23.0" 322 | babel-types "^6.23.0" 323 | 324 | babel-plugin-transform-es2015-modules-systemjs@^6.23.0: 325 | version "6.23.0" 326 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0" 327 | dependencies: 328 | babel-helper-hoist-variables "^6.22.0" 329 | babel-runtime "^6.22.0" 330 | babel-template "^6.23.0" 331 | 332 | babel-plugin-transform-es2015-modules-umd@^6.23.0: 333 | version "6.24.0" 334 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.0.tgz#fd5fa63521cae8d273927c3958afd7c067733450" 335 | dependencies: 336 | babel-plugin-transform-es2015-modules-amd "^6.24.0" 337 | babel-runtime "^6.22.0" 338 | babel-template "^6.23.0" 339 | 340 | babel-plugin-transform-es2015-object-super@^6.22.0: 341 | version "6.22.0" 342 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz#daa60e114a042ea769dd53fe528fc82311eb98fc" 343 | dependencies: 344 | babel-helper-replace-supers "^6.22.0" 345 | babel-runtime "^6.22.0" 346 | 347 | babel-plugin-transform-es2015-parameters@^6.23.0: 348 | version "6.23.0" 349 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b" 350 | dependencies: 351 | babel-helper-call-delegate "^6.22.0" 352 | babel-helper-get-function-arity "^6.22.0" 353 | babel-runtime "^6.22.0" 354 | babel-template "^6.23.0" 355 | babel-traverse "^6.23.0" 356 | babel-types "^6.23.0" 357 | 358 | babel-plugin-transform-es2015-shorthand-properties@^6.22.0: 359 | version "6.22.0" 360 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz#8ba776e0affaa60bff21e921403b8a652a2ff723" 361 | dependencies: 362 | babel-runtime "^6.22.0" 363 | babel-types "^6.22.0" 364 | 365 | babel-plugin-transform-es2015-spread@^6.22.0: 366 | version "6.22.0" 367 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" 368 | dependencies: 369 | babel-runtime "^6.22.0" 370 | 371 | babel-plugin-transform-es2015-sticky-regex@^6.22.0: 372 | version "6.22.0" 373 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz#ab316829e866ee3f4b9eb96939757d19a5bc4593" 374 | dependencies: 375 | babel-helper-regex "^6.22.0" 376 | babel-runtime "^6.22.0" 377 | babel-types "^6.22.0" 378 | 379 | babel-plugin-transform-es2015-template-literals@^6.22.0: 380 | version "6.22.0" 381 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" 382 | dependencies: 383 | babel-runtime "^6.22.0" 384 | 385 | babel-plugin-transform-es2015-typeof-symbol@^6.23.0: 386 | version "6.23.0" 387 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" 388 | dependencies: 389 | babel-runtime "^6.22.0" 390 | 391 | babel-plugin-transform-es2015-unicode-regex@^6.22.0: 392 | version "6.22.0" 393 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz#8d9cc27e7ee1decfe65454fb986452a04a613d20" 394 | dependencies: 395 | babel-helper-regex "^6.22.0" 396 | babel-runtime "^6.22.0" 397 | regexpu-core "^2.0.0" 398 | 399 | babel-plugin-transform-exponentiation-operator@^6.22.0: 400 | version "6.22.0" 401 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d" 402 | dependencies: 403 | babel-helper-builder-binary-assignment-operator-visitor "^6.22.0" 404 | babel-plugin-syntax-exponentiation-operator "^6.8.0" 405 | babel-runtime "^6.22.0" 406 | 407 | babel-plugin-transform-regenerator@^6.22.0: 408 | version "6.22.0" 409 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6" 410 | dependencies: 411 | regenerator-transform "0.9.8" 412 | 413 | babel-plugin-transform-strict-mode@^6.22.0: 414 | version "6.22.0" 415 | resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz#e008df01340fdc87e959da65991b7e05970c8c7c" 416 | dependencies: 417 | babel-runtime "^6.22.0" 418 | babel-types "^6.22.0" 419 | 420 | babel-preset-env@^1.6.0: 421 | version "1.7.0" 422 | resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" 423 | dependencies: 424 | babel-plugin-check-es2015-constants "^6.22.0" 425 | babel-plugin-syntax-trailing-function-commas "^6.22.0" 426 | babel-plugin-transform-async-to-generator "^6.22.0" 427 | babel-plugin-transform-es2015-arrow-functions "^6.22.0" 428 | babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" 429 | babel-plugin-transform-es2015-block-scoping "^6.23.0" 430 | babel-plugin-transform-es2015-classes "^6.23.0" 431 | babel-plugin-transform-es2015-computed-properties "^6.22.0" 432 | babel-plugin-transform-es2015-destructuring "^6.23.0" 433 | babel-plugin-transform-es2015-duplicate-keys "^6.22.0" 434 | babel-plugin-transform-es2015-for-of "^6.23.0" 435 | babel-plugin-transform-es2015-function-name "^6.22.0" 436 | babel-plugin-transform-es2015-literals "^6.22.0" 437 | babel-plugin-transform-es2015-modules-amd "^6.22.0" 438 | babel-plugin-transform-es2015-modules-commonjs "^6.23.0" 439 | babel-plugin-transform-es2015-modules-systemjs "^6.23.0" 440 | babel-plugin-transform-es2015-modules-umd "^6.23.0" 441 | babel-plugin-transform-es2015-object-super "^6.22.0" 442 | babel-plugin-transform-es2015-parameters "^6.23.0" 443 | babel-plugin-transform-es2015-shorthand-properties "^6.22.0" 444 | babel-plugin-transform-es2015-spread "^6.22.0" 445 | babel-plugin-transform-es2015-sticky-regex "^6.22.0" 446 | babel-plugin-transform-es2015-template-literals "^6.22.0" 447 | babel-plugin-transform-es2015-typeof-symbol "^6.23.0" 448 | babel-plugin-transform-es2015-unicode-regex "^6.22.0" 449 | babel-plugin-transform-exponentiation-operator "^6.22.0" 450 | babel-plugin-transform-regenerator "^6.22.0" 451 | browserslist "^3.2.6" 452 | invariant "^2.2.2" 453 | semver "^5.3.0" 454 | 455 | babel-register@^6.24.1, babel-register@^6.26.0: 456 | version "6.26.0" 457 | resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" 458 | dependencies: 459 | babel-core "^6.26.0" 460 | babel-runtime "^6.26.0" 461 | core-js "^2.5.0" 462 | home-or-tmp "^2.0.0" 463 | lodash "^4.17.4" 464 | mkdirp "^0.5.1" 465 | source-map-support "^0.4.15" 466 | 467 | babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: 468 | version "6.26.0" 469 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" 470 | dependencies: 471 | core-js "^2.4.0" 472 | regenerator-runtime "^0.11.0" 473 | 474 | babel-template@^6.22.0, babel-template@^6.23.0, babel-template@^6.24.1, babel-template@^6.26.0: 475 | version "6.26.0" 476 | resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" 477 | dependencies: 478 | babel-runtime "^6.26.0" 479 | babel-traverse "^6.26.0" 480 | babel-types "^6.26.0" 481 | babylon "^6.18.0" 482 | lodash "^4.17.4" 483 | 484 | babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.26.0: 485 | version "6.26.0" 486 | resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" 487 | dependencies: 488 | babel-code-frame "^6.26.0" 489 | babel-messages "^6.23.0" 490 | babel-runtime "^6.26.0" 491 | babel-types "^6.26.0" 492 | babylon "^6.18.0" 493 | debug "^2.6.8" 494 | globals "^9.18.0" 495 | invariant "^2.2.2" 496 | lodash "^4.17.4" 497 | 498 | babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0, babel-types@^6.26.0: 499 | version "6.26.0" 500 | resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" 501 | dependencies: 502 | babel-runtime "^6.26.0" 503 | esutils "^2.0.2" 504 | lodash "^4.17.4" 505 | to-fast-properties "^1.0.3" 506 | 507 | babylon@^6.18.0: 508 | version "6.18.0" 509 | resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" 510 | 511 | balanced-match@^1.0.0: 512 | version "1.0.0" 513 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 514 | 515 | brace-expansion@^1.1.7: 516 | version "1.1.11" 517 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 518 | dependencies: 519 | balanced-match "^1.0.0" 520 | concat-map "0.0.1" 521 | 522 | browser-stdout@1.3.1: 523 | version "1.3.1" 524 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 525 | 526 | browserslist@^3.2.6: 527 | version "3.2.8" 528 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" 529 | dependencies: 530 | caniuse-lite "^1.0.30000844" 531 | electron-to-chromium "^1.3.47" 532 | 533 | camelcase@^5.0.0: 534 | version "5.2.0" 535 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.2.0.tgz#e7522abda5ed94cc0489e1b8466610e88404cf45" 536 | 537 | caniuse-lite@^1.0.30000844: 538 | version "1.0.30000971" 539 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000971.tgz#d1000e4546486a6977756547352bc96a4cfd2b13" 540 | 541 | chai@^4.1.0: 542 | version "4.2.0" 543 | resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" 544 | dependencies: 545 | assertion-error "^1.1.0" 546 | check-error "^1.0.2" 547 | deep-eql "^3.0.1" 548 | get-func-name "^2.0.0" 549 | pathval "^1.1.0" 550 | type-detect "^4.0.5" 551 | 552 | chalk@^1.1.3: 553 | version "1.1.3" 554 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 555 | dependencies: 556 | ansi-styles "^2.2.1" 557 | escape-string-regexp "^1.0.2" 558 | has-ansi "^2.0.0" 559 | strip-ansi "^3.0.0" 560 | supports-color "^2.0.0" 561 | 562 | chalk@^2.0.1: 563 | version "2.4.2" 564 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 565 | dependencies: 566 | ansi-styles "^3.2.1" 567 | escape-string-regexp "^1.0.5" 568 | supports-color "^5.3.0" 569 | 570 | check-error@^1.0.2: 571 | version "1.0.2" 572 | resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" 573 | 574 | cliui@^4.0.0: 575 | version "4.1.0" 576 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" 577 | dependencies: 578 | string-width "^2.1.1" 579 | strip-ansi "^4.0.0" 580 | wrap-ansi "^2.0.0" 581 | 582 | code-point-at@^1.0.0: 583 | version "1.1.0" 584 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 585 | 586 | color-convert@^1.9.0: 587 | version "1.9.3" 588 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 589 | dependencies: 590 | color-name "1.1.3" 591 | 592 | color-name@1.1.3: 593 | version "1.1.3" 594 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 595 | 596 | concat-map@0.0.1: 597 | version "0.0.1" 598 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 599 | 600 | convert-source-map@^1.5.1: 601 | version "1.6.0" 602 | resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" 603 | dependencies: 604 | safe-buffer "~5.1.1" 605 | 606 | core-js@^2.4.0: 607 | version "2.4.1" 608 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" 609 | 610 | core-js@^2.5.0: 611 | version "2.6.9" 612 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.9.tgz#6b4b214620c834152e179323727fc19741b084f2" 613 | 614 | cross-spawn@^6.0.0: 615 | version "6.0.5" 616 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 617 | dependencies: 618 | nice-try "^1.0.4" 619 | path-key "^2.0.1" 620 | semver "^5.5.0" 621 | shebang-command "^1.2.0" 622 | which "^1.2.9" 623 | 624 | debug@3.2.6: 625 | version "3.2.6" 626 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" 627 | dependencies: 628 | ms "^2.1.1" 629 | 630 | debug@^2.6.8, debug@^2.6.9: 631 | version "2.6.9" 632 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 633 | dependencies: 634 | ms "2.0.0" 635 | 636 | decamelize@^1.2.0: 637 | version "1.2.0" 638 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 639 | 640 | deep-eql@^3.0.1: 641 | version "3.0.1" 642 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" 643 | dependencies: 644 | type-detect "^4.0.0" 645 | 646 | define-properties@^1.1.2: 647 | version "1.1.3" 648 | resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" 649 | dependencies: 650 | object-keys "^1.0.12" 651 | 652 | detect-indent@^4.0.0: 653 | version "4.0.0" 654 | resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" 655 | dependencies: 656 | repeating "^2.0.0" 657 | 658 | diff@3.5.0: 659 | version "3.5.0" 660 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 661 | 662 | electron-to-chromium@^1.3.47: 663 | version "1.3.137" 664 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.137.tgz#ba7c88024984c038a5c5c434529aabcea7b42944" 665 | 666 | emoji-regex@^7.0.1: 667 | version "7.0.3" 668 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 669 | 670 | end-of-stream@^1.1.0: 671 | version "1.4.1" 672 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" 673 | dependencies: 674 | once "^1.4.0" 675 | 676 | erlang-types@^1.0.1: 677 | version "1.1.3" 678 | resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.1.3.tgz#833538d82a33f300c307ee19fab93bf625c92d89" 679 | 680 | es-abstract@^1.5.1: 681 | version "1.13.0" 682 | resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" 683 | dependencies: 684 | es-to-primitive "^1.2.0" 685 | function-bind "^1.1.1" 686 | has "^1.0.3" 687 | is-callable "^1.1.4" 688 | is-regex "^1.0.4" 689 | object-keys "^1.0.12" 690 | 691 | es-to-primitive@^1.2.0: 692 | version "1.2.0" 693 | resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" 694 | dependencies: 695 | is-callable "^1.1.4" 696 | is-date-object "^1.0.1" 697 | is-symbol "^1.0.2" 698 | 699 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 700 | version "1.0.5" 701 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 702 | 703 | esprima@^4.0.0: 704 | version "4.0.1" 705 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 706 | 707 | estree-walker@^0.2.1: 708 | version "0.2.1" 709 | resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" 710 | 711 | esutils@^2.0.2: 712 | version "2.0.2" 713 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 714 | 715 | execa@^1.0.0: 716 | version "1.0.0" 717 | resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" 718 | dependencies: 719 | cross-spawn "^6.0.0" 720 | get-stream "^4.0.0" 721 | is-stream "^1.1.0" 722 | npm-run-path "^2.0.0" 723 | p-finally "^1.0.0" 724 | signal-exit "^3.0.0" 725 | strip-eof "^1.0.0" 726 | 727 | find-up@3.0.0, find-up@^3.0.0: 728 | version "3.0.0" 729 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 730 | dependencies: 731 | locate-path "^3.0.0" 732 | 733 | flat@^4.1.0: 734 | version "4.1.0" 735 | resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" 736 | dependencies: 737 | is-buffer "~2.0.3" 738 | 739 | fs.realpath@^1.0.0: 740 | version "1.0.0" 741 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 742 | 743 | function-bind@^1.1.1: 744 | version "1.1.1" 745 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 746 | 747 | get-caller-file@^1.0.1: 748 | version "1.0.3" 749 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" 750 | 751 | get-caller-file@^2.0.1: 752 | version "2.0.5" 753 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 754 | 755 | get-func-name@^2.0.0: 756 | version "2.0.0" 757 | resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" 758 | 759 | get-stream@^4.0.0: 760 | version "4.1.0" 761 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" 762 | dependencies: 763 | pump "^3.0.0" 764 | 765 | glob@7.1.3: 766 | version "7.1.3" 767 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" 768 | dependencies: 769 | fs.realpath "^1.0.0" 770 | inflight "^1.0.4" 771 | inherits "2" 772 | minimatch "^3.0.4" 773 | once "^1.3.0" 774 | path-is-absolute "^1.0.0" 775 | 776 | globals@^9.18.0: 777 | version "9.18.0" 778 | resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" 779 | 780 | growl@1.10.5: 781 | version "1.10.5" 782 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 783 | 784 | has-ansi@^2.0.0: 785 | version "2.0.0" 786 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 787 | dependencies: 788 | ansi-regex "^2.0.0" 789 | 790 | has-flag@^3.0.0: 791 | version "3.0.0" 792 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 793 | 794 | has-symbols@^1.0.0: 795 | version "1.0.0" 796 | resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" 797 | 798 | has@^1.0.1, has@^1.0.3: 799 | version "1.0.3" 800 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 801 | dependencies: 802 | function-bind "^1.1.1" 803 | 804 | he@1.2.0: 805 | version "1.2.0" 806 | resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" 807 | 808 | home-or-tmp@^2.0.0: 809 | version "2.0.0" 810 | resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" 811 | dependencies: 812 | os-homedir "^1.0.0" 813 | os-tmpdir "^1.0.1" 814 | 815 | inflight@^1.0.4: 816 | version "1.0.6" 817 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 818 | dependencies: 819 | once "^1.3.0" 820 | wrappy "1" 821 | 822 | inherits@2: 823 | version "2.0.3" 824 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 825 | 826 | invariant@^2.2.2: 827 | version "2.2.2" 828 | resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" 829 | dependencies: 830 | loose-envify "^1.0.0" 831 | 832 | invert-kv@^2.0.0: 833 | version "2.0.0" 834 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" 835 | 836 | is-buffer@~2.0.3: 837 | version "2.0.3" 838 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" 839 | 840 | is-callable@^1.1.4: 841 | version "1.1.4" 842 | resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" 843 | 844 | is-date-object@^1.0.1: 845 | version "1.0.1" 846 | resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" 847 | 848 | is-finite@^1.0.0: 849 | version "1.0.2" 850 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" 851 | dependencies: 852 | number-is-nan "^1.0.0" 853 | 854 | is-fullwidth-code-point@^1.0.0: 855 | version "1.0.0" 856 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 857 | dependencies: 858 | number-is-nan "^1.0.0" 859 | 860 | is-fullwidth-code-point@^2.0.0: 861 | version "2.0.0" 862 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 863 | 864 | is-regex@^1.0.4: 865 | version "1.0.4" 866 | resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" 867 | dependencies: 868 | has "^1.0.1" 869 | 870 | is-stream@^1.1.0: 871 | version "1.1.0" 872 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 873 | 874 | is-symbol@^1.0.2: 875 | version "1.0.2" 876 | resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" 877 | dependencies: 878 | has-symbols "^1.0.0" 879 | 880 | isexe@^2.0.0: 881 | version "2.0.0" 882 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 883 | 884 | js-tokens@^3.0.0: 885 | version "3.0.1" 886 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" 887 | 888 | js-tokens@^3.0.2: 889 | version "3.0.2" 890 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 891 | 892 | js-yaml@3.13.1: 893 | version "3.13.1" 894 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 895 | dependencies: 896 | argparse "^1.0.7" 897 | esprima "^4.0.0" 898 | 899 | jsesc@^1.3.0: 900 | version "1.3.0" 901 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" 902 | 903 | jsesc@~0.5.0: 904 | version "0.5.0" 905 | resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" 906 | 907 | json5@^0.5.1: 908 | version "0.5.1" 909 | resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" 910 | 911 | lcid@^2.0.0: 912 | version "2.0.0" 913 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" 914 | dependencies: 915 | invert-kv "^2.0.0" 916 | 917 | locate-path@^3.0.0: 918 | version "3.0.0" 919 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 920 | dependencies: 921 | p-locate "^3.0.0" 922 | path-exists "^3.0.0" 923 | 924 | lodash@^4.17.11, lodash@^4.17.4, lodash@^4.2.0: 925 | version "4.17.15" 926 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" 927 | 928 | log-symbols@2.2.0: 929 | version "2.2.0" 930 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" 931 | dependencies: 932 | chalk "^2.0.1" 933 | 934 | loose-envify@^1.0.0: 935 | version "1.3.1" 936 | resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" 937 | dependencies: 938 | js-tokens "^3.0.0" 939 | 940 | map-age-cleaner@^0.1.1: 941 | version "0.1.3" 942 | resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" 943 | dependencies: 944 | p-defer "^1.0.0" 945 | 946 | mem@^4.0.0: 947 | version "4.2.0" 948 | resolved "https://registry.yarnpkg.com/mem/-/mem-4.2.0.tgz#5ee057680ed9cb8dad8a78d820f9a8897a102025" 949 | dependencies: 950 | map-age-cleaner "^0.1.1" 951 | mimic-fn "^2.0.0" 952 | p-is-promise "^2.0.0" 953 | 954 | mimic-fn@^2.0.0: 955 | version "2.0.0" 956 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.0.0.tgz#0913ff0b121db44ef5848242c38bbb35d44cabde" 957 | 958 | minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: 959 | version "3.0.4" 960 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 961 | dependencies: 962 | brace-expansion "^1.1.7" 963 | 964 | minimist@0.0.8: 965 | version "0.0.8" 966 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 967 | 968 | mkdirp@0.5.1, mkdirp@^0.5.1: 969 | version "0.5.1" 970 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 971 | dependencies: 972 | minimist "0.0.8" 973 | 974 | mocha@^6.0.2: 975 | version "6.2.0" 976 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.0.tgz#f896b642843445d1bb8bca60eabd9206b8916e56" 977 | dependencies: 978 | ansi-colors "3.2.3" 979 | browser-stdout "1.3.1" 980 | debug "3.2.6" 981 | diff "3.5.0" 982 | escape-string-regexp "1.0.5" 983 | find-up "3.0.0" 984 | glob "7.1.3" 985 | growl "1.10.5" 986 | he "1.2.0" 987 | js-yaml "3.13.1" 988 | log-symbols "2.2.0" 989 | minimatch "3.0.4" 990 | mkdirp "0.5.1" 991 | ms "2.1.1" 992 | node-environment-flags "1.0.5" 993 | object.assign "4.1.0" 994 | strip-json-comments "2.0.1" 995 | supports-color "6.0.0" 996 | which "1.3.1" 997 | wide-align "1.1.3" 998 | yargs "13.2.2" 999 | yargs-parser "13.0.0" 1000 | yargs-unparser "1.5.0" 1001 | 1002 | ms@2.0.0: 1003 | version "2.0.0" 1004 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 1005 | 1006 | ms@2.1.1, ms@^2.1.1: 1007 | version "2.1.1" 1008 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" 1009 | 1010 | nice-try@^1.0.4: 1011 | version "1.0.5" 1012 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 1013 | 1014 | node-environment-flags@1.0.5: 1015 | version "1.0.5" 1016 | resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" 1017 | dependencies: 1018 | object.getownpropertydescriptors "^2.0.3" 1019 | semver "^5.7.0" 1020 | 1021 | npm-run-path@^2.0.0: 1022 | version "2.0.2" 1023 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 1024 | dependencies: 1025 | path-key "^2.0.0" 1026 | 1027 | number-is-nan@^1.0.0: 1028 | version "1.0.1" 1029 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 1030 | 1031 | object-keys@^1.0.11, object-keys@^1.0.12: 1032 | version "1.1.0" 1033 | resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" 1034 | 1035 | object.assign@4.1.0: 1036 | version "4.1.0" 1037 | resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" 1038 | dependencies: 1039 | define-properties "^1.1.2" 1040 | function-bind "^1.1.1" 1041 | has-symbols "^1.0.0" 1042 | object-keys "^1.0.11" 1043 | 1044 | object.getownpropertydescriptors@^2.0.3: 1045 | version "2.0.3" 1046 | resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" 1047 | dependencies: 1048 | define-properties "^1.1.2" 1049 | es-abstract "^1.5.1" 1050 | 1051 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 1052 | version "1.4.0" 1053 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1054 | dependencies: 1055 | wrappy "1" 1056 | 1057 | os-homedir@^1.0.0: 1058 | version "1.0.2" 1059 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 1060 | 1061 | os-locale@^3.0.0, os-locale@^3.1.0: 1062 | version "3.1.0" 1063 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" 1064 | dependencies: 1065 | execa "^1.0.0" 1066 | lcid "^2.0.0" 1067 | mem "^4.0.0" 1068 | 1069 | os-tmpdir@^1.0.1: 1070 | version "1.0.2" 1071 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 1072 | 1073 | p-defer@^1.0.0: 1074 | version "1.0.0" 1075 | resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" 1076 | 1077 | p-finally@^1.0.0: 1078 | version "1.0.0" 1079 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 1080 | 1081 | p-is-promise@^2.0.0: 1082 | version "2.0.0" 1083 | resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" 1084 | 1085 | p-limit@^2.0.0: 1086 | version "2.2.0" 1087 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" 1088 | dependencies: 1089 | p-try "^2.0.0" 1090 | 1091 | p-locate@^3.0.0: 1092 | version "3.0.0" 1093 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 1094 | dependencies: 1095 | p-limit "^2.0.0" 1096 | 1097 | p-try@^2.0.0: 1098 | version "2.1.0" 1099 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.1.0.tgz#c1a0f1030e97de018bb2c718929d2af59463e505" 1100 | 1101 | path-exists@^3.0.0: 1102 | version "3.0.0" 1103 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 1104 | 1105 | path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: 1106 | version "1.0.1" 1107 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1108 | 1109 | path-key@^2.0.0, path-key@^2.0.1: 1110 | version "2.0.1" 1111 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 1112 | 1113 | pathval@^1.1.0: 1114 | version "1.1.0" 1115 | resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" 1116 | 1117 | private@^0.1.6, private@^0.1.8: 1118 | version "0.1.8" 1119 | resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" 1120 | 1121 | pump@^3.0.0: 1122 | version "3.0.0" 1123 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 1124 | dependencies: 1125 | end-of-stream "^1.1.0" 1126 | once "^1.3.1" 1127 | 1128 | regenerate@^1.2.1: 1129 | version "1.3.2" 1130 | resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" 1131 | 1132 | regenerator-runtime@^0.11.0: 1133 | version "0.11.1" 1134 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" 1135 | 1136 | regenerator-transform@0.9.8: 1137 | version "0.9.8" 1138 | resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c" 1139 | dependencies: 1140 | babel-runtime "^6.18.0" 1141 | babel-types "^6.19.0" 1142 | private "^0.1.6" 1143 | 1144 | regexpu-core@^2.0.0: 1145 | version "2.0.0" 1146 | resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" 1147 | dependencies: 1148 | regenerate "^1.2.1" 1149 | regjsgen "^0.2.0" 1150 | regjsparser "^0.1.4" 1151 | 1152 | regjsgen@^0.2.0: 1153 | version "0.2.0" 1154 | resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" 1155 | 1156 | regjsparser@^0.1.4: 1157 | version "0.1.5" 1158 | resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" 1159 | dependencies: 1160 | jsesc "~0.5.0" 1161 | 1162 | repeating@^2.0.0: 1163 | version "2.0.1" 1164 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 1165 | dependencies: 1166 | is-finite "^1.0.0" 1167 | 1168 | require-directory@^2.1.1: 1169 | version "2.1.1" 1170 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1171 | 1172 | require-main-filename@^1.0.1: 1173 | version "1.0.1" 1174 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" 1175 | 1176 | require-main-filename@^2.0.0: 1177 | version "2.0.0" 1178 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" 1179 | 1180 | rollup-plugin-babel@^3.0.7: 1181 | version "3.0.7" 1182 | resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.7.tgz#5b13611f1ab8922497e9d15197ae5d8a23fe3b1e" 1183 | dependencies: 1184 | rollup-pluginutils "^1.5.0" 1185 | 1186 | rollup-pluginutils@^1.5.0: 1187 | version "1.5.2" 1188 | resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" 1189 | dependencies: 1190 | estree-walker "^0.2.1" 1191 | minimatch "^3.0.2" 1192 | 1193 | rollup@^1.12.4: 1194 | version "1.19.4" 1195 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.19.4.tgz#0cb4e4d6fa127adab59b11d0be50e8dd1c78123a" 1196 | dependencies: 1197 | "@types/estree" "0.0.39" 1198 | "@types/node" "^12.6.9" 1199 | acorn "^6.2.1" 1200 | 1201 | safe-buffer@~5.1.1: 1202 | version "5.1.2" 1203 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1204 | 1205 | semver@^5.3.0, semver@^5.5.0: 1206 | version "5.6.0" 1207 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" 1208 | 1209 | semver@^5.7.0: 1210 | version "5.7.0" 1211 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" 1212 | 1213 | set-blocking@^2.0.0: 1214 | version "2.0.0" 1215 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 1216 | 1217 | shebang-command@^1.2.0: 1218 | version "1.2.0" 1219 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 1220 | dependencies: 1221 | shebang-regex "^1.0.0" 1222 | 1223 | shebang-regex@^1.0.0: 1224 | version "1.0.0" 1225 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 1226 | 1227 | signal-exit@^3.0.0: 1228 | version "3.0.2" 1229 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 1230 | 1231 | slash@^1.0.0: 1232 | version "1.0.0" 1233 | resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" 1234 | 1235 | source-map-support@^0.4.15: 1236 | version "0.4.18" 1237 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" 1238 | dependencies: 1239 | source-map "^0.5.6" 1240 | 1241 | source-map@^0.5.6, source-map@^0.5.7: 1242 | version "0.5.7" 1243 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1244 | 1245 | sprintf-js@~1.0.2: 1246 | version "1.0.3" 1247 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1248 | 1249 | string-width@^1.0.1: 1250 | version "1.0.2" 1251 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1252 | dependencies: 1253 | code-point-at "^1.0.0" 1254 | is-fullwidth-code-point "^1.0.0" 1255 | strip-ansi "^3.0.0" 1256 | 1257 | "string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: 1258 | version "2.1.1" 1259 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 1260 | dependencies: 1261 | is-fullwidth-code-point "^2.0.0" 1262 | strip-ansi "^4.0.0" 1263 | 1264 | string-width@^3.0.0: 1265 | version "3.1.0" 1266 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 1267 | dependencies: 1268 | emoji-regex "^7.0.1" 1269 | is-fullwidth-code-point "^2.0.0" 1270 | strip-ansi "^5.1.0" 1271 | 1272 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 1273 | version "3.0.1" 1274 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1275 | dependencies: 1276 | ansi-regex "^2.0.0" 1277 | 1278 | strip-ansi@^4.0.0: 1279 | version "4.0.0" 1280 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 1281 | dependencies: 1282 | ansi-regex "^3.0.0" 1283 | 1284 | strip-ansi@^5.1.0: 1285 | version "5.2.0" 1286 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 1287 | dependencies: 1288 | ansi-regex "^4.1.0" 1289 | 1290 | strip-eof@^1.0.0: 1291 | version "1.0.0" 1292 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 1293 | 1294 | strip-json-comments@2.0.1: 1295 | version "2.0.1" 1296 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1297 | 1298 | supports-color@6.0.0: 1299 | version "6.0.0" 1300 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" 1301 | dependencies: 1302 | has-flag "^3.0.0" 1303 | 1304 | supports-color@^2.0.0: 1305 | version "2.0.0" 1306 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1307 | 1308 | supports-color@^5.3.0: 1309 | version "5.5.0" 1310 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1311 | dependencies: 1312 | has-flag "^3.0.0" 1313 | 1314 | to-fast-properties@^1.0.3: 1315 | version "1.0.3" 1316 | resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" 1317 | 1318 | trim-right@^1.0.1: 1319 | version "1.0.1" 1320 | resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" 1321 | 1322 | type-detect@^4.0.0, type-detect@^4.0.5: 1323 | version "4.0.8" 1324 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" 1325 | 1326 | which-module@^2.0.0: 1327 | version "2.0.0" 1328 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 1329 | 1330 | which@1.3.1, which@^1.2.9: 1331 | version "1.3.1" 1332 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1333 | dependencies: 1334 | isexe "^2.0.0" 1335 | 1336 | wide-align@1.1.3: 1337 | version "1.1.3" 1338 | resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" 1339 | dependencies: 1340 | string-width "^1.0.2 || 2" 1341 | 1342 | wrap-ansi@^2.0.0: 1343 | version "2.1.0" 1344 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" 1345 | dependencies: 1346 | string-width "^1.0.1" 1347 | strip-ansi "^3.0.1" 1348 | 1349 | wrappy@1: 1350 | version "1.0.2" 1351 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1352 | 1353 | "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: 1354 | version "4.0.0" 1355 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" 1356 | 1357 | yargs-parser@13.0.0: 1358 | version "13.0.0" 1359 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b" 1360 | dependencies: 1361 | camelcase "^5.0.0" 1362 | decamelize "^1.2.0" 1363 | 1364 | yargs-parser@^11.1.1: 1365 | version "11.1.1" 1366 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" 1367 | dependencies: 1368 | camelcase "^5.0.0" 1369 | decamelize "^1.2.0" 1370 | 1371 | yargs-parser@^13.0.0: 1372 | version "13.1.0" 1373 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.0.tgz#7016b6dd03e28e1418a510e258be4bff5a31138f" 1374 | dependencies: 1375 | camelcase "^5.0.0" 1376 | decamelize "^1.2.0" 1377 | 1378 | yargs-unparser@1.5.0: 1379 | version "1.5.0" 1380 | resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.5.0.tgz#f2bb2a7e83cbc87bb95c8e572828a06c9add6e0d" 1381 | dependencies: 1382 | flat "^4.1.0" 1383 | lodash "^4.17.11" 1384 | yargs "^12.0.5" 1385 | 1386 | yargs@13.2.2: 1387 | version "13.2.2" 1388 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993" 1389 | dependencies: 1390 | cliui "^4.0.0" 1391 | find-up "^3.0.0" 1392 | get-caller-file "^2.0.1" 1393 | os-locale "^3.1.0" 1394 | require-directory "^2.1.1" 1395 | require-main-filename "^2.0.0" 1396 | set-blocking "^2.0.0" 1397 | string-width "^3.0.0" 1398 | which-module "^2.0.0" 1399 | y18n "^4.0.0" 1400 | yargs-parser "^13.0.0" 1401 | 1402 | yargs@^12.0.5: 1403 | version "12.0.5" 1404 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" 1405 | dependencies: 1406 | cliui "^4.0.0" 1407 | decamelize "^1.2.0" 1408 | find-up "^3.0.0" 1409 | get-caller-file "^1.0.1" 1410 | os-locale "^3.0.0" 1411 | require-directory "^2.1.1" 1412 | require-main-filename "^1.0.1" 1413 | set-blocking "^2.0.0" 1414 | string-width "^2.0.0" 1415 | which-module "^2.0.0" 1416 | y18n "^3.2.1 || ^4.0.0" 1417 | yargs-parser "^11.1.1" 1418 | --------------------------------------------------------------------------------