<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sokratis Tzifkas</title>
    <description>The latest articles on DEV Community by Sokratis Tzifkas (@stzifkas).</description>
    <link>https://dev.to/stzifkas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3956377%2Fe14e81ed-63ab-4691-b076-c5b9403fc324.png</url>
      <title>DEV Community: Sokratis Tzifkas</title>
      <link>https://dev.to/stzifkas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stzifkas"/>
    <language>en</language>
    <item>
      <title>Pluto-ecss: A transpiler and runtime for PLUTO procedure language</title>
      <dc:creator>Sokratis Tzifkas</dc:creator>
      <pubDate>Sat, 30 May 2026 11:22:34 +0000</pubDate>
      <link>https://dev.to/stzifkas/pluto-ecss-a-transpiler-and-runtime-for-pluto-procedure-language-5c59</link>
      <guid>https://dev.to/stzifkas/pluto-ecss-a-transpiler-and-runtime-for-pluto-procedure-language-5c59</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/stzifkas/pluto-ecss" rel="noopener noreferrer"&gt;pluto-ecss&lt;/a&gt;&lt;/strong&gt; is a transpiler and&lt;br&gt;
runtime for &lt;strong&gt;PLUTO&lt;/strong&gt; — the procedure language standardised by ECSS&lt;br&gt;
(&lt;a href="https://ecss.nl/standard/ecss-e-st-70-32c-test-and-operations-procedure-language/" rel="noopener noreferrer"&gt;ECSS-E-ST-70-32C&lt;/a&gt;)&lt;br&gt;
for spacecraft testing and operations. It's the DSL ground operators write to&lt;br&gt;
bring up a star tracker, run a parallel safety sequence, or react to an on-board&lt;br&gt;
event.&lt;/p&gt;

&lt;p&gt;You hand it a PLUTO procedure and it gives you back &lt;strong&gt;readable, runnable Python&lt;/strong&gt;&lt;br&gt;
— plus a small runtime library, a CLI, a live TUI, and a browser playground.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pluto-ecss run examples/01_original.pluto
&lt;span class="o"&gt;[&lt;/span&gt;ACTIVITY] Switch on Star Tracker2
&lt;span class="o"&gt;[&lt;/span&gt;ACTIVITY] Switch on Reaction Wheel3 of AOC of Satellite
&lt;span class="o"&gt;[&lt;/span&gt;ACTIVITY] Switch on Star Tracker1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It started life in &lt;strong&gt;2019&lt;/strong&gt; as a Google Summer of Code work product: a sample&lt;br&gt;
parser that built a tree from one hard-coded script and "ran" it by walking the&lt;br&gt;
tree. It never grew past that one file, and it sat dormant for nearly seven&lt;br&gt;
years. Finishing it means closing a loop I'd quietly written off — turning a&lt;br&gt;
"sample for a proposal" into something you can actually &lt;code&gt;pip install&lt;/code&gt; and use.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live playground (no install):&lt;/strong&gt; &lt;a href="https://stzifkas.github.io/pluto-ecss/playground/" rel="noopener noreferrer"&gt;https://stzifkas.github.io/pluto-ecss/playground/&lt;/a&gt; — write PLUTO and compile/run it entirely in your browser via Pyodide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs:&lt;/strong&gt; &lt;a href="https://stzifkas.github.io/pluto-ecss/" rel="noopener noreferrer"&gt;https://stzifkas.github.io/pluto-ecss/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/stzifkas/pluto-ecss" rel="noopener noreferrer"&gt;https://github.com/stzifkas/pluto-ecss&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install:&lt;/strong&gt; &lt;code&gt;pip install pluto-ecss&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ctebvx5ov2bcd36lpce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ctebvx5ov2bcd36lpce.png" alt="A friendly parse error" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vh34anh9gzxkc349g9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vh34anh9gzxkc349g9y.png" alt="A compiled output" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The TUI demo (&lt;code&gt;pluto-ecss demo SCRIPT&lt;/code&gt;) lights up a fake satellite as the&lt;br&gt;
procedure executes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;╭──────────────── Procedure: 05_full_bringup.pluto ────────────────╮
│                            EXECUTING                             │
╰──────────────────────────────────────────────────────────────────╯
                     🛰  Satellite (AOC subsystem)
  Component             │        Status
  ─────────────────────┼─────────────────
  Reaction Wheel3       │          ON
  Star Tracker1         │          ON
  Star Tracker2         │          OFF
