11import Resizable , { type ContextValue } from "@corvu/resizable" ;
22import { useParams } from "@solidjs/router" ;
3- import { Show , createEffect , createResource , createSignal , useContext } from "solid-js" ;
3+ import {
4+ Match ,
5+ Show ,
6+ Switch ,
7+ createEffect ,
8+ createResource ,
9+ createSignal ,
10+ useContext ,
11+ } from "solid-js" ;
412import { Dynamic } from "solid-js/web" ;
513import invariant from "tiny-invariant" ;
614
7- import { RepoContext , RpcContext , getLiveDoc } from "../api" ;
15+ import { useApi } from "../api" ;
816import { IconButton , ResizableHandle } from "../components" ;
9- import { LiveModelContext , type ModelDocument , enlivenModelDocument } from "../model " ;
17+ import { DiagramPane } from "../diagram/diagram_editor " ;
1018import { ModelPane } from "../model/model_editor" ;
1119import {
1220 type CellConstructor ,
@@ -16,9 +24,15 @@ import {
1624} from "../notebook" ;
1725import { BrandedToolbar , HelpButton } from "../page" ;
1826import { TheoryLibraryContext } from "../stdlib" ;
19- import type { ModelAnalysisMeta } from "../theory" ;
20- import type { AnalysisDocument , LiveAnalysisDocument } from "./document" ;
21- import type { ModelAnalysis } from "./types" ;
27+ import type { AnalysisMeta } from "../theory" ;
28+ import { LiveAnalysisContext } from "./context" ;
29+ import {
30+ type LiveAnalysisDocument ,
31+ type LiveDiagramAnalysisDocument ,
32+ type LiveModelAnalysisDocument ,
33+ getLiveAnalysis ,
34+ } from "./document" ;
35+ import type { Analysis } from "./types" ;
2236
2337import PanelRight from "lucide-solid/icons/panel-right" ;
2438import PanelRightClose from "lucide-solid/icons/panel-right-close" ;
@@ -28,87 +42,13 @@ export default function AnalysisPage() {
2842 const refId = params . ref ;
2943 invariant ( refId , "Must provide document ref as parameter to analysis page" ) ;
3044
31- const rpc = useContext ( RpcContext ) ;
32- const repo = useContext ( RepoContext ) ;
45+ const api = useApi ( ) ;
3346 const theories = useContext ( TheoryLibraryContext ) ;
34- invariant ( rpc && repo && theories , "Missing context for analysis page" ) ;
35-
36- const [ liveAnalysis ] = createResource < LiveAnalysisDocument > ( async ( ) => {
37- const liveDoc = await getLiveDoc < AnalysisDocument > ( rpc , repo , refId ) ;
38- const { doc } = liveDoc ;
39- invariant ( doc . type === "analysis" , ( ) => `Expected analysis, got type: ${ doc . type } ` ) ;
47+ invariant ( theories , "Must provide theory library as context to analysis page" ) ;
4048
41- const liveModelDoc = await getLiveDoc < ModelDocument > ( rpc , repo , doc . modelRef . refId ) ;
42- const liveModel = enlivenModelDocument ( doc . modelRef . refId , liveModelDoc , theories ) ;
43-
44- return { refId, liveDoc, liveModel } ;
45- } ) ;
49+ const [ liveAnalysis ] = createResource ( ( ) => getLiveAnalysis ( refId , api , theories ) ) ;
4650
47- return (
48- < Show when = { liveAnalysis ( ) } >
49- { ( liveAnalysis ) => < AnalysisDocumentEditor liveAnalysis = { liveAnalysis ( ) } /> }
50- </ Show >
51- ) ;
52- }
53-
54- /** Notebook editor for analyses of models of double theories.
55- */
56- export function AnalysisPane ( props : {
57- liveAnalysis : LiveAnalysisDocument ;
58- } ) {
59- const liveDoc = ( ) => props . liveAnalysis . liveDoc ;
60- return (
61- < LiveModelContext . Provider value = { props . liveAnalysis . liveModel } >
62- < NotebookEditor
63- handle = { liveDoc ( ) . docHandle }
64- path = { [ "notebook" ] }
65- notebook = { liveDoc ( ) . doc . notebook }
66- changeNotebook = { ( f ) => liveDoc ( ) . changeDoc ( ( doc ) => f ( doc . notebook ) ) }
67- formalCellEditor = { ModelAnalysisCellEditor }
68- cellConstructors = { modelAnalysisCellConstructors (
69- props . liveAnalysis . liveModel . theory ( ) ?. modelAnalyses ?? [ ] ,
70- ) }
71- noShortcuts = { true }
72- />
73- </ LiveModelContext . Provider >
74- ) ;
75- }
76-
77- function ModelAnalysisCellEditor ( props : FormalCellEditorProps < ModelAnalysis > ) {
78- const liveModel = useContext ( LiveModelContext ) ;
79- invariant ( liveModel , "Live model should be provided as context for analysis" ) ;
80-
81- return (
82- < Show when = { liveModel . theory ( ) ?. modelAnalysis ( props . content . id ) } >
83- { ( analysis ) => (
84- < Dynamic
85- component = { analysis ( ) . component }
86- liveModel = { liveModel }
87- content = { props . content . content }
88- changeContent = { ( f : ( c : unknown ) => void ) =>
89- props . changeContent ( ( content ) => f ( content . content ) )
90- }
91- />
92- ) }
93- </ Show >
94- ) ;
95- }
96-
97- function modelAnalysisCellConstructors (
98- analyses : ModelAnalysisMeta [ ] ,
99- ) : CellConstructor < ModelAnalysis > [ ] {
100- return analyses . map ( ( analysis ) => {
101- const { id, name, description, initialContent } = analysis ;
102- return {
103- name,
104- description,
105- construct : ( ) =>
106- newFormalCell ( {
107- id,
108- content : initialContent ( ) ,
109- } ) ,
110- } ;
111- } ) ;
51+ return < AnalysisDocumentEditor liveAnalysis = { liveAnalysis ( ) } /> ;
11252}
11353
11454/** Editor for a model of a double theory.
@@ -117,11 +57,8 @@ The editor includes a notebook for the model itself plus another pane for
11757performing analysis of the model.
11858 */
11959export function AnalysisDocumentEditor ( props : {
120- liveAnalysis : LiveAnalysisDocument ;
60+ liveAnalysis ? : LiveAnalysisDocument ;
12161} ) {
122- const rpc = useContext ( RpcContext ) ;
123- invariant ( rpc , "Must provide RPC context" ) ;
124-
12562 const [ resizableContext , setResizableContext ] = createSignal < ContextValue > ( ) ;
12663 const [ isSidePanelOpen , setSidePanelOpen ] = createSignal ( true ) ;
12764
@@ -170,7 +107,7 @@ export function AnalysisDocumentEditor(props: {
170107 </ Show >
171108 </ IconButton >
172109 </ BrandedToolbar >
173- < ModelPane liveModel = { props . liveAnalysis . liveModel } />
110+ < AnalysisOfPane liveAnalysis = { props . liveAnalysis } />
174111 </ Resizable . Panel >
175112 < ResizableHandle hidden = { ! isSidePanelOpen ( ) } />
176113 < Resizable . Panel
@@ -184,7 +121,11 @@ export function AnalysisDocumentEditor(props: {
184121 >
185122 < div class = "notebook-container" >
186123 < h2 > Analysis</ h2 >
187- < AnalysisPane liveAnalysis = { props . liveAnalysis } />
124+ < Show when = { props . liveAnalysis } >
125+ { ( liveAnalysis ) => (
126+ < AnalysisNotebookEditor liveAnalysis = { liveAnalysis ( ) } />
127+ ) }
128+ </ Show >
188129 </ div >
189130 </ Resizable . Panel >
190131 </ >
@@ -193,3 +134,107 @@ export function AnalysisDocumentEditor(props: {
193134 </ Resizable >
194135 ) ;
195136}
137+
138+ const AnalysisOfPane = ( props : {
139+ liveAnalysis ?: LiveAnalysisDocument ;
140+ } ) => (
141+ < Switch >
142+ < Match when = { props . liveAnalysis ?. analysisType === "model" && props . liveAnalysis . liveModel } >
143+ { ( liveModel ) => < ModelPane liveModel = { liveModel ( ) } /> }
144+ </ Match >
145+ < Match
146+ when = { props . liveAnalysis ?. analysisType === "diagram" && props . liveAnalysis . liveDiagram }
147+ >
148+ { ( liveDiagram ) => < DiagramPane liveDiagram = { liveDiagram ( ) } /> }
149+ </ Match >
150+ </ Switch >
151+ ) ;
152+
153+ /** Notebook editor for analyses of models of double theories.
154+ */
155+ export function AnalysisNotebookEditor ( props : {
156+ liveAnalysis : LiveAnalysisDocument ;
157+ } ) {
158+ const liveDoc = ( ) => props . liveAnalysis . liveDoc ;
159+
160+ const cellConstructors = ( ) => {
161+ let meta = undefined ;
162+ if ( props . liveAnalysis . analysisType === "model" ) {
163+ meta = props . liveAnalysis . liveModel . theory ( ) ?. modelAnalyses ;
164+ } else if ( props . liveAnalysis . analysisType === "diagram" ) {
165+ meta = props . liveAnalysis . liveDiagram . liveModel . theory ( ) ?. diagramAnalyses ;
166+ }
167+ return ( meta ?? [ ] ) . map ( analysisCellConstructor ) ;
168+ } ;
169+
170+ return (
171+ < LiveAnalysisContext . Provider value = { props . liveAnalysis } >
172+ < NotebookEditor
173+ handle = { liveDoc ( ) . docHandle }
174+ path = { [ "notebook" ] }
175+ notebook = { liveDoc ( ) . doc . notebook }
176+ changeNotebook = { ( f ) => liveDoc ( ) . changeDoc ( ( doc ) => f ( doc . notebook ) ) }
177+ formalCellEditor = { AnalysisCellEditor }
178+ cellConstructors = { cellConstructors ( ) }
179+ noShortcuts = { true }
180+ />
181+ </ LiveAnalysisContext . Provider >
182+ ) ;
183+ }
184+
185+ function AnalysisCellEditor ( props : FormalCellEditorProps < Analysis < unknown > > ) {
186+ const liveAnalysis = useContext ( LiveAnalysisContext ) ;
187+ invariant ( liveAnalysis , "Live analysis should be provided as context for cell editor" ) ;
188+
189+ return (
190+ < Switch >
191+ < Match
192+ when = {
193+ liveAnalysis . analysisType === "model" &&
194+ liveAnalysis . liveModel . theory ( ) ?. modelAnalysis ( props . content . id )
195+ }
196+ >
197+ { ( analysis ) => (
198+ < Dynamic
199+ component = { analysis ( ) . component }
200+ liveModel = { ( liveAnalysis as LiveModelAnalysisDocument ) . liveModel }
201+ content = { props . content . content }
202+ changeContent = { ( f : ( c : unknown ) => void ) =>
203+ props . changeContent ( ( content ) => f ( content . content ) )
204+ }
205+ />
206+ ) }
207+ </ Match >
208+ < Match
209+ when = {
210+ liveAnalysis . analysisType === "diagram" &&
211+ liveAnalysis . liveDiagram . liveModel . theory ( ) ?. diagramAnalysis ( props . content . id )
212+ }
213+ >
214+ { ( analysis ) => (
215+ < Dynamic
216+ component = { analysis ( ) . component }
217+ liveDiagram = { ( liveAnalysis as LiveDiagramAnalysisDocument ) . liveDiagram }
218+ content = { props . content . content }
219+ changeContent = { ( f : ( c : unknown ) => void ) =>
220+ props . changeContent ( ( content ) => f ( content . content ) )
221+ }
222+ />
223+ ) }
224+ </ Match >
225+ </ Switch >
226+ ) ;
227+ }
228+
229+ function analysisCellConstructor < T > ( meta : AnalysisMeta < T > ) : CellConstructor < Analysis < T > > {
230+ const { id, name, description, initialContent } = meta ;
231+ return {
232+ name,
233+ description,
234+ construct : ( ) =>
235+ newFormalCell ( {
236+ id,
237+ content : initialContent ( ) ,
238+ } ) ,
239+ } ;
240+ }
0 commit comments