react 0.0.2 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.npmignore +6 -0
  2. package/Jakefile.js +8 -0
  3. package/README.md +226 -86
  4. package/examples/ast1.js +26 -0
  5. package/examples/chain-events1.js +34 -0
  6. package/examples/chain1.js +19 -0
  7. package/examples/default-events1.js +52 -0
  8. package/examples/default1.js +40 -0
  9. package/examples/fstr-events1.js +51 -0
  10. package/examples/fstr1.js +36 -0
  11. package/examples/pcode1.js +22 -0
  12. package/jake-tasks/jake-test.js +64 -0
  13. package/lib/base-task.js +115 -0
  14. package/lib/cb-task.js +67 -0
  15. package/lib/chain.js +148 -0
  16. package/lib/core.js +96 -0
  17. package/lib/dsl.js +122 -0
  18. package/lib/error.js +37 -0
  19. package/lib/event-manager.js +57 -0
  20. package/lib/finalcb-first-task.js +59 -0
  21. package/lib/finalcb-task.js +54 -0
  22. package/lib/fstr.js +110 -0
  23. package/lib/id.js +10 -0
  24. package/lib/input-parser.js +44 -0
  25. package/lib/parse.js +29 -0
  26. package/lib/pcode.js +164 -0
  27. package/lib/ret-task.js +67 -0
  28. package/lib/status.js +5 -0
  29. package/lib/task.js +234 -0
  30. package/lib/validate.js +102 -0
  31. package/lib/vcon.js +76 -0
  32. package/oldExamples/analyze.js +29 -0
  33. package/oldExamples/analyze2.js +29 -0
  34. package/oldExamples/example10-dsl.js +63 -0
  35. package/oldExamples/example11.js +62 -0
  36. package/oldExamples/example12.js +63 -0
  37. package/oldExamples/example13.js +63 -0
  38. package/oldExamples/example14.js +63 -0
  39. package/oldExamples/example15.js +75 -0
  40. package/{test → oldExamples}/example6-ast.js +4 -4
  41. package/{test → oldExamples}/example6-dsl.js +3 -2
  42. package/{test → oldExamples}/example8-ast.js +3 -2
  43. package/{test → oldExamples}/example8-dsl.js +3 -2
  44. package/{test → oldExamples}/example9-ast.js +3 -2
  45. package/{test → oldExamples}/example9-dsl.js +3 -2
  46. package/oldExamples/function-str-ex1.js +33 -0
  47. package/oldExamples/function-str-ex2.js +67 -0
  48. package/oldExamples/trait1.js +41 -0
  49. package/oldExamples/trait2.js +44 -0
  50. package/package.json +16 -6
  51. package/react.js +11 -1
  52. package/test/ast.test.js +69 -0
  53. package/test/cb-task.test.js +197 -0
  54. package/test/chain.test.js +239 -0
  55. package/test/core.test.js +519 -0
  56. package/test/dsl.test.js +237 -0
  57. package/test/event-manager.test.js +102 -0
  58. package/test/exec-options.test.js +32 -0
  59. package/test/finalcb-task.test.js +37 -0
  60. package/test/fstr.test.js +288 -0
  61. package/test/input-parser.test.js +62 -0
  62. package/test/module-use.test.js +317 -0
  63. package/test/pcode.test.js +321 -0
  64. package/test/ret-task.test.js +199 -0
  65. package/test/task.test.js +21 -0
  66. package/test/validate-cb-task.test.js +74 -0
  67. package/test/validate-ret-task.test.js +83 -0
  68. package/test/validate.test.js +218 -0
  69. package/test/vcon.test.js +160 -0
  70. package/lib/react.js +0 -239
