2016-05-08 15:33:39 +00:00
|
|
|
"use strict";
|
|
|
|
// "Structures": Simple named-tuple-like records.
|
|
|
|
|
|
|
|
var Immutable = require("immutable");
|
|
|
|
var $Special = require('./special.js');
|
|
|
|
|
2016-05-10 04:40:53 +00:00
|
|
|
/* Defined here rather than in trie.js because we need it in makeConstructor. */
|
2016-05-08 15:33:39 +00:00
|
|
|
var __ = new $Special("wildcard"); /* wildcard marker */
|
|
|
|
|
2016-05-10 04:40:53 +00:00
|
|
|
function StructureType(label, arity) {
|
|
|
|
this.label = label;
|
|
|
|
this.arity = arity;
|
|
|
|
this.pattern = this.instantiate(Immutable.Repeat(__, arity).toArray());
|
2016-05-08 15:33:39 +00:00
|
|
|
|
2016-05-10 04:40:53 +00:00
|
|
|
var self = this;
|
|
|
|
this.ctor = function () {
|
|
|
|
return self.instantiate(Array.prototype.slice.call(arguments));
|
2016-05-08 15:33:39 +00:00
|
|
|
};
|
2016-05-10 04:40:53 +00:00
|
|
|
this.ctor.meta = this;
|
|
|
|
this.ctor.pattern = this.pattern;
|
|
|
|
this.ctor.isClassOf = function (v) { return self.isClassOf(v); };
|
2016-05-08 15:33:39 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 04:40:53 +00:00
|
|
|
function makeConstructor(label, fieldNames) {
|
|
|
|
return new StructureType(label, fieldNames.length).ctor;
|
2016-05-08 15:33:39 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 04:40:53 +00:00
|
|
|
StructureType.prototype.equals = function (other) {
|
|
|
|
if (!(other instanceof StructureType)) return false;
|
|
|
|
return this.arity === other.arity && this.label === other.label;
|
|
|
|
};
|
|
|
|
|
|
|
|
StructureType.prototype.instantiate = function (fields) {
|
|
|
|
return new Structure(this, fields);
|
|
|
|
};
|
|
|
|
|
|
|
|
StructureType.prototype.isClassOf = function (v) {
|
|
|
|
return v && (v instanceof Structure) && (v.meta.equals(this));
|
|
|
|
};
|
|
|
|
|
|
|
|
function Structure(meta, fields) {
|
|
|
|
if (!isStructureType(meta)) {
|
|
|
|
throw new Error("Structure: requires structure type");
|
|
|
|
}
|
|
|
|
if (fields.length !== meta.arity) {
|
|
|
|
throw new Error("Structure: cannot instantiate meta "+JSON.stringify(meta.label)+
|
|
|
|
" expecting "+meta.arity+" fields with "+fields.length+" fields");
|
|
|
|
}
|
|
|
|
this.meta = meta;
|
|
|
|
this.length = meta.arity;
|
|
|
|
this.fields = fields.slice(0);
|
|
|
|
for (var i = 0; i < fields.length; i++) {
|
|
|
|
this[i] = fields[i];
|
|
|
|
}
|
2016-05-08 15:33:39 +00:00
|
|
|
}
|
|
|
|
|
2016-05-10 04:40:53 +00:00
|
|
|
function reviveStructs(j) {
|
|
|
|
if (Array.isArray(j)) {
|
|
|
|
return j.map(reviveStructs);
|
2016-05-08 15:33:39 +00:00
|
|
|
}
|
2016-05-10 04:40:53 +00:00
|
|
|
|
|
|
|
if ((j !== null) && typeof j === 'object') {
|
|
|
|
if ((typeof j['@type'] === 'string') && Array.isArray(j['fields'])) {
|
|
|
|
return (new StructureType(j['@type'], j['fields'].length)).instantiate(j['fields']);
|
|
|
|
} else {
|
|
|
|
for (var k in j) {
|
|
|
|
if (Object.prototype.hasOwnProperty.call(j, k)) {
|
|
|
|
j[k] = reviveStructs(j[k]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return j;
|
|
|
|
}
|
|
|
|
|
|
|
|
function reviver(k, v) {
|
|
|
|
if (k === '') {
|
|
|
|
return reviveStructs(v);
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
};
|
|
|
|
|
|
|
|
Structure.prototype.toJSON = function () {
|
|
|
|
return { '@type': this.meta.label, 'fields': this.fields };
|
|
|
|
};
|
|
|
|
|
|
|
|
function isStructureType(v) {
|
|
|
|
return v && (v instanceof StructureType);
|
|
|
|
}
|
|
|
|
|
|
|
|
function isStructure(v) {
|
|
|
|
return v && (v instanceof Structure);
|
2016-05-08 15:33:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
module.exports.__ = __;
|
2016-05-10 04:40:53 +00:00
|
|
|
module.exports.StructureType = StructureType;
|
|
|
|
module.exports.makeConstructor = makeConstructor;
|
|
|
|
module.exports.Structure = Structure;
|
|
|
|
module.exports.reviveStructs = reviveStructs;
|
|
|
|
module.exports.reviver = reviver;
|
|
|
|
module.exports.isStructureType = isStructureType;
|
2016-05-08 15:33:39 +00:00
|
|
|
module.exports.isStructure = isStructure;
|