flipjump

The single instruction language - Flip a bit, then Jump


Keywords
esolang, oisc, assembly, compiler, esoteric-programming-language, macro-assembler, programming-language, simple, standard-library
License
BSD-2-Clause
Install
pip install flipjump==1.2.0

Documentation

FlipJump

Tests PyPI - Version Code style: black Checked with mypy
Website GitHub Discussions GitHub code size in bytes GitHub

FlipJump is the simplest programing language.
Yet, it can do any modern computation.

It's an Esoteric language (FlipJump esolangs page), with just 1 operation a;b:

  • not *a; jump b

Which means - Flip a bit, then Jump.

The operation takes 2 memory addresses - it flips (inverts) the bit the first address points to, and jumps to (continue execution from) the second address. The next opcode is the two memory-addresses found right where you jumped to. You flip and jump again, and so on...

This project includes a Macro Assembler, an Interpreter, and a Thoroughly Tested Standard Library for the FlipJump language.
Additionally, it provides a Python Library that makes it easy to work with those components.

This prime numbers program was coded only with FlipJump (source): Printing prime numbers using only FlipJump

Hello, World!

A simple hello-world flipjump program, not using the standard library: (jump to the source code)
// define macros that will be used later

// this macro exports the "IO" label to be a global label
def startup @ code_start > IO  {
    ;code_start
  IO:
    ;0              // the second op is reserved for Input/Output.
  code_start:
}

// this macro gets one parameter "bit", and uses the global label "IO".
def output_bit bit < IO {
    IO + bit;       // flipping IO+0 outputs 0; flipping IO+1 outputs 1.
}
def output_char ascii {
    // the next line will be unwinded into 8 output_bit macro-uses, each with a different parameter
    rep(8, i) output_bit ((ascii>>i)&1)
}

def end_loop @ loop_label {
    loop_label:
    ;loop_label     // a flipjump program finishes on a self loop
}


// The first lines of actual code:

    startup
    
    output_char 'H'
    output_char 'e'
    output_char 'l'
    output_char 'l'
    output_char 'o'
    output_char ','
    output_char ' '
    
    output_char 'W'
    output_char 'o'
    output_char 'r'
    output_char 'l'
    output_char 'd'
    output_char '!'
    
    end_loop

The source code can be found here: hello_no-stl.fj.

The FlipJump assembly supports a "Hello, World!" syntax for initializing a variable with a string value. Look at the hello_world.fj program for more info.

Note that all of these macros are already implemented in the standard library (all in runlib.fj):

  • startup
  • end_loop (loop)
  • output_char
  • output (for printing string consts, e.g. output "Hello, World!")

How to install?

pip install flipjump

You can also install it with its extras:

  • flipjump[stats]: support for viewing macro usage in an interactive graph.
  • flipjump[tests]: all the testing libraries needed.
pip install flipjump[stats,tests]

Pycharm Extensions:

How to run?

Use the fj utility:

fj hello_world.fj

Hello World in FlipJump

  • The --no-stl flag tells the assembler not to include the standard library. for example: fj programs/print_tests/hello_no-stl.fj --no-stl.
  • the -w [WIDTH] flag allows compiling the .fj files to a WIDTH-bits memory width. WIDTH is 64 by default.
  • You can use the -o flag to save the assembled file for later use too.
  • you can find all the different flags with fj -h.

You can also Test the project with the project's tests, and with your own tests.

You can also assemble and run separately:

fj --asm hello.fj -o hello_world.fjm
fj --run hello_world.fjm
  • The first line will assemble your code.
  • The second line will run your code.

You can also use the faster cpp-based interpreter:

>>> fji hello.fjm -s
Hello, World!

How to Debug?

Programs won't work on their first run. They just can't. That's why we support the next debugging flags.

  • No debugging flags at all: Shows the last 10 executed addresses of tests that failed their run (i.e. finished not by looping).
  • -d [PATH]: Save debug information: Adds very extensive label names, Which are like a "macro-stack" for each of the last executed address. (can be used with --debug-ops-list LEN)
  • --debug-ops-list LEN: Shows the last LEN executed addresses (instead of 10). (can be used with -d)
  • -b NAME [NAME ...]: Places breakpoints at every specified label NAMEs (note that label names are long: more information about labels). (requires -b)
  • -B NAME [NAME ...]: Places breakpoints at every label that contains one of the given NAMEs. (requires -b)

