Atomis Development Blog

Modernizing BASIC: Implementing Method Chaining in jdBasic

Method Chaining in jdBasic

Introduction

Who said BASIC has to be clunky? I’ve been working on the object-oriented features of jdBasic, and I realized something was missing. I wanted the code to flow more naturally, specifically when initializing or manipulating objects.

Today, I successfully implemented Method Chaining (often called a Fluent Interface) into the interpreter.

The Goal

In standard BASIC (and many older languages), performing multiple operations on an object usually looks like this:

DIM calc AS T_CALC
calc.init(10)
calc.add(5)
calc.multiply(2)
calc.print_me()

It works, but it's verbose. I wanted to be able to write it like a sentence:

calc.init(10).add(5).multiply(2).print_me()

The Implementation

Getting this to work required a deep dive into the C++ runtime environment (`NeReLaBasic.cpp`). The challenge wasn't just syntactic sugar; it was about how the interpreter handles state between statements.

There were two main hurdles:

  1. `RETURN THIS`: I had to implement a mechanism for a function to return its own object context. In `Commands.cpp`, I updated the variable lookup to intercept the keyword THIS and inject the current object instance from the stack back into the local scope.
  2. Dot-Chaining Statements: The interpreter naturally sees calc.init() as one statement. When it reached the next dot .add(), it originally saw a syntax error. I had to modify the main statement loop to recognize a leading dot as a continuation of the previous statement's return value (`RETVAL`).

The Result

The result is a syntax that feels strangely modern for a BASIC dialect. It allows for concise, readable code that "flows" down the screen.

' This is now valid jdBasic code!
calc.init(1) _
    .add(2) _
    .mul(3) _
    .print_me()

It feels so wrong, but so right.


Check out the source code on GitHub to see the changes in `NeReLaBasic.cpp` and `Commands.cpp`!