Skip to content

Commit

Permalink
Initial commit + basic implementation w/ async
Browse files Browse the repository at this point in the history
  • Loading branch information
elierotenberg committed Aug 7, 2017
0 parents commit 42eb617
Show file tree
Hide file tree
Showing 10 changed files with 2,481 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"presets": [
[
"env",
{
"loose": true,
"target": {
"node": "current"
}
}
]
],
"plugins": [
"transform-runtime",
"transform-object-rest-spread",
"transform-class-properties"
]
}
32 changes: 32 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module.exports = {
env: {
browser: true,
es6: true,
node: true,
},
extends: ['eslint:recommended'],
parser: 'babel-eslint',
parserOptions: {
sourceType: 'module',
},
plugins: ['prettier'],
rules: {
'prettier/prettier': [
'error',
{
singleQuote: true,
semi: true,
trailingComma: 'all',
bracketSpacing: true,
jsxBracketSameLine: false,
parser: 'babylon',
},
],
'no-console': 0,
indent: ['error', 2],
'linebreak-style': ['error', 'unix'],
quotes: ['error', 'single', { avoidEscape: true }],
semi: ['error', 'always'],
'require-yield': 0,
},
};
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
*.log
tmp/
29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "algebraic-effects-experiments",
"version": "1.0.0",
"main": "dist/index.js",
"repository": "[email protected]:elierotenberg/algebraic-effects-experiments",
"author": "Elie Rotenberg <[email protected]>",
"license": "UNLICENSED",
"scripts": {
"make:lint": "eslint src/**/*.js",
"make:clean": "rimraf dist",
"make:build": "yarn run clean && mkdir dist && cp -r src/* dist && babel src -d dist --source-maps",
"make": "yarn run make:build"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.25.0",
"babel-eslint": "^7.2.3",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.0",
"babel-preset-latest": "^6.24.1",
"babel-register": "^6.24.1",
"babel-runtime": "^6.25.0",
"eslint": "^4.4.0",
"eslint-plugin-prettier": "^2.1.2",
"prettier": "^1.5.3",
"rimraf": "^2.6.1"
}
}
8 changes: 8 additions & 0 deletions src/CallEffect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CallEffect {
constructor(handlerName, args) {
this.handlerName = handlerName;
this.args = args;
}
}

export default CallEffect;
69 changes: 69 additions & 0 deletions src/Context.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import CallEffect from './CallEffect';
import ForkEffect from './ForkEffect';

const noop = () => void 0;

class Context {
static current = new Context({}, '<root>');

static switch(nextContext) {
const prevContext = this.current;
this.current = nextContext;
return () => this.switch(prevContext);
}

constructor(handlers, name = '<anonymous>') {
this.handlers = handlers;
this.name = name;
}

perform(genFn) {
return (fn = noop) => this.step(genFn(), null, void 0, fn);
}

step(gen, err, val, fn) {
const method = err ? 'throw' : 'next';
const restoreContext = Context.switch(this);
let g;
try {
g = gen[method](err || val);
} catch (err) {
fn(err);
return;
} finally {
restoreContext();
}
const { value, done } = g;
if (done) {
fn(null, value);
return;
}
if (value instanceof CallEffect) {
const { handlerName, args } = value;
const handler = this.handlers[handlerName];
const resume = nextVal => this.step(gen, null, nextVal, fn);
const interrupt = nextErr => this.step(gen, nextErr, null, fn);
handler(...args)(resume, interrupt);
return;
}
if (value instanceof ForkEffect) {
const { handlers, name, genFn } = value;
const forkContext = this.fork(handlers, name);
forkContext.perform(genFn)((nextErr, nextVal) =>
this.step(gen, nextErr, nextVal, fn),
);
return;
}
fn(
new TypeError(
"Only CallEffects can be yielded (created using 'use(handlerName)')",
),
);
}

fork(handlers, name) {
return new Context({ ...this.handlers, ...handlers }, name);
}
}

export default Context;
9 changes: 9 additions & 0 deletions src/ForkEffect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class ForkEffect {
constructor(handlers, name, genFn) {
this.handlers = handlers;
this.name = name;
this.genFn = genFn;
}
}

export default ForkEffect;
44 changes: 44 additions & 0 deletions src/example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { using, use, fork } from './lib';

const read = use('read');
const write = use('write');
const sleep = use('sleep');
const print = use('print');

function* writeValues() {
yield sleep(1000);
yield write('foo', 'bar');
yield sleep(1000);
yield write('fizz', 'buzz');
}

function* readValues() {
return [yield read('foo'), yield read('fizz')];
}

const store = {};

using({
print: (...args) => resume => {
console.log(...args);
resume(...args);
},
sleep: ms => resume => setTimeout(resume, ms),
}).perform(function*() {
yield print('outer context');
return yield fork({
read: key => resume => {
const value = store[key];
resume(value);
},
write: (key, value) => resume => {
store[key] = value;
resume(value);
},
})(function*() {
yield print('inner context');
yield* writeValues();
const [foo, bar] = yield* readValues();
return yield print([foo, bar].join(', '));
});
})();
11 changes: 11 additions & 0 deletions src/lib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import CallEffect from './CallEffect';
import ForkEffect from './ForkEffect';
import Context from './Context';

const use = handlerName => (...args) => new CallEffect(handlerName, args);

const using = (handlers, name) => Context.current.fork(handlers, name);

const fork = (handlers, name) => genFn => new ForkEffect(handlers, name, genFn);

export { use, using, fork };
Loading

0 comments on commit 42eb617

Please sign in to comment.