<?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: Divyansh Garg</title>
    <description>The latest articles on DEV Community by Divyansh Garg (@divyanshgarg3105).</description>
    <link>https://dev.to/divyanshgarg3105</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4176399%2F90bc1cb7-72f0-46a5-aaa1-fdd5d3619529.jpg</url>
      <title>DEV Community: Divyansh Garg</title>
      <link>https://dev.to/divyanshgarg3105</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/divyanshgarg3105"/>
    <language>en</language>
    <item>
      <title>What I got wrong building my own programming language in Python</title>
      <dc:creator>Divyansh Garg</dc:creator>
      <pubDate>Sun, 11 Oct 2026 06:06:11 +0000</pubDate>
      <link>https://dev.to/divyanshgarg3105/what-i-got-wrong-building-my-own-programming-language-in-python-2apk</link>
      <guid>https://dev.to/divyanshgarg3105/what-i-got-wrong-building-my-own-programming-language-in-python-2apk</guid>
      <description>&lt;p&gt;While recording a demo video for GravLang v1.1.0, I pasted the example from my own README into my own interpreter. It didn't run.&lt;/p&gt;

&lt;p&gt;The example used &lt;code&gt;new Student(...)&lt;/code&gt;, &lt;code&gt;super.init(...)&lt;/code&gt; and an arrow lambda, &lt;code&gt;(a, b) =&amp;gt; a + b&lt;/code&gt;. GravLang supports none of those. It also used &lt;code&gt;//&lt;/code&gt; comments (GravLang uses &lt;code&gt;#&lt;/code&gt;), and the README promised six IDE themes when the IDE ships four. I hadn't noticed any of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What GravLang is
&lt;/h2&gt;

&lt;p&gt;GravLang is a dynamically typed language written entirely in Python 3.10+. It has classes with single inheritance, closures, lambdas (&lt;code&gt;func(x) { return x * 2; }&lt;/code&gt;), variadic parameters, f-strings, dictionaries, array slicing, &lt;code&gt;try / catch / finally&lt;/code&gt; and a built-in formatter. The pipeline is the classic one: lexer, parser, AST, interpreter, environment.&lt;/p&gt;

&lt;p&gt;The part I like most is the IDE. Press Stages and it shows each step for the code you just wrote. For &lt;code&gt;let total = 2 + 3;&lt;/code&gt; the lexer produces:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LET  ID(total)  ASSIGN  INT(2)  PLUS  INT(3)  SEMI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The parser builds:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VarDecl(name='total', value=BinOp(Literal(2) + Literal(3)))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and the interpreter logs each step as it runs. There is also a debugger with breakpoints, single-stepping and a live variable inspector, plus linting, autocomplete and four themes: Catppuccin Mocha, GitHub Dark, Solarized Dark and Catppuccin Latte. Watching a program move through those three stages taught me more than writing them did.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bugs v1.1.0 fixed
&lt;/h2&gt;

&lt;p&gt;None of them were parser bugs.&lt;/p&gt;

&lt;p&gt;Files with a byte-order mark wouldn't load. Some Windows editors save UTF-8 files with a BOM, and others leave non-breaking spaces in the source. The lexer rejected both, and now it accepts them.&lt;/p&gt;

&lt;p&gt;The standard library was wrong in boring ways. &lt;code&gt;sqrt&lt;/code&gt;, &lt;code&gt;capitalize&lt;/code&gt; and padding had bugs, and the iterative &lt;code&gt;factorial&lt;/code&gt; and &lt;code&gt;fib&lt;/code&gt; gave wrong answers. Those are the first functions anyone tries.&lt;/p&gt;

&lt;p&gt;The config file lived in the wrong place. I stored IDE settings next to the code. That works from source, but a one-file &lt;code&gt;.exe&lt;/code&gt; unpacks into a temp folder, so the settings are lost, and it fails outright on read-only installs. Settings now live in a per-user file, and the &lt;code&gt;GRAVLANG_CONFIG&lt;/code&gt; environment variable overrides the path.&lt;/p&gt;

&lt;p&gt;Theme switching only half worked. It updated the editor but not hover handlers, ttk styles or scrollbars, so parts of the IDE kept the old colours.&lt;/p&gt;

&lt;p&gt;Formatting also couldn't be undone. The formatter rewrites your code from the AST, which is fine until it changes something you wanted to keep. A format can now be undone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would do differently
&lt;/h2&gt;

&lt;p&gt;If I started over, I would run every README example in CI, test with files saved by other people's editors, and decide where settings live before packaging anything. The code I wrote for the language was the part I tested. The files around it caused most of the bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;GravLang is MIT licensed. Four demos are written in GravLang itself: Snake, a todo app, a Brainfuck interpreter and a grade analyzer.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/Divyansh3105/GravLang.git
cd GravLang
pip install -e .
python main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/Divyansh3105/GravLang" rel="noopener noreferrer"&gt;https://github.com/Divyansh3105/GravLang&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a learning project and a tree-walking interpreter in Python, so speed isn't the goal. If you have built a language or an interpreter, what would you add next?&lt;/p&gt;

</description>
      <category>programming</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>python</category>
    </item>
  </channel>
</rss>
