npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

flatscript

v0.2.0

Published

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

Downloads

6

Readme

Flatscript

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)
    console.log(i)

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

And for Flatscript code like:

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

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: []
try
    for i range files.length
        content.push(fs.readFile(files[i], %%).toString())
    console.log('content', content)
catch e
    console.error(e)
console.log('end')

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

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

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()

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

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)

Ouput

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 +
    b

Anonymous function in an easy way

Anonymous functions are written in this way without any keywords

(parameters):
    function-body

Code samples

fs.read('some-file', (error, content):
        console.log(content.toString())
    )

Output

fs.read("some-file", (function ($Rerror, $Rcontent) {
    console.log($Rcontent.toString());
}));

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 fs.read(fileA, %%) + fs.read(fileB, %%)

JS code generated as (demangled)

function read(fileA, fileB, $racb) {
    fs.read(fileA, (function (err, $ar_0) {
        if (err) return $racb(err);
        fs.read(fileB, (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

console.log(0)
setTimeout(%, 1000)
console.log(1)
setTimeout(%, 1000)
console.log(2)

JS code generated as

console.log(0);
setTimeout((function() {
    console.log(1);
    setTimeout((function() {
        console.log(2);
    }), 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)

Results

[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 |: fs.read($, %%)
    return fileContent.join('')

Output

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];
                fs.read($element, (function ($cb_err, $ar_1) {
                    if ($cb_err) return $racb($cb_err);
                    $result.push($ar_1);
                    return $next($index + 1, $result);
                }));
            }
        }
        $next(0, []);
    })($RfileList);
}

Use the Compiler

Run

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

FAQ

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.