Skip to content

Commit f4fb24c

Browse files
committed
Added some resolvers
1 parent 207bd1d commit f4fb24c

File tree

6 files changed

+122
-5
lines changed

6 files changed

+122
-5
lines changed

src/types/common.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export type CircomValueType = bigint | CircomValueType[];
22

33
export type VariableContext = Record<string, CircomValueType>;
4+
5+
export type VariableContextWithNull = Record<string, CircomValueType | null>;

src/utils/common.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { SimpleIdentifierListContext } from "../generated";
2+
import { VariableContext, VariableContextWithNull } from "../types";
23

34
export function parseSimpleIdentifierList(
45
ctx: SimpleIdentifierListContext,
@@ -15,3 +16,70 @@ export function parseSimpleIdentifierList(
1516

1617
return result;
1718
}
19+
20+
export function bindVariableContext(
21+
variableName: string,
22+
dimensions: number[],
23+
values: any[],
24+
): VariableContextWithNull {
25+
const context: VariableContextWithNull = {};
26+
27+
const resolved = resolveDimensions(variableName, dimensions);
28+
for (const variable of resolved) {
29+
try {
30+
context[variable] = parseVariable(
31+
values,
32+
variable.replace(variableName, ""),
33+
);
34+
} catch {
35+
context[variable] = null;
36+
}
37+
}
38+
39+
return context;
40+
}
41+
42+
// reference MUST be similar to [0][1]
43+
function parseVariable(value: any, reference: string): bigint {
44+
const parts = reference
45+
.split("[")
46+
.map((part) => part.replace("]", ""))
47+
.filter((part) => part !== "")
48+
.map((part) => parseInt(part));
49+
50+
return getReferenceValueInternal(value, parts);
51+
}
52+
53+
function getReferenceValueInternal(value: any, reference: number[]): bigint {
54+
if (reference.length === 0) {
55+
return value;
56+
}
57+
58+
return getReferenceValueInternal(value[reference[0]], reference.slice(1));
59+
}
60+
61+
export function resolveDimensions(
62+
variableName: string,
63+
dimensions: number[],
64+
): string[] {
65+
return internalResolveDimensions([variableName], dimensions, 0);
66+
}
67+
68+
function internalResolveDimensions(
69+
variables: string[],
70+
dimensions: number[],
71+
layer: number,
72+
): string[] {
73+
if (layer >= dimensions.length) {
74+
return variables;
75+
}
76+
77+
const result: string[] = [];
78+
for (let i = 0; i < dimensions[layer]; i++) {
79+
for (const variable of variables) {
80+
result.push(`${variable}[${i}]`);
81+
}
82+
}
83+
84+
return internalResolveDimensions(result, dimensions, layer + 1);
85+
}

test/circom-template-inputs-visitor.test.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import { expect } from "chai";
22
import { getCircomParser, VariableContext } from "../src";
33

4-
import { Templates } from "./mocks/types";
4+
import { CircomFileData, Templates } from "./mocks/types";
55
import { CircomFilesVisitor } from "./mocks/CircomFilesVisitor";
66
import { CircomTemplateInputsVisitor } from "./mocks/CircomTemplateInputsVisitor";
77

88
describe("Circom Template Inputs Visitor", () => {
9-
function getData(fileName: string): Templates {
9+
function getData(fileName: string): CircomFileData {
1010
const visitor = new CircomFilesVisitor(fileName);
1111

1212
const parser = getCircomParser(`test/data/${fileName}`);
1313

1414
visitor.visit(parser.circuit());
1515

16-
return visitor.fileData.templates;
16+
return visitor.fileData;
1717
}
1818

1919
it("should analyse the curve.circom circuit", () => {
@@ -34,7 +34,7 @@ describe("Circom Template Inputs Visitor", () => {
3434

3535
const visitor = new CircomTemplateInputsVisitor(
3636
"curve.circom",
37-
data["RegisterIdentityBuilder"].context,
37+
data.templates["RegisterIdentityBuilder"].context,
3838
mainComponentData,
3939
);
4040

@@ -100,7 +100,7 @@ describe("Circom Template Inputs Visitor", () => {
100100

101101
const visitor = new CircomTemplateInputsVisitor(
102102
"MainComponent.circom",
103-
data["C"].context,
103+
data.templates["C"].context,
104104
mainComponentData,
105105
);
106106

@@ -117,4 +117,18 @@ describe("Circom Template Inputs Visitor", () => {
117117
expect(visitor.templateInputs.out.type).to.equal("output");
118118
expect(visitor.templateInputs.out.dimension).to.deep.equal([]);
119119
});
120+
121+
it.only("should analyse the ComplexMainComponent.circom circuit", () => {
122+
const data = getData("ComplexMainComponent.circom");
123+
124+
// const visitor = new CircomTemplateInputsVisitor(
125+
// "MainComponent.circom",
126+
// data.,
127+
// {},
128+
// );
129+
//
130+
// visitor.startParse();
131+
//
132+
// console.log(visitor.errors);
133+
});
120134
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
pragma circom 2.1.6;
2+
3+
template C(p1, p2){
4+
signal input in1;
5+
signal input in2[3][p1[1][0][0][0][0][0][0]];
6+
7+
signal output out <== in1 * in2[0][0] * p2[0][1][0];
8+
}
9+
10+
component main {public [in1]} = C([[[[[[[10]]]]]], [[[[[[20]]]]]]], [[[30], [40]]]);

test/file-visitor.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,17 @@ describe("Circom File Visitor", () => {
173173
expect(templateA.parallel).to.equal(true);
174174
expect(templateA.parameters).to.deep.equal(["a1"]);
175175
});
176+
177+
it("should analyse the ComplexMainComponent.circom circuit", () => {
178+
const [errors, fileData] = getData("ComplexMainComponent.circom");
179+
180+
expect(errors.length).to.equal(0);
181+
expect(fileData.mainComponentInfo.parameters[0]).to.deep.equal([
182+
[[[[[[10n]]]]]],
183+
[[[[[[20n]]]]]],
184+
]);
185+
expect(fileData.mainComponentInfo.parameters[1]).to.deep.equal([
186+
[[30n], [40n]],
187+
]);
188+
});
176189
});

test/utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { bindVariableContext, resolveDimensions } from "../src";
2+
3+
describe("utils", () => {
4+
describe("resolve dimensions", () => {
5+
it.only("should resolve the case: [1]", () => {
6+
console.log(bindVariableContext("a", [1, 2], [[3, 5]]));
7+
console.log(bindVariableContext("a", [1, 2], []));
8+
});
9+
});
10+
});

0 commit comments

Comments
 (0)