Write a story and run it anywhere
{
print("Would you like to write a simple story book?")
choice("Yes", {
print("Great! Let's check this out!")
})
choice("No", {
print("No worries!")
})
}
Stories that are written in JABL can be run from the command line, a web server or a web browser.
JABL is a constrained language that allows you to write stories and run them equally well from a CLI, web server or a web browser.
Each section of a story is a single file in a directory, where the directory is the story itself.
$ tree
.
├── story
│ ├── entrypoint.jabl
│ ├── chapter1.jabl
│ └── chapter2.jabl
There are only a handful of special keywords in JABL.
If something can be achieved without introducing a new keyword, it should be done.
print
: Print a message to the consolechoice
: Present a choice to the usergoto
: Jump to another sectionif
: Choose the branch to run based on a conditionset
: Set a variableget
,getn
,getb
: Get a variable (string, number, boolean)
Adds text to the output buffer.
print("Hello, World!")
Present a choice to the user. The first parameter is the identifier of this choice and the second parameter is a block of code to execute when the user selects it.
choice("Yes", {
print("Great! Let's check this out!")
})
Jump to another section. This causes the interpreter to load and execute the section with the given identifier.
It is up to the loader itself to determine the code for a particular identifier.
goto("chapter1.jabl")
Choose the branch to run based on a condition. If accepts any expression that evaluates to a boolean and must be wrapped in parentheses.
if (true) {
print("this is printed")
}
You can also use an else statement
if (false) {
print("this is not printed")
} else {
print("this is printed")
}
Set a variable. The first parameter is the name of the variable and the second parameter is the value.
This function returns the value that was set.
Variables can be float64 values, strings or booleans.
set("some-value", 123) # => 123
set("some-value", true) # => true
set("some-value", "test") # => "test"
Get a variable. The first parameter is the name of the variable.
This function returns the value of the variable.
This returns the string
value or ""
if the variable does not exist.
get("some-value") # => "Hello World!"
Get a variable. The first parameter is the name of the variable.
This function returns the value of the variable.
This returns the float64
value or 0
if the variable does not exist.
get("some-value") # => 123
Get a variable. The first parameter is the name of the variable.
This function returns the value of the variable.
This returns the bool
value or false
if the variable does not exist.
getb("some-value") # => false
You can add single-line coments by prefixing a line with //
.
// This is a comment
The JABL interpreter is a simple program that reads a story and executes it. It is written in Go and can be run from the command line or compiled to WASM and invoked from Javascript.
The Interpreter has two key abstractions:
StateMapper
: Implements theget
andset
functions with a backing store forfloat64
variablesSectionLoader
: Implements a strategy for loading sections from a story. This could be from a URL or a local file system.
It is (should be) safe to load JABL code from any source, as the interpreter does not execute any code until it has been parsed and validated.
The interpreter reads a section by identifier from a SectionLoader
, then parses the JABL code into an AST. The AST is then executed by the interpreter.
The JABL code is executed immediately and synchronously and results in a structure that has three components:
output
: A string that is printed to the consolechoices
: A list of choices that the user can maketransition
: The identifier of the next section to load and execute
If there is a transition
value, the interpreter will load and execute the next section. If there is no transition
value, the interpreter will stop until the user selects a choice
.
Each choice
is a name and function that is executed when the user selects it. The function is a block of JABL code that is executed immediately and synchronously.
The output
is an output buffer that is a collection of each print
statement separated by a newline.
The JABL interpreter can be built for the command line or for the web.
go build -o bin cmd/cli/main.go
GOOS=js GOARCH=wasm go build -o ./web/jabl.wasm ./cmd/wasm/main.go
cd web
npm ci
npm run start