FAWK: LLMs can write a language interpreter

After reading the book The AWK Programming Language
(recommended!)I was planning to try AWK on this year’s Advent Code. Having some time off from work this week, I tried to implement one of these problems to get some practice, set up my tooling, see how hard AWK would be, and… I found out I’m FP-piled.

I knew I’m used to the combination of algebraic data types (tagged unions) and exhaustive pattern matching, but what I found this time was the basic human rights of immutability, literal scope, and allowing arrays to be returned from functions.

Part 1 of arriving at the code problem was easy enough, but for part 2 (basically shortest path finding with a twist, so not to spoil too much), I found myself unable to switch from my usual functional BFS approach to some variable, and ended up trying to implement my functional approach in AWK.

It made hair grow very fast: I needed to apply it:

  • Hashing (by piping) strings and 2D arrays. md5sum,
  • A global ~set~ array of observed states
  • A way to serialize and deserialize a 2D array to/from a string
  • And some associative array to retrieve this sorted array by its hash.

By the time I had it all I had lost a lot; I spent hours trying to figure out what felt like emergent complicationThings I would consider in more modern languages.

Now, I know no one said AWK is modern, or functional, or that it promises any features for anything other than one-liners and basic scripts that fit under a handful of lines. I don’t want to say that I expected AWK to do anything like this; I knew going in I was pulling equipment. But I couldn’t escape the feeling that there is a beautiful AWK-like language within reach, an iteration on the AWK design (the pattern-action way of thinking is beautiful) that also gives us some of the things that programming language designers have learned in the 48 years since AWK’s birth.

Dreaming of functional AWK

Pausing my efforts to solve the AoC puzzle in pure AWK, I wondered: What am I missing here?

What if AWK had it? First class arrays?

BEGIN {
  # array literals
  normal   = [1, 2, 3]
  nested   = [[1,2], [3,4]]
  assoc    = ["foo" => "bar", "baz" => "quux"]
  multidim = [(1,"abc") => 999]

  five = range(1,5)
  analyze(five)
  print five  # --> still [1, 2, 3, 4, 5]! was passed by value
}

function range(a,b) {
  r = []
  for (i = a; i <= b; i++) {
    r[length(r)] = i
  }
  return r  # arrays can be returned!
}

function analyze(arr) {
  arr[0] = 100
  print arr[0]  # --> 100, only within this function
}

What if AWK had it? First class functions and lambdas?

BEGIN {
  # construct anonymous functions
  double = (x) => { x * 2 }
  add = (a, b) => { c = a + b; return c }

  # functions can be passed as values
  apply = (func, value) => { func(value) }

  print apply(double,add(1,3))  # --> 8
  print apply(inc,5)  # --> 6
}

function inc(a) { return a + 1 }

What if AWK had it? lexical scope Instead of dynamic scope?

# No need for this hack anymore ↓     ↓
#function foo(a, b         ,local1, local2) {
function foo(a, b) {
  local1 = a + b
  local2 = a - b
  return local1 + local2
}

BEGIN {
  c = foo(1,2)
  print(local1)  # --> 0, the local1 from foo() didn't leak!
}

What if AWK had it? clear globaland everything else was local by default?

BEGIN { global count }
END {
  foo()
  print count  # --> 1
  print mylocal # --> 0, didn't leak
}
function foo() { count++; mylocal++ }

(Supposedly this might make the program a little more functional. I’m willing to pay that cost.)

What if AWK had it? line pipe? (Okay, now I’m reaching for the syntax sugar…)

BEGIN {
  result = [1, 2, 3, 4, 5] 
      |> filter((x) => { x % 2 == 0 })
      |> map((x) => { x * x })
      |> reduce((acc, x) => { acc + x }, 0)

  print "Result:", result
}

making it happen

TL;DR: Janiczek/fawk on GitHub

Now for the crazy, LLM-related part of the post. I didn’t want to waste days implementing AWK from scratch or making changes to someone else’s implementation. So I tried using the cursor agent for a larger task than usual (I ask for very small targeted edits), and asked Sonnet 4.5 for a readme with code examples, and then did a full implementation in Python.

