Skip to content
Branch: master
Go to file

Latest commit


Failed to load latest commit information.
Latest commit message
Commit time


Flatscript is a language and compiler that generates Javascript from a Python like language.

Installation and Build

Flatscript is implemented by Flatscript itself so it is not possible to build it from scratch.

You need to install it from npm before compiling it.

npm install -g flatscript

You could check the installation by the following command

flsc -h

Key Features

Javascript is famous for its callback-hell coding style. In Flatscript it allows developers to write code in synchronous styles and the compiler will translate it to asynchronous Javascript code.

For example, Flatscript code like:

for i range 10
    if i != 0
        setTimeout(%, 1000)

will print 0 up to 9 and "sleep" for 1 second between each print.

And for Flatscript code like:

fs: require('fs')
    console.log(fs.readFile('a.txt', %%) + fs.readFile('b.txt', %%))
catch e

will work in this order

  • read "a.txt"
  • read "b.txt"
  • concatenate their content
  • output to console

If any error, like file not found, occurs, the work flow will be interrupted and the error will be caught and sent to stderr. A message "end" would get outputted in the end.

Those features are an alternative of ES7 await. The lexical token % and %% indicates the argument should be a callback whose body will be generated by the compiler from the latter part of the syntax tree.

To read a list of files and store their content, Flatscript code is like

fs: require('fs')
files: ['a.txt', 'b.txt', 'c.txt']
content: []
    for i range files.length
        content.push(fs.readFile(files[i], %%).toString())
    console.log('content', content)
catch e

Or more simply, to use Flatscript pipeline syntax like (using pipeline mapping operator |:)

fs: require('fs')
files: ['a.txt', 'b.txt', 'c.txt']
    console.log('content', files |: fs.readFile($, %%).toString())
catch e

To encapsule this into a regular asynchronous function (like an async function in ES7)

fs: require('fs')

func readFiles(fileList, %%)
    return fileList |: fs.readFile($, %%).toString()

    console.log('content', readFiles(['a.txt', 'b.txt', 'c.txt'], %%))
catch e

Other Features

Indentation-indicated syntax

Code samples

# define a function that calculates fibonacci number
func fib(n)
    if n <= 1
        return 1
    return fib(n - 1) + fib(n - 2)


function $Rfib($Rn) {
    if (($Rn <= 1)) {
        return 1;
    return ($Rfib(($Rn - 1)) + $Rfib(($Rn - 2)));

Flatscript will also do some name mangling.

It is easy to break a long line into shorter ones, by hitting return after proper tokens. Code samples

['this', 'is', 'a',
    'long', 'list']

callFunction('with', 'several'
        , 'arguments')

x: a +

Anonymous function in an easy way

Anonymous functions are written in this way without any keywords


Code samples'some-file', (error, content):

Output"some-file", (function ($Rerror, $Rcontent) {

Convert synchronous code into asynchronous

In a call to a function which takes a callback with parameters (error, result), the callback argument could be represented as %%, and latter expressions and statements will become the body of the callback. The former and latter relationship is determined by the syntax tree, for instance, in the binary operation a + b, b is the latter of a. More detailed example:

func read(fileA, fileB, %%)
    return, %%) +, %%)

JS code generated as (demangled)

function read(fileA, fileB, $racb) {, (function (err, $ar_0) {
        if (err) return $racb(err);, (function (err, $ar_1) {
            if (err) return $racb(err);
            return $racb(null, $ar_0 + $ar_1);

Similarly, in a call to a function which takes a callback with no parameters, the callback could be represented as %. For example

setTimeout(%, 1000)
setTimeout(%, 1000)

JS code generated as

setTimeout((function() {
    setTimeout((function() {
    }), 1000);
}), 1000);

Pipe a list into a result

It uses a pipeline to iterate over a list. Pipeline operators are |: and |?. The former represents a mapping operation while the latter represents a filtering. Within a pipeline, use $ to reference the element, and $i for the index.

Code sample

x: [1, 1, 2, 3, 5, 8, 13]
console.log(x |: $ * $)
console.log(x |? $ % 3 = 1)
console.log(x |: $i % 2 = 0)
console.log(x |? $i % 2 = 0)


[1, 1, 4, 9, 25, 64, 169]
[1, 1, 13]
[true, false, true, false, true, false, true]
[1, 2, 5, 13]

Pipeline could be used along with regular asynchronous calls.

Code sample

func readFiles(fileList, %%)
    fileContent: fileList |:$, %%)
    return fileContent.join('')


function $RreadFiles($RfileList, $racb) {
    var $RfileContent;
    var $ar_0 = (function ($list) {
        function $next($index, $result) {
            var $key = null;
            if ($index === $list.length) {
                $RfileContent = $result;
                return $racb(null, $RfileContent.join(""));
            } else {
                var $element = $list[$index];
      $element, (function ($cb_err, $ar_1) {
                    if ($cb_err) return $racb($cb_err);
                    return $next($index + 1, $result);
        $next(0, []);

Use the Compiler


Flatscript will read source code from stdin or a file (with -i option), and print Javascript via stdout, or to a file (with -o option). The ordinary ways to compile

flsc < source.fls > output.js
flsc -i source.fls -o output.js

Or pipe the program to node

flsc < source.fls | node
flsc -i source.fls | node


Why the compiler complains names like 'require'/'document'/'window' not defined?

Flatscript checks name definition at compile time, and it is not possible to use any name that is not defined or not marked as external.

You could declare external names via -e option, like

flsc -e document -e window -i client/source.fls > client/output.js
flsc -e document:window -i client/source.fls > client/output.js
flsc -e require -i server/source.fls -o server/output.js

Or using extern statement in the source file:

extern require
fs: require('fs')
console.log(fs.readFile('a.txt', %%))

How could I use jQuery in Flatscript?

Use jQuery the identifier instead of $ because $ means the current list element in pipeline context, like

buttons: jQuery('.btn')

For More Information

Please read the wiki pages.


A Javascript-targeting programming language that makes it easy to write asynchronous code in a synchronous way




No releases published
You can’t perform that action at this time.