git.fiddlerwoaroof.com
Browse code

chore: reformat, etc.

Ed Langley authored on 08/10/2019 04:46:02
Showing 2 changed files
... ...
@@ -0,0 +1,24 @@
1
+{
2
+    "compilerOptions": {
3
+        "target": "es2017",
4
+        "baseUrl": "src",
5
+        "allowSyntheticDefaultImports": true,
6
+        "noEmit": true,
7
+        "checkJs": true,
8
+        "lib": [ "es2017" ],
9
+        "rootDirs": [
10
+            "src"
11
+        ],
12
+        "module": "commonjs"
13
+    },
14
+    "exclude": [
15
+        ".history/*",
16
+        "frontend",
17
+        "node_modules",
18
+        "node_modules/**/*",
19
+        "**/node_modules/**/*",
20
+        "**/node_modules/*",
21
+        "/.#*",
22
+        "**/.#*"
23
+    ]
24
+}
... ...
@@ -1,63 +1,78 @@
1
-export function NoNextMethodError() { }
1
+export function NoNextMethodError() {}
2 2
 NoNextMethodError.prototype = Object.create(Error);
3 3
 
4
-export function NoApplicableMethodError() { }
4
+export function NoApplicableMethodError() {}
5 5
 NoApplicableMethodError.prototype = Object.create(Error);
6 6
 
7
-export function NoPrimaryMethodError() { }
7
+export function NoPrimaryMethodError() {}
8 8
 NoPrimaryMethodError.prototype = Object.create(NoApplicableMethodError);
9 9
 
10
-const before_qualifier = Symbol.for('before');
11
-const after_qualifier = Symbol.for('after');
12
-const around_qualifier = Symbol.for('around');
10
+const before_qualifier = Symbol.for("before");
11
+const after_qualifier = Symbol.for("after");
12
+const around_qualifier = Symbol.for("around");
13
+
14
+const Method = {
15
+  lambda_list: [],
16
+  qualifiers: [],
17
+  specializers: [],
18
+  body: () => {},
19
+  generic_function: null
20
+};
13 21
 
14 22
 let genfun_prototype = {
15
-    name: "(placeholder)",
16
-    lambda_list: [],
17
-    methods: [],
18
-    method(qualifiers, specializers, body) {
19
-        ensure_method(this, this.lambda_list, qualifiers, specializers, body)
20
-        return this;
21
-    },
22
-    primary(specializers, body) {
23
-        return this.method([], specializers, body);
24
-    },
25
-    before(specializers, body) {
26
-        return this.method([before_qualifier], specializers, body);
27
-    },
28
-    after(specializers, body) {
29
-        return this.method([after_qualifier], specializers, body);
30
-    },
31
-    around(specializers, body) {
32
-        return this.method([around_qualifier], specializers, body);
33
-    },
34
-    get fn() {
35
-        const gf = this;
36
-        const lambda = (function () {
37
-            return apply_generic_function(gf, [].slice.call(arguments));
38
-        }).bind(gf);
39
-        return Object.defineProperties(lambda, {
40
-            'name': { value: gf.name },
41
-            'lambda_list': { value: gf.lambda_list },
42
-            'gf': { value: gf },
43
-        });
44
-    }
23
+  name: "(placeholder)",
24
+  lambda_list: [],
25
+  methods: [],
26
+  method(qualifiers, specializers, body) {
27
+    ensure_method(this, this.lambda_list, qualifiers, specializers, body);
28
+    return this;
29
+  },
30
+  primary(specializers, body) {
31
+    return this.method([], specializers, body);
32
+  },
33
+  before(specializers, body) {
34
+    return this.method([before_qualifier], specializers, body);
35
+  },
36
+  after(specializers, body) {
37
+    return this.method([after_qualifier], specializers, body);
38
+  },
39
+  around(specializers, body) {
40
+    return this.method([around_qualifier], specializers, body);
41
+  },
42
+  get fn() {
43
+    const gf = this;
44
+    const lambda = function() {
45
+      return apply_generic_function(gf, [].slice.call(arguments));
46
+    }.bind(gf);
47
+    return Object.defineProperties(lambda, {
48
+      name: { value: gf.name },
49
+      lambda_list: { value: gf.lambda_list },
50
+      gf: { value: gf }
51
+    });
52
+  }
45 53
 };
