Whirlpool

A data-driven programming language developed for the recreational purpose of writing fun software.

Inspired by the book Writing an Interpreter in Go by Thorsten Ball

How it started:

Me:

Hey, I want to write a Golang interpreter for a language. Define the specs of a brand new language, it must be simple and innovative. Surprise me!

Claude.ai:

Alright! Let’s try something innovative and out of the ordinary. Here's a brand new language concept called "Whirl"—it’s designed to challenge conventional programming paradigms with simplicity and a unique twist on flow and data manipulation.

Sadly Whir already exists and it's far too esoteric for my palate, so Whirlpool was born.

REPL

Want to play with whirlpool? Clone the repo and give a go to the terminal REPL available:

  • $ git clone https://github.com/Hyla96/whirlpool.git
  • $ go run main.go

Original language specs:


Whirl Language Specification


1. Flow-Based Programming

  • Whirl is built around data flow rather than traditional control flow. Programs in Whirl look more like a series of transformations, where data moves through pipes.

  • No traditional loops or if-else blocks, just data transformations and routing.


2. Core Concept: “Spirals” and “Nodes”

  • The building blocks of Whirl are Spirals and Nodes:

    • Spirals: Represent a flow of data, similar to pipelines.
    • Nodes: Represent operations that transform data.
  • Spirals are circular in nature, meaning data can pass through them continuously unless explicitly broken. Each pass modifies the data.


3. Types

  • Whirl uses implicit types and relies on the transformations applied to define the shape of data:

    • Primitive Types: num, txt, bool, list
    • Transformative Types: wave, pulse, current
  • Primitive types are ordinary, but the transformative types are dynamic data types that can change with each pass through the Spiral.


4. Unique Constructs

  • Siphons: Think of these as valves that decide whether data flows through. They are akin to conditional logic, but they operate based on the state of the data:

    siphon num > 10 -> pipe
    
  • Flickers: Temporal states. Data can be stored in flickers, a short-term, volatile memory:

    flicker num = 42
    
  • Cyclones: These are accumulators or reducers, pulling together data over several passes:

    cyclone total -> add
    

5. Programming by Example:

  • Basic Program Flow: In Whirl, code is a series of transformations. For example, to add 1 to a number, filter out the numbers that are even, and print them:

    spiral num -> add 1 -> siphon num % 2 != 0 -> output
    

    In this example, spiral represents the flow of numbers, add 1 adds to each number, the siphon filters odd numbers, and output prints them.

  • Fibonacci Sequence (No loops, just flow):

    flicker prev = 0
    flicker curr = 1
    
    spiral -> flicker next = prev + curr -> cyclone (prev, curr) -> rotate
    

    The Fibonacci sequence is generated by constantly rotating and accumulating two numbers, without a traditional loop.


6. Communication and Channels

  • Data flows continuously through channels. Think of them as conveyors of data across different Spirals. Data can be passed from one part of a program to another:

    channel num -> spiral_a -> spiral_b
    

    Channels link Spirals together, making it possible to separate logic into discrete flows.


7. Error Handling

  • Glitches: Instead of exceptions or error codes, Whirl uses Glitches, which bubble up through Spirals. Glitches must be handled via special filters:

    glitch -> siphon is_glitch -> recover
    

    If an error occurs, it moves through a glitch channel, where it’s either handled or allowed to propagate until recovery.


8. Functions and Modularity

  • Whirl doesn’t have functions in the traditional sense. Instead, you define shapes, which are reusable flow patterns:

    shape double -> spiral num -> multiply 2 -> output
    

    Shapes can be plugged into different Spirals, effectively working like functions.


9. No Variables, Just States

  • Rather than mutable variables, Whirl works with state transitions. Data enters a state within a Spiral, gets transformed, and moves on. Once data leaves a state, it no longer exists.

10. Visual Programming

  • Whirl is designed to be both text-based and visual. The text syntax you write can be directly mapped to a visual representation where Nodes are boxes and Spirals are arrows. This makes debugging and program understanding much easier.

    Example visual for:

    spiral num -> add 1 -> siphon num % 2 != 0 -> output
    
    • A circular node labeled "spiral num"
    • Arrows pointing to transformations: "add 1"
    • A branch node for "siphon num % 2 != 0"
    • An endpoint "output"

Key Innovations

  1. Flow Over Control: Whirl eliminates loops, conditionals, and variables in favor of flow-based design. Everything moves continuously through a Spiral.

  2. Temporal Constructs: Features like flickers and cyclones introduce temporal states and reduction in a very organic way.

  3. No Functions, Only Shapes: Instead of the function/method paradigm, reusable logic is encapsulated in shapes, which plug directly into the flow of data.

  4. Visual Hybrid: Whirl can be visualized directly from the code, making it ideal for dataflow-driven debugging.


Example Programs

  1. Prime Numbers:

    spiral num -> add 1 -> siphon is_prime(num) -> output
    
  2. Word Counting in Text:

    spiral txt -> split " " -> cyclone count -> output count
    
  3. HTTP Request (Async by Nature):

    channel request -> siphon is_ready -> cyclone response -> output
    

With Whirl, programming becomes a continuous flow of data, where operations are nodes in a giant feedback loop of transformations. It’s designed to feel different from conventional languages, emphasizing movement over static logic.

What do you think of this? It should definitely be a new challenge when writing the interpreter!