Skip to content

Commit

Permalink
Merge pull request #32 from Thunkar/gj/new_compiler
Browse files Browse the repository at this point in the history
New compiler, project support
  • Loading branch information
signorecello authored Mar 21, 2024
2 parents 9b1c09d + cd64ea8 commit 1c5269f
Show file tree
Hide file tree
Showing 18 changed files with 1,546 additions and 1,356 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
10 changes: 5 additions & 5 deletions packages/playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
},
"dependencies": {
"@monaco-editor/react": "4.6.0",
"@noir-lang/backend_barretenberg": "^0.22.0",
"@noir-lang/noir_js": "^0.22.0",
"@noir-lang/noir_wasm": "^0.22.0",
"@noir-lang/types": "^0.22.0",
"@noir-lang/backend_barretenberg": "0.25.0",
"@noir-lang/noir_js": "0.25.0",
"@noir-lang/noir_wasm": "0.25.0",
"@noir-lang/types": "0.25.0",
"fflate": "^0.8.1",
"js-base64": "^3.7.5",
"monaco-editor": "^0.44.0",
Expand All @@ -39,7 +39,7 @@
},
"devDependencies": {
"@tailwindcss/forms": "^0.5.7",
"@types/node": "^20.10.0",
"@types/node": "^20.10.6",
"@types/react": "18.2.38",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.12.0",
Expand Down
38 changes: 14 additions & 24 deletions packages/playground/src/components/actionsBox/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@ import React, { ChangeEvent, FormEvent, useEffect, useState } from "react";
import { RenderInputs } from "../inputs/inputs";
import { compileCode, generateProof } from "../../utils/generateProof";
import { prepareInputs } from "../../utils/serializeParams";
import { shareSnippet } from "../../utils/shareSnippet";
import { shareProject } from "../../utils/shareSnippet";
import { toast } from "react-toastify";
import { CompiledCircuit } from "@noir-lang/types";
import { useParams } from "../../hooks/useParams";
import { InputMap } from "@noir-lang/noirc_abi";
import { flattenPublicInputs } from "@noir-lang/backend_barretenberg";
import { Button } from "../buttons/buttons";
import { ButtonContainer } from "../buttons/containers";
import { NoirProps, PlaygroundProps, ProofData } from "../../types";
import { toHex } from "../..//utils/toHex";
import { toHex } from "../../utils/toHex";
import { FileSystem } from "../../utils/fileSystem";

export const ActionsBox = ({
code,
project,
props,
setProof,
}: {
code: string;
project: FileSystem;
props: PlaygroundProps;
setProof: React.Dispatch<React.SetStateAction<ProofData | null>>;
}) => {
Expand All @@ -44,10 +44,10 @@ export const ActionsBox = ({

useEffect(() => {
setCompiledCode(null);
}, [code]);
}, [project]);

const compile = async (code: string | undefined) => {
const compiledCode = await compileCode(code);
const compile = async (project: FileSystem) => {
const compiledCode = await compileCode(project);
setCompiledCode(compiledCode);
};

Expand All @@ -56,26 +56,16 @@ export const ActionsBox = ({

if (!compiledCode) {
setPending(true);
const compileTO = new Promise((resolve, reject) =>
setTimeout(async () => {
try {
setPending(false);
await compile(code);
resolve(code);
} catch (err) {
reject(err);
}
}, 100)
);

await toast.promise(compileTO, {
await toast.promise(compile(project), {
pending: "Compiling...",
success: "Compiled!",
error: "Error compiling",
error: { render: ({ data }) => `${data}` },
});
} else {
await prove(e);
}
setPending(false);
};

const prove = async (e: FormEvent) => {
Expand All @@ -97,16 +87,16 @@ export const ActionsBox = ({

const proofDataHex = {
proof: toHex(proofData.proof),
publicInputs: flattenPublicInputs(proofData.publicInputs),
publicInputs: Array.from(proofData.publicInputs.values()),
};
setProof(proofDataHex);
setPending(false);
};

const share = async (e: FormEvent) => {
e.preventDefault();
if (code) {
await toast.promise(shareSnippet({ code, baseUrl: props.baseUrl }), {
if (project) {
await toast.promise(shareProject({ project, baseUrl: props.baseUrl }), {
pending: "Copying to clipboard...",
success: "Copied!",
error: "Error sharing",
Expand Down
95 changes: 65 additions & 30 deletions packages/playground/src/components/editor/NoirEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@ import React, { useRef } from "react";
import { useEffect, useState } from "react";
import { ToastContainer } from "react-toastify";
import { useMonaco } from "../../hooks/useMonaco";
import { decodeSnippet } from "../../utils/shareSnippet";
import {
decodeProject,
decodeSnippet,
encodeSnippet,
} from "../../utils/shareSnippet";
import examples from "../../syntax/examples.json";
import { ActionsBox } from "../actionsBox/actions";
import { PlaygroundProps, ProofData } from "../../types";
import { File, PlaygroundProps, ProofData } from "../../types";
import { ResultBox } from "../resultBox/result";
import { editor } from "monaco-editor";
import Directory from "../fileExplorer/Directory";
import { FileSystem } from "../../utils/fileSystem";

type editorType = editor.IStandaloneCodeEditor;

Expand All @@ -18,28 +24,35 @@ function NoirEditor(props: PlaygroundProps) {
const { monaco, loaded } = useMonaco();

const [monacoEditor, setMonacoEditor] = useState<editorType | null>(null); // To track the editor instance
const [code, setCode] = useState<string | undefined>();
const [proof, setProof] = useState<ProofData | null>(null);
const rootFs = props.initialProject
? decodeProject(props.initialProject)
: (examples.main as unknown as File);
const [fileSystem, setFilesystem] = useState<FileSystem>(
new FileSystem(rootFs)
);
const [currentPath, setCurrentPath] = useState<string>("src/main.nr");
const [oldPath, setOldPath] = useState<string | undefined>();
const [codeInBuffer, setCodeInBuffer] = useState<string | undefined>("");

useEffect(() => {
const code = decodeSnippet({
encoded: props.initialCode || examples.default,
});
setCode(code);

async function load() {
if (monaco && editorRef.current && !monacoEditor) {
const initialCode = decodeSnippet(
fileSystem.getByPath(currentPath).content as string
);
setCodeInBuffer(initialCode);
if (editorRef.current.hasChildNodes())
editorRef.current.removeChild(editorRef.current.firstChild!);

const monacoProperties = {
value: code,
value: initialCode,
fontSize: 18,
language: "noir",
fontFamily: "Fira Code Variable",
roundedSelection: false,
automaticLayout: true,
lineNumbers: "off",
lineNumbers: "on",
scrollBeyondLastLine: false,
minimap: { enabled: false },
};
Expand All @@ -50,34 +63,56 @@ function NoirEditor(props: PlaygroundProps) {
);

setMonacoEditor(editor);
} else if (monacoEditor) {
monacoEditor?.getModel()?.onDidChangeContent(() => {
setCodeInBuffer(monacoEditor?.getValue());
});
}
}

load();
}, [monaco, monacoEditor, props.initialCode]);
}, [monaco, monacoEditor, oldPath, currentPath, fileSystem]);

useEffect(() => {
if (monacoEditor)
monacoEditor.getModel()?.onDidChangeContent(() => {
setCode(monacoEditor.getValue());
});
}, [monacoEditor]);
if (currentPath !== oldPath) {
setOldPath(currentPath);
monacoEditor?.setValue(
decodeSnippet(fileSystem.getByPath(currentPath).content as string)
);
} else {
setFilesystem((fs) =>
fs.updateByPath(currentPath, encodeSnippet(codeInBuffer as string))
);
}
}, [currentPath, oldPath, monacoEditor, fileSystem, codeInBuffer]);

return (
<div
className="h-full w-full flex items-center flex-col box-border text-sm font-fira-code"
id="noir__playground"
>
<ToastContainer />
<section style={props.style}>
<div ref={editorRef} id="editor" className="w-full h-full"></div>
</section>
<div className="h-full w-full flex flex-row">
<div className="w-1/4 text-lg flex bg-yellow-4 shadow rounded-bl-lg flex-column pl-6 border-r-yellow-6 border-r-2">
<Directory
files={fileSystem.root}
selectFile={setCurrentPath}
currentPath={currentPath}
></Directory>
</div>
<div
className="w-3/4 flex items-stretch flex-col box-border text-sm font-fira-code"
id="noir__playground"
>
<ToastContainer />
<section style={props.style}>
<div ref={editorRef} id="editor" className="w-full h-full"></div>
</section>

<div className="w-full bg-yellow-4 shadow rounded-b-lg flex flex-row flex-wrap">
{loaded && !proof && code && (
<ActionsBox code={code} props={props} setProof={setProof} />
)}
{loaded && proof && <ResultBox proof={proof} setProof={setProof} />}
<div className="w-full bg-yellow-4 shadow rounded-br-lg flex flex-row flex-wrap">
{loaded && !proof && (
<ActionsBox
project={fileSystem}
props={props}
setProof={setProof}
/>
)}
{loaded && proof && <ResultBox proof={proof} setProof={setProof} />}
</div>
</div>
</div>
);
Expand Down
61 changes: 61 additions & 0 deletions packages/playground/src/components/fileExplorer/Directory.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from "react";
import { useState } from "react";
import { File } from "../../types";

const Directory = ({
root,
files,
selectFile,
currentPath,
}: {
root?: string;
files: File;
selectFile: (file: string) => void;
currentPath: string;
}) => {
const [isExpanded, toggleExpanded] = useState(true);

root = root || "";

if (files.type === "folder") {
return (
<div className="w-full -ml-6">
<div className="flex flex-col w-full pl-6">
<p
className="cursor-pointer font-mono"
onClick={() => toggleExpanded(!isExpanded)}
>
{isExpanded ? "[-]" : "[+]"}&nbsp;{files.name}/
</p>
{isExpanded &&
files.items?.map((item) => {
return (
<div className="pl-6" key={`${root}${item.name}`}>
<Directory
root={`${root}${files.name}/`}
selectFile={selectFile}
files={item}
currentPath={currentPath}
/>
</div>
);
})}
</div>
</div>
);
}
return (
<div className="w-full -ml-6">
<p
className={`font-mono m-0 p-0 cursor-pointer pl-6 ${
currentPath === `${root}${files.name}` ? "bg-yellow-3" : ""
}`}
onClick={() => selectFile(`${root}${files.name}`)}
>
{files.name}
</p>
</div>
);
};

export default Directory;
11 changes: 1 addition & 10 deletions packages/playground/src/hooks/useMonaco.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import tmLanguage from "../syntax/noir.tmLanguage.json";
import { Registry } from "monaco-textmate";
import { wireTmGrammars } from "monaco-editor-textmate";

import initNoirWasm from "@noir-lang/noir_wasm";
import initNoirC from "@noir-lang/noirc_abi";
import initACVM from "@noir-lang/acvm_js";
import initACVM from "@noir-lang/acvm_js";
import { loadWASM } from "onigasm";
import { useEffect, useState } from "react";

Expand Down Expand Up @@ -47,14 +46,6 @@ export const useMonaco = () => {
console.log("Onigasm already initialized, skipping re-initialization.");
})
);
promArray.push(
initNoirWasm(
new URL(
"@noir-lang/noir_wasm/web/noir_wasm_bg.wasm",
import.meta.url
).toString()
)
);
promArray.push(
initNoirC(
new URL(
Expand Down
6 changes: 3 additions & 3 deletions packages/playground/src/hooks/useParams.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { InputMap } from "@noir-lang/noirc_abi";
export function useParams({
compiledCode,
}: {
compiledCode: ReturnType<typeof compileCode> | null;
compiledCode: Awaited<ReturnType<typeof compileCode>> | null;
}) {
const [params, setParams] = useState<{ name: string }[] | null>(null);

Expand All @@ -14,7 +14,7 @@ export function useParams({
setParams(null);
return;
}
const params = compiledCode!.abi.parameters.map((param: InputMap) => {
const params = compiledCode!.abi.parameters.map((param) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function unroll(param: any) {
if (param.type.kind !== "struct") {
Expand All @@ -32,7 +32,7 @@ export function useParams({
return unroll(param);
});

setParams(params);
setParams(params as { name: string }[] | null);
}, [compiledCode]);

return params;
Expand Down
23 changes: 22 additions & 1 deletion packages/playground/src/syntax/examples.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
{
"default": "H4sIAMooXmUAA0vLU8hNzMzTqLBScMtMzUnRUai0UigoTYLwNBWquRSAILG4OLWoRKNCQdFWoVLTmqsWAJCM2nw3AAAA"
"main": {
"name": "root",
"type": "folder",
"items": [
{
"name": "src",
"type": "folder",
"items": [
{
"name": "main.nr",
"type": "file",
"content": "H4sIAMooXmUAA0vLU8hNzMzTqLBScMtMzUnRUai0UigoTYLwNBWquRSAILG4OLWoRKNCQdFWoVLTmqsWAJCM2nw3AAAA"
}
]
},
{
"name": "Nargo.toml",
"type": "file",
"content": "H4sIAIV_mGUAAx3LSwqAIBRG4fldRdwFRM2a1EZEwvSnpLyKWtDue0wP51PJ2N2s0CQmoBkbriiVyZx1i7m8QTFrsjEkfyDPF3LxUb5xGru2H9qOqd7pp4sXJlIOCeIg1qNoegCFqwRkYgAAAA"
}
]
}
}
Loading

0 comments on commit 1c5269f

Please sign in to comment.