Skip to content
Minimal code-interchange format
Branch: master
Clone or download
Latest commit 88c39b7 Oct 26, 2017
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
base Empty DApp Oct 25, 2017
benchmark Getting ready for 0.2 (major update) Aug 18, 2017
examples
lib
src
test Faster slice on single-char case Sep 1, 2017
.DS_Store updates do wallet app Oct 17, 2017
.gitignore Either datatype. Oct 17, 2017
LICENSE
package.json Formatter: wrap arrows and equal signs Oct 25, 2017
readme.md

readme.md

Moon

Moon is an minimal, JIT-compilable, portable and secure code-interchange format. It is:

  • Safe: Moon isolates logic from side-effects, allowing you to securely run code from untrusted sources.

  • Fast: when compiled to JS, it beats popular libs by a large margin.

  • Compact: Moon has a canonical binary format for very small bundles.

  • Decentralized: Moon imports are hash-addressed, recursively resolved from IPFS.

  • Small: this entire implementation, for example, is a 7.5K JS file (gzipped).

Formally, Moon is just untyped λ-calculus extended with numbers, strings and maps.

Usage / Examples

Running code

To evaluate some code, simply use Moon.run():

const Moon = require("moon-lang")();

const program = `
  maximum = array =>
    (for 0 (get array "length") 0 index => result =>
      value = (get array (stn index))
      (if (gtn value result)
        value
        result))
  (maximum [1 7 6 9 5 2 8])
`;

console.log(Moon.run(program));

This is safe to do no matter the code contents, because Moon runs fully sandboxed.

Compiling Moon to a native function

You can also JIT-compile it to fast native functions:

const Moon = require("moon-lang")();

const factorial = Moon.parse(`n =>
  (for 1 (add n 1) 1 i => result =>
    (mul i result))
`);

console.log(factorial(4));

Decompiling a native function to Moon

And the other way around:

const Moon = require("moon-lang")();

const pair = Moon.parse("a => b => [a b]");

console.log(Moon.stringify(pair(1)));

Loading code from IPFS

Moon can recursivelly import hash-addressed terms from IPFS:

const Moon = require("moon-lang")(); 

(async () => {

  const sum = Moon.parse(await Moon.imports(`n =>
    // Imports array library from IPFS
    List = zb2rha9PW5Wnvhvz1n7pxXFZoMzeD3NxKYdZUHgxEsbhW8B4D
    reduce = (List "foldr")
    range = (List "range")

    (reduce (add) 0 (range 0 n))
  `));

  console.log(sum(5000000));

})();

Saving code to IPFS

It can also easily publish those terms:

const Moon = require("moon-lang")();

(async () => {

  const cid = await Moon.save("x => (mul x 2)");
  console.log(cid);

  const double = Moon.parse(await Moon.imports(cid));
  console.log(double(7));
  
})();

Performing side-effects (IO)

Moon itself is pure, but it can perform side-effective computations by injecting the effects from the host language. To avoid the "callback-hell", you can use Moon's monadic notation:

do = zb2rhkLJtRQwHz9e5GjiQkBtjL2SzZZByogr1uNZFyzJGA9dX

askPowerLevel = loop@ lazy =>
  | power =< (do "prompt" "What is your power level? ")
    (if (gtn (stn power) 9000)
      | (do "print" "No, it is not.")>
        (loop 0)
      | (do "print" "Ah, that's cute!")>
        (do "stop"))

(askPowerLevel 0)

You can run the code above using moon-tool:

moon runio zb2rhjR4sMEiMQ9m9bNCnavSUjEDzUvSrtAhuJStRWHcvNzb8

Optimizing code

  1. Use # to fully inline an expression.

  2. Use {fast:true} option (faster, only tradeoff is it can't be decompiled).

  3. Don't use recursive algorithms (map, reduce, etc.) directly on arrays; convert to churh-lists to enable fusion.

(async () => {

// Notice the hash (#): it fully inlines an expression, making it 8x faster.
const dotCode = `# x0 => y0 => z0 => x1 => y1 => z1 =>
  Array = zb2rhYmsjmQuJivUtDRARcobLbApVQZE1CwqhfnbBxmYuGpXx
  a = [x0 y0 z0]
  b = [x1 y1 z1]
  (Array "sum" (Array "zipWith" (mul) a b))
`;

// Also, use {fast:true}
const dot = Moon.parse(await Moon.imports(dotCode), {fast:true});

// Call it a ton of times
var dots = 0;
for (var i = 0; i < 1000000; ++i) {
  dots += dot(1)(2)(3)(4)(5)(6);
}
console.log(dots);

// Check the difference on the output
console.log(Moon.compile(await Moon.imports(dotCode)));

})();

Exporting Moon libs to npm

See this repository.

CLI

Check out moon-tool.

TODO

  • Time limit option
You can’t perform that action at this time.