Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>IPU AssemblyNew to Visual Studio Code? Get it now.
IPU Assembly

IPU Assembly

yarden carmi

|
1 install
| (0) | Free
Syntax highlighting and assembler diagnostics for IPU VLIW assembly, generated from the assembler's own grammar.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

IPU Assembly — VS Code extension

Syntax highlighting for IPU VLIW assembly (.asm, .s, .asm.j2).

Generated, not written

The TextMate grammar in syntaxes/ is generated by ipu_as/gen_vscode.py from two sources, and it is worth being precise about which is which:

  • Structure — comments, ; / ;;, :, the identifier shape — from get_parser().terminals via pattern.to_regexp(). No token text is restated.
  • Vocabulary — which identifiers are instructions or registers — from instruction_spec.py and the register enums.

The vocabulary cannot come from the parser: asm_grammar.lark has a single catch-all TOKEN terminal, so the parser genuinely does not distinguish BKPT from lr0 from my_label. Neither layer is written by hand; both are enumerated.

This matters because the previous, hand-written grammar drifted from the language: it coloured BEQ lr0, cr0, +1;; as valid (commas are a lex error) and failed to recognise end: in BKPT;; end: BKPT;; as a label. Nothing detected either, because nothing compared the grammar to the parser. That is what the agreement test below now does.

Edits reflect automatically on the next build:

Change Effect
A terminal's value in asm_grammar.lark picked up automatically
An instruction added to instruction_spec.py picked up automatically
A new terminal named COMMENT_* / STRING_* / PUNCT_* / WS_* scoped by convention
A new terminal with an unrecognised name build fails, naming the terminal

The last row is the one manual step, and it is deliberate: nothing can guess what colour a brand-new lexical concept should be, so the build stops at the moment of the change rather than quietly leaving it unhighlighted.

Regenerate

bazel run //vscode-ipu-asm:gen_vscode

syntaxes/ipu-asm.tmLanguage.json and language-configuration.json are build outputs and are not committed.

The agreement test

test/agreement.js tokenizes a corpus twice — once with the Lark parser, once with the exact engine VS Code ships (vscode-textmate + vscode-oniguruma) — and fails on any disagreement about a token's boundaries or role. It runs in .github/workflows/vscode-extension.yml.

test/corpus/edge_cases.asm covers constructs the six app kernels happen not to use (mid-line labels, labels spelled like mnemonics, every numeric base). It must keep assembling; a change that breaks it is a real grammar regression.

Install

Every push to master republishes the vscode-latest prerelease:

curl -LO https://github.com/rechefe/ipu-emulator/releases/download/vscode-latest/ipu-asm.vsix
code --install-extension ipu-asm.vsix

Diagnostics

The grammar colours tokens; it cannot say a program is wrong. A TextMate rule assigns scopes to spans and has no notion of what the grammar expects next, and validity is not a lexical property — whether a comma is legal depends on the parser's state, not on the characters. BEQ lr0, cr0, +1;; would be coloured perfectly normally.

So extension.js runs the real assembler and turns its errors into squiggles, covering all three stages:

Example Reported at
template {% for x in %} the template line
parse BEQ lr0, cr0, +1;; the comma
encode BGT lr0 lr1;;, mac.ee r0;; the mnemonic

It shells out to ipu-as check --json rather than speaking LSP, which keeps the extension dependency-free — no vscode-languageclient, no bundled node_modules, and the vsix stays a few kilobytes.

By default it runs the checker through Bazel. To avoid paying Bazel's startup cost on every check, point ipuAsm.checkCommand at a virtualenv instead:

"ipuAsm.checkCommand": [".venv/bin/ipu-as", "check", "--json", "--input"]

The file path is appended to whatever you configure.

When diagnostics are not running

A broken toolchain must not paint the file red — that would be a diagnostic about the environment masquerading as one about the code. But it must not be silent either: "checker unavailable" and "your code is fine" look identical, and silence is the worse failure.

So a status bar item reports which state you are in — $(check) IPU when diagnostics are live, $(warning) IPU: checks off when they are not. Clicking it, or running IPU Assembly: Why are diagnostics not running?, gives the reason.

The most common reason: ipu-as check is added by the same change as this extension, so a workspace on a branch predating it has no check subcommand and diagnostics cannot run there. Highlighting still works — that is self-contained in the vsix.

ipu-as check is a normal CLI too: it exits 1 on problems and prints file:line:col: error: …, so it works in a pre-commit hook or CI.

Positions inside Jinja templates

The parser only ever sees rendered text, so a byte offset in what it parsed has no general relationship to the file on screen — loops repeat lines, conditionals drop them, whitespace control joins them.

Rather than guess afterwards by matching line content, the checker renders the template a second time with each line tagged by its own line number. The tags are # comments, so they are invisible to the parser, and Jinja carries them through whatever it does to the text — so a diagnostic names the source line exactly, including inside a loop body or below a block of {%- set -%} aliases. The tagged render is used only when it is equivalent to the real one.

Where a construct cannot be tagged safely, or an error carries no position at all, the diagnostic says so with (position approximate) rather than implying byte accuracy.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft