diff --git a/package-lock.json b/package-lock.json index 62a7642..cf1831c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@distributedlab/circom-parser", - "version": "0.2.4", + "version": "0.2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@distributedlab/circom-parser", - "version": "0.2.4", + "version": "0.2.5", "license": "MIT", "dependencies": { "antlr4": "4.13.1-patch-1", diff --git a/package.json b/package.json index 09f5bbb..61e5dac 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@distributedlab/circom-parser", "description": "Circom circuit parser built with ANTLR4", - "version": "0.2.4", + "version": "0.2.5", "main": "dist/index.js", "types": "dist/index.d.ts", "files": [ diff --git a/src/utils/ExpressionHelper.ts b/src/utils/ExpressionHelper.ts index 79ef7b4..e64e20e 100644 --- a/src/utils/ExpressionHelper.ts +++ b/src/utils/ExpressionHelper.ts @@ -177,8 +177,13 @@ class ExpressionVisitor extends ExtendedCircomVisitor { }; visitPParentheses = (ctx: PParenthesesContext): CircomValueType | null => { - this.addError("Parentheses are not supported", ctx); - return null; + let expressions = ctx.expressionList().expression_list(); + if (expressions.length !== 1) { + this.addError("Parentheses can only contain one expression", ctx); + return null; + } + + return this.visit(expressions[0]); }; visitPArray = (ctx: PArrayContext): CircomValueType | null => { @@ -283,8 +288,8 @@ class ExpressionVisitor extends ExtendedCircomVisitor { case CircomParser.DIV: return firstExpression / secondExpression; case CircomParser.QUO: - this.addError("QUO operation is not supported", ctx); - return null; + // See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Division + return firstExpression / secondExpression; case CircomParser.MOD: return firstExpression % secondExpression; case CircomParser.ADD: diff --git a/test/circom-template-inputs-visitor.test.ts b/test/circom-template-inputs-visitor.test.ts index 0ea0e34..9becc82 100644 --- a/test/circom-template-inputs-visitor.test.ts +++ b/test/circom-template-inputs-visitor.test.ts @@ -233,4 +233,44 @@ describe("Circom Template Inputs Visitor", () => { expect(visitor.templateInputs.out.type).to.equal("output"); expect(visitor.templateInputs.out.dimension).to.deep.equal([2, 4]); }); + + it("should analyse the Math.circom circuit", () => { + const data = getData("Math.circom"); + + const visitor = new CircomTemplateInputsVisitor( + "Math.circom", + data.templates[data.mainComponentInfo.templateName!].context, + buildVariableContext( + data.templates[data.mainComponentInfo.templateName!].parameters, + data.mainComponentInfo.parameters, + ), + ); + + visitor.startParse(); + + expect(visitor.errors.length).to.equal(0); + + expect(visitor.templateInputs.out1.type).to.equal("output"); + expect(visitor.templateInputs.out1.dimension).to.deep.equal([13]); + + expect(visitor.templateInputs.out2.type).to.equal("output"); + expect(visitor.templateInputs.out2.dimension).to.deep.equal([16]); + + expect(visitor.templateInputs.tmp1.type).to.equal("intermediate"); + expect(visitor.templateInputs.tmp1.dimension).to.deep.equal([6, 8, 2, 20]); + + expect(visitor.templateInputs.tmp2.type).to.equal("intermediate"); + expect(visitor.templateInputs.tmp2.dimension).to.deep.equal([6, 2, 20]); + + expect(visitor.templateInputs.tmp3.type).to.equal("intermediate"); + expect(visitor.templateInputs.tmp3.dimension).to.deep.equal([6, 2, 2, 20]); + + expect(visitor.templateInputs.tmp4.type).to.equal("intermediate"); + expect(visitor.templateInputs.tmp4.dimension).to.deep.equal([5, 2, 2, 20]); + + expect(visitor.templateInputs.powers.type).to.equal("intermediate"); + expect(visitor.templateInputs.powers.dimension).to.deep.equal([ + 2, 256, 2, 6, + ]); + }); }); diff --git a/test/data/Math.circom b/test/data/Math.circom new file mode 100644 index 0000000..f7c10b2 --- /dev/null +++ b/test/data/Math.circom @@ -0,0 +1,24 @@ +pragma circom 2.1.6; + +template Math(a, b, c) { + var input1 = (a + b) / 2; + var input2 = a + b / 2; + + var PRECOMPUTE_NUMBER = 2 ** c; + + signal tmp1 [a][PRECOMPUTE_NUMBER][2][b]; + + var STRIDE = 8; + var parts = a * c \ STRIDE; + + signal tmp2[a] [2] [b]; + signal tmp3[a] [2][2][b]; + signal tmp4[a - 1][2][2][b]; + + signal powers[parts][2 ** STRIDE][2][a]; + + signal output out1[input1]; + signal output out2[input2]; +} + +component main = Math(6, 20, 3);