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};