-
Notifications
You must be signed in to change notification settings - Fork 114
FE-514: Compile TypeScript expressions to SymPy #8541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: graphite-base/8541
Are you sure you want to change the base?
Changes from all commits
e6d79a2
ec17fcd
087ff05
980a2ce
8f94821
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,12 @@ | ||
| import type ts from "typescript"; | ||
|
|
||
| import type { SDCPN } from "../../core/types/sdcpn"; | ||
| import { | ||
| buildContextForDifferentialEquation, | ||
| buildContextForTransition, | ||
| compileToSymPy, | ||
| type SymPyResult, | ||
| } from "../../simulation/simulator/compile-to-sympy"; | ||
| import type { SDCPNLanguageServer } from "./create-sdcpn-language-service"; | ||
| import { getItemFilePath } from "./file-paths"; | ||
|
|
||
|
|
@@ -27,6 +33,113 @@ export type SDCPNCheckResult = { | |
| itemDiagnostics: SDCPNDiagnostic[]; | ||
| }; | ||
|
|
||
| /** | ||
| * Creates a synthetic ts.Diagnostic from a SymPy compilation error result. | ||
| * Uses category 0 (Warning) since SymPy compilation failures are informational | ||
| * — the TypeScript code may still be valid, just not convertible to SymPy. | ||
| */ | ||
| function makeSymPyDiagnostic( | ||
| result: SymPyResult & { ok: false }, | ||
| ): ts.Diagnostic { | ||
| return { | ||
| category: 0, // Warning | ||
| code: 99000, // Custom code for SymPy diagnostics | ||
| messageText: `SymPy: ${result.error}`, | ||
| file: undefined, | ||
| start: result.start, | ||
| length: result.length, | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * Appends a SymPy diagnostic to the item diagnostics list, merging with | ||
| * any existing entry for the same item. | ||
| */ | ||
| function appendSymPyDiagnostic( | ||
| itemDiagnostics: SDCPNDiagnostic[], | ||
| itemId: string, | ||
| itemType: ItemType, | ||
| filePath: string, | ||
| result: SymPyResult & { ok: false }, | ||
| ): void { | ||
| const diag = makeSymPyDiagnostic(result); | ||
| const existing = itemDiagnostics.find( | ||
| (di) => di.itemId === itemId && di.itemType === itemType, | ||
| ); | ||
| if (existing) { | ||
| existing.diagnostics.push(diag); | ||
| } else { | ||
| itemDiagnostics.push({ itemId, itemType, filePath, diagnostics: [diag] }); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Runs SymPy compilation on all SDCPN code expressions and appends | ||
| * any errors as warning diagnostics. | ||
| */ | ||
| function checkSymPyCompilation( | ||
| sdcpn: SDCPN, | ||
| itemDiagnostics: SDCPNDiagnostic[], | ||
| ): void { | ||
| // Check differential equations | ||
| for (const de of sdcpn.differentialEquations) { | ||
| const ctx = buildContextForDifferentialEquation(sdcpn, de.colorId); | ||
| const result = compileToSymPy(de.code, ctx); | ||
| if (!result.ok) { | ||
| const filePath = getItemFilePath("differential-equation-code", { | ||
| id: de.id, | ||
| }); | ||
| appendSymPyDiagnostic( | ||
| itemDiagnostics, | ||
| de.id, | ||
| "differential-equation", | ||
| filePath, | ||
| result, | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| // Check transition lambdas and kernels | ||
| for (const transition of sdcpn.transitions) { | ||
| const lambdaCtx = buildContextForTransition(sdcpn, transition, "Lambda"); | ||
| const lambdaResult = compileToSymPy(transition.lambdaCode, lambdaCtx); | ||
| if (!lambdaResult.ok) { | ||
| const filePath = getItemFilePath("transition-lambda-code", { | ||
| transitionId: transition.id, | ||
| }); | ||
| appendSymPyDiagnostic( | ||
| itemDiagnostics, | ||
| transition.id, | ||
| "transition-lambda", | ||
| filePath, | ||
| lambdaResult, | ||
| ); | ||
| } | ||
|
|
||
| const kernelCtx = buildContextForTransition( | ||
| sdcpn, | ||
| transition, | ||
| "TransitionKernel", | ||
| ); | ||
| const kernelResult = compileToSymPy( | ||
| transition.transitionKernelCode, | ||
| kernelCtx, | ||
| ); | ||
| if (!kernelResult.ok) { | ||
| const filePath = getItemFilePath("transition-kernel-code", { | ||
| transitionId: transition.id, | ||
| }); | ||
| appendSymPyDiagnostic( | ||
| itemDiagnostics, | ||
| transition.id, | ||
| "transition-kernel", | ||
| filePath, | ||
| kernelResult, | ||
| ); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Checks the validity of an SDCPN by running TypeScript validation | ||
| * on all user-provided code (transitions and differential equations). | ||
|
|
@@ -111,6 +224,9 @@ export function checkSDCPN( | |
| } | ||
| } | ||
|
|
||
| // Run SymPy compilation checks on all code expressions | ||
| checkSymPyCompilation(sdcpn, itemDiagnostics); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SymPy warnings incorrectly invalidate the SDCPN check resultHigh Severity
Additional Locations (1) |
||
| return { | ||
| isValid: itemDiagnostics.length === 0, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Severity: high 🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage. |
||
| itemDiagnostics, | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
checkSymPyCompilation()compilestransitionKernelCodefor every transition, but the TS checker explicitly skips kernel validation when there are no coloured output places; this will likely produce noisy SymPy warnings (and changeisValid) for kernels that are effectively unused.Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.