Skip to content

Commit 5018197

Browse files
committed
rough sketch of asynchronous variable package and impl of unsafeInterleaveAff
1 parent 40eac43 commit 5018197

File tree

5 files changed

+215
-4
lines changed

5 files changed

+215
-4
lines changed

Gruntfile.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,25 @@ module.exports = function(grunt) {
1717
src: "src/**/*.purs",
1818
dest: "MODULES.md"
1919
}
20+
},
21+
jsvalidate: {
22+
options:{
23+
globals: {},
24+
esprimaOptions: {},
25+
verbose: false
26+
},
27+
targetName:{
28+
files:{
29+
src:['output/**/*.js']
30+
}
31+
}
2032
}
21-
2233
});
2334

2435
grunt.loadNpmTasks("grunt-contrib-clean");
2536
grunt.loadNpmTasks("grunt-purescript");
37+
grunt.loadNpmTasks('grunt-jsvalidate');
2638

27-
grunt.registerTask("make", ["pscMake", "dotPsci", "pscDocs"]);
39+
grunt.registerTask("make", ["pscMake", "jsvalidate", "dotPsci", "pscDocs"]);
2840
grunt.registerTask("default", ["make"]);
2941
};

MODULES.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,72 @@ instance alternativeAff :: Alternative (Aff e)
173173

174174
``` purescript
175175
instance monadPlusAff :: MonadPlus (Aff e)
176-
```
176+
```
177+
178+
179+
180+
## Module Control.Monad.Aff.Unsafe
181+
182+
#### `unsafeInterleaveAff`
183+
184+
``` purescript
185+
unsafeInterleaveAff :: forall e1 e2 a. Aff e1 a -> Aff e2 a
186+
```
187+
188+
189+
190+
## Module Control.Monad.Aff.Var
191+
192+
#### `VarF`
193+
194+
``` purescript
195+
data VarF :: !
196+
```
197+
198+
199+
#### `Var`
200+
201+
``` purescript
202+
data Var :: * -> *
203+
```
204+
205+
206+
#### `AffVar`
207+
208+
``` purescript
209+
type AffVar e a = Aff (var :: VarF | e) a
210+
```
211+
212+
213+
#### `makeVar`
214+
215+
``` purescript
216+
makeVar :: forall e a. AffVar e (Var a)
217+
```
218+
219+
Makes a new asynchronous variable.
220+
221+
#### `takeVar`
222+
223+
``` purescript
224+
takeVar :: forall e a. Var a -> AffVar e a
225+
```
226+
227+
Takes the next value from the asynchronous variable.
228+
229+
#### `putVar`
230+
231+
``` purescript
232+
putVar :: forall e a. Var a -> a -> AffVar e Unit
233+
```
234+
235+
Puts a new value into the asynchronous variable. If the variable has
236+
been killed, this will result in an error.
237+
238+
#### `killVar`
239+
240+
``` purescript
241+
killVar :: forall e a. Var a -> Error -> AffVar e Unit
242+
```
243+
244+
Kills an asynchronous variable.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"dependencies": {
44
"grunt": "~0.4.5",
55
"grunt-purescript": "~0.6.0",
6-
"grunt-contrib-clean": "~0.6.0"
6+
"grunt-contrib-clean": "~0.6.0",
7+
"grunt-jsvalidate": "~0.2.2"
78
}
89
}

src/Control/Monad/Aff/Unsafe.purs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module Control.Monad.Aff.Unsafe where
2+
import Control.Monad.Aff
3+
4+
foreign import unsafeInterleaveAff """
5+
function unsafeInterleaveAff(aff) {
6+
return aff;
7+
}
8+
""" :: forall e1 e2 a. Aff e1 a -> Aff e2 a

src/Control/Monad/Aff/Var.purs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
-- | A low-level primitive for building asynchronous code.
2+
module Control.Monad.Aff.Var
3+
( AffVar()
4+
, Var()
5+
, VarF()
6+
, killVar
7+
, makeVar
8+
, putVar
9+
, takeVar
10+
) where
11+
12+
import Control.Monad.Aff
13+
import Control.Monad.Eff.Exception(Error())
14+
15+
foreign import data VarF :: !
16+
17+
foreign import data Var :: * -> *
18+
19+
type AffVar e a = Aff (var :: VarF | e) a
20+
21+
-- | Makes a new asynchronous variable.
22+
foreign import makeVar """
23+
function makeVar(error) {
24+
return function(success) {
25+
return function() {
26+
success({
27+
consumers: [],
28+
producers: [],
29+
error: undefined
30+
});
31+
}
32+
}
33+
}
34+
""" :: forall e a. AffVar e (Var a)
35+
36+
-- | Takes the next value from the asynchronous variable.
37+
foreign import takeVar """
38+
function takeVar(avar) {
39+
return function(error) {
40+
return function(success) {
41+
return function() {
42+
if (avar.error !== undefined) {
43+
error(avar.error)();
44+
} else if (avar.producers.length > 0) {
45+
var producer = avar.producers.shift();
46+
47+
producer(error, success);
48+
} else {
49+
avar.consumers.push({error: error, success: success});
50+
}
51+
}
52+
}
53+
}
54+
}
55+
""" :: forall e a. Var a -> AffVar e a
56+
57+
-- | Puts a new value into the asynchronous variable. If the variable has
58+
-- | been killed, this will result in an error.
59+
foreign import putVar """
60+
function putVar(avar) {
61+
return function(a) {
62+
return function(error) {
63+
return function(success) {
64+
return function() {
65+
if (avar.error !== undefined) {
66+
error(avar.error)();
67+
} else if (avar.consumers.length == 0) {
68+
avar.producer.push(function(error, success) {
69+
success(a)();
70+
});
71+
} else {
72+
var consumer = avar.shift();
73+
74+
try {
75+
consumer.success(a)();
76+
77+
success({})();
78+
} catch (e) {
79+
error(e)();
80+
}
81+
}
82+
}
83+
}
84+
}
85+
}
86+
}
87+
""" :: forall e a. Var a -> a -> AffVar e Unit
88+
89+
-- | Kills an asynchronous variable.
90+
foreign import killVar """
91+
function killVar(avar) {
92+
return function(e) {
93+
return function(error) {
94+
return function(success) {
95+
return function() {
96+
if (avar.error !== undefined) {
97+
error(avar.error);
98+
} else {
99+
var errors = [];
100+
101+
avar.error = e;
102+
103+
while (avar.consumers.length > 0) {
104+
var consumer = avar.shift();
105+
106+
try {
107+
consumer.error(e)();
108+
} catch (e) {
109+
errors.push(e);
110+
}
111+
}
112+
113+
if (errors.length > 0) error(errors[0])();
114+
else success({})();
115+
}
116+
}
117+
}
118+
}
119+
}
120+
}
121+
""" :: forall e a. Var a -> Error -> AffVar e Unit
122+

0 commit comments

Comments
 (0)