From Baghdad to S-Expressions: Why I Built an AI Language That Humans Were Never Meant to Read
In June 2006, I had just returned from a year-long deployment to Baghdad. I was restarting my life with my wife and kids, trying to…
From Baghdad to S-Expressions: Why I Built an AI Language That Humans Were Never Meant to Read

In June 2006, I had just returned from a year-long deployment to Baghdad. I was restarting my life with my wife and kids, trying to remember what it felt like to think about something other than survival. I needed to get excited about technology again. So I did what any sane person returning from a war zone would do.
I started studying artificial intelligence.
I wrote about it on my blog that month, the very first entry after coming home:
“Today is the day I have started my studies of Artificial Intelligence (AI). AI has always interested me, but I have only studied what I could do with program code, not what it can do for me.”
Within hours of my first search, I stumbled onto two things that would quietly shape the next twenty years of my thinking: Alan Turing and the LISP programming language.
The Parentheses That Changed Everything
The day after that first blog post, I wrote another one. I was learning LISP, the second oldest programming language still in active use, created by John McCarthy, the father of artificial intelligence himself. Everything in LISP is written as a list. Open parenthesis. Operator. Operands. Close parenthesis.
(+ 1 2 3 4)
That’s it. That’s the whole syntax. I was a Java developer at IBM. I was used to class hierarchies, interfaces, design patterns, and semicolons everywhere. LISP felt alien. It also felt inevitable, like I was looking at something fundamental that the industry had paved over with decades of syntactic sugar.
I emailed a fellow architect about it:
“I have been trying to learn Lisp (yeah… I said Lisp). Since I started down this path, I am learning more about programming languages than I have ever before.”
I learned about s-expressions, the tree-structured symbolic notation that LISP is built on. I learned about the REPL, about SLIME, about Emacs. I was a MIS major who had spent his career in enterprise middleware, and here I was, back to first principles, studying a language from 1958 because an AI textbook told me to.
Then life happened. Career at IBM. Two more combat deployments to Afghanistan. Air Combat Command Federal Laboratory (U-2 Fed Lab). Pandemic. FinTech. CTO work. Twenty years of building things in web, Java, Python, and the enterprise stack. LISP went to the back of my mind. But it never left.
The COBOL Moment
Fast forward to a few weeks ago. I wrote an article about building a space debris tracking game in COBOL after Anthropic announced that Claude Code could modernize legacy COBOL codebases and IBM’s stock fell 13% in a day. That article was about nostalgia, about revisiting a language I was forced to learn in college and discovering it still had something to teach me about data structures and clarity.
But writing that piece kicked something loose. I kept thinking about a question that wouldn’t leave me alone.
The Question
Here it is:
If AI is writing the code, why does the code need to be readable by humans?
Think about what happens when you ask an AI to generate a program today. You write a prompt in English. The AI generates Python, or Java, or C. You read the code. You run it. Maybe you debug it.
But why is the middle step, generating human-readable source code, still in the pipeline?
When a C compiler generates machine code, nobody reads the assembly output. We don’t expect to. We trust the compiler to faithfully translate our intent into instructions the CPU can execute. The abstraction between C and machine code exists because humans can’t efficiently think in binary and hex.
Now look at the AI code generation pipeline:
Human prompt (English) → AI generates Python → Python interpreter → result
Who is that Python for? Not the machine. It gets interpreted down to bytecode anyway. Not the AI. It generated the code; it doesn’t need to read it back in a human-friendly format. It’s for the human developer, who wants to inspect, understand, and modify the code.
But what happens when the AI gets good enough that you don’t need to inspect it? What happens when you trust the output the way you trust a compiler’s output?
Then the human-readable layer becomes what it actually is: unnecessary overhead.
The Thesis
This is the core idea behind ARIA, AI Representation for Instruction Architecture.
Instead of having AI models generate code in languages designed for human consumption, what if we gave them a representation optimized for their strengths? A language where:
- The syntax is unambiguous. No operator precedence rules, no dangling else problems, no implicit type coercion. S-expressions. Trees all the way down.
- Every operation states its types explicitly.
add.i32,mul.f64. No guessing, no implicit promotion, no undefined behavior hiding behind a valid-looking expression. - Functions carry intent annotations, first-class semantic nodes that say what the function is supposed to do, not just how it does it. Not comments that can lie, but verifiable contracts.
- Effects are declared. A function says whether it’s pure, reads memory, performs I/O, or might loop forever. The compiler enforces this. No surprises.
- The output compiles to any target. The same ARIA file produces a native x86 binary, an ARM executable, a WebAssembly module, or code running in a Docker container. The AI generates once. The compiler handles the rest.
The pipeline becomes:
Human prompt (English) → AI generates ARIA-IR → ariac compiler → native binary
The human writes English. The machine runs native code. The middle layer is optimized for the only two entities that touch it: the AI that writes it and the compiler that reads it.
Building It
I built ARIA as a working prototype. Not a whiteboard exercise, but a compiler you can run. The system has four layers:
Layer 1 takes your natural language prompt and generates ARIA-IR. You type “compute the first 20 prime numbers” and the AI composes a complete, type-checked ARIA program.
Layer 2 is the toolchain, a lexer, parser, and type checker that validates the generated IR. If the AI hallucinates an instruction that doesn’t exist or gets a type wrong, this layer catches it before anything compiles.
Layer 3 is the backend. Currently ARIA-C, which transpiles ARIA-IR to portable C99. That C is then compiled by gcc or clang to native code for whatever architecture you’re targeting.
Layer 4 is verification. It reads the intent annotations and checks whether the generated code actually does what it says it does. This is only possible because the IR is structured, explicit, and semantically annotated. Try doing that with generated Python. You’d be parsing variable names and hoping for the best.
Here’s what a function looks like in ARIA-IR:
(func $fibonacci
(param $n i32) (result i32)
(effects pure)
(intent "Compute the nth Fibonacci number recursively")
(if (le.i32 $n 1)
(then (return $n))
(else
(let %a i32 (call $fibonacci (sub.i32 $n 1)))
(let %b i32 (call $fibonacci (sub.i32 $n 2)))
(return (add.i32 %a %b)))))
No human would choose to write this. And that’s exactly the point. It’s explicit, unambiguous, type-safe, carries its own intent documentation, and compiles cleanly to C. It’s the honest representation for what it is: an intermediate form between intelligence and execution.
The Circle Closes: Clojure
Now here’s where the story comes back to that blog post from Baghdad.
ARIA-IR is s-expressions. Open parenthesis. Operator. Operands. Close parenthesis. The same notation I discovered in 2006 when I was trying to relearn how to be excited about technology after a year in a war zone.
When I looked at the ARIA toolchain, a lexer, parser, type checker, and code generator, all built in Python to process s-expression source files, a thought hit me that felt less like an engineering insight and more like something clicking into place after twenty years.
Why am I using Python to parse s-expressions when there’s a language built on s-expressions?
Clojure is the most modern dialect of LISP. It runs on the JVM, which means anywhere Java runs, and Java runs everywhere. It has immutable persistent data structures, which mirror ARIA’s SSA (Static Single Assignment) semantics. It has clojure.edn/read, which can parse s-expressions natively, meaning the hand-written lexer and parser that took 400+ lines of Python practically disappear.
And here’s the part that matters for the thesis: the toolchain and the representation share the same structural DNA. ARIA-IR is s-expressions. Clojure is s-expressions. The compiler for an AI language is written in the same notation as the language itself. There’s an elegance there that goes beyond convenience. It’s a statement about the nature of the representation.
The JVM gives ARIA something else: a path to real portability. Compile ARIA-IR through a Clojure-based toolchain running on the JVM, and you can target any platform Java supports. That’s not theoretical. That’s every server, every cloud instance, every enterprise environment that’s been running Java for the last thirty years.
I built the Clojure port as a separate project. Same ARIA spec. Same example programs. Same compiled output. But the implementation feels like it belongs, like the language and the tool were always meant to meet.
Why Not Just Generate C?
The obvious objection is, if the AI is good enough, why not just have it generate C directly and skip the intermediate layer?
For simple programs, that works fine. But it breaks down at scale for reasons that matter:
C is a minefield for AI. Implicit integer promotion. Undefined behavior from signed overflow. Pointer aliasing violations. Missing break in switch statements. All of these are syntactically valid C that compiles without warnings and produces wrong results. AI generating C has to navigate the full surface area of C's undefined behavior. AI generating ARIA-IR operates in a space where entire categories of these bugs are structurally impossible.
Verification requires structure. When an AI generates C, checking correctness means reading C, parsing human-centric syntax, inferring intent from variable names and comments, hoping the formatting reflects the logic. ARIA’s intent annotations and explicit effect system make verification a tractable, automatable operation.
Portability means generating once. If AI generates C, you get C. If you want WebAssembly, generate again. If you want JVM bytecode, start over. ARIA generates once; the backend handles the target.
The AI reads it back. When an AI needs to modify code it previously generated, it has to comprehend that code. Reading ARIA-IR is trivial. It’s a tree with explicit types and intent labels. Reading C means navigating preprocessor macros, typedef chains, platform-specific #ifdef blocks, and thirty years of accumulated idiom.
C is a great compilation target for ARIA. It’s a poor generation target for AI.
What I’m Actually Arguing
I’m not arguing that human-readable code is obsolete. Humans will always need to architect, design, specify, and verify software systems. We will still think in abstractions, define interfaces, reason about tradeoffs.
What I am arguing is that the act of writing the code, translating a design into syntax that a compiler can process, is increasingly a task better suited for AI. And if the AI is doing the writing, the language it writes in should be optimized for the AI-to-compiler pipeline, not the human-to-compiler pipeline that we’ve been building for since FORTRAN.
We don’t ask compilers to generate human-readable assembly. We shouldn’t ask AI to generate human-readable source code. We should let the AI compose in whatever representation makes it most correct, most verifiable, and most portable. And then we should trust the compiler, just like we always have.
The AI composes. The machine performs. The human experiences the result.
That’s ARIA.
I’m the CTO and Co-Founder of xOrbita, where we’re building AI-powered space domain awareness from detection to decision. ARIA is a thesis project exploring the architecture of AI-first software development. The Python prototype and Clojure implementation are both on GitHub.
The LISP journey that started in a post-deployment blog in 2006 took twenty years to produce something. But the parentheses were always there, waiting. The original blog posts from that deployment are still online at johnavera.blogspot.com.
AI #Programming #LISP #Clojure #CompilerDesign #ArtificialIntelligence #SoftwareArchitecture #ARIA #CodeGeneration
메타데이터
- post_id
- 6c0c992cb48b
- slug
- from-baghdad-to-s-expressions-why-i-built-an-ai-language-that-humans-were-never-meant-to-read-6c0c992cb48b
- url
- https://medium.com/@jhavera/from-baghdad-to-s-expressions-why-i-built-an-ai-language-that-humans-were-never-meant-to-read-6c0c992cb48b
- canonical_url
- https://medium.com/@jhavera/from-baghdad-to-s-expressions-why-i-built-an-ai-language-that-humans-were-never-meant-to-read-6c0c992cb48b
- author_url
- https://medium.com/@jhavera
- status
- ok
- fetched_at
- 2026-06-14 11:28:49