FreeForm

Introduction

Which is the best programming language in the world? Scala, D or perhaps the good old C? How about the the best data description format? JSON or maybe XML?

The question is somewhat naive as to a degree the question is merely of a personal preference and - even further - of the specific needs. JavaScript and C are hardly comparable. The syntax, semantics and the end results must fit the specific purpose and we may accept that there is no single ideal language for the generic cause.

Still, the idea of 'universal' language is tempting. What if - there would be only one language - but to fit a diverse and dynamic problem domain the language would be diverse and dynamic itself?

Meet FreeForm

FreeForm is not a traditional programming or data description language, but more of a runtime and a framework, which allows you define languages inline and take them into use inline. Syntax can be defined and taken into use like any utility or library. Even further - with FreeForm - a multithreading library could ship with multithreading syntax, SQL library with SQL syntax and RPC library with RPC syntax. The vision is that a library can provide syntax most convenient for the domain as an addition to functionality needed by domain. Even further, the dream is for the language to adopt any shape, form or function, that fit best the task at hand.

While FreeForm is not mature enought to act as a full programming environment, it does provide the basic mechanism for defining languages and language extensions inline and for taking the syntax into use inline. While language is dynamic in its essense, it ships with a some utilities and a 'standard language' that can be used for defining and organizing new language and functionality packages. Standard language is extremely minimalistic consisting only of 5 different directives that are:

FreeForm core ships with three different packages meant to form the very core of FreeForm runtime and framework. The basic language and functionality packages are:

The CoreForm project extends FreeForm with some additional utility functionality and syntax:

The FreeForm demo package introduces examples, and also extendable and minimalistic Lisp dialect (lisp.lang). While the Lisp dialect allows defining functions and expressions, it doesn't support defining generic expressions that are possible with the standard language.

Status

Right now, FreeForm is more of an idea than a practical high performing tool. FreeForm is a toy and may remain as such, but it is a curious, powerful and interesting toy with an approach to languages - that I believe - has not been tried before.

Try FreeForm:

If you wish to contribute to the project, please contact the author at arau at iki dot fi.

About Author

Antti Rauhala works as a senior software designer / developer at Futurice. The specialities are systems engineering, information retrieval and machine learning.

Code snippets

Calculator (calc.ff)

pkg calc {
    use m = ff.math;
    use e = ff.exp;
    use func = ff.func.lang;
    // operations
    exp plus = {hvalue>a '+' value>b}
    -> <func> (exp) => m.add(exp.a, exp.b);
    exp minus = {hvalue>a '-' value>b}
    -> <func> (exp) => m.reduce(exp.a, exp.b);
    exp mul = {pvalue>a '*' hvalue>b}
    -> <func> (exp) => m.mul(exp.a, exp.b);
    exp div = {pvalue>a '/' hvalue>b}
    -> <func> (exp) => m.div(exp.a, exp.b);
    exp brace = { '(' value>v ')' }
    -> <func> (exp) => exp.v;
    // primitive value
    exp pvalue = brace|ff.exp.int|ff.exp.ref;
    // define resolvation order
    exp hvalue = mul|div|pvalue;
    exp value = plus|minus|hvalue;
    // language definition
    name lang = value;
}

Usage

> <calc.lang> 4 + 5
9
> use calc.lang;
> 3 + 1 * 5
8
> (3 + 1) * 5
20
> <ff.func.lang> exit()

Extending Lisp (lispdemo.ff)

// Let's define a package using our dialect of lisp
pkg lispdemo(lisp.lang) {

    // lets steal C like increments and decrements
    (defexp inc {'+''+' func>f} (lambda (... args) (+ (exp.f ... args) 1)))
    (defexp dec {'-''-' func>f} (lambda (... args) (- (exp.f ... args) 1))) 
    
    // let's borrow a bit of json like syntax. the json.obj
    // syntax is extended here with our extended lisp-dialect
    (defexp obj (json.obj lang) (lambda () exp))

    // then just wrap things up
    (defexp func (lisp.gfunc (exp inc|dec|obj)))
    (defexp lang func (exp))

    // here's example of using C-style decrement
    <lang> 
    (defun factorial (n)
         (if (<= n 1)
               1
         (* n (factorial --n))))
    
    // And an example of how the object notation can be used
    <lang> 
    (define dog {
        name : 'scruffy', 
        hello  : (lambda (n) (ff.sys.out.println 'woof ' n)),
        legs : 4
        })
}

Usage

> use ff.func.lang;
> lispdemo.dog.hello('world!')
woof world!
> ff.math.plus(1, lispdemo.dog.legs)
5
> reset()
> use lispdemo.lang;
> (factorial 4)
24
> (factorial --4)
6
> (dog.hello 'world!')
woof world!
> (exit)

more examples here...