git.schokokeks.org
Repositories
Help
Report an Issue
fs-words.git
Code
Commits
Branches
Tags
Suche
Strukturansicht:
99941cf
Branches
Tags
develop-client_server
master
typescript
fs-words.git
server
lib
plankton
trait
logic-impl.js
[upd] server:lib:plankton
Christian Fraß
commited
99941cf
at 2021-03-12 00:46:54
logic-impl.js
Blame
History
Raw
/* This file is part of »bacterio-plankton:trait«. Copyright 2016-2021 greenscale <info@greenscale.de> »bacterio-plankton:trait« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »bacterio-plankton:trait« is distributed in the hope that it will be callful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »bacterio-plankton:trait«. If not, see <http://www.gnu.org/licenses/>. */ var lib_trait; (function (lib_trait) { /** * @author fenris */ function domain_make(_a, _make) { var _b = _a["soft"], soft = _b === void 0 ? false : _b, kind = _a["kind"]; return { "soft": soft, "kind": kind }; } /** * @author fenris */ function domain_inspect(parameters, value, _inspect) { var inspection = lib_shape.inspection_create(); if (value == undefined) { if (parameters.soft) { // all good } else { lib_shape.inspection_add(inspection, "null is not allowed"); } } else { var jstype_actual = typeof (value); var jstype_expected = "object"; if (jstype_actual === jstype_expected) { if ("domain" in value) { var domain_actual = value["domain"]["kind"]; var domain_expected = parameters.kind; if (domain_actual == domain_expected) { // all good? } else { lib_shape.inspection_add(inspection, "expected domain-kind '" + domain_expected + "' but got '" + domain_actual + "'"); } } else { lib_shape.inspection_add(inspection, "field 'domain' missing"); } } else { lib_shape.inspection_add(inspection, "expected JS-type '" + jstype_expected + "' but got '" + jstype_actual + "'"); } } return inspection; } /** * @author fenris */ function domain_stance(parameters, bindings, _stance) { return { "name": "domain", "parameters": { "soft": parameters.soft, "kind": parameters.kind } }; } /** * @author fenris */ function domain_show(parameters, _show) { var str; // core { str = ("#" + parameters.kind); } /* // parameters { str += (":" + JSON.stringify(parameters.parameters)) } */ // soft { if (parameters.soft) { str = "~" + str; } } return str; } /** * @author fenris */ lib_shape.register({ "name": "domain", "make": domain_make, "inspect": domain_inspect, "stance": domain_stance, "show": domain_show }); })(lib_trait || (lib_trait = {})); /* This file is part of »bacterio-plankton:trait«. Copyright 2016-2021 greenscale <info@greenscale.de> »bacterio-plankton:trait« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »bacterio-plankton:trait« is distributed in the hope that it will be callful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »bacterio-plankton:trait«. If not, see <http://www.gnu.org/licenses/>. */ /** * @author fenris */ var lib_trait; (function (lib_trait) { /** * @author fenris */ lib_trait._verbosity = 1; /** * @author fenris */ lib_trait._logprefix = "[lib_trait] "; /** * @desc holds all defined traits * @author fenris */ var _pool = {}; /** * @author fenris */ var _typechecker = function (value, shape, logger) { var messages = lib_shape.inspect(shape, value).messages; messages.forEach(logger); return (messages.length === 0); }; /** * @author fenris */ function log(_a) { var message = _a["message"], _b = _a["kind"], kind = _b === void 0 ? "log" : _b, _c = _a["level"], level = _c === void 0 ? 0 : _c; if (level <= lib_trait._verbosity) { var message_ = "" + lib_trait._logprefix + message; switch (kind) { default: case "log": { console.log(message_); break; } case "information": case "info": { console.info(message_); break; } case "warning": case "warn": { console.warn(message_); break; } case "error": case "err": { console.error(message_); break; } } } } /** * @author fenris */ function set_typechecker(typechecker) { _typechecker = typechecker; } lib_trait.set_typechecker = set_typechecker; /** * @author fenris */ function domain_instance(domain, value) { return { "domain": domain, "value": value }; } lib_trait.domain_instance = domain_instance; /** * @desc adds a trait * @author fenris */ function define(trait_id, variable_conditions, facets_raw) { if (trait_id in _pool) { var message = "trait '" + trait_id + "' already registered"; throw (new Error(message)); } else { var trait_1 = { "variables": {}, "facets": {}, "attendants": {} }; Object.keys(variable_conditions).forEach(function (variable_name) { var variable = { "conditions": variable_conditions[variable_name], "bindings": {} }; trait_1.variables[variable_name] = variable; }); Object.keys(facets_raw).forEach(function (facet_name) { var facet_raw = facets_raw[facet_name]; var facet = { "shape": lib_shape.make(facet_raw.shape || { "name": "any" }), "description": facet_raw.description, "implementation": facet_raw.implementation, "handlers": {} }; trait_1.facets[facet_name] = facet; }); _pool[trait_id] = trait_1; } } lib_trait.define = define; /** * @desc adhoc binding * @author fenris */ function attend(trait_id, domain_kind, bindings, handlers, condition) { if (condition === void 0) { condition = null; } var strict_binding = true; var strict_handling = true; if (!_pool.hasOwnProperty(trait_id)) { var message = "no trait '" + trait_id + "'"; throw (new Error(message)); } else { var trait_2 = _pool[trait_id]; // assignments { // variables { Object.keys(bindings).forEach(function (variable_name) { if (!trait_2.variables.hasOwnProperty(variable_name)) { var message = ""; message += "no variable '" + variable_name + "'"; message += " to bind in trait '" + trait_id + "'"; log({ "message": message, "kind": "warning" }); // throw (new Error(message)); } else { var variable = trait_2.variables[variable_name]; if (variable.bindings.hasOwnProperty(domain_kind)) { var message = ""; message += "variable '" + variable_name + "'"; message += " already bound for domain '" + domain_kind + "'"; message += " in trait '" + trait_id + "'"; throw (new Error(message)); } else { variable.bindings[domain_kind] = lib_shape.make(bindings[variable_name]); } } }); } // facets { Object.keys(handlers).forEach(function (facet_name) { if (!trait_2.facets.hasOwnProperty(facet_name)) { var message = ""; message += "no facet '" + facet_name + "'"; message += " to implement at trait '" + trait_id + "'"; log({ "kind": "warning", "message": message }); // throw (new Error(message)); } else { var facet = trait_2.facets[facet_name]; var intrinsic = (facet.implementation != undefined); if (intrinsic) { var message = "shadowing intrinsic facet '" + facet_name + "'"; console.warn(message); } else { // do nothing } if (facet.handlers.hasOwnProperty(domain_kind)) { var message = ""; message += "facet '" + facet_name + "'"; message += " already implemented in domain '" + domain_kind + "'"; message += " at trait '" + trait_id + "'"; throw (new Error(message)); } else { facet.handlers[domain_kind] = handlers[facet_name]; } } }); } // attendants { trait_2.attendants[domain_kind] = { "condition": condition }; } } // checks { var messages_1 = []; // variables { if (strict_binding) { var variable_names_given_1 = Object.keys(bindings); var variable_names_present = Object.keys(trait_2.variables); var variable_names_missing = variable_names_present.filter(function (variable_name) { return (!variable_names_given_1.some(function (variable_name_) { return (variable_name == variable_name_); })); }); variable_names_missing.forEach(function (variable_name) { var message = "binding missing for variable '" + variable_name + "'"; messages_1.push(message); }); } else { // do nothing } } // facets { if (strict_handling) { var facet_names_given_1 = Object.keys(handlers); var facet_names_needed = (Object.keys(trait_2.facets).filter(function (facet_name) { return (trait_2.facets[facet_name].implementation == undefined); })); var facet_names_missing = (facet_names_needed.filter(function (facet_name) { return (!facet_names_given_1.some(function (facet_name_) { return (facet_name === facet_name_); })); })); facet_names_missing.forEach(function (facet_name) { var message = "implementation missing for the facet '" + facet_name + "'"; messages_1.push(message); }); } else { // do nothing } } if (messages_1.length > 0) { var message = ""; message += "assignment of domain '" + domain_kind + "'"; message += " to trait '" + trait_id + "'"; message += " incomplete: " + messages_1.join(", "); throw (new Error(message)); } } } } lib_trait.attend = attend; /** * @desc calls a facet from a trait according to a given domain * @author fenris */ function call(trait_id, facet_name, domain, check) { if (check === void 0) { check = true; } if (!_pool.hasOwnProperty(trait_id)) { var message = "no trait '" + trait_id + "'"; throw (new Error(message)); } else { var trait_3 = _pool[trait_id]; if (!trait_3.facets.hasOwnProperty(facet_name)) { var message = "no facet '" + facet_name + "' in trait '" + trait_id + "'"; throw (new Error(message)); } else { var facet = trait_3.facets[facet_name]; var intrinsic = (facet.implementation !== undefined); var result = void 0; if (intrinsic) { result = facet.implementation(function (facet_name_) { return call(trait_id, facet_name_, domain, check); }); } else { if (!facet.handlers.hasOwnProperty(domain.kind)) { var message = ""; message += "implementation missing"; message += " at trait '" + trait_id + "'"; message += " for facet '" + facet_name + "'"; message += " in domain '" + domain.kind + "'"; throw (new Error(message)); } else { var show_shape = (function (shape) { return lib_shape.show(shape); }); var handler = facet.handlers[domain.kind]; var bindings_1 = {}; Object.keys(trait_3.variables).forEach(function (variable_name) { bindings_1[variable_name] = trait_3.variables[variable_name].bindings[domain.kind]; }); result = handler(domain.parameters); if (check && (_typechecker !== null) && (facet.shape !== undefined)) { var shape = lib_shape.stance(facet.shape, bindings_1); // console.info("expected shape of result: " + lib_shape.show(shape)); console.info("result: ", result); var valid = _typechecker(result, shape, function (message) { return log({ "kind": "warning", "message": "[typechecker] [result] " + message }); }); if (!valid) { var message = ""; message += "result '" + instance_show(result) + "'"; message += " doesn't match the expected type '" + show_shape(shape) + "'"; message += " at trait '" + trait_id + "'"; message += " for facet '" + facet_name + "'"; message += " in domain '" + domain.kind + "'"; log({ "kind": "warning", "message": message }); } { var condition = trait_3.attendants[domain.kind].condition; if (condition != null) { var attends = function (trait_id_, domain_) { return (_pool.hasOwnProperty(trait_id_) && _pool[trait_id_].attendants.hasOwnProperty(domain_.kind)); }; if (!condition(attends)(domain.parameters)) { var message = ""; message += "condition not fulfilled"; message += " at trait '" + trait_id + "'"; message += " for facet '" + facet_name + "'"; message += " in domain '" + domain.kind + "'"; log({ "kind": "warning", "message": message }); } else { // do nothing } } else { // do nothing } } } } } return result; } } } lib_trait.call = call; /** * @author fenris */ function explain(trait_id) { if (!_pool.hasOwnProperty(trait_id)) { var message = "no trait '" + trait_id + "'"; throw (new Error(message)); } else { var trait_4 = _pool[trait_id]; var str_1 = ""; // head { str_1 += "<<" + trait_id + ">>"; str_1 += (" " + "(" + (Object.keys(trait_4.variables) .map(function (variable_name) { var shape = lib_shape.make({ "name": "variable", "parameters": { "name": variable_name } }); return lib_shape.show(shape); }) .join(",")) + ")"); str_1 += "\n"; } // facets { Object.keys(trait_4.facets) .forEach(function (facet_name) { var facet = trait_4.facets[facet_name]; // str += "\t"; str_1 += "* "; str_1 += ((facet.implementation != undefined) ? ("[" + facet_name + "]") : facet_name); str_1 += (" : " + lib_shape.show(facet.shape)); if (facet.description !== undefined) { str_1 += (" ~ " + "" + facet.description + ""); } str_1 += "\n"; }); } return str_1; } } lib_trait.explain = explain; /** * @author fenris */ function explain_all() { return Object.keys(_pool).map(function (trait_id) { return explain(trait_id); }).join("\n"); } lib_trait.explain_all = explain_all; })(lib_trait || (lib_trait = {})); /* This file is part of »bacterio-plankton:trait«. Copyright 2016-2021 greenscale <info@greenscale.de> »bacterio-plankton:trait« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »bacterio-plankton:trait« is distributed in the hope that it will be callful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »bacterio-plankton:trait«. If not, see <http://www.gnu.org/licenses/>. */ /** * @author fenris */ var lib_trait; (function (lib_trait) { /** * @desc the ability to check for equality with another element of the same domain * @author fenris */ function define_collatable() { lib_trait.define("collatable", { "value": [] }, { "collate": { "shape": { "name": "function", "parameters": { "shape_input": { "name": "variable", "parameters": { "name": "value" } }, "shape_output": { "name": "function", "parameters": { "shape_input": { "name": "variable", "parameters": { "name": "value" } }, "shape_output": { "name": "boolean" } } } } } } }); lib_trait.attend("collatable", "crude", { "value": { "name": "any" } }, { "collate": function () { return function (instance) { return function (other) { if (typeof (instance) === "object") { if (instance == null) { return (other == null); } else { if ("_collate" in instance) { return instance["_collate"](other); } else { var message = ("[collate]" + " " + "object has no such method"); throw (new Error(message)); } } } else { if (lib_trait._verbosity >= 1) { var message = ("[collate]" + " " + "primitive value; using default implementation"); console.warn(message); } return (instance === other); } }; }; } }); } lib_trait.define_collatable = define_collatable; /** * @author fenris */ function _collate(instance, other, domain) { if (domain === void 0) { domain = { "kind": "crude" }; } return lib_trait.call("collatable", "collate", domain)(instance)(other); } lib_trait._collate = _collate; define_collatable(); })(lib_trait || (lib_trait = {})); /* This file is part of »bacterio-plankton:trait«. Copyright 2016-2021 greenscale <info@greenscale.de> »bacterio-plankton:trait« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »bacterio-plankton:trait« is distributed in the hope that it will be callful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »bacterio-plankton:trait«. If not, see <http://www.gnu.org/licenses/>. */ /** * @author fenris */ var lib_trait; (function (lib_trait) { /** * @desc the ability to compare with another element of the same domain for determining if the first is "smaller than or equal to" the latter * @author fenris */ function define_comparable() { lib_trait.define("comparable", { "value": [] }, { "compare": { "shape": { "name": "function", "parameters": { "shape_input": { "name": "variable", "parameters": { "name": "value" } }, "shape_output": { "name": "function", "parameters": { "shape_input": { "name": "variable", "parameters": { "name": "value" } }, "shape_output": { "name": "boolean" } } } } } } }); lib_trait.attend("comparable", "crude", { "value": { "name": "any" } }, { "compare": function () { return function (instance) { return function (other) { if (typeof (instance) === "object") { if ("_compare" in instance) { return instance["_compare"](other); } else { throw (new Error("[compare]" + " " + "object has no such method")); } } else { if (lib_trait._verbosity >= 1) { console.warn("[compare]" + " " + "primitive value; using default implementation"); } return (instance <= other); } }; }; } }); } lib_trait.define_comparable = define_comparable; /** * @author fenris */ function _compare(instance, other, domain) { if (domain === void 0) { domain = { "kind": "crude" }; } return lib_trait.call("comparable", "compare", domain)(instance)(other); } lib_trait._compare = _compare; define_comparable(); })(lib_trait || (lib_trait = {})); /* This file is part of »bacterio-plankton:trait«. Copyright 2016-2021 greenscale <info@greenscale.de> »bacterio-plankton:trait« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »bacterio-plankton:trait« is distributed in the hope that it will be callful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »bacterio-plankton:trait«. If not, see <http://www.gnu.org/licenses/>. */ /** * @author fenris */ var lib_trait; (function (lib_trait) { /** * @desc the ability to create an exact copy * @author fenris */ function define_clonable() { lib_trait.define("clonable", { "value": [] }, { "clone": { "shape": { "name": "function", "parameters": { "shape_input": { "name": "variable", "parameters": { "name": "value" } }, "shape_output": { "name": "variable", "parameters": { "name": "value" } } } } } }); lib_trait.attend("clonable", "crude", { "value": { "name": "any" } }, { "clone": function () { return function (instance) { if (typeof (instance) === "object") { if ("_clone" in instance) { return instance["_clone"](); } else { throw (new Error("[clone]" + " " + "object has no such method")); } } else { if (lib_trait._verbosity >= 1) { console.warn("[clone]" + " " + "primitive value; using default implementation"); } return instance; } }; } }); } lib_trait.define_clonable = define_clonable; /** * @author fenris */ function _clone(instance, domain) { if (domain === void 0) { domain = { "kind": "crude" }; } return lib_trait.call("clonable", "clone", domain)(instance); } lib_trait._clone = _clone; define_clonable(); })(lib_trait || (lib_trait = {})); /* This file is part of »bacterio-plankton:trait«. Copyright 2016-2021 greenscale <info@greenscale.de> »bacterio-plankton:trait« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »bacterio-plankton:trait« is distributed in the hope that it will be callful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »bacterio-plankton:trait«. If not, see <http://www.gnu.org/licenses/>. */ /** * @author fenris */ var lib_trait; (function (lib_trait) { /** * @desc the ability to generate a string out of the element, which identifies it to a high degree * @author fenris */ function define_hashable() { lib_trait.define("hashable", { "value": [] }, { "hash": { "shape": { "name": "function", "parameters": { "shape_input": { "name": "variable", "parameters": { "name": "value" } }, "shape_output": { "name": "string" } } } } }); lib_trait.attend("hashable", "crude", { "value": { "name": "any" } }, { "hash": function () { return function (thing) { if (typeof (thing) === "object") { if ("_hash" in thing) { return thing["_hash"](); } else { var message = ("[hash]" + " " + "object has no such method"); throw (new Error(message)); } } else { if (lib_trait._verbosity >= 1) { var message = ("[hash]" + " " + "primitive value; using default implementation"); console.warn(message); } return String(thing); } }; } }); } lib_trait.define_hashable = define_hashable; /** * @author fenris */ function _hash(instance, domain) { if (domain === void 0) { domain = { "kind": "crude" }; } return lib_trait.call("hashable", "hash", domain)(instance); } lib_trait._hash = _hash; define_hashable(); })(lib_trait || (lib_trait = {})); /* This file is part of »bacterio-plankton:trait«. Copyright 2016-2021 greenscale <info@greenscale.de> »bacterio-plankton:trait« is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. »bacterio-plankton:trait« is distributed in the hope that it will be callful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with »bacterio-plankton:trait«. If not, see <http://www.gnu.org/licenses/>. */ /** * @author fenris */ var lib_trait; (function (lib_trait) { /** * @desc the ability to map the element to a textual representation (most likely not injective) * @author fenris */ function define_showable() { lib_trait.define("showable", { "value": [] }, { "show": { "shape": { "name": "function", "parameters": { "shape_input": { "name": "variable", "parameters": { "name": "value" } }, "shape_output": { "name": "string", "parameters": { "soft": false } } } } } }); lib_trait.attend("showable", "crude", { "value": { "name": "any" } }, { "show": function () { return function (instance) { if (typeof (instance) === "object") { if (instance == null) { return "NULL"; } else { if ("_show" in instance) { return instance["_show"](); } else { // throw (new Error("[show]" + " " + "object has no such method")); return JSON.stringify(instance); } } } else { if (lib_trait._verbosity >= 1) { var message = ("[show]" + " " + "primitive value; using default implementation"); // console.warn(message); } return String(instance); } }; } }); } lib_trait.define_showable = define_showable; /** * @author fenris */ function _show(instance, domain) { if (domain === void 0) { domain = { "kind": "crude" }; } return lib_trait.call("showable", "show", domain)(instance); } lib_trait._show = _show; define_showable(); })(lib_trait || (lib_trait = {}));