goodguide-gibbon 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 26638ccdac2b7fd84c9e103ae7943f2c7f9db804
4
+ data.tar.gz: 46759bac41cb0d02ef3d080e4bf22d9b0d0ea034
5
+ SHA512:
6
+ metadata.gz: 84699372110c0383dab2c46d753e29abe7f02e1385952b3fadb07182439828333057ad1bbbce838ee3d391f80aadf9fa1bfc39e78fe3d9d85108036daeca0fd5
7
+ data.tar.gz: c52e4ebea106a7194bd4e445da5521e6ff062f8bbfb1c40f2af9661786d1acf509a8191274acdc7b2baebbb9f2896070a2d1daa4a129f41a5ce057ba65cd46e6
@@ -1,7 +1,7 @@
1
1
  module GoodGuide
2
2
  module Gibbon
3
3
  def self.version
4
- '0.6.3'
4
+ '0.6.4'
5
5
  end
6
6
  end
7
7
  end
@@ -100,7 +100,43 @@ Parsimmon.Parser = P(function(_, _super, Parser) {
100
100
  // construct your Parser from the base parsers and the
101
101
  // parser combinator methods.
102
102
 
103
- function parseError(stream, i, expected) {
103
+ function makeSuccess(index, value) {
104
+ return {
105
+ status: true,
106
+ index: index,
107
+ value: value,
108
+ furthest: -1,
109
+ expected: ''
110
+ };
111
+ }
112
+
113
+ function makeFailure(index, expected) {
114
+ return {
115
+ status: false,
116
+ index: -1,
117
+ value: null,
118
+ furthest: index,
119
+ expected: expected
120
+ };
121
+ }
122
+
123
+ function furthestBacktrackFor(result, last) {
124
+ if (!last) return result;
125
+ if (result.furthest >= last.furthest) return result;
126
+
127
+ return {
128
+ status: result.status,
129
+ index: result.index,
130
+ value: result.value,
131
+ furthest: last.furthest,
132
+ expected: last.expected
133
+ }
134
+ }
135
+
136
+ function parseError(stream, result) {
137
+ var expected = result.expected;
138
+ var i = result.furthest;
139
+
104
140
  if (i === stream.length) {
105
141
  var message = 'expected ' + expected + ', got the end of the string';
106
142
  }
@@ -116,54 +152,32 @@ Parsimmon.Parser = P(function(_, _super, Parser) {
116
152
  _.init = function(body) { this._ = body; };
117
153
 
118
154
  _.parse = function(stream) {
119
- return this.skip(eof)._(stream, 0, success, parseError);
155
+ var result = this.skip(eof)._(stream, 0);
120
156
 
121
- function success(stream, i, result) { return result; }
157
+ return result.status ? result.value : parseError(stream, result);
122
158
  };
123
159
 
124
- function furthestFailure(onFailure, myI, myExpected) {
125
- return function(stream, yourI, yourExpected) {
126
- if (myI > yourI) return onFailure(stream, myI, myExpected);
127
- else return onFailure.apply(this, arguments);
128
- };
129
- }
130
-
131
- function furthestFailureSuccess(onSuccess, myFurthestFailureI, myFurthestExpected) {
132
- return function(stream, i, result, yourFurthestFailureI, yourFurthestExpected) {
133
- if (myFurthestFailureI > yourFurthestFailureI) {
134
- return onSuccess(stream, i, result, myFurthestFailureI, myFurthestExpected);
135
- }
136
- else return onSuccess.apply(this, arguments);
137
- };
138
- }
139
-
140
160
  // -*- primitive combinators -*- //
141
161
  _.or = function(alternative) {
142
162
  var self = this;
143
163
 
144
- return Parser(function(stream, i, onSuccess, onFailure) {
145
- return self._(stream, i, onSuccess, failure);
164
+ return Parser(function(stream, i) {
165
+ var result = self._(stream, i);
146
166
 
147
- function failure(stream, newI, expected) {
148
- var altSuccess = furthestFailureSuccess(onSuccess, newI, expected);
149
- var altFailure = furthestFailure(onFailure, newI, expected);
150
- return alternative._(stream, i, altSuccess, altFailure);
151
- }
167
+ return result.status ? result : furthestBacktrackFor(alternative._(stream, i), result);
152
168
  });
153
169
  };
154
170
 
155
171
  _.then = function(next) {
156
172
  var self = this;
157
173
 
158
- return Parser(function(stream, i, onSuccess, onFailure) {
159
- return self._(stream, i, success, onFailure);
174
+ return Parser(function(stream, i) {
175
+ var result = self._(stream, i);
160
176
 
161
- function success(stream, newI, result, furthestFailureI, furthestExpected) {
162
- var nextParser = (next instanceof Parser ? next : next(result));
163
- var nextSuccess = furthestFailureSuccess(onSuccess, furthestFailureI, furthestExpected);
164
- var nextFailure = furthestFailure(onFailure, furthestFailureI, furthestExpected);
165
- return nextParser._(stream, newI, nextSuccess, nextFailure);
166
- }
177
+ if (!result.status) return result;
178
+
179
+ var nextParser = (next instanceof Parser ? next : next(result.value));
180
+ return furthestBacktrackFor(nextParser._(stream, result.index), result);
167
181
  });
168
182
  };
169
183
 
@@ -184,26 +198,21 @@ Parsimmon.Parser = P(function(_, _super, Parser) {
184
198
  _.many = function() {
185
199
  var self = this;
186
200
 
187
- return Parser(function(stream, i, onSuccess, onFailure) {
188
- var xs = [];
189
- while (self._(stream, i, success, failure));
190
- var furthestFailureI, furthestExpected;
191
- return onSuccess(stream, i, xs, furthestFailureI, furthestExpected);
192
-
193
- function success(stream, newI, x, successFurthestFailureI, successFurthestExpected) {
194
- i = newI;
195
- xs.push(x);
196
- furthestFailureI = successFurthestFailureI;
197
- furthestExpected = successFurthestExpected;
198
- return true;
199
- }
201
+ return Parser(function(stream, i) {
202
+ var accum = [];
203
+ var result;
204
+ var prevResult;
205
+
206
+ for (;;) {
207
+ result = furthestBacktrackFor(self._(stream, i), result);
200
208
 
201
- function failure(stream, newI, expected) {
202
- if (!(furthestFailureI > newI)) {
203
- furthestFailureI = newI;
204
- furthestExpected = expected;
209
+ if (result.status) {
210
+ i = result.index;
211
+ accum.push(result.value);
212
+ }
213
+ else {
214
+ return furthestBacktrackFor(makeSuccess(i, accum), result);
205
215
  }
206
- return false;
207
216
  }
208
217
  });
209
218
  };
@@ -232,37 +241,37 @@ Parsimmon.Parser = P(function(_, _super, Parser) {
232
241
  if (arguments.length < 2) max = min;
233
242
  var self = this;
234
243
 
235
- return Parser(function(stream, i, onSuccess, onFailure) {
236
- var xs = [];
237
- var result = true;
238
- var furthestFailureI, furthestExpected;
244
+ return Parser(function(stream, i) {
245
+ var accum = [];
246
+ var start = i;
247
+ var result;
248
+ var prevResult;
239
249
 
240
250
  for (var times = 0; times < min; times += 1) {
241
- result = self._(stream, i, success, failure);
242
- if (!result) return onFailure(stream, furthestFailureI, furthestExpected);
251
+ result = self._(stream, i);
252
+ prevResult = furthestBacktrackFor(result, prevResult);
253
+ if (result.status) {
254
+ i = result.index;
255
+ accum.push(result.value);
256
+ }
257
+ else {
258
+ return prevResult;
259
+ }
243
260
  }
244
261
 
245
262
  for (; times < max && result; times += 1) {
246
- result = self._(stream, i, success, failure);
247
- }
248
-
249
- return onSuccess(stream, i, xs, furthestFailureI, furthestExpected);
250
-
251
- function success(stream, newI, x, successFurthestFailureI, successFurthestExpected) {
252
- i = newI;
253
- xs.push(x);
254
- furthestFailureI = successFurthestFailureI;
255
- furthestExpected = successFurthestExpected;
256
- return true;
257
- }
258
-
259
- function failure(stream, newI, expected) {
260
- if (!(furthestFailureI > newI)) {
261
- furthestFailureI = newI;
262
- furthestExpected = expected;
263
+ result = self._(stream, i);
264
+ prevResult = furthestBacktrackFor(result, prevResult);
265
+ if (result.status) {
266
+ i = result.index;
267
+ accum.push(result.value);
268
+ }
269
+ else {
270
+ break;
263
271
  }
264
- return false;
265
272
  }
273
+
274
+ return furthestBacktrackFor(makeSuccess(i, accum), prevResult);
266
275
  });
267
276
  };
268
277
 
@@ -271,19 +280,28 @@ Parsimmon.Parser = P(function(_, _super, Parser) {
271
280
  _.atMost = function(n) { return this.times(0, n); };
272
281
  _.atLeast = function(n) {
273
282
  var self = this;
274
- return self.times(n).then(function(start) {
275
- return self.many().map(function(end) {
276
- return start.concat(end);
277
- });
283
+ return seq([this.times(n), this.many()]).map(function(results) {
284
+ return results[0].concat(results[1]);
278
285
  });
279
286
  };
280
287
 
281
288
  _.map = function(fn) {
282
- return this.then(function(result) { return succeed(fn(result)); });
289
+ var self = this;
290
+ return Parser(function(stream, i) {
291
+ var result = self._(stream, i);
292
+ if (!result.status) return result;
293
+ return furthestBacktrackFor(makeSuccess(result.index, fn(result.value)), result);
294
+ });
295
+ };
296
+
297
+ _.skip = function(next) {
298
+ return seq([this, next]).map(function(results) { return results[0]; });
283
299
  };
284
300
 
285
- _.skip = function(two) {
286
- return this.then(function(result) { return two.result(result); });
301
+ _.mark = function() {
302
+ return seq([index, this, index]).map(function(results) {
303
+ return { start: results[0], value: results[1], end: results[2] };
304
+ });
287
305
  };
288
306
 
289
307
  // -*- primitive parsers -*- //
@@ -291,70 +309,113 @@ Parsimmon.Parser = P(function(_, _super, Parser) {
291
309
  var len = str.length;
292
310
  var expected = "'"+str+"'";
293
311
 
294
- return Parser(function(stream, i, onSuccess, onFailure) {
312
+ return Parser(function(stream, i) {
295
313
  var head = stream.slice(i, i+len);
296
314
 
297
315
  if (head === str) {
298
- return onSuccess(stream, i+len, head, -1);
316
+ return makeSuccess(i+len, head);
299
317
  }
300
318
  else {
301
- return onFailure(stream, i, expected);
319
+ return makeFailure(i, expected);
302
320
  }
303
321
  });
304
322
  };
305
323
 
306
324
  var regex = Parsimmon.regex = function(re) {
307
- if (re.source[0] !== '^') throw 'regex '+re+' must be anchored';
308
-
309
- var expected = ''+re;
325
+ var anchored = RegExp('^(?:'+re.source+')', (''+re).slice((''+re).lastIndexOf('/')+1));
310
326
 
311
- return Parser(function(stream, i, onSuccess, onFailure) {
312
- var match = re.exec(stream.slice(i));
327
+ return Parser(function(stream, i) {
328
+ var match = anchored.exec(stream.slice(i));
313
329
 
314
330
  if (match) {
315
331
  var result = match[0];
316
- return onSuccess(stream, i+result.length, result, -1);
332
+ return makeSuccess(i+result.length, result);
317
333
  }
318
334
  else {
319
- return onFailure(stream, i, expected);
335
+ return makeFailure(i, re);
320
336
  }
321
337
  });
322
338
  };
323
339
 
324
- var succeed = Parsimmon.succeed = function(result) {
325
- return Parser(function(stream, i, onSuccess) {
326
- return onSuccess(stream, i, result);
340
+ var succeed = Parsimmon.succeed = function(value) {
341
+ return Parser(function(stream, i) {
342
+ return makeSuccess(i, value);
327
343
  });
328
344
  };
329
345
 
330
346
  var fail = Parsimmon.fail = function(expected) {
331
- return Parser(function(stream, i, _, onFailure) {
332
- return onFailure(stream, i, expected);
333
- });
347
+ return Parser(function(stream, i) { return makeFailure(i, expected); });
334
348
  };
335
349
 
336
- var letter = Parsimmon.letter = regex(/^[a-z]/i);
337
- var letters = Parsimmon.letters = regex(/^[a-z]*/i);
338
- var digit = Parsimmon.digit = regex(/^[0-9]/);
339
- var digits = Parsimmon.digits = regex(/^[0-9]*/);
340
- var whitespace = Parsimmon.whitespace = regex(/^\s+/);
341
- var optWhitespace = Parsimmon.optWhitespace = regex(/^\s*/);
350
+ var letter = Parsimmon.letter = regex(/[a-z]/i);
351
+ var letters = Parsimmon.letters = regex(/[a-z]*/i);
352
+ var digit = Parsimmon.digit = regex(/[0-9]/);
353
+ var digits = Parsimmon.digits = regex(/[0-9]*/);
354
+ var whitespace = Parsimmon.whitespace = regex(/\s+/);
355
+ var optWhitespace = Parsimmon.optWhitespace = regex(/\s*/);
342
356
 
343
- var any = Parsimmon.any = Parser(function(stream, i, onSuccess, onFailure) {
344
- if (i >= stream.length) return onFailure(stream, i, 'any character');
357
+ var any = Parsimmon.any = Parser(function(stream, i) {
358
+ if (i >= stream.length) return makeFailure(i, 'any character');
345
359
 
346
- return onSuccess(stream, i+1, stream.charAt(i), -1);
360
+ return makeSuccess(i+1, stream.charAt(i));
347
361
  });
348
362
 
349
- var all = Parsimmon.all = Parser(function(stream, i, onSuccess, onFailure) {
350
- return onSuccess(stream, stream.length, stream.slice(i), -1);
363
+ var all = Parsimmon.all = Parser(function(stream, i) {
364
+ return makeSuccess(stream.length, stream.slice(i));
351
365
  });
352
366
 
353
- var eof = Parsimmon.eof = Parser(function(stream, i, onSuccess, onFailure) {
354
- if (i < stream.length) return onFailure(stream, i, 'EOF');
367
+ var eof = Parsimmon.eof = Parser(function(stream, i) {
368
+ if (i < stream.length) return makeFailure(i, 'EOF');
355
369
 
356
- return onSuccess(stream, i, '', -1);
370
+ return makeSuccess(i, null);
357
371
  });
372
+
373
+ var lazy = Parsimmon.lazy = function(f) {
374
+ var parser = Parser(function(stream, i) {
375
+ parser._ = f()._;
376
+ return parser._(stream, i);
377
+ });
378
+
379
+ return parser;
380
+ };
381
+
382
+ // [Parser a] -> Parser [a]
383
+ var seq = Parsimmon.seq = function(parsers) {
384
+ return Parser(function(stream, i) {
385
+ var result;
386
+ var accum = new Array(parsers.length);
387
+
388
+ for (var j = 0; j < parsers.length; j += 1) {
389
+ result = furthestBacktrackFor(parsers[j]._(stream, i), result);
390
+ if (!result.status) return result;
391
+ accum[j] = result.value
392
+ i = result.index;
393
+ }
394
+
395
+ return furthestBacktrackFor(makeSuccess(i, accum), result);
396
+ });
397
+ }
398
+
399
+ var index = Parsimmon.index = Parser(function(stream, i) {
400
+ return makeSuccess(i, i);
401
+ });
402
+
403
+ //- fantasyland compat
404
+
405
+ //- Semigroup
406
+ _.concat = _.then;
407
+
408
+ //- Applicative
409
+ _.of = Parser.of = Parsimmon.of = succeed
410
+
411
+ _.ap = function(other) {
412
+ return seq([this, other]).map(function(results) {
413
+ return results[0](results[1]);
414
+ });
415
+ };
416
+
417
+ //- Monad
418
+ _.chain = _.then;
358
419
  });
359
420
  return Parsimmon;
360
421
  })()
@@ -1033,22 +1094,22 @@ Gibbon.AST = AST = (function(_super) {
1033
1094
  }
1034
1095
 
1035
1096
  AST.variants({
1036
- integer: ['value'],
1037
- decimal: ['value'],
1038
- percent: ['value'],
1039
- fraction: ['numerator', 'denominator'],
1040
- string: ['value'],
1041
- subst: ['flow'],
1042
- block: ['flow'],
1043
- list: ['elements', 'squish'],
1044
- defaulted: ['body', 'alternative'],
1045
- query: ['type', 'args'],
1046
- func: ['name', 'args'],
1047
- pair: ['first', 'second'],
1048
- flow: ['head', 'tail'],
1049
- metadata: ['key', 'text'],
1050
- definition: ['metadata', 'name', 'frame'],
1051
- frame: ['definitions', 'flow']
1097
+ integer: ['loc', 'value'],
1098
+ decimal: ['loc', 'value'],
1099
+ percent: ['loc', 'value'],
1100
+ fraction: ['loc', 'numerator', 'denominator'],
1101
+ string: ['loc', 'value'],
1102
+ subst: ['loc', 'flow'],
1103
+ block: ['loc', 'flow'],
1104
+ list: ['loc', 'elements', 'squish'],
1105
+ defaulted: ['loc', 'body', 'alternative'],
1106
+ query: ['loc', 'type', 'args'],
1107
+ func: ['loc', 'name', 'args'],
1108
+ pair: ['loc', 'first', 'second'],
1109
+ flow: ['loc', 'head', 'tail'],
1110
+ metadata: ['loc', 'key', 'text'],
1111
+ definition: ['loc', 'metadata', 'name', 'frame'],
1112
+ frame: ['loc', 'definitions', 'flow']
1052
1113
  });
1053
1114
 
1054
1115
  inspectDefinitions = function(defs) {
@@ -1063,34 +1124,34 @@ Gibbon.AST = AST = (function(_super) {
1063
1124
  };
1064
1125
 
1065
1126
  AST.prototype.inspect = function() {
1066
- var id;
1067
- id = function(x) {
1127
+ var useValue;
1128
+ useValue = function(_, x) {
1068
1129
  return x;
1069
1130
  };
1070
1131
  return this.cases({
1071
- integer: id,
1072
- decimal: id,
1073
- percent: id,
1074
- fraction: function(num, denom) {
1132
+ integer: useValue,
1133
+ decimal: useValue,
1134
+ percent: useValue,
1135
+ fraction: function(_, num, denom) {
1075
1136
  return "" + num + "/" + denom;
1076
1137
  },
1077
- string: function(s) {
1138
+ string: function(_, s) {
1078
1139
  return "'" + s + "'";
1079
1140
  },
1080
- query: function(query, args) {
1141
+ query: function(_, query, args) {
1081
1142
  if (query === 'access') {
1082
1143
  return "@" + args[0];
1083
1144
  } else {
1084
1145
  return "." + query + " " + (args.join(' '));
1085
1146
  }
1086
1147
  },
1087
- subst: function(flow) {
1148
+ subst: function(_, flow) {
1088
1149
  return "(" + (flow.inspect()) + ")";
1089
1150
  },
1090
- block: function(flow) {
1151
+ block: function(_, flow) {
1091
1152
  return "{ " + (flow.inspect()) + " }";
1092
1153
  },
1093
- list: function(els, squish) {
1154
+ list: function(_, els, squish) {
1094
1155
  var close, el, open;
1095
1156
  open = squish ? '[*' : '[';
1096
1157
  close = squish ? '*]' : ']';
@@ -1104,10 +1165,10 @@ Gibbon.AST = AST = (function(_super) {
1104
1165
  return _results;
1105
1166
  })()).join(', ')) + " " + close;
1106
1167
  },
1107
- defaulted: function(body, alt) {
1168
+ defaulted: function(_, body, alt) {
1108
1169
  return "" + (body.inspect()) + " | " + (alt.inspect());
1109
1170
  },
1110
- func: function(name, args) {
1171
+ func: function(_, name, args) {
1111
1172
  var arg;
1112
1173
  args = (function() {
1113
1174
  var _i, _len, _results;
@@ -1120,10 +1181,10 @@ Gibbon.AST = AST = (function(_super) {
1120
1181
  })();
1121
1182
  return "" + name + " " + (args.join(' '));
1122
1183
  },
1123
- pair: function(first, second) {
1184
+ pair: function(_, first, second) {
1124
1185
  return "" + (first.inspect()) + " : " + (second.inspect());
1125
1186
  },
1126
- flow: function(head, tail) {
1187
+ flow: function(_, head, tail) {
1127
1188
  if (tail) {
1128
1189
  tail = "" + (tail.inspect()) + " -> ";
1129
1190
  } else {
@@ -1131,10 +1192,10 @@ Gibbon.AST = AST = (function(_super) {
1131
1192
  }
1132
1193
  return "" + tail + (head.inspect());
1133
1194
  },
1134
- metadata: function(key, text) {
1195
+ metadata: function(_, key, text) {
1135
1196
  return "" + key + ": " + text;
1136
1197
  },
1137
- definition: function(metadata, name, frame) {
1198
+ definition: function(_, metadata, name, frame) {
1138
1199
  var m, out, _i, _len;
1139
1200
  out = [];
1140
1201
  for (_i = 0, _len = metadata.length; _i < _len; _i++) {
@@ -1146,7 +1207,7 @@ Gibbon.AST = AST = (function(_super) {
1146
1207
  out.push(frame.inspect());
1147
1208
  return out.join('');
1148
1209
  },
1149
- frame: function(definitions, flow) {
1210
+ frame: function(_, definitions, flow) {
1150
1211
  var out;
1151
1212
  out = [];
1152
1213
  out.push("(");
@@ -1173,7 +1234,6 @@ Gibbon.TypeAST = TypeAST = (function(_super) {
1173
1234
  TypeAST.variants({
1174
1235
  concrete: ['name'],
1175
1236
  variable: ['name'],
1176
- "native": ['id'],
1177
1237
  wildcard: [],
1178
1238
  list: ['of'],
1179
1239
  func: ['input', 'args', 'output'],
@@ -1186,37 +1246,58 @@ Gibbon.TypeAST = TypeAST = (function(_super) {
1186
1246
  return parse.type(str);
1187
1247
  };
1188
1248
 
1189
- TypeAST.parseUnit = function(str) {
1190
- return parse.unitType(str);
1191
- };
1192
-
1193
1249
  return TypeAST;
1194
1250
 
1195
1251
  })(Variant);
1196
1252
 
1197
1253
  parse = Gibbon.parse = (function() {
1198
- var accessor, accessorExpr, arrow, arrowType, assertString, bang, blankLines, blockExpr, blockType, comma, commaSepFlows, comment, component, concrete, decimal, decimalExpr, defaulted, define, definition, expr, fail, flow, fraction, fractionExpr, frame, freeFrame, fullSignature, func, funcPlaceholder, identifier, innerFrame, integer, integerExpr, isString, label, labelVal, lbrace, lbrack, lexeme, lines, listExpr, listType, lparen, lsplat, metadata, multiline, name, nativeId, nativeType, nonDefaultedFlow, nonPairedFlow, numericExpr, pair, parenFlow, parenFrame, parenType, percent, percentExpr, program, query, queryArg, queryExpr, rbrace, rbrack, regex, rparen, rsplat, signature, simpleType, singletonFlow, squishListExpr, str, string, stringExpr, substExpr, succeed, tag, tassign, type, typeVar, variable, whitespace, wildType, wildcard;
1254
+ var accessor, accessorExpr, arrow, arrowType, assertString, blankLines, blockExpr, blockType, comma, commaSepFlows, comment, component, concrete, decimal, decimalExpr, defaulted, define, definition, expr, fail, flow, fraction, fractionExpr, frame, freeFrame, fullSignature, func, funcPlaceholder, identifier, innerFrame, integer, integerExpr, isString, label, labelVal, lazy, lbrace, lbrack, lexeme, lines, listExpr, listType, lparen, lsplat, metadata, multiline, name, nonDefaultedFlow, nonPairedFlow, numericExpr, opt, pair, parenFlow, parenFrame, parenType, percent, percentExpr, program, query, queryArg, queryExpr, rbrace, rbrack, regex, rparen, rsplat, seq, signature, simpleType, singletonFlow, spanLoc, squishListExpr, str, string, stringExpr, substExpr, succeed, tag, tassign, type, typeVar, variable, whitespace, wildType, wildcard, withLoc,
1255
+ _this = this;
1199
1256
  tag = function(name, parser) {
1200
- return parser.tag(name);
1257
+ return Parsimmon.Parser(function(stream, i) {
1258
+ var result;
1259
+ result = parser._(stream, i);
1260
+ if (!result.status) {
1261
+ result.expected = name;
1262
+ }
1263
+ return result;
1264
+ });
1201
1265
  };
1202
- Parsimmon.Parser.prototype.tag = function(name) {
1203
- var _this = this;
1204
- return Parsimmon.Parser(function(stream, i, onSuccess, onFailure) {
1205
- return _this._(stream, i, onSuccess, function(stream, newI, expected) {
1206
- return onFailure(stream, newI, name);
1207
- });
1266
+ Parsimmon.Parser.prototype.tryChain = function(f) {
1267
+ return this.chain(function(res) {
1268
+ return f(res).or(succeed(res));
1208
1269
  });
1209
1270
  };
1210
1271
  string = Parsimmon.string, regex = Parsimmon.regex, succeed = Parsimmon.succeed, fail = Parsimmon.fail;
1272
+ seq = Parsimmon.seq, lazy = Parsimmon.lazy;
1211
1273
  whitespace = regex(/^[ \t]*/);
1212
1274
  blankLines = regex(/^[\n\s]+/);
1213
1275
  comment = regex(/^#.*?(\n|$)/);
1214
1276
  lines = (blankLines.or(comment)).many();
1215
1277
  lexeme = function(p) {
1216
- return p.skip(whitespace);
1278
+ return p.mark().skip(whitespace);
1217
1279
  };
1218
1280
  multiline = function(p) {
1219
- return p.skip(lines);
1281
+ return p.mark().skip(lines);
1282
+ };
1283
+ opt = function(p) {
1284
+ return p.or(succeed(null));
1285
+ };
1286
+ withLoc = function(p, f) {
1287
+ return p.map(function(_arg) {
1288
+ var end, start, value;
1289
+ start = _arg.start, value = _arg.value, end = _arg.end;
1290
+ return f({
1291
+ start: start,
1292
+ end: end
1293
+ }, value);
1294
+ });
1295
+ };
1296
+ spanLoc = function(l, r) {
1297
+ return {
1298
+ start: l.start,
1299
+ end: r.end
1300
+ };
1220
1301
  };
1221
1302
  identifier = tag('an identifier', regex(/^[a-z][\w-]*[?]?/i));
1222
1303
  arrow = multiline(string('->'));
@@ -1228,7 +1309,7 @@ parse = Gibbon.parse = (function() {
1228
1309
  rbrack = lexeme(string(']'));
1229
1310
  lparen = multiline(string('('));
1230
1311
  rparen = lexeme(string(')'));
1231
- comma = lexeme(string(','));
1312
+ comma = multiline(string(','));
1232
1313
  defaulted = multiline(string('|'));
1233
1314
  lsplat = multiline(string('[*'));
1234
1315
  rsplat = lexeme(string('*]'));
@@ -1246,154 +1327,187 @@ parse = Gibbon.parse = (function() {
1246
1327
  variable = lexeme(string('%').then(identifier));
1247
1328
  wildcard = lexeme(string('%'));
1248
1329
  funcPlaceholder = lexeme(string('&'));
1249
- integerExpr = integer.map(function(i) {
1250
- return AST.integer(parseInt(i));
1330
+ integerExpr = withLoc(integer, function(loc, i) {
1331
+ return AST.integer(loc, parseInt(i));
1251
1332
  });
1252
- decimalExpr = decimal.map(function(d) {
1253
- return AST.decimal(parseFloat(d));
1333
+ decimalExpr = withLoc(decimal, function(loc, d) {
1334
+ return AST.decimal(loc, parseFloat(d));
1254
1335
  });
1255
- percentExpr = percent.map(function(p) {
1256
- return AST.percent(parseInt(p));
1336
+ percentExpr = withLoc(percent, function(loc, p) {
1337
+ return AST.percent(loc, parseInt(p));
1257
1338
  });
1258
- fractionExpr = fraction.map(function(f) {
1339
+ fractionExpr = withLoc(fraction, function(loc, f) {
1259
1340
  var denom, num, _ref5;
1260
1341
  _ref5 = f.split('/'), num = _ref5[0], denom = _ref5[1];
1261
- return AST.fraction(num, denom);
1342
+ return AST.fraction(loc, num, denom);
1262
1343
  });
1263
- stringExpr = str.map(function(s) {
1264
- return AST.string(s);
1344
+ stringExpr = withLoc(str, function(loc, s) {
1345
+ return AST.string(loc, s);
1265
1346
  });
1266
- accessorExpr = accessor.map(function(name) {
1267
- return AST.query('access', [name]);
1347
+ accessorExpr = withLoc(accessor, function(loc, name) {
1348
+ return AST.query(loc, 'access', [name]);
1268
1349
  });
1269
- queryExpr = query.then(function(q) {
1270
- return queryArg.many().map(function(args) {
1271
- return AST.query(q, args);
1272
- });
1350
+ queryExpr = seq([query, queryArg.many()]).map(function(_arg) {
1351
+ var a, args, loc, q, _ref5;
1352
+ q = _arg[0], args = _arg[1];
1353
+ loc = spanLoc(q, ((_ref5 = args[args.length - 1]) != null ? _ref5.end : void 0) || q);
1354
+ return AST.query(loc, q.value, (function() {
1355
+ var _i, _len, _results;
1356
+ _results = [];
1357
+ for (_i = 0, _len = args.length; _i < _len; _i++) {
1358
+ a = args[_i];
1359
+ _results.push(a.value);
1360
+ }
1361
+ return _results;
1362
+ })());
1273
1363
  });
1274
1364
  numericExpr = percentExpr.or(decimalExpr.or(fractionExpr.or(integerExpr)));
1275
- parenFlow = lparen.then(function() {
1276
- return flow.skip(rparen);
1365
+ parenFlow = lazy(function() {
1366
+ return lparen.then(flow).skip(rparen);
1367
+ });
1368
+ substExpr = lazy(function() {
1369
+ return seq([lparen, flow, rparen]).map(function(_arg) {
1370
+ var fl, l, r;
1371
+ l = _arg[0], fl = _arg[1], r = _arg[2];
1372
+ return AST.subst(spanLoc(l, r), fl);
1373
+ });
1277
1374
  });
1278
- substExpr = parenFlow.map(function(fl) {
1279
- return AST.subst(fl);
1375
+ listExpr = lazy(function() {
1376
+ return seq([lbrack, commaSepFlows, rbrack]).map(function(_arg) {
1377
+ var els, l, r;
1378
+ l = _arg[0], els = _arg[1], r = _arg[2];
1379
+ return AST.list(spanLoc(l, r), els, false);
1380
+ });
1280
1381
  });
1281
- listExpr = lbrack.then(function() {
1282
- return commaSepFlows.then(function(els) {
1283
- return rbrack.result(AST.list(els, false));
1382
+ squishListExpr = lazy(function() {
1383
+ return seq([lsplat, commaSepFlows, rsplat]).map(function(_arg) {
1384
+ var els, l, r;
1385
+ l = _arg[0], els = _arg[1], r = _arg[2];
1386
+ return AST.list(spanLoc(l, r), els, true);
1284
1387
  });
1285
1388
  });
1286
- squishListExpr = lsplat.then(function() {
1287
- return commaSepFlows.then(function(els) {
1288
- return rsplat.result(AST.list(els, true));
1389
+ blockExpr = lazy(function() {
1390
+ return seq([lbrace, flow, rbrace]).map(function(_arg) {
1391
+ var flow, l, r;
1392
+ l = _arg[0], flow = _arg[1], r = _arg[2];
1393
+ return AST.block(spanLoc(l, r), flow);
1289
1394
  });
1290
1395
  });
1291
- blockExpr = lbrace.then(function() {
1292
- return flow.skip(rbrace);
1293
- }).map(AST.block);
1294
1396
  expr = tag('an expr', queryExpr.or(accessorExpr.or(substExpr.or(squishListExpr.or(listExpr.or(stringExpr.or(blockExpr.or(numericExpr))))))));
1295
1397
  singletonFlow = expr.map(function(e) {
1296
- return AST.flow(e, null);
1398
+ return AST.flow(e.loc, e, null);
1297
1399
  });
1298
- func = name.then(function(funcName) {
1299
- return parenFlow.or(singletonFlow).many().map(function(args) {
1300
- return AST.func(funcName, args);
1301
- });
1400
+ func = seq([name, parenFlow.or(singletonFlow).many()]).map(function(_arg) {
1401
+ var args, loc, name;
1402
+ name = _arg[0], args = _arg[1];
1403
+ loc = {
1404
+ start: name.start,
1405
+ end: name.end
1406
+ };
1407
+ if (args.length) {
1408
+ loc.end = args[args.length - 1].loc.end;
1409
+ }
1410
+ return AST.func(loc, name.value, args);
1302
1411
  });
1303
- component = multiline(expr.or(func));
1304
- nonPairedFlow = component.then(function(first) {
1305
- return arrow.then(component).many().map(function(rest) {
1306
- var comp, cursor, _i, _len;
1307
- cursor = AST.flow(first, null);
1308
- for (_i = 0, _len = rest.length; _i < _len; _i++) {
1309
- comp = rest[_i];
1310
- cursor = AST.flow(comp, cursor);
1311
- }
1312
- return cursor;
1313
- });
1412
+ component = expr.or(func).skip(lines);
1413
+ nonPairedFlow = seq([component, arrow.then(component).many()]).map(function(_arg) {
1414
+ var comp, cursor, first, rest, _i, _len;
1415
+ first = _arg[0], rest = _arg[1];
1416
+ cursor = AST.flow(first.loc, first, null);
1417
+ for (_i = 0, _len = rest.length; _i < _len; _i++) {
1418
+ comp = rest[_i];
1419
+ cursor = AST.flow(spanLoc(first.loc, comp.loc), comp, cursor);
1420
+ }
1421
+ return cursor;
1314
1422
  });
1315
- nonDefaultedFlow = nonPairedFlow.then(function(first) {
1423
+ nonDefaultedFlow = nonPairedFlow.tryChain(function(first) {
1316
1424
  return pair.then(nonDefaultedFlow).map(function(second) {
1317
- return AST.flow(AST.pair(first, second), null);
1318
- }).or(succeed(first));
1425
+ var loc;
1426
+ loc = spanLoc(first.loc, second.loc);
1427
+ return AST.flow(loc, AST.pair(loc, first, second), null);
1428
+ });
1319
1429
  });
1320
- flow = tag('a flow', nonDefaultedFlow.then(function(body) {
1430
+ flow = tag('a flow', nonDefaultedFlow.tryChain(function(body) {
1321
1431
  return defaulted.then(flow).map(function(alternative) {
1322
- return AST.flow(AST.defaulted(body, alternative), null);
1323
- }).or(succeed(body));
1324
- }));
1325
- commaSepFlows = flow.skip(comma.or(succeed(null)).then(lines)).many().then(function(els) {
1326
- return flow.or(succeed(null)).map(function(final) {
1327
- if (final) {
1328
- els.push(final);
1329
- }
1330
- return els;
1432
+ var loc;
1433
+ loc = spanLoc(body.loc, alternative.loc);
1434
+ return AST.flow(loc, AST.defaulted(loc, body, alternative), null);
1331
1435
  });
1436
+ }));
1437
+ commaSepFlows = seq([flow.skip(seq([opt(comma, lines)])).many(), opt(flow)]).map(function(_arg) {
1438
+ var els, final;
1439
+ els = _arg[0], final = _arg[1];
1440
+ if (final) {
1441
+ els.push(final);
1442
+ }
1443
+ return els;
1332
1444
  });
1333
- metadata = label.then(function(key) {
1334
- return labelVal.map(function(text) {
1335
- return AST.metadata(key, text);
1336
- });
1445
+ metadata = seq([label, labelVal]).map(function(key, text) {
1446
+ return AST.metadata(spanLoc(key, text), key.value, text.value);
1337
1447
  });
1338
- definition = tag('a definition', metadata.many().then(function(md) {
1339
- return name.then(function(n) {
1340
- return define.then(innerFrame).map(function(fl) {
1341
- return AST.definition(md, n, fl);
1342
- });
1343
- });
1344
- }));
1345
- frame = definition.many().then(function(defs) {
1346
- return flow.map(function(fl) {
1347
- return AST.frame(defs, fl);
1448
+ definition = lazy(function() {
1449
+ return seq([metadata.many(), name, define.then(innerFrame)]).map(function(_arg) {
1450
+ var fl, loc, md, n, _ref5;
1451
+ md = _arg[0], n = _arg[1], fl = _arg[2];
1452
+ loc = spanLoc(((_ref5 = md[0]) != null ? _ref5.loc : void 0) || n, fl);
1453
+ return AST.definition(loc, md, n.value, fl);
1348
1454
  });
1349
1455
  });
1350
- parenFrame = lparen.then(frame).skip(rparen.then(lines));
1456
+ frame = seq([definition.many(), flow]).map(function(_arg) {
1457
+ var defs, flow, loc;
1458
+ defs = _arg[0], flow = _arg[1];
1459
+ loc = spanLoc((defs[0] || flow).loc, flow.loc);
1460
+ return AST.frame(loc, defs, flow);
1461
+ });
1462
+ parenFrame = seq([lparen, frame, rparen, lines]).map(function(_arg) {
1463
+ var fr, l, r, _;
1464
+ l = _arg[0], fr = _arg[1], r = _arg[2], _ = _arg[3];
1465
+ fr.loc = spanLoc(l, r);
1466
+ return fr;
1467
+ });
1351
1468
  freeFrame = flow.map(function(fl) {
1352
- return AST.frame([], fl);
1469
+ return AST.frame(fl.loc, [], fl);
1353
1470
  });
1354
1471
  innerFrame = parenFrame.or(freeFrame);
1355
1472
  program = lines.then(frame);
1356
1473
  tassign = lexeme(string('='));
1357
- bang = lexeme(string('!'));
1358
- nativeId = lexeme(regex(/^\w+/));
1359
1474
  concrete = name.map(function(n) {
1360
- return TypeAST.concrete(n);
1475
+ return TypeAST.concrete(n.value);
1361
1476
  });
1362
1477
  typeVar = variable.map(function(v) {
1363
- return TypeAST.variable(v);
1478
+ return TypeAST.variable(v.value);
1364
1479
  });
1365
1480
  wildType = wildcard.result(TypeAST.wildcard());
1366
- listType = lbrack.then(function() {
1367
- return type.skip(rbrack).map(function(t) {
1481
+ listType = lazy(function() {
1482
+ return seq([lbrack, type, rbrack]).map(function(_arg) {
1483
+ var t, _, __;
1484
+ _ = _arg[0], t = _arg[1], __ = _arg[2];
1368
1485
  return TypeAST.list(t);
1369
1486
  });
1370
1487
  });
1371
- parenType = lparen.then(function() {
1372
- return type.skip(rparen);
1488
+ parenType = lazy(function() {
1489
+ return lparen.then(type).skip(rparen);
1373
1490
  });
1374
- blockType = lbrace.then(function() {
1375
- return arrowType.skip(rbrace).map(function(t) {
1491
+ blockType = lazy(function() {
1492
+ return lbrace.then(arrowType).skip(rbrace).map(function(t) {
1376
1493
  return TypeAST.block(t);
1377
1494
  });
1378
1495
  });
1379
- nativeType = bang.then(nativeId).map(TypeAST["native"]);
1380
- simpleType = typeVar.or(wildType.or(listType.or(parenType.or(blockType.or(concrete.or(nativeType))))));
1381
- type = simpleType.then(function(first) {
1496
+ simpleType = typeVar.or(wildType.or(listType.or(parenType.or(blockType.or(concrete)))));
1497
+ type = simpleType.tryChain(function(first) {
1382
1498
  return pair.then(type).map(function(second) {
1383
1499
  return TypeAST.pair(first, second);
1384
- }).or(succeed(first));
1385
- });
1386
- arrowType = type.then(function(first) {
1387
- return arrow.then(type).map(function(second) {
1388
- return TypeAST.arrow(first, second);
1389
1500
  });
1390
1501
  });
1391
- signature = name.then(function(n) {
1392
- return type.many().then(function(argTypes) {
1393
- return tassign.then(arrowType).map(function(ftype) {
1394
- return TypeAST.func(ftype.from, argTypes, ftype.to);
1395
- });
1396
- });
1502
+ arrowType = seq([type, arrow, type]).map(function(_arg) {
1503
+ var first, second, _;
1504
+ first = _arg[0], _ = _arg[1], second = _arg[2];
1505
+ return TypeAST.arrow(first, second);
1506
+ });
1507
+ signature = seq([name, type.many(), tassign.then(arrowType)]).map(function(_arg) {
1508
+ var argTypes, ftype, name;
1509
+ name = _arg[0], argTypes = _arg[1], ftype = _arg[2];
1510
+ return TypeAST.func(ftype.from, argTypes, ftype.to);
1397
1511
  });
1398
1512
  fullSignature = lines.then(signature);
1399
1513
  isString = function(s) {
@@ -1412,10 +1526,6 @@ parse = Gibbon.parse = (function() {
1412
1526
  assertString(str);
1413
1527
  return fullSignature.parse(str);
1414
1528
  };
1415
- parse.unitType = function(str) {
1416
- assertString(str);
1417
- return type.parse(str);
1418
- };
1419
1529
  return parse;
1420
1530
  })();
1421
1531
 
@@ -1971,12 +2081,12 @@ analyze = Gibbon.analyze = (function() {
1971
2081
  input = flow.tail ? TypeExpr.expr(flow.tail) : global;
1972
2082
  return push(TypeExpr.expr(flow), TypeExpr.query(input, _this, flow.head));
1973
2083
  },
1974
- pair: function(first, second) {
2084
+ pair: function(_, first, second) {
1975
2085
  _this.analyzeFlow(first, global, push);
1976
2086
  _this.analyzeFlow(second, global, push);
1977
2087
  return push(TypeExpr.expr(flow), TypeExpr.param('pair', [TypeExpr.expr(first), TypeExpr.expr(second)]));
1978
2088
  },
1979
- func: function(name, args) {
2089
+ func: function(_, name, args) {
1980
2090
  var arg, ast, func, i, input, scope, _i, _len, _results;
1981
2091
  if (!stdlib.hasOwnProperty(name)) {
1982
2092
  push(TypeExpr.expr(flow.head), TypeExpr.error('func', [flow.head]));
@@ -2010,11 +2120,11 @@ analyze = Gibbon.analyze = (function() {
2010
2120
  string: function() {
2011
2121
  return push(TypeExpr.expr(flow), TypeExpr.param('string', []));
2012
2122
  },
2013
- subst: function(subFlow) {
2123
+ subst: function(_, subFlow) {
2014
2124
  push(TypeExpr.expr(flow), TypeExpr.expr(subFlow));
2015
2125
  return _this.analyzeFlow(subFlow, global, push);
2016
2126
  },
2017
- list: function(elements) {
2127
+ list: function(_, elements) {
2018
2128
  var el, elVar, _i, _len, _results;
2019
2129
  elVar = TypeExpr.variable('el');
2020
2130
  push(TypeExpr.expr(flow), TypeExpr.param('list', [elVar]));
@@ -2026,13 +2136,13 @@ analyze = Gibbon.analyze = (function() {
2026
2136
  }
2027
2137
  return _results;
2028
2138
  },
2029
- block: function(subFlow) {
2139
+ block: function(_, subFlow) {
2030
2140
  var input;
2031
2141
  input = TypeExpr.variable('.input');
2032
2142
  push(TypeExpr.expr(flow), TypeExpr.param('block', [input, TypeExpr.expr(subFlow)]));
2033
2143
  return _this.analyzeFlow(subFlow, input, push);
2034
2144
  },
2035
- defaulted: function(body, alt) {
2145
+ defaulted: function(_, body, alt) {
2036
2146
  push(TypeExpr.expr(body), TypeExpr.expr(alt));
2037
2147
  push(TypeExpr.expr(flow), TypeExpr.expr(alt));
2038
2148
  _this.analyzeFlow(body, global, push);
@@ -2104,7 +2214,7 @@ analyze = Gibbon.analyze = (function() {
2104
2214
 
2105
2215
  })(Variant);
2106
2216
  DEBUG.logConstraint = function(prefix, lhs, rhs) {
2107
- return console.log(prefix, lhs.inspect(), '=', rhs.inspect());
2217
+ return DEBUG.log(prefix, lhs.inspect(), '=', rhs.inspect());
2108
2218
  };
2109
2219
  consume = function(array, next, body) {
2110
2220
  var loop_, push;
@@ -2256,19 +2366,19 @@ analyze = Gibbon.analyze = (function() {
2256
2366
  };
2257
2367
  toSemanticTree = function(expr) {
2258
2368
  return expr.cases({
2259
- frame: function(_, flow) {
2369
+ frame: function(_, __, flow) {
2260
2370
  return Semantic.definition(dependencies, toSemanticTree(flow));
2261
2371
  },
2262
- flow: function(head, tail) {
2372
+ flow: function(_, head, tail) {
2263
2373
  return Semantic.flow(flowType(TypeExpr.expr(this)), toSemanticTree(head), tail && toSemanticTree(tail));
2264
2374
  },
2265
- query: function(type, name) {
2375
+ query: function(_, type, name) {
2266
2376
  if (!(errors.length || semanticAccessors.has(this))) {
2267
2377
  throw "unsolved with no errors!";
2268
2378
  }
2269
2379
  return semanticAccessors.get(this);
2270
2380
  },
2271
- func: function(name, args) {
2381
+ func: function(_, name, args) {
2272
2382
  var a, scope, semArgs, solvedScope;
2273
2383
  scope = this.__scope__;
2274
2384
  solvedScope = new Hash;
@@ -2286,16 +2396,16 @@ analyze = Gibbon.analyze = (function() {
2286
2396
  })();
2287
2397
  return Semantic.func(name, semArgs, solvedScope);
2288
2398
  },
2289
- pair: function(first, second) {
2399
+ pair: function(_, first, second) {
2290
2400
  return Semantic.pair(toSemanticTree(first), toSemanticTree(second));
2291
2401
  },
2292
- block: function(flow) {
2402
+ block: function(_, flow) {
2293
2403
  return Semantic.block(toSemanticTree(flow));
2294
2404
  },
2295
- subst: function(subFlow) {
2405
+ subst: function(_, subFlow) {
2296
2406
  return toSemanticTree(subFlow);
2297
2407
  },
2298
- list: function(elements, squish) {
2408
+ list: function(_, elements, squish) {
2299
2409
  var e;
2300
2410
  return Semantic.list((function() {
2301
2411
  var _i, _len, _results;
@@ -2307,7 +2417,7 @@ analyze = Gibbon.analyze = (function() {
2307
2417
  return _results;
2308
2418
  })(), squish);
2309
2419
  },
2310
- defaulted: function(body, alt) {
2420
+ defaulted: function(_, body, alt) {
2311
2421
  return Semantic.defaulted(toSemanticTree(body), toSemanticTree(alt));
2312
2422
  },
2313
2423
  integer: function() {
@@ -2565,6 +2675,9 @@ Value = Gibbon.Value = Value = (function(_super) {
2565
2675
  }
2566
2676
  return Value.boolean(o);
2567
2677
  },
2678
+ block: function(from, to) {
2679
+ return Value.block(o);
2680
+ },
2568
2681
  other: function() {
2569
2682
  throw "could not return object of type " + (type.inspect());
2570
2683
  }
@@ -3584,7 +3697,6 @@ Gibbon.Core = Core = (function(_super) {
3584
3697
  _ref14 = this.subtrees();
3585
3698
  for (_i = 0, _len = _ref14.length; _i < _len; _i++) {
3586
3699
  subtree = _ref14[_i];
3587
- console.log("checking alwaysSucceeds " + (subtree.inspect()));
3588
3700
  if (!subtree.alwaysSucceeds()) {
3589
3701
  return false;
3590
3702
  }
@@ -3609,6 +3721,9 @@ Gibbon.Core = Core = (function(_super) {
3609
3721
  fail: function() {
3610
3722
  return true;
3611
3723
  },
3724
+ branch: function(ifTrue, ifFalse) {
3725
+ return ifTrue.alwaysFails() && ifFalse.alwaysFails();
3726
+ },
3612
3727
  rescue: function(e, default_) {
3613
3728
  return e.alwaysFails() && default_.alwaysFails();
3614
3729
  },
@@ -3620,7 +3735,6 @@ Gibbon.Core = Core = (function(_super) {
3620
3735
  _ref14 = this.subtrees();
3621
3736
  for (_i = 0, _len = _ref14.length; _i < _len; _i++) {
3622
3737
  subtree = _ref14[_i];
3623
- console.log("checking alwaysFails " + (subtree.inspect()));
3624
3738
  if (subtree.alwaysFails()) {
3625
3739
  return true;
3626
3740
  }
@@ -3755,7 +3869,7 @@ Gibbon.Core = Core = (function(_super) {
3755
3869
  return Core.foldList(f(l), f(o), a, i, aa, f(b));
3756
3870
  },
3757
3871
  mapList: function(l, a, i, b) {
3758
- return Core.mapList(f(l), i, a, f(b));
3872
+ return Core.mapList(f(l), a, i, f(b));
3759
3873
  },
3760
3874
  zipLists: function(l, r) {
3761
3875
  return Core.zipLists(f(l), f(r));
@@ -4433,16 +4547,35 @@ Gibbon.optimize = (function() {
4433
4547
  });
4434
4548
  },
4435
4549
  op2: function(op, left, right) {
4436
- var checkIdent, identFold, l, r, _ref14;
4550
+ var checkConst, checkIdent, identFold, l, r, _ref14;
4437
4551
  left = partialEval(left);
4438
4552
  right = partialEval(right);
4439
- checkIdent = function(opTest, val, ident, identVal) {
4440
- return op === opTest && val._tag === 'constant' && val.value === ident && identVal;
4553
+ checkConst = function(val, f) {
4554
+ return val._tag === 'constant' && f(val.value);
4441
4555
  };
4442
- identFold = checkIdent('*', right, 1, left) || checkIdent('*', left, 1, right) || checkIdent('*', right, 0, Core.constant(0)) || checkIdent('*', left, 0, Core.constant(0)) || checkIdent('+', left, 0, right) || checkIdent('+', right, 0, left) || checkIdent('/', right, 1, left);
4443
- if (identFold) {
4444
- DEBUG.log("identity-folding " + (this.inspect()) + " to " + (identFold.inspect()));
4445
- return identFold;
4556
+ if (op === '>' || op === '<' || op === '>=' || op === '<=') {
4557
+ if (checkConst(left, function(x) {
4558
+ return !isFinite(x);
4559
+ })) {
4560
+ DEBUG.log("reducing comparison with infinite values");
4561
+ right = Core.constant(0);
4562
+ } else if (checkConst(right, function(x) {
4563
+ return !isFinite(x);
4564
+ })) {
4565
+ DEBUG.log("reducing comparison with infinite values");
4566
+ left = Core.constant(0);
4567
+ }
4568
+ } else {
4569
+ checkIdent = function(opTest, val, ident, identVal) {
4570
+ return op === opTest && checkConst(val, function(x) {
4571
+ return x === ident;
4572
+ }) && identVal;
4573
+ };
4574
+ identFold = checkIdent('*', right, 1, left) || checkIdent('*', left, 1, right) || checkIdent('*', right, 0, Core.constant(0)) || checkIdent('*', left, 0, Core.constant(0)) || checkIdent('+', left, 0, right) || checkIdent('+', right, 0, left) || checkIdent('/', right, 1, left);
4575
+ if (identFold) {
4576
+ DEBUG.log("identity-folding " + (this.inspect()) + " to " + (identFold.inspect()));
4577
+ return identFold;
4578
+ }
4446
4579
  }
4447
4580
  if (!(left._tag === 'constant' && right._tag === 'constant')) {
4448
4581
  return Core.op2(op, left, right);
@@ -4476,18 +4609,19 @@ Gibbon.optimize = (function() {
4476
4609
  }).reverse();
4477
4610
  };
4478
4611
  genSubstitutions = function(expr) {
4479
- var newTrace, queue, sub, substitutions, trace, _i, _len, _ref14, _ref15;
4480
- substitutions = new ObjHash;
4612
+ var newTrace, occurrences, queue, sub, substitutions, trace, _i, _len, _ref14, _ref15;
4613
+ occurrences = new ObjHash;
4614
+ substitutions = new Hash;
4481
4615
  queue = [[expr, List.empty()]];
4482
4616
  while (queue.length) {
4483
4617
  _ref14 = queue.shift(), expr = _ref14[0], trace = _ref14[1];
4484
- if (expr.isSimple()) {
4618
+ if (expr.isSimple() || expr.alwaysFails()) {
4485
4619
  continue;
4486
4620
  }
4487
- if (substitutions.has(expr)) {
4488
- substitutions.get(expr).push(makeCrumbs(trace));
4621
+ if (occurrences.has(expr)) {
4622
+ occurrences.get(expr).push(makeCrumbs(trace));
4489
4623
  } else {
4490
- substitutions.set(expr, [makeCrumbs(trace)]);
4624
+ occurrences.set(expr, [makeCrumbs(trace)]);
4491
4625
  newTrace = trace.cons(expr);
4492
4626
  _ref15 = expr.subtrees();
4493
4627
  for (_i = 0, _len = _ref15.length; _i < _len; _i++) {
@@ -4496,6 +4630,17 @@ Gibbon.optimize = (function() {
4496
4630
  }
4497
4631
  }
4498
4632
  }
4633
+ occurrences.each(function(expr, crumbs) {
4634
+ var insertionPoint;
4635
+ if (!(crumbs.length >= 2)) {
4636
+ return;
4637
+ }
4638
+ insertionPoint = findLastCommon(crumbs);
4639
+ substitutions.cache(insertionPoint, function() {
4640
+ return [];
4641
+ });
4642
+ return substitutions.get(insertionPoint).push(expr);
4643
+ });
4499
4644
  return substitutions;
4500
4645
  };
4501
4646
  findLastCommon = function(_arg) {
@@ -4515,27 +4660,49 @@ Gibbon.optimize = (function() {
4515
4660
  return refCrumb;
4516
4661
  };
4517
4662
  simplify = function(expr, substitutions) {
4518
- substitutions.each(function(subExpr, crumbs) {
4519
- var lastCommon, name, recurse;
4520
- if (!(crumbs.length >= 2)) {
4521
- return;
4663
+ var recurse;
4664
+ return (recurse = function(expr) {
4665
+ var bindable, bindableExprs, i, names, out, recurseInner, _, _i, _len;
4666
+ bindableExprs = substitutions.get(expr.hash());
4667
+ if (!bindableExprs) {
4668
+ return expr.map(recurse);
4522
4669
  }
4523
- lastCommon = findLastCommon(crumbs);
4524
- name = nameGen('b');
4525
- DEBUG.log("eliminating common expression " + (expr.inspect()) + " as " + name);
4526
- return expr = (recurse = function(expr) {
4527
- var hash;
4528
- hash = expr.hash();
4529
- if (hash === lastCommon) {
4530
- return Core.bind(name, subExpr, expr.map(recurse));
4531
- } else if (hash === subExpr.hash()) {
4532
- return Core.variable(name);
4533
- } else {
4534
- return expr.map(recurse);
4670
+ names = (function() {
4671
+ var _i, _len, _results;
4672
+ _results = [];
4673
+ for (_i = 0, _len = bindableExprs.length; _i < _len; _i++) {
4674
+ _ = bindableExprs[_i];
4675
+ _results.push(nameGen('b'));
4676
+ }
4677
+ return _results;
4678
+ })();
4679
+ DEBUG(function() {
4680
+ var bindable, i, _i, _len, _results;
4681
+ _results = [];
4682
+ for (i = _i = 0, _len = bindableExprs.length; _i < _len; i = ++_i) {
4683
+ bindable = bindableExprs[i];
4684
+ _results.push(DEBUG.log("binding " + (bindable.inspect()) + " as " + names[i]));
4685
+ }
4686
+ return _results;
4687
+ });
4688
+ out = (recurseInner = function(boundExpr) {
4689
+ var bindable, hash, i, _i, _len;
4690
+ hash = boundExpr.hash();
4691
+ for (i = _i = 0, _len = bindableExprs.length; _i < _len; i = ++_i) {
4692
+ bindable = bindableExprs[i];
4693
+ if (hash === bindable.hash()) {
4694
+ return Core.variable(names[i]);
4695
+ }
4535
4696
  }
4697
+ return boundExpr.map(recurseInner);
4536
4698
  })(expr);
4537
- });
4538
- return expr;
4699
+ for (i = _i = 0, _len = bindableExprs.length; _i < _len; i = ++_i) {
4700
+ bindable = bindableExprs[i];
4701
+ out = Core.bind(names[i], bindable, out);
4702
+ }
4703
+ DEBUG.log("=> " + (out.inspect()));
4704
+ return out.map(recurse);
4705
+ })(expr);
4539
4706
  };
4540
4707
  return function(expr) {
4541
4708
  return simplify(expr, genSubstitutions(expr));
@@ -5020,7 +5187,8 @@ VarTrace = (function(_super) {
5020
5187
 
5021
5188
  VarTrace.variants({
5022
5189
  value: ['val'],
5023
- continued: ['continuation', 'index']
5190
+ continued: ['continuation', 'index'],
5191
+ lambda: []
5024
5192
  });
5025
5193
 
5026
5194
  VarTrace.prototype.equals = function(other) {
@@ -5340,7 +5508,7 @@ RVal = (function(_super) {
5340
5508
  });
5341
5509
  };
5342
5510
 
5343
- RVal.prototype.mapSteps = function() {
5511
+ RVal.prototype.mapSteps = function(f) {
5344
5512
  return this.cases({
5345
5513
  lambda: function(a, r, n, b) {
5346
5514
  return RVal.lambda(a, r, n, f(b));
@@ -5510,9 +5678,11 @@ Gibbon.sequence = (function() {
5510
5678
  });
5511
5679
  },
5512
5680
  block: function(argName, body) {
5513
- return bind(RVal.makeLambda(argName, function(rescue, next) {
5681
+ var lambda;
5682
+ lambda = RVal.makeLambda([argName], function(rescue, next) {
5514
5683
  return sequenceTail(body, rescue, next);
5515
- }));
5684
+ });
5685
+ return Step.makeVar(lambda, bind);
5516
5686
  },
5517
5687
  app: function(block, arg) {
5518
5688
  return Step.makeCont(1, bind, function(cont) {
@@ -6247,9 +6417,6 @@ Gibbon.codegen = (function() {
6247
6417
  var extended, varToJS;
6248
6418
  varToJS = function(varName) {
6249
6419
  return trace.getVar(varName).cases({
6250
- continued: function() {
6251
- return JS.ident(varName);
6252
- },
6253
6420
  value: function(val) {
6254
6421
  return val.cases({
6255
6422
  constant: function(v) {
@@ -6258,8 +6425,18 @@ Gibbon.codegen = (function() {
6258
6425
  global: function() {
6259
6426
  return JS.ident('$');
6260
6427
  },
6261
- lambda: function() {
6262
- throw 'TODO';
6428
+ lambda: function(args, rescue, next, body) {
6429
+ var arg, bodyTrace, lambdaStatements, _i, _len;
6430
+ lambdaStatements = [];
6431
+ bodyTrace = trace;
6432
+ for (_i = 0, _len = args.length; _i < _len; _i++) {
6433
+ arg = args[_i];
6434
+ bodyTrace = bodyTrace.traceVar(arg, VarTrace.lambda());
6435
+ }
6436
+ generate(body, bodyTrace, function(statement) {
6437
+ return lambdaStatements.push(statement);
6438
+ });
6439
+ return JS.func(null, __slice.call(args).concat([rescue], [next]), JS.block(lambdaStatements));
6263
6440
  },
6264
6441
  prim: function(arity, name, args) {
6265
6442
  var a, jsArgs;
@@ -6299,6 +6476,9 @@ Gibbon.codegen = (function() {
6299
6476
  return JS.ident(varName);
6300
6477
  }
6301
6478
  });
6479
+ },
6480
+ other: function() {
6481
+ return JS.ident(varName);
6302
6482
  }
6303
6483
  });
6304
6484
  };