Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

cfg: fix double-fold async result usage

  • Loading branch information...
commit 50e755e9f09f30a19e638c7902c3b80f5e6281d7 1 parent b8827af
Fedor Indutny authored October 11, 2012
10  lib/spoon/block.js
@@ -111,12 +111,15 @@ Block.prototype.split = function split(at, root, asyncify, marker) {
111 111
   this.successors = [];
112 112
 
113 113
   // Add function declaration to the root block
114  
-  var fn = root.prepend('fn', [ next ]);
  114
+  var fn = root.prepend('fn', [ next ]),
  115
+      res = '__$r' + next.id;
  116
+
  117
+  root.prepend('var', [ res ]);
115 118
 
116 119
   fn.name = '__$fn' + next.id;
117 120
   fn.params = ['__$e', '__$r'];
118 121
   fn.isExpression = false;
119  
-  next.prepend('async-test-err');
  122
+  next.prepend('async-prelude', [ res ]);
120 123
 
121 124
   this.ended = false;
122 125
 
@@ -148,7 +151,8 @@ Block.prototype.split = function split(at, root, asyncify, marker) {
148 151
 
149 152
   return {
150 153
     next: next,
151  
-    fn: fn
  154
+    fn: fn,
  155
+    res: res
152 156
   };
153 157
 };
154 158
 
14  lib/spoon/cfg.js
@@ -106,7 +106,7 @@ Cfg.prototype.split = function split(at, root, asyncify, marker) {
106 106
   if (this.asyncifyState[block.id]) return this.asyncifyState[block.id];
107 107
 
108 108
   var info = block.split(at, root, asyncify, marker);
109  
-  this.asyncifyState[block.id] = info.fn;
  109
+  this.asyncifyState[block.id] = info;
110 110
 
111 111
   this.roots.push(info.next);
112 112
   this.blocks.push(info.next);
@@ -116,21 +116,21 @@ Cfg.prototype.split = function split(at, root, asyncify, marker) {
116 116
 
117 117
   // Traverse blocks starting from next, split on every frontier
118 118
   info.next.frontier.forEach(function(block) {
119  
-    var fn = this.split(block.instructions[0], root, false, marker);
  119
+    var info = this.split(block.instructions[0], root, false, marker);
120 120
 
121 121
     block.predecessors.forEach(function(pred) {
122 122
       // Remove goto
123 123
       var last = pred.instructions.pop();
124 124
 
125 125
       pred.ended = false;
126  
-      pred.add('async-goto', [ pred.add('get', [ fn.name ]) ]);
  126
+      pred.add('async-goto', [ pred.add('get', [ info.fn.name ]) ]);
127 127
       pred.end();
128 128
       pred.successors = [];
129 129
     }, this);
130 130
     block.predecessors = [];
131 131
   }, this);
132 132
 
133  
-  return info.fn;
  133
+  return info;
134 134
 };
135 135
 
136 136
 Cfg.prototype.asyncify = function asyncify(asts, options) {
@@ -251,15 +251,15 @@ Cfg.prototype.asyncify = function asyncify(asts, options) {
251 251
       if (marker < 0 && !match(instr)) return;
252 252
 
253 253
       // Split graph at instruction
254  
-      var fn = this.split(instr, instr.block.getRoot(), true, marker);
  254
+      var info = this.split(instr, instr.block.getRoot(), true, marker);
255 255
 
256  
-      // Replace all instruction uses by __$r
  256
+      // Replace all instruction uses by __$r[num]
257 257
       instr.uses.forEach(function(use, i) {
258 258
         if (i === instr.uses.length - 1) return;
259 259
         use.args = use.args.map(function(arg) {
260 260
           if (arg !== instr) return arg;
261 261
 
262  
-          var r = spoon.instruction.create(use.block, 'get', ['__$r']),
  262
+          var r = spoon.instruction.create(use.block, 'get', [ info.res ]),
263 263
               index = use.block.instructions.indexOf(use);
264 264
 
265 265
           use.block.instructions = [].concat(
19  lib/spoon/renderer.js
@@ -204,8 +204,8 @@ Renderer.prototype.renderInstruction = function renderInstruction(instr) {
204 204
     fn = this.renderAsyncReturn;
205 205
   } else if (t === 'async-end') {
206 206
     fn = this.renderAsyncEnd;
207  
-  } else if (t === 'async-test-err') {
208  
-    fn = this.renderAsyncTestErr;
  207
+  } else if (t === 'async-prelude') {
  208
+    fn = this.renderAsyncPrelude;
209 209
   } else if (t === 'nop') {
210 210
     fn = this.renderNop;
211 211
   } else {
@@ -409,11 +409,16 @@ Renderer.prototype.renderAsyncGoto = function renderAsyncGoto(args) {
409 409
   return ['return', ['call', ['dot', args[0], 'call'], [['name', 'this']]]];
410 410
 };
411 411
 
412  
-Renderer.prototype.renderAsyncTestErr = function renderAsyncTestErr(args) {
413  
-  return ['if', ['name', '__$e'], ['block',
414  
-    [['return', ['call',
415  
-    ['dot', ['name', '__$callback'], 'call'],
416  
-    [['name', 'this'],['name', '__$e']]]]]]];
  412
+Renderer.prototype.renderAsyncPrelude = function renderAsyncPrelude(args) {
  413
+  return ['if', ['name', '__$e'],
  414
+      ['block', [
  415
+        ['return', ['call', ['dot', ['name', '__$callback'], 'call'],
  416
+                            [['name', 'this'],['name', '__$e']]]]
  417
+      ]],
  418
+      ['block', [
  419
+        ['assign', true, ['name', args[0]], ['name', '__$r']]
  420
+      ]]
  421
+  ];
417 422
 };
418 423
 
419 424
 Renderer.prototype.renderNop = function renderNop() {
12  test/asyncify-test.js
@@ -31,6 +31,18 @@ describe('Spoon', function() {
31 31
   }
32 32
 
33 33
   describe('asyncify', function() {
  34
+    it('should asyncify two-fold operation', function() {
  35
+      var r = test(function fn(__$callback) {
  36
+        "enable spoon";
  37
+        function async(a, callback) {
  38
+          callback(null, a * a);
  39
+        }
  40
+
  41
+        return async(3) + async(4);
  42
+      }, 'async');
  43
+      assert.equal(r, 25);
  44
+    });
  45
+
34 46
     it('should asyncify method', function() {
35 47
       var r = test(function fn(__$callback) {
36 48
         "enable spoon";

0 notes on commit 50e755e

Please sign in to comment.
Something went wrong with that request. Please try again.