Today is ∞/∞/2^3 - Infinity Day - Origyn has 3 Gifts for the Motoko Community!
Gift 3 - Kusanagi - a little language that compiles to Motoko - It’s just motoko
@rossberg , @claudio , @matthewhammer - Please don’t kill me.
We all know what a great language motoko is. It is designed with the IC in mind and makes writing clear smart contracts with a high level language more possible for beginners than RUST.
…but sometimes…it is hard…and verbose…and takes up a lot of room on the screen.
And since the compiler is written in oCAML it can be very hard to contribute to.
Kusanagi is an attempt to fix that.
Back in 2009 a little language called coffeescript emerged to try to expose the “gorgeous heart” of javascript. It pioneered things like fat arrow, the existential operator, deconstructed arguments, and a ton of other features that eventually made their way into ECMAscript. CoffeeScript has faded from memory, but if you were one of the folks privileged enough to use it, you felt like it made you a faster, better developer(and it can make sure you produce lint-able, best practices code).
Kusanagi is CoffeeScript for Motoko. It is a significant whitespace, no semi, no braces, easy-to-add syntactic sugar engine that transpires into motoko. It is ultimately just motoko and in fact, you can mostly just start with motoko and start taking things out and it should transpile nicely.
What can it do?
Handle nulls a bit cleaner - null soaks:
let x = item?.child?.thing
to
let x = do?{item!.child!.thing};
Adds the take operator
let x = take item?.child?.thing, return #err("was null!")
to
let x = switch(do?{item!.child!.thing}){case(null){return #err("was null!")};case(?val){val}};
Adds the match operator
let x = match(aResult, #ok(aResult), return #err(debug_show(aResult)))
to
let x = switch(aResult){case(#ok(aResult)){aResult};case(_){return #err(debug_show(aResult))}};
Adds Fat arrow functions
let addOne = (x: Nat) : Nat =>
x + 1
to
let addOne = func (x: Nat) : Nat {
x + 1;
};
Adds cleaner object definition:
let x =
item = "1"
item2 = take item2, "default"
to
let x = {
item = "1";
item2 = switch(item2){case(null){"default"};case(?val){val}};
};
Back ticks let you put traditional motoko in:
module
let x = "1"
`
let y = "2";
`
The fat arrow and null soaks were added in the last 24 hours based on feedback from the community. So the hope here is that we can move faster to make the language more effective…and then good ideas can be migrated to motoko proper.
Oh…and the parser and transpiler are all written in a form coffeescript called hera which is a peg.js competitor so js devs can jump in and try adding features themselves(a little parser framework upfront work will be required…but you don’t have to learn oCaml). I’ll let the dev describe this more formally.
Here is the take definition:
"match" ExpNullary:exps ->
var exp, pred, def;
if (Array.isArray(exps)) {
if (exps[0] === "(") {
exp = exps[2][0];
pred = exps[3][2];
def = exps[4][2];
} else if (exps[1] === "(") {
exp = exps[3][0][0];
pred = exps[3][1][0];
def = exps[3][2][0];
}
if (exp != undefined && def != undefined) {
return ["switch(", exp, "){case(", pred, "){", exp, "};case(_){", def, "}}"]
}
}
return $skip
All of the work to this point has been done by @DanielXMoore with a bit of funding and guidance by the Origyn Foundation. We now want to open it up to the community as you all will be able to pound on this much more efficiently than we can.
You can try the language out at: Kusanagi
File issues at GitHub - DanielXMoore/kusanagi: CoffeeScript style syntax for Motoko language
There are certainly some bumps in it but we feel like we’re at about v0.9.0 and you all can help us get docs built(hopefully we can get to something like https://coffeescript.org/), edge cases covered(porting the base libraries might be a good start), and integrated with a build pipeline.
We hope we can hand this over to the community to improve and maybe pick up a DFINITY Grant for Daniel to increase his ability to contribute and move things along.