<?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: DiverSE</title>
    <description>The latest articles on DEV Community by DiverSE (@diverse_research).</description>
    <link>https://dev.to/diverse_research</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%2F1165301%2F832f6eaf-237b-4573-98a4-1ec461a1ec10.png</url>
      <title>DEV Community: DiverSE</title>
      <link>https://dev.to/diverse_research</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/diverse_research"/>
    <language>en</language>
    <item>
      <title>Testing your DSLs in Langium</title>
      <dc:creator>DiverSE</dc:creator>
      <pubDate>Tue, 07 Nov 2023 14:18:09 +0000</pubDate>
      <link>https://dev.to/diverse_research/testing-your-dsls-in-langium-gp9</link>
      <guid>https://dev.to/diverse_research/testing-your-dsls-in-langium-gp9</guid>
      <description>&lt;p&gt;&lt;a href="https://langium.org/" rel="noopener noreferrer"&gt;Langium&lt;/a&gt; is a framework to build domain-specific languages (DSLs). &lt;br&gt;
The principle is to write a grammar-like specification and obtains for &lt;del&gt;free&lt;/del&gt; zero-effort a parser, an abstract syntax tree (AST), a customizable and advanced editor that can run on the Web or on any modern IDEs such as VSCode, and facilities to interpret or compile programs written in your DSL. Basically, engineering external, textual DSLs at the speed of light! &lt;br&gt;
Langium is the successor of &lt;a href="https://www.eclipse.org/Xtext/" rel="noopener noreferrer"&gt;Xtext&lt;/a&gt; and is under active development. &lt;br&gt;
Langium targets TypeScript, Language Server Protocol (LSP), VSCode, and Web technologies.&lt;br&gt;
One "feature" missing from Xtext is the ability to programmatically test your DSL: test your syntax and conformant/illegal programs, test your interpreter or multiple compilers of your DSL, etc.&lt;br&gt;
In this post, let's outline a possible setup for facilitating the testing of a DSL using Langium.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running example
&lt;/h2&gt;

&lt;p&gt;Let us consider a simple DSL for chess game. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;grammar&lt;/span&gt; &lt;span class="nx"&gt;ChessGame&lt;/span&gt;

