From 1b2b20803ab82fafbfe75fecaa05f6f6c1222242 Mon Sep 17 00:00:00 2001 From: francisanthony17 Date: Wed, 29 Nov 2023 15:57:20 +1100 Subject: [PATCH] initialise debugger dev --- client/src/hooks/useBreakpoints.tsx | 141 ++++++++++++++++------------ client/src/layers/trace/index.tsx | 3 +- client/src/pages/DebugPage.tsx | 21 +++++ 3 files changed, 106 insertions(+), 59 deletions(-) diff --git a/client/src/hooks/useBreakpoints.tsx b/client/src/hooks/useBreakpoints.tsx index 70c9f476..e5cfde5c 100644 --- a/client/src/hooks/useBreakpoints.tsx +++ b/client/src/hooks/useBreakpoints.tsx @@ -1,60 +1,85 @@ -import { useCallback } from "react"; +import { call } from "components/script-editor/call"; +import { get, keyBy, toLower as lower, startCase } from "lodash"; +import memoizee from "memoizee"; +import { TraceEventType } from "protocol"; +import { useMemo } from "react"; +import { UploadedTrace } from "slices/UIState"; +import { useLayer } from "slices/layers"; + + +export type Comparator = { + key: string; + apply: (value: number, reference: number) => boolean; +}; + +export type Breakpoint = { + key: string; + property?: string; + reference?: number; + condition?: Comparator; + active?: boolean; + type?: TraceEventType; +}; + +export type DebugLayerData = { + code?: string; + monotonicF?: boolean; + monotonicG?: boolean; + breakpoints?: Breakpoint[]; + trace?: UploadedTrace; +}; +export function useBreakpoints(key?: string) { + const { layer } = useLayer(key); + const {monotonicF, monotonicG,breakpoints ,code,trace} = layer?.source??{} + // TODO: + return useMemo(() => { + const memo = keyBy(trace?.content?.events, "id"); + return memoizee((step: number) => { + const event = trace?.content?.events?.[step]; + if (event) { + try { + // Check monotonic f or g values + if (step) { + for (const p of [monotonicF && "f", monotonicG && "g"]) { + if (p && get(memo[`${event.pId}`], p) > get(event, p)) { + return { result: `Monotonicity violation on ${p}` }; + } + } + } + // Check breakpoints in the breakpoints section + for (const { + active, + condition, + type, + property = "", + reference = 0, + } of breakpoints??[]) { + const isType = !type || type === event.type; + const match = condition?.apply?.(get(event, property), reference); + if (active && isType && match) { + return { + result: `${property} ${lower( + startCase(condition?.key) + )} ${reference}`, + }; + } + } + // Check breakpoints in the script editor section + if ( + call(code ?? "", "shouldBreak", [ + step, + event, + trace?.content?.events?? [], + ]) + ) { + return { result: "Script editor" }; + } + } catch (e) { + return { error: `${e}` }; + } + } + return { result: "" }; + }); + }, [code, trace?.content, breakpoints, monotonicF, monotonicG]); -export function useBreakpoints() { - //TODO: - // const [{ specimen }] = useSpecimen(); - // const [{ code, breakpoints = [], monotonicF, monotonicG }] = useUIState(); - // return useMemo(() => { - // const memo = keyBy(specimen?.eventList, "id"); - // return memoize((step: number) => { - // const event = specimen?.eventList?.[step]; - // if (event) { - // try { - // // Check monotonic f or g values - // if (step) { - // for (const p of [monotonicF && "f", monotonicG && "g"]) { - // if (p && get(memo[`${event.pId}`], p) > get(event, p)) { - // return { result: `Monotonicity violation on ${p}` }; - // } - // } - // } - // // Check breakpoints in the breakpoints section - // for (const { - // active, - // condition, - // type, - // property = "", - // reference = 0, - // } of breakpoints) { - // const isType = !type || type === event.type; - // const match = condition?.apply?.(get(event, property), reference); - // if (active && isType && match) { - // return { - // result: `${property} ${lower( - // startCase(condition?.key) - // )} ${reference}`, - // }; - // } - // } - // // Check breakpoints in the script editor section - // if ( - // call(code ?? "", "shouldBreak", [ - // step, - // event, - // specimen?.eventList ?? [], - // ]) - // ) { - // return { result: "Script editor" }; - // } - // } catch (e) { - // return { error: `${e}` }; - // } - // } - // return { result: "" }; - // }); - // }, [code, specimen, breakpoints, monotonicF, monotonicG]); - return useCallback( - (_i: number) => ({ result: "", error: undefined, offset: 0 }), - [] - ); } diff --git a/client/src/layers/trace/index.tsx b/client/src/layers/trace/index.tsx index 142d9c59..c43ac307 100644 --- a/client/src/layers/trace/index.tsx +++ b/client/src/layers/trace/index.tsx @@ -14,6 +14,7 @@ import { colorsHex, getColorHex } from "components/renderer/colors"; import { parseString } from "components/renderer/parser/parseString"; import { useTraceParser } from "components/renderer/parser/parseTrace"; import { ParseTraceWorkerReturnType } from "components/renderer/parser/parseTraceSlave.worker"; +import { DebugLayerData } from "hooks/useBreakpoints"; import { useEffectWhen } from "hooks/useEffectWhen"; import { LayerController, inferLayerName } from "layers"; import { @@ -99,7 +100,7 @@ export type TraceLayerData = { trace?: UploadedTrace; parsedTrace?: ParseTraceWorkerReturnType; onion?: "off" | "transparent" | "solid"; -} & PlaybackLayerData; +} & PlaybackLayerData & DebugLayerData; export type TraceLayer = Layer; diff --git a/client/src/pages/DebugPage.tsx b/client/src/pages/DebugPage.tsx index 57eb1d18..864b480b 100644 --- a/client/src/pages/DebugPage.tsx +++ b/client/src/pages/DebugPage.tsx @@ -1,5 +1,10 @@ import { TabContext, TabList, TabPanel } from "@mui/lab"; import { Box, Tab, Typography as Type } from "@mui/material"; +import { + LayersOutlined as LayersIcon, + SortOutlined as StepsIcon, +} from "@mui/icons-material"; +import { delay, map } from "lodash"; import { Flex } from "components/generic/Flex"; import { Space } from "components/generic/Space"; import { Switch } from "components/generic/Switch"; @@ -9,11 +14,16 @@ import { Page } from "pages/Page"; import { ReactNode, useState } from "react"; import { useUIState } from "slices/UIState"; import { BreakpointListEditor } from "../components/breakpoint-editor/BreakpointListEditor"; +import { useLayer } from "slices/layers"; +import { FeaturePicker } from "components/app-bar/FeaturePicker"; +import { inferLayerName, layerHandlers } from "layers/Layer"; + export function DebugPage() { const { controls, onChange, state } = useViewTreeContext(); const [{ monotonicF, monotonicG }, setUIState] = useUIState(); const [tab, setTab] = useState("standard"); + const { key, setKey, layers, layer } = useLayer(); function renderHeading(label: ReactNode) { return ( @@ -25,6 +35,17 @@ export function DebugPage() { + } + label="Layer" + value={key} + items={map(layers, (l) => ({ + id: l.key, + name: inferLayerName(l), + }))} + onChange={setKey} + showArrow + /> setTab(v)}>