The debugger can single-step, read-memory, read flipjump variables (bit/hex/byte, and their vectors), continue, or skip forward a fixed number of opcodes.

Get Started with FlipJump

  • Install flipjump: pip install flipjump
  • Write your flipjump program (use the stl - standard library macros).
  • assemble+run your program: fj print_dec.fj

Example usage of the flipjump python library

from pathlib import Path
from flipjump import assemble_and_run  # assemble, run_test_output, ...

fj_file_paths = [Path('path/to/main.fj'), Path('path/to/consts.fj')]
termination_statistics = assemble_and_run(fj_file_paths)

You can also use the flipjump.assemble_run_according_to_cmd_line_args(cmd_line_args=[...]).

Project Structure

flipjump (assembler + interpreter source files):

flipjump/stl (standard library files - macros. The stl readme contains the list of all macros):

  • runlib.fj - Constants and initialization macros. Output constant strings.
  • bit/ - Directory of stl files. Macros for io/manipulating binary variables and vectors (i.e. numbers): math, logic, conditional jumps, pointers, casting, IO, ...
  • hex/ - Directory of stl files. Macros for io/manipulating hexadecimal variables and vectors (i.e. numbers): math, logic, conditional jumps, pointers, casting, IO, ...
  • mathlib.fj - Advanced math macros (mul/div).
  • casting.fj - Macros for casting between bit/hex.
  • ptrlib.fj - Macros for working with pointers, stacks, and functions.
  • conf.json - The list of the standard library files.

programs (flipjump programs, used by the tests), for example:

  • hello_world.fj - Prints "hello world :)"
  • calc.fj - A command-line calculator for 2 hex/dec numbers: a [+-*/%] b.
  • func_tests/ - Programs for testing function calls and stack operations.
  • hexlib_tests/ - Tests for all the hex macros, except the hex.pointers.
  • quine16.fj - A 16-bits quine by lestrozi; when assembled with -w16 -v0 - prints itself.
  • pair_ns.fj - Simulates the concept of a Class, by using a namespace.
  • print_dec.fj - Prints binary variables as decimals.
  • multi_comp/ - Simulates a big project (compilation of multiple files).

tests (tests compiling+running the programs with the stl), for example:

  • compiled/ - The designated directory for the assembled tests files.
  • inout/ - Contains the .in and .out files for each test.
  • conftest.py - The pytest configuration file. The tests are being generated here.
  • test_fj.py - The base test functions for compilation and running (how to run).
  • conf.json - The tests groups+order lists.
  • tests_tables/

Read More - Extra Documentation

Take a look at the other READMEs:

A very extensive explanation can be found on the GitHub wiki page.

More detailed explanation and the specifications of the FlipJump assembly can be found on the FlipJump esolangs page.

If you are new to FlipJump and you want to learn how modern computation can be executed using FlipJump, and you want to jump onto your first flipjump code - Start by reading the bit.xor and bit.if macros. That's where the FlipJump magic begins.
If you want to understand how the deep optimized hex macros work, understand how the next macros are implemented: hex.exact_xor, hex.output, hex.inc1, and hex.add (understand the concept of the lookup tables.

You can also write and run programs for yourself! It is just that easy :)

Turing Complete?

As the language expects a finite memory, like most of today's programming languages, it's technically not Turing complete. Yet, It's very capable.

I wrote a Brainfuck to Flipjump Compiler (bf2fj) to emphasize just that. Brainfuck is indeed Turing complete, and the compiler proves that flipjump can run any program that brainfuck runs (besides those that require an unbounded memory).

Contribute

If you want to contribute to this project, read the CONTRIBUTING.md file, and take a look at the I-Want-To-Contribute Thread.

Actually, just writing your own flipjump programs and sharing them with the world is a great contribution to the community :)
Take a look at what the standard library offers, and see some example programs to get you inspired!