@@ -0,0 +1,59 @@
1
+ 'use strict';
2
+
3
+ var sprintf = require('sprintf').sprintf;
4
+ var util = require('util');
5
+
6
+ var STATUS = require('./status.js');
7
+ var VContext = require('./vcon.js');
8
+
9
+ var OUTTASK_A_REQ = 'ast.outTask.a should be an array of string param names';
10
+
11
+ function FinalCbFirstSuccTask(taskDef, cbFunc, tasks, vCon) {
12
+ var self = this;
13
+ Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
14
+ this.f = cbFunc;
15
+ this.tasks = tasks;
16
+ this.vCon = vCon;
17
+ }
18
+
19
+ function format_error(errmsg, obj) {
20
+ return sprintf('%s - %s', errmsg, util.inspect(obj));
21
+ }
22
+
23
+ FinalCbFirstSuccTask.validate = function (taskDef) {
24
+ var errors = [];
25
+ if (! (Array.isArray(taskDef.a) &&
26
+ taskDef.a.every(function (x) { return (typeof(x) === 'string'); }))) {
27
+ errors.push(format_error(OUTTASK_A_REQ, taskDef));
28
+ }
29
+ return errors;
30
+ }
31
+
32
+ FinalCbFirstSuccTask.create = function (taskDef, cbFunc, tasks, vCon) {
33
+ if (!(cbFunc && cbFunc instanceof Function)) throw new Error('callback is not a function');
34
+ return new FinalCbFirstSuccTask(taskDef, cbFunc, tasks, vCon);
35
+ };
36
+
37
+ /**
38
+ is ready to exit when any task comes back with non-null defined value
39
+ */
40
+ FinalCbFirstSuccTask.prototype.isReady = function () {
41
+ var lastres = this.vCon.getLastResults();
42
+ if (!lastres) return false; // no results yet
43
+ return (lastres.some(function (v) { return (v !== undefined && v !== null); }));
44
+ };
45
+
46
+ FinalCbFirstSuccTask.prototype.exec = function (err) {
47
+ if (!this.f) return; //must have already been called
48
+ if (err) {
49
+ this.f.call(null, err); //call the final callback with the first error hit
50
+ } else { // no error, call with args
51
+ var vCon = this.vCon;
52
+ var finalArgs = this.a.map(function (k) { return vCon.getVar(k); });
53
+ finalArgs.unshift(null); //unshift err=null to front
54
+ this.f.apply(null, finalArgs);
55
+ }
56
+ this.f = null; // prevent multiple calls
57
+ };
58
+
59
+ module.exports = FinalCbFirstSuccTask;
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ var sprintf = require('sprintf').sprintf;
4
+ var util = require('util');
5
+
6
+ var STATUS = require('./status.js');
7
+
8
+ var OUTTASK_A_REQ = 'ast.outTask.a should be an array of string param names';
9
+
10
+ function FinalCbTask(taskDef, cbFunc, tasks, vCon) {
11
+ var self = this;
12
+ Object.keys(taskDef).forEach(function (k) { self[k] = taskDef[k]; });
13
+ this.f = cbFunc;
14
+ this.tasks = tasks;
15
+ this.vCon = vCon;
16
+ }
17
+
18
+ function format_error(errmsg, obj) {
19
+ return sprintf('%s - %s', errmsg, util.inspect(obj));
20
+ }
21
+
22
+
23
+ FinalCbTask.validate = function (taskDef) {
24
+ var errors = [];
25
+ if (! (Array.isArray(taskDef.a) &&
26
+ taskDef.a.every(function (x) { return (typeof(x) === 'string'); }))) {
27
+ errors.push(format_error(OUTTASK_A_REQ, taskDef));
28
+ }
29
+ return errors;
30
+ };
31
+
32
+ FinalCbTask.create = function (taskDef, cbFunc, tasks, vCon) {
33
+ if (!(cbFunc && cbFunc instanceof Function)) throw new Error('callback is not a function');
34
+ return new FinalCbTask(taskDef, cbFunc, tasks, vCon);
35
+ };
36
+
37
+ FinalCbTask.prototype.isReady = function () {
38
+ return (this.tasks.every(function (t) { return (t.status === STATUS.COMPLETE); }));
39
+ };
40
+
41
+ FinalCbTask.prototype.exec = function (err) {
42
+ if (!this.f) return; //must have already been called
43
+ if (err) {
44
+ this.f.call(null, err); //call the final callback with the first error hit
45
+ } else { // no error, call with args
46
+ var vCon = this.vCon;
47
+ var finalArgs = this.a.map(function (k) { return vCon.getVar(k); });
48
+ finalArgs.unshift(null); //unshift err=null to front
49
+ this.f.apply(null, finalArgs);
50
+ }
51
+ this.f = null; // prevent multiple calls
52
+ };
53
+
54
+ module.exports = FinalCbTask;
package/lib/fstr.js ADDED
@@ -0,0 +1,110 @@
1
+ 'use strict';
2
+
3
+ var sprintf = require('sprintf').sprintf;
4
+ var core = require('./core.js');
5
+ var parse = require('./parse.js');
6
+ var tutil = require('./task.js');
7
+
8
+ var INPARAMS_NO_MATCH = 'input params in wrong format, wanted "foo, bar" - found: %s';
9
+ var OUTPARAMS_NO_MATCH = 'output params in wrong format, wanted "foo, bar" - found: %s';
10
+ var INOUT_PARAMS_NO_MATCH = 'task params in wrong format, wanted "foo, bar -> err, baz" - found: %s';
11
+ var EXTRA_TASKARG = 'extra unmatched task arg: %s';
12
+
13
+ var inOutDefParse = {
14
+ regex: /^([^-]*)(->)?\s*(er{0,2}\s*,|returns?\s+)?(.*)$/i,
15
+ fn: function (m) {
16
+ var reMatchReturns = /returns?/i;
17
+ return {
18
+ type: (m[3] && m[3].match(reMatchReturns)) ? 'ret' : 'cb',
19
+ inDef: parse.splitTrimFilterArgs(m[1]),
20
+ outDef: parse.splitTrimFilterArgs(m[4])
21
+ };
22
+ }
23
+ };
24
+
25
+ function filterOutTrailingCbParam(args) { // if has trailing cb | callback param, filter it out
26
+ var cbNamesRe = /^cb|callback$/i; //cb, Cb, CB, callback, Callback
27
+ if (args.length && args[args.length - 1].match(cbNamesRe)) args.pop();
28
+ return args;
29
+ }
30
+
31
+ function parseInParams(str) {
32
+ var objDef = parse.parseStr(str, [inOutDefParse], INPARAMS_NO_MATCH);
33
+ objDef.inDef = filterOutTrailingCbParam(objDef.inDef);
34
+ return objDef;
35
+ }
36
+
37
+ function parseInOutParams(str) {
38
+ var objDef = parse.parseStr(str, [inOutDefParse], INOUT_PARAMS_NO_MATCH);
39
+ objDef.inDef = filterOutTrailingCbParam(objDef.inDef);
40
+ return objDef;
41
+ }
42
+
43
+ function parseOutParams(str) {
44
+ if (str.indexOf('->') === -1) str = '-> ' + str; // prefix so does out err process
45
+ return parse.parseStr(str, [inOutDefParse], OUTPARAMS_NO_MATCH);
46
+ }
47
+
48
+ function parseTasks(arr) {
49
+ var tasks = [];
50
+ var fn, obj, result;
51
+ while (arr.length >= 2) {
52
+ obj = {};
53
+ fn = arr.shift();
54
+ result = parseInOutParams(arr.shift());
55
+ if (typeof(arr[0]) === 'object') obj = arr.shift(); // has options, use as obj
56
+ obj.f = fn;
57
+ obj.a = result.inDef;
58
+ var type = result.type;
59
+ obj.out = result.outDef;
60
+ obj.type = type;
61
+ tasks.push(obj);
62
+ }
63
+ if (arr.length) throw new Error(sprintf(EXTRA_TASKARG, arr[0]));
64
+ return tasks;
65
+ }
66
+
67
+
68
+ function fstrDefine(inParamStr, taskDefArr, outParamStr, options) {
69
+ if (!inParamStr) inParamStr = '';
70
+ if (!taskDefArr) taskDefArr = [];
71
+ if (!outParamStr) outParamStr = '';
72
+
73
+ var reactFn = core();
74
+ var ast = {
75
+ inParams: parseInParams(inParamStr).inDef,
76
+ tasks: parseTasks(taskDefArr),
77
+ outTask: { a: parseOutParams(outParamStr).outDef }
78
+ };
79
+ if (options) Object.keys(options).forEach(function (k) { ast[k] = options[k]; });
80
+ var errors = reactFn.setAndValidateAST(ast);
81
+ if (errors.length) {
82
+ var errorStr = errors.join('\n');
83
+ throw new Error(errorStr);
84
+ }
85
+ return reactFn;
86
+ }
87
+
88
+ function selectFirst(inParamStr, taskDefArr, outParamStr, options) {
89
+ if (!inParamStr) inParamStr = '';
90
+ if (!taskDefArr) taskDefArr = [];
91
+ if (!outParamStr) outParamStr = '';
92
+ var tasks = tutil.serializeTasks(parseTasks(taskDefArr));
93
+
94
+ var reactFn = core();
95
+ var ast = {
96
+ inParams: parseInParams(inParamStr).inDef,
97
+ tasks: tasks,
98
+ outTask: { type: 'finalcbFirst', a: parseOutParams(outParamStr).outDef },
99
+ };
100
+ if (options) Object.keys(options).forEach(function (k) { ast[k] = options[k]; });
101
+ var errors = reactFn.setAndValidateAST(ast);
102
+ if (errors.length) {
103
+ var errorStr = errors.join('\n');
104
+ throw new Error(errorStr);
105
+ }
106
+ return reactFn;
107
+ }
108
+
109
+ module.exports = fstrDefine;
110
+ module.exports.selectFirst = selectFirst;
package/lib/id.js ADDED
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ var startingId = 0;
4
+
5
+ function createUniqueId() {
6
+ startingId += 1;
7
+ return startingId;
8
+ }
9
+
10
+ exports.createUniqueId = createUniqueId;
@@ -0,0 +1,44 @@
1
+ 'use strict';
2
+
3
+ var defaultExecOptions = {
4
+ reactExecOptions: true,
5
+ outputStyle: 'callback',
6
+ };
7
+
8
+ var OUTPUT_STYLES = {
9
+ CALLBACK: 'callback',
10
+ NONE: 'none'
11
+ };
12
+
13
+ function isExecOptions(x) { return (x && x.reactExecOptions); }
14
+ function execOptionsFilter(x) { return isExecOptions(x); }
15
+ function nonExecOptionsFilter(x) { return !isExecOptions(x); }
16
+ function mergeExecOptions(accum, options) {
17
+ Object.keys(options).forEach(function (k) { accum[k] = options[k]; });
18
+ return accum;
19
+ }
20
+
21
+ function splitArgs(args, inParams, style) {
22
+ var result = { };
23
+ result.args = inParams.map(function (p) { return args.shift(); }); // take args for input params first
24
+ if (style === OUTPUT_STYLES.CALLBACK && args.length) result.cb = args.shift(); // next take the cb
25
+ result.extra = args; // these remaining were after the callback
26
+ return result;
27
+ }
28
+
29
+ function inputParser(inputArgs, ast) {
30
+ var parsedInput = { };
31
+ var execOptionsArr = inputArgs.filter(execOptionsFilter);
32
+ execOptionsArr.unshift(defaultExecOptions);
33
+ parsedInput.options = execOptionsArr.reduce(mergeExecOptions, {});
34
+
35
+ var args = inputArgs.filter(nonExecOptionsFilter);
36
+ var splitResult = splitArgs(args, ast.inParams, parsedInput.options.outputStyle);
37
+ parsedInput.args = splitResult.args;
38
+ parsedInput.cb = splitResult.cb;
39
+ if (splitResult.extra) parsedInput.extraArgs = splitResult.extra;
40
+ return parsedInput;
41
+ }
42
+
43
+ module.exports = inputParser;
44
+ module.exports.defaultExecOptions = defaultExecOptions;
package/lib/parse.js ADDED
@@ -0,0 +1,29 @@
1
+ 'use strict';
2
+
3
+ var sprintf = require('sprintf').sprintf;
4
+
5
+ function splitTrimFilterArgs(commaSepArgs) { //parse 'one, two' into ['one', 'two']
6
+ if (!commaSepArgs) return [];
7
+ return commaSepArgs.split(',') //split on commas
8
+ .map(function (s) { return s.trim(); }) //trim
9
+ .filter(function (s) { return (s); }); //filter out empty strings
10
+ }
11
+
12
+ function parseReduce(accum, regexFn) {
13
+ if (typeof(accum) !== 'string') return accum; // already matched
14
+ var m = regexFn.regex.exec(accum);
15
+ if (m) return regexFn.fn(m); // return result obj
16
+ return accum; // no match, return str, will try next matcher
17
+ }
18
+
19
+ function parseStr(str, parseMatchers, errStr) {
20
+ var result = parseMatchers.reduce(parseReduce, str);
21
+ if (typeof(result) !== 'string') { // matched
22
+ return result;
23
+ } else { // no match
24
+ throw new Error(sprintf(errStr, str));
25
+ }
26
+ }
27
+
28
+ exports.splitTrimFilterArgs = splitTrimFilterArgs;
29
+ exports.parseStr = parseStr;
package/lib/pcode.js ADDED
@@ -0,0 +1,164 @@
1
+ 'use strict';
2
+
3
+ var sprintf = require('sprintf').sprintf;
4
+ var core = require('./core.js');
5
+ var parse = require('./parse.js');
6
+ var tutil = require('./task.js');
7
+
8
+ var INPARAMS_NO_MATCH = 'input params in wrong format, wanted "foo, bar, cb" - found: %s';
9
+ var OUTPARAMS_NO_MATCH = 'output params in wrong format, wanted "cb(err, foo)" - found: %s';
10
+ var INOUT_PARAMS_NO_MATCH = 'task params in wrong format, wanted "foo, bar := func(baz, cat, cb) " - found: %s';
11
+ var EXTRA_TASKARG = 'extra unmatched task arg: %s';
12
+
13
+ /**
14
+ Examples:
15
+ var react = require('react');
16
+
17
+ var locals = { falpha: falpha, fbeta: fbeta, fcharlie: fcharlie };
18
+ var fn = react.pcodeDefine('a, b', [
19
+ 'd := fbeta(a, b)',
20
+ 'e = fcharlie(a, b)',
21
+ 'c := falpha(a, b) when fbeta:done and fcharlie:done',
22
+ 'cb(err, c, d, e);'
23
+ ], locals);
24
+
25
+ function cb(err, d, e) { }
26
+ fn(10, 20, cb);
27
+ */
28
+
29
+ function splitAndFilterArgs(commaSepArgs) { // split, trim, filter out empty and (cb or callback)
30
+ var args = parse.splitTrimFilterArgs(commaSepArgs);
31
+ var cbNamesRe = /^cb|callback$/i; //cb, Cb, CB, callback, Callback
32
+ if (args.length && args[args.length - 1].match(cbNamesRe)) args.pop();
33
+ return args;
34
+ }
35
+
36
+ function extractNamesFromWhenClause(str) { //given 'foo:done and bar.baz:done' return ['foo', 'bar.baz']
37
+ var reSplit = /\s+and\s+/i;
38
+ var reDone = /^([^:]+):done$/i;
39
+ var names = str.split(reSplit).map(function (x) {
40
+ x = x.trim();
41
+ var m = x.match(reDone); // if foo:done, we'll use foo
42
+ return (m) ? m[1] : x;
43
+ });
44
+ return names;
45
+ }
46
+
47
+ var inParse = {
48
+ regex: /^(.*)$/,
49
+ fn: function (m) {
50
+ return {
51
+ inDef: splitAndFilterArgs(m[1]),
52
+ };
53
+ }
54
+ };
55
+
56
+ var cbParse = {
57
+ regex: /^\s*(var\s+)?([^:]*)\s*:=\s*([a-zA-Z0-9_\.-]+)\s*\(\s*([^)]*)\)\s*(when\s+([^;]+))?;?\s*$/,
58
+ fn: function (m) {
59
+ var taskDef = {
60
+ type: 'cb',
61
+ f: m[3],
62
+ inDef: (m[4]) ? splitAndFilterArgs(m[4]) : [],
63
+ outDef: (m[2]) ? parse.splitTrimFilterArgs(m[2]) : []
64
+ };
65
+ if (m[6]) taskDef.after = extractNamesFromWhenClause(m[6]);
66
+ return taskDef;
67
+ }
68
+ };
69
+
70
+ var retParse = {
71
+ regex: /^\s*(var\s+)?([^:]*)\s*=\s*([a-zA-Z0-9_\.-]+)\s*\(\s*([^)]*)\)\s*(when\s+([^;]+))?;?\s*$/,
72
+ fn: function (m) {
73
+ var taskDef = {
74
+ type: 'ret',
75
+ f: m[3],
76
+ inDef: (m[4]) ? splitAndFilterArgs(m[4]) : [],
77
+ outDef: (m[2]) ? parse.splitTrimFilterArgs(m[2]) : []
78
+ };
79
+ if (m[6]) taskDef.after = extractNamesFromWhenClause(m[6]);
80
+ return taskDef;
81
+ }
82
+ };
83
+
84
+ var finalCbParse = {
85
+ regex: /^\s*(cb|callback)\s*\((er{0,2}\s*,\s*)?([^)]*)\)\s*;?$/i,
86
+ fn: function (m) {
87
+ return {
88
+ outDef: (m[3]) ? parse.splitTrimFilterArgs(m[3]) : []
89
+ };
90
+ }
91
+ };
92
+
93
+ function parseInParams(str) {
94
+ return parse.parseStr(str, [inParse], INPARAMS_NO_MATCH);
95
+ }
96
+
97
+ function parseTask(str) {
98
+ var result = parse.parseStr(str, [cbParse, retParse], INOUT_PARAMS_NO_MATCH);
99
+ var type = result.type;
100
+ var task = {
101
+ f: result.f,
102
+ a: result.inDef
103
+ };
104
+ task.out = result.outDef;
105
+ task.type = type;
106
+ if (result.after) task.after = result.after;
107
+ return task;
108
+ }
109
+
110
+ function parseOutParams(str) {
111
+ if (!str.trim().length) return { outDef: [] };
112
+ return parse.parseStr(str, [finalCbParse], OUTPARAMS_NO_MATCH);
113
+ }
114
+
115
+ function parseTasks(arr) { return arr.map(parseTask); }
116
+
117
+
118
+ function pcodeDefine(inParamStr, taskStrArr, locals, options) {
119
+ if (!inParamStr) inParamStr = '';
120
+ if (!taskStrArr) taskStrArr = [];
121
+ var outTaskStr = (taskStrArr.length) ? taskStrArr.pop() : '';
122
+ if (!locals) locals = { };
123
+
124
+ var reactFn = core();
125
+ var ast = {
126
+ inParams: parseInParams(inParamStr).inDef,
127
+ tasks: parseTasks(taskStrArr),
128
+ outTask: { a: parseOutParams(outTaskStr).outDef },
129
+ locals: locals
130
+ };
131
+ if (options) Object.keys(options).forEach(function (k) { ast[k] = options[k]; });
132
+ var errors = reactFn.setAndValidateAST(ast);
133
+ if (errors.length) {
134
+ var errorStr = errors.join('\n');
135
+ throw new Error(errorStr);
136
+ }
137
+ return reactFn;
138
+ }
139
+
140
+ function selectFirst(inParamStr, taskStrArr, locals, options) {
141
+ if (!inParamStr) inParamStr = '';
142
+ if (!taskStrArr) taskStrArr = [];
143
+ var outTaskStr = (taskStrArr.length) ? taskStrArr.pop() : '';
144
+ if (!locals) locals = { };
145
+ var tasks = tutil.serializeTasks(parseTasks(taskStrArr));
146
+
147
+ var reactFn = core();
148
+ var ast = {
149
+ inParams: parseInParams(inParamStr).inDef,
150
+ tasks: tasks,
151
+ outTask: { type: 'finalcbFirst', a: parseOutParams(outTaskStr).outDef },
152
+ locals: locals
153
+ };
154
+ if (options) Object.keys(options).forEach(function (k) { ast[k] = options[k]; });
155
+ var errors = reactFn.setAndValidateAST(ast);
156
+ if (errors.length) {
157
+ var errorStr = errors.join('\n');
158
+ throw new Error(errorStr);
159
+ }
160
+ return reactFn;
161
+ }
162
+
163
+ module.exports = pcodeDefine;
164
+ module.exports.selectFirst = selectFirst;