46 54
 
55
+/**
56
+ * @class
57
+ * @extends genfun_prototype
58
+ * @param {string} name
59
+ * @param {string[]} lambda_list
60
+ * @property {Method[]} methods
61
+ */
47 62
 function GenericFunction(name, lambda_list) {
48
-    if (!(this instanceof GenericFunction)) {
49
-        return new GenericFunction(...arguments);
50
-    }
63
+  if (!(this instanceof GenericFunction)) {
64
+    return new GenericFunction(...arguments);
65
+  }
51 66
 
52
-    this.name = name;
53
-    this.lambda_list = lambda_list;
54
-    this.methods = [];
67
+  this.name = name;
68
+  this.lambda_list = lambda_list;
69
+  this.methods = [];
55 70
 }
56 71
 
57 72
 GenericFunction.prototype = Object.create(genfun_prototype);
58 73
 
59 74
 export function defgeneric(name, ...argument_names) {
60
-    return GenericFunction(name, argument_names);
75
+  return GenericFunction(name, argument_names);
61 76
 }
62 77
 
63 78
 // let method_prototype = {
... ...
@@ -69,30 +84,37 @@ export function defgeneric(name, ...argument_names) {
69 84
 //     generic_function: {},
70 85
 // };
71 86
 
72
-export function StandardMethod(
73
-    lambda_list, qualifiers, specializers, body
74
-) {
75
-    if (!(this instanceof StandardMethod)) {
76
-        return new StandardMethod(...arguments);
77
-    }
78
-
79
-    this.lambda_list = lambda_list;
80
-    this.qualifiers = qualifiers;
81
-    this.specializers = specializers;
82
-    this.body = body;
83
-    this.generic_function = null;
87
+/**
88
+ * @class
89
+ * @extends Method
90
+ * @param {string[]} lambda_list
91
+ * @param {Symbol[]} qualifiers
92
+ * @param {Specializer | Object} specializers
93
+ * @param {Function} body
94
+ */
95
+export function StandardMethod(lambda_list, qualifiers, specializers, body) {
96
+  if (!(this instanceof StandardMethod)) {
97
+    return new StandardMethod(...arguments);
98
+  }
99
+
100
+  this.lambda_list = lambda_list;
101
+  this.qualifiers = qualifiers;
102
+  this.specializers = specializers;
103
+  this.body = body;
104
+  this.generic_function = null;
84 105
 }
106
+StandardMethod.prototype = Object.create(Method);
85 107
 
86
-function ensure_method(gf/*, lambda_list, qualifiers, specializers, body*/) {
87
-    let new_method = StandardMethod(...[].slice.call(arguments, 1));
88
-    add_method(gf, new_method);
89
-    return new_method;
108
+function ensure_method(gf /*, lambda_list, qualifiers, specializers, body*/) {
109
+  let new_method = StandardMethod(...[].slice.call(arguments, 1));
110
+  add_method(gf, new_method);
111
+  return new_method;
90 112
 }
91 113
 
92 114
 function add_method(gf, method) {
93
-    method.generic_function = gf;
94
-    gf.methods.push(method);
95
-    return method;
115
+  method.generic_function = gf;
116
+  gf.methods.push(method);
117
+  return method;
96 118
 }
97 119
 
98 120
 // function classes_of(args) {
... ...
@@ -102,88 +124,101 @@ function add_method(gf, method) {
102 124
 const required_portion = x => x;
103 125
 
104 126
 function apply_generic_function(gf, args) {
105
-    let applicable_methods =
106
-        compute_applicable_methods_using_classes(gf, required_portion(args));
107
-    if (applicable_methods.length === 0) {
108
-        throw new NoApplicableMethodError(`no applicable methods for gf ${gf.name} with args ${JSON.stringify(args)}`);
109
-    } else {
110
-        return apply_methods(gf, args, applicable_methods);
111
-    }
127
+  let applicable_methods = compute_applicable_methods_using_classes(
128
+    gf,
129
+    required_portion(args)
130
+  );
131
+  if (applicable_methods.length === 0) {
132
+    throw new NoApplicableMethodError(
133
+      `no applicable methods for gf ${gf.name} with args ${JSON.stringify(
134
+        args
135
+      )}`
136
+    );
137
+  } else {
138
+    return apply_methods(gf, args, applicable_methods);
139
+  }
112 140
 }
113 141
 
114
-function method_more_specific_p(m1, m2/*, required_classes*/) {
115
-    const m1specializers = m1.specializers;
116
-    const m2specializers = m2.specializers;
117
-
118
-    let result = null;
119
-    for (let [spec1, spec2] of m1specializers.map((el, idx) => [el, m2specializers[idx]])) {
120
-        if (spec1 !== spec2) {
121
-            result = sub_specializer_p(spec1, spec2);
122
-            break;
123
-        }
142
+function method_more_specific_p(m1, m2 /*, required_classes*/) {
143
+  const m1specializers = m1.specializers;
144
+  const m2specializers = m2.specializers;
145
+
146
+  let result = null;
147
+  for (let [spec1, spec2] of m1specializers.map((el, idx) => [
148
+    el,
149
+    m2specializers[idx]
150
+  ])) {
151
+    if (spec1 !== spec2) {
152
+      result = sub_specializer_p(spec1, spec2);
153
+      break;
124 154
     }
155
+  }
125 156
 
126
-    return result;
157
+  return result;
127 158
 }
128 159
 
129 160
 export function sub_specializer_p(c1, c2) {
130
-    let result = false;
131
-    if (c1 instanceof Specializer) {
132
-        result = c1.super_of(c2);
133
-    } else if (c1.prototype !== undefined && c2.prototype !== undefined) {
134
-        result = Object.isPrototypeOf.call(c1.prototype, c2.prototype);
135
-    }
136
-    return result;
161
+  let result = false;
162
+  if (c1 instanceof Specializer) {
163
+    result = c1.super_of(c2);
164
+  } else if (c1.prototype !== undefined && c2.prototype !== undefined) {
165
+    result = Object.isPrototypeOf.call(c1.prototype, c2.prototype);
166
+  }
167
+  return result;
137 168
 }
138 169
 
139
-const idS = Symbol.for('id');
140
-Object.prototype[idS] = function () { return this };
170
+const idS = Symbol.for("id");
171
+Object.prototype[idS] = function() {
172
+  return this;
173
+};
141 174
 
142
-export function Specializer() { }
175
+export function Specializer() {}
143 176
 Specializer.prototype = {
144
-    matches(_obj) { return false; },
145
-    super_of(_obj) { return false; },
146
-}
177
+  matches(_obj) {
178
+    return false;
179
+  },
180
+  super_of(_obj) {
181
+    return false;
182
+  }
183
+};
147 184
 
148 185
 function isSuperset(superset, subset) {
149
-    return (
150
-        (superset.size > subset.size)
151
-        && Array.from(subset).every(superset.has.bind(superset))
152
-    );
186
+  return (
187
+    superset.size > subset.size &&
188
+    Array.from(subset).every(superset.has.bind(superset))
189
+  );
153 190
 }
154 191
 
155 192
 const matchShape = defgeneric("matchShape", "shape", "value")
156
-    .primary([Array], ([name, dflt], v) => dflt !== undefined && v[name] === dflt)
157
-    .primary([String], (name, v) => v[name] !== undefined)
158
-    .fn;
193
+  .primary([Array], ([name, dflt], v) => dflt !== undefined && v[name] === dflt)
194
+  .primary([String], (name, v) => v[name] !== undefined).fn;
159 195
 
160 196
 export const extractKey = defgeneric("extractKey", "key")
161
-    .primary([Array], ([name, _]) => name)
162
-    .primary([String], (name) => name)
163
-    .fn;
197
+  .primary([Array], ([name, _]) => name)
198
+  .primary([String], name => name).fn;
164 199
 
165 200
 export function Shape(...keys) {
166
-    if (!(this instanceof Shape)) {
167
-        return new Shape(...keys);
168
-    }
169
-    this.keys = new Set(keys);
201
+  if (!(this instanceof Shape)) {
202
+    return new Shape(...keys);
203
+  }
204
+  this.keys = new Set(keys);
170 205
 }
171 206
 Shape.prototype = Object.assign(new Specializer(), {
172
-    matches(obj) {
173
-        return Array.from(this.keys).every(key => matchShape(key, obj));
174
-    },
175
-    super_of(spec) {
176
-        // this is the super of spec
177
-        //     if this.keys is a subset of spec.keys
178
-        // and if this.keys != spec.keys
179
-
180
-        if (!(spec instanceof Shape)) {
181
-            const specKeys = spec && new Set(Object.getOwnPropertyNames(spec));
182
-            return !!specKeys && isSuperset(specKeys, this.keys);
183
-        } else {
184
-            return isSuperset(spec.keys, this.keys);
185
-        }
207
+  matches(obj) {
208
+    return Array.from(this.keys).every(key => matchShape(key, obj));
209
+  },
210
+  super_of(spec) {
211
+    // this is the super of spec
212
+    //     if this.keys is a subset of spec.keys
213
+    // and if this.keys != spec.keys
214
+
215
+    if (!(spec instanceof Shape)) {
216
+      const specKeys = spec && new Set(Object.getOwnPropertyNames(spec));
217
+      return !!specKeys && isSuperset(specKeys, this.keys);
218
+    } else {
219
+      return isSuperset(spec.keys, this.keys);
186 220
     }
221
+  }
187 222
 });
188 223
 
189 224
 // function trace(fun) {
... ...
@@ -196,65 +231,85 @@ Shape.prototype = Object.assign(new Specializer(), {
196 231
 // }
197 232
 
198 233
 export function matches_specializer(obj, specializer) {
199
-    let objType = typeof obj;
200
-    let specializer_proto = specializer && specializer.prototype
201
-    let result = obj === specializer_proto;
202
-
203
-    if (obj === null && obj === specializer) {
204
-        result = true;
205
-    } else if (specializer && specializer.prototype !== undefined) {
206
-        if (!result && objType === 'object') {
207
-            result = Object.isPrototypeOf.call(specializer_proto, obj);
208
-        } else if (objType === 'number') {
209
-            result = matches_specializer(Number.prototype, specializer) || matches_specializer(specializer_proto, Number);
210
-        } else if (objType === 'string') {
211
-            result = matches_specializer(String.prototype, specializer) || matches_specializer(specializer_proto, String);
212
-        }
213
-    } else if (specializer instanceof Specializer) {
214
-        result = specializer.matches(obj);
234
+  let objType = typeof obj;
235
+  let specializer_proto = specializer && specializer.prototype;
236
+  let result = obj === specializer_proto;
237
+
238
+  if (obj === null && obj === specializer) {
239
+    result = true;
240
+  } else if (specializer && specializer.prototype !== undefined) {
241
+    if (!result && objType === "object") {
242
+      result = Object.isPrototypeOf.call(specializer_proto, obj);
243
+    } else if (objType === "number") {
244
+      result =
245
+        matches_specializer(Number.prototype, specializer) ||
246
+        matches_specializer(specializer_proto, Number);
247
+    } else if (objType === "string") {
248
+      result =
249
+        matches_specializer(String.prototype, specializer) ||
250
+        matches_specializer(specializer_proto, String);
215 251
     }
252
+  } else if (specializer instanceof Specializer) {
253
+    result = specializer.matches(obj);
254
+  }
216 255
 
217
-    return result;
256
+  return result;
218 257
 }
219 258
 
220
-
259
+/**
260
+ * @param {GenericFunction} gf
261
+ */
221 262
 function compute_applicable_methods_using_classes(gf, required_classes) {
222
-    const applicable_methods = gf.methods.filter(
223
-        method => method.specializers.every((specializer, idx) => matches_specializer(required_classes[idx], specializer))
224
-
225
-    );
226
-
227
-    applicable_methods.sort((a, b) => {
228
-        let result = 0;
229
-        if (method_more_specific_p(a, b)) {
230
-            result = 1;
231
-        }
232
-        if (method_more_specific_p(b, a)) {
233
-            result = -1;
234
-        }
263
+  const applicable_methods = gf.methods.filter(method =>
264
+    method.specializers.every((specializer, idx) =>
265
+      matches_specializer(required_classes[idx], specializer)
266
+    )
267
+  );
268
+
269
+  applicable_methods.sort((a, b) => {
270
+    let result = 0;
271
+    if (method_more_specific_p(a, b)) {
272
+      result = 1;
273
+    }
274
+    if (method_more_specific_p(b, a)) {
275
+      result = -1;
276
+    }
235 277
 
236
-        return result;
237
-    })
278
+    return result;
279
+  });
238 280
 
239
-    return applicable_methods;
281
+  return applicable_methods;
240 282
 }
241 283
 
242
-
284
+/**
285
+ * @param {any[]} a1
286
+ * @param {any[]} a2
287
+ */
243 288
 function arr_eq(a1, a2) {
244
-    if (a1.length !== a2.length) {
245
-        return false;
246
-    } else {
247
-        for (let x = 0; x < a1.length; x++) {
248
-            if (a1[x] instanceof Array && a2[x] instanceof Array) {
249
-                if (!arr_eq(a1[x], a2[x])) {
250
-                    return false;
251
-                }
252
-            } else if (a1[x] !== a2[x]) {
253
-                return false;
254
-            }
289
+  if (a1.length !== a2.length) {
290
+    return false;
291
+  } else {
292
+    for (let x = 0; x < a1.length; x++) {
293
+      if (a1[x] instanceof Array && a2[x] instanceof Array) {
294
+        if (!arr_eq(a1[x], a2[x])) {
295
+          return false;
255 296
         }
256
-        return true;
297
+      } else if (a1[x] !== a2[x]) {
298
+        return false;
299
+      } else if (
300
+        Object.hasOwnProperty.call(a1[x], "equals") &&
301
+        !a1[x].equals(a2[x])
302
+      ) {
303
+        return false;
304
+      } else if (
305
+        Object.hasOwnProperty.call(a2[x], "equals") &&
306
+        !a2[x].equals(a1[x])
307
+      ) {
308
+        return false;
309
+      }
257 310
     }
311
+    return true;
312
+  }
258 313
 }
259 314
 
260 315
 // function set_eq(a1, a2) {
... ...
@@ -270,72 +325,94 @@ function arr_eq(a1, a2) {
270 325
 //     }
271 326
 // }
272 327
 
273
-const primary_method_p =
274
-    method => method instanceof WrappedMethod || method.qualifiers.length === 0;
275
-const before_method_p =
276
-    method => !(method instanceof WrappedMethod) && arr_eq(method.qualifiers, [before_qualifier]);
277
-const after_method_p =
278
-    method => !(method instanceof WrappedMethod) && arr_eq(method.qualifiers, [after_qualifier]);
279
-const around_method_p =
280
-    method => !(method instanceof WrappedMethod) && arr_eq(method.qualifiers, [around_qualifier]);
328
+const primary_method_p = method =>
329
+  method instanceof WrappedMethod || method.qualifiers.length === 0;
330
+const before_method_p = method =>
331
+  !(method instanceof WrappedMethod) &&
332
+  arr_eq(method.qualifiers, [before_qualifier]);
333
+const after_method_p = method =>
334
+  !(method instanceof WrappedMethod) &&
335
+  arr_eq(method.qualifiers, [after_qualifier]);
336
+const around_method_p = method =>
337
+  !(method instanceof WrappedMethod) &&
338
+  arr_eq(method.qualifiers, [around_qualifier]);
281 339
 
282 340
 function WrappedMethod(continuation) {
283
-    this.continuation = continuation;
341
+  this.continuation = continuation;
284 342
 }
285 343
 
344
+/**
345
+ * @param {GenericFunction} gf
346
+ * @param {any[]} args
347
+ * @param {Method[]} applicable_methods
348
+ */
286 349
 function apply_methods(gf, args, applicable_methods) {
287
-    const primaries = applicable_methods.filter(primary_method_p);
288
-    const befores = applicable_methods.filter(before_method_p);
289
-    const arounds = applicable_methods.filter(around_method_p);
290
-    const afters = applicable_methods.filter(after_method_p);
291
-    afters.reverse();
292
-
293
-    const main_call = Object.defineProperty(
294
-        function () {
295
-            if (primaries.length === 0) {
296
-                throw new NoPrimaryMethodError(`No primary method for ${gf.name}`);
297
-            }
298
-
299
-            for (let before of befores) {
300
-                apply_method(before, args, []);
301
-            }
302
-
303
-            try {
304
-                return apply_method(primaries[0], args, primaries.slice(1));
305
-            } finally {
306
-                for (let after of afters) {
307
-                    apply_method(after, args, []);
308
-                }
309
-            }
310
-        },
311
-        'name', { value: `main_call_${gf.name}` },
312
-    );
313
-
314
-    if (arounds.length === 0) {
315
-        return main_call();
316
-    } else {
317
-        const wrapped_main_call = new WrappedMethod(main_call);
318
-        const next_methods = arounds.slice(1).concat([wrapped_main_call]);
319
-        return apply_method(arounds[0], args, next_methods);
320
-    }
350
+  const primaries = applicable_methods.filter(primary_method_p);
351
+  const befores = applicable_methods.filter(before_method_p);
352
+  const arounds = applicable_methods.filter(around_method_p);
353
+  const afters = applicable_methods.filter(after_method_p);
354
+  afters.reverse();
355
+
356
+  const main_call = Object.defineProperty(
357
+    function() {
358
+      if (primaries.length === 0) {
359
+        throw new NoPrimaryMethodError(`No primary method for ${gf.name}`);
360
+      }
361
+
362
+      for (let before of befores) {
363
+        apply_method(before, args, []);
364
+      }
365
+
366
+      try {
367
+        return apply_method(primaries[0], args, primaries.slice(1));
368
+      } finally {
369
+        for (let after of afters) {
370
+          apply_method(after, args, []);
371
+        }
372
+      }
373
+    },
374
+    "name",
375
+    { value: `main_call_${gf.name}` }
376
+  );
377
+
378
+  if (arounds.length === 0) {
379
+    return main_call();
380
+  } else {
381
+    const wrapped_main_call = new WrappedMethod(main_call);
382
+    const next_methods = arounds.slice(1).concat([wrapped_main_call]);
383
+    return apply_method(arounds[0], args, next_methods);
384
+  }
321 385
 }
322 386
 
387
+/**
388
+ * @param {Method} method
389
+ * @param {any[]} args
390
+ * @param {Method[]} next_methods
391
+ */
323 392
 function apply_method(method, args, next_methods) {
324
-    const method_context = {
325
-        call_next_method(...cnm_args) {
326
-            if (next_methods.length === 0) {
327
-                throw new NoNextMethodError(`no next method for genfun ${method.generic_function.name}`);
328
-            }
329
-
330
-            return method instanceof WrappedMethod
331
-                ? method.continuation()
332
-                : apply_methods(method.generic_function, cnm_args.length > 0 ? cnm_args : args, next_methods);
333
-        },
334
-
335
-        get next_method_p() {
336
-            return next_methods.length !== 0
337
-        }
338
-    };
393
+  const method_context = {
394
+    call_next_method(...cnm_args) {
395
+      if (next_methods.length === 0) {
396
+        throw new NoNextMethodError(
397
+          `no next method for genfun ${method.generic_function.name}`
398
+        );
399
+      }
400
+
401
+      return method instanceof WrappedMethod
402
+        ? method.continuation()
403
+        : apply_methods(
404
+            method.generic_function,
405
+            cnm_args.length > 0 ? cnm_args : args,
406
+            next_methods
407
+          );
408
+    },
409
+
410
+    get next_method_p() {
411
+      return next_methods.length !== 0;
412
+    }
413
+  };
339 414
 
340
-    return method.body ? method.body.bind(method_context)(...args) : method.continuation();
415
+  return method.body
416
+    ? method.body.bind(method_context)(...args)
417
+    : method.continuation();
341 418
 }