Skip to content

Commit

Permalink
Merge branch 'main' into pvm-64-bit
Browse files Browse the repository at this point in the history
  • Loading branch information
tomusdrw committed Dec 17, 2024
2 parents c4fd0cb + 2e55ee5 commit 1f94de6
Show file tree
Hide file tree
Showing 17 changed files with 334 additions and 192 deletions.
12 changes: 11 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"react-toastify": "^10.0.6",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.1"
"vaul": "^0.9.1",
"zod": "^3.24.1"
},
"devDependencies": {
"@playwright/test": "^1.47.2",
Expand Down
14 changes: 10 additions & 4 deletions src/components/Instructions/InstructionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import { TableCell, TableRow } from "../ui/table";
import { ProgramRow } from ".";
import { useAppSelector } from "@/store/hooks.ts";
import { selectWorkers, WorkerState } from "@/store/workers/workersSlice.ts";
import { hexToRgb } from "@/lib/utils.ts";
import { hexToRgb, invertHexColor } from "@/lib/utils.ts";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip.tsx";
import useDarkMode from "@/hooks/useDarkMode.ts";

const getWorkerValueFromState = (
worker: WorkerState,
Expand Down Expand Up @@ -73,6 +74,7 @@ export const InstructionItem = forwardRef(
ref: ForwardedRef<HTMLTableRowElement>,
) => {
const { numeralSystem } = useContext(NumeralSystemContext);
const isDarkMode = useDarkMode();

const workers = useAppSelector(selectWorkers);
const workersWithCurrentPc = workers.filter((worker) => worker.currentState.pc === programRow.address);
Expand All @@ -81,7 +83,7 @@ export const InstructionItem = forwardRef(
onClick(programRow);
}, [programRow, onClick]);

const { backgroundColor, hasTooltip } = getHighlightStatus(workers, programRow, status);
const { backgroundColor, hasTooltip } = getHighlightStatus(workers, programRow, status, isDarkMode);

const renderContent = () => {
return (
Expand Down Expand Up @@ -161,7 +163,7 @@ export const InstructionItem = forwardRef(
},
);

function getHighlightStatus(workers: WorkerState[], programRow: ProgramRow, status?: Status) {
function getHighlightStatus(workers: WorkerState[], programRow: ProgramRow, status?: Status, isDarkMode?: boolean) {
const pcInAllWorkers = (state: "currentState" | "previousState") =>
workers.map((worker) => getWorkerValueFromState(worker, state, "pc"));

Expand All @@ -177,7 +179,11 @@ function getHighlightStatus(workers: WorkerState[], programRow: ProgramRow, stat
pcInAllWorkers("currentState").length;

const blockBackground = programRow.block.number % 2 === 0 ? "#fff" : "#efefef";
const backgroundColor = isHighlighted ? `rgba(${hexToRgb(bgColor)}, ${bgOpacity})` : blockBackground;
const backgroundColor = isHighlighted
? `rgba(${hexToRgb(bgColor)}, ${bgOpacity})`
: isDarkMode
? invertHexColor(blockBackground)
: blockBackground;

return {
backgroundColor,
Expand Down
4 changes: 2 additions & 2 deletions src/components/MemoryPreview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ const MemoryCell = ({
<span
key={index}
className={classNames("relative mr-[1px]", {
"text-gray-700": (index + 1) % 2 === 0,
"text-gray-950": (index + 1) % 2 === 1,
"text-gray-700 dark:text-gray-300": (index + 1) % 2 === 0,
"text-gray-950 dark:text-gray-400": (index + 1) % 2 === 1,
"font-bold": value !== 0,
"opacity-50": isEqualAcrossWorkers && value === 0,
})}
Expand Down
3 changes: 3 additions & 0 deletions src/components/ProgramLoader/Assembly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import classNames from "classnames";
import { compile_assembly, disassemble } from "@typeberry/spectool-wasm";
import { mapUploadFileInputToOutput } from "./utils";
import CodeMirror from "@uiw/react-codemirror";
import useDarkMode from "@/hooks/useDarkMode.ts";

const DEFAULT_ASSEMBLY = `pre: a0 = 9
pre: ra = 0xffff0000
Expand Down Expand Up @@ -156,6 +157,7 @@ export const Assembly = ({
const [error, setError] = useState<string>();
const [assembly, setAssembly] = useState(defaultAssembly);
const [isFirstCompilation, setFirstCompilation] = useState(true);
const isDarkMode = useDarkMode();

// compile the assembly for the first time
useEffect(() => {
Expand Down Expand Up @@ -194,6 +196,7 @@ export const Assembly = ({
height="100%"
placeholder="Try writing some PolkaVM assembly code."
value={assembly}
theme={isDarkMode ? "dark" : "light"}
onChange={(value) => compile(value)}
/>
</div>
Expand Down
63 changes: 0 additions & 63 deletions src/components/ProgramLoader/BinaryFileUpload.tsx

This file was deleted.

18 changes: 0 additions & 18 deletions src/components/ProgramLoader/Bytecode.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/ProgramLoader/Examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const programs: {
export const Examples = ({ onProgramLoad }: { onProgramLoad: (val: ProgramUploadFileOutput) => void }) => {
return (
<div>
<p className="mb-2">Load example test file</p>
<h2 className="text-lg mb-4">Load an example test file</h2>
<RadioGroup
defaultValue="option-fibonacci"
onValueChange={(val) =>
Expand Down
107 changes: 78 additions & 29 deletions src/components/ProgramLoader/Loader.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Button } from "../ui/button";
import { Bytecode } from "./Bytecode";
import { Examples } from "./Examples";
import { TextFileUpload } from "./TextFileUpload";
import { useState, useCallback, useEffect } from "react";
import { ProgramUploadFileOutput } from "./types";
import { useDebuggerActions } from "@/hooks/useDebuggerActions";
import { useAppDispatch, useAppSelector } from "@/store/hooks.ts";
import { setIsProgramEditMode } from "@/store/debugger/debuggerSlice.ts";
import { selectIsAnyWorkerLoading } from "@/store/workers/workersSlice";
import { isSerializedError } from "@/store/utils";
import { ProgramFileUpload } from "@/components/ProgramLoader/ProgramFileUpload.tsx";
import { bytes } from "@typeberry/block";
import { selectInitialState } from "@/store/debugger/debuggerSlice.ts";
import { decodeStandardProgram } from "@typeberry/pvm-debugger-adapter";
import { RegistersArray } from "@/types/pvm.ts";

export const Loader = ({ setIsDialogOpen }: { setIsDialogOpen?: (val: boolean) => void }) => {
const dispatch = useAppDispatch();
const initialState = useAppSelector(selectInitialState);
const [programLoad, setProgramLoad] = useState<ProgramUploadFileOutput>();
const [error, setError] = useState<string>();
const [isSubmitted, setIsSubmitted] = useState(false);
Expand All @@ -23,38 +27,92 @@ export const Loader = ({ setIsDialogOpen }: { setIsDialogOpen?: (val: boolean) =
setError("");
}, [isLoading]);

const handleLoad = useCallback(async () => {
setIsSubmitted(true);
if (!programLoad) return;
const handleLoad = useCallback(
async (_event: unknown, program?: ProgramUploadFileOutput) => {
setIsSubmitted(true);

dispatch(setIsProgramEditMode(false));
if (!programLoad && !program) return;

try {
await debuggerActions.handleProgramLoad(programLoad);
setIsDialogOpen?.(false);
} catch (error) {
if (error instanceof Error || isSerializedError(error)) {
setError(error.message);
} else {
setError("Unknown error occured");
dispatch(setIsProgramEditMode(false));

try {
await debuggerActions.handleProgramLoad(program || programLoad);
setIsDialogOpen?.(false);
} catch (error) {
if (error instanceof Error || isSerializedError(error)) {
setError(error.message);
} else {
setError("Unknown error occurred");
}
}
},
[dispatch, programLoad, debuggerActions, setIsDialogOpen],
);

useEffect(() => {
const searchParams = new URLSearchParams(window.location.search);

if (searchParams.get("program")) {
const program = searchParams.get("program");

try {
// Add 0x prefix if it's not there - we're assuming it's the hex program either way
const hexProgram = program?.startsWith("0x") ? program : `0x${program}`;
const parsedBlob = bytes.BytesBlob.parseBlob(hexProgram ?? "");
const parsedBlobArray = Array.prototype.slice.call(parsedBlob.raw);

if (searchParams.get("flavour") === "jam") {
try {
const { code, /*memory,*/ registers } = decodeStandardProgram(parsedBlob.raw, new Uint8Array());

handleLoad({
program: Array.from(code),
name: "custom",
initial: {
regs: Array.from(registers) as RegistersArray,
pc: 0,
pageMap: [],
// TODO: map memory properly
// memory: [...memory],
gas: 10000n,
},
});
} catch (e) {
console.warn("Could not load the program from URL", e);
}
} else {
handleLoad(undefined, {
program: parsedBlobArray,
name: "custom",
initial: initialState,
});
}

window.history.replaceState({}, document.title, "/");
} catch (e) {
console.warn("Could not parse the program from URL", e);
}
}
}, [dispatch, programLoad, debuggerActions, setIsDialogOpen]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<>
<Tabs className="flex-1 flex flex-col items-start overflow-auto" defaultValue="upload">
<TabsList>
<TabsTrigger value="upload">JSON tests</TabsTrigger>
<TabsTrigger value="examples">Examples</TabsTrigger>
<TabsTrigger value="bytecode">RAW bytecode</TabsTrigger>
<TabsTrigger value="upload">Upload file</TabsTrigger>
<TabsTrigger value="examples">Start with examples</TabsTrigger>
</TabsList>
<div className="border-2 rounded p-4 flex-1 flex flex-col w-full h-full overflow-auto md:px-5">
<TabsContent value="upload">
<TextFileUpload
<ProgramFileUpload
onFileUpload={(val) => {
setProgramLoad(val);
setIsSubmitted(false);
}}
onParseError={(error) => {
setError(error);
}}
/>
</TabsContent>
<TabsContent value="examples">
Expand All @@ -65,16 +123,7 @@ export const Loader = ({ setIsDialogOpen }: { setIsDialogOpen?: (val: boolean) =
}}
/>
</TabsContent>
<TabsContent value="bytecode">
<Bytecode
onProgramLoad={(val, error) => {
setProgramLoad(val);
setIsSubmitted(false);
setError(error);
}}
/>
</TabsContent>
{error && isSubmitted && <p className="text-red-500">{error}</p>}
{error && isSubmitted && <p className="text-red-500 whitespace-pre-line">{error}</p>}
</div>
</Tabs>
<Button className="mt-3" id="load-button" type="button" onClick={handleLoad}>
Expand Down
Loading

0 comments on commit 1f94de6

Please sign in to comment.