Saffire: december 2012 update

Warning: This blogpost has been posted over two years ago. That is a long time in development-world! The story here may not be relevant, complete or secure. Code might not be complete or obsoleted, and even my current vision might have (completely) changed on the subject. So please do read further, but use it with caution.
Posted on 10 Dec 2012
Tagged with:

A few months ago I started with a new programming language called Saffire, and it’s time for an update. Since then, we have merged over 100 pull requests, and the number of contributors is steadily increasing. This post is explains of the functionality we already implemented (or want to implement).

From the user perspective, Saffire will operate the same way as “git”. This means that internally, many smaller sub-programs are called from one main binary. This keeps everything nice and tight without having to worry if you installed X or Y. If you install Saffire, you get Saffire. That’s it.

Configuration

Also, another great feature we added is the configuration management. Some aspects of Saffire can be controlled by configuration settings, and we provide a simple way to edit this configuration. Either manually the configuration file with an editor, or use the “config” command from Saffire.

First of all, generating a configuration file is easy:

$saffire config generate > myconfig.ini

Secondly, inspecting values is not hard as well:

$saffire config list fastcgi
fastcgi.pid.path : /var/run/saffire.pid
fastcgi.log.path : /var/log/saffire/fastcgi.log
fastcgi.log.level : notice
fastcgi.daemonize : false
fastcgi.spawn_children : 10
fastcgi.user : -1
fastcgi.group : -1
fastcgi.listen : 0.0.0.0:8080
fastcgi.listen.backlog : -1
fastcgi.listen.socket.user : nobody
fastcgi.listen.socket.group : nobody
fastcgi.listen.socket.mode : 0666

Also, adding or updating a setting:

$saffire config set fastcgi.daemonize true

FastCGI

As mentioned straight from the beginning, Saffire can be run through FastCGI. We provide a FastCGI server for this (again, inside the Saffire binary), but we haven’t done much work on it. Hopefully, we can find some time to get the FastCGI working properly

Repl & Lint

Other commands are the REPL and lint checker. The lint checker does exactly what it says: it can test a single Saffire binary or even a directory for syntax errors. The REPL (read/eval/print/loop) is the interactive console where you can easily run Saffire code. It’s not functional yet. Bummer…

Compilation & interpreting

This leaves our compile and execution commands. All Saffire code is actually converted in something called byte-code, which is an intermediate code. This has got a few reasons, most importantly because it speeds up execution, and we don’t need to read the actual Saffire-source over and over again. There are actually multiple steps in between: Saffire-source code will be translated to a so-called AST, that AST will converted to Saffire-assembler code and that assembler code is transformed into the bytecode.

The actual meat of Saffire are two components: the object-engine and the virtual machine. Since everything in Saffire is an object, this needs to be a very powerful engine. We modelled a lot of our engine on the Python engine (every language needs a base I guess), but we have some additional features we will implement (for instance, operator and method overloading). The operator overloading is partly functional as well. Everytime you do a a = b + 1, it will actually call the add-operator from object b.

The virtual machine is one of the most important pieces of Saffire, since most of the time will be spend inside this. It basically mimics a computer on itself (hence: virtual machine) that takes care of all kind of internals in order to run the Saffire bytecode. This also means that the virtual machine in itself should be fairly, euh, stupid. There are not many sanity checks one might expect so things will be as fast as possible for instance. We assume (and have to be 100% sure) that the bytecode we run is actually sane enough so we don’t need any checks. A lot of work has to be done to squeeze every CPU-cycle possible out of this system, but for the sake of clarity (and getting stuff done), we don’t right now. Optimization is not on our todo-list at this moment.

So, what can we actually run from Saffire? A lot of things actually. The basic foundations of the language are implemented. Think assigning and fetch identifiers, scopes, while/do/if/else statements.

a = 1;
while (a < 10) {
  a = a + 1;
  if (a == 5) break;
}

Looks simple, but the amount of work in order to get this running is massive. Trust me :)

Classes

Since everything is an object, classes and objects are pretty important. Right now, creating classes is functional and it’s even possible to extend other classes as well. It also knows if you call static methods from an instance (which is not allowed). One of the next things is visibility, abstract classes and implementing interfaces.  Calling methods also involves arguments. An argument can have a typehint (it should be a String, a Numerical etc), and it can have a default value. The system will figure out if you added the correct arguments and types, and if not, will throw an error.

class foo {
  public method bar(String name = "saffire!", Numerical a = 5) {
    for (i=0; i<=a; i++) io.print("hello", name, "\n");
   }
} 
tmp = foo.new();
tmp.bar("world", 1); // prints hello worl 1 time
tmp.bar("world"); // prints hello world, 5 times
tmp.bar();  // prints hello Saffire, 5 times

Notice the new(). This is because we cannot (yet) instantiate through our “normal” way:  tmp = foo(). Basically, we call the new() method, which instantiate it for us. This method is found in the base class, a class that every object extends from (actually, it will extends from base when no other extends is found). This base class has got all functionality needed to deal with objects: the reference count, the name, the memory usage, functionality to make an object read-only, functionality to clone, get parents, get interfaces, even get annotations (yes, we will implement annotations in the core).

The road ahead

We currently have a few contributors who are really busy implementing all kind of cool stuff. But we can always use your help. We are focussing on getting modules running. Once we can “load” code from other files, we can setup modules (which are like bundles, or directories with classes grouped together). These modules are the main Saffire “currency”. You need a twitter-client? Install the (or a) twitter-module. Need a framework, install the framework module and you’re good to go. This system can be seen as ruby “gems”. Another nice thing, we try and implement a repository system for modules, and we try to keep things as safe as possible. Modules are by default signed by the author, and will be validated upon download/installing. It’s even possible to sign single Saffire bytecode files!

The module repository

The module repository will be very similar to repository systems like apt and yum. You can add your own repositories, which are nothing more than websites with a specific structure. You can search through all Saffire modules and their metadata, install them, update them to the latest version (or lock a specific version), upload new modules, etc etc etc.. It really deserves a special blogpost (and it will, as soon as we start with the system).