&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;White:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;whitePlayer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;STRING&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Black:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;blackPlayer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;STRING &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;moves&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="nx"&gt;Move&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;Move&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AlgebraicMove&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;SpokenMove&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;AlgebraicMove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;piece&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;Piece&lt;/span&gt;&lt;span class="p"&gt;)?&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Square &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;captures&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?&lt;/span&gt; &lt;span class="nx"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;SpokenMove&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;piece&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;Piece&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Square &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;captures&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;captures&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;capturedPiece&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;Piece&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;at&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moves_to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// regular expression ('a'..'h')('1'..'8');&lt;/span&gt;
&lt;span class="nx"&gt;terminal&lt;/span&gt; &lt;span class="nx"&gt;Square&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;a-h&lt;/span&gt;&lt;span class="se"&gt;][&lt;/span&gt;&lt;span class="sr"&gt;1-8&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="nx"&gt;Piece&lt;/span&gt; &lt;span class="nx"&gt;returns&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Piece_PAWN&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Piece_KNIGHT&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Piece_BISHOP&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Piece_ROOK&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Piece_QUEEN&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Piece_KING&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Piece_PAWN&lt;/span&gt; &lt;span class="nx"&gt;returns&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;P&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pawn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Piece_KNIGHT&lt;/span&gt; &lt;span class="nx"&gt;returns&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;N&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;knight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// not K, because of King&lt;/span&gt;
&lt;span class="nx"&gt;Piece_KING&lt;/span&gt; &lt;span class="nx"&gt;returns&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;K&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;king&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Piece_BISHOP&lt;/span&gt; &lt;span class="nx"&gt;returns&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bishop&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Piece_QUEEN&lt;/span&gt; &lt;span class="nx"&gt;returns&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Q&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;queen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Piece_ROOK&lt;/span&gt; &lt;span class="nx"&gt;returns&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;R&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rook&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;hidden&lt;/span&gt; &lt;span class="nx"&gt;terminal&lt;/span&gt; &lt;span class="nx"&gt;WS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="nx"&gt;terminal&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;_a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;zA&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;w_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="nx"&gt;terminal&lt;/span&gt; &lt;span class="nx"&gt;STRING&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[^&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/;

hidden terminal ML_COMMENT: /&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;*[&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;s&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;S]*?&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;//;
hidden terminal SL_COMMENT: /&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;/[^&lt;/span&gt;&lt;span class="se"&gt;\n\r&lt;/span&gt;&lt;span class="s2"&gt;]*/;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It is actually based on the old tutorial of Xtext in 2009 (&lt;a href="https://www.slideshare.net/HeikoB/xtext-at-eclipse-democamp-london-in-june-2009" rel="noopener noreferrer"&gt;https://www.slideshare.net/HeikoB/xtext-at-eclipse-democamp-london-in-june-2009&lt;/a&gt;). &lt;br&gt;
The DSL has limited, practical interest (&lt;a href="https://en.wikipedia.org/wiki/Portable_Game_Notation" rel="noopener noreferrer"&gt;PGN&lt;/a&gt; is better!), but why not for having a more human-readable DSL for chess games? &lt;/p&gt;

&lt;p&gt;Out of the grammar, you can enjoy typing a program (a chess game) using the VS Code generated editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F80zjwoz5xd8ibl6jbbk2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F80zjwoz5xd8ibl6jbbk2.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Playing with the editor is fun, but your tries and errors will go away: How to test more systematically and automatically the syntax of your DSL?&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the syntax
&lt;/h2&gt;

&lt;p&gt;We have used &lt;a href="https://www.eclipse.org/Xtext/" rel="noopener noreferrer"&gt;Xtext&lt;/a&gt; for many years, as part of teaching and research, and enjoyed facilities to test DSL (see eg &lt;a href="https://blog.mathieuacher.com/XtextStandaloneParsing/" rel="noopener noreferrer"&gt;https://blog.mathieuacher.com/XtextStandaloneParsing/&lt;/a&gt;).&lt;br&gt;
Xtext was oriented towards Java, Eclipse, and EMF as opposed to Langium that targets TypeScript, VSCode, and Web technologies. &lt;br&gt;
A solution for testing DSLs in Langium is not straightforward, here is a possible approach.&lt;/p&gt;

&lt;p&gt;We first need a helper function that loads any program written in your DSL and returns the AST. &lt;br&gt;
In TypeScript and leveraging the Langium API:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vitest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../language/generated/ast.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AstNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EmptyFileSystem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LangiumDocument&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;langium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parseDocument&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;langium/test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createChessGameServices&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../language/chess-game-module.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createChessGameServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EmptyFileSystem&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;ChessGame&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;assertModelNoErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;modelText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="na"&gt;doc&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LangiumDocument&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AstNode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;parseDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modelText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DocumentBuilder&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parseResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$document&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;diagnostics&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The imports and Langium facilities are not well documented right now. &lt;br&gt;
The &lt;code&gt;parseDocument&lt;/code&gt; function is key to load a program and obtain the AST.&lt;br&gt;
&lt;code&gt;Promise&amp;lt;Game&amp;gt;&lt;/code&gt; is the type of the AST and is specific to our DSL.&lt;br&gt;
Same for &lt;code&gt;const services = createChessGameServices(EmptyFileSystem).ChessGame;&lt;/code&gt;.&lt;br&gt;
You should adapt to your grammar and main entry point (rule) or DSL name.&lt;/p&gt;

&lt;p&gt;You can then call this function in a test, and puts further assertions on the AST, leveraging &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;vitest&lt;/a&gt;.&lt;br&gt;
For instance:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test basic game&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Two moves&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;game&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;assertModelNoErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
        White: "INSA INFO5"
        Black: "ChatGPT"

        e2 e4
        e7 e5
        `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;whitePlayer&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INSA INFO5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moves&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can check some representative programs of your DSL that should be accepted or rejected by the parser.&lt;br&gt;
More examples here: &lt;a href="https://github.com/acherm/dsl-langium/blob/main/Chess/src/test/validation-test.ts" rel="noopener noreferrer"&gt;https://github.com/acherm/dsl-langium/blob/main/Chess/src/test/validation-test.ts&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing interpreters and compilers
&lt;/h2&gt;

&lt;p&gt;In the same spirit, you can test the interpreter or compiler of your DSL.&lt;/p&gt;

&lt;p&gt;For instance:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;convertMovesToPGNWithPython&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;generateMoves&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../generator/pgn_converter.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Immortal game&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;game&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;assertModelNoErrors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
        White: "Adolf Anderssen"
        Black: "Jean Dufresne"

        pawn at e2 moves_to e4 
        pawn at e7 moves_to e5        
        pawn at f2 moves_to f4 
        P at e5 captures pawn at f4 
        bishop at f1 moves_to c4
        queen at d8 moves_to h4
        king at e1 moves_to f1 
        P at b7 moves_to b5
        bishop at c4 captures pawn at b5 
        knight at g8 moves_to f6        
        `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pgn_moves&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateMoves&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moves&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pgn_moves&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1. e4 e5 2. f4 exf4 3. Bc4 Qh4+ 4. Kf1 b5 5. Bxb5 Nf6&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pgn_moves_with_python&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;convertMovesToPGNWithPython&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moves&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pgn_moves&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pgn_moves_with_python&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;})();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are tests of an interpreter based on &lt;a href="https://github.com/jhlywa/chess.js/tree/master" rel="noopener noreferrer"&gt;chess.js&lt;/a&gt; that translates a chess game into &lt;a href="https://en.wikipedia.org/wiki/Portable_Game_Notation" rel="noopener noreferrer"&gt;PGN&lt;/a&gt; format. &lt;br&gt;
There are other tests for the translation into PGN, but this time generating and executing Python code (based on &lt;a href="https://python-chess.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;python-chess&lt;/a&gt;).&lt;br&gt;
More details here: &lt;a href="https://github.com/acherm/dsl-langium/blob/main/Chess/src/generator/pgn_converter.ts" rel="noopener noreferrer"&gt;https://github.com/acherm/dsl-langium/blob/main/Chess/src/generator/pgn_converter.ts&lt;/a&gt; and &lt;a href="https://github.com/acherm/dsl-langium/blob/main/Chess/src/test/pgn-test.ts" rel="noopener noreferrer"&gt;https://github.com/acherm/dsl-langium/blob/main/Chess/src/test/pgn-test.ts&lt;/a&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Other technicalities
&lt;/h3&gt;

&lt;p&gt;To make it work, you have to set up a few things in your project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;adding a &lt;code&gt;vite.config.ts&lt;/code&gt; to set up &lt;code&gt;vite&lt;/code&gt; testing framework (eg see &lt;a href="https://github.com/acherm/dsl-langium/blob/main/Chess/vite.config.ts" rel="noopener noreferrer"&gt;https://github.com/acherm/dsl-langium/blob/main/Chess/vite.config.ts&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;in the &lt;code&gt;package.json&lt;/code&gt; adding a script rule &lt;code&gt;"test": "vitest"&lt;/code&gt; and &lt;code&gt;devDependencies&lt;/code&gt; something like &lt;code&gt;"vitest": "^0.27.3",&lt;/code&gt;, in such a way you can use &lt;code&gt;npm run test&lt;/code&gt; (eg see &lt;a href="https://github.com/acherm/dsl-langium/blob/main/Chess/package.json" rel="noopener noreferrer"&gt;https://github.com/acherm/dsl-langium/blob/main/Chess/package.json&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This post has shown how to test your DSLs in Langium, leveraging the Langium API and the &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;vitest&lt;/a&gt; testing framework.&lt;br&gt;
For sure, other testing frameworks can be used as well.&lt;br&gt;
The solution presented, quite closed to ParseHelper in Xtext, can be systematized to any DSL. &lt;br&gt;
Hopefully, new versions of Langium will generate such testing facilities out of the box. &lt;/p&gt;

&lt;p&gt;Github of the illustrative project: &lt;a href="https://github.com/acherm/dsl-langium/tree/main/Chess" rel="noopener noreferrer"&gt;https://github.com/acherm/dsl-langium/tree/main/Chess&lt;/a&gt;. &lt;br&gt;
See also DSLs in Langium here: &lt;a href="https://github.com/acherm/dsl-langium/" rel="noopener noreferrer"&gt;https://github.com/acherm/dsl-langium/&lt;/a&gt;. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>End-user Programming of Flappy Bird with ChatGPT: A Reality Check</title>
      <dc:creator>DiverSE</dc:creator>
      <pubDate>Tue, 19 Sep 2023 16:08:29 +0000</pubDate>
      <link>https://dev.to/diverse_research/end-user-programming-of-flappy-bird-with-chatgpt-a-reality-check-18lk</link>
      <guid>https://dev.to/diverse_research/end-user-programming-of-flappy-bird-with-chatgpt-a-reality-check-18lk</guid>
      <description>&lt;p&gt;Is it possible to program non-trivial applications and customize code without knowing much about programming? &lt;br&gt;
Impressive &lt;a href="https://youtu.be/qbIk7-JPB2c?t=1865"&gt;showcases&lt;/a&gt; of &lt;a href="https://twitter.com/acherm/status/1636035908137893896"&gt;ChatGPT&lt;/a&gt; suggest a positive answer. &lt;br&gt;
Some people have even claimed that &lt;a href="https://cacm.acm.org/magazines/2023/1/267976-the-end-of-programming/fulltext"&gt;programmers will be replaced or disappear&lt;/a&gt;. &lt;br&gt;
So, can end-users create working and non-trivial applications, like games, just using instructions in natural language with ChatGPT? &lt;/p&gt;

&lt;p&gt;We have considered the game Flappy bird, using Python. &lt;br&gt;
We have employed various methods and strategies to interact with ChatGPT versions 3.5 and 4, using different prompts, and trying to play the role of an "end-user"  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/nmx1pg_DHzw"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ushFlO0r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://img.youtube.com/vi/nmx1pg_DHzw/0.jpg" alt="FlappyBirdsChatGPT" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Method, prompts, code, observations, and results
&lt;/h2&gt;

&lt;p&gt;Specifically, the five (prompting) methods we tried are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;A short prompt&lt;/em&gt;.
The prompt is given as a simple sentence that provides the overall (general) goal of the task.
No specific information nor detailed functionalities are given. At lot have to be inferred by the Large Language Model (LLM) at generation time.
For instance:
  &amp;gt; Write a Flappy Bird game in Python.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Providing a list of characteristics (this time written by a human)&lt;/em&gt;.
The user will come with a list of functions and/or characteristics that describe the game. The list is given all at once to ChatGPT and is used as the prompt. &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;A short description of the main features&lt;/em&gt;.
This can be seen as a mix of previous methods, as the prompt is written in natural written language and not as a list of functionalities or characteristics. Yet, the text gives more information than the prompt proposed in the second method.
For instance:
&amp;gt; Write the code for a Flappy Bird game in python. I have a folder "assets" with "background.png", "pipe.png" and "bird.png". I would like to know my score and keep track of my highcore in a separate file. I would like to have a start screen when I first open the game, where I can see my highscore, and a game over screen where I can see my score, highscore and play again. &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Giving ChatGPT an example of finished code doing what we want (in our case a complete Flappy Bird game written in Python), and asking it to return a prompt&lt;/em&gt;.
The prompt returned was never the same (probably because of the temperature parameter), but was usually in the form of a list of characteristics.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;A list of prompts (without having to look at the code in between the requests)&lt;/em&gt;.
This last method would mimic the behavior of an end-user that carefully thought about what they need. They do not really interact with the LLM and only give the instruction one after another without caring for the provided output.
Only the final output is used and potentially asked to be improved, anything before that is only the user trying to build little by little what would be its codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We obtained different codes and games, with varying qualities (let say). &lt;/p&gt;

&lt;h2&gt;
  
  
  Observation and synthesis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do claims generalize? (Use the prompt and you'll get a game)
&lt;/h3&gt;

&lt;p&gt;No, we did not find a method (or a magic prompt) that &lt;strong&gt;systematically&lt;/strong&gt; works and would generate a feature-rich game.&lt;br&gt;
Though we have been able to generate interesting and playable games without technical intervention, there are also several cases and sessions that lead to a dead-end situation, far from the ideal scenario usually promised. &lt;/p&gt;

&lt;p&gt;First, it happens that we reach a dead "end-state" with a non-working or unusable game (mainly due to inability to fix an issue), see for instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2nd method, 2nd session (it is possible to continue, but just requiring skills to debug code "("Pipes only came 1 by 1 and not by pair. Trying to implement that only led to more problems that ChatGPT couldn't solve.")")&lt;/li&gt;
&lt;li&gt;2nd method, 4th session (10 interactions, Too many problems (no top pipes, always at the same height, wrong collision detection...))&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Second, despite the same original prompt (and the same "method"), we can have very different generated code. &lt;br&gt;
This difference is in terms of: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;issues in the code, requiring more or less fixing and debugging effort&lt;/li&gt;
&lt;li&gt;features supported: ChatGPT takes the liberty to implement (or not) some functionalities, and the resulting game might be very different... It forces again to interact with ChatGPT, specifically with regard to what has been generated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The consequence is that several specific interactions are needed, some leading to the worst situation (no working game), far from the ideal scenario. &lt;/p&gt;

&lt;h3&gt;
  
  
  Is it possible to program without expertise?
&lt;/h3&gt;

&lt;p&gt;Yes, but again, it is not systematic.&lt;/p&gt;

&lt;p&gt;Direct interventions in the code are sometimes needed (to fix issues!). &lt;br&gt;
For example, we had to &lt;code&gt;[...] change the values of the gravity, bird_movemement and pipe_gap to make it easier and more controllable.&lt;/code&gt;&lt;br&gt;
ChatGPT does not seem to find how to fix the code by itself (when we just point out the problems).&lt;br&gt;
Besides, it is more challenging to interact as end-user when the game was from the start in a very bad shape, and basically unplayable or missing critical features. In this case, it is not possible to get a visual observation that would help to formulate a proper feedback. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;style&lt;/em&gt; of ChatGPT is sometimes to decompose the problem and put placeholders in the code... but without the implementation!&lt;br&gt;
From a developer perspective, it is an interesting style that forces to consider a step-by-step implementation. &lt;br&gt;
However, from a end-user perspective, the game is in an incomplete shape. &lt;/p&gt;

&lt;p&gt;There are sometimes ChatGPT explanations related to a "feature" that does not exist, leading to time-consuming effort. &lt;br&gt;
For example, &lt;code&gt;Implement a feature that has no meaning "There was a 'FLAP' event that made the bird jump every 200ms. That's not part of the game!"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Some examples of issues that needed to be fixed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;clock (pygame specifics?) =&amp;gt; bird crashes immediately &lt;/li&gt;
&lt;li&gt;gap placement between the pipes&lt;/li&gt;
&lt;li&gt;collision detection&lt;/li&gt;
&lt;li&gt;breaking of older functionality &lt;/li&gt;
&lt;li&gt;missing a bit of diversity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both fixes are time-consuming. It is possible to help, thanks to end-user, visual observations about the game. &lt;br&gt;
Sometimes, there is the need to orient discussions and interactions towards code. &lt;/p&gt;

&lt;h3&gt;
  
  
  How are games different? What are the features?
&lt;/h3&gt;

&lt;p&gt;In our &lt;a href="https://github.com/diverse-project/enduserprogrammingLLM/"&gt;git repository&lt;/a&gt; we share sessions and code. &lt;br&gt;
Our observation is that you can get well a feature-rich Flappy bird, but also a game with closed pipes that make the progression of the game limited.  &lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://youtu.be/nmx1pg_DHzw"&gt;Youtube video&lt;/a&gt; for an excerpt of games you can get&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and perspectives
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Formulating a prompt and systematically getting a comprehensive and playable game is not yet a reality&lt;/strong&gt;. &lt;br&gt;
ChatGPT can provide impressive results, but not all times. A magic prompt is missing to make ChatGPT reliable. &lt;br&gt;
&lt;em&gt;Many interactions are rather needed to fix issues or expand the features, sometimes in non-technical terms and with instructions out of observations of the current game&lt;/em&gt;. But the control of the code is not that far and seems inevitable. &lt;/p&gt;

&lt;p&gt;Throughout our experiments, we notice several positive aspects of using ChatGPT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inspiration, funny variants &lt;/li&gt;
&lt;li&gt;discovering new features&lt;/li&gt;
&lt;li&gt;good starting point for developers (or end-users) &lt;/li&gt;
&lt;li&gt;sometimes it can work and end-users can create interesting games&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are several interesting directions to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;change the targeted programming language and/or the framework&lt;/em&gt;: instead of Python and pygame, it's possible to use JavaScript and p5 for instance... A hypothesis is that the targeted technological space can help ChatGPT filling the gap between the prompts and the intentions. &lt;/li&gt;
&lt;li&gt;
&lt;em&gt;find a super prompt&lt;/em&gt; or a language (who says a domain-specific language?) that leads to more determinism and control of ChatGPT&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;improve the usability and the integration&lt;/em&gt; of ChatGPT outputs into development environment. The back and forth between the IDE and ChatGPT is time-consuming. Moreover, some (informal) instructions of ChatGPT can be automatically applied onto the code base, limiting the user effort or the technical expertise required. The hope is to have a better feedback-loop! &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are interested, we are sharing 35 sessions, with prompts, code, observations, and results (videos) with ChatGPT-3.5 and ChatGPT-4 in this repository: &lt;a href="https://github.com/diverse-project/enduserprogrammingLLM/"&gt;https://github.com/diverse-project/enduserprogrammingLLM/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we have &lt;a href="https://www.diverse-team.fr/positions/enduser-llm/"&gt;open positions&lt;/a&gt; (for internships, engineers, PhDs, post-docs, etc.) about the use of ChatGPT in software engineering at &lt;a href="https://www.diverse-team.fr/positions"&gt;DiverSE&lt;/a&gt;!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
