arnaucube
arnaucube/circomPublic Self-hosted repository
circom/src/ctx.js
src/ctx.jsRaw
  1const BigArray = require("./bigarray.js");
  2const F1Field = require("ffjavascript").F1Field;
  3
  4class TableName {
  5    constructor (ctx) {
  6        this.ctx = ctx;
  7        this.o = {};
  8    }
  9
 10    _allocElement(name, _sizes, type) {
 11        const sizes = _sizes || [];
 12        let l = 1;
 13        for (let i=0; i<sizes.length; i++) {
 14            l = l*sizes[i];
 15        }
 16        this.o[name] = {
 17            sizes: sizes,
 18            type: type
 19        };
 20        return l;
 21    }
 22
 23    addSignal(name, sizes) {
 24        const l = this._allocElement(name, sizes, "S");
 25        const o = this.ctx.nSignals;
 26        this.o[name].offset = o;
 27        this.ctx.nSignals += l;
 28        if (l>1) {
 29            return [o, o+l];
 30        } else {
 31            return o;
 32        }
 33    }
 34
 35    addComponent(name, sizes) {
 36        const l = this._allocElement(name, sizes, "C");
 37        const o = this.ctx.nComponents;
 38        this.o[name].offset = o;
 39        this.ctx.nComponents += l;
 40        if (l>1) {
 41            return [o, o+l];
 42        } else {
 43            return o;
 44        }
 45    }
 46
 47    _getElement(name, _sels, type) {
 48        const sels = _sels || [];
 49        const s = this.o[name];
 50        if (!s) return -1;
 51        if (s.type != type) return -1;
 52        if (sels.length > s.sizes.length) return -1;
 53        let l=1;
 54        for (let i = s.sizes.length-1; i>sels.length; i--) {
 55            l = l*s.sizes[i];
 56        }
 57        let o =0;
 58        let p=1;
 59        for (let i=sels.length-1; i>=0; i--) {
 60            if (sels[i] > s.sizes[i]) return -1; // Out of range
 61            if (sels[i] < 0) return -1; // Out of range
 62            o += p*sels[i];
 63            p *= s.sizes[i];
 64        }
 65        if (l>1) {
 66            return [s.offset + o, s.offset + o + l];
 67        } else {
 68            return s.offset + o;
 69        }
 70    }
 71
 72    getSignalIdx(name, sels) {
 73        return this._getElement(name, sels, "S");
 74    }
 75
 76    getComponentIdx(name, sels) {
 77        return this._getElement(name, sels, "C");
 78    }
 79
 80    getSizes(name) {
 81        return this.o[name].sels;
 82    }
 83
 84}
 85
 86module.exports = class Ctx {
 87
 88    constructor(p) {
 89
 90        this.F = new F1Field(p);
 91
 92        this.stONE = 1;
 93        this.stOUTPUT = 2;
 94        this.stPUBINPUT = 3;
 95        this.stPRVINPUT = 4;
 96        this.stINTERNAL = 5;
 97        this.stDISCARDED = 6;
 98        this.stCONSTANT = 7;
 99
100        this.IN = 0x01;
101        this.OUT = 0x02;
102        this.PRV = 0x04;
103        this.ONE = 0x08;
104        this.MAIN = 0x10;
105        this.COUNTED = 0x20;
106
107        this.scopes = [{}];
108        this.signals = new BigArray();
109
110        this.currentComponent= -1;
111        this.constraints= new BigArray();
112        this.components= new BigArray();
113        this.templates= {};
114        this.functions= {};
115        this.functionParams= {};
116        this.nSignals = 0;
117        this.nComponents =0;
118        this.names = new TableName(this);
119        this.main=false;
120        this.error = null;
121        this.warnings = [];
122
123        const oneIdx = this.addSignal("one");
124        this.signals[oneIdx] = {
125            v: this.F.one,
126            o: this.ONE,
127            e: -1,
128        };
129
130        this.uniqueNames = {};
131    }
132
133    addSignal(name, sizes) {
134        if (this.currentComponent>=0) {
135            return this.components[this.currentComponent].names.addSignal(name, sizes);
136        } else {
137            return this.names.addSignal(name, sizes);
138        }
139    }
140
141    addComponent(name, sizes) {
142        if (this.currentComponent>=0) {
143            return this.components[this.currentComponent].names.addComponent(name, sizes);
144        } else {
145            return this.names.addComponent(name, sizes);
146        }
147    }
148
149    getSignalIdx(name, sels) {
150        if (this.currentComponent>=0) {
151            return this.components[this.currentComponent].names.getSignalIdx(name, sels);
152        } else {
153            return this.names.getSignalIdx(name, sels);
154        }
155    }
156
157    getComponentIdx(name, sels) {
158        if (this.currentComponent>=0) {
159            return this.components[this.currentComponent].names.getComponentIdx(name, sels);
160        } else {
161            return this.names.getComponentIdx(name, sels);
162        }
163    }
164
165    getSizes(name) {
166        if (this.currentComponent>=0) {
167            return this.components[this.currentComponent].names.getSizes(name);
168        } else {
169            return this.names.getSizes(name);
170        }
171    }
172
173    newTableName() {
174        return new TableName(this);
175    }
176
177    _buildErr(ast, errStr) {
178        if (typeof ast == "string") {
179            ast = null;
180            errStr = ast;
181        }
182        if (ast) {
183            return {
184                pos:   {
185                    first_line: ast.first_line,
186                    first_column: ast.first_column,
187                    last_line: ast.last_line,
188                    last_column: ast.last_column
189                },
190                errStr: errStr,
191                ast: ast,
192                message: errStr,
193                errFile: this.fileName
194            };
195        } else {
196            return {
197                errStr: errStr,
198                message: errStr
199            };
200        }
201    }
202
203    throwError(ast, errStr) {
204        const err = this._buildErr(ast, errStr);
205        this.error = err;
206    }
207
208    logWarning(ast, errStr) {
209        const w = this._buildErr(ast, errStr);
210        this.warnings.push(w);
211    }
212
213    getUniqueName(suggestedName) {
214        if (!suggestedName) {
215            suggestedName = "_tmp";
216        }
217
218        if (typeof(this.uniqueNames[suggestedName]) == "undefined") {
219            this.uniqueNames[suggestedName] = 1;
220            return suggestedName;
221        } else {
222            const name = suggestedName + "_" + this.uniqueNames[suggestedName];
223            this.uniqueNames[suggestedName]++;
224            return name;
225        }
226    }
227
228};