diff --git a/javascripts/discourse/api-initializers/theme-initializer.gjs b/javascripts/discourse/api-initializers/theme-initializer.gjs index 45f6474..078f1e6 100644 --- a/javascripts/discourse/api-initializers/theme-initializer.gjs +++ b/javascripts/discourse/api-initializers/theme-initializer.gjs @@ -627,6 +627,106 @@ function julia(hljs) { return DEFAULT; } +/* +Language: Julia IR +Description: Julia Static Single Assignment (SSA) form Intermediate Representation +Author: Matt Bauman +Website: https://docs.julialang.org/en/v1/devdocs/ssair/ +Category: scientific +Extends: julia.js +*/ + +function juliaIR(hljs) { + // Get the base Julia language definition + const jl = hljs.getLanguage("julia"); + + if (!jl) { + throw new Error( + "Julia language definition not found. Julia IR extends Julia." + ); + } + + // Clone the Julia definition to avoid modifying the original + const jlir = { + ...jl, + name: "julia-ir", + }; + + // Add IR-specific keywords to existing Julia keywords + const IR_KEYWORDS = [ + "goto", + "not", + "invoke", + "call", + "enter", + "leave", + "unreachable", + "φᶜ", + "φ", + "π", + "ϒ", + ]; + + // Extend keywords + if (jlir.keywords) { + jlir.keywords = { + ...jlir.keywords, + keyword: [...(juliaIR.keywords.keyword || []), ...IR_KEYWORDS], + }; + } + + // IR-specific patterns that need to be added to the contains array + const IR_PATTERNS = [ + // SSA values (%1, %2, etc.) - highest priority + { + scope: "variable", + match: /%\d+/, + relevance: 10, + }, + + // Basic block labels (1 ─, 2 ┄, etc.) and box drawing + { + scope: "section", + match: /^\s*\d*[ ─│╻╷└┃┌┄]+/, + relevance: 8, + }, + + // Control flow labels (#1, #2, etc.) + { + scope: "symbol", + match: /#\d+/, + relevance: 5, + }, + + // Warned type annotations + { + scope: "type.unstable", + match: /::(Any|Box)\b/, + relevance: 8, + }, + + // CodeInfo wrapper + { + scope: "meta", + begin: /\bCodeInfo\s*\(/, + end: /$/, + contains: ["self"], + relevance: 10, + }, + ]; + + // Prepend IR patterns to the contains array (higher priority than base Julia patterns) + if (jlir.contains) { + jlir.contains = [...IR_PATTERNS, ...jlir.contains]; + } else { + jlir.contains = IR_PATTERNS; + } + + jlir.case_insensitive = false; + + return jlir; +} + /* Language: Julia REPL Description: Julia REPL sessions @@ -703,6 +803,30 @@ function juliaRepl(hljs) { ], }, }, + { + className: "meta.prompt", + begin: /^julia>(?=\s+@?code_(typed|lowered|warntype)\b)/, + relevance: 15, + starts: { + end: /^(?=julia>)/, + returnBegin: true, + contains: [ + { + // The Julia command line itself + begin: /\s+@?code_(typed|lowered|warntype)/, + end: /^(?![ ]{6})/, + subLanguage: "julia", + endsWithParent: true, + }, + { + // The IR that follows + begin: /^./, + subLanguage: "julia-ir", + endsWithParent: true, + }, + ], + }, + }, { className: "meta.prompt", begin: /^julia>/, @@ -777,6 +901,7 @@ function juliaRepl(hljs) { export default apiInitializer((api) => { api.registerHighlightJSLanguage("julia", julia); + api.registerHighlightJSLanguage("julia-ir", juliaIR); api.registerHighlightJSLanguage("julia-repl", juliaRepl); // Register meta-language that auto-detects between julia and julia-repl api.registerHighlightJSLanguage("julia-auto", function (hljs) {