Skip to content

Commit

Permalink
Merge pull request #3158 from quantified-uncertainty/serializable-values
Browse files Browse the repository at this point in the history
Value serialization
  • Loading branch information
berekuk authored May 2, 2024
2 parents 090b5f4 + 6f23f20 commit 736e123
Show file tree
Hide file tree
Showing 125 changed files with 5,461 additions and 1,853 deletions.
9 changes: 4 additions & 5 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
"lodash": "^4.17.21",
"mermaid": "^10.9.0",
"prettier": "^3.2.5",
"react": "^18.2.0",
"react-draggable": "^4.4.6",
"react-hook-form": "^7.50.0",
"react-markdown": "^9.0.1",
Expand All @@ -59,15 +58,15 @@
"@storybook/react": "^7.6.12",
"@storybook/react-vite": "^8.0.9",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.1",
"@testing-library/react": "^15.0.6",
"@testing-library/user-event": "^14.5.2",
"@types/d3": "^7.4.3",
"@types/hast": "^3.0.4",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.14.202",
"@types/node": "^20.12.7",
"@types/react": "^18.2.52",
"@types/react-dom": "^18.2.19",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"@types/unist": "^3.0.2",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
Expand All @@ -83,7 +82,7 @@
"postcss": "^8.4.35",
"postcss-cli": "^11.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-dom": "^18.3.1",
"rollup-plugin-node-builtins": "^2.1.2",
"storybook": "^8.0.9",
"tailwindcss": "^3.4.3",
Expand Down
133 changes: 107 additions & 26 deletions packages/components/src/components/PlaygroundSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
import React from "react";
import { FC } from "react";
import { z } from "zod";

import { SqScale } from "@quri/squiggle-lang";
import { defaultRunnerName, RunnerName, SqScale } from "@quri/squiggle-lang";
import {
CheckboxFormField,
NumberFormField,
RadioFormField,
SelectFormField,
TextFormField,
WrenchIcon,
} from "@quri/ui";

import { SAMPLE_COUNT_MAX, SAMPLE_COUNT_MIN } from "../lib/constants.js";
import { functionChartDefaults } from "../widgets/LambdaWidget/FunctionChart/utils.js";
import { FormComment } from "./ui/FormComment.js";
import { FormSection } from "./ui/FormSection.js";
import { useWatch } from "react-hook-form";

export const environmentSchema = z.object({
sampleCount: z.number().int().gte(SAMPLE_COUNT_MIN).lte(SAMPLE_COUNT_MAX),
xyPointLength: z.number().int().gte(10).lte(10000),
seed: z.string(),
});

const runnerSchema = z.union([
z.literal("embedded" satisfies RunnerName),
z.literal("web-worker" satisfies RunnerName),
z.literal("embedded-with-serialization" satisfies RunnerName),
]);

