Skip to content
BFJ HelpBlock-based Featherweight Java
02 / Getting started

Your first Featherweight Java program

FJ's smallest program is barely a program at all — one class, one field, one expression. Building it is still the fastest way to see the parts that make BFJ worth using: a constructor that appears without being asked for, and two semantics views that fill in the moment you press Run.

A workspace with nothing assumed

A fresh BFJ workspace is empty, and that emptiness is deliberate. FJ has no main, no static entry point, no Goal wrapper the way B-MJ does — a program is simply a set of class declarations plus one loose top-level expression sitting beside them on the canvas, and that loose expression is the thing that actually gets reduced. Nothing stops you from dropping several candidate expressions down at once; only the one you Run, or Load into a stepper, is evaluated.

Your first class

Build the shipped Field access example by hand once, so the pieces are familiar later:

  1. From Class, drag an fj_class block onto the workspace. Name it A and leave it extends Object.
  2. From Members, drag an fj_field block into the class's field socket and give it a type and a name — Object f is enough.
  3. Look at what is already sitting under the field. That is covered next.
  4. Drop an fj_new block from Expressions beside the class, set it to A, then chain an fj_field_access onto it for .f. This loose expression, new A().f, is your program.

That is also exactly the shipped Field access example, so if a step feels fiddly the first time, load the example from the Examples menu instead and read the blocks it produced.

The constructor writes itself

Notice there was no step above for building a constructor. fj_ctor is already attached under the field list, and it has no sockets to fill in — it is labelled constructor (auto) and stays that way.

Why the constructor is fixed

FJ's own typing rules say the constructor for a class is fully determined by fields(C) — the class's fields plus its superclass's fields, in order. BFJ enforces that literally: fj_ctor is synthesized, not built, so there is no way to construct two different block trees that mean the same class. That is what keeps the block↔AST bijection proved in chapter 06 from breaking on day one. See Blocks for the full argument.

The Editable Code panel

Open the FJ Inspector's Editable Code tab. It already shows genuine, javac-shaped Java source for the class and expression you just built, including the synthesized constructor's super(...) call. Add a second field and watch the constructor's parameter list and body grow in the text before you have touched anything else — the panel is synchronised live in both directions, the same parser and printer covered in Translation.

Running it

▶ Run in the workspace title bar reduces the expression to a value and puts it on the Inspector's Output tab. For new A().f that value is null-free by construction — FJ has no null, so a field that was never assigned anything but a value obtained the same way still prints as a fully-applied constructor call.

Open the bottom dock with Ctrl + J and press Load on the Reduction tab: it precomputes the whole substitution trace for your expression, one numbered line per step, each tagged with the rule that fired. Do the same on CK Machine and you get the same reduction again, this time as an explicit Control/Kontinuation pair you can Step and Back through one transition at a time. Both are the subject of chapter 05.

Press Ctrl + Shift + F, or use the search field at the top of the sidebar, to filter block labels and category names live — useful once you are past the thirteen blocks in the toolbox and just want fj_invk without scrolling past Types and Arguments to find it.

BFJ is developed at L-Workshop. This help was written against the build running at bfj.l-workshop.my.id.