diff --git a/src/core/TypePatterns.js b/src/core/TypePatterns.js index cf3d58a..86669c8 100644 --- a/src/core/TypePatterns.js +++ b/src/core/TypePatterns.js @@ -5,7 +5,7 @@ const tpBrand = Symbol() export class TypePattern { constructor() { - this[tpBrand] = true + throw new Error('Cannot construct an abstract TypePattern') } match(_typeSequence, _options={}) { throw new Error('Specific TypePatterns must implement match') @@ -13,16 +13,15 @@ export class TypePattern { sampleTypes() { throw new Error('Specific TypePatterns must implement sampleTypes') } - equal(other) {return other.constructor === this.constructor} toString() {return 'Abstract Pattern (?!)'} // Returns true if entity is a TypePattern static holds(entity) {return entity[tpBrand]} } -class MatchTypePattern extends TypePattern { +class MatchTypePattern { constructor(typeToMatch) { - super() + this[tpBrand] = true this.type = typeToMatch } match(typeSequence, options={}) { @@ -42,13 +41,15 @@ class MatchTypePattern extends TypePattern { return [-1, Undefined] } sampleTypes() {return [this.type]} - equal(other) {return super.equal(other) && this.type === other.type} + equal(other) { + return this.constructor === other.constructor && this.type === other.type + } toString() {return `Match(${this.type})`} } -class SequencePattern extends TypePattern { +class SequencePattern { constructor(itemsToMatch) { - super() + this[tpBrand] = true this.patterns = itemsToMatch.map(pattern) } match(typeSequence, options={_internal: true}) { @@ -70,16 +71,16 @@ class SequencePattern extends TypePattern { return this.patterns.map(pat => pat.sampleTypes()).flat() } equal(other) { - return super.equal(other) + return this.constructor === other.constructor && this.patterns.length === other.patterns.length && this.patterns.every((elt, ix) => elt.equal(other.patterns[ix])) } toString() {return `[${this.patterns}]`} } -class PredicatePattern extends TypePattern { +class PredicatePattern { constructor(predicate) { - super() + this[tpBrand] = true this.predicate = predicate } match(typeSequence, options={}) { @@ -93,7 +94,8 @@ class PredicatePattern extends TypePattern { throw new Error('sampleTypes() not yet implemented for PredicatePattern') } equal(other) { - return super.equal(other) && this.predicate === other.predicate + return this.constructor === other.constructor + && this.predicate === other.predicate } toString() {return `Test(${this.predicate})`} } @@ -110,7 +112,8 @@ export const pattern = patternOrSpec => { throw new TypeError(`Can't interpret '${patternOrSpec}' as a type pattern`) } -class AnyPattern extends TypePattern { +class AnyPattern { + constructor () {this[tpBrand] = true} match(typeSequence, options={}) { const position = options.position ?? 0 return position < typeSequence.length @@ -118,14 +121,15 @@ class AnyPattern extends TypePattern { : [-1, Undefined] } sampleTypes() {return [Undefined]} + equal(other) {return this.constructor === other.constructor} toString() {return 'Any'} } export const Any = new AnyPattern() -class OptionalPattern extends TypePattern { +class OptionalPattern { constructor(item) { - super() + this[tpBrand] = true this.pattern = pattern(item) } match(typeSequence, options={_internal: true}) { @@ -143,16 +147,17 @@ class OptionalPattern extends TypePattern { } sampleTypes() {return []} equal(other) { - return super.equal(other) && this.pattern.equal(other.pattern) + return this.constructor === other.constructor + && this.pattern.equal(other.pattern) } toString() {return `?${this.pattern}`} } export const Optional = item => new OptionalPattern(item) -class MultiPattern extends TypePattern { +class MultiPattern { constructor(item) { - super() + this[tpBrand] = true this.pattern = pattern(item) } match(typeSequence, options={_internal: true}) { @@ -170,7 +175,8 @@ class MultiPattern extends TypePattern { } sampleTypes() {return []} equal(other) { - return super.equal(other) && this.pattern.equal(other.pattern) + return this.constructor === other.constructor + && this.pattern.equal(other.pattern) } toString() {return `${this.pattern}*`} } @@ -179,13 +185,15 @@ export const Multiple = item => new MultiPattern(item) // Like Multiple(Any) except leaves the argument list alone; it doesn't // chunk it into a single Array of all arguments -class PassthruPattern extends TypePattern { +class PassthruPattern { + constructor () {this[tpBrand] = true} match(typeSequence, options={}) { const position = options.position ?? 0 return [typeSequence.length, typeSequence.slice(position)] } sampleTypes() {return []} toString() {return 'Passthru'} + equal(other) {return this.constructor === other.constructor} } export const Passthru = new PassthruPattern()