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.
@@ -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
  })()
@@ -1023,22 +1084,22 @@ Gibbon.AST = AST = (function(_super) {
1023
1084
  }
1024
1085
 
1025
1086
  AST.variants({
1026
- integer: ['value'],
1027
- decimal: ['value'],
1028
- percent: ['value'],
1029
- fraction: ['numerator', 'denominator'],
1030
- string: ['value'],
1031
- subst: ['flow'],
1032
- block: ['flow'],
1033
- list: ['elements', 'squish'],
1034
- defaulted: ['body', 'alternative'],
1035
- query: ['type', 'args'],
1036
- func: ['name', 'args'],
1037
- pair: ['first', 'second'],
1038
- flow: ['head', 'tail'],
1039
- metadata: ['key', 'text'],
1040
- definition: ['metadata', 'name', 'frame'],
1041
- frame: ['definitions', 'flow']
1087
+ integer: ['loc', 'value'],
1088
+ decimal: ['loc', 'value'],
1089
+ percent: ['loc', 'value'],
1090
+ fraction: ['loc', 'numerator', 'denominator'],
1091
+ string: ['loc', 'value'],
1092
+ subst: ['loc', 'flow'],
1093
+ block: ['loc', 'flow'],
1094
+ list: ['loc', 'elements', 'squish'],
1095
+ defaulted: ['loc', 'body', 'alternative'],
1096
+ query: ['loc', 'type', 'args'],
1097
+ func: ['loc', 'name', 'args'],
1098
+ pair: ['loc', 'first', 'second'],
1099
+ flow: ['loc', 'head', 'tail'],
1100
+ metadata: ['loc', 'key', 'text'],
1101
+ definition: ['loc', 'metadata', 'name', 'frame'],
1102
+ frame: ['loc', 'definitions', 'flow']
1042
1103
  });
1043
1104
 
1044
1105
  inspectDefinitions = function(defs) {
@@ -1053,34 +1114,34 @@ Gibbon.AST = AST = (function(_super) {
1053
1114
  };
1054
1115
 
1055
1116
  AST.prototype.inspect = function() {
1056
- var id;
1057
- id = function(x) {
1117
+ var useValue;
1118
+ useValue = function(_, x) {
1058
1119
  return x;
1059
1120
  };
1060
1121
  return this.cases({
1061
- integer: id,
1062
- decimal: id,
1063
- percent: id,
1064
- fraction: function(num, denom) {
1122
+ integer: useValue,
1123
+ decimal: useValue,
1124
+ percent: useValue,
1125
+ fraction: function(_, num, denom) {
1065
1126
  return "" + num + "/" + denom;
1066
1127
  },
1067
- string: function(s) {
1128
+ string: function(_, s) {
1068
1129
  return "'" + s + "'";
1069
1130
  },
1070
- query: function(query, args) {
1131
+ query: function(_, query, args) {
1071
1132
  if (query === 'access') {
1072
1133
  return "@" + args[0];
1073
1134
  } else {
1074
1135
  return "." + query + " " + (args.join(' '));
1075
1136
  }
1076
1137
  },
1077
- subst: function(flow) {
1138
+ subst: function(_, flow) {
1078
1139
  return "(" + (flow.inspect()) + ")";
1079
1140
  },
1080
- block: function(flow) {
1141
+ block: function(_, flow) {
1081
1142
  return "{ " + (flow.inspect()) + " }";
1082
1143
  },
1083
- list: function(els, squish) {
1144
+ list: function(_, els, squish) {
1084
1145
  var close, el, open;
1085
1146
  open = squish ? '[*' : '[';
1086
1147
  close = squish ? '*]' : ']';
@@ -1094,10 +1155,10 @@ Gibbon.AST = AST = (function(_super) {
1094
1155
  return _results;
1095
1156
  })()).join(', ')) + " " + close;
1096
1157
  },
1097
- defaulted: function(body, alt) {
1158
+ defaulted: function(_, body, alt) {
1098
1159
  return "" + (body.inspect()) + " | " + (alt.inspect());
1099
1160
  },
1100
- func: function(name, args) {
1161
+ func: function(_, name, args) {
1101
1162
  var arg;
1102
1163
  args = (function() {
1103
1164
  var _i, _len, _results;
@@ -1110,10 +1171,10 @@ Gibbon.AST = AST = (function(_super) {
1110
1171
  })();
1111
1172
  return "" + name + " " + (args.join(' '));
1112
1173
  },
1113
- pair: function(first, second) {
1174
+ pair: function(_, first, second) {
1114
1175
  return "" + (first.inspect()) + " : " + (second.inspect());
1115
1176
  },
1116
- flow: function(head, tail) {
1177
+ flow: function(_, head, tail) {
1117
1178
  if (tail) {
1118
1179
  tail = "" + (tail.inspect()) + " -> ";
1119
1180
  } else {
@@ -1121,10 +1182,10 @@ Gibbon.AST = AST = (function(_super) {
1121
1182
  }
1122
1183
  return "" + tail + (head.inspect());
1123
1184
  },
1124
- metadata: function(key, text) {
1185
+ metadata: function(_, key, text) {
1125
1186
  return "" + key + ": " + text;
1126
1187
  },
1127
- definition: function(metadata, name, frame) {
1188
+ definition: function(_, metadata, name, frame) {
1128
1189
  var m, out, _i, _len;
1129
1190
  out = [];
1130
1191
  for (_i = 0, _len = metadata.length; _i < _len; _i++) {
@@ -1136,7 +1197,7 @@ Gibbon.AST = AST = (function(_super) {
1136
1197
  out.push(frame.inspect());
1137
1198
  return out.join('');
1138
1199
  },
1139
- frame: function(definitions, flow) {
1200
+ frame: function(_, definitions, flow) {
1140
1201
  var out;
1141
1202
  out = [];
1142
1203
  out.push("(");
@@ -1163,7 +1224,6 @@ Gibbon.TypeAST = TypeAST = (function(_super) {
1163
1224
  TypeAST.variants({
1164
1225
  concrete: ['name'],
1165
1226
  variable: ['name'],
1166
- "native": ['id'],
1167
1227
  wildcard: [],
1168
1228
  list: ['of'],
1169
1229
  func: ['input', 'args', 'output'],
@@ -1176,37 +1236,58 @@ Gibbon.TypeAST = TypeAST = (function(_super) {
1176
1236
  return parse.type(str);
1177
1237
  };
1178
1238
 
1179
- TypeAST.parseUnit = function(str) {
1180
- return parse.unitType(str);
1181
- };
1182
-
1183
1239
  return TypeAST;
1184
1240
 
1185
1241
  })(Variant);
1186
1242
 
1187
1243
  parse = Gibbon.parse = (function() {
1188
- 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;
1244
+ 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,
1245
+ _this = this;
1189
1246
  tag = function(name, parser) {
1190
- return parser.tag(name);
1247
+ return Parsimmon.Parser(function(stream, i) {
1248
+ var result;
1249
+ result = parser._(stream, i);
1250
+ if (!result.status) {
1251
+ result.expected = name;
1252
+ }
1253
+ return result;
1254
+ });
1191
1255
  };
1192
- Parsimmon.Parser.prototype.tag = function(name) {
1193
- var _this = this;
1194
- return Parsimmon.Parser(function(stream, i, onSuccess, onFailure) {
1195
- return _this._(stream, i, onSuccess, function(stream, newI, expected) {
1196
- return onFailure(stream, newI, name);
1197
- });
1256
+ Parsimmon.Parser.prototype.tryChain = function(f) {
1257
+ return this.chain(function(res) {
1258
+ return f(res).or(succeed(res));
1198
1259
  });
1199
1260
  };
1200
1261
  string = Parsimmon.string, regex = Parsimmon.regex, succeed = Parsimmon.succeed, fail = Parsimmon.fail;
1262
+ seq = Parsimmon.seq, lazy = Parsimmon.lazy;
1201
1263
  whitespace = regex(/^[ \t]*/);
1202
1264
  blankLines = regex(/^[\n\s]+/);
1203
1265
  comment = regex(/^#.*?(\n|$)/);
1204
1266
  lines = (blankLines.or(comment)).many();
1205
1267
  lexeme = function(p) {
1206
- return p.skip(whitespace);
1268
+ return p.mark().skip(whitespace);
1207
1269
  };
1208
1270
  multiline = function(p) {
1209
- return p.skip(lines);
1271
+ return p.mark().skip(lines);
1272
+ };
1273
+ opt = function(p) {
1274
+ return p.or(succeed(null));
1275
+ };
1276
+ withLoc = function(p, f) {
1277
+ return p.map(function(_arg) {
1278
+ var end, start, value;
1279
+ start = _arg.start, value = _arg.value, end = _arg.end;
1280
+ return f({
1281
+ start: start,
1282
+ end: end
1283
+ }, value);
1284
+ });
1285
+ };
1286
+ spanLoc = function(l, r) {
1287
+ return {
1288
+ start: l.start,
1289
+ end: r.end
1290
+ };
1210
1291
  };
1211
1292
  identifier = tag('an identifier', regex(/^[a-z][\w-]*[?]?/i));
1212
1293
  arrow = multiline(string('->'));
@@ -1218,7 +1299,7 @@ parse = Gibbon.parse = (function() {
1218
1299
  rbrack = lexeme(string(']'));
1219
1300
  lparen = multiline(string('('));
1220
1301
  rparen = lexeme(string(')'));
1221
- comma = lexeme(string(','));
1302
+ comma = multiline(string(','));
1222
1303
  defaulted = multiline(string('|'));
1223
1304
  lsplat = multiline(string('[*'));
1224
1305
  rsplat = lexeme(string('*]'));
@@ -1236,154 +1317,187 @@ parse = Gibbon.parse = (function() {
1236
1317
  variable = lexeme(string('%').then(identifier));
1237
1318
  wildcard = lexeme(string('%'));
1238
1319
  funcPlaceholder = lexeme(string('&'));
1239
- integerExpr = integer.map(function(i) {
1240
- return AST.integer(parseInt(i));
1320
+ integerExpr = withLoc(integer, function(loc, i) {
1321
+ return AST.integer(loc, parseInt(i));
1241
1322
  });
1242
- decimalExpr = decimal.map(function(d) {
1243
- return AST.decimal(parseFloat(d));
1323
+ decimalExpr = withLoc(decimal, function(loc, d) {
1324
+ return AST.decimal(loc, parseFloat(d));
1244
1325
  });
1245
- percentExpr = percent.map(function(p) {
1246
- return AST.percent(parseInt(p));
1326
+ percentExpr = withLoc(percent, function(loc, p) {
1327
+ return AST.percent(loc, parseInt(p));
1247
1328
  });
1248
- fractionExpr = fraction.map(function(f) {
1329
+ fractionExpr = withLoc(fraction, function(loc, f) {
1249
1330
  var denom, num, _ref5;
1250
1331
  _ref5 = f.split('/'), num = _ref5[0], denom = _ref5[1];
1251
- return AST.fraction(num, denom);
1332
+ return AST.fraction(loc, num, denom);
1252
1333
  });
1253
- stringExpr = str.map(function(s) {
1254
- return AST.string(s);
1334
+ stringExpr = withLoc(str, function(loc, s) {
1335
+ return AST.string(loc, s);
1255
1336
  });
1256
- accessorExpr = accessor.map(function(name) {
1257
- return AST.query('access', [name]);
1337
+ accessorExpr = withLoc(accessor, function(loc, name) {
1338
+ return AST.query(loc, 'access', [name]);
1258
1339
  });
1259
- queryExpr = query.then(function(q) {
1260
- return queryArg.many().map(function(args) {
1261
- return AST.query(q, args);
1262
- });
1340
+ queryExpr = seq([query, queryArg.many()]).map(function(_arg) {
1341
+ var a, args, loc, q, _ref5;
1342
+ q = _arg[0], args = _arg[1];
1343
+ loc = spanLoc(q, ((_ref5 = args[args.length - 1]) != null ? _ref5.end : void 0) || q);
1344
+ return AST.query(loc, q.value, (function() {
1345
+ var _i, _len, _results;
1346
+ _results = [];
1347
+ for (_i = 0, _len = args.length; _i < _len; _i++) {
1348
+ a = args[_i];
1349
+ _results.push(a.value);
1350
+ }
1351
+ return _results;
1352
+ })());
1263
1353
  });
1264
1354
  numericExpr = percentExpr.or(decimalExpr.or(fractionExpr.or(integerExpr)));
1265
- parenFlow = lparen.then(function() {
1266
- return flow.skip(rparen);
1355
+ parenFlow = lazy(function() {
1356
+ return lparen.then(flow).skip(rparen);
1357
+ });
1358
+ substExpr = lazy(function() {
1359
+ return seq([lparen, flow, rparen]).map(function(_arg) {
1360
+ var fl, l, r;
1361
+ l = _arg[0], fl = _arg[1], r = _arg[2];
1362
+ return AST.subst(spanLoc(l, r), fl);
1363
+ });
1267
1364
  });
1268
- substExpr = parenFlow.map(function(fl) {
1269
- return AST.subst(fl);
1365
+ listExpr = lazy(function() {
1366
+ return seq([lbrack, commaSepFlows, rbrack]).map(function(_arg) {
1367
+ var els, l, r;
1368
+ l = _arg[0], els = _arg[1], r = _arg[2];
1369
+ return AST.list(spanLoc(l, r), els, false);
1370
+ });
1270
1371
  });
1271
- listExpr = lbrack.then(function() {
1272
- return commaSepFlows.then(function(els) {
1273
- return rbrack.result(AST.list(els, false));
1372
+ squishListExpr = lazy(function() {
1373
+ return seq([lsplat, commaSepFlows, rsplat]).map(function(_arg) {
1374
+ var els, l, r;
1375
+ l = _arg[0], els = _arg[1], r = _arg[2];
1376
+ return AST.list(spanLoc(l, r), els, true);
1274
1377
  });
1275
1378
  });
1276
- squishListExpr = lsplat.then(function() {
1277
- return commaSepFlows.then(function(els) {
1278
- return rsplat.result(AST.list(els, true));
1379
+ blockExpr = lazy(function() {
1380
+ return seq([lbrace, flow, rbrace]).map(function(_arg) {
1381
+ var flow, l, r;
1382
+ l = _arg[0], flow = _arg[1], r = _arg[2];
1383
+ return AST.block(spanLoc(l, r), flow);
1279
1384
  });
1280
1385
  });
1281
- blockExpr = lbrace.then(function() {
1282
- return flow.skip(rbrace);
1283
- }).map(AST.block);
1284
1386
  expr = tag('an expr', queryExpr.or(accessorExpr.or(substExpr.or(squishListExpr.or(listExpr.or(stringExpr.or(blockExpr.or(numericExpr))))))));
1285
1387
  singletonFlow = expr.map(function(e) {
1286
- return AST.flow(e, null);
1388
+ return AST.flow(e.loc, e, null);
1287
1389
  });
1288
- func = name.then(function(funcName) {
1289
- return parenFlow.or(singletonFlow).many().map(function(args) {
1290
- return AST.func(funcName, args);
1291
- });
1390
+ func = seq([name, parenFlow.or(singletonFlow).many()]).map(function(_arg) {
1391
+ var args, loc, name;
1392
+ name = _arg[0], args = _arg[1];
1393
+ loc = {
1394
+ start: name.start,
1395
+ end: name.end
1396
+ };
1397
+ if (args.length) {
1398
+ loc.end = args[args.length - 1].loc.end;
1399
+ }
1400
+ return AST.func(loc, name.value, args);
1292
1401
  });
1293
- component = multiline(expr.or(func));
1294
- nonPairedFlow = component.then(function(first) {
1295
- return arrow.then(component).many().map(function(rest) {
1296
- var comp, cursor, _i, _len;
1297
- cursor = AST.flow(first, null);
1298
- for (_i = 0, _len = rest.length; _i < _len; _i++) {
1299
- comp = rest[_i];
1300
- cursor = AST.flow(comp, cursor);
1301
- }
1302
- return cursor;
1303
- });
1402
+ component = expr.or(func).skip(lines);
1403
+ nonPairedFlow = seq([component, arrow.then(component).many()]).map(function(_arg) {
1404
+ var comp, cursor, first, rest, _i, _len;
1405
+ first = _arg[0], rest = _arg[1];
1406
+ cursor = AST.flow(first.loc, first, null);
1407
+ for (_i = 0, _len = rest.length; _i < _len; _i++) {
1408
+ comp = rest[_i];
1409
+ cursor = AST.flow(spanLoc(first.loc, comp.loc), comp, cursor);
1410
+ }
1411
+ return cursor;
1304
1412
  });
1305
- nonDefaultedFlow = nonPairedFlow.then(function(first) {
1413
+ nonDefaultedFlow = nonPairedFlow.tryChain(function(first) {
1306
1414
  return pair.then(nonDefaultedFlow).map(function(second) {
1307
- return AST.flow(AST.pair(first, second), null);
1308
- }).or(succeed(first));
1415
+ var loc;
1416
+ loc = spanLoc(first.loc, second.loc);
1417
+ return AST.flow(loc, AST.pair(loc, first, second), null);
1418
+ });
1309
1419
  });
1310
- flow = tag('a flow', nonDefaultedFlow.then(function(body) {
1420
+ flow = tag('a flow', nonDefaultedFlow.tryChain(function(body) {
1311
1421
  return defaulted.then(flow).map(function(alternative) {
1312
- return AST.flow(AST.defaulted(body, alternative), null);
1313
- }).or(succeed(body));
1314
- }));
1315
- commaSepFlows = flow.skip(comma.or(succeed(null)).then(lines)).many().then(function(els) {
1316
- return flow.or(succeed(null)).map(function(final) {
1317
- if (final) {
1318
- els.push(final);
1319
- }
1320
- return els;
1422
+ var loc;
1423
+ loc = spanLoc(body.loc, alternative.loc);
1424
+ return AST.flow(loc, AST.defaulted(loc, body, alternative), null);
1321
1425
  });
1426
+ }));
1427
+ commaSepFlows = seq([flow.skip(seq([opt(comma, lines)])).many(), opt(flow)]).map(function(_arg) {
1428
+ var els, final;
1429
+ els = _arg[0], final = _arg[1];
1430
+ if (final) {
1431
+ els.push(final);
1432
+ }
1433
+ return els;
1322
1434
  });
1323
- metadata = label.then(function(key) {
1324
- return labelVal.map(function(text) {
1325
- return AST.metadata(key, text);
1326
- });
1435
+ metadata = seq([label, labelVal]).map(function(key, text) {
1436
+ return AST.metadata(spanLoc(key, text), key.value, text.value);
1327
1437
  });
1328
- definition = tag('a definition', metadata.many().then(function(md) {
1329
- return name.then(function(n) {
1330
- return define.then(innerFrame).map(function(fl) {
1331
- return AST.definition(md, n, fl);
1332
- });
1333
- });
1334
- }));
1335
- frame = definition.many().then(function(defs) {
1336
- return flow.map(function(fl) {
1337
- return AST.frame(defs, fl);
1438
+ definition = lazy(function() {
1439
+ return seq([metadata.many(), name, define.then(innerFrame)]).map(function(_arg) {
1440
+ var fl, loc, md, n, _ref5;
1441
+ md = _arg[0], n = _arg[1], fl = _arg[2];
1442
+ loc = spanLoc(((_ref5 = md[0]) != null ? _ref5.loc : void 0) || n, fl);
1443
+ return AST.definition(loc, md, n.value, fl);
1338
1444
  });
1339
1445
  });
1340
- parenFrame = lparen.then(frame).skip(rparen.then(lines));
1446
+ frame = seq([definition.many(), flow]).map(function(_arg) {
1447
+ var defs, flow, loc;
1448
+ defs = _arg[0], flow = _arg[1];
1449
+ loc = spanLoc((defs[0] || flow).loc, flow.loc);
1450
+ return AST.frame(loc, defs, flow);
1451
+ });
1452
+ parenFrame = seq([lparen, frame, rparen, lines]).map(function(_arg) {
1453
+ var fr, l, r, _;
1454
+ l = _arg[0], fr = _arg[1], r = _arg[2], _ = _arg[3];
1455
+ fr.loc = spanLoc(l, r);
1456
+ return fr;
1457
+ });
1341
1458
  freeFrame = flow.map(function(fl) {
1342
- return AST.frame([], fl);
1459
+ return AST.frame(fl.loc, [], fl);
1343
1460
  });
1344
1461
  innerFrame = parenFrame.or(freeFrame);
1345
1462
  program = lines.then(frame);
1346
1463
  tassign = lexeme(string('='));
1347
- bang = lexeme(string('!'));
1348
- nativeId = lexeme(regex(/^\w+/));
1349
1464
  concrete = name.map(function(n) {
1350
- return TypeAST.concrete(n);
1465
+ return TypeAST.concrete(n.value);
1351
1466
  });
1352
1467
  typeVar = variable.map(function(v) {
1353
- return TypeAST.variable(v);
1468
+ return TypeAST.variable(v.value);
1354
1469
  });
1355
1470
  wildType = wildcard.result(TypeAST.wildcard());
1356
- listType = lbrack.then(function() {
1357
- return type.skip(rbrack).map(function(t) {
1471
+ listType = lazy(function() {
1472
+ return seq([lbrack, type, rbrack]).map(function(_arg) {
1473
+ var t, _, __;
1474
+ _ = _arg[0], t = _arg[1], __ = _arg[2];
1358
1475
  return TypeAST.list(t);
1359
1476
  });
1360
1477
  });
1361
- parenType = lparen.then(function() {
1362
- return type.skip(rparen);
1478
+ parenType = lazy(function() {
1479
+ return lparen.then(type).skip(rparen);
1363
1480
  });
1364
- blockType = lbrace.then(function() {
1365
- return arrowType.skip(rbrace).map(function(t) {
1481
+ blockType = lazy(function() {
1482
+ return lbrace.then(arrowType).skip(rbrace).map(function(t) {
1366
1483
  return TypeAST.block(t);
1367
1484
  });
1368
1485
  });
1369
- nativeType = bang.then(nativeId).map(TypeAST["native"]);
1370
- simpleType = typeVar.or(wildType.or(listType.or(parenType.or(blockType.or(concrete.or(nativeType))))));
1371
- type = simpleType.then(function(first) {
1486
+ simpleType = typeVar.or(wildType.or(listType.or(parenType.or(blockType.or(concrete)))));
1487
+ type = simpleType.tryChain(function(first) {
1372
1488
  return pair.then(type).map(function(second) {
1373
1489
  return TypeAST.pair(first, second);
1374
- }).or(succeed(first));
1375
- });
1376
- arrowType = type.then(function(first) {
1377
- return arrow.then(type).map(function(second) {
1378
- return TypeAST.arrow(first, second);
1379
1490
  });
1380
1491
  });
1381
- signature = name.then(function(n) {
1382
- return type.many().then(function(argTypes) {
1383
- return tassign.then(arrowType).map(function(ftype) {
1384
- return TypeAST.func(ftype.from, argTypes, ftype.to);
1385
- });
1386
- });
1492
+ arrowType = seq([type, arrow, type]).map(function(_arg) {
1493
+ var first, second, _;
1494
+ first = _arg[0], _ = _arg[1], second = _arg[2];
1495
+ return TypeAST.arrow(first, second);
1496
+ });
1497
+ signature = seq([name, type.many(), tassign.then(arrowType)]).map(function(_arg) {
1498
+ var argTypes, ftype, name;
1499
+ name = _arg[0], argTypes = _arg[1], ftype = _arg[2];
1500
+ return TypeAST.func(ftype.from, argTypes, ftype.to);
1387
1501
  });
1388
1502
  fullSignature = lines.then(signature);
1389
1503
  isString = function(s) {
@@ -1402,10 +1516,6 @@ parse = Gibbon.parse = (function() {
1402
1516
  assertString(str);
1403
1517
  return fullSignature.parse(str);
1404
1518
  };
1405
- parse.unitType = function(str) {
1406
- assertString(str);
1407
- return type.parse(str);
1408
- };
1409
1519
  return parse;
1410
1520
  })();
1411
1521
 
@@ -1961,12 +2071,12 @@ analyze = Gibbon.analyze = (function() {
1961
2071
  input = flow.tail ? TypeExpr.expr(flow.tail) : global;
1962
2072
  return push(TypeExpr.expr(flow), TypeExpr.query(input, _this, flow.head));
1963
2073
  },
1964
- pair: function(first, second) {
2074
+ pair: function(_, first, second) {
1965
2075
  _this.analyzeFlow(first, global, push);
1966
2076
  _this.analyzeFlow(second, global, push);
1967
2077
  return push(TypeExpr.expr(flow), TypeExpr.param('pair', [TypeExpr.expr(first), TypeExpr.expr(second)]));
1968
2078
  },
1969
- func: function(name, args) {
2079
+ func: function(_, name, args) {
1970
2080
  var arg, ast, func, i, input, scope, _i, _len, _results;
1971
2081
  if (!stdlib.hasOwnProperty(name)) {
1972
2082
  push(TypeExpr.expr(flow.head), TypeExpr.error('func', [flow.head]));
@@ -2000,11 +2110,11 @@ analyze = Gibbon.analyze = (function() {
2000
2110
  string: function() {
2001
2111
  return push(TypeExpr.expr(flow), TypeExpr.param('string', []));
2002
2112
  },
2003
- subst: function(subFlow) {
2113
+ subst: function(_, subFlow) {
2004
2114
  push(TypeExpr.expr(flow), TypeExpr.expr(subFlow));
2005
2115
  return _this.analyzeFlow(subFlow, global, push);
2006
2116
  },
2007
- list: function(elements) {
2117
+ list: function(_, elements) {
2008
2118
  var el, elVar, _i, _len, _results;
2009
2119
  elVar = TypeExpr.variable('el');
2010
2120
  push(TypeExpr.expr(flow), TypeExpr.param('list', [elVar]));
@@ -2016,13 +2126,13 @@ analyze = Gibbon.analyze = (function() {
2016
2126
  }
2017
2127
  return _results;
2018
2128
  },
2019
- block: function(subFlow) {
2129
+ block: function(_, subFlow) {
2020
2130
  var input;
2021
2131
  input = TypeExpr.variable('.input');
2022
2132
  push(TypeExpr.expr(flow), TypeExpr.param('block', [input, TypeExpr.expr(subFlow)]));
2023
2133
  return _this.analyzeFlow(subFlow, input, push);
2024
2134
  },
2025
- defaulted: function(body, alt) {
2135
+ defaulted: function(_, body, alt) {
2026
2136
  push(TypeExpr.expr(body), TypeExpr.expr(alt));
2027
2137
  push(TypeExpr.expr(flow), TypeExpr.expr(alt));
2028
2138
  _this.analyzeFlow(body, global, push);
@@ -2232,19 +2342,19 @@ analyze = Gibbon.analyze = (function() {
2232
2342
  };
2233
2343
  toSemanticTree = function(expr) {
2234
2344
  return expr.cases({
2235
- frame: function(_, flow) {
2345
+ frame: function(_, __, flow) {
2236
2346
  return Semantic.definition(dependencies, toSemanticTree(flow));
2237
2347
  },
2238
- flow: function(head, tail) {
2348
+ flow: function(_, head, tail) {
2239
2349
  return Semantic.flow(flowType(TypeExpr.expr(this)), toSemanticTree(head), tail && toSemanticTree(tail));
2240
2350
  },
2241
- query: function(type, name) {
2351
+ query: function(_, type, name) {
2242
2352
  if (!(errors.length || semanticAccessors.has(this))) {
2243
2353
  throw "unsolved with no errors!";
2244
2354
  }
2245
2355
  return semanticAccessors.get(this);
2246
2356
  },
2247
- func: function(name, args) {
2357
+ func: function(_, name, args) {
2248
2358
  var a, scope, semArgs, solvedScope;
2249
2359
  scope = this.__scope__;
2250
2360
  solvedScope = new Hash;
@@ -2262,16 +2372,16 @@ analyze = Gibbon.analyze = (function() {
2262
2372
  })();
2263
2373
  return Semantic.func(name, semArgs, solvedScope);
2264
2374
  },
2265
- pair: function(first, second) {
2375
+ pair: function(_, first, second) {
2266
2376
  return Semantic.pair(toSemanticTree(first), toSemanticTree(second));
2267
2377
  },
2268
- block: function(flow) {
2378
+ block: function(_, flow) {
2269
2379
  return Semantic.block(toSemanticTree(flow));
2270
2380
  },
2271
- subst: function(subFlow) {
2381
+ subst: function(_, subFlow) {
2272
2382
  return toSemanticTree(subFlow);
2273
2383
  },
2274
- list: function(elements, squish) {
2384
+ list: function(_, elements, squish) {
2275
2385
  var e;
2276
2386
  return Semantic.list((function() {
2277
2387
  var _i, _len, _results;
@@ -2283,7 +2393,7 @@ analyze = Gibbon.analyze = (function() {
2283
2393
  return _results;
2284
2394
  })(), squish);
2285
2395
  },
2286
- defaulted: function(body, alt) {
2396
+ defaulted: function(_, body, alt) {
2287
2397
  return Semantic.defaulted(toSemanticTree(body), toSemanticTree(alt));
2288
2398
  },
2289
2399
  integer: function() {
@@ -2537,6 +2647,9 @@ Value = Gibbon.Value = Value = (function(_super) {
2537
2647
  }
2538
2648
  return Value.boolean(o);
2539
2649
  },
2650
+ block: function(from, to) {
2651
+ return Value.block(o);
2652
+ },
2540
2653
  other: function() {
2541
2654
  throw "could not return object of type " + (type.inspect());
2542
2655
  }
@@ -3556,7 +3669,6 @@ Gibbon.Core = Core = (function(_super) {
3556
3669
  _ref14 = this.subtrees();
3557
3670
  for (_i = 0, _len = _ref14.length; _i < _len; _i++) {
3558
3671
  subtree = _ref14[_i];
3559
- console.log("checking alwaysSucceeds " + (subtree.inspect()));
3560
3672
  if (!subtree.alwaysSucceeds()) {
3561
3673
  return false;
3562
3674
  }
@@ -3581,6 +3693,9 @@ Gibbon.Core = Core = (function(_super) {
3581
3693
  fail: function() {
3582
3694
  return true;
3583
3695
  },
3696
+ branch: function(ifTrue, ifFalse) {
3697
+ return ifTrue.alwaysFails() && ifFalse.alwaysFails();
3698
+ },
3584
3699
  rescue: function(e, default_) {
3585
3700
  return e.alwaysFails() && default_.alwaysFails();
3586
3701
  },
@@ -3592,7 +3707,6 @@ Gibbon.Core = Core = (function(_super) {
3592
3707
  _ref14 = this.subtrees();
3593
3708
  for (_i = 0, _len = _ref14.length; _i < _len; _i++) {
3594
3709
  subtree = _ref14[_i];
3595
- console.log("checking alwaysFails " + (subtree.inspect()));
3596
3710
  if (subtree.alwaysFails()) {
3597
3711
  return true;
3598
3712
  }
@@ -3727,7 +3841,7 @@ Gibbon.Core = Core = (function(_super) {
3727
3841
  return Core.foldList(f(l), f(o), a, i, aa, f(b));
3728
3842
  },
3729
3843
  mapList: function(l, a, i, b) {
3730
- return Core.mapList(f(l), i, a, f(b));
3844
+ return Core.mapList(f(l), a, i, f(b));
3731
3845
  },
3732
3846
  zipLists: function(l, r) {
3733
3847
  return Core.zipLists(f(l), f(r));
@@ -4405,16 +4519,35 @@ Gibbon.optimize = (function() {
4405
4519
  });
4406
4520
  },
4407
4521
  op2: function(op, left, right) {
4408
- var checkIdent, identFold, l, r, _ref14;
4522
+ var checkConst, checkIdent, identFold, l, r, _ref14;
4409
4523
  left = partialEval(left);
4410
4524
  right = partialEval(right);
4411
- checkIdent = function(opTest, val, ident, identVal) {
4412
- return op === opTest && val._tag === 'constant' && val.value === ident && identVal;
4525
+ checkConst = function(val, f) {
4526
+ return val._tag === 'constant' && f(val.value);
4413
4527
  };
4414
- 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);
4415
- if (identFold) {
4416
-
4417
- return identFold;
4528
+ if (op === '>' || op === '<' || op === '>=' || op === '<=') {
4529
+ if (checkConst(left, function(x) {
4530
+ return !isFinite(x);
4531
+ })) {
4532
+
4533
+ right = Core.constant(0);
4534
+ } else if (checkConst(right, function(x) {
4535
+ return !isFinite(x);
4536
+ })) {
4537
+
4538
+ left = Core.constant(0);
4539
+ }
4540
+ } else {
4541
+ checkIdent = function(opTest, val, ident, identVal) {
4542
+ return op === opTest && checkConst(val, function(x) {
4543
+ return x === ident;
4544
+ }) && identVal;
4545
+ };
4546
+ 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);
4547
+ if (identFold) {
4548
+
4549
+ return identFold;
4550
+ }
4418
4551
  }
4419
4552
  if (!(left._tag === 'constant' && right._tag === 'constant')) {
4420
4553
  return Core.op2(op, left, right);
@@ -4448,18 +4581,19 @@ Gibbon.optimize = (function() {
4448
4581
  }).reverse();
4449
4582
  };
4450
4583
  genSubstitutions = function(expr) {
4451
- var newTrace, queue, sub, substitutions, trace, _i, _len, _ref14, _ref15;
4452
- substitutions = new ObjHash;
4584
+ var newTrace, occurrences, queue, sub, substitutions, trace, _i, _len, _ref14, _ref15;
4585
+ occurrences = new ObjHash;
4586
+ substitutions = new Hash;
4453
4587
  queue = [[expr, List.empty()]];
4454
4588
  while (queue.length) {
4455
4589
  _ref14 = queue.shift(), expr = _ref14[0], trace = _ref14[1];
4456
- if (expr.isSimple()) {
4590
+ if (expr.isSimple() || expr.alwaysFails()) {
4457
4591
  continue;
4458
4592
  }
4459
- if (substitutions.has(expr)) {
4460
- substitutions.get(expr).push(makeCrumbs(trace));
4593
+ if (occurrences.has(expr)) {
4594
+ occurrences.get(expr).push(makeCrumbs(trace));
4461
4595
  } else {
4462
- substitutions.set(expr, [makeCrumbs(trace)]);
4596
+ occurrences.set(expr, [makeCrumbs(trace)]);
4463
4597
  newTrace = trace.cons(expr);
4464
4598
  _ref15 = expr.subtrees();
4465
4599
  for (_i = 0, _len = _ref15.length; _i < _len; _i++) {
@@ -4468,6 +4602,17 @@ Gibbon.optimize = (function() {
4468
4602
  }
4469
4603
  }
4470
4604
  }
4605
+ occurrences.each(function(expr, crumbs) {
4606
+ var insertionPoint;
4607
+ if (!(crumbs.length >= 2)) {
4608
+ return;
4609
+ }
4610
+ insertionPoint = findLastCommon(crumbs);
4611
+ substitutions.cache(insertionPoint, function() {
4612
+ return [];
4613
+ });
4614
+ return substitutions.get(insertionPoint).push(expr);
4615
+ });
4471
4616
  return substitutions;
4472
4617
  };
4473
4618
  findLastCommon = function(_arg) {
@@ -4487,27 +4632,41 @@ Gibbon.optimize = (function() {
4487
4632
  return refCrumb;
4488
4633
  };
4489
4634
  simplify = function(expr, substitutions) {
4490
- substitutions.each(function(subExpr, crumbs) {
4491
- var lastCommon, name, recurse;
4492
- if (!(crumbs.length >= 2)) {
4493
- return;
4635
+ var recurse;
4636
+ return (recurse = function(expr) {
4637
+ var bindable, bindableExprs, i, names, out, recurseInner, _, _i, _len;
4638
+ bindableExprs = substitutions.get(expr.hash());
4639
+ if (!bindableExprs) {
4640
+ return expr.map(recurse);
4494
4641
  }
4495
- lastCommon = findLastCommon(crumbs);
4496
- name = nameGen('b');
4642
+ names = (function() {
4643
+ var _i, _len, _results;
4644
+ _results = [];
4645
+ for (_i = 0, _len = bindableExprs.length; _i < _len; _i++) {
4646
+ _ = bindableExprs[_i];
4647
+ _results.push(nameGen('b'));
4648
+ }
4649
+ return _results;
4650
+ })();
4497
4651
 
4498
- return expr = (recurse = function(expr) {
4499
- var hash;
4500
- hash = expr.hash();
4501
- if (hash === lastCommon) {
4502
- return Core.bind(name, subExpr, expr.map(recurse));
4503
- } else if (hash === subExpr.hash()) {
4504
- return Core.variable(name);
4505
- } else {
4506
- return expr.map(recurse);
4652
+ out = (recurseInner = function(boundExpr) {
4653
+ var bindable, hash, i, _i, _len;
4654
+ hash = boundExpr.hash();
4655
+ for (i = _i = 0, _len = bindableExprs.length; _i < _len; i = ++_i) {
4656
+ bindable = bindableExprs[i];
4657
+ if (hash === bindable.hash()) {
4658
+ return Core.variable(names[i]);
4659
+ }
4507
4660
  }
4661
+ return boundExpr.map(recurseInner);
4508
4662
  })(expr);
4509
- });
4510
- return expr;
4663
+ for (i = _i = 0, _len = bindableExprs.length; _i < _len; i = ++_i) {
4664
+ bindable = bindableExprs[i];
4665
+ out = Core.bind(names[i], bindable, out);
4666
+ }
4667
+
4668
+ return out.map(recurse);
4669
+ })(expr);
4511
4670
  };
4512
4671
  return function(expr) {
4513
4672
  return simplify(expr, genSubstitutions(expr));
@@ -4992,7 +5151,8 @@ VarTrace = (function(_super) {
4992
5151
 
4993
5152
  VarTrace.variants({
4994
5153
  value: ['val'],
4995
- continued: ['continuation', 'index']
5154
+ continued: ['continuation', 'index'],
5155
+ lambda: []
4996
5156
  });
4997
5157
 
4998
5158
  VarTrace.prototype.equals = function(other) {
@@ -5312,7 +5472,7 @@ RVal = (function(_super) {
5312
5472
  });
5313
5473
  };
5314
5474
 
5315
- RVal.prototype.mapSteps = function() {
5475
+ RVal.prototype.mapSteps = function(f) {
5316
5476
  return this.cases({
5317
5477
  lambda: function(a, r, n, b) {
5318
5478
  return RVal.lambda(a, r, n, f(b));
@@ -5482,9 +5642,11 @@ Gibbon.sequence = (function() {
5482
5642
  });
5483
5643
  },
5484
5644
  block: function(argName, body) {
5485
- return bind(RVal.makeLambda(argName, function(rescue, next) {
5645
+ var lambda;
5646
+ lambda = RVal.makeLambda([argName], function(rescue, next) {
5486
5647
  return sequenceTail(body, rescue, next);
5487
- }));
5648
+ });
5649
+ return Step.makeVar(lambda, bind);
5488
5650
  },
5489
5651
  app: function(block, arg) {
5490
5652
  return Step.makeCont(1, bind, function(cont) {
@@ -6219,9 +6381,6 @@ Gibbon.codegen = (function() {
6219
6381
  var extended, varToJS;
6220
6382
  varToJS = function(varName) {
6221
6383
  return trace.getVar(varName).cases({
6222
- continued: function() {
6223
- return JS.ident(varName);
6224
- },
6225
6384
  value: function(val) {
6226
6385
  return val.cases({
6227
6386
  constant: function(v) {
@@ -6230,8 +6389,18 @@ Gibbon.codegen = (function() {
6230
6389
  global: function() {
6231
6390
  return JS.ident('$');
6232
6391
  },
6233
- lambda: function() {
6234
- throw 'TODO';
6392
+ lambda: function(args, rescue, next, body) {
6393
+ var arg, bodyTrace, lambdaStatements, _i, _len;
6394
+ lambdaStatements = [];
6395
+ bodyTrace = trace;
6396
+ for (_i = 0, _len = args.length; _i < _len; _i++) {
6397
+ arg = args[_i];
6398
+ bodyTrace = bodyTrace.traceVar(arg, VarTrace.lambda());
6399
+ }
6400
+ generate(body, bodyTrace, function(statement) {
6401
+ return lambdaStatements.push(statement);
6402
+ });
6403
+ return JS.func(null, __slice.call(args).concat([rescue], [next]), JS.block(lambdaStatements));
6235
6404
  },
6236
6405
  prim: function(arity, name, args) {
6237
6406
  var a, jsArgs;
@@ -6271,6 +6440,9 @@ Gibbon.codegen = (function() {
6271
6440
  return JS.ident(varName);
6272
6441
  }
6273
6442
  });
6443
+ },
6444
+ other: function() {
6445
+ return JS.ident(varName);
6274
6446
  }
6275
6447
  });
6276
6448
  };