mirror of
https://github.com/arnaucube/circom.git
synced 2026-02-07 03:06:42 +01:00
First test added
This commit is contained in:
@@ -1,209 +0,0 @@
|
||||
const bigInt = require("big-integer");
|
||||
|
||||
module.exports = calculateWitness;
|
||||
|
||||
function calculateWitness(circuit, inputSignals) {
|
||||
const ctx = new RTCtx(circuit);
|
||||
|
||||
function iterateSelector(values, sels, cb) {
|
||||
if (!Array.isArray(values)) {
|
||||
return cb(sels, values);
|
||||
}
|
||||
for (let i=0; i<values.length; i++) {
|
||||
sels.push(i);
|
||||
iterateSelector(values[i], sels, cb);
|
||||
sels.pop(i);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.setSignal("one", [], bigInt(1));
|
||||
|
||||
for (let c in ctx.notInitSignals) {
|
||||
if (ctx.notInitSignals[c] == 0) ctx.triggerComponent(c);
|
||||
}
|
||||
|
||||
for (let s in inputSignals) {
|
||||
ctx.currentComponent = "main";
|
||||
iterateSelector(inputSignals[s], [], function(selector, value) {
|
||||
ctx.setSignal(s, selector, bigInt(value));
|
||||
});
|
||||
}
|
||||
|
||||
for (let i=0; i<ctx.witness.length; i++) {
|
||||
if (typeof(ctx.witness[i]) == "undefined") {
|
||||
throw("Signal not assigned: " + ctx.circuit.witnessNames[i].join(", "));
|
||||
}
|
||||
console.log(ctx.circuit.witnessNames[i].join(",") + " --> " + ctx.witness[i].toString());
|
||||
}
|
||||
return ctx.witness;
|
||||
}
|
||||
|
||||
class RTCtx {
|
||||
constructor(circuit) {
|
||||
this.scopes = [];
|
||||
this.circuit = circuit;
|
||||
this.witness = [];
|
||||
this.notInitSignals = {};
|
||||
for (let c in this.circuit.components) {
|
||||
this.notInitSignals[c] = this.circuit.components[c].inputSignals;
|
||||
if (this.notInitSignals == 0) {
|
||||
this.currentComponent = c;
|
||||
this.components.calc(this);
|
||||
this.currentComponent = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_sels2str(sels) {
|
||||
let res = "";
|
||||
for (let i=0; i<sels.length; i++) {
|
||||
res += `[${sels[i]}]`;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
setPin(componentName, componentSels, signalName, signalSels, value) {
|
||||
let fullName = componentName=="one" ? "one" : this.currentComponent + "." + componentName;
|
||||
fullName += this._sels2str(componentSels) +
|
||||
"."+
|
||||
signalName+
|
||||
this._sels2str(signalSels);
|
||||
this.setSignalFullName(fullName, value);
|
||||
}
|
||||
|
||||
setSignal(name, sels, value) {
|
||||
let fullName = this.currentComponent ? this.currentComponent + "." + name : name;
|
||||
fullName += this._sels2str(sels);
|
||||
this.setSignalFullName(fullName, value);
|
||||
}
|
||||
|
||||
triggerComponent(c) {
|
||||
console.log("Component Treiggered: " + c);
|
||||
|
||||
// Set notInitSignals to -1 to not initialize again
|
||||
this.notInitSignals[c] --;
|
||||
const oldComponent = this.currentComponent;
|
||||
this.currentComponent = c;
|
||||
const template = this.circuit.components[c].template;
|
||||
|
||||
const newScope = {};
|
||||
for (let p in this.circuit.components[c].params) {
|
||||
newScope[p] = this.circuit.components[c].params[p];
|
||||
}
|
||||
|
||||
const oldScope = this.scopes;
|
||||
this.scopes = [ this.scopes[0], newScope ];
|
||||
|
||||
// TODO set params.
|
||||
|
||||
this.circuit.templates[template](this);
|
||||
this.scopes = oldScope;
|
||||
this.currentComponent = oldComponent;
|
||||
}
|
||||
|
||||
callFunction(functionName, params) {
|
||||
|
||||
const newScope = {};
|
||||
for (let p=0; p<this.circuit.functionParams[functionName].length; p++) {
|
||||
const paramName = this.circuit.functionParams[functionName][p];
|
||||
newScope[paramName] = params[p];
|
||||
}
|
||||
|
||||
const oldScope = this.scopes;
|
||||
this.scopes = [ this.scopes[0], newScope ];
|
||||
|
||||
// TODO set params.
|
||||
|
||||
const res = this.circuit.functions[functionName](this);
|
||||
this.scopes = oldScope;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
setSignalFullName(fullName, value) {
|
||||
console.log("set " + fullName + " <-- " + value.toString());
|
||||
const sId = this.circuit.signals[fullName].id;
|
||||
let firstInit =false;
|
||||
if (!this.witness[sId]) {
|
||||
firstInit = true;
|
||||
}
|
||||
this.witness[sId] = value;
|
||||
const callComponents = [];
|
||||
for (let i=0; i<this.circuit.witnessNames[sId].length; i++) {
|
||||
const ss = this.circuit.witnessNames[sId][i];
|
||||
if (this.circuit.signals[ss].direction == "IN") {
|
||||
if (firstInit) this.notInitSignals[ this.circuit.signals[ss].component] --;
|
||||
callComponents.push(this.circuit.signals[ss].component);
|
||||
}
|
||||
}
|
||||
for (let i in callComponents) {
|
||||
const c= callComponents[i];
|
||||
if (this.notInitSignals[c] == 0) this.triggerComponent(c);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
setVar(name, sels, value) {
|
||||
function setVarArray(a, sels2, value) {
|
||||
if (sels2.length == 1) {
|
||||
a[sels2[0]] = value;
|
||||
} else {
|
||||
if (typeof(a[sels2[0]]) == "undefined") a[sels2[0]] = [];
|
||||
setVarArray(a[sels2[0]], sels2.slice(1), value);
|
||||
}
|
||||
}
|
||||
const scope = this.scopes[this.scopes.length-1];
|
||||
if (sels.length == 0) {
|
||||
scope[name] = value;
|
||||
} else {
|
||||
if (typeof(scope[name]) == "undefined") scope[name] = [];
|
||||
setVarArray(scope[name], sels, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
getVar(name, sels) {
|
||||
function select(a, sels2) {
|
||||
return (sels2.length == 0) ? a : select(a[sels2[0]], sels2.slice(1));
|
||||
}
|
||||
for (let i=this.scopes.length-1; i>=0; i--) {
|
||||
if (typeof(this.scopes[i][name]) != "undefined") return select(this.scopes[i][name], sels);
|
||||
}
|
||||
throw new Error("Variable not defined: " + name);
|
||||
}
|
||||
|
||||
getSignal(name, sels) {
|
||||
let fullName = name=="one" ? "one" : this.currentComponent + "." + name;
|
||||
fullName += this._sels2str(sels);
|
||||
return this.getSignalFullName(fullName);
|
||||
}
|
||||
|
||||
|
||||
getPin(componentName, componentSels, signalName, signalSels) {
|
||||
let fullName = componentName=="one" ? "one" : this.currentComponent + "." + componentName;
|
||||
fullName += this._sels2str(componentSels) +
|
||||
"."+
|
||||
signalName+
|
||||
this._sels2str(signalSels);
|
||||
return this.getSignalFullName(fullName);
|
||||
}
|
||||
|
||||
getSignalFullName(fullName) {
|
||||
const sId = this.circuit.signals[fullName].id;
|
||||
if (typeof(this.witness[sId]) == "undefined") {
|
||||
throw new Error("Signal not initialized: "+fullName);
|
||||
}
|
||||
console.log("get --->" + fullName + " = " + this.witness[sId].toString() );
|
||||
return this.witness[sId];
|
||||
}
|
||||
|
||||
assert(a,b) {
|
||||
const ba = bigInt(a);
|
||||
const bb = bigInt(b);
|
||||
if (!ba.equals(bb)) {
|
||||
throw new Error("Constrain doesn't match: " + ba.toString() + " != " + bb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const bigInt = require("big-integer");
|
||||
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const __MASK__ = new bigInt(2).pow(253).minus(1);
|
||||
const assert = require("assert");
|
||||
const gen = require("./gencode");
|
||||
const exec = require("./exec");
|
||||
const lc = require("./lcalgebra");
|
||||
|
||||
|
||||
const argv = require("optimist")
|
||||
.alias("c", "circuit")
|
||||
.alias("o", "output")
|
||||
.alias("w", "witnes")
|
||||
.argv;
|
||||
|
||||
const parser = require("../jaz.js").parser;
|
||||
|
||||
const fullFileName = path.resolve(process.cwd(), argv.circuit);
|
||||
const fullFilePath = path.dirname(fullFileName);
|
||||
|
||||
const src = fs.readFileSync(fullFileName, "utf8");
|
||||
const ast = parser.parse(src);
|
||||
|
||||
assert(ast.type == "BLOCK");
|
||||
|
||||
const ctx = {
|
||||
scopes: [{}],
|
||||
signals: {
|
||||
one: {
|
||||
fullName: "one",
|
||||
value: bigInt(1),
|
||||
equivalence: "",
|
||||
direction: ""
|
||||
}
|
||||
},
|
||||
currentComponent: "",
|
||||
constrains: [],
|
||||
components: {},
|
||||
templates: {},
|
||||
functions: {},
|
||||
functionParams: {},
|
||||
filePath: fullFilePath,
|
||||
fileName: fullFileName
|
||||
};
|
||||
|
||||
exec(ctx, ast);
|
||||
|
||||
reduceConstrains(ctx);
|
||||
generateWitnessNames(ctx);
|
||||
generateWitnessConstrains(ctx);
|
||||
|
||||
if (ctx.error) {
|
||||
console.log(`ERROR at ${ctx.error.errFile}:${ctx.error.pos.first_line},${ctx.error.pos.first_column}-${ctx.error.pos.last_line},${ctx.error.pos.last_column} ${ctx.error.errStr}`);
|
||||
console.log(JSON.stringify(ctx.error.ast, null, 1));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
console.log("SIGNALS");
|
||||
console.log("==========");
|
||||
for (let key in ctx.signals) {
|
||||
const signal = ctx.signals[key];
|
||||
console.log(signal.fullName);
|
||||
}
|
||||
|
||||
console.log("CONSTRAINS");
|
||||
console.log("==========");
|
||||
for (let i=0; i<ctx.constrains.length; i++) {
|
||||
console.log(lc.toString(ctx.constrains[i], ctx) + " === 0");
|
||||
}
|
||||
*/
|
||||
ctx.scopes = [{}];
|
||||
|
||||
const mainCode = gen(ctx,ast);
|
||||
if (ctx.error) {
|
||||
console.log(`ERROR at ${ctx.error.pos.first_line},${ctx.error.pos.first_column}-${ctx.error.pos.last_line},${ctx.error.pos.last_column} ${ctx.error.errStr}`);
|
||||
console.log(JSON.stringify(ctx.error.ast, null, 1));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
let outCode = "";
|
||||
outCode += "const bigInt = require(\"big-integer\");\n";
|
||||
outCode += "const __P__ = new bigInt(\"21888242871839275222246405745257275088696311157297823662689037894645226208583\");\n";
|
||||
outCode += "const __MASK__ = new bigInt(2).pow(253).minus(1);\n";
|
||||
outCode += "const circuit = {};\n";
|
||||
outCode += "module.exports = circuit;\n\n";
|
||||
outCode += `circuit.signals=${JSON.stringify(ctx.signals, null, 1)};\n\n`;
|
||||
outCode += `circuit.components=${JSON.stringify(ctx.components, null, 1)};\n\n`;
|
||||
outCode += `circuit.signalConstrains=${JSON.stringify(ctx.constrains, null, 1)};\n\n`;
|
||||
outCode += `circuit.witnessNames=${JSON.stringify(ctx.witnessNames, null, 1)};\n\n`;
|
||||
outCode += mainCode;
|
||||
outCode += "\ncircuit.templates = {};\n";
|
||||
for (let t in ctx.templates) {
|
||||
outCode += `\ncircuit.templates["${t}"] = ${ctx.templates[t]};\n`;
|
||||
}
|
||||
outCode += `circuit.functionParams=${JSON.stringify(ctx.functionParams, null, 1)};\n\n`;
|
||||
outCode += "\ncircuit.functions = {};\n";
|
||||
for (let f in ctx.functions) {
|
||||
outCode += `\ncircuit.functions["${f}"] = ${ctx.functions[f]};\n`;
|
||||
}
|
||||
|
||||
/*
|
||||
console.log("CODE");
|
||||
console.log("====");
|
||||
console.log(outCode);
|
||||
*/
|
||||
|
||||
|
||||
console.log("#Constrains:" +ctx.constrains.length);
|
||||
|
||||
fs.writeFileSync(argv.output, outCode, "utf8");
|
||||
|
||||
function generateWitnessNames(ctx) {
|
||||
ctx.witnessNames = [];
|
||||
for (let c in ctx.components) {
|
||||
ctx.components[c].inputSignals = 0;
|
||||
}
|
||||
for (let s in ctx.signals) {
|
||||
const signal = ctx.signals[s];
|
||||
let lSignal = signal;
|
||||
while (lSignal.equivalence) {
|
||||
lSignal = ctx.signals[lSignal.equivalence];
|
||||
}
|
||||
if ( typeof(lSignal.id) === "undefined" ) {
|
||||
lSignal.id = ctx.witnessNames.length;
|
||||
ctx.witnessNames.push([]);
|
||||
}
|
||||
if (signal.direction == "IN") {
|
||||
ctx.components[signal.component].inputSignals++;
|
||||
}
|
||||
|
||||
signal.id = lSignal.id;
|
||||
ctx.witnessNames[signal.id].push(signal.fullName);
|
||||
}
|
||||
}
|
||||
|
||||
function reduceConstrains(ctx) {
|
||||
const newConstrains = [];
|
||||
for (let i=0; i<ctx.constrains.length; i++) {
|
||||
const c = lc.canonize(ctx, ctx.constrains[i]);
|
||||
if (!lc.isZero(c)) {
|
||||
newConstrains.push(c);
|
||||
}
|
||||
}
|
||||
ctx.constrains = newConstrains;
|
||||
}
|
||||
|
||||
function generateWitnessConstrains(ctx) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
27
src/cli.js
Normal file
27
src/cli.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/* eslint-disable no-console */
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const compiler = require("./compiler");
|
||||
|
||||
const argv = require("yargs")
|
||||
.usage("jaz -s [input source circuit file] -o [output definition circuit file]")
|
||||
.alias("s", "source")
|
||||
.alias("o", "output")
|
||||
.require(["s","o"])
|
||||
.argv;
|
||||
|
||||
const fullFileName = path.resolve(process.cwd(), argv.source);
|
||||
|
||||
compiler(fullFileName).then( (cir) => {
|
||||
fs.writeFileSync(argv.output, JSON.stringify(cir, null, 1), "utf8");
|
||||
}, (err) => {
|
||||
console.error(`ERROR at ${err.errFile}:${err.pos.first_line},${err.pos.first_column}-${err.pos.last_line},${err.pos.last_column} ${err.errStr}`);
|
||||
console.error(JSON.stringify(err.ast, null, 1));
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
279
src/compiler.js
Normal file
279
src/compiler.js
Normal file
@@ -0,0 +1,279 @@
|
||||
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const bigInt = require("big-integer");
|
||||
const __P__ = new bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
const __MASK__ = new bigInt(2).pow(253).minus(1);
|
||||
const assert = require("assert");
|
||||
const gen = require("./gencode");
|
||||
const exec = require("./exec");
|
||||
const lc = require("./lcalgebra");
|
||||
|
||||
module.exports = compile;
|
||||
|
||||
const parser = require("../jaz.js").parser;
|
||||
|
||||
function compile(srcFile) {
|
||||
|
||||
return new Promise ((resolve, reject) => {
|
||||
const fullFileName = srcFile;
|
||||
const fullFilePath = path.dirname(fullFileName);
|
||||
|
||||
const src = fs.readFileSync(fullFileName, "utf8");
|
||||
const ast = parser.parse(src);
|
||||
|
||||
assert(ast.type == "BLOCK");
|
||||
|
||||
const ctx = {
|
||||
scopes: [{}],
|
||||
signals: {
|
||||
one: {
|
||||
fullName: "one",
|
||||
value: bigInt(1),
|
||||
equivalence: "",
|
||||
direction: ""
|
||||
}
|
||||
},
|
||||
currentComponent: "",
|
||||
constrains: [],
|
||||
components: {},
|
||||
templates: {},
|
||||
functions: {},
|
||||
functionParams: {},
|
||||
filePath: fullFilePath,
|
||||
fileName: fullFileName
|
||||
};
|
||||
|
||||
exec(ctx, ast);
|
||||
|
||||
reduceConstrains(ctx);
|
||||
generateWitnessNames(ctx);
|
||||
|
||||
if (ctx.error) {
|
||||
reject(ctx.error);
|
||||
}
|
||||
|
||||
ctx.scopes = [{}];
|
||||
|
||||
const mainCode = gen(ctx,ast);
|
||||
if (ctx.error) reject(ctx.error);
|
||||
|
||||
const def = buildCircuitDef(ctx, mainCode);
|
||||
|
||||
resolve(def);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function generateWitnessNames(ctx) {
|
||||
|
||||
const totals = {
|
||||
"output": 0,
|
||||
"pubInput": 0,
|
||||
"one": 0,
|
||||
"prvInput": 0,
|
||||
"internal": 0,
|
||||
"constant": 0,
|
||||
};
|
||||
const ids = {};
|
||||
|
||||
function priorize(t1, t2) {
|
||||
if ((t1 == "error") || (t2=="error")) return "error";
|
||||
if (t1 == "internal") {
|
||||
return t2;
|
||||
} else if (t2=="internal") {
|
||||
return t1;
|
||||
}
|
||||
if ((t1 == "one") || (t2 == "one")) return "one";
|
||||
if ((t1 == "constant") || (t2 == "constant")) return "constant";
|
||||
if (t1!=t2) return "error";
|
||||
return t1;
|
||||
}
|
||||
|
||||
// First classify the signals
|
||||
for (let s in ctx.signals) {
|
||||
const signal = ctx.signals[s];
|
||||
let tAll = "internal";
|
||||
let lSignal = signal;
|
||||
let end = false;
|
||||
while (!end) {
|
||||
let t = lSignal.category || "internal";
|
||||
if (s == "one") {
|
||||
t = "one";
|
||||
} else if (lSignal.value) {
|
||||
t = "constant";
|
||||
} else if (lSignal.component=="main") {
|
||||
if (lSignal.direction == "IN") {
|
||||
if (lSignal.private) {
|
||||
t = "prvInput";
|
||||
} else {
|
||||
t = "pubInput";
|
||||
}
|
||||
} else if (lSignal.direction == "OUT") {
|
||||
t = "output";
|
||||
}
|
||||
}
|
||||
tAll = priorize(t,tAll);
|
||||
if (lSignal.equivalence) {
|
||||
lSignal = ctx.signals[lSignal.equivalence];
|
||||
} else {
|
||||
end=true;
|
||||
}
|
||||
}
|
||||
if (tAll == "error") {
|
||||
throw new Error("Incompatible types in signal: " + s);
|
||||
}
|
||||
if (lSignal.category) totals[lSignal.category]--;
|
||||
lSignal.category = tAll;
|
||||
totals[lSignal.category] ++;
|
||||
}
|
||||
|
||||
ids["one"] = 0;
|
||||
ids["output"] = 1;
|
||||
ids["pubInput"] = ids["output"] + totals["output"];
|
||||
ids["prvInput"] = ids["pubInput"] + totals["pubInput"];
|
||||
ids["internal"] = ids["prvInput"] + totals["prvInput"];
|
||||
ids["constant"] = ids["internal"] + totals["internal"];
|
||||
const nSignals = ids["constant"] + totals["constant"];
|
||||
|
||||
ctx.signalNames = new Array(nSignals);
|
||||
for (let i=0; i< nSignals; i++) ctx.signalNames[i] = [];
|
||||
ctx.signalName2Idx = {};
|
||||
|
||||
for (let s in ctx.signals) {
|
||||
const signal = ctx.signals[s];
|
||||
let lSignal = signal;
|
||||
while (lSignal.equivalence) {
|
||||
lSignal = ctx.signals[lSignal.equivalence];
|
||||
}
|
||||
if ( typeof(lSignal.id) === "undefined" ) {
|
||||
lSignal.id = ids[lSignal.category] ++;
|
||||
}
|
||||
|
||||
signal.id = lSignal.id;
|
||||
ctx.signalNames[signal.id].push(signal.fullName);
|
||||
ctx.signalName2Idx[signal.fullName] = signal.id;
|
||||
}
|
||||
|
||||
ctx.totals = totals;
|
||||
}
|
||||
|
||||
function reduceConstrains(ctx) {
|
||||
const newConstrains = [];
|
||||
for (let i=0; i<ctx.constrains.length; i++) {
|
||||
const c = lc.canonize(ctx, ctx.constrains[i]);
|
||||
if (!lc.isZero(c)) {
|
||||
newConstrains.push(c);
|
||||
}
|
||||
}
|
||||
ctx.constrains = newConstrains;
|
||||
}
|
||||
|
||||
|
||||
function buildCircuitDef(ctx, mainCode) {
|
||||
const res = {
|
||||
mainCode: mainCode
|
||||
};
|
||||
res.signalName2Idx = ctx.signalName2Idx;
|
||||
|
||||
res.components = [];
|
||||
res.componentName2Idx = {};
|
||||
for (let c in ctx.components) {
|
||||
const idCoponent = res.components.length;
|
||||
res.components.push({
|
||||
name: c,
|
||||
params: ctx.components[c].params,
|
||||
template: ctx.components[c].template,
|
||||
inputSignals: 0
|
||||
});
|
||||
res.componentName2Idx[c] = idCoponent;
|
||||
}
|
||||
|
||||
res.signals = new Array(ctx.signalNames.length);
|
||||
for (let i=0; i<ctx.signalNames.length; i++) {
|
||||
res.signals[i] = {
|
||||
names: ctx.signalNames[i],
|
||||
triggerComponents: []
|
||||
};
|
||||
ctx.signalNames[i].map( (fullName) => {
|
||||
const idComponet = res.componentName2Idx[ctx.signals[fullName].component];
|
||||
if (ctx.signals[fullName].direction == "IN") {
|
||||
res.signals[i].triggerComponents.push(idComponet);
|
||||
res.components[idComponet].inputSignals++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
res.constrains = buildConstrains(ctx);
|
||||
|
||||
res.templates = ctx.templates;
|
||||
|
||||
res.functions = {};
|
||||
for (let f in ctx.functions) {
|
||||
res.functions[f] = {
|
||||
params: ctx.functionParams[f],
|
||||
func: ctx.functions[f]
|
||||
};
|
||||
}
|
||||
|
||||
res.nPrvInputs = ctx.totals.prvInput;
|
||||
res.nPubInputs = ctx.totals.pubInput;
|
||||
res.nInputs = res.nPrvInputs + res.nPubInputs;
|
||||
res.nOutputs = ctx.totals.output;
|
||||
res.nVars = res.nInputs + res.nOutputs + ctx.totals.one + ctx.totals.internal;
|
||||
res.nConstants = ctx.totals.constant;
|
||||
res.nSignals = res.nVars + res.nConstants;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Build constrains
|
||||
|
||||
A constrain like this
|
||||
|
||||
[s1 + 2*s2 + 3*s3] * [ s2 + 5*s4] - [s0 ] = 0
|
||||
[ 5*s2 + 6*s3] * [ s2 + ] - [s0 + 2* s2] = 0
|
||||
[s1 + s3] * [ s2 + 5*s3] - [s4 ] = 0
|
||||
|
||||
is converted to
|
||||
|
||||
[
|
||||
[{"1":"1","2":"2","3":"3"} , {"2":"1","4":"5"} , {"0":"1" }],
|
||||
[{ "2":"5","3":"6"} , {"2":"1" } , {"0":"1", "2":"2"}],
|
||||
[{"1":"1", "3":"1"} , {"2":"1","3":"5"} , {"4":"1" }]
|
||||
]
|
||||
^ ^ ^
|
||||
| | |
|
||||
A B C
|
||||
|
||||
*/
|
||||
|
||||
function buildConstrains(ctx) {
|
||||
const res = [];
|
||||
|
||||
function fillLC(dst, src) {
|
||||
for (let s in src.values) {
|
||||
const v = src.values[s].toString();
|
||||
const id = ctx.signalName2Idx[s];
|
||||
dst[id] = v;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i=0; i<ctx.constrains.length; i++) {
|
||||
const A = {};
|
||||
const B = {};
|
||||
const C = {};
|
||||
|
||||
fillLC(A, ctx.constrains[i].a);
|
||||
fillLC(B, ctx.constrains[i].b);
|
||||
fillLC(C, lc.negate(ctx.constrains[i].c));
|
||||
|
||||
res.push([A,B,C]);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -419,6 +419,7 @@ function execDeclareSignal(ctx, ast) {
|
||||
ctx.signals[fullName] = {
|
||||
fullName: fullName,
|
||||
direction: ast.declareType == "SIGNALIN" ? "IN" : (ast.declareType == "SIGNALOUT" ? "OUT" : ""),
|
||||
private: ast.private,
|
||||
component: ctx.currentComponent,
|
||||
equivalence: "",
|
||||
alias: [fullName]
|
||||
@@ -828,8 +829,6 @@ function execInclude(ctx, ast) {
|
||||
const incFileName = path.resolve(ctx.filePath, ast.file);
|
||||
const incFilePath = path.dirname(incFileName);
|
||||
|
||||
console.log("Include: "+incFileName);
|
||||
|
||||
ctx.includedFiles = ctx.includedFiles || [];
|
||||
if (ctx.includedFiles[incFileName]) return;
|
||||
|
||||
|
||||
@@ -368,7 +368,7 @@ function genVarMulAssignement(ctx, ast) {
|
||||
}
|
||||
|
||||
function genPlusPlusRight(ctx, ast) {
|
||||
return `(${genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "+", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]})}).add(__P__).minus(1).mod(__P__)`;
|
||||
return `(${genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "+", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]})}).add(__P__).sub(bigInt(1)).mod(__P__)`;
|
||||
}
|
||||
|
||||
function genPlusPlusLeft(ctx, ast) {
|
||||
@@ -380,7 +380,7 @@ function genAdd(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).add(${b}).mod(__P__)`;
|
||||
return `bigInt(${a}).add(bigInt(${b})).mod(__P__)`;
|
||||
}
|
||||
|
||||
function genMul(ctx, ast) {
|
||||
@@ -388,7 +388,7 @@ function genMul(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).times(${b}).mod(__P__)`;
|
||||
return `bigInt(${a}).mul(bigInt(${b})).mod(__P__)`;
|
||||
}
|
||||
|
||||
function genSub(ctx, ast) {
|
||||
@@ -396,7 +396,7 @@ function genSub(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).add(__P__).minus(${b}).mod(__P__)`;
|
||||
return `bigInt(${a}).add(__P__).sub(bigInt(${b})).mod(__P__)`;
|
||||
}
|
||||
|
||||
function genExp(ctx, ast) {
|
||||
@@ -404,7 +404,7 @@ function genExp(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).modPow(${b}, __P__)`;
|
||||
return `bigInt(${a}).modPow(bigInt(${b}), __P__)`;
|
||||
}
|
||||
|
||||
function genBAnd(ctx, ast) {
|
||||
@@ -412,7 +412,7 @@ function genBAnd(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).and(${b}).and(__MASK__)`;
|
||||
return `bigInt(${a}).and(bigInt(${b})).and(__MASK__)`;
|
||||
}
|
||||
|
||||
function genShl(ctx, ast) {
|
||||
@@ -420,7 +420,7 @@ function genShl(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${b}).greater(256) ? 0 : bigInt(${a}).shiftLeft(bigInt(${b}).value).and(__MASK__)`;
|
||||
return `bigInt(${b}).greater(bigInt(256)) ? 0 : bigInt(${a}).shl(bigInt(${b})).and(__MASK__)`;
|
||||
}
|
||||
|
||||
function genShr(ctx, ast) {
|
||||
@@ -428,7 +428,7 @@ function genShr(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${b}).greater(256) ? 0 : bigInt(${a}).shiftRight(bigInt(${b}).value).and(__MASK__)`;
|
||||
return `bigInt(${b}).greater(bigInt(256)) ? 0 : bigInt(${a}).shr(bigInt(${b})).and(__MASK__)`;
|
||||
}
|
||||
|
||||
function genLt(ctx, ast) {
|
||||
@@ -436,7 +436,7 @@ function genLt(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).lt(${b}) ? 1 : 0`;
|
||||
return `bigInt(${a}).lt(bigInt(${b})) ? 1 : 0`;
|
||||
}
|
||||
|
||||
function genEq(ctx, ast) {
|
||||
@@ -444,13 +444,13 @@ function genEq(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const b = gen(ctx, ast.values[1]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).eq(${b}) ? 1 : 0`;
|
||||
return `bigInt(${a}).eq(bigInt(${b})) ? 1 : 0`;
|
||||
}
|
||||
|
||||
function genUMinus(ctx, ast) {
|
||||
const a = gen(ctx, ast.values[0]);
|
||||
if (ctx.error) return;
|
||||
return `__P__.minus(bigInt(${a})).mod(__P__)`;
|
||||
return `__P__.sub(bigInt(${a})).mod(__P__)`;
|
||||
}
|
||||
|
||||
function genTerCon(ctx, ast) {
|
||||
@@ -460,7 +460,7 @@ function genTerCon(ctx, ast) {
|
||||
if (ctx.error) return;
|
||||
const c = gen(ctx, ast.values[2]);
|
||||
if (ctx.error) return;
|
||||
return `bigInt(${a}).neq(0) ? (${b}) : (${c})`;
|
||||
return `bigInt(${a}).neq(bigInt(0)) ? (${b}) : (${c})`;
|
||||
}
|
||||
|
||||
function genInclude(ctx, ast) {
|
||||
|
||||
@@ -418,7 +418,15 @@ function canonize(ctx, a) {
|
||||
for (let k in a.values) {
|
||||
let s = k;
|
||||
while (ctx.signals[s].equivalence) s= ctx.signals[s].equivalence;
|
||||
if (s != k) {
|
||||
if (typeof(ctx.signals[s].value) != "undefined") {
|
||||
const v = a.values[k].times(ctx.signals[s].value).mod(__P__);
|
||||
if (!a.values["one"]) {
|
||||
a.values["one"]=v;
|
||||
} else {
|
||||
a.values["one"]= a.values["one"].add(v).mod(__P__);
|
||||
}
|
||||
delete a.values[k];
|
||||
} else if (s != k) {
|
||||
if (!a.values[s]) {
|
||||
a.values[s]=bigInt(a.values[k]);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user