circom/src/ctx.js
src/ctx.jsRaw
1const bigInt = require("big-integer");
2
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() {
89
90 this.stONE = 1;
91 this.stOUTPUT = 2;
92 this.stPUBINPUT = 3;
93 this.stPRVINPUT = 4;
94 this.stINTERNAL = 5;
95 this.stDISCARDED = 6;
96 this.stCONSTANT = 7;
97
98 this.IN = 0x01;
99 this.OUT = 0x02;
100 this.PRV = 0x04;
101 this.ONE = 0x08;
102 this.MAIN = 0x10;
103 this.COUNTED = 0x20;
104
105 this.scopes = [{}];
106 this.signals = [];
107
108 this.currentComponent= -1;
109 this.constraints= [];
110 this.components= [];
111 this.templates= {};
112 this.functions= {};
113 this.functionParams= {};
114 this.nSignals = 0;
115 this.nComponents =0;
116 this.names = new TableName(this);
117 this.main=false;
118 this.error = null;
119 this.warnings = [];
120
121 const oneIdx = this.addSignal("one");
122 this.signals[oneIdx] = {
123 v: bigInt(1),
124 o: this.ONE,
125 e: -1,
126 };
127
128 this.uniqueNames = {};
129 }
130
131 addSignal(name, sizes) {
132 if (this.currentComponent>=0) {
133 return this.components[this.currentComponent].names.addSignal(name, sizes);
134 } else {
135 return this.names.addSignal(name, sizes);
136 }
137 }
138
139 addComponent(name, sizes) {
140 if (this.currentComponent>=0) {
141 return this.components[this.currentComponent].names.addComponent(name, sizes);
142 } else {
143 return this.names.addComponent(name, sizes);
144 }
145 }
146
147 getSignalIdx(name, sels) {
148 if (this.currentComponent>=0) {
149 return this.components[this.currentComponent].names.getSignalIdx(name, sels);
150 } else {
151 return this.names.getSignalIdx(name, sels);
152 }
153 }
154
155 getComponentIdx(name, sels) {
156 if (this.currentComponent>=0) {
157 return this.components[this.currentComponent].names.getComponentIdx(name, sels);
158 } else {
159 return this.names.getComponentIdx(name, sels);
160 }
161 }
162
163 getSizes(name) {
164 if (this.currentComponent>=0) {
165 return this.components[this.currentComponent].names.getSizes(name);
166 } else {
167 return this.names.getSizes(name);
168 }
169 }
170
171 newTableName() {
172 return new TableName(this);
173 }
174
175 _buildErr(ast, errStr) {
176 if (typeof ast == "string") {
177 ast = null;
178 errStr = ast;
179 }
180 if (ast) {
181 return {
182 pos: {
183 first_line: ast.first_line,
184 first_column: ast.first_column,
185 last_line: ast.last_line,
186 last_column: ast.last_column
187 },
188 errStr: errStr,
189 ast: ast,
190 message: errStr,
191 errFile: ast.fileName
192 };
193 } else {
194 return {
195 errStr: errStr,
196 message: errStr
197 };
198 }
199 }
200
201 throwError(ast, errStr) {
202 const err = this._buildErr(ast, errStr);
203 this.error = err;
204 }
205
206 logWarning(ast, errStr) {
207 const w = this._buildErr(ast, errStr);
208 this.warnings.push(w);
209 }
210
211 getUniqueName(suggestedName) {
212 if (!suggestedName) {
213 suggestedName = "_tmp";
214 }
215
216 if (typeof(this.uniqueNames[suggestedName]) == "undefined") {
217 this.uniqueNames[suggestedName] = 1;
218 return suggestedName;
219 } else {
220 const name = suggestedName + "_" + this.uniqueNames[suggestedName];
221 this.uniqueNames[suggestedName]++;
222 return name;
223 }
224 }
225
226};