And it did so.

Note: I also asked for implementations in C, Haskell, and Rust at the same time, not knowing if any of the four would succeed, and it seems they all produced code that at least compiles/runs. However I have not even attempted to test them or run them. PR is here.

I was very impressed—I still am! I expected LLM to fumble around and ultimately do nothing, but it did what I asked it for (gave me an interpreter that could do the job). those specific examples), and over the course of a few chat sessions, I directed it towards greater implementation of “the rest of AWK” as well as an excessive amount of end-to-end tests.

Take a look at those tests!

The only time I could see it struggling was when I asked it to implement arbitrary precision floating point operations without using an external library.
mpmathIt attempted to use Taylor series, but could not get it right, at least for a few minutes, I thought about it and told it uv add mpmath And simplify the interpreter code. It was done in a moment.

Other things that I thought would be suffocating, like print Both being a statement (with) > And >> redirection support) and an expression, or multi-dimensional arrays, or multi-row records, all of these were implemented correctly. Updating the test suite to check backward compatibility with GAWK is not a problem. Lexical scoping and tricky closure environment behavior – handled it properly.

what now?

As the good kids say, I have to Update my predecessors. The range of what LLM can do has changed since the last time I tried to vibe-code something. I did not expect to find a working interpreter same day I dreamed of a new programming language. This seems possible now.

The downside of vibe coding the entire interpreter is that I have zero knowledge of code. I only interacted with the agent by asking him to implement something and write tests for it, and only I In fact Reviewed tests. I think this will be an issue in the future when I want to manually make some changes to the actual code, as I have no knowledge of it.

This also opened up new questions for me. My other projects where I’ve already run out of momentum, for example. Trying to implement a Hindley-Milner type system for my dream Forever-WIP programming language CARA. It seems like now I can ask LLM to do it, and he will do it? But then again, I don’t want to fall into that trap where I’m no longer able to work on the codebase myself. I want to be familiar with the code and be able to make changes to it. I have to spend my time reviewing and reading code instead of writing everything myself. Maybe it’s okay.

FAWK performance may also be an issue, although that’s a non-goal right now, my intended use case is to have scripts thrown in for code arrivals, not anything user-facing. And who knows, based on what I see, maybe I can direct it
Rewrite it in Rust And have a good chance of success?

For now, I’ll go dogfood on the Advent of Code problem (and as many 2025 puzzles as possible) on my shiny new vibe-coded black box of a programming language, and see what rough edges I can find. I expect they’ll be equal parts “not yet implemented” and “unexpected interaction of new PL features with old ones”.

If you’re willing to jump through some Python project dependency hoops, you can also try using FAWK at your own risk. Janiczek/fawk On GitHub.




2 thoughts on “FAWK: LLMs can write a language interpreter”

  1. For those seeking an exceptional online gaming experience, us.com](https://maxispin.us.com/) stands out as a premier destination. At Maxispin Casino, players can enjoy a vast array of pokies, table games, and other thrilling options, all accessible in both demo and real-money modes. The casino offers attractive bonuses, including free spins and a generous welcome offer, along with cashback promotions and engaging tournaments. To ensure a seamless experience, Maxispin provides various payment methods, efficient withdrawal processes, and reliable customer support through live chat. Security is a top priority, with robust safety measures and a strong focus on responsible gambling tools. Players can easily navigate the site, with detailed guides on account creation, verification, and payment methods. Whether you’re interested in high RTP slots, hold and win pokies, or the latest slot releases, Maxispin Casino delivers a user-friendly and secure platform. Explore their terms and conditions, read reviews, and discover why many consider Maxispin a legitimate and trustworthy choice in Australia.
    The platform provides state-of-the-art tools to create unique and captivating text content.

    **Features of MaxiSpin.us.com**
    One of the standout features of MaxiSpin.us.com is its ability to generate content in multiple languages.

    **Benefits of Using MaxiSpin.us.com**
    By saving time and resources, companies can redirect their focus to other essential aspects of their business.

    Reply

Leave a Comment