reader.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. const fs = require('fs');
  2. const path = require('path');
  3. const stream = require('stream');
  4. const split2 = require('split2');
  5. const pumpify = require('pumpify');
  6. const cprotoParser = require('./reader-cproto-parser.js');
  7. const docParser = require('./reader-doc-parser.js');
  8. const DOC_FILE = path.resolve(__dirname, '..', 'cephes', 'cephes.txt');
  9. const INTERNAL_CEPHES_FUNCTIONS = new Set([
  10. 'hyp2f0', 'onef2', 'threef0'
  11. ]);
  12. class MergeDocumentation extends stream.Transform {
  13. constructor() {
  14. super({ objectMode: true });
  15. this._prototypes = new Map();
  16. this._documentationEnded = false;
  17. this._documentation = [];
  18. this._documentationStream = fs.createReadStream(DOC_FILE)
  19. .pipe(docParser())
  20. .on('data', (doc) => this._documentation.push(doc))
  21. .once('end', (err) => this._documentationEnded = true)
  22. .on('error', (err) => this.emit('error', err));
  23. }
  24. _transform(proto, encoding, done) {
  25. this._prototypes.set(proto.functionName, proto);
  26. done(null);
  27. }
  28. _finish(done) {
  29. // Validate that no documentation is missing
  30. const documentationParts = new Set(
  31. this._documentation.map((doc) => doc.functionName)
  32. );
  33. for (const protoFunctionName of this._prototypes.keys()) {
  34. if (INTERNAL_CEPHES_FUNCTIONS.has(protoFunctionName)) continue;
  35. if (!documentationParts.has(protoFunctionName)) {
  36. throw new Error(`documentation for ${protoFunctionName} is missing`);
  37. }
  38. }
  39. // Merge data
  40. // The order of the documentation stream is meaninful, so use the
  41. // documentation as the order and merge in the prototypes.
  42. for (const doc of this._documentation) {
  43. if (INTERNAL_CEPHES_FUNCTIONS.has(doc.functionName)) continue;
  44. if (this._prototypes.has(doc.functionName)) {
  45. this.push(
  46. Object.assign({}, doc, this._prototypes.get(doc.functionName))
  47. );
  48. }
  49. }
  50. done(null);
  51. }
  52. _flush(done) {
  53. if (this._documentationEnded) {
  54. process.nextTick(() => this._finish(done));
  55. } else {
  56. this._documentationStream.once('end', () => this._finish(done));
  57. }
  58. }
  59. }
  60. function parser() {
  61. return pumpify.obj(
  62. cprotoParser(),
  63. new MergeDocumentation()
  64. );
  65. }
  66. module.exports = parser;