Skip to content

Commit 192b87e

Browse files
host calls wip (#455)
* Handle host calls. * Initial version of host calls handling. * More wip stuff * Update gol example. * Increase default gas. * Refresh faster * More host calls WiP. * dedupe * use global service id * Update src/components/HostCallDialog/handlers/FetchHostCall.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update src/components/HostCallDialog/MemoryEditor.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 794f4bd commit 192b87e

39 files changed

+3039
-47
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"@radix-ui/react-tooltip": "^1.1.7",
3232
"@reduxjs/toolkit": "^2.9.0",
3333
"@tanstack/react-virtual": "^3.10.9",
34-
"@typeberry/lib": "^0.4.1-ea3c83c",
34+
"@typeberry/lib": "^0.4.1-3923458",
3535
"@typeberry/spectool-wasm": "0.23.0",
3636
"@uiw/react-codemirror": "^4.25.1",
3737
"class-variance-authority": "^0.7.1",

src/App.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import ProgramLoader from "@/pages/ProgramLoader.tsx";
1010
import { Navigate, Route, Routes } from "react-router";
1111
import { AppsSidebar } from "./packages/ui-kit/AppsSidebar";
1212
import { MobileDebuggerControls } from "./components/MobileDebuggerControlls";
13+
import { HostCallDialog } from "./components/HostCallDialog";
1314

1415
function App() {
1516
const { pvmInitialized } = useAppSelector((state) => state.debugger);
@@ -45,6 +46,7 @@ function App() {
4546
</div>
4647

4748
<ToastContainer />
49+
<HostCallDialog />
4850
</>
4951
);
5052
}

src/components/DebuggerSettings/Content.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@ function stringToNumber<T>(value: string, cb: (x: string) => T): T {
2626
export const DebuggerSettingsContent = () => {
2727
const debuggerState = useAppSelector((state) => state.debugger);
2828
const dispatch = useAppDispatch();
29+
const spiArgs = bytes.BytesBlob.blobFrom(debuggerState.spiArgs?.slice(0) ?? new Uint8Array());
2930
const { numeralSystem } = useContext(NumeralSystemContext);
3031
const [error, setError] = useState<string>();
31-
const [textSpi, setTextSpi] = useState(debuggerState.spiArgs?.toString() ?? "");
32-
const isSpiError = textSpi !== debuggerState.spiArgs?.toString();
32+
const [textSpi, setTextSpi] = useState(spiArgs.toString());
33+
const isSpiError = textSpi !== spiArgs.toString();
3334
const handleTextSpi = (newVal: string) => {
3435
setTextSpi(newVal);
3536
try {
3637
const parsed = bytes.BytesBlob.parseBlob(newVal);
37-
dispatch(setSpiArgs(parsed));
38+
dispatch(setSpiArgs(parsed.raw));
3839
} catch {
3940
// Ignore parse errors - user may be typing
4041
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { useCallback, useEffect, useState } from "react";
2+
import { Input } from "@/components/ui/input";
3+
import { valueToNumeralSystem } from "@/components/Instructions/utils";
4+
import { DEFAULT_GAS, DEFAULT_REGS, ExpectedState, RegistersArray } from "@/types/pvm";
5+
import { NumeralSystem } from "@/context/NumeralSystem";
6+
import { MemoryEditor } from "./MemoryEditor";
7+
import { HostCallActionButtons } from "./handlers/HostCallActionButtons";
8+
9+
// Re-export for convenience
10+
export type { MemoryEdit } from "@/store/workers/workersSlice";
11+
import type { HostCallResumeMode, MemoryEdit } from "@/store/workers/workersSlice";
12+
13+
function stringToNumber<T>(value: string, cb: (x: string) => T): T {
14+
try {
15+
return cb(value);
16+
} catch {
17+
return cb("0");
18+
}
19+
}
20+
21+
interface DefaultHostCallContentProps {
22+
currentState: ExpectedState;
23+
isLoading: boolean;
24+
numeralSystem: NumeralSystem;
25+
readMemory: (startAddress: number, length: number) => Promise<Uint8Array>;
26+
onRegsChange: (regs: bigint[]) => void;
27+
onGasChange: (gas: bigint) => void;
28+
onMemoryChange: (memory: MemoryEdit | null) => void;
29+
onResume: (mode: HostCallResumeMode, regs?: bigint[], gas?: bigint) => void;
30+
}
31+
32+
export const DefaultHostCallContent: React.FC<DefaultHostCallContentProps> = ({
33+
currentState,
34+
isLoading,
35+
numeralSystem,
36+
readMemory,
37+
onRegsChange,
38+
onResume,
39+
onGasChange,
40+
onMemoryChange,
41+
}) => {
42+
// Local state for editable values
43+
const [regs, setRegs] = useState<bigint[]>([...DEFAULT_REGS]);
44+
const [gas, setGas] = useState<bigint>(0n);
45+
46+
// Initialize local state when currentState changes
47+
useEffect(() => {
48+
if (currentState) {
49+
// Copy current registers
50+
const newRegs = currentState.regs ? [...currentState.regs] : [...DEFAULT_REGS];
51+
setRegs(newRegs);
52+
onRegsChange(newRegs);
53+
54+
// Set gas to current gas - 10 (as per requirement)
55+
const currentGas = currentState.gas ?? DEFAULT_GAS;
56+
const newGas = currentGas > 10n ? currentGas - 10n : 0n;
57+
setGas(newGas);
58+
onGasChange(newGas);
59+
}
60+
}, [currentState, onRegsChange, onGasChange]);
61+
62+
const handleRegisterChange = (index: number, value: string) => {
63+
const newValue = stringToNumber(value, BigInt);
64+
setRegs((prev) => {
65+
const newRegs = [...prev];
66+
newRegs[index] = newValue;
67+
onRegsChange(newRegs);
68+
return newRegs;
69+
});
70+
};
71+
72+
const handleGasChange = (value: string) => {
73+
const newValue = stringToNumber(value, BigInt);
74+
setGas(newValue);
75+
onGasChange(newValue);
76+
};
77+
78+
const handleMemoryChange = useCallback(
79+
(address: number, data: Uint8Array) => {
80+
onMemoryChange({ address, data });
81+
},
82+
[onMemoryChange],
83+
);
84+
85+
return (
86+
<>
87+
<div className="space-y-4 flex-1 overflow-y-auto p-2">
88+
{/* Two-column layout: 1fr for gas/registers, 2fr for memory */}
89+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
90+
{/* Column 1: Gas and Registers */}
91+
<div className="space-y-4 md:col-span-1">
92+
{/* Gas */}
93+
<div className="space-y-2">
94+
<label className="text-sm font-medium">Gas</label>
95+
<Input
96+
className="font-mono"
97+
value={valueToNumeralSystem(gas, numeralSystem)}
98+
onChange={(e) => handleGasChange(e.target.value)}
99+
onKeyUp={(e) => e.key === "Enter" && e.currentTarget.blur()}
100+
disabled={isLoading}
101+
/>
102+
</div>
103+
104+
{/* Registers */}
105+
<div className="space-y-2">
106+
<label className="text-sm font-medium">Registers</label>
107+
<div className="space-y-1">
108+
{(regs as RegistersArray).map((regValue, index) => (
109+
<div key={index} className="flex items-center gap-2">
110+
<span className="w-6 text-xs font-mono">
111+
ω<sub>{index}</sub>
112+
</span>
113+
<Input
114+
className="font-mono text-sm h-7 flex-1"
115+
value={valueToNumeralSystem(regValue, numeralSystem)}
116+
onChange={(e) => handleRegisterChange(index, e.target.value)}
117+
onKeyUp={(e) => e.key === "Enter" && e.currentTarget.blur()}
118+
disabled={isLoading}
119+
/>
120+
</div>
121+
))}
122+
</div>
123+
</div>
124+
</div>
125+
126+
{/* Column 2: Memory Editor (2x width) */}
127+
<div className="space-y-2 md:col-span-2">
128+
<MemoryEditor readMemory={readMemory} disabled={isLoading} onMemoryChange={handleMemoryChange} />
129+
</div>
130+
</div>
131+
</div>
132+
<HostCallActionButtons onResume={onResume} disabled={isLoading} />
133+
</>
134+
);
135+
};

0 commit comments

Comments
 (0)