📡 Activity feed: ▶ Switch on Reaction Wheel3 …   ⚡ Events: declared: boom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before — the 2019 GSoC snapshot&lt;/strong&gt; (still browsable on the&lt;br&gt;
&lt;a href="https://github.com/stzifkas/pluto-ecss/tree/legacy/gsoc-2019" rel="noopener noreferrer"&gt;&lt;code&gt;legacy/gsoc-2019&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
branch): two &lt;code&gt;.py&lt;/code&gt; files, a ~30-line grammar covering five constructs, a&lt;br&gt;
tree-walking interpreter tangled into the parser, zero tests, no CLI, no&lt;br&gt;
packaging — and real bugs (&lt;code&gt;setExecutionSatus&lt;/code&gt; typo, &lt;code&gt;super.__init__&lt;/code&gt; with no&lt;br&gt;
parens, &lt;code&gt;types&lt;/code&gt; never imported). It ran exactly one script and &lt;code&gt;NameError&lt;/code&gt;'d on&lt;br&gt;
anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After — &lt;code&gt;main&lt;/code&gt; today:&lt;/strong&gt; a proper transpiler (PLUTO → parse tree → readable&lt;br&gt;
Python), a standalone runtime, and a real toolchain.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;2019&lt;/th&gt;
&lt;th&gt;2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Grammar&lt;/td&gt;
&lt;td&gt;~30 lines&lt;/td&gt;
&lt;td&gt;168 lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;164 passing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Examples&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Package LOC&lt;/td&gt;
&lt;td&gt;~600&lt;/td&gt;
&lt;td&gt;~3,600&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLI&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;&lt;code&gt;parse / compile / run / demo / fmt / gen&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtimes&lt;/td&gt;
&lt;td&gt;inline tree walker&lt;/td&gt;
&lt;td&gt;threaded + asyncio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output formats&lt;/td&gt;
&lt;td&gt;side effects only&lt;/td&gt;
&lt;td&gt;Python (sync / async / class / no-runtime) + JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docs&lt;/td&gt;
&lt;td&gt;one README&lt;/td&gt;
&lt;td&gt;mkdocs site + Pygments lexer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playground&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;browser-based (Pyodide)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ECSS coverage&lt;/td&gt;
&lt;td&gt;a handful of constructs&lt;/td&gt;
&lt;td&gt;most of Annex A.1 and A.3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What I added/fixed to finish it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rebuilt the grammar with proper keyword-priority handling (the old one used
brittle negative-lookahead patterns that broke on common words).&lt;/li&gt;
&lt;li&gt;Replaced the interpreter with a transpiler that emits self-contained Python.&lt;/li&gt;
&lt;li&gt;Implemented most of the ECSS spec: steps and sub-bodies (A.1.7), object
property requests (A.3.9.8), &lt;code&gt;in the context of …&lt;/code&gt; (A.3.9.10), reporting data
and &lt;code&gt;save context&lt;/code&gt; (A.3.9.5/.25), &lt;code&gt;refer by&lt;/code&gt; (A.3.9.26/.27), record/array
activity arguments (A.3.9.28), and continuation tests with all seven actions
and A.2.5 defaults (A.3.9.33).&lt;/li&gt;
&lt;li&gt;Added the everyday language layer (&lt;code&gt;if/case/while/for/repeat&lt;/code&gt;, &lt;code&gt;wait until&lt;/code&gt;,
expressions), a runtime with concurrency primitives, friendly parse errors
with file:line:column carets, a CLI, an mkdocs docs site, and the playground.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;Copilot is genuinely visible in the history — several release commits are&lt;br&gt;
co-authored by it. Where it helped most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The grammar's keyword-priority resolution.&lt;/strong&gt; Earley grammars for a DSL full
of multi-word identifiers (&lt;code&gt;Star Tracker2&lt;/code&gt;, &lt;code&gt;Reaction Wheel3 of AOC of
Satellite&lt;/code&gt;) are finicky. Copilot helped me reason through lexer priorities and
surfaced an Earley lexer-priority bug that would have cost me hours to chase
down alone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The transpiler's parse-tree walker&lt;/strong&gt; — a lot of repetitive &lt;code&gt;_stmt_*&lt;/code&gt;
emit methods where Copilot's suggestions removed most of the typing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The runtime's threading/concurrency primitives&lt;/strong&gt; (&lt;code&gt;parallel_until_all&lt;/code&gt;,
&lt;code&gt;wait_for_event&lt;/code&gt;, watchdogs) — boilerplate it could draft and I could refine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architectural calls were mine — choosing a transpiler over an interpreter,&lt;br&gt;
the &lt;code&gt;src/&lt;/code&gt; layout, the multiple compile targets, the test design. What Copilot&lt;br&gt;
changed most was the &lt;em&gt;psychology&lt;/em&gt; of returning to old code: the 2019 version was&lt;br&gt;
full of bugs and missing imports that, back then, felt like cliff-edges. With&lt;br&gt;
Copilot at hand, fixing those and &lt;em&gt;then&lt;/em&gt; doing the real spec work felt like one&lt;br&gt;
continuous flow instead of three separate undertakings. That's largely why this&lt;br&gt;
finally got finished.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>python</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
