If you're in a hurry, try the wild overview of Rizzly .

The big picture

Rizzly is a programming language and compiler tailored for embedded systems. It has the following goals:

Example

Lamp = Component
lampOn: signal();
lampOff: signal();
buttonDown: slot();
buttonUp: slot();

elementary
isOn: Boolean = False;

buttonDown: slot()
isOn := not isOn;
if isOn then
lampOn();
else
lampOff();
end
end

buttonUp: slot()
end
end

The model

Rizzly is designed to write event-driven, reactive programs. This means, that everything one can do is reacting to events and sending events. The basic model is a message passing system whereas messages need some time to be delivered but execution is atomic. It implies that your code is never interrupted by another message.

The basic entity is a component. A component is defined by its input and output events. The input events specify which events a component can receive and the output which events a component can send. The programmer has 3 different ways to implement a component. Those are elementary event handlers, hierarchical finite state machines and composition of other components.

Elementary component implementation

Within the elementary component implementation, you react to events by writing an event handler. This is basically just a function which implements a prototype of an input event (function). In this function you can do (nearly) what you want: read and write state, send events out or just do nothing.

Hierarchical finite state machine component implementation

Lamp = Component
lampOn: signal();
lampOff: signal();
buttonDown: slot();
buttonUp: slot();

hfsm( Off )
Off: state
entry
lampOff();
end
end

On: state
entry
lampOn();
end
end

Off to On by buttonDown();
On to Off by buttonDown();
end

Since hierarchical finite state machines (hfsm) are an often used way to program such systems, we offer a way to write a component as a hfsm. A hfsm is entirely written as code and consist of states and transitions.

States support entry and exit functions, variables to keep additional (state) information, constants, state specific functions and more. They can of course also contain states itself.

A transition is always form one state to another one and executed by an event. The transitions can be guarded, i.e. only be executed if an predicate evaluates to true. Several transitions can handle the same event, depending on the state, guard and priority the right one is chosen.

...
Visible: state
timer: R{0,80} := 80; // this is the basic type, a range type

Visible to Visible by tick() if timer > 0 do
timer := timer - 1;
end
end

Visible to Hidden by tick() if timer = 0;
...

Composition component implementation

In the composition implementation you can not do much, but that is easily done. Components are built upon other components and you can connect output events to input events of other components.

The language

The syntax is inspired by Pascal; the type system by Ada. It provides the usual things you would expect: you can create types, have statements like if and while and expressions. Moreover, you can create components. The components support a textual composition implementation as also a hierarchical finite state machine implementation.

The program can be organized in several files. Every file can contain constants, functions, types and components. Note that there is no way to declare global variables. The state of the program is always encapsulated in the components. A further consequence is, that all global functions are pure - they have no possibility to access state variables.

To make the code reusable, you can parametrize the components and functions. This means, that you can provide values or types when using them. It works like templates, you can provide types and values.

The compiler

The Rizzly compiler is implemented in Java for practical reasons. You have to specify the input file and the component you want to instantiate. If other files are used too, they are loaded automatically. All used components are instantiated at compile time; this leads to a lower RAM footprint, allows more optimizations on the cost of a higher ROM footprint. Since we think that you seldom use a component more than once in one program, we pay that price.

In the end, the compiler writes one C file with all the code and one header file to access it. The C file should be compilable with our C compiler for the target system. You write the hardware access functions in C and let the Rizzly code handle the logic of our program.

The produced code is also easy testable on the host system since it only communicates over events. To support that, interface files in other languages can be produced by the compiler. For debugging, the compiler can add a debugging interface which gets you informed whenever an event is received or sent.

Find the source code of the Rizzly compiler on gitorious.org.