diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b14e3ce --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.orig +node_modules +lib +dist +npm-debug.log +docs/literate \ No newline at end of file diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..c26f9ec --- /dev/null +++ b/.hgignore @@ -0,0 +1,7 @@ +syntax: glob +*.orig +node_modules +lib +dist +npm-debug.log +docs/literate \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..60d00ce --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "0.10" + - "0.8" + - "0.6" diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..599eb3d --- /dev/null +++ b/LICENCE @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2013 Quildreen Motta + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e00310b --- /dev/null +++ b/Makefile @@ -0,0 +1,63 @@ +bin = $(shell npm bin) +lsc = $(bin)/lsc +browserify = $(bin)/browserify +groc = $(bin)/groc +uglify = $(bin)/uglifyjs +VERSION = $(shell node -e 'console.log(require("./package.json").version)') + + +lib: src/*.ls + $(lsc) -o lib -c src/*.ls + +dist: + mkdir -p dist + +dist/control.async.umd.js: compile dist + $(browserify) lib/index.js --standalone Async > $@ + +dist/control.async.umd.min.js: dist/control.async.umd.js + $(uglify) --mangle - < $^ > $@ + +# ---------------------------------------------------------------------- +bundle: dist/control.async.umd.js + +minify: dist/control.async.umd.min.js + +compile: lib + +documentation: + $(groc) --index "README.md" \ + --out "docs/literate" \ + src/*.ls test/*.ls test/specs/**.ls README.md + +clean: + rm -rf dist build lib + +test: + $(lsc) test/tap.ls + +package: compile documentation bundle minify + mkdir -p dist/control.async-$(VERSION) + cp -r docs/literate dist/control.async-$(VERSION)/docs + cp -r lib dist/control.async-$(VERSION) + cp dist/*.js dist/control.async-$(VERSION) + cp package.json dist/control.async-$(VERSION) + cp README.md dist/control.async-$(VERSION) + cp LICENCE dist/control.async-$(VERSION) + cd dist && tar -czf control.async-$(VERSION).tar.gz control.async-$(VERSION) + +publish: clean + npm install + npm publish + +bump: + node tools/bump-version.js $$VERSION_BUMP + +bump-feature: + VERSION_BUMP=FEATURE $(MAKE) bump + +bump-major: + VERSION_BUMP=MAJOR $(MAKE) bump + + +.PHONY: test diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a949b2 --- /dev/null +++ b/README.md @@ -0,0 +1,106 @@ +control.async +============= + +[![Build Status](https://secure.travis-ci.org/folktale/control.async.png?branch=master)](https://travis-ci.org/folktale/control.async) +[![NPM version](https://badge.fury.io/js/control.async.png)](http://badge.fury.io/js/control.async) +[![Dependencies Status](https://david-dm.org/folktale/control.async.png)](https://david-dm.org/folktale/control.async) +[![experimental](http://hughsk.github.io/stability-badges/dist/experimental.svg)](http://github.com/hughsk/stability-badges) + + +Operations for asynchronous control flow. + + +## Example + +```js +( ... ) +``` + + +## Installing + +The easiest way is to grab it from NPM. If you're running in a Browser +environment, you can use [Browserify][] + + $ npm install control.async + + +### Using with CommonJS + +If you're not using NPM, [Download the latest release][release], and require +the `control.async.umd.js` file: + +```js +var Async = require('control.async') +``` + + +### Using with AMD + +[Download the latest release][release], and require the `control.async.umd.js` +file: + +```js +require(['control.async'], function(Async) { + ( ... ) +}) +``` + + +### Using without modules + +[Download the latest release][release], and load the `control.async.umd.js` +file. The properties are exposed in the global `Async` object: + +```html + +``` + + +### Compiling from source + +If you want to compile this library from the source, you'll need [Git][], +[Make][], [Node.js][], and run the following commands: + + $ git clone git://github.com/folktale/control.async.git + $ cd control.async + $ npm install + $ make bundle + +This will generate the `dist/control.async.umd.js` file, which you can load in +any JavaScript environment. + + +## Documentation + +You can [read the documentation online][docs] or build it yourself: + + $ git clone git://github.com/folktale/monads.maybe.git + $ cd monads.maybe + $ npm install + $ make documentation + +Then open the file `docs/literate/index.html` in your browser. + + +## Platform support + +This library assumes an ES5 environment, but can be easily supported in ES3 +platforms by the use of shims. Just include [es5-shim][] :) + + +## Licence + +Copyright (c) 2013 Quildreen Motta. + +Released under the [MIT licence](https://github.com/folktale/control.async/blob/master/LICENCE). + + +[Fantasy Land]: https://github.com/fantasyland/fantasy-land +[Browserify]: http://browserify.org/ +[release]: https://github.com/folktale/control.async/releases/download/v0.0.0/control.async-0.0.0.tar.gz +[Git]: http://git-scm.com/ +[Make]: http://www.gnu.org/software/make/ +[Node.js]: http://nodejs.org/ +[es5-shim]: https://github.com/kriskowal/es5-shim +[docs]: http://folktale.github.io/control.async diff --git a/package.json b/package.json new file mode 100644 index 0000000..59bfe6e --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "control.async", + "version": "0.0.0", + "description": "Operations for asynchronous control flow.", + "main": "lib/index.js", + "scripts": { + "test": "make test", + "prepublish": "make compile" + }, + "repository": { + "type": "git", + "url": "https://github.com/folktale/control.async" + }, + "keywords": [ + "fantasy-land", + "folktale" + ], + "author": "Quildreen Motta", + "license": "MIT", + "bugs": { + "url": "https://github.com/folktale/control.async/issues" + }, + "dependencies": {}, + "devDependencies": { + "browserify": "~2.35.4", + "groc": "git://github.com/killdream/groc#patch-livescript", + "LiveScript": "~1.2.0", + "hifive-tap": "~0.1.0", + "hifive": "~0.1.0", + "uglify-js": "~2.4.3", + "laws": "~0.2.0" + } +} diff --git a/src/index.ls b/src/index.ls new file mode 100644 index 0000000..128b30f --- /dev/null +++ b/src/index.ls @@ -0,0 +1,26 @@ +# # control.async + +/** ^ + * Copyright (c) 2013 Quildreen Motta + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +# Operations for asynchronous control flow. diff --git a/test/specs/index.ls b/test/specs/index.ls new file mode 100644 index 0000000..10a2fd5 --- /dev/null +++ b/test/specs/index.ls @@ -0,0 +1,30 @@ +# # Entry point for the specifications + +/** ^ + * Copyright (c) 2013 Quildreen Motta + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +module.exports = [ + # The specification objects go here + # See: http://hifivejs.github.io/hifive/getting-started.html + require './monad-laws' +] diff --git a/test/specs/monad-laws.ls b/test/specs/monad-laws.ls new file mode 100644 index 0000000..c6ed683 --- /dev/null +++ b/test/specs/monad-laws.ls @@ -0,0 +1,70 @@ +# # Specification for the monadic laws + +/** ^ + * Copyright (c) 2013 Quildreen Motta + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +# Before we define the specification, we need to set up the specs +# libraries, and grab a hold of our data structure and the laws we want +# to verify. +spec = (require 'hifive')! +laws = require 'laws' +Async = require '../../src/' + +# And to use the laws, we need to provide a constructor function, that +# given a single argument will return a new data structure containing +# that argument. We also make sure that the constructor for our +# semigroup implementation lifts the value into a non empty list, so we +# can concatenate the values. +make = (a) -> new Async a +make-nel = (a) -> new Async [a] + +# Then we provide the specification for the test runner. As we're using +# Hifive here, it expects that each definition for the specification to +# have a function that will throw exceptions on failures. We use the +# `asTest` property from Claire that returns exactly what Hifive (and +# Mocha & other testing libraries) expect. +module.exports = spec 'Algebraic laws' (o, spec) -> + + spec ': Semigroup' (o) -> + o '1. Associativity' laws.semigroup.associativity(make-nel).as-test! + + spec ': Monoid' (o) -> + o '1. Right identity' laws.monoid.right-identity(make).as-test! + o '2. Left identity' laws.monoid.left-identity(make).as-test! + + spec ': Functor' (o) -> + o '1. Identity' laws.functor.identity(make).as-test! + o '2. Composition' laws.functor.composition(make).as-test! + + spec ': Applicative' (o) -> + o '1. Identity' laws.applicative.identity(make).as-test! + o '2. Composition' laws.applicative.composition(make).as-test! + o '3. Homomorphism' laws.applicative.homomorphism(make).as-test! + o '4. Interchange' laws.applicative.interchange(make).as-test! + + spec ': Chain' (o) -> + o '1. Associativity' laws.chain.associativity(make).as-test! + + spec ': Monad' (o) -> + o '1. Left identity' laws.monad.left-identity(make).as-test! + o '2. Right identity' laws.monad.right-identity(make).as-test! diff --git a/test/tap.ls b/test/tap.ls new file mode 100644 index 0000000..0786387 --- /dev/null +++ b/test/tap.ls @@ -0,0 +1,34 @@ +# # A node test runner + +/** ^ + * Copyright (c) 2013 Quildreen Motta + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +# This will run the tests in a Node environment, and present the results +# with the TAP reporter. +hifive = require 'hifive' +tap = require 'hifive-tap' +specs = require './specs' + +# If we, for any reason, fail any of the tests, signal that with an +# error exit status. +(hifive.run specs, tap!).otherwise -> process?.exit 1 diff --git a/tools/bump-version.js b/tools/bump-version.js new file mode 100644 index 0000000..33e9d4f --- /dev/null +++ b/tools/bump-version.js @@ -0,0 +1,19 @@ +var pkg = require('../package.json') +var fs = require('fs') + +function minor(a) { + return [a[0], a[1], Number(a[2]) + 1] } + +function feature(a) { + return [a[0], Number(a[1]) + 1, 0] } + +function major(a) { + return [Number(a[0]) + 1, 0, 0] } + +function bump(what, version) { + return what === 'MAJOR'? major(version) + : what === 'FEATURE'? feature(version) + : /* otherwise */ minor(version) } + +pkg.version = bump(process.argv[2], pkg.version.split('.')).join('.') +fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2))