export const functionSettingsSchema = z.object({
start: z.number().finite(),
stop: z.number().finite(),
Expand Down Expand Up @@ -67,6 +76,7 @@ export const distributionSettingsSchema = z.object({

export const viewSettingsSchema = z.object({
environment: environmentSchema,
runner: runnerSchema,
distributionChartSettings: distributionSettingsSchema,
functionChartSettings: functionSettingsSchema,
editorSettings: editorSettings,
Expand All @@ -83,6 +93,7 @@ export const defaultPlaygroundSettings: PlaygroundSettings = {
xyPointLength: 1000,
seed: "default_seed",
},
runner: defaultRunnerName,
functionChartSettings: {
start: functionChartDefaults.min,
stop: functionChartDefaults.max,
Expand Down Expand Up @@ -130,27 +141,97 @@ export type MetaSettings = {
disableLogX?: boolean;
};

export const EnvironmentForm: React.FC = () => (
<div className="space-y-4">
<TextFormField<PlaygroundSettings>
name="environment.seed"
label="Random Seed"
description="Seed for random number generation. All random functions ultimately are dependent on this value."
/>
<NumberFormField<PlaygroundSettings>
name="environment.sampleCount"
label="Sample Count"
description="How many samples to use for Monte Carlo simulations. This can occasionally be overridden by specific Squiggle programs."
/>
<NumberFormField<PlaygroundSettings>
name="environment.xyPointLength"
label="Coordinate Count (For PointSet Shapes)"
description="When distributions are converted into PointSet shapes, we need to know how many coordinates to use."
/>
</div>
);
const SelectRunnerField: FC = () => {
const runner = useWatch<PlaygroundSettings, "runner">({ name: "runner" });

type Option = { value: RunnerName; label: string };

const options: Option[] = [
{ value: "embedded", label: "Embedded" },
{ value: "web-worker", label: "Web Worker (experimental)" },
{
value: "embedded-with-serialization",
label: "Embedded with serialization check (experimental)",
},
];

return (
<div>
<SelectFormField<PlaygroundSettings, RunnerName, Option>
name="runner"
label="Squiggle Runner (Experimental)"
size="small"
options={options}
optionToFieldValue={(option) => option.value}
fieldValueToOption={(value) =>
options.find((o) => o.value === value) ?? null
}
renderOption={(option) => <div className="text-sm">{option.label}</div>}
required
/>
{runner === "embedded" && (
<FormComment>
<p>
This runner runs all Squiggle code in the main browser thread. This
can cause the UI to freeze during long-running simulations.
</p>
</FormComment>
)}
{runner === "web-worker" && (
<FormComment>
<p className="pb-2 pt-1">
<WrenchIcon className="mr-1 inline" size={14} />
This runner is <strong>experimental</strong>.
</p>
<p className="pb-2">
Risks involved: out-of-memory errors; responses arriving in wrong
order; bugs in serialization code when we return values from the
worker to the main thread.
</p>
<p>
The main benefit is that the UI won&apos;t be blocked during
long-running computations.
</p>
</FormComment>
)}
{runner === "embedded-with-serialization" && (
<FormComment>
<p>
<WrenchIcon className="mr-1 inline" size={14} />
This runner is only useful for debugging. It works in the same way
as the embedded runner, but it serializes and then deserializes each
result to check for bugs in serialization code.
</p>
</FormComment>
)}
</div>
);
};

export const RenderingSettingsForm: FC = () => {
return (
<div className="space-y-4">
<TextFormField<PlaygroundSettings>
name="environment.seed"
label="Random Seed"
description="Seed for random number generation. All random functions ultimately are dependent on this value."
/>
<NumberFormField<PlaygroundSettings>
name="environment.sampleCount"
label="Sample Count"
description="How many samples to use for Monte Carlo simulations. This can occasionally be overridden by specific Squiggle programs."
/>
<NumberFormField<PlaygroundSettings>
name="environment.xyPointLength"
label="Coordinate Count (For PointSet Shapes)"
description="When distributions are converted into PointSet shapes, we need to know how many coordinates to use."
/>
<SelectRunnerField />
</div>
);
};

export const DistributionSettingsForm: React.FC<{
export const DistributionSettingsForm: FC<{
metaSettings?: MetaSettings;
}> = ({ metaSettings }) => {
return (
Expand Down Expand Up @@ -219,7 +300,7 @@ export const DistributionSettingsForm: React.FC<{
);
};

export const FunctionSettingsForm: React.FC = () => {
export const FunctionSettingsForm: FC = () => {
return (
<FormSection title="Function Display Settings">
<div className="space-y-6">
Expand Down Expand Up @@ -248,7 +329,7 @@ export const FunctionSettingsForm: React.FC = () => {
);
};

export const EditorSettingsForm: React.FC = () => {
export const EditorSettingsForm: FC = () => {
return (
<FormSection title="Editor Settings">
<CheckboxFormField<PlaygroundSettings>
Expand All @@ -259,7 +340,7 @@ export const EditorSettingsForm: React.FC = () => {
);
};

export const PlaygroundSettingsForm: React.FC<{
export const PlaygroundSettingsForm: FC<{
withFunctionSettings?: boolean;
withGlobalSettings?: boolean;
metaSettings?: MetaSettings;
Expand All @@ -274,7 +355,7 @@ export const PlaygroundSettingsForm: React.FC<{
<>
<div className="mb-6">
<FormSection title="Rendering Settings">
<EnvironmentForm />
<RenderingSettingsForm />
</FormSection>
</div>

Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/components/SquiggleChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { FC, memo } from "react";
import { SqValuePath } from "@quri/squiggle-lang";
import { RefreshIcon } from "@quri/ui";

import { useSimulatorManager } from "../lib/hooks/useSimulatorManager.js";
import { useSimulator } from "../lib/hooks/useSimulator.js";
import {
ProjectExecutionProps,
StandaloneExecutionProps,
Expand Down Expand Up @@ -33,7 +33,7 @@ export const SquiggleChart: FC<SquiggleChartProps> = memo(
// This is important, for example, in VS Code extension.
// TODO: maybe `useRunnerState` could be merged with `useSquiggle`, but it does some extra stuff (autorun mode).

const { simulation } = useSimulatorManager({
const { simulation } = useSimulator({
code,
setup: project
? { type: "project", project, continues }
Expand Down
4 changes: 2 additions & 2 deletions packages/components/src/components/SquiggleEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { FC, useMemo, useRef } from "react";

import { useUncontrolledCode } from "../lib/hooks/index.js";
import { usePlaygroundSettings } from "../lib/hooks/usePlaygroundSettings.js";
import { useSimulatorManager } from "../lib/hooks/useSimulatorManager.js";
import { useSimulator } from "../lib/hooks/useSimulator.js";
import {
ProjectExecutionProps,
simulationErrors,
Expand Down Expand Up @@ -41,7 +41,7 @@ export const SquiggleEditor: FC<SquiggleEditorProps> = ({
onCodeChange,
});

const { simulation, project, sourceId, runSimulation } = useSimulatorManager({
const { simulation, project, sourceId, runSimulation } = useSimulator({
code,
setup: propsProject
? { type: "project", project: propsProject, continues }
Expand Down
15 changes: 7 additions & 8 deletions packages/components/src/components/SquigglePlayground/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SqLinker, SqValuePath } from "@quri/squiggle-lang";
import { RefreshIcon } from "@quri/ui";

import { usePlaygroundSettings } from "../../lib/hooks/usePlaygroundSettings.js";
import { useSimulatorManager } from "../../lib/hooks/useSimulatorManager.js";
import { useSimulator } from "../../lib/hooks/useSimulator.js";
import { useUncontrolledCode } from "../../lib/hooks/useUncontrolledCode.js";
import {
PartialPlaygroundSettings,
Expand Down Expand Up @@ -72,14 +72,12 @@ export const SquigglePlayground: React.FC<SquigglePlaygroundProps> = (
) => {
const {
linker,
sourceId: _sourceId,
onExportsChange,
onSettingsChange,
renderExtraControls,
renderExtraDropdownItems,
renderExtraModal,
renderImportTooltip,
autorunMode: defaultAutorunMode = true,
height = 500,
...defaultSettings
} = props;
Expand All @@ -101,15 +99,16 @@ export const SquigglePlayground: React.FC<SquigglePlaygroundProps> = (
project,
simulation,
autorunMode,
sourceId,
sourceId, // from props.sourceId or generated by hook
setAutorunMode,
runSimulation,
} = useSimulatorManager({
} = useSimulator({
code,
sourceId: _sourceId,
sourceId: props.sourceId, // can be undefined
setup: { type: "projectFromLinker", linker },
environment: settings.environment,
initialAutorunMode: defaultAutorunMode,
initialAutorunMode: props.autorunMode ?? true,
runnerName: settings.runner,
});

useEffect(() => {
Expand Down Expand Up @@ -186,7 +185,7 @@ export const SquigglePlayground: React.FC<SquigglePlaygroundProps> = (
/>
</ProjectContext.Provider>
);
} else if (defaultAutorunMode === false) {
} else if (!autorunMode) {
return (
<div className="grid h-full place-items-center">
<div className="text-sm text-gray-500">{`Press the "Run" button (top left) to simulate`}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export type ViewerWithMenuBarHandle = {
export const ViewerWithMenuBar = forwardRef<ViewerWithMenuBarHandle, Props>(
function ViewerWithMenuBar(
{
simulation: simulation,
simulation,
playgroundSettings,
randomizeSeed,
showMenu = true,
Expand Down
1 change: 0 additions & 1 deletion packages/components/src/lib/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ export { useCanvasCursor } from "./useCanvasCursor.js";
export { useEffectRef } from "./useEffectRef.js";
export { useForceUpdate } from "./useForceUpdate.js";
export { useInitialWidth } from "./useInitialWidth.js";
export { type SimulatorManagerArgs } from "./useSimulatorManager.js";
export { useUncontrolledCode } from "./useUncontrolledCode.js";
Loading

0 comments on commit 736e123

Please sign in to comment.