Skip to content
This repository has been archived by the owner on Oct 24, 2023. It is now read-only.

Channels for communicating sequential processes #10

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7af6692
Placeholder commit for channel branch, to start discussions
mstade Apr 22, 2014
50f5f22
Added `defprop` and `when`
mstade Oct 12, 2014
c37655e
Clean up `nth`
mstade Oct 12, 2014
242a11c
Fix up `src`
mstade Oct 12, 2014
4e8daa6
Fixed `is` when checking for booleans, and improved tests.
mstade Apr 25, 2014
71dadb7
Fixed a bug when calling `is` with identical args
mstade Apr 26, 2014
581c289
Fixed `type` to return constructor name if it exists.
mstade Oct 14, 2014
eb55446
Tab fix in test/each.js
mstade Oct 14, 2014
96e8990
Added `every` for easy testing of sequence values
mstade Oct 14, 2014
57f6199
A stab at protocols
mstade Oct 14, 2014
4491110
Fix failing tests; expose crappy coverage of `defprotocol`
Oct 10, 2014
8fee34e
Some first tests for `defprotocol`
mstade Oct 15, 2014
2b7c258
Rebased branch, fix all the things
mstade Jan 31, 2015
83edd97
Change funkis test to only pick up js files
mstade Jan 31, 2015
61a6536
Add `when` to index
mstade Jan 31, 2015
6d26bb1
Remove unused argument from `assert`
mstade Jan 31, 2015
2758968
Make sure `is` also tests constructor inheritance when type checking
mstade Jan 31, 2015
f6c6a9a
Fix `nth` tests and remove unnecessary partial application
mstade Jan 31, 2015
48b97b1
Fix indentation issues. (I hate Windows so much it hurts sometimes.)
mstade Jan 31, 2015
216a60c
Add feature detection for generators
mstade Jan 31, 2015
58e1203
Fix all indentation issues. Seriously.
mstade Jan 31, 2015
7101635
Change Travis config to use iojs instead of node
mstade Feb 7, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
language: node_js
node_js:
- "0.11"
- "0.10"
- "iojs"

after_script: NODE_ENV=test istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
83 changes: 44 additions & 39 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,41 +1,46 @@
module.exports =
{ and : require('./lib/and')
, apply : require('./lib/apply')
, assert : require('./lib/assert')
, call : require('./lib/call')
, compose : require('./lib/compose')
, constantly : require('./lib/constantly')
, count : require('./lib/count')
, dec : require('./lib/dec')
, each : require('./lib/each')
, eq : require('./lib/eq')
, gt : require('./lib/gt')
, get : require('./lib/get')
, identity : require('./lib/identity')
, inc : require('./lib/inc')
, is : require('./lib/is')
, isEmpty : require('./lib/isEmpty')
, isnt : require('./lib/isnt')
, log : require('./lib/log')
, lowerCase : require('./lib/lowerCase')
, lt : require('./lib/lt')
, merge : require('./lib/merge')
, min : require('./lib/min')
, not : require('./lib/not')
, nth : require('./lib/nth')
, once : require('./lib/once')
, partial : require('./lib/partial')
, pipe : require('./lib/pipe')
, range : require('./lib/range')
, repeatedly : require('./lib/repeatedly')
, seq : require('./lib/seq')
, slice : require('./lib/slice')
, src : require('./lib/src')
, take : require('./lib/take')
, thunk : require('./lib/thunk')
, trampoline : require('./lib/trampoline')
, type : require('./lib/type')
, val : require('./lib/val')
, variadic : require('./lib/variadic')
, vec : require('./lib/vec')
{ and : require('./lib/and')
, apply : require('./lib/apply')
, assert : require('./lib/assert')
, call : require('./lib/call')
, compose : require('./lib/compose')
, constantly : require('./lib/constantly')
, count : require('./lib/count')
, dec : require('./lib/dec')
, defprop : require('./lib/defprop')
, deftype : require('./lib/deftype')
, defprotocol : require('./lib/defprotocol')
, each : require('./lib/each')
, every : require('./lib/every')
, eq : require('./lib/eq')
, gt : require('./lib/gt')
, get : require('./lib/get')
, identity : require('./lib/identity')
, inc : require('./lib/inc')
, is : require('./lib/is')
, isEmpty : require('./lib/isEmpty')
, isnt : require('./lib/isnt')
, log : require('./lib/log')
, lowerCase : require('./lib/lowerCase')
, lt : require('./lib/lt')
, merge : require('./lib/merge')
, min : require('./lib/min')
, not : require('./lib/not')
, nth : require('./lib/nth')
, once : require('./lib/once')
, partial : require('./lib/partial')
, pipe : require('./lib/pipe')
, range : require('./lib/range')
, repeatedly : require('./lib/repeatedly')
, seq : require('./lib/seq')
, slice : require('./lib/slice')
, src : require('./lib/src')
, take : require('./lib/take')
, thunk : require('./lib/thunk')
, trampoline : require('./lib/trampoline')
, type : require('./lib/type')
, val : require('./lib/val')
, variadic : require('./lib/variadic')
, vec : require('./lib/vec')
, when : require('./lib/when')
}
2 changes: 1 addition & 1 deletion lib/assert.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module.exports = assert

function assert(x, message, type) {
function assert(x, message) {
if (isnt(x)) {
message = val(message)
isnt(message) && (message = "Assertion failed.")
Expand Down
5 changes: 5 additions & 0 deletions lib/async/buffer/fixed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = fixed

function fixed() {

}
35 changes: 35 additions & 0 deletions lib/async/buffer/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
var defprotocol = require('../../defprotocol')

module.exports = defprotocol('Buffer',
{ add : [Object]
, isFull : []
, remove : []
}
)

module.exports = deftype(FixedBuffer, [LinkedList, Number], Buffer)

function FixedBuffer(size) {
var list = []

return Buffer(FixedBuffer,
{ add : add
, remove : remove
, isFull : isFull
}
)

function add(item) {
!isFull() && list.unshift(item)
}

function remove() {
return list.pop()
}

function isFull() {
return list.length >= size
}
}

Buffer(obj).add()
46 changes: 46 additions & 0 deletions lib/async/chan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
module.exports = chan

function chan() {
return create(
{ put : { value: put }
, take : { value: take }
}
)

function put(value) {
}

function take() {
}
}

var create = Object.create

// var ReadPort = protocol({
// 'take' : [protocol, { returns: Promise }]
// })

// var WritePort = protocol({
// 'put' : [protocol, Object, { returns: Promise }]
// })

// var Channel = protocol({
// 'isClosed' : [protocol, { returns: Boolean }]
// 'close' : [protocol]
// })

// var Channel = protocol({
// 'take' : { returns: Promise }
// 'put' : { sig: [Object], returns: Promise }
// })

// var Channel = protocol({
// 'take' : { returns: Promise }
// 'put' : { sig: [Object], returns: Promise }
// })

// Channel(thing).take()

// go(function *() {
// var search = yield get('www.google.com').take()
// })
34 changes: 34 additions & 0 deletions lib/async/go.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = require('../variadic')(go)

function go(process, rest) {
if (isnt(Generator, process)) throw new TypeError('Co-routine must be a generator function')

var routine = process.apply(undefined, rest)
, error = routine.throw.bind(routine)
, next = routine.next.bind(routine)

tick(function() {
step(next())
})

function step(state) {
if (is(Promise, state.value) || is(Function, state.value.then)) {
console.log('step:promise', state)
Promise.resolve(state.value).then(next).then(step).catch(error)
} else if (state.done) {
return /* Put state.value on return channel */
} else {
console.log('step:value', state)
tick(function() {
step(next(state.value))
})
}
}
}

var tick = setImmediate
, comp = require('../compose')
, isnt = require('../isnt')
, is = require('../is')

var Generator = (function *(){}).constructor
1 change: 1 addition & 0 deletions lib/async/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {}
52 changes: 52 additions & 0 deletions lib/defprop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module.exports = defprop

function defprop(target, fields, opts) {
if (isnt(target)) throw TypeError("Target must exist.")
if (isnt(fields)) throw TypeError("Fields must exist.")

opts || (opts = {})

var names = Object.getOwnPropertyNames(fields)

var isMutable = get(opts, "^writable", false)
, isEnum = get(opts, "^enumerable", false)
, isConf = get(opts, "^configurable", false)
, scope = get(opts, "^bind", false)

return Object.defineProperties(target,
names.reduce(function(p, k) {
var prop = describe(fields, k)
, opt = $(get, opts[k])

if (isnt(prop.get) && isnt(prop.set)) {
prop.writable = opt("writable", isMutable)

when(is(Function, prop.value) && opt("bind", scope), function(scope) {
prop.value = prop.value.bind(scope)
})
} else {
when(prop.get && opt("writable") && !prop.set, function() {
throw TypeError("The accessor `"+k+"` can't be writable without a setter.")
})

when(opt("bind", scope), function(scope) {
prop.get && (prop.get = prop.get.bind(scope))
prop.set && (prop.set = prop.set.bind(scope))
})
}

prop.enumerable = opt("enumerable", isEnum)
prop.configurable = opt("configurable", isConf)

return (p[k] = prop), p
}, {})
)
}

var describe = Object.getOwnPropertyDescriptor
, isEmpty = require("./isEmpty")
, isnt = require("./isnt")
, when = require("./when")
, get = require("./get")
, is = require("./is")
, $ = require("./partial")
89 changes: 89 additions & 0 deletions lib/defprotocol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
module.exports = defprotocol

function defprotocol(name, sigs) {
assert(is(String, name), 'Name must be a string.')
assert(is(Object, sigs), 'Signatures must be an object.')

var map = new WeakMap()

defprop(Protocol, { toString : constantly('[protocol ' + name + ']') })

return Protocol

function Protocol(target, impl) {
return arguments.length > 1
? reify(map, target, sigs, impl)
: fetch(map, target, Protocol)
}
}

function fetch(map, target, Protocol) {
var T = typeOf(target)
, impl = map.get(T)

if (!impl) return

var exec = Object.create(Protocol, {})

each(impl, function(sig) {
var name = sig[0]
, fun = sig[1]

exec[name] = fun.bind(target)
})

return exec
}

function reify(map, target, sigs, impl) {
var T = is(Function, target)? target : typeOf(target)

assert(not(map.has(T)), 'Protocol already implemented for type ' + type(target))

var exec = {}

map.set(T, exec)

each(sigs, function(sig) {
var name = sig[0]
, args = sig[1]
, fun = impl[name]

assert(fun, 'Missing implementation for ' + name)
assert(every(args, $(is, Function)), 'Argument signature must be a function')

exec[name] = function() {
var vals = new Array(args.length)
, raw = [].slice.call(arguments)

for (var i = 1; i < args.length; i++) {
vals[i] = args[i](raw)
}

return fun.apply(this, vals)
}
})
}

function typeOf(x) {
if (isnt(x)) {
return nil
} else {
return x.constructor || Object.getPrototypeOf(x)
}
}

var constantly = require('./constantly')
, variadic = require('./variadic')
, defprop = require('./defprop')
, assert = require('./assert')
, lower = require('./lowerCase')
, every = require('./every')
, each = require('./each')
, type = require('./type')
, isnt = require('./isnt')
, src = require('./src')
, not = require('./not')
, nil = {}
, is = require('./is')
, $ = require('./partial')
5 changes: 5 additions & 0 deletions lib/deftype.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = deftype

function deftype() {

}
Loading