Plasma User’s Guide

Copyright (C) 2021 Plasma Team
Distributed under CC BY-SA 4.0

Updated: March 2021
Source: on github
Table of Contents

The user’s guide describes how to use the Plasma tools to work with your programs.

Organising your program

Plasma programs are made up of modules. Each module corresponds to a file and also (in our implementation) a compilation unit. When someone says "Plasma module" or "Plasma file" you can assume they mean the same thing.

Filenames

A Plasma file ends with the extension .p and the filename must correspond to the module name. Files are checked for modules by ignoring case and the hyphen (-) and underscore (_) symbols.

In other words, my_module.p, my-module.p, mymodule.p, MyModule.p and My_-_Mo-Du-Le.p are all legal file names for MyModule. Likewise the file my_module.p could contain any of MyModule, my_module, mY_MoD_ule etc. While my_file.p does not match my_module. The exception is that - is not legal in module names since in Plasma code it represents subtraction.

Note
Why does Plasma match filenames loosely?

Some file systems are case sensitive and others are case insensitive, in different ways (storing filenames with case but matching them insensitively). Meanwhile not all writing systems have a concept of case. Rather than make separate rules for different situations so that we can support different file systems and writing systems; it is simpler to avoid making case meaningful.

By convention module names should be in UpperCase and their filenames in snake_case. These give the best clarity in code and the most compatibility on filesystems.

Programs

A plasma program must have at least one module and a BUILD.plz file to describe what’s required to build it. The BUILD.plz file is a TOML-ish file containing one or more TOML tables. For example:

[hello]
type = program
modules = [ Hello ]

Line one gives the name of the program (as the name of the TOML table). This is the name of the bytecode object that will be produced by plzbuild. The table has two keys, type and modules. The type key must be set to the string program or Plasma will not recognise it as a program. The modules key lists the modules that make up the program. It is an error to import (in source code) a module that’s not listed here.

Note
Why does Plasma require this?

This gives you one place where you can get an idea of how big and complex your program is, which becomes harder to tell if there are many programs sharing the same directory.

The following example shows a program with multiple modules:

[my_example]
type = program
modules = [ ModuleExample, ModuleToImport ]

A BUILD.plz file may describe more than one program. Plasma will check the BUILD.plz file for tables whose type key matches program and interpret each one as a program. This allows the source for multiple programs to live in the same directory. For example.

[program_1]
type = program
modules = [ Prog1, SharedCode ]

[program_2]
type = program
modules = [ Prog2, SharedCode ]

They may even share modules, as the above programs both use the SharedCode module which is compiled once and used by the two programs. In the future Plasma will also support libraries, but the ability to share code between programs in this way will always be provided.

This also means that if SharedCode imports another module CommonStuff, then CommonStuff must be in the modules lists of all the programs that include SharedCode.

Note
Why share code like this when libraries are more flexible?

Sharing code between multiple related programs can be useful when distributing a library is inconvenient (static linking is another solution) or when the shared code is too small to worry about (some utility code).

Future work:

Program entrypoints

Programs must have exactly one entrypoint. This is specified in the source code by placing the entrypoint keyword in front of a function definition.

entrypoint
func hello() uses IO -> Int {
     ...
     return 0
}

The chosen function must take zero arguments and return an integer. Following UNIX convention returning 0 from this function means the program ran successfully and any other value means it failed.

The entrypoint function’s name is irrelevant. There is no need to name your function main or WinMain.

It is syntactically possible to put the entrypoint specifier in front of multiple functions. In the future the linker will be able to choose the actual entrypoint from these candidates, but for now this is unsupported.

Future work:

Building programs

Programs are compiled form source code to bytecode using the plzbuild tool. Each module is compiled separately and then linked together to create a bytecode file for each program.

Running plzbuild with no command line arguments will build every program in the current directory’s BUILD.plz file. It will only rebuild the files/modules as necessary.

$ plzbuild
ninja: Entering directory `_build'
[4/4] Copying hello bytecode
Note
The hidden details

plzbuild doesn’t do its work on its own. It calls upon the services of another program, a ninja, the the ninja build system to do the dirty work. plzbuild creates a _build directory and places files in there for ninja. It then executes ninja to calculate dependencies and execute the compiler and linker with the right arguments to build your programs.

ninja (invoked by plzbuild) prints out a description of each command as it runs on a status line. The examples here show the last command to run (copying a bytecode file).

plzbuild can be given the names of programs to build, and options from the table below.

Table 1. plzbuild Options

-v, --verbose

Write verbose output

--rebuild

Regenerate/rebuild everything regardless of timestamps

--report-timing

Report the CPU & elapsed time for each build step

To build the fib and hello programs while ignoring any others (eg in the Plasma examples):

$ plzbuild hello fib
ninja: Entering directory `_build'
[8/8] Copying fib bytecode

Running programs

Plasma bytecode can be interpreted by the plzrun program:

$ plzrun hello.pz
Hello world

If your program dynamically links with other bytecode libraries load them with -l.

$ plzrun -l my_library.pz -l another_library.pz my_program.pz

Future work: