This repository contains a toy programming language called "FrankenScript" with Python-like syntax and Python/JavaScript-inspired semantics.
The purpose of FrankenScript is to explore the design space for adding a region-based ownership system inspired by Reggio and a concurrency
model inspired by behaviour-oriented concurrency to dynamic programming languages to unlock parallelism in a way that is free from data-races
(and also deadlocks, if the full behaviour-oriented concurrency model is adopted). FrankenScript is implemented using Trieste.
To this end, FrankenScript programs generate a file called mermaid.md with a Mermaid diagram per line in the source program showing the object and region
graph of the program at that program point.
This is a legend for the diagrams that FrankenScript generates:
This project is C++20 based and uses CMake as the build system. We also recommend installing Ninja to speed up the build process.
sudo apt-get install cmake ninja-build clang-15
Once you have the pre-requisites installed, you can build the project by running the following commands:
mkdir build
cd build
cmake -G Ninja ..
ninjaand run the tests with:
ctestThe project can be run by
./build/frankenscript build foo.frankwhere foo.fs is a FrankenScript program. This generates a file mermaid.md that contains the Mermaid representation of the heap after each step of the program.
You can run in interactive mode by running:
./build/frankenscript build --interactive foo.frankWhich will keep overwritting the mermaid.md file with the new heap state after each step.
FrankenScript has been submitted as an PLDI25 artifact to explain the Lungfish Ownership Model implemented here.
A critical part of Lungfish is the write-barrier shown in Figure 6 of the Paper. FrankenScript implements
these functions in src/rt/objects/region.cc. The important functions are:
add_reference(source, target): This adds a new reference fromsourcetotarget.add_to_region(region, target, source): This addstargetand all reachable nodes toregionif possible.remove_reference(source, old_target): This removes a reference fromsourcetoold_targetmove_reference(old_src, new_src, target): This is thewriteBarrier()function, which adds a new reference fromnew_srctotargetand removes the reference fromold_srctotarget.
The interpreter, implemented in src/lang/interpreter.cc, calls these functions via the public API of the
runtime (rt::add_reference, rt::remove_reference, rt::move_reference). The add_to_region() method is
never called directly by the interpreter.
A good example for the write-barrier is the StoreField bytecode implementation:
frankenscript/src/lang/interpreter.cc
Lines 303 to 318 in 30e431c
