From 3674e9da45917830b86f058744ac74f1da0cf481 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 2 Dec 2025 11:14:00 +0000 Subject: [PATCH 1/2] Compile button. --- _config.yml | 4 ++ playground/editor.ts | 94 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 14 deletions(-) diff --git a/_config.yml b/_config.yml index 341ef22..fb3c23e 100644 --- a/_config.yml +++ b/_config.yml @@ -20,6 +20,10 @@ callouts: error-titled: color: red + success: + title: Success + color: green + exclude: # from https://github.com/jekyll/jekyll/blob/master/lib/site_template/_config.yml: - .sass-cache/ diff --git a/playground/editor.ts b/playground/editor.ts index 7a898fc..0644d56 100644 --- a/playground/editor.ts +++ b/playground/editor.ts @@ -86,9 +86,26 @@ class PlaygroundInstance { return this.getDiagnosticsAndFree(pg); } + compile(program: string): GraphAlgDiagnostic[] { + const ga_new = this.bindings.ga_new; + const ga_parse = this.bindings.ga_parse; + const ga_desugar = this.bindings.ga_desugar; + + const pg = ga_new(); + + if (!ga_parse(pg, program)) { + return this.getDiagnosticsAndFree(pg); + } + + if (!ga_desugar(pg)) { + return this.getDiagnosticsAndFree(pg); + } + + return []; + } + run(program: string, func: string, args: GraphAlgMatrix[]): RunResults { const ga_new = this.bindings.ga_new; - const ga_free = this.bindings.ga_free; const ga_parse = this.bindings.ga_parse; const ga_desugar = this.bindings.ga_desugar; const ga_add_arg = this.bindings.ga_add_arg; @@ -692,6 +709,24 @@ function buildErrorNote(diagnostics: GraphAlgDiagnostic[]): HTMLQuoteElement { return quote; } +function buildCompileSuccessNote(): HTMLQuoteElement { + const quote = document.createElement("blockquote"); + quote.setAttribute('class', 'success-title'); + const messages = [ + "Compiled successfully", + "Parser: OK, syntax is valid", + "Type checker: OK, types are valid", + ]; + + for (let msg of messages) { + const pelem = document.createElement("p"); + pelem.textContent = msg; + quote.appendChild(pelem); + } + + return quote; +} + function run(editor: GraphAlgEditor, inst: PlaygroundInstance) { const program = editor.editorView?.state.doc.toString(); if (!program) { @@ -719,25 +754,56 @@ function run(editor: GraphAlgEditor, inst: PlaygroundInstance) { editor.outputContainer.replaceChildren(details); } +function compile(editor: GraphAlgEditor, inst: PlaygroundInstance) { + const program = editor.editorView?.state.doc.toString(); + if (!program) { + throw new Error("No program to compile"); + } + + const diagnostics = inst.compile(program); + let resultElem; + if (diagnostics.length > 0) { + resultElem = buildErrorNote(diagnostics); + } else { + resultElem = buildCompileSuccessNote(); + } + + // Place output in a default-open accordion + const details = document.createElement("details"); + details.setAttribute('open', 'true'); + const summary = document.createElement("summary"); + summary.textContent = "Output"; + details.append(summary, resultElem); + editor.outputContainer.replaceChildren(details); +} + // Add run buttons playgroundWasmBindings.onLoaded((bindings: any) => { const instance = new PlaygroundInstance(bindings); for (let editor of editors) { - if (!editor.functionName) { - // No function to run - continue; + if (editor.functionName) { + const runButton = document.createElement("button"); + runButton.setAttribute('type', 'button'); + runButton.setAttribute('name', 'run'); + runButton.setAttribute('class', 'btn'); + runButton.textContent = `Run '${editor.functionName}'`; + runButton.addEventListener('click', () => { + run(editor, instance); + }); + editor.toolbar.appendChild(runButton); + } else { + // No function to run, compile only + const compileButton = document.createElement("button"); + compileButton.setAttribute('type', 'button'); + compileButton.setAttribute('name', 'compile'); + compileButton.setAttribute('class', 'btn'); + compileButton.textContent = "Compile"; + compileButton.addEventListener('click', () => { + compile(editor, instance); + }); + editor.toolbar.appendChild(compileButton); } - - const runButton = document.createElement("button"); - runButton.setAttribute('type', 'button'); - runButton.setAttribute('name', 'run'); - runButton.setAttribute('class', 'btn'); - runButton.textContent = `Run '${editor.functionName}'`; - runButton.addEventListener('click', () => { - run(editor, instance); - }); - editor.toolbar.appendChild(runButton); } }); From bfc9b3ffbc8b651fa2d908b905eda24242b86676 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 2 Dec 2025 12:20:22 +0000 Subject: [PATCH 2/2] Also update the other example. --- tutorial/index.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/tutorial/index.md b/tutorial/index.md index 3d57074..d3bafef 100644 --- a/tutorial/index.md +++ b/tutorial/index.md @@ -128,9 +128,6 @@ This is okay because the loop scope is defined *inside* of the function scope. What is not allowed however is to first define a variable in a nested scope, and then refer to it from the outer scope. For an example, consider the (invalid) program below. -{: - data-ga-func="NotValid" -} ```graphalg func NotValid() -> int { a = int(0);