JavaScript embedded effects compiler
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs
packages
samples persist-box stored in localStorage Aug 6, 2018
.gitattributes
.gitignore es-persist demo project Jun 10, 2018
.gitmodules
.tern-project initial rewrite to estransducers framework instead of visitors Feb 5, 2017
LICENSE
README.md
lerna.json
package.json

README.md

JavaScript embedded effects compiler

This is a JavaScript to JavaScript transpiler. It offers extending JavaScript language with various effects by means of runtime libraries, with or without compiler plugins.

There are such libraries for:

  • EcmaScript effects extensions (async functions, generators and async generators)
    • Why not native or other transpilers
      • Abstract API - @effectful/es
      • Persistent state - @effectful/es-persist
      • Concrete API - @effectful/es, the best performance
      • Implicit parallelism - Docs SOON
      • Deriving program's static graphs for analysis and conversion to other languages - SOON
  • Multi-prompt delimited continuations - @effectful/cc
  • Logical programming - SOON Old version

Not yet implemented:

  • probabilistic programming
  • parallel and distributed programming
  • persistent continuations
  • adaptive computations
  • reactive programming (with RxJS) - Old version

They are typically small libraries, some of them are just tiny wrappers around well known interfaces, such as Promises or Observables.

The compiler converts ES2018 to ES2018 and doesn't need any syntax extensions. So it may be applied to results of other compilers targeting JS such as CoffeeScript, TypeScript, Babel etc.

It stratifies input JavaScript code into two levels. The first level (pure) contains JS constructs (expressions, statements) kept as is in generated code. The second level (effectful) contains effectful constructs. The compiler converts them into abstract function calls.

I'm abusing term pure here. I don't mean the first level staments or expressions don't have side effects. This is plain, usual JavaScript and it is absolutely not a problem to use the side effects already embedded in JavaScript. Namely IO, references, exceptions, control flow, etc.

Their separation may be either explicit or implicit (two-level or single-level syntax resp.).

Async functions or generators syntax can be used for explicit level separation.

async function a() {
  console.log("x:",await getX());
}

The resulting function may be either standard conforming async function, or some effects library can overload default behavior to implement something from the list above.

The overloading may be either compile time - implementing some syntax transforms, or runtime - providing libraries with abstract interfaces implementations.

This is an example of one of a few possible outputs:

function a() {
  return M.chain(getX(), _1);

  function _1(a) {
    console.log("x:",a)
  }

}

There chain, raise methods are provided by some runtime library. For example its concrete implementation for Promises calls then function for chain and rejects the promise in M.raise.

The names and interfaces of the functions in the generated code are configurable.

There is a dozen of such functions required to be implemented in concrete effects implementation library but usually most of them are trivial.

The interface is based on Monads. However understanding Monads is required only to implement some new effects library. No needs to know anything about them to use the libraries.

With the implicit single-level mode the same code may be even more succinct:

function() {
  console.log("x:",getX());
}

There are more examples of input/output in the test folder.

It is arguable if explicit or implicit levels separation is better. This likely depends on what kind of effects is used. The succinct and more readable code is good, but if effects are heavy making them explicit may be better. So EffectfulJS compiler supports both options.

Usage

There are babel presets in separate packages.

  • @effectful/js compiles to the most abstract code, single or double level depending on parameters
  • @effectful/es for two-levels syntax either concrete ECMAScript compatible effects or abstract for async, generator and async generators semantics overloading.
  • @effectful/es-inline A shortcut for @effectful/es with concrete ECMAScript effects implementations.

All the presets are just shortcuts to @effectful/core setting needed lower level options described in config.js thus generated code uses different runtime interfaces.

Known major limitations

  • ES6 supper just replaced with Object.getPrototypeOf(...) and call, this is enough for most applications. If it is not, transpile classes with babel before effectful pass. No plans to fix this for now. No plans to implement.
  • In parameter's threading mode closure captured variables are always handled by reference. Compiler tries to handle only variables by value. All mutating operation like Array.prototype.push or object's field setting are still visible in other control threads. Closure capturing variables semantically are nothing but object's field. So they are references now too. But there are short term plans to track even mutating updates soon.
  • setters/getters and constructors cannot be effectful now, may be changed in near future after effectful's object referrences are implemented
  • eval/Function construction from string doesn't work, no plans to implement it.
  • configurations with state handling don't support arguments object aliasing (chainging its element - changes parameter value). This may be implemented in future.

LICENSE

Copyright © 2016-2018 Vitaliy Akimov

Distributed under the terms of The MIT License (MIT).