mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-06 18:56:40 +01:00
for loops
This commit is contained in:
@@ -17,15 +17,18 @@
|
||||
along with circom. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
const utils = require("./utils");
|
||||
const assert = require("assert");
|
||||
const gen = require("./c_gen");
|
||||
const bigInt = require("big-integer");
|
||||
const utils = require("./utils");
|
||||
const gen = require("./c_gen").gen;
|
||||
const newRef = require("./c_gen").newRef;
|
||||
|
||||
module.exports = buildC;
|
||||
|
||||
|
||||
function buildC(ctx) {
|
||||
ctx.code = "";
|
||||
ctx.conditionalCodeHeader = "";
|
||||
ctx.tmpNames = {};
|
||||
ctx.getTmpName = getTmpName;
|
||||
ctx.codes_sizes = [];
|
||||
@@ -158,6 +161,7 @@ function buildCode(ctx) {
|
||||
|
||||
const scope = {_prefix : ""};
|
||||
ctx.scopes = [scope];
|
||||
ctx.conditionalCode = false;
|
||||
ctx.nScopes = 0;
|
||||
ctx.code = "";
|
||||
ctx.codeHeader = "// Header\n";
|
||||
@@ -165,7 +169,7 @@ function buildCode(ctx) {
|
||||
ctx.tmpNames = Object.assign({},globalNames);
|
||||
|
||||
for (let p in ctx.components[i].params) {
|
||||
newRef(ctx, "BIGINT", p, ctx.components[i].params[p]);
|
||||
newRef(ctx, "BIGINT", p, bigInt(ctx.components[i].params[p]));
|
||||
}
|
||||
|
||||
gen(ctx, ctx.templates[ctx.components[i].template].block);
|
||||
@@ -212,6 +216,7 @@ function buildHeader(ctx) {
|
||||
`#define NInputs ${ctx.components[ ctx.getComponentIdx("main") ].nInSignals}\n`+
|
||||
`#define NOutputs ${ctx.totals[ ctx.stOUTPUT ]}\n`+
|
||||
`#define NVars ${ctx.totals[ctx.stONE] + ctx.totals[ctx.stOUTPUT] + ctx.totals[ctx.stPUBINPUT] + ctx.totals[ctx.stPRVINPUT] + ctx.totals[ctx.stINTERNAL]}\n` +
|
||||
`#define __P__ "${ctx.field.p.toString()}"\n` +
|
||||
"\n";
|
||||
}
|
||||
|
||||
@@ -310,7 +315,8 @@ function buildCircuitVar() {
|
||||
" NVars,\n"+
|
||||
" _wit2sig,\n"+
|
||||
" _components,\n"+
|
||||
" _mapIsInput\n"+
|
||||
" _mapIsInput,\n"+
|
||||
" __P__\n" +
|
||||
"};\n";
|
||||
}
|
||||
|
||||
|
||||
275
src/c_gen.js
275
src/c_gen.js
@@ -1,8 +1,9 @@
|
||||
const bigInt = require("big-integer");
|
||||
const utils = require("./utils");
|
||||
const assert = require("assert");
|
||||
|
||||
module.exports = gen;
|
||||
|
||||
module.exports.gen = gen;
|
||||
module.exports.newRef = newRef;
|
||||
|
||||
function newRef(ctx, type, _name, value, _sizes) {
|
||||
const isValue = ((typeof(value) != "undefined")&&(value != null));
|
||||
@@ -28,7 +29,7 @@ function newRef(ctx, type, _name, value, _sizes) {
|
||||
}
|
||||
|
||||
const scope = ctx.scopes[ctx.scopes.length-1];
|
||||
if (scope[name]) return error("Variable already exists: " + name);
|
||||
if (scope[name]) return error(ctx, null, "Variable already exists: " + name);
|
||||
|
||||
const label = scope._prefix + name;
|
||||
scope[name] = {
|
||||
@@ -64,9 +65,9 @@ function newSizes(ctx, sizes) {
|
||||
}
|
||||
|
||||
|
||||
function instantiateRef(ctx, name) {
|
||||
function instantiateRef(ctx, name, initValue) {
|
||||
const v = getScope(ctx, name);
|
||||
if (!v.stack) return error("Using a non existing var: " + name);
|
||||
if (!v.stack) return error(ctx, null, "Using a non existing var: " + name);
|
||||
if (v.used) return;
|
||||
|
||||
if (v.type=="BIGINT") {
|
||||
@@ -76,7 +77,12 @@ function instantiateRef(ctx, name) {
|
||||
if (iSize.used) {
|
||||
const labelSize = iSize.label;
|
||||
ctx.codeHeader += `PBigInt ${v.label};\n`;
|
||||
ctx.code += `${v.label} = ctx->allocBigInts(${labelSize});\n`;
|
||||
const c = `${v.label} = ctx->allocBigInts(${labelSize});\n`;
|
||||
if (ctx.conditionalCode) {
|
||||
ctx.conditionalCodeHeader += c;
|
||||
} else {
|
||||
ctx.code += c;
|
||||
}
|
||||
ctx.codeFooter += `ctx->freeBigInts(${v.label}, ${labelSize});\n`;
|
||||
} else if (iSize.value) {
|
||||
const labelSize = ctx.addSizes(iSize.value);
|
||||
@@ -92,6 +98,30 @@ function instantiateRef(ctx, name) {
|
||||
ctx.codeHeader += `Circom_Sizes ${v.label};\n`;
|
||||
}
|
||||
v.used = true;
|
||||
if ((typeof initValue!= "undefined")&&(initValue != null)) {
|
||||
const flatedValue = utils.flatArray(initValue);
|
||||
for (let i=0; i<flatedValue.length; i++) {
|
||||
const c = `mpz_set_str(${v.label}[${i}], "${flatedValue[i].toString(10)}", 10);\n`;
|
||||
if (ctx.conditionalCode) {
|
||||
ctx.conditionalCodeHeader += c;
|
||||
} else {
|
||||
ctx.code += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function instantiateConstant(ctx, value) {
|
||||
const labelSize = ctx.addSizes(utils.extractSizes(value));
|
||||
const flatedValue = utils.flatArray(value);
|
||||
const res = ctx.getTmpName("_const");
|
||||
ctx.codeHeader += `PBigInt ${res};\n`;
|
||||
ctx.codeHeader += `${res} = ctx->allocBigInts(${labelSize});\n`;
|
||||
for (let i=0; i<flatedValue.length; i++) {
|
||||
ctx.codeHeader += `mpz_set_str(${res}[${i}], "${flatedValue[i].toString(10)}", 10);\n`;
|
||||
}
|
||||
ctx.codeFooter += `ctx->freeBigInts(${res}, ${labelSize});\n`;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,7 +170,7 @@ function gen(ctx, ast) {
|
||||
} else if (ast.op == "*=") {
|
||||
return genVarMulAssignement(ctx, ast);
|
||||
} else if (ast.op == "+") {
|
||||
return genAdd(ctx, ast);
|
||||
return genBinaryOp(ctx, ast, "add");
|
||||
} else if (ast.op == "-") {
|
||||
return genSub(ctx, ast);
|
||||
} else if (ast.op == "UMINUS") {
|
||||
@@ -174,7 +204,7 @@ function gen(ctx, ast) {
|
||||
} else if (ast.op == ">>") {
|
||||
return genShr(ctx, ast);
|
||||
} else if (ast.op == "<") {
|
||||
return genLt(ctx, ast);
|
||||
return genBinaryOp(ctx, ast, "lt");
|
||||
} else if (ast.op == ">") {
|
||||
return genGt(ctx, ast);
|
||||
} else if (ast.op == "<=") {
|
||||
@@ -226,6 +256,7 @@ function gen(ctx, ast) {
|
||||
}
|
||||
|
||||
function genBlock(ctx, ast) {
|
||||
ctx.scopes.push({_prefix : ""});
|
||||
const oldCode = ctx.code;
|
||||
let res = null;
|
||||
ctx.code = "";
|
||||
@@ -236,26 +267,35 @@ function genBlock(ctx, ast) {
|
||||
res = gen(ctx, ast.statements[i]);
|
||||
if (ctx.error) return;
|
||||
}
|
||||
if (ctx.scopes.length>1) {
|
||||
ctx.code = oldCode + `{\n${utils.ident(ctx.code)}}\n`;
|
||||
} else {
|
||||
ctx.code = oldCode + ctx.code;
|
||||
}
|
||||
ctx.code = oldCode + ctx.code;
|
||||
ctx.scopes.pop();
|
||||
return res;
|
||||
}
|
||||
|
||||
function genSrcComment(ctx, ast) {
|
||||
function getSource(ctx, ast) {
|
||||
let codes = [];
|
||||
const fl= ast.first_line-1;
|
||||
const ll = ast.last_line-1;
|
||||
const fc = ast.first_column-1;
|
||||
const fc = ast.first_column;
|
||||
const lc = ast.last_column;
|
||||
for (let i=fl; i<=ll; i++) {
|
||||
const p1 = i==fl ? fc : 0;
|
||||
const p2 = i==ll ? lc : -1;
|
||||
codes.push(ctx.includedFiles[ctx.fileName][i].slice(p1, p2>=0 ? p2 : undefined));
|
||||
}
|
||||
ctx.code += "\n/* "+codes.join("\n")+"*/\n";
|
||||
return codes.join("\n");
|
||||
}
|
||||
|
||||
function genSrcComment(ctx, ast) {
|
||||
const code = getSource(ctx, ast);
|
||||
ctx.code += "\n/* "+code+" */\n";
|
||||
}
|
||||
|
||||
function genForSrcComment(ctx, ast) {
|
||||
const init = getSource(ctx, ast.init);
|
||||
const condition = getSource(ctx, ast.condition);
|
||||
const step = getSource(ctx, ast.step);
|
||||
ctx.code += `\n/* for (${init},${condition},${step}) */\n`;
|
||||
}
|
||||
|
||||
|
||||
@@ -297,7 +337,7 @@ function genDeclareVariable(ctx, ast) {
|
||||
const labelName = scope._prefix + ast.name.name;
|
||||
|
||||
if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid component name");
|
||||
if (ctx.scope[varName]) return error(ctx, ast, "Name already exists: "+varName);
|
||||
if (typeof scope[varName] != "undefined") return error(ctx, ast, "Name already exists: "+varName);
|
||||
|
||||
const sizes=[];
|
||||
let instantiate = false;
|
||||
@@ -329,16 +369,17 @@ function genDeclareVariable(ctx, ast) {
|
||||
iSizes.value = sizes;
|
||||
}
|
||||
|
||||
const res = ctx.scope[varName] = {
|
||||
const res = scope[varName] = {
|
||||
stack: true,
|
||||
type: "BIGINT",
|
||||
sizes: vSizes,
|
||||
label: labelName
|
||||
label: labelName,
|
||||
used: false,
|
||||
};
|
||||
|
||||
scope[varName] = res;
|
||||
|
||||
return res;
|
||||
return varName;
|
||||
}
|
||||
|
||||
function genNumber(ctx, ast) {
|
||||
@@ -432,17 +473,23 @@ function genVariable(ctx, ast) {
|
||||
|
||||
} else if (v.type == "BIGINT") {
|
||||
const vOffset = genGetOffset(ctx, 0, v.sizes, ast.sels );
|
||||
const offset = getScope(ctx, vOffset);
|
||||
if (v.used) {
|
||||
if (vOffset == 0) {
|
||||
return ast.name;
|
||||
} else {
|
||||
if (offset.used) {
|
||||
const res = newRef(ctx, "BIGINT", "_v");
|
||||
instantiateRef(ctx, res);
|
||||
ctx.code += `${res} = ${ast.name} + ${vOffset};\n`;
|
||||
return res;
|
||||
} else if (offset.value) {
|
||||
const res = newRef(ctx, "BIGINT", "_v");
|
||||
instantiateRef(ctx, res);
|
||||
ctx.code += `${res} = ${ast.name} + ${vOffset.value};\n`;
|
||||
return res;
|
||||
} else {
|
||||
return ast.name;
|
||||
}
|
||||
} else {
|
||||
if (typeof(vOffset) == "string") {
|
||||
if (offset.used) {
|
||||
instantiateRef(ctx, ast.name);
|
||||
const vConstant = instantiateConstant(ctx, v.value);
|
||||
const res = newRef(ctx, "BIGINT", "_v");
|
||||
@@ -475,17 +522,6 @@ function genVariable(ctx, ast) {
|
||||
}
|
||||
}
|
||||
|
||||
function instantiateConstant(ctx, value) {
|
||||
const flatedValue = utils.flatArray(value);
|
||||
const res = ctx.getTmpName("_const");
|
||||
ctx.codeHeader += `PBigInt ${res};\n`;
|
||||
ctx.code += `${res.label} = ctx->allocBigInts(${flatedValue.length});\n`;
|
||||
for (let i=0; i<flatedValue.length; i++) {
|
||||
ctx.code += `mpz_init_set_str(${res.label}[${i}], ${flatedValue[i].toString(16)}, 16);\n`;
|
||||
}
|
||||
ctx.codeFooter += `ctx->freeBigInts(${res.label});\n`;
|
||||
return res;
|
||||
}
|
||||
|
||||
function genPin(ctx, ast) {
|
||||
let vcIdx;
|
||||
@@ -546,7 +582,12 @@ function genGetSignalSizes(ctx, sIdx, label) {
|
||||
}
|
||||
|
||||
function genSetSignal(ctx, cIdx, sIdx, value) {
|
||||
const v = getScope(ctx, value);
|
||||
if (!v.used) {
|
||||
value = instantiateConstant(ctx, v.value);
|
||||
}
|
||||
ctx.code += `ctx->setSignal(${cIdx}, ${sIdx}, ${value});\n`;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -604,6 +645,10 @@ function genVarAssignement(ctx, ast) {
|
||||
const left = getScope(ctx, lName);
|
||||
if (!left) return error(ctx, ast, "Variable does not exists: "+ast.values[0].name);
|
||||
|
||||
if (ctx.conditionalCode && !left.used) {
|
||||
instantiateRef(ctx, lName, left.value);
|
||||
}
|
||||
|
||||
// Component instantiation is already done.
|
||||
if (left.type == "COMPONENT") {
|
||||
ctx.last = lName;
|
||||
@@ -626,36 +671,29 @@ function genVarAssignement(ctx, ast) {
|
||||
}
|
||||
|
||||
return genSetSignal(ctx, "ctx->cIdx", vsIdx, rName);
|
||||
} else if (left.type == "VAR") {
|
||||
} else if (left.type == "BIGINT") {
|
||||
if (left.used) {
|
||||
if (!right.used) {
|
||||
instantiateRef(ctx, rName);
|
||||
}
|
||||
ctx.code += `BigInt_copy(${left.label}, ${right.label});\n`;
|
||||
return lName;
|
||||
ctx.code += `ctx->field->copy(${left.label}, ${right.label});\n`;
|
||||
} else {
|
||||
if (right.used) {
|
||||
instantiateRef(ctx, lName);
|
||||
ctx.code += `BigInt_copy(${left.label}, ${right.label});\n`;
|
||||
return lName;
|
||||
ctx.code += `ctx->field->copy(${left.label}, ${right.label});\n`;
|
||||
} else {
|
||||
if (!left.value) {
|
||||
left.value = right.value;
|
||||
if (ctx.conditionalCode) {
|
||||
instantiateRef(ctx, lName);
|
||||
ctx.code += `ctx->field->copy(${left.label}, ${right.label});\n`;
|
||||
} else {
|
||||
if (!left.value.equals(right.value)) {
|
||||
if (ctx.scopes.length > 1) {
|
||||
instantiateRef(ctx, lName);
|
||||
ctx.code += `BigInt_copy(${left.label}, ${right.label});\n`;
|
||||
} else {
|
||||
left.value = right.value;
|
||||
}
|
||||
}
|
||||
left.value = right.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return error(ctx, ast, "Assigning to invalid");
|
||||
}
|
||||
return lName;
|
||||
}
|
||||
|
||||
function genConstraint(ctx, ast) {
|
||||
@@ -690,18 +728,103 @@ function genFunctionCall(ctx, ast) {
|
||||
return `ctx.callFunction("${ast.name}", ${S})`;
|
||||
}
|
||||
|
||||
function enterConditionalCode(ctx) {
|
||||
if (!ctx.conditionalCode) {
|
||||
ctx.conditionalCode = 1;
|
||||
ctx.conditionalCodeHeader = "";
|
||||
ctx.code += "__CONDITIONAL_CODE_HEADER__";
|
||||
} else {
|
||||
ctx.conditionalCode ++;
|
||||
}
|
||||
}
|
||||
|
||||
function leaveConditionalCode(ctx) {
|
||||
assert(ctx.conditionalCode, "Leaving conditional code too many times");
|
||||
ctx.conditionalCode --;
|
||||
if (!ctx.conditionalCode) {
|
||||
ctx.code = ctx.code.replace("__CONDITIONAL_CODE_HEADER__",
|
||||
"// Conditional Code Header\n" +
|
||||
ctx.conditionalCodeHeader+
|
||||
"\n");
|
||||
delete ctx.conditionalCodeHeader;
|
||||
delete ctx.conditionalCode;
|
||||
}
|
||||
}
|
||||
|
||||
function genFor(ctx, ast) {
|
||||
ctx.scopes.push({});
|
||||
const init = gen(ctx, ast.init);
|
||||
if (ctx.error) return;
|
||||
const condition = gen(ctx, ast.condition);
|
||||
if (ctx.error) return;
|
||||
const step = gen(ctx, ast.step);
|
||||
if (ctx.error) return;
|
||||
const body = gen(ctx, ast.body);
|
||||
genForSrcComment(ctx, ast);
|
||||
let inLoop = false;
|
||||
ctx.scopes.push({_prefix : ""});
|
||||
gen(ctx, ast.init);
|
||||
if (ctx.error) return;
|
||||
|
||||
let end=false;
|
||||
let condVar;
|
||||
|
||||
|
||||
const condName = gen(ctx, ast.condition);
|
||||
const cond = getScope(ctx, condName);
|
||||
if (cond.used) {
|
||||
inLoop = true;
|
||||
enterConditionalCode(ctx);
|
||||
condVar = newRef(ctx, "INT", "_cond");
|
||||
instantiateRef(ctx, condVar);
|
||||
|
||||
ctx.code +=
|
||||
`${condVar} = ctx->field->isTrue(${condName});\n` +
|
||||
`while (${condVar}) {\n`;
|
||||
} else {
|
||||
if ((typeof cond.value == "undefined")||(cond.value == null)) return error(ctx, ast, "condition value not assigned");
|
||||
if (cond.value.isZero()) end=true;
|
||||
}
|
||||
|
||||
|
||||
while (!end) {
|
||||
|
||||
const oldCode = ctx.code;
|
||||
ctx.code = "";
|
||||
|
||||
if (ast.body.type != "BLOCK") genSrcComment(ctx, ast.body);
|
||||
gen(ctx, ast.body);
|
||||
if (ctx.error) return;
|
||||
|
||||
gen(ctx, ast.step);
|
||||
if (ctx.error) return;
|
||||
|
||||
const condName2 = gen(ctx, ast.condition);
|
||||
const cond2 = getScope(ctx, condName2);
|
||||
|
||||
if (!inLoop) {
|
||||
if (cond2.used) {
|
||||
ctx.code = oldCode + ctx.code;
|
||||
inLoop = true;
|
||||
enterConditionalCode(ctx);
|
||||
condVar = newRef(ctx, "INT", "_cond");
|
||||
instantiateRef(ctx, condVar);
|
||||
|
||||
ctx.code =
|
||||
oldCode +
|
||||
ctx.code +
|
||||
`${condVar} = ctx->field->isTrue(${condName2});\n` +
|
||||
`while (${condVar}) {\n`;
|
||||
} else {
|
||||
ctx.code = oldCode + ctx.code;
|
||||
if (cond2.value.isZero()) end=true;
|
||||
}
|
||||
} else {
|
||||
ctx.code =
|
||||
oldCode +
|
||||
utils.ident(
|
||||
ctx.code +
|
||||
`${condVar} = ctx->field->isTrue(${condName2});\n`);
|
||||
end=true;
|
||||
}
|
||||
}
|
||||
if (inLoop) {
|
||||
ctx.code += "}\n";
|
||||
leaveConditionalCode(ctx);
|
||||
}
|
||||
ctx.scopes.pop();
|
||||
return `for (${init};bigInt(${condition}).neq(bigInt(0));${step}) { \n${body}\n }\n`;
|
||||
}
|
||||
|
||||
function genWhile(ctx, ast) {
|
||||
@@ -743,9 +866,9 @@ function genReturn(ctx, ast) {
|
||||
|
||||
function genSignalAssignConstrain(ctx, ast) {
|
||||
const res = genVarAssignement(ctx, ast);
|
||||
genConstraint(ctx, ast);
|
||||
// genConstraint(ctx, ast);
|
||||
return res;
|
||||
// return genVarAssignement(ctx, ast);
|
||||
// return genVarAssignement(ctx, ast);
|
||||
}
|
||||
|
||||
function genVarAddAssignement(ctx, ast) {
|
||||
@@ -772,12 +895,34 @@ function genMinusMinusLeft(ctx, ast) {
|
||||
return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "-", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]});
|
||||
}
|
||||
|
||||
function genAdd(ctx, ast) {
|
||||
const a = gen(ctx, ast.values[0]);
|
||||
function genBinaryOp(ctx, ast, op) {
|
||||
let aName = gen(ctx, ast.values[0]);
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
const a = getScope(ctx, aName);
|
||||
|
||||
let bName = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).add(bigInt(${b})).mod(__P__)`;
|
||||
const b = getScope(ctx, bName);
|
||||
|
||||
if ((!a.used)&&(typeof a.value == "undefined")) return error(ctx, ast, "Using a not assigned varialble: "+aName);
|
||||
if ((!b.used)&&(typeof b.value == "undefined")) return error(ctx, ast, "Using a not assigned varialble: "+bName);
|
||||
|
||||
let rName;
|
||||
if (a.used || b.used) {
|
||||
if (!a.used) {
|
||||
aName = instantiateConstant(ctx, a.value);
|
||||
}
|
||||
if (!b.used) {
|
||||
bName = instantiateConstant(ctx, b.value);
|
||||
}
|
||||
|
||||
rName = newRef(ctx, "BIGINT", "_tmp");
|
||||
instantiateRef(ctx, rName);
|
||||
ctx.code += `ctx->field->${op}(${rName},${aName}, ${bName});\n`;
|
||||
} else {
|
||||
rName = newRef(ctx, "BIGINT", "_tmp", ctx.field[op](a.value, b.value));
|
||||
}
|
||||
return rName;
|
||||
}
|
||||
|
||||
function genMul(ctx, ast) {
|
||||
|
||||
@@ -8,8 +8,8 @@ const compiler = require("./compiler");
|
||||
const util = require("util");
|
||||
const exec = util.promisify(require("child_process").exec);
|
||||
|
||||
const stringifyBigInts = require("snarkjs").stringifyBigInts;
|
||||
const unstringifyBigInts = require("snarkjs").unstringifyBigInts;
|
||||
const stringifyBigInts = require("./utils").stringifyBigInts;
|
||||
const unstringifyBigInts = require("./utils").unstringifyBigInts;
|
||||
const bigInt = require("snarkjs").bigInt;
|
||||
|
||||
module.exports = c_tester;
|
||||
@@ -35,12 +35,13 @@ async function c_tester(circomFile, mainComponent, _options) {
|
||||
` ${path.join(cdir, "main.cpp")}` +
|
||||
` ${path.join(cdir, "calcwit.cpp")}` +
|
||||
` ${path.join(cdir, "utils.cpp")}` +
|
||||
` ${path.join(cdir, "zqfield.cpp")}` +
|
||||
` -o ${path.join(dir.path, baseName)}` +
|
||||
` -I ${cdir}` +
|
||||
" -lgmp -std=c++11 -DSANITY_CHECK"
|
||||
);
|
||||
|
||||
console.log(dir.path);
|
||||
// console.log(dir.path);
|
||||
return new CTester(dir, baseName, mainComponent);
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ class CTester {
|
||||
for (let i=0; i<eOut.length; i++) {
|
||||
checkObject(prefix + "["+i+"]", eOut[i]);
|
||||
}
|
||||
} else if (typeof eOut == "object") {
|
||||
} else if ((typeof eOut == "object")&&(eOut.constructor.name == "Object")) {
|
||||
for (let k in eOut) {
|
||||
checkObject(prefix + "."+k, eOut[k]);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ const buildC = require("./c_build");
|
||||
const exec = require("./exec");
|
||||
const lc = require("./lcalgebra");
|
||||
const Ctx = require("./ctx");
|
||||
const ZqField = require("./zqfield");
|
||||
|
||||
module.exports = compile;
|
||||
|
||||
@@ -36,6 +37,7 @@ const parser = require("../parser/jaz.js").parser;
|
||||
const timeout = ms => new Promise(res => setTimeout(res, ms));
|
||||
|
||||
async function compile(srcFile, options) {
|
||||
options.p = options.p || __P__;
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
@@ -51,6 +53,7 @@ async function compile(srcFile, options) {
|
||||
assert(ast.type == "BLOCK");
|
||||
|
||||
const ctx = new Ctx();
|
||||
ctx.field = new ZqField(options.p);
|
||||
ctx.mainComponent = options.mainComponent || "main";
|
||||
ctx.filePath= fullFilePath;
|
||||
ctx.fileName= fullFileName;
|
||||
|
||||
@@ -1143,7 +1143,7 @@ function execConstrain(ctx, ast) {
|
||||
ctx.constraints.push(lc.toQEQ(res));
|
||||
}
|
||||
|
||||
if (ctx.constraints.length % 10000 == 0) console.log("Constraints: " + ctx.constraints.length);
|
||||
if ((ctx.constraints.length % 10000 == 0)&&(ctx.constraints.length>0)) console.log("Constraints: " + ctx.constraints.length);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
56
src/utils.js
56
src/utils.js
@@ -1,12 +1,16 @@
|
||||
const fnv = require("fnv-plus");
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
module.exports.ident =ident;
|
||||
|
||||
module.exports.extractSizes =extractSizes;
|
||||
module.exports.flatArray = flatArray;
|
||||
module.exports.csArr = csArr;
|
||||
module.exports.subArray = subArray;
|
||||
module.exports.accSizes = accSizes;
|
||||
module.exports.fnvHash = fnvHash;
|
||||
module.exports.stringifyBigInts = stringifyBigInts;
|
||||
module.exports.unstringifyBigInts = unstringifyBigInts;
|
||||
|
||||
function ident(text) {
|
||||
let lines = text.split("\n");
|
||||
@@ -17,10 +21,26 @@ function ident(text) {
|
||||
}
|
||||
|
||||
function extractSizes (o) {
|
||||
if (! Array.isArray(o)) return [1, 0];
|
||||
if (! Array.isArray(o)) return [];
|
||||
return [o.length, ...extractSizes(o[0])];
|
||||
}
|
||||
|
||||
function flatArray(a) {
|
||||
var res = [];
|
||||
fillArray(res, a);
|
||||
return res;
|
||||
|
||||
function fillArray(res, a) {
|
||||
if (Array.isArray(a)) {
|
||||
for (let i=0; i<a.length; i++) {
|
||||
fillArray(res, a[i]);
|
||||
}
|
||||
} else {
|
||||
res.push(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input [1,2,3]
|
||||
// Returns " ,1 ,2, 3"
|
||||
function csArr(_arr) {
|
||||
@@ -53,3 +73,37 @@ function fnvHash(str) {
|
||||
|
||||
|
||||
|
||||
function stringifyBigInts(o) {
|
||||
if ((typeof(o) == "bigint") || o.isZero !== undefined) {
|
||||
return o.toString(10);
|
||||
} else if (Array.isArray(o)) {
|
||||
return o.map(stringifyBigInts);
|
||||
} else if (typeof o == "object") {
|
||||
const res = {};
|
||||
for (let k in o) {
|
||||
res[k] = stringifyBigInts(o[k]);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
function unstringifyBigInts(o) {
|
||||
if ((typeof(o) == "string") && (/^[0-9]+$/.test(o) )) {
|
||||
return bigInt(o);
|
||||
} else if (Array.isArray(o)) {
|
||||
return o.map(unstringifyBigInts);
|
||||
} else if (typeof o == "object") {
|
||||
const res = {};
|
||||
for (let k in o) {
|
||||
res[k] = unstringifyBigInts(o[k]);
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
17
src/zqfield.js
Normal file
17
src/zqfield.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
module.exports = class ZqField {
|
||||
constructor(p) {
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
add(a, b) {
|
||||
return a.add(b).mod(this.p);
|
||||
}
|
||||
|
||||
lt(a, b) {
|
||||
return a.lt(b) ? bigInt(1) : bigInt(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user