| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 | 
const XorShift = require('xorshift').constructor;const stream = require('stream');const reader = require('./reader.js');const header = `#include "mconf.h"#include "cephes.h"#include <stdio.h>int error_code = -1;int mtherr(char *name, int code) {  error_code = code;  return 0;}int main() {`;const footer = `}\n`;var rng = new XorShift([  6724524440630955, 4369800304473057,  1956920014856890, 8721370862793116]);const type2printf = {  'double': '%.20f',  'int': '%d'};const type2zero = {  'double': '0.0',  'int': '0'};const argGenerators = {  double: function () {    return (rng.random() * 10).toFixed(8);  },  int: function () {    return (rng.random() * 10 + 1).toFixed(0);  },  "double[]": function () {    let code = '[';    code += (rng.random() * 20 - 10).toFixed(2) + ', ';    code += (rng.random() * 20 - 10).toFixed(2) + ', ';    code += (rng.random() * 20 - 10).toFixed(2) + ', ';    code += (rng.random() * 20 - 10).toFixed(2) + ']';    return code;  },  // Bad range in igami, causes infinite loop  "igami:y0": function () {    return rng.random().toFixed(8);  },  "igami:a": function () {    return (rng.random() * 10).toFixed(8);  }};class CTesterGenerator extends stream.Transform {  constructor() {    super({ objectMode: true });    this.push(header);  }  _generateSampleCode(data) {    const {filename, returnType, functionName, functionArgs} = data;    // Check if there is extra data returned    const extraReturn = functionArgs.some((arg) => arg.isPointer);    // Sample function arguments    let fnargs = new Map();    for (const { fullType, name, isPointer, isArrayLength } of functionArgs) {      if (isPointer) continue;      if (isArrayLength) {         // The array is of length 4, .length - 1 is not always the correct         // choice, but it is always the safe choice.        fnargs.set(name, "3");      } else if (argGenerators.hasOwnProperty(`${functionName}:${name}`)) {        fnargs.set(name, argGenerators[`${functionName}:${name}`]());      } else {        fnargs.set(name, argGenerators[fullType]());      }    }    //    // Start code generation    //    let code = '';    code += `  { /* ${functionName} from cephes/${filename}.c */\n`;    code += '     error_code = -1;\n';    //    // Function call    //    // Create pointer inputs    for (const { type, name, isPointer } of functionArgs) {      if (!isPointer) continue;      code += `    ${type} extra_${name} = ${type2zero[type]};\n`;    }    // Call function    code += `    ${returnType} ret = cephes_${functionName}(`    for (const { fullType, name, isPointer, isArray } of functionArgs) {      if (isPointer) {        code += `&extra_${name}, `;      } else if (isArray) {        const c_array = fnargs.get(name).replace('[', '{').replace(']', '}');        code += `(${fullType}) ${c_array}, `;      }      else code += fnargs.get(name) + ', ';    }    code = code.slice(0, -2);    code += ');\n';    // Normalize return value    code += `    ret = error_code == -1 ? ret : ${type2zero[returnType]};\n`;    //    // Print output    //    // The printf string    code += `    printf("{"\n`;    code += `           "\\"fn\\": \\"${functionName}\\", "\n`;    code += `           "\\"ret\\": ${type2printf[returnType]}, "\n`;    code += `           "\\"args\\": [`;    for (const { name, isPointer } of functionArgs) {      if (isPointer) continue;      code += `${fnargs.get(name)}, `;    }    code = code.slice(0, -2);    code += `], "\n`;    code += `           "\\"extra\\": {`;    if (extraReturn) {      for (const { type, name, isPointer } of functionArgs) {        if (!isPointer) continue;        code += `\\"${name}\\": ${type2printf[type]}, `;      }      code = code.slice(0, -2);    }    code += `}, "\n`;    code += `           "\\"error_code\\": %d"\n`;    code += `           "}\\n",\n`;    // The printf content    code += `           ret, `;    for (const { fullType, name, isPointer } of functionArgs) {      if (!isPointer) continue;      code += `extra_${name}, `;    }    code += `error_code`;    // Close printf    code += `);\n`;    //    code += '  }\n';    code += '\n';    return code;  }  _transform(data, encoding, done) {    for (let i = 0; i < 5; i++) {      this.push(this._generateSampleCode(data));    }    done(null);  }  _flush(done) {    this.push(footer);    done(null);  }}process.stdin  .pipe(reader())  .pipe(new CTesterGenerator())  .pipe(process.stdout)
 |