circom/src/c_gen.js
src/c_gen.jsRaw
1const bigInt = require("big-integer");
2const utils = require("./utils");
3
4module.exports = gen;
5
6
7function newRef(ctx, type, _name, value, _sizes) {
8 const isValue = ((typeof(value) != "undefined")&&(value != null));
9 let name;
10 let sizes;
11 if (!_name) {
12 name = ctx.getTmpName();
13 } else {
14 if (_name[0] =="_") {
15 name = ctx.getTmpName(_name);
16 } else {
17 name = _name;
18 }
19 }
20 if (typeof(_sizes) == "string") {
21 sizes = _sizes;
22 } else if (Array.isArray(_sizes)) {
23 sizes = newSizes(ctx, _sizes);
24 } else if (isValue) {
25 sizes = newSizes(ctx, utils.extractSizes(value));
26 } else {
27 sizes = newSizes(ctx, []);
28 }
29
30 const scope = ctx.scopes[ctx.scopes.length-1];
31 if (scope[name]) return error("Variable already exists: " + name);
32
33 const label = scope._prefix + name;
34 scope[name] = {
35 stack: true,
36 type: type,
37 used: false,
38 sizes: sizes,
39 label: label
40 };
41
42 if (isValue) {
43 scope[name].value = value;
44 }
45
46 return name;
47}
48
49function newSizes(ctx, sizes) {
50 const scope = ctx.scopes[ctx.scopes.length-1];
51
52 const name = ctx.getTmpName("_sz");
53
54 scope[name] = {
55 stack: true,
56 type: "SIZES",
57 used: false,
58 dim: sizes.length,
59 label: name,
60 value: sizes
61 };
62
63 return name;
64}
65
66
67function instantiateRef(ctx, name) {
68 const v = getScope(ctx, name);
69 if (!v.stack) return error("Using a non existing var: " + name);
70 if (v.used) return;
71
72 if (v.type=="BIGINT") {
73
74 const iSize = getScope(ctx, v.sizes);
75
76 if (iSize.used) {
77 const labelSize = iSize.label;
78 ctx.codeHeader += `PBigInt ${v.label};\n`;
79 ctx.code += `${v.label} = ctx->allocBigInts(${labelSize});\n`;
80 ctx.codeFooter += `ctx->freeBigInts(${v.label}, ${labelSize});\n`;
81 } else if (iSize.value) {
82 const labelSize = ctx.addSizes(iSize.value);
83 ctx.codeHeader += `PBigInt ${v.label} = ctx->allocBigInts(${labelSize});\n`;
84 ctx.codeFooter += `ctx->freeBigInts(${v.label}, ${labelSize});\n`;
85 } else {
86 return error(ctx, null, "Undefined Sizes: " +name);
87 }
88
89 } else if (v.type=="INT") {
90 ctx.codeHeader += `int ${v.label};\n`;
91 } else if (v.type=="SIZES") {
92 ctx.codeHeader += `Circom_Sizes ${v.label};\n`;
93 }
94 v.used = true;
95}
96
97
98function error(ctx, ast, errStr) {
99 ctx.error = {
100 pos: {
101 first_line: ast.first_line,
102 first_column: ast.first_column,
103 last_line: ast.last_line,
104 last_column: ast.last_column
105 },
106 errStr: errStr,
107 ast: ast,
108 message: errStr
109 };
110}
111
112
113function getScope(ctx, name) {
114 for (let i=ctx.scopes.length-1; i>=0; i--) {
115 if (ctx.scopes[i][name]) return ctx.scopes[i][name];
116 }
117 return null;
118}
119
120
121
122function gen(ctx, ast) {
123 if ((ast.type == "NUMBER") ) {
124 return genNumber(ctx, ast);
125 } else if (ast.type == "VARIABLE") {
126 return genVariable(ctx, ast);
127 } else if (ast.type == "PIN") {
128 return genPin(ctx, ast);
129 } else if (ast.type == "OP") {
130 if (ast.op == "=") {
131 return genVarAssignement(ctx, ast);
132 } else if (ast.op == "<--") {
133 return genVarAssignement(ctx, ast);
134 } else if (ast.op == "<==") {
135 return genSignalAssignConstrain(ctx, ast);
136 } else if (ast.op == "===") {
137 return genConstraint(ctx, ast);
138 } else if (ast.op == "+=") {
139 return genVarAddAssignement(ctx, ast);
140 } else if (ast.op == "*=") {
141 return genVarMulAssignement(ctx, ast);
142 } else if (ast.op == "+") {
143 return genAdd(ctx, ast);
144 } else if (ast.op == "-") {
145 return genSub(ctx, ast);
146 } else if (ast.op == "UMINUS") {
147 return genUMinus(ctx, ast);
148 } else if (ast.op == "*") {
149 return genMul(ctx, ast);
150 } else if (ast.op == "%") {
151 return genMod(ctx, ast);
152 } else if (ast.op == "PLUSPLUSRIGHT") {
153 return genPlusPlusRight(ctx, ast);
154 } else if (ast.op == "PLUSPLUSLEFT") {
155 return genPlusPlusLeft(ctx, ast);
156 } else if (ast.op == "MINUSMINUSRIGHT") {
157 return genMinusMinusRight(ctx, ast);
158 } else if (ast.op == "MINUSMINUSLEFT") {
159 return genMinusMinusLeft(ctx, ast);
160 } else if (ast.op == "**") {
161 return genExp(ctx, ast);
162 } else if (ast.op == "/") {
163 return genDiv(ctx, ast);
164 } else if (ast.op == "\\") {
165 return genIDiv(ctx, ast);
166 } else if (ast.op == "&") {
167 return genBAnd(ctx, ast);
168 } else if (ast.op == "&&") {
169 return genAnd(ctx, ast);
170 } else if (ast.op == "||") {
171 return genOr(ctx, ast);
172 } else if (ast.op == "<<") {
173 return genShl(ctx, ast);
174 } else if (ast.op == ">>") {
175 return genShr(ctx, ast);
176 } else if (ast.op == "<") {
177 return genLt(ctx, ast);
178 } else if (ast.op == ">") {
179 return genGt(ctx, ast);
180 } else if (ast.op == "<=") {
181 return genLte(ctx, ast);
182 } else if (ast.op == ">=") {
183 return genGte(ctx, ast);
184 } else if (ast.op == "==") {
185 return genEq(ctx, ast);
186 } else if (ast.op == "!=") {
187 return genNeq(ctx, ast);
188 } else if (ast.op == "?") {
189 return genTerCon(ctx, ast);
190 } else {
191 error(ctx, ast, "Invalid operation: " + ast.op);
192 }
193 } else if (ast.type == "DECLARE") {
194 if (ast.declareType == "COMPONENT") {
195 return genDeclareComponent(ctx, ast);
196 } else if ((ast.declareType == "SIGNALIN")||
197 (ast.declareType == "SIGNALOUT")||
198 (ast.declareType == "SIGNAL")) {
199 return genDeclareSignal(ctx, ast);
200 } else if (ast.declareType == "VARIABLE") {
201 return genDeclareVariable(ctx, ast);
202 } else {
203 error(ctx, ast, "Invalid declaration: " + ast.declareType);
204 }
205 } else if (ast.type == "FUNCTIONCALL") {
206 return genFunctionCall(ctx, ast);
207 } else if (ast.type == "BLOCK") {
208 return genBlock(ctx, ast);
209 } else if (ast.type == "COMPUTE") {
210 return genCompute(ctx, ast);
211 } else if (ast.type == "FOR") {
212 return genFor(ctx, ast);
213 } else if (ast.type == "WHILE") {
214 return genWhile(ctx, ast);
215 } else if (ast.type == "IF") {
216 return genIf(ctx, ast);
217 } else if (ast.type == "RETURN") {
218 return genReturn(ctx, ast);
219 } else if (ast.type == "INCLUDE") {
220 return genInclude(ctx, ast);
221 } else if (ast.type == "ARRAY") {
222 return genArray(ctx, ast);
223 } else {
224 error(ctx, ast, "GEN -> Invalid AST node type: " + ast.type);
225 }
226}
227
228function genBlock(ctx, ast) {
229 const oldCode = ctx.code;
230 let res = null;
231 ctx.code = "";
232 for (let i=0; i<ast.statements.length; i++) {
233 if (["BLOCK", "COMPUTE", "FOR", "WHILE", "IF"].indexOf(ast.statements[i].type)<0) {
234 genSrcComment(ctx, ast.statements[i]);
235 }
236 res = gen(ctx, ast.statements[i]);
237 if (ctx.error) return;
238 }
239 if (ctx.scopes.length>1) {
240 ctx.code = oldCode + `{\n${utils.ident(ctx.code)}}\n`;
241 } else {
242 ctx.code = oldCode + ctx.code;
243 }
244 return res;
245}
246
247function genSrcComment(ctx, ast) {
248 let codes = [];
249 const fl= ast.first_line-1;
250 const ll = ast.last_line-1;
251 const fc = ast.first_column-1;
252 const lc = ast.last_column;
253 for (let i=fl; i<=ll; i++) {
254 const p1 = i==fl ? fc : 0;
255 const p2 = i==ll ? lc : -1;
256 codes.push(ctx.includedFiles[ctx.fileName][i].slice(p1, p2>=0 ? p2 : undefined));
257 }
258 ctx.code += "\n/* "+codes.join("\n")+"*/\n";
259}
260
261
262function genDeclareComponent(ctx, ast) {
263 const scope = ctx.scopes[ctx.scopes.length - 1];
264
265 if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid component name");
266 if (getScope(ctx, ast.name.name)) return error(ctx, ast, "Name already exists: "+ast.name.name);
267
268 scope[ast.name.name] = {
269 type: "COMPONENT",
270 label: ast.name.name
271 };
272
273 return ast.name.name;
274}
275
276function genDeclareSignal(ctx, ast) {
277 const scope = ctx.scopes[ctx.scopes.length-1];
278
279 if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid component name");
280 if (getScope(ctx, ast.name.name)) return error(ctx, ast, "Name already exists: "+ast.name.name);
281
282 const res = {
283 type: "SIGNAL",
284 label: ast.name.name
285 };
286
287 scope[ast.name.name] = res;
288
289 return res;
290}
291
292function genDeclareVariable(ctx, ast) {
293
294 const scope = ctx.scopes[ctx.scopes.length-1];
295
296 const varName = ast.name.name;
297 const labelName = scope._prefix + ast.name.name;
298
299 if (ast.name.type != "VARIABLE") return error(ctx, ast, "Invalid component name");
300 if (ctx.scope[varName]) return error(ctx, ast, "Name already exists: "+varName);
301
302 const sizes=[];
303 let instantiate = false;
304 for (let i=0; i< ast.name.selectors.length; i++) {
305 const size = gen(ctx, ast.name.selectors[i]);
306 if (ctx.error) return;
307
308 if (size.used) {
309 instantiate = true;
310 sizes.push(`BigInt2Int(${scope[size].label})`);
311 } else {
312 sizes.push(size.value.toJSNumber());
313 }
314
315 sizes.push( size.value.toJSNumber() );
316 }
317
318 const vSizes = newRef(ctx, "SIZES", "_sizes");
319 const iSizes = scope[vSizes];
320 iSizes.dim = ast.name.selectors.length;
321 if (instantiate) {
322 instantiateRef(ctx, vSizes);
323 ctx.code += `${iSizes.label}[${iSizes.dim+1}]=0`;
324 ctx.code += `${iSizes.label}[${iSizes.dim}]=1`;
325 for (let i=iSizes.dim-1; i>=0; i--) {
326 ctx.code += `${iSizes.label}[${i}] = ${sizes[i]}*${iSizes.label}[${i+1}];\n`;
327 }
328 } else {
329 iSizes.value = sizes;
330 }
331
332 const res = ctx.scope[varName] = {
333 stack: true,
334 type: "BIGINT",
335 sizes: vSizes,
336 label: labelName
337 };
338
339 scope[varName] = res;
340
341 return res;
342}
343
344function genNumber(ctx, ast) {
345 return newRef(ctx, "BIGINT", "_num", ast.value);
346}
347
348
349
350function genGetOffset(ctx, vOffset, vSizes, sels) {
351
352 let rN = 0;
353 let rStr = "";
354 let iOffset;
355
356 if (vOffset) {
357 iOffset = getScope(ctx, vOffset);
358 if (iOffset.used) {
359 rStr += iOffset.label;
360 } else {
361 rN += iOffset.value.toJSNumber();
362 }
363 }
364
365 if ((sels)&&(sels.length>0)) {
366
367 const iSizes = getScope(ctx, vSizes);
368
369 for (let i=0; i<sels.length; i++) {
370 const vIdx = gen(ctx, sels[i]);
371 const iIdx = getScope(ctx, vIdx);
372
373 if ((!iIdx.used) && (!iSizes.used)) {
374 rN = rN + iIdx.value * iSizes.sizes[i+1];
375 } else {
376 if (rN>0) {
377 if (rStr != "") rStr += " + ";
378 rStr += rN;
379 rN =0;
380 }
381
382 if (rStr != "") rStr += " + ";
383 if (iIdx.used) {
384 rStr += vIdx;
385 } else {
386 rStr += iIdx.value;
387 }
388 rStr += "*";
389 if (iSizes.used) {
390 rStr += `${iSizes.label}[${i+1}]`;
391 } else {
392 rStr += iSizes.sizes[i+1];
393 }
394 }
395 }
396 }
397
398 if (rStr == "") {
399 const o = newRef(ctx, "INT", "_offset", rN);
400 return o;
401 } else {
402 if (rN>0) {
403 if (rStr != "") rStr += " + ";
404 rStr += rN;
405 rN =0;
406 }
407 if (rStr == iOffset.label) {
408 return vOffset;
409 } else {
410 const res = newRef(ctx, "INT", "_offset");
411 instantiateRef(ctx, res);
412 ctx.code += `${res} = ${rStr};\n`;
413 return res;
414 }
415 }
416}
417
418function genVariable(ctx, ast) {
419 const v = getScope(ctx, ast.name);
420
421
422 if (v.type == "SIGNAL") {
423 let vOffset;
424 if (ast.selectors.length>0) {
425 const vsOffset = genGetSigalOffset(ctx, "ctx->cIdx", ast.name);
426 const vsSizes = genGetSignalSizes(ctx, "ctx->cIdx", ast.name);
427 vOffset = genGetOffset(ctx, vsOffset, vsSizes, ast.selectors );
428 } else {
429 vOffset = genGetSigalOffset(ctx, "ctx->cIdx", ast.name);
430 }
431 return genGetSignal(ctx, "ctx->cIdx", vOffset);
432
433 } else if (v.type == "BIGINT") {
434 const vOffset = genGetOffset(ctx, 0, v.sizes, ast.sels );
435 if (v.used) {
436 if (vOffset == 0) {
437 return ast.name;
438 } else {
439 const res = newRef(ctx, "BIGINT", "_v");
440 instantiateRef(ctx, res);
441 ctx.code += `${res} = ${ast.name} + ${vOffset};\n`;
442 return res;
443 }
444 } else {
445 if (typeof(vOffset) == "string") {
446 instantiateRef(ctx, ast.name);
447 const vConstant = instantiateConstant(ctx, v.value);
448 const res = newRef(ctx, "BIGINT", "_v");
449 instantiateRef(ctx, res);
450 ctx.code += `${res} = ${vConstant} + ${vOffset};\n`;
451 return res;
452 } else {
453 const sa = utils.subArray(v.value, ast.selectors);
454 const res = newRef(ctx, "BIGINT", "_v", sa);
455 return res;
456 }
457 }
458 }
459
460 const sels = [];
461 for (let i=0; i<ast.selectors.length; i++) {
462 sels.push(gen(ctx, ast.selectors[i]));
463 if (ctx.error) return;
464 }
465
466 if (!v) {
467 return error(ctx, ast, "Invalid left operand");
468 }
469 if (v.type == "VARIABLE") {
470 return `ctx.getVar("${ast.name}",[${sels.join(",")}])`;
471 } else if (v.type == "SIGNAL") {
472 return `ctx.getSignal("${ast.name}", [${sels.join(",")}])`;
473 } else {
474 error(ctx, ast, "Invalid Variable type");
475 }
476}
477
478function instantiateConstant(ctx, value) {
479 const flatedValue = utils.flatArray(value);
480 const res = ctx.getTmpName("_const");
481 ctx.codeHeader += `PBigInt ${res};\n`;
482 ctx.code += `${res.label} = ctx->allocBigInts(${flatedValue.length});\n`;
483 for (let i=0; i<flatedValue.length; i++) {
484 ctx.code += `mpz_init_set_str(${res.label}[${i}], ${flatedValue[i].toString(16)}, 16);\n`;
485 }
486 ctx.codeFooter += `ctx->freeBigInts(${res.label});\n`;
487 return res;
488}
489
490function genPin(ctx, ast) {
491 let vcIdx;
492 if (ast.component.selectors.length>0) {
493 const vcOffset = genGetSubComponentOffset(ctx, "ctx->cIdx", ast.component.name);
494 const vcSizes = genGetSubComponentSizes(ctx, "ctx->cIdx", ast.component.name);
495 vcIdx = genGetOffset(ctx, vcOffset, vcSizes, ast.component.selectors );
496 } else {
497 vcIdx = genGetSubComponentOffset(ctx, "ctx->cIdx", ast.component.name);
498 }
499
500 let vsIdx;
501 if (ast.pin.selectors.length>0) {
502 const vsOffset = genGetSigalOffset(ctx, vcIdx, ast.pin.name);
503 const vsSizes = genGetSignalSizes(ctx, vcIdx, ast.pin.name);
504 vsIdx = genGetOffset(ctx, vsOffset, vsSizes, ast.pin.selectors );
505 } else {
506 vsIdx = genGetSigalOffset(ctx, vcIdx, ast.pin.name);
507 }
508
509 return genGetSignal(ctx, vcIdx, vsIdx);
510}
511
512function genGetSubComponentOffset(ctx, cIdx, label) {
513 const vOffset = newRef(ctx, "INT", "_compIdx");
514 instantiateRef(ctx, vOffset);
515
516 const h = utils.fnvHash(label);
517 ctx.code += `${vOffset} = ctx->getSubComponentOffset(${cIdx}, 0x${h}LL /* ${label} */);\n`;
518 return vOffset;
519}
520
521function genGetSubComponentSizes(ctx, cIdx, label) {
522 const vSizes = newRef(ctx, "SIZES", "_compSizes");
523 instantiateRef(ctx, vSizes);
524
525 const h = utils.fnvHash(label);
526 ctx.code += `${vSizes} = ctx->getSubComponentSizes(${cIdx}, 0x${h}LL /* ${label} */);\n`;
527 return vSizes;
528}
529
530function genGetSigalOffset(ctx, sIdx, label) {
531 const vOffset = newRef(ctx, "INT", "_sigIdx");
532 instantiateRef(ctx, vOffset);
533
534 const h = utils.fnvHash(label);
535 ctx.code += `${vOffset} = ctx->getSignalOffset(${sIdx}, 0x${h}LL /* ${label} */);\n`;
536 return vOffset;
537}
538
539function genGetSignalSizes(ctx, sIdx, label) {
540 const vSizes = newRef(ctx, "SIZES", "_sigSizes");
541 instantiateRef(ctx, vSizes);
542
543 const h = utils.fnvHash(label);
544 ctx.code += `${vSizes} = ctx->getSignalSizes(${sIdx}, 0x${h}LL /* ${label} */);\n`;
545 return vSizes;
546}
547
548function genSetSignal(ctx, cIdx, sIdx, value) {
549 ctx.code += `ctx->setSignal(${cIdx}, ${sIdx}, ${value});\n`;
550 return value;
551}
552
553function genGetSignal(ctx, cIdx, sIdx) {
554 const res = newRef(ctx, "BIGINT", "_sigValue");
555 instantiateRef(ctx, res);
556 ctx.code += `ctx->getSignal(${cIdx}, ${sIdx}, ${res});\n`;
557 return res;
558}
559
560function genVarAssignement(ctx, ast) {
561
562 let lName;
563 let sels;
564
565 if (ctx.error) return;
566
567 if (ast.values[0].type == "PIN") {
568
569 let vcIdx;
570 if (ast.values[0].component.selectors.length>0) {
571 const vcOffset = genGetSubComponentOffset(ctx, "ctx->cIdx", ast.values[0].component.name);
572 const vcSizes = genGetSubComponentSizes(ctx, "ctx->cIdx", ast.values[0].component.name);
573 vcIdx = genGetOffset(ctx, vcOffset, vcSizes, ast.values[0].component.selectors );
574 } else {
575 vcIdx = genGetSubComponentOffset(ctx, "ctx->cIdx", ast.values[0].component.name);
576 }
577
578 let vsIdx;
579 if (ast.values[0].pin.selectors.length>0) {
580 const vsOffset = genGetSigalOffset(ctx, vcIdx, ast.values[0].pin.name);
581 const vsSizes = genGetSignalSizes(ctx, vcIdx, ast.values[0].pin.name);
582 vsIdx = genGetOffset(ctx, vsOffset, vsSizes, ast.values[0].pin.selectors );
583 } else {
584 vsIdx = genGetSigalOffset(ctx, vcIdx, ast.values[0].pin.name);
585 }
586
587 const vVal = gen(ctx, ast.values[1]);
588
589 genSetSignal(ctx, vcIdx, vsIdx, vVal);
590
591 return vVal;
592 }
593
594 if (ast.values[0].type == "DECLARE") {
595 lName = gen(ctx, ast.values[0]);
596 if (ctx.error) return;
597 sels = [];
598 } else {
599 lName = ast.values[0].name;
600 sels = ast.values[0].selectors;
601 }
602
603
604 const left = getScope(ctx, lName);
605 if (!left) return error(ctx, ast, "Variable does not exists: "+ast.values[0].name);
606
607 // Component instantiation is already done.
608 if (left.type == "COMPONENT") {
609 ctx.last = lName;
610 return;
611 }
612
613
614 const rName = gen(ctx, ast.values[1]);
615 const right = getScope(ctx, rName);
616
617 if (left.type == "SIGNAL") {
618
619 let vsIdx;
620 if (sels.length>0) {
621 const vsOffset = genGetSigalOffset(ctx, "ctx->cIdx", lName);
622 const vsSizes = genGetSignalSizes(ctx, "ctx->cIdx", lName);
623 vsIdx = genGetOffset(ctx, vsOffset, vsSizes, sels );
624 } else {
625 vsIdx = genGetSigalOffset(ctx, "ctx->cIdx", lName);
626 }
627
628 return genSetSignal(ctx, "ctx->cIdx", vsIdx, rName);
629 } else if (left.type == "VAR") {
630 if (left.used) {
631 if (!right.used) {
632 instantiateRef(ctx, rName);
633 }
634 ctx.code += `BigInt_copy(${left.label}, ${right.label});\n`;
635 return lName;
636 } else {
637 if (right.used) {
638 instantiateRef(ctx, lName);
639 ctx.code += `BigInt_copy(${left.label}, ${right.label});\n`;
640 return lName;
641 } else {
642 if (!left.value) {
643 left.value = right.value;
644 } else {
645 if (!left.value.equals(right.value)) {
646 if (ctx.scopes.length > 1) {
647 instantiateRef(ctx, lName);
648 ctx.code += `BigInt_copy(${left.label}, ${right.label});\n`;
649 } else {
650 left.value = right.value;
651 }
652 }
653 }
654 }
655 }
656 } else {
657 return error(ctx, ast, "Assigning to invalid");
658 }
659}
660
661function genConstraint(ctx, ast) {
662 const a = gen(ctx, ast.values[0]);
663 if (ctx.error) return;
664 const b = gen(ctx, ast.values[1]);
665 if (ctx.error) return;
666 const strErr = ast.fileName + ":" + ast.first_line + ":" + ast.first_column;
667 ctx.code += `ctx->checkConstraint(${a}, ${b}, "${strErr}");`;
668}
669
670
671function genArray(ctx, ast) {
672 let S = "[";
673 for (let i=0; i<ast.values.length; i++) {
674 if (i>0) S += ",";
675 S += gen(ctx, ast.values[i]);
676 }
677 S+="]";
678 return S;
679}
680
681
682function genFunctionCall(ctx, ast) {
683 let S = "[";
684 for (let i=0; i<ast.params.length; i++) {
685 if (i>0) S += ",";
686 S += gen(ctx, ast.params[i]);
687 }
688 S+="]";
689
690 return `ctx.callFunction("${ast.name}", ${S})`;
691}
692
693function genFor(ctx, ast) {
694 ctx.scopes.push({});
695 const init = gen(ctx, ast.init);
696 if (ctx.error) return;
697 const condition = gen(ctx, ast.condition);
698 if (ctx.error) return;
699 const step = gen(ctx, ast.step);
700 if (ctx.error) return;
701 const body = gen(ctx, ast.body);
702 if (ctx.error) return;
703 ctx.scopes.pop();
704 return `for (${init};bigInt(${condition}).neq(bigInt(0));${step}) { \n${body}\n }\n`;
705}
706
707function genWhile(ctx, ast) {
708 const condition = gen(ctx, ast.condition);
709 if (ctx.error) return;
710 const body = gen(ctx, ast.body);
711 if (ctx.error) return;
712 return `while (bigInt(${condition}).neq(bigInt(0))) {\n${body}\n}\n`;
713}
714
715function genCompute(ctx, ast) {
716 const body = gen(ctx, ast.body);
717 if (ctx.error) return;
718 return `{\n${body}\n}\n`;
719}
720
721function genIf(ctx, ast) {
722 const condition = gen(ctx, ast.condition);
723 if (ctx.error) return;
724 const thenBody = gen(ctx, ast.then);
725 if (ctx.error) return;
726 if (ast.else) {
727 const elseBody = gen(ctx, ast.else);
728 if (ctx.error) return;
729 return `if (bigInt(${condition}).neq(bigInt(0))) {\n${thenBody}\n} else {\n${elseBody}\n}\n`;
730 } else {
731 return `if (bigInt(${condition}).neq(bigInt(0))) {\n${thenBody}\n}\n`;
732 }
733}
734
735
736function genReturn(ctx, ast) {
737 const value = gen(ctx, ast.value);
738 if (ctx.error) return;
739 return `return ${value};`;
740}
741
742
743
744function genSignalAssignConstrain(ctx, ast) {
745 const res = genVarAssignement(ctx, ast);
746 genConstraint(ctx, ast);
747 return res;
748// return genVarAssignement(ctx, ast);
749}
750
751function genVarAddAssignement(ctx, ast) {
752 return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "+", values: ast.values}]});
753}
754
755function genVarMulAssignement(ctx, ast) {
756 return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "*", values: ast.values}]});
757}
758
759function genPlusPlusRight(ctx, ast) {
760 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__)`;
761}
762
763function genPlusPlusLeft(ctx, ast) {
764 return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "+", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]});
765}
766
767function genMinusMinusRight(ctx, ast) {
768 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__)`;
769}
770
771function genMinusMinusLeft(ctx, ast) {
772 return genVarAssignement(ctx, {values: [ast.values[0], {type: "OP", op: "-", values: [ast.values[0], {type: "NUMBER", value: bigInt(1)}]}]});
773}
774
775function genAdd(ctx, ast) {
776 const a = gen(ctx, ast.values[0]);
777 if (ctx.error) return;
778 const b = gen(ctx, ast.values[1]);
779 if (ctx.error) return;
780 return `bigInt(${a}).add(bigInt(${b})).mod(__P__)`;
781}
782
783function genMul(ctx, ast) {
784 const a = gen(ctx, ast.values[0]);
785 if (ctx.error) return;
786 const b = gen(ctx, ast.values[1]);
787 if (ctx.error) return;
788 return `bigInt(${a}).mul(bigInt(${b})).mod(__P__)`;
789}
790
791function genSub(ctx, ast) {
792 const a = gen(ctx, ast.values[0]);
793 if (ctx.error) return;
794 const b = gen(ctx, ast.values[1]);
795 if (ctx.error) return;
796 return `bigInt(${a}).add(__P__).sub(bigInt(${b})).mod(__P__)`;
797}
798
799function genDiv(ctx, ast) {
800 const a = gen(ctx, ast.values[0]);
801 if (ctx.error) return;
802 const b = gen(ctx, ast.values[1]);
803 if (ctx.error) return;
804
805 return `bigInt(${a}).mul( bigInt(${b}).inverse(__P__) ).mod(__P__)`;
806}
807
808function genIDiv(ctx, ast) {
809 const a = gen(ctx, ast.values[0]);
810 if (ctx.error) return;
811 const b = gen(ctx, ast.values[1]);
812 if (ctx.error) return;
813
814 return `bigInt(${a}).div( bigInt(${b}))`;
815}
816
817function genExp(ctx, ast) {
818 const a = gen(ctx, ast.values[0]);
819 if (ctx.error) return;
820 const b = gen(ctx, ast.values[1]);
821 if (ctx.error) return;
822 return `bigInt(${a}).modPow(bigInt(${b}), __P__)`;
823}
824
825function genBAnd(ctx, ast) {
826 const a = gen(ctx, ast.values[0]);
827 if (ctx.error) return;
828 const b = gen(ctx, ast.values[1]);
829 if (ctx.error) return;
830 return `bigInt(${a}).and(bigInt(${b})).and(__MASK__)`;
831}
832
833function genAnd(ctx, ast) {
834 const a = gen(ctx, ast.values[0]);
835 if (ctx.error) return;
836 const b = gen(ctx, ast.values[1]);
837 if (ctx.error) return;
838 return `((bigInt(${a}).neq(bigInt(0)) && bigInt(${b}).neq(bigInt(0))) ? bigInt(1) : bigInt(0))`;
839}
840
841function genOr(ctx, ast) {
842 const a = gen(ctx, ast.values[0]);
843 if (ctx.error) return;
844 const b = gen(ctx, ast.values[1]);
845 if (ctx.error) return;
846 return `((bigInt(${a}).neq(bigInt(0)) || bigInt(${b}).neq(bigInt(0))) ? bigInt(1) : bigInt(0))`;
847}
848
849function genShl(ctx, ast) {
850 const a = gen(ctx, ast.values[0]);
851 if (ctx.error) return;
852 const b = gen(ctx, ast.values[1]);
853 if (ctx.error) return;
854 return `bigInt(${b}).greater(bigInt(256)) ? 0 : bigInt(${a}).shl(bigInt(${b})).and(__MASK__)`;
855}
856
857function genShr(ctx, ast) {
858 const a = gen(ctx, ast.values[0]);
859 if (ctx.error) return;
860 const b = gen(ctx, ast.values[1]);
861 if (ctx.error) return;
862 return `bigInt(${b}).greater(bigInt(256)) ? 0 : bigInt(${a}).shr(bigInt(${b})).and(__MASK__)`;
863}
864
865function genMod(ctx, ast) {
866 const a = gen(ctx, ast.values[0]);
867 if (ctx.error) return;
868 const b = gen(ctx, ast.values[1]);
869 if (ctx.error) return;
870 return `bigInt(${a}).mod(bigInt(${b}))`;
871}
872
873function genLt(ctx, ast) {
874 const a = gen(ctx, ast.values[0]);
875 if (ctx.error) return;
876 const b = gen(ctx, ast.values[1]);
877 if (ctx.error) return;
878 return `bigInt(${a}).lt(bigInt(${b})) ? 1 : 0`;
879}
880
881function genGt(ctx, ast) {
882 const a = gen(ctx, ast.values[0]);
883 if (ctx.error) return;
884 const b = gen(ctx, ast.values[1]);
885 if (ctx.error) return;
886 return `bigInt(${a}).gt(bigInt(${b})) ? 1 : 0`;
887}
888
889function genLte(ctx, ast) {
890 const a = gen(ctx, ast.values[0]);
891 if (ctx.error) return;
892 const b = gen(ctx, ast.values[1]);
893 if (ctx.error) return;
894 return `bigInt(${a}).lesserOrEquals(bigInt(${b})) ? 1 : 0`;
895}
896
897function genGte(ctx, ast) {
898 const a = gen(ctx, ast.values[0]);
899 if (ctx.error) return;
900 const b = gen(ctx, ast.values[1]);
901 if (ctx.error) return;
902 return `bigInt(${a}).greaterOrEquals(bigInt(${b})) ? 1 : 0`;
903}
904
905function genEq(ctx, ast) {
906 const a = gen(ctx, ast.values[0]);
907 if (ctx.error) return;
908 const b = gen(ctx, ast.values[1]);
909 if (ctx.error) return;
910 return `(bigInt(${a}).eq(bigInt(${b})) ? 1 : 0)`;
911}
912
913function genNeq(ctx, ast) {
914 const a = gen(ctx, ast.values[0]);
915 if (ctx.error) return;
916 const b = gen(ctx, ast.values[1]);
917 if (ctx.error) return;
918 return `(bigInt(${a}).eq(bigInt(${b})) ? 0 : 1)`;
919}
920
921function genUMinus(ctx, ast) {
922 const a = gen(ctx, ast.values[0]);
923 if (ctx.error) return;
924 return `__P__.sub(bigInt(${a})).mod(__P__)`;
925}
926
927function genTerCon(ctx, ast) {
928 const a = gen(ctx, ast.values[0]);
929 if (ctx.error) return;
930 const b = gen(ctx, ast.values[1]);
931 if (ctx.error) return;
932 const c = gen(ctx, ast.values[2]);
933 if (ctx.error) return;
934 return `bigInt(${a}).neq(bigInt(0)) ? (${b}) : (${c})`;
935}
936
937function genInclude(ctx, ast) {
938 return ast.block ? gen(ctx, ast.block) : "";